diff --git a/src/ui/public/chrome/appSwitcher/__tests__/appSwitcher.js b/src/ui/public/chrome/appSwitcher/__tests__/appSwitcher.js index 3135f6bcb519..35c33c7ef1f4 100644 --- a/src/ui/public/chrome/appSwitcher/__tests__/appSwitcher.js +++ b/src/ui/public/chrome/appSwitcher/__tests__/appSwitcher.js @@ -11,22 +11,6 @@ require('ui/chrome'); require('ui/chrome/appSwitcher'); var DomLocationProvider = require('ui/domLocation'); -function findTestSubject() { - var subjectSelectors = [].slice.apply(arguments); - var $context = subjectSelectors.shift(); - var $els = $(); - - subjectSelectors.forEach(function (subjects) { - var selector = subjects.split(/\s+/).map(function (subject) { - return '[data-test-subj~="' + subject + '"]'; - }).join(' '); - - $els = $els.add($context.find(selector)); - }); - - return $els; -} - describe('appSwitcher directive', function () { var env; @@ -79,13 +63,13 @@ describe('appSwitcher directive', function () { beforeEach(setup('http://localhost:5555/app/myApp/', [myLink, notMyLink])); it('links to the inactive apps base url', function () { - var $myLink = findTestSubject(env.$el, 'appLink').eq(0); + var $myLink = env.$el.findTestSubject('appLink').eq(0); expect($myLink.prop('href')).to.be(myLink.url); expect($myLink.prop('href')).to.not.be(myLink.lastSubUrl); }); it('links to the inactive apps last sub url', function () { - var $notMyLink = findTestSubject(env.$el, 'appLink').eq(1); + var $notMyLink = env.$el.findTestSubject('appLink').eq(1); expect($notMyLink.prop('href')).to.be(notMyLink.lastSubUrl); expect($notMyLink.prop('href')).to.not.be(notMyLink.url); }); @@ -109,7 +93,7 @@ describe('appSwitcher directive', function () { beforeEach(setup('http://localhost:5555/app/myApp/', [myLink, notMyLink])); it('links to the lastSubUrl for each', function () { - var $links = findTestSubject(env.$el, 'appLink'); + var $links = env.$el.findTestSubject('appLink'); var $myLink = $links.eq(0); var $notMyLink = $links.eq(1); @@ -134,7 +118,7 @@ describe('appSwitcher directive', function () { expect(event.isDefaultPrevented()).to.be(false); expect(event.isPropagationStopped()).to.be(false); - var $link = findTestSubject(env.$el, 'appLink'); + var $link = env.$el.findTestSubject('appLink'); expect($link.prop('href')).to.be(url); $link.trigger(event); @@ -157,7 +141,7 @@ describe('appSwitcher directive', function () { expect(event.isDefaultPrevented()).to.be(false); expect(event.isPropagationStopped()).to.be(false); - var $link = findTestSubject(env.$el, 'appLink'); + var $link = env.$el.findTestSubject('appLink'); expect($link.prop('href')).to.be(env.currentHref); $link.trigger(event); @@ -182,7 +166,7 @@ describe('appSwitcher directive', function () { expect(event.isDefaultPrevented()).to.be(false); expect(event.isPropagationStopped()).to.be(false); - var $link = findTestSubject(env.$el, 'appLink'); + var $link = env.$el.findTestSubject('appLink'); expect($link.prop('href')).to.be(url); $link.trigger(event); @@ -206,7 +190,7 @@ describe('appSwitcher directive', function () { expect(env.location.reload.callCount).to.be(0); expect(event.isPropagationStopped()).to.be(false); - findTestSubject(env.$el, 'appLink').trigger(event); + env.$el.findTestSubject('appLink').trigger(event); expect(env.location.reload.callCount).to.be(0); expect(event.isPropagationStopped()).to.be(false); @@ -227,7 +211,7 @@ describe('appSwitcher directive', function () { expect(env.location.reload.callCount).to.be(0); expect(event.isPropagationStopped()).to.be(false); - findTestSubject(env.$el, 'appLink').trigger(event); + env.$el.findTestSubject('appLink').trigger(event); expect(env.location.reload.callCount).to.be(0); expect(event.isPropagationStopped()).to.be(false); diff --git a/src/ui/public/jquery/__tests__/findTestSubject.js b/src/ui/public/jquery/__tests__/findTestSubject.js new file mode 100644 index 000000000000..891dbdd81a95 --- /dev/null +++ b/src/ui/public/jquery/__tests__/findTestSubject.js @@ -0,0 +1,69 @@ +var $ = require('jquery'); +var expect = require('expect.js'); + +function $make(subject) { + return $('
').attr('data-test-subj', subject); +} + +describe('jQuery.findTestSubject', function () { + it('finds all of the element with a subject', function () { + var $container = $('
'); + var $match = $make('subject').appendTo($container); + var $noMatch = $make('notSubject').appendTo($container); + + var $found = $container.findTestSubject('subject'); + expect($found.is($match)).to.be(true); + expect($found.is($noMatch)).to.be(false); + }); + + it('finds multiple elements with a subject', function () { + var $container = $('
'); + var $match = $make('subject').appendTo($container); + var $otherMatch = $make('subject').appendTo($container); + + var $found = $container.findTestSubject('subject'); + expect($found.filter($match).size()).to.be(1); + expect($found.filter($otherMatch).size()).to.be(1); + }); + + it('finds all of the elements with either subject', function () { + var $container = $('
'); + var $match1 = $make('subject').appendTo($container); + var $match2 = $make('alsoSubject').appendTo($container); + var $noMatch = $make('notSubject').appendTo($container); + + var $found = $container.findTestSubject('subject', 'alsoSubject'); + expect($found.filter($match1).size()).to.be(1); + expect($found.filter($match2).size()).to.be(1); + expect($found.filter($noMatch).size()).to.be(0); + }); + + it('finds all of the elements with a decendant selector', function () { + var $container = $('
'); + var $parent = $make('foo name').appendTo($container); + var $bar = $make('bar othername').appendTo($parent); + var $baz = $make('baz third name').appendTo($parent); + + expect($container.findTestSubject('foo bar').is($bar)).to.be(true); + expect($container.findTestSubject('foo bar').is($baz)).to.be(false); + + expect($container.findTestSubject('foo baz').is($bar)).to.be(false); + expect($container.findTestSubject('foo baz').is($baz)).to.be(true); + }); + + it('finds elements with compound subjects', function () { + var $container = $('
'); + var $bar = $make('button bar').appendTo($container); + var $baz = $make('button baz').appendTo($container); + + expect($container.findTestSubject('button&bar').is($bar)).to.be(true); + expect($container.findTestSubject('button& bar').is($bar)).to.be(true); + expect($container.findTestSubject('button & bar').is($bar)).to.be(true); + expect($container.findTestSubject('button &bar').is($bar)).to.be(true); + + expect($container.findTestSubject('button&baz').is($baz)).to.be(true); + expect($container.findTestSubject('button& baz').is($baz)).to.be(true); + expect($container.findTestSubject('button & baz').is($baz)).to.be(true); + expect($container.findTestSubject('button &baz').is($baz)).to.be(true); + }); +}); diff --git a/src/ui/public/jquery/findTestSubject.js b/src/ui/public/jquery/findTestSubject.js new file mode 100644 index 000000000000..6ffb01789a9a --- /dev/null +++ b/src/ui/public/jquery/findTestSubject.js @@ -0,0 +1,71 @@ +module.exports = function bindToJquery($) { + + /** + * Find elements with the `data-test-subj` attribute by the terms in that attribute. + * + * ```js + * // this + * var $button = $('[data-test-subj~="saveButton"]'); + * + * // becomes this + * var $button = $.findTestSubject('saveButton'); + * ``` + * + * Supports multiple subjects + * ```js + * // find any saveButton or cancelButton + * var $buttons = $.findTestSubject('saveButton', 'cancelButton'); + * ``` + * + * Supports subject "selectors" + * ```js + * // find any saveButton inside a savedObjectForm + * var $button = $.findTestSubject('savedObjectForm saveButton'); + * ``` + * + * Supports selecting compound subjects + * ```js + * // find any smallButton that is also a saveButton inside a savedObjectForm + * var $input = $.findTestSubject('savedObjectForm smallButton&saveButton'); + * ``` + * + * @return {jQueryCollection} + */ + $.findTestSubject = function () { + return findTestSubject.apply($(document.body), arguments); + }; + + /** + * Just like $.findTestSubject, except only finds elements within another element. + * @return {jQueryCollection} + */ + $.fn.findTestSubject = findTestSubject; + + function findTestSubject(/* ...subjectSelectors */) { + var subjectSelectors = [].slice.apply(arguments); + var $els = $(); + var $context = this; + + subjectSelectors.forEach(function (subjectSelector) { + var cssSelectors = []; + var terms = subjectSelector + .replace(/\s*&\s*/g, '&') // remove all whitespace around joins + .split(/\s+/); + + function termToCssSelector(term) { + return term ? '[data-test-subj~="' + term + '"]' : ''; + } + + while (terms.length) { + var term = terms.shift(); + // split each term by joins/& and map to css selectors + cssSelectors.push(term.split('&').map(termToCssSelector).join('')); + } + + $els = $els.add($context.find(cssSelectors.join(' '))); + }); + + return $els; + }; + +}; diff --git a/webpackShims/jquery.js b/webpackShims/jquery.js index 4cef6e2479f3..e9ac7b7cbfda 100644 --- a/webpackShims/jquery.js +++ b/webpackShims/jquery.js @@ -1 +1,2 @@ -window.jQuery = window.$ = module.exports = require('node_modules/jquery/dist/jquery'); +var $ = window.jQuery = window.$ = module.exports = require('node_modules/jquery/dist/jquery'); +require('ui/jquery/findTestSubject')($);