1 QUnit.module( "selector", {
2 beforeEach: function() {
3 this.safari = /\bsafari\b/i.test( navigator.userAgent ) &&
4 !/\bchrome\b/i.test( navigator.userAgent );
6 afterEach: moduleTeardown
9 QUnit.test( "empty", function( assert ) {
14 assert.strictEqual( jQuery( "" ).length, 0,
15 "Empty selector returns an empty array" );
17 assert.deepEqual( jQuery( "div", document.createTextNode( "" ) ).get(), [],
18 "Text element as context fails silently" );
19 form = document.getElementById( "form" );
20 assert.ok( !jQuery( form ).is( "" ), "Empty string passed to .is() does not match" );
22 if ( QUnit.jQuerySelectors ) {
23 assert.equal( jQuery( " " ).length, 0, "Empty selector returns an empty array" );
24 assert.equal( jQuery( "\t" ).length, 0, "Empty selector returns an empty array" );
26 assert.ok( "skip", "whitespace-only selector not supported in selector-native" );
27 assert.ok( "skip", "whitespace-only selector not supported in selector-native" );
31 QUnit.test( "star", function( assert ) {
35 var all = jQuery( "*" );
37 assert.ok( all.length >= 30, "Select all" );
39 for ( i = 0; i < all.length; i++ ) {
40 if ( all[ i ].nodeType === 8 ) {
44 assert.ok( good, "Select all elements, no comment nodes" );
47 QUnit.test( "element", function( assert ) {
50 var i, lengthtest, siblingTest, html;
51 var fixture = document.getElementById( "qunit-fixture" );
53 assert.deepEqual( jQuery( "p", fixture ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a Node context." );
54 assert.deepEqual( jQuery( "p", "#qunit-fixture" ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a selector context." );
55 assert.deepEqual( jQuery( "p", jQuery( "#qunit-fixture" ) ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a jQuery object context." );
56 assert.deepEqual( jQuery( "#qunit-fixture" ).find( "p" ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a context via .find()." );
58 assert.ok( jQuery( "#length" ).length, "<input name=\"length\"> cannot be found under IE, see #945" );
59 assert.ok( jQuery( "#lengthtest input" ).length, "<input name=\"length\"> cannot be found under IE, see #945" );
62 assert.equal( jQuery( "<div id=\"A'B~C.D[E]\"><p>foo</p></div>" ).find( "p" ).length, 1, "Find where context root is a node and has an ID with CSS3 meta characters" );
64 assert.equal( jQuery( "" ).length, 0, "Empty selector returns an empty array" );
65 assert.deepEqual( jQuery( "div", document.createTextNode( "" ) ).get(), [],
66 "Text element as context fails silently" );
68 assert.t( "Element Selector", "html", [ "html" ] );
69 assert.t( "Element Selector", "body", [ "body" ] );
70 assert.t( "Element Selector", "#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
72 assert.t( "Leading space", " #qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
73 assert.t( "Leading tab", "\t#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
74 assert.t( "Leading carriage return", "\r#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
75 assert.t( "Leading line feed", "\n#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
76 assert.t( "Leading form feed", "\f#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
77 assert.t( "Trailing space", "#qunit-fixture p ", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
78 assert.t( "Trailing tab", "#qunit-fixture p\t", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
79 assert.t( "Trailing carriage return", "#qunit-fixture p\r",
80 [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
81 assert.t( "Trailing line feed", "#qunit-fixture p\n", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
82 assert.t( "Trailing form feed", "#qunit-fixture p\f", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
85 jQuery( jQuery( "div ol" ) ).filter( "#qunit-fixture *" ).get(),
86 q( "empty", "listWithTabIndex" ),
90 jQuery( jQuery( "div\tol" ) ).filter( "#qunit-fixture *" ).get(),
91 q( "empty", "listWithTabIndex" ),
92 "Parent Element (non-space descendant combinator)"
95 // Check for unique-ness and sort order
96 assert.deepEqual( jQuery( "p, div p" ), jQuery( "p" ), "Check for duplicates: p, div p" );
98 jQuery( "<h1 id='h1'></h1><h2 id='h2'></h2><h2 id='h2-2'></h2>" ).prependTo( "#qunit-fixture" );
99 assert.t( "Checking sort order", "#qunit-fixture h2, #qunit-fixture h1", [ "h1", "h2", "h2-2" ] );
101 if ( QUnit.jQuerySelectorsPos ) {
102 assert.t( "Checking sort order", "#qunit-fixture h2:first, #qunit-fixture h1:first", [ "h1", "h2" ] );
104 assert.ok( "skip", "Positional selectors are not supported" );
107 assert.t( "Checking sort order", "#qunit-fixture p, #qunit-fixture p a",
108 [ "firstp", "simon1", "ap", "google", "groups", "anchor1", "mark", "sndp", "en", "yahoo",
109 "sap", "anchor2", "simon", "first" ] );
112 lengthtest = document.getElementById( "lengthtest" );
113 assert.deepEqual( jQuery( "#idTest", lengthtest ).get(), q( "idTest" ),
114 "Finding element with id of ID." );
115 assert.deepEqual( jQuery( "[name='id']", lengthtest ).get(), q( "idTest" ),
116 "Finding element with id of ID." );
117 assert.deepEqual( jQuery( "input[id='idTest']", lengthtest ).get(), q( "idTest" ),
118 "Finding elements with id of ID." );
120 if ( QUnit.jQuerySelectors ) {
121 siblingTest = document.getElementById( "siblingTest" );
122 assert.deepEqual( jQuery( "div em", siblingTest ).get(), [],
123 "Element-rooted QSA does not select based on document context" );
124 assert.deepEqual( jQuery( "div em, div em, div em:not(div em)", siblingTest ).get(), [],
125 "Element-rooted QSA does not select based on document context" );
126 assert.deepEqual( jQuery( "div em, em\\,", siblingTest ).get(), [],
127 "Escaped commas do not get treated with an id in element-rooted QSA" );
129 assert.ok( "skip", "Element-rooted QSA behavior different in selector-native" );
130 assert.ok( "skip", "Element-rooted QSA behavior different in selector-native" );
131 assert.ok( "skip", "Element-rooted QSA behavior different in selector-native" );
135 for ( i = 0; i < 100; i++ ) {
136 html = "<div>" + html + "</div>";
138 html = jQuery( html ).appendTo( document.body );
139 assert.ok( !!jQuery( "body div div div" ).length,
140 "No stack or performance problems with large amounts of descendants" );
141 assert.ok( !!jQuery( "body>div div div" ).length,
142 "No stack or performance problems with large amounts of descendants" );
145 // Real use case would be using .watch in browsers with window.watch (see Issue #157)
146 q( "qunit-fixture" )[ 0 ].appendChild( document.createElement( "toString" ) ).id = "toString";
147 assert.t( "Element name matches Object.prototype property", "toString#toString", [ "toString" ] );
150 QUnit.test( "XML Document Selectors", function( assert ) {
153 var xml = createWithFriesXML();
155 assert.equal( jQuery( "foo_bar", xml ).length, 1, "Element Selector with underscore" );
156 assert.equal( jQuery( ".component", xml ).length, 1, "Class selector" );
157 assert.equal( jQuery( "[class*=component]", xml ).length, 1, "Attribute selector for class" );
158 assert.equal( jQuery( "property[name=prop2]", xml ).length, 1, "Attribute selector with name" );
159 assert.equal( jQuery( "[name=prop2]", xml ).length, 1, "Attribute selector with name" );
160 assert.equal( jQuery( "#seite1", xml ).length, 1, "Attribute selector with ID" );
161 assert.equal( jQuery( "component#seite1", xml ).length, 1, "Attribute selector with ID" );
162 assert.equal( jQuery( "component", xml ).filter( "#seite1" ).length, 1,
163 "Attribute selector filter with ID" );
164 assert.equal( jQuery( "meta property thing", xml ).length, 2,
165 "Descendent selector and dir caching" );
166 if ( QUnit.jQuerySelectors ) {
167 assert.ok( jQuery( xml.lastChild ).is( "soap\\:Envelope" ), "Check for namespaced element" );
169 xml = jQuery.parseXML( "<?xml version='1.0' encoding='UTF-8'?><root><elem id='1'/></root>" );
171 assert.equal( jQuery( "elem:not(:has(*))", xml ).length, 1,
172 "Non-qSA path correctly handles numeric ids (jQuery #14142)" );
174 assert.ok( "skip", "namespaced elements not matching correctly in selector-native" );
175 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
179 QUnit.test( "broken selectors throw", function( assert ) {
182 function broken( name, selector ) {
183 assert.throws( function() {
185 }, name + ": " + selector );
188 broken( "Broken Selector", "[" );
189 broken( "Broken Selector", "(" );
190 broken( "Broken Selector", "{" );
191 broken( "Broken Selector", "<" );
192 broken( "Broken Selector", "()" );
193 broken( "Broken Selector", "<>" );
194 broken( "Broken Selector", "{}" );
195 broken( "Broken Selector", "," );
196 broken( "Broken Selector", ",a" );
197 broken( "Broken Selector", "a," );
198 broken( "Post-comma invalid selector", "*,:x" );
199 broken( "Identifier with bad escape", "foo\\\fbaz" );
200 broken( "Broken Selector", "[id=012345678901234567890123456789" );
201 broken( "Doesn't exist", ":visble" );
202 broken( "Nth-child", ":nth-child" );
203 broken( "Nth-child", ":nth-child(-)" );
204 broken( "Nth-child", ":nth-child(asdf)", [] );
205 broken( "Nth-child", ":nth-child(2n+-0)" );
206 broken( "Nth-child", ":nth-child(2+0)" );
207 broken( "Nth-child", ":nth-child(- 1n)" );
208 broken( "Nth-child", ":nth-child(-1 n)" );
209 broken( "First-child", ":first-child(n)" );
210 broken( "Last-child", ":last-child(n)" );
211 broken( "Only-child", ":only-child(n)" );
212 broken( "Nth-last-last-child", ":nth-last-last-child(1)" );
213 broken( "First-last-child", ":first-last-child" );
214 broken( "Last-last-child", ":last-last-child" );
215 broken( "Only-last-child", ":only-last-child" );
217 // Make sure attribute value quoting works correctly. See: #6093
218 jQuery( "<input type='hidden' value='2' name='foo.baz' id='attrbad1'/>" +
219 "<input type='hidden' value='2' name='foo[baz]' id='attrbad2'/>" )
220 .appendTo( "#qunit-fixture" );
222 broken( "Attribute equals non-value", "input[name=]" );
223 broken( "Attribute equals unquoted non-identifier", "input[name=foo.baz]" );
224 broken( "Attribute equals unquoted non-identifier", "input[name=foo[baz]]" );
225 broken( "Attribute equals bad string", "input[name=''double-quoted'']" );
226 broken( "Attribute equals bad string", "input[name='apostrophe'd']" );
229 QUnit.test( "id", function( assert ) {
234 assert.t( "ID Selector", "#body", [ "body" ] );
235 assert.t( "ID Selector w/ Element", "body#body", [ "body" ] );
236 assert.t( "ID Selector w/ Element", "ul#first", [] );
237 assert.t( "ID selector with existing ID descendant", "#firstp #simon1", [ "simon1" ] );
238 assert.t( "ID selector with non-existent descendant", "#firstp #foobar", [] );
239 assert.t( "ID selector using UTF8", "#台北Táiběi", [ "台北Táiběi" ] );
240 assert.t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", [ "台北Táiběi", "台北" ] );
241 assert.t( "Descendant ID selector using UTF8", "div #台北", [ "台北" ] );
242 assert.t( "Child ID selector using UTF8", "form > #台北", [ "台北" ] );
244 assert.t( "Escaped ID", "#foo\\:bar", [ "foo:bar" ] );
246 if ( QUnit.jQuerySelectors ) {
247 assert.t( "Escaped ID with descendant", "#foo\\:bar span:not(:input)", [ "foo_descendant" ] );
249 assert.ok( "skip", ":input not supported in selector-native" );
252 assert.t( "Escaped ID", "#test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
253 assert.t( "Descendant escaped ID", "div #foo\\:bar", [ "foo:bar" ] );
254 assert.t( "Descendant escaped ID", "div #test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
255 assert.t( "Child escaped ID", "form > #foo\\:bar", [ "foo:bar" ] );
256 assert.t( "Child escaped ID", "form > #test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
258 fiddle = jQuery( "<div id='fiddle\\Foo'><span id='fiddleSpan'></span></div>" )
259 .appendTo( "#qunit-fixture" );
261 if ( QUnit.jQuerySelectors ) {
262 assert.deepEqual( jQuery( "> span", jQuery( "#fiddle\\\\Foo" )[ 0 ] ).get(),
263 q( [ "fiddleSpan" ] ), "Escaped ID as context" );
265 assert.ok( "skip", "leading > not supported in selector-native" );
270 assert.t( "ID Selector, child ID present", "#form > #radio1", [ "radio1" ] ); // bug #267
271 assert.t( "ID Selector, not an ancestor ID", "#form #first", [] );
272 assert.t( "ID Selector, not a child ID", "#form > #option1a", [] );
274 assert.t( "All Children of ID", "#foo > *", [ "sndp", "en", "sap" ] );
275 assert.t( "All Children of ID with no children", "#firstUL > *", [] );
277 assert.equal( jQuery( "#tName1" )[ 0 ].id, "tName1",
278 "ID selector with same value for a name attribute" );
279 assert.t( "ID selector non-existing but name attribute on an A tag", "#tName2", [] );
280 assert.t( "Leading ID selector non-existing but name attribute on an A tag", "#tName2 span", [] );
281 assert.t( "Leading ID selector existing, retrieving the child", "#tName1 span", [ "tName1-span" ] );
282 assert.equal( jQuery( "div > div #tName1" )[ 0 ].id, jQuery( "#tName1-span" )[ 0 ].parentNode.id,
285 a = jQuery( "<a id='backslash\\foo'></a>" ).appendTo( "#qunit-fixture" );
286 assert.t( "ID Selector contains backslash", "#backslash\\\\foo", [ "backslash\\foo" ] );
289 assert.t( "ID Selector on Form with an input that has a name of 'id'", "#lengthtest", [ "lengthtest" ] );
291 assert.t( "ID selector with non-existent ancestor", "#asdfasdf #foobar", [] ); // bug #986
293 assert.deepEqual( jQuery( "div#form", document.body ).get(), [],
294 "ID selector within the context of another element" );
296 assert.t( "Underscore ID", "#types_all", [ "types_all" ] );
297 assert.t( "Dash ID", "#qunit-fixture", [ "qunit-fixture" ] );
299 assert.t( "ID with weird characters in it", "#name\\+value", [ "name+value" ] );
302 QUnit.test( "class", function( assert ) {
305 assert.deepEqual( jQuery( ".blog", document.getElementsByTagName( "p" ) ).get(),
306 q( "mark", "simon" ), "Finding elements with a context." );
307 assert.deepEqual( jQuery( ".blog", "p" ).get(),
308 q( "mark", "simon" ), "Finding elements with a context." );
309 assert.deepEqual( jQuery( ".blog", jQuery( "p" ) ).get(),
310 q( "mark", "simon" ), "Finding elements with a context." );
311 assert.deepEqual( jQuery( "p" ).find( ".blog" ).get(),
312 q( "mark", "simon" ), "Finding elements with a context." );
314 assert.t( "Class Selector", ".blog", [ "mark", "simon" ] );
315 assert.t( "Class Selector", ".GROUPS", [ "groups" ] );
316 assert.t( "Class Selector", ".blog.link", [ "simon" ] );
317 assert.t( "Class Selector w/ Element", "a.blog", [ "mark", "simon" ] );
318 assert.t( "Parent Class Selector", "p .blog", [ "mark", "simon" ] );
320 assert.t( "Class selector using UTF8", ".台北Táiběi", [ "utf8class1" ] );
321 assert.t( "Class selector using UTF8", ".台北", [ "utf8class1", "utf8class2" ] );
322 assert.t( "Class selector using UTF8", ".台北Táiběi.台北", [ "utf8class1" ] );
323 assert.t( "Class selector using UTF8", ".台北Táiběi, .台北", [ "utf8class1", "utf8class2" ] );
324 assert.t( "Descendant class selector using UTF8", "div .台北Táiběi", [ "utf8class1" ] );
325 assert.t( "Child class selector using UTF8", "form > .台北Táiběi", [ "utf8class1" ] );
327 assert.t( "Escaped Class", ".foo\\:bar", [ "foo:bar" ] );
328 assert.t( "Escaped Class", ".test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
329 assert.t( "Descendant escaped Class", "div .foo\\:bar", [ "foo:bar" ] );
330 assert.t( "Descendant escaped Class", "div .test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
331 assert.t( "Child escaped Class", "form > .foo\\:bar", [ "foo:bar" ] );
332 assert.t( "Child escaped Class", "form > .test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
334 var div = document.createElement( "div" );
335 div.innerHTML = "<div class='test e'></div><div class='test'></div>";
336 assert.deepEqual( jQuery( ".e", div ).get(), [ div.firstChild ], "Finding a second class." );
338 div.lastChild.className = "e";
340 assert.ok( !jQuery( div ).is( ".null" ),
341 ".null does not match an element with no class" );
342 assert.ok( !jQuery( div.firstChild ).is( ".null div" ),
343 ".null does not match an element with no class" );
344 div.className = "null";
345 assert.ok( jQuery( div ).is( ".null" ), ".null matches element with class 'null'" );
346 assert.ok( jQuery( div.firstChild ).is( ".null div" ),
347 "caching system respects DOM changes" );
348 assert.ok( !jQuery( document ).is( ".foo" ),
349 "testing class on document doesn't error" );
350 assert.ok( !jQuery( window ).is( ".foo" ), "testing class on window doesn't error" );
352 assert.deepEqual( jQuery( ".e", div ).get(), [ div.firstChild, div.lastChild ],
353 "Finding a modified class." );
355 div.lastChild.className += " hasOwnProperty toString";
356 assert.deepEqual( jQuery( ".e.hasOwnProperty.toString", div ).get(), [ div.lastChild ],
357 "Classes match Object.prototype properties" );
359 div = jQuery( "<div><svg width='200' height='250' version='1.1'" +
360 " xmlns='http://www.w3.org/2000/svg'><rect x='10' y='10' width='30' height='30'" +
361 "class='foo'></rect></svg></div>" )[ 0 ];
362 assert.equal( jQuery( ".foo", div ).length, 1, "Class selector against SVG container" );
363 assert.equal( jQuery( ".foo", div.firstChild ).length, 1,
364 "Class selector directly against SVG" );
367 QUnit.test( "name", function( assert ) {
372 assert.t( "Name selector", "input[name=action]", [ "text1" ] );
373 assert.t( "Name selector with single quotes", "input[name='action']", [ "text1" ] );
374 assert.t( "Name selector with double quotes", "input[name=\"action\"]", [ "text1" ] );
376 assert.t( "Name selector non-input", "[name=example]", [ "name-is-example" ] );
377 assert.t( "Name selector non-input", "[name=div]", [ "name-is-div" ] );
378 assert.t( "Name selector non-input", "*[name=iframe]", [ "iframe" ] );
380 assert.t( "Name selector for grouped input", "input[name='types[]']", [ "types_all", "types_anime", "types_movie" ] );
382 form = document.getElementById( "form" );
383 assert.deepEqual( jQuery( "input[name=action]", form ).get(), q( "text1" ),
384 "Name selector within the context of another element" );
385 assert.deepEqual( jQuery( "input[name='foo[bar]']", form ).get(), q( "hidden2" ),
386 "Name selector for grouped form element within the context of another element" );
388 form = jQuery( "<form><input name='id'/></form>" ).appendTo( "body" );
389 assert.equal( jQuery( "input", form[ 0 ] ).length, 1,
390 "Make sure that rooted queries on forms (with possible expandos) work." );
394 assert.t( "Find elements that have similar IDs", "[name=tName1]", [ "tName1ID" ] );
395 assert.t( "Find elements that have similar IDs", "[name=tName2]", [ "tName2ID" ] );
396 assert.t( "Find elements that have similar IDs", "#tName2ID", [ "tName2ID" ] );
398 assert.t( "Case-sensitivity", "[name=tname1]", [] );
401 QUnit.test( "comma-separated", function( assert ) {
404 var fixture = jQuery( "<div><h2><span></span></h2><div><p><span></span></p><p></p></div></div>" );
406 assert.equal( fixture.find( "h2, div p" ).filter( "p" ).length, 2, "has to find two <p>" );
407 assert.equal( fixture.find( "h2, div p" ).filter( "h2" ).length, 1, "has to find one <h2>" );
408 assert.equal( fixture.find( "h2 , div p" ).filter( "p" ).length, 2, "has to find two <p>" );
409 assert.equal( fixture.find( "h2 , div p" ).filter( "h2" ).length, 1, "has to find one <h2>" );
412 QUnit.test( "child and adjacent", function( assert ) {
415 var siblingFirst, en, nothiddendiv;
417 assert.t( "Child", "p > a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] );
418 assert.t( "Child minus leading whitespace", "p> a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] );
419 assert.t( "Child minus trailing whitespace", "p >a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] );
420 assert.t( "Child minus whitespace", "p>a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] );
421 assert.t( "Child w/ Class", "p > a.blog", [ "mark", "simon" ] );
422 assert.t( "All Children", "code > *", [ "anchor1", "anchor2" ] );
423 assert.selectInFixture( "All Grandchildren", "p > * > *", [ "anchor1", "anchor2" ] );
425 assert.t( "Rooted tag adjacent", "#qunit-fixture a + a", [ "groups", "tName2ID" ] );
426 assert.t( "Rooted tag adjacent minus whitespace", "#qunit-fixture a+a", [ "groups", "tName2ID" ] );
427 assert.t( "Rooted tag adjacent minus leading whitespace", "#qunit-fixture a +a",
428 [ "groups", "tName2ID" ] );
429 assert.t( "Rooted tag adjacent minus trailing whitespace", "#qunit-fixture a+ a",
430 [ "groups", "tName2ID" ] );
432 assert.t( "Tag adjacent", "p + p", [ "ap", "en", "sap" ] );
433 assert.t( "#id adjacent", "#firstp + p", [ "ap" ] );
434 assert.t( "Tag#id adjacent", "p#firstp + p", [ "ap" ] );
435 assert.t( "Tag[attr] adjacent", "p[lang=en] + p", [ "sap" ] );
436 assert.t( "Tag.class adjacent", "a.GROUPS + code + a", [ "mark" ] );
437 assert.t( "Comma, Child, and Adjacent", "#qunit-fixture a + a, code > a",
438 [ "groups", "anchor1", "anchor2", "tName2ID" ] );
440 assert.t( "Element Preceded By", "#qunit-fixture p ~ div",
441 [ "foo", "nothiddendiv", "moretests", "tabindex-tests", "liveHandlerOrder", "siblingTest", "fx-test-group" ] );
442 assert.t( "Element Preceded By", "#first ~ div",
443 [ "moretests", "tabindex-tests", "liveHandlerOrder", "siblingTest", "fx-test-group" ] );
444 assert.t( "Element Preceded By", "#groups ~ a", [ "mark" ] );
445 assert.t( "Element Preceded By", "#length ~ input", [ "idTest" ] );
446 assert.t( "Element Preceded By", "#siblingfirst ~ em", [ "siblingnext", "siblingthird" ] );
447 assert.t( "Element Preceded By (multiple)", "#siblingTest em ~ em ~ em ~ span", [ "siblingspan" ] );
449 siblingFirst = document.getElementById( "siblingfirst" );
451 if ( QUnit.jQuerySelectors ) {
452 assert.deepEqual( jQuery( "+ em", siblingFirst ).get(), q( "siblingnext" ),
453 "Element Directly Preceded By with a context." );
454 assert.deepEqual( jQuery( "~ em", siblingFirst ).get(), q( "siblingnext", "siblingthird" ),
455 "Element Preceded By with a context." );
457 assert.ok( "skip", "leading + not supported in selector-native" );
458 assert.ok( "skip", "leading ~ not supported in selector-native" );
461 if ( QUnit.jQuerySelectorsPos ) {
462 assert.deepEqual( jQuery( "~ em:first", siblingFirst ).get(), q( "siblingnext" ),
463 "Element Preceded By positional with a context." );
465 assert.ok( "skip", "Positional selectors are not supported" );
468 if ( QUnit.jQuerySelectors ) {
469 en = document.getElementById( "en" );
470 assert.deepEqual( jQuery( "+ p, a", en ).get(), q( "yahoo", "sap" ),
471 "Compound selector with context, beginning with sibling test." );
472 assert.deepEqual( jQuery( "a, + p", en ).get(), q( "yahoo", "sap" ),
473 "Compound selector with context, containing sibling test." );
475 assert.ok( "skip", "leading + not supported in selector-native" );
476 assert.ok( "skip", "leading + not supported in selector-native" );
479 if ( QUnit.jQuerySelectors ) {
480 assert.t( "Element Preceded By, Containing", "#liveHandlerOrder ~ div em:contains('1')", [ "siblingfirst" ] );
481 assert.t( "Combinators are not skipped when mixing general and specific", "#siblingTest > em:contains('x') + em ~ span", [] );
483 assert.ok( "skip", ":contains not supported in selector-native" );
484 assert.ok( "skip", ":contains not supported in selector-native" );
487 if ( QUnit.jQuerySelectorsPos ) {
488 assert.equal( jQuery( "#listWithTabIndex li:eq(2) ~ li" ).length, 1, "Find by general sibling combinator (#8310)" );
490 nothiddendiv = document.getElementById( "nothiddendiv" );
491 assert.deepEqual( jQuery( "> :first", nothiddendiv ).get(), q( "nothiddendivchild" ),
492 "Verify child context positional selector" );
493 assert.deepEqual( jQuery( "> :eq(0)", nothiddendiv ).get(), q( "nothiddendivchild" ),
494 "Verify child context positional selector" );
495 assert.deepEqual( jQuery( "> *:first", nothiddendiv ).get(), q( "nothiddendivchild" ),
496 "Verify child context positional selector" );
498 assert.ok( "skip", "Positional selectors are not supported" );
499 assert.ok( "skip", "Positional selectors are not supported" );
500 assert.ok( "skip", "Positional selectors are not supported" );
501 assert.ok( "skip", "Positional selectors are not supported" );
504 assert.t( "Multiple combinators selects all levels", "#siblingTest em *", [ "siblingchild", "siblinggrandchild", "siblinggreatgrandchild" ] );
505 assert.t( "Multiple combinators selects all levels", "#siblingTest > em *", [ "siblingchild", "siblinggrandchild", "siblinggreatgrandchild" ] );
506 assert.t( "Multiple sibling combinators doesn't miss general siblings", "#siblingTest > em:first-child + em ~ span", [ "siblingspan" ] );
508 assert.equal( jQuery( "#listWithTabIndex" ).length, 1, "Parent div for next test is found via ID (#8310)" );
509 assert.equal( jQuery( "#__sizzle__" ).length, 0, "Make sure the temporary id assigned by sizzle is cleared out (#8310)" );
510 assert.equal( jQuery( "#listWithTabIndex" ).length, 1, "Parent div for previous test is still found via ID (#8310)" );
512 assert.t( "Verify deep class selector", "div.blah > p > a", [] );
513 assert.t( "No element deep selector", "div.foo > span > a", [] );
514 assert.t( "Non-existent ancestors", ".fototab > .thumbnails > a", [] );
517 QUnit.test( "attributes - existence", function( assert ) {
520 assert.t( "On element", "#qunit-fixture a[title]", [ "google" ] );
521 assert.t( "On element (whitespace ignored)", "#qunit-fixture a[ title ]", [ "google" ] );
522 assert.t( "On element (case-insensitive)", "#qunit-fixture a[TITLE]", [ "google" ] );
523 assert.t( "On any element", "#qunit-fixture *[title]", [ "google" ] );
524 assert.t( "On implicit element", "#qunit-fixture [title]", [ "google" ] );
525 assert.t( "Boolean", "#select2 option[selected]", [ "option2d" ] );
526 assert.t( "For attribute on label", "form label[for]", [ "label-for" ] );
529 QUnit.test( "attributes - equals", function( assert ) {
534 assert.t( "Identifier", "#qunit-fixture a[rel=bookmark]", [ "simon1" ] );
535 assert.t( "Identifier with underscore", "input[id=types_all]", [ "types_all" ] );
536 assert.t( "String", "#qunit-fixture a[rel='bookmark']", [ "simon1" ] );
537 assert.t( "String (whitespace ignored)", "#qunit-fixture a[ rel = 'bookmark' ]", [ "simon1" ] );
538 assert.t( "Non-identifier string", "#qunit-fixture a[href='https://www.google.com/']", [ "google" ] );
539 assert.t( "Empty string", "#select1 option[value='']", [ "option1a" ] );
541 if ( QUnit.jQuerySelectors ) {
543 "#qunit-fixture option[value=1]",
544 [ "option1b", "option2b", "option3b", "option4b", "option5c" ] );
545 assert.t( "negative number",
546 "#qunit-fixture li[tabIndex=-1]", [ "foodWithNegativeTabIndex" ] );
548 assert.ok( "skip", "Number value not supported in selector-native" );
549 assert.ok( "skip", "Negative number value not supported in selector-native" );
552 assert.t( "Non-ASCII identifier", "span[lang=中文]", [ "台北" ] );
554 assert.t( "input[type=text]", "#form input[type=text]", [ "text1", "text2", "hidden2", "name" ] );
555 assert.t( "input[type=search]", "#form input[type=search]", [ "search" ] );
557 withScript = supportjQuery( "<div><span><script src=''></script></span></div>" );
558 assert.ok( withScript.find( "#moretests script[src]" ).has( "script" ), "script[src] (jQuery #13777)" );
560 assert.t( "Boolean attribute equals name", "#select2 option[selected='selected']", [ "option2d" ] );
561 assert.t( "for Attribute in form", "#form [for=action]", [ "label-for" ] );
562 assert.t( "Grouped Form Elements - name", "input[name='foo[bar]']", [ "hidden2" ] );
563 assert.t( "Value", "input[value=Test]", [ "text1", "text2" ] );
566 jQuery( "input[data-comma='0,1']" ).get(),
568 "Without context, single-quoted attribute containing ','" );
570 jQuery( "input[data-comma=\"0,1\"]" ).get(),
572 "Without context, double-quoted attribute containing ','" );
574 jQuery( "input[data-comma='0,1']", document.getElementById( "t12087" ) ).get(),
576 "With context, single-quoted attribute containing ','" );
578 jQuery( "input[data-comma=\"0,1\"]", document.getElementById( "t12087" ) ).get(),
580 "With context, double-quoted attribute containing ','" );
583 QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "attributes - does not equal", function( assert ) {
586 assert.t( "string", "#ap a[hreflang!='en']", [ "google", "groups", "anchor1" ] );
587 assert.t( "Empty values", "#select1 option[value!='']", [ "option1b", "option1c", "option1d" ] );
590 QUnit.test( "attributes - starts with", function( assert ) {
593 assert.t( "string (whitespace ignored)", "a[href ^= 'https://www']", [ "google", "yahoo" ] );
594 assert.t( "href starts with hash", "p a[href^='#']", [ "anchor2" ] );
595 assert.t( "string containing '['", "input[name^='foo[']", [ "hidden2" ] );
596 assert.t( "string containing '[' ... ']'", "input[name^='foo[bar]']", [ "hidden2" ] );
599 QUnit.test( "attributes - contains", function( assert ) {
602 assert.t( "string (whitespace ignored)", "a[href *= 'google']", [ "google", "groups" ] );
603 assert.t( "string like '[' ... ']']", "input[name*='[bar]']", [ "hidden2" ] );
604 assert.t( "string containing '['...']", "input[name*='foo[bar]']", [ "hidden2" ] );
605 assert.t( "href contains hash", "p a[href*='#']", [ "simon1", "anchor2" ] );
608 QUnit.test( "attributes - ends with", function( assert ) {
611 assert.t( "string (whitespace ignored)", "a[href $= 'org/']", [ "mark" ] );
612 assert.t( "string ending with ']'", "input[name$='bar]']", [ "hidden2" ] );
613 assert.t( "string like '[' ... ']'", "input[name$='[bar]']", [ "hidden2" ] );
614 assert.t( "Attribute containing []", "input[name$='foo[bar]']", [ "hidden2" ] );
617 QUnit.test( "attributes - whitespace list includes", function( assert ) {
620 assert.t( "string found at the beginning",
621 "input[data-15233~='foo']",
622 [ "t15233-single", "t15233-double", "t15233-double-tab", "t15233-double-nl", "t15233-triple" ] );
623 assert.t( "string found in the middle",
624 "input[data-15233~='bar']",
625 [ "t15233-double", "t15233-double-tab", "t15233-double-nl", "t15233-triple" ] );
626 assert.t( "string found at the end", "input[data-15233~='baz']", [ "t15233-triple" ] );
629 QUnit.test( "attributes - hyphen-prefix matches", function( assert ) {
632 assert.t( "string", "#names-group span[id|='name']", [ "name-is-example", "name-is-div" ] );
633 assert.t( "string containing hyphen",
634 "#names-group span[id|='name-is']",
635 [ "name-is-example", "name-is-div" ] );
636 assert.t( "string ending with hyphen", "#names-group span[id|='name-is-']", [] );
639 QUnit.test( "attributes - special characters", function( assert ) {
643 var div = document.createElement( "div" );
646 div.innerHTML = "<div id='foo' xml:test='something'></div>";
647 assert.deepEqual( jQuery( "[xml\\:test]", div ).get(),
649 "attribute name containing colon" );
651 // Make sure attribute value quoting works correctly.
652 // See jQuery trac-6093; trac-6428; trac-13894.
653 // Use seeded results to bypass querySelectorAll optimizations.
655 "<input type='hidden' id='attrbad_space' name='foo bar'/>" +
656 "<input type='hidden' id='attrbad_dot' value='2' name='foo.baz'/>" +
657 "<input type='hidden' id='attrbad_brackets' value='2' name='foo[baz]'/>" +
658 "<input type='hidden' id='attrbad_leading_digits' name='agent' value='007'/>" +
659 "<input type='hidden' id='attrbad_injection' data-attr='foo_baz']'/>" +
660 "<input type='hidden' id='attrbad_quote' data-attr='''/>" +
661 "<input type='hidden' id='attrbad_backslash' data-attr='\'/>" +
662 "<input type='hidden' id='attrbad_backslash_quote' data-attr='\''/>" +
663 "<input type='hidden' id='attrbad_backslash_backslash' data-attr='\\'/>" +
664 "<input type='hidden' id='attrbad_unicode' data-attr='一'/>"
665 ).appendTo( "#qunit-fixture" ).get();
668 assert.deepEqual( jQuery( attrbad ).filter( "input[name=foo\\ bar]" ).get(),
669 q( "attrbad_space" ),
670 "identifier containing space" );
671 assert.deepEqual( jQuery( attrbad ).filter( "input[name=foo\\.baz]" ).get(),
673 "identifier containing dot" );
674 assert.deepEqual( jQuery( attrbad ).filter( "input[name=foo\\[baz\\]]" ).get(),
675 q( "attrbad_brackets" ),
676 "identifier containing brackets" );
677 assert.deepEqual( jQuery( attrbad ).filter( "input[data-attr='foo_baz\\']']" ).get(),
678 q( "attrbad_injection" ),
679 "string containing quote and right bracket" );
681 assert.deepEqual( jQuery( attrbad ).filter( "input[value=\\30 \\30\\37 ]" ).get(),
682 q( "attrbad_leading_digits" ),
683 "identifier containing escaped leading digits with whitespace termination" );
684 assert.deepEqual( jQuery( attrbad ).filter( "input[value=\\00003007]" ).get(),
685 q( "attrbad_leading_digits" ),
686 "identifier containing escaped leading digits without whitespace termination" );
688 assert.deepEqual( jQuery( attrbad ).filter( "input[data-attr='\\'']" ).get(),
689 q( "attrbad_quote" ),
690 "string containing quote" );
691 assert.deepEqual( jQuery( attrbad ).filter( "input[data-attr='\\\\']" ).get(),
692 q( "attrbad_backslash" ),
693 "string containing backslash" );
694 assert.deepEqual( jQuery( attrbad ).filter( "input[data-attr='\\\\\\'']" ).get(),
695 q( "attrbad_backslash_quote" ),
696 "string containing backslash and quote" );
697 assert.deepEqual( jQuery( attrbad ).filter( "input[data-attr='\\\\\\\\']" ).get(),
698 q( "attrbad_backslash_backslash" ),
699 "string containing adjacent backslashes" );
701 assert.deepEqual( jQuery( attrbad ).filter( "input[data-attr='\\5C\\\\']" ).get(),
702 q( "attrbad_backslash_backslash" ),
703 "string containing numeric-escape backslash and backslash" );
704 assert.deepEqual( jQuery( attrbad ).filter( "input[data-attr='\\5C \\\\']" ).get(),
705 q( "attrbad_backslash_backslash" ),
706 "string containing numeric-escape-with-trailing-space backslash and backslash" );
707 assert.deepEqual( jQuery( attrbad ).filter( "input[data-attr='\\5C\t\\\\']" ).get(),
708 q( "attrbad_backslash_backslash" ),
709 "string containing numeric-escape-with-trailing-tab backslash and backslash" );
710 assert.deepEqual( jQuery( attrbad ).filter( "input[data-attr='\\04e00']" ).get(),
711 q( "attrbad_unicode" ),
712 "Long numeric escape (BMP)" );
714 document.getElementById( "attrbad_unicode" ).setAttribute( "data-attr", "\uD834\uDF06A" );
715 assert.deepEqual( jQuery( attrbad ).filter( "input[data-attr='\\01D306A']" ).get(),
716 q( "attrbad_unicode" ),
717 "Long numeric escape (non-BMP)" );
720 QUnit.test( "attributes - others", function( assert ) {
723 var div = document.getElementById( "foo" );
725 assert.t( "Find elements with a tabindex attribute", "[tabindex]", [ "listWithTabIndex", "foodWithNegativeTabIndex", "linkWithTabIndex", "linkWithNegativeTabIndex", "linkWithNoHrefWithTabIndex", "linkWithNoHrefWithNegativeTabIndex" ] );
727 assert.t( "Selector list with multiple quoted attribute-equals",
728 "#form input[type='radio'], #form input[type='hidden']",
729 [ "radio1", "radio2", "hidden1" ] );
730 assert.t( "Selector list with differently-quoted attribute-equals",
731 "#form input[type='radio'], #form input[type=\"hidden\"]",
732 [ "radio1", "radio2", "hidden1" ] );
733 assert.t( "Selector list with quoted and unquoted attribute-equals",
734 "#form input[type='radio'], #form input[type=hidden]",
735 [ "radio1", "radio2", "hidden1" ] );
737 assert.t( "Object.prototype property \"constructor\" (negative)", "[constructor]", [] );
738 assert.t( "Gecko Object.prototype property \"watch\" (negative)", "[watch]", [] );
739 div.setAttribute( "constructor", "foo" );
740 div.setAttribute( "watch", "bar" );
741 assert.t( "Object.prototype property \"constructor\"", "[constructor='foo']", [ "foo" ] );
742 assert.t( "Gecko Object.prototype property \"watch\"", "[watch='bar']", [ "foo" ] );
745 assert.ok( jQuery( "<input type='checkbox' checked='checked'/>" ).prop( "checked", false ).is( "[checked]" ),
746 "[checked] selects by attribute (positive)"
748 assert.ok( !jQuery( "<input type='checkbox'/>" ).prop( "checked", true ).is( "[checked]" ),
749 "[checked] selects by attribute (negative)"
752 assert.t( "empty name", "[name='']", [ "name-empty" ] );
753 assert.t( "prefixed empty name", "#empty-name-parent [name='']", [ "name-empty" ] );
755 var emptyNameContainer = jQuery( ".empty-name-container" );
756 assert.deepEqual( emptyNameContainer.find( "[name='']" ).get(),
758 "empty name with context" );
759 assert.deepEqual( emptyNameContainer.find( "#empty-name-parent [name='']" ).get(),
761 "prefixed empty name with context" );
764 QUnit.test( "pseudo - (parent|empty)", function( assert ) {
766 assert.t( "Empty", "#qunit-fixture ul:empty", [ "firstUL" ] );
767 assert.t( "Empty with comment node", "#qunit-fixture ol:empty", [ "empty" ] );
769 if ( QUnit.jQuerySelectors ) {
770 assert.t( "Is A Parent", "#qunit-fixture p:parent",
771 [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
773 assert.ok( "skip", ":parent not supported in selector-native" );
777 QUnit.test( "pseudo - (first|last|only)-(child|of-type)", function( assert ) {
780 assert.t( "First Child", "#qunit-fixture p:first-child", [ "firstp", "sndp" ] );
781 assert.t( "First Child (leading id)", "#qunit-fixture p:first-child", [ "firstp", "sndp" ] );
782 assert.t( "First Child (leading class)", ".nothiddendiv div:first-child", [ "nothiddendivchild" ] );
783 assert.t( "First Child (case-insensitive)", "#qunit-fixture p:FIRST-CHILD", [ "firstp", "sndp" ] );
785 assert.t( "Last Child", "#qunit-fixture p:last-child", [ "sap" ] );
786 assert.t( "Last Child (leading id)", "#qunit-fixture a:last-child", [ "simon1", "anchor1", "mark", "yahoo", "anchor2", "simon", "liveLink1", "liveLink2" ] );
788 assert.t( "Only Child", "#qunit-fixture a:only-child", [ "simon1", "anchor1", "yahoo", "anchor2", "liveLink1", "liveLink2" ] );
790 assert.t( "First-of-type", "#qunit-fixture > p:first-of-type", [ "firstp" ] );
791 assert.t( "Last-of-type", "#qunit-fixture > p:last-of-type", [ "first" ] );
792 assert.t( "Only-of-type", "#qunit-fixture > :only-of-type", [ "name+value", "firstUL", "empty", "floatTest", "iframe", "table", "last" ] );
794 // Verify that the child position isn't being cached improperly
795 var secondChildren = jQuery( "p:nth-child(2)" ).before( "<div></div>" );
797 assert.t( "No longer second child", "p:nth-child(2)", [] );
798 secondChildren.prev().remove();
799 assert.t( "Restored second child", "p:nth-child(2)", [ "ap", "en" ] );
802 QUnit.test( "pseudo - nth-child", function( assert ) {
805 assert.t( "Nth-child", "p:nth-child(1)", [ "firstp", "sndp" ] );
806 assert.t( "Nth-child (with whitespace)", "p:nth-child( 1 )", [ "firstp", "sndp" ] );
807 assert.t( "Nth-child (case-insensitive)", "#form #select1 option:NTH-child(3)", [ "option1c" ] );
808 assert.t( "Not nth-child", "#qunit-fixture p:not(:nth-child(1))", [ "ap", "en", "sap", "first" ] );
810 assert.t( "Nth-child(2)", "#qunit-fixture form#form > *:nth-child(2)", [ "text1" ] );
811 assert.t( "Nth-child(2)", "#qunit-fixture form#form > :nth-child(2)", [ "text1" ] );
813 assert.t( "Nth-child(-1)", "#form #select1 option:nth-child(-1)", [] );
814 assert.t( "Nth-child(3)", "#form #select1 option:nth-child(3)", [ "option1c" ] );
815 assert.t( "Nth-child(0n+3)", "#form #select1 option:nth-child(0n+3)", [ "option1c" ] );
816 assert.t( "Nth-child(1n+0)", "#form #select1 option:nth-child(1n+0)", [ "option1a", "option1b", "option1c", "option1d" ] );
817 assert.t( "Nth-child(1n)", "#form #select1 option:nth-child(1n)", [ "option1a", "option1b", "option1c", "option1d" ] );
818 assert.t( "Nth-child(n)", "#form #select1 option:nth-child(n)", [ "option1a", "option1b", "option1c", "option1d" ] );
819 assert.t( "Nth-child(even)", "#form #select1 option:nth-child(even)", [ "option1b", "option1d" ] );
820 assert.t( "Nth-child(odd)", "#form #select1 option:nth-child(odd)", [ "option1a", "option1c" ] );
821 assert.t( "Nth-child(2n)", "#form #select1 option:nth-child(2n)", [ "option1b", "option1d" ] );
822 assert.t( "Nth-child(2n+1)", "#form #select1 option:nth-child(2n+1)", [ "option1a", "option1c" ] );
823 assert.t( "Nth-child(2n + 1)", "#form #select1 option:nth-child(2n + 1)", [ "option1a", "option1c" ] );
824 assert.t( "Nth-child(+2n + 1)", "#form #select1 option:nth-child(+2n + 1)", [ "option1a", "option1c" ] );
825 assert.t( "Nth-child(3n)", "#form #select1 option:nth-child(3n)", [ "option1c" ] );
826 assert.t( "Nth-child(3n+1)", "#form #select1 option:nth-child(3n+1)", [ "option1a", "option1d" ] );
827 assert.t( "Nth-child(3n+2)", "#form #select1 option:nth-child(3n+2)", [ "option1b" ] );
828 assert.t( "Nth-child(3n+3)", "#form #select1 option:nth-child(3n+3)", [ "option1c" ] );
829 assert.t( "Nth-child(3n-1)", "#form #select1 option:nth-child(3n-1)", [ "option1b" ] );
830 assert.t( "Nth-child(3n-2)", "#form #select1 option:nth-child(3n-2)", [ "option1a", "option1d" ] );
831 assert.t( "Nth-child(3n-3)", "#form #select1 option:nth-child(3n-3)", [ "option1c" ] );
832 assert.t( "Nth-child(3n+0)", "#form #select1 option:nth-child(3n+0)", [ "option1c" ] );
833 assert.t( "Nth-child(-1n+3)", "#form #select1 option:nth-child(-1n+3)", [ "option1a", "option1b", "option1c" ] );
834 assert.t( "Nth-child(-n+3)", "#form #select1 option:nth-child(-n+3)", [ "option1a", "option1b", "option1c" ] );
835 assert.t( "Nth-child(-1n + 3)", "#form #select1 option:nth-child(-1n + 3)", [ "option1a", "option1b", "option1c" ] );
837 if ( QUnit.jQuerySelectors || this.safari ) {
839 jQuery( [ document.createElement( "a" ) ].concat( q( "ap" ) ) )
840 .filter( ":nth-child(n)" )
846 // Support: Chrome 75+, Firefox 67+
847 // Some browsers mark disconnected elements as matching `:nth-child(n)`
848 // so let's skip the test.
849 assert.ok( "skip", "disconnected elements match ':nth-child(n)' in Chrome/Firefox" );
853 QUnit.test( "pseudo - nth-last-child", function( assert ) {
856 jQuery( "#qunit-fixture" ).append( "<form id='nth-last-child-form'></form><i></i><i></i><i></i><i></i>" );
857 assert.t( "Nth-last-child", "form:nth-last-child(5)", [ "nth-last-child-form" ] );
858 assert.t( "Nth-last-child (with whitespace)", "form:nth-last-child( 5 )", [ "nth-last-child-form" ] );
861 assert.t( "Nth-last-child (case-insensitive)", "#form #select1 option:NTH-last-child(3)", [ "option1b" ] );
862 assert.t( "Not nth-last-child", "#qunit-fixture p:not(:nth-last-child(1))", [ "firstp", "ap", "sndp", "en", "first" ] );
864 assert.t( "Nth-last-child(-1)", "#form #select1 option:nth-last-child(-1)", [] );
865 assert.t( "Nth-last-child(3)", "#form #select1 :nth-last-child(3)", [ "option1b" ] );
866 assert.t( "Nth-last-child(3)", "#form #select1 *:nth-last-child(3)", [ "option1b" ] );
867 assert.t( "Nth-last-child(3)", "#form #select1 option:nth-last-child(3)", [ "option1b" ] );
868 assert.t( "Nth-last-child(0n+3)", "#form #select1 option:nth-last-child(0n+3)", [ "option1b" ] );
869 assert.t( "Nth-last-child(1n+0)", "#form #select1 option:nth-last-child(1n+0)", [ "option1a", "option1b", "option1c", "option1d" ] );
870 assert.t( "Nth-last-child(1n)", "#form #select1 option:nth-last-child(1n)", [ "option1a", "option1b", "option1c", "option1d" ] );
871 assert.t( "Nth-last-child(n)", "#form #select1 option:nth-last-child(n)", [ "option1a", "option1b", "option1c", "option1d" ] );
872 assert.t( "Nth-last-child(even)", "#form #select1 option:nth-last-child(even)", [ "option1a", "option1c" ] );
873 assert.t( "Nth-last-child(odd)", "#form #select1 option:nth-last-child(odd)", [ "option1b", "option1d" ] );
874 assert.t( "Nth-last-child(2n)", "#form #select1 option:nth-last-child(2n)", [ "option1a", "option1c" ] );
875 assert.t( "Nth-last-child(2n+1)", "#form #select1 option:nth-last-child(2n+1)", [ "option1b", "option1d" ] );
876 assert.t( "Nth-last-child(2n + 1)", "#form #select1 option:nth-last-child(2n + 1)", [ "option1b", "option1d" ] );
877 assert.t( "Nth-last-child(+2n + 1)", "#form #select1 option:nth-last-child(+2n + 1)", [ "option1b", "option1d" ] );
878 assert.t( "Nth-last-child(3n)", "#form #select1 option:nth-last-child(3n)", [ "option1b" ] );
879 assert.t( "Nth-last-child(3n+1)", "#form #select1 option:nth-last-child(3n+1)", [ "option1a", "option1d" ] );
880 assert.t( "Nth-last-child(3n+2)", "#form #select1 option:nth-last-child(3n+2)", [ "option1c" ] );
881 assert.t( "Nth-last-child(3n+3)", "#form #select1 option:nth-last-child(3n+3)", [ "option1b" ] );
882 assert.t( "Nth-last-child(3n-1)", "#form #select1 option:nth-last-child(3n-1)", [ "option1c" ] );
883 assert.t( "Nth-last-child(3n-2)", "#form #select1 option:nth-last-child(3n-2)", [ "option1a", "option1d" ] );
884 assert.t( "Nth-last-child(3n-3)", "#form #select1 option:nth-last-child(3n-3)", [ "option1b" ] );
885 assert.t( "Nth-last-child(3n+0)", "#form #select1 option:nth-last-child(3n+0)", [ "option1b" ] );
886 assert.t( "Nth-last-child(-1n+3)", "#form #select1 option:nth-last-child(-1n+3)", [ "option1b", "option1c", "option1d" ] );
887 assert.t( "Nth-last-child(-n+3)", "#form #select1 option:nth-last-child(-n+3)", [ "option1b", "option1c", "option1d" ] );
888 assert.t( "Nth-last-child(-1n + 3)", "#form #select1 option:nth-last-child(-1n + 3)", [ "option1b", "option1c", "option1d" ] );
890 if ( QUnit.jQuerySelectors || this.safari ) {
892 jQuery( [ document.createElement( "a" ) ].concat( q( "ap" ) ) )
893 .filter( ":nth-last-child(n)" )
896 "Seeded nth-last-child"
899 // Support: Chrome 75+, Firefox 67+
900 // Some browsers mark disconnected elements as matching `:nth-last-child(n)`
901 // so let's skip the test.
902 assert.ok( "skip", "disconnected elements match ':nth-last-child(n)' in Chrome/Firefox" );
906 QUnit.test( "pseudo - nth-of-type", function( assert ) {
908 assert.t( "Nth-of-type(-1)", ":nth-of-type(-1)", [] );
909 assert.t( "Nth-of-type(3)", "#ap :nth-of-type(3)", [ "mark" ] );
910 assert.t( "Nth-of-type(n)", "#ap :nth-of-type(n)", [ "google", "groups", "code1", "anchor1", "mark" ] );
911 assert.t( "Nth-of-type(0n+3)", "#ap :nth-of-type(0n+3)", [ "mark" ] );
912 assert.t( "Nth-of-type(2n)", "#ap :nth-of-type(2n)", [ "groups" ] );
913 assert.t( "Nth-of-type(even)", "#ap :nth-of-type(even)", [ "groups" ] );
914 assert.t( "Nth-of-type(2n+1)", "#ap :nth-of-type(2n+1)", [ "google", "code1", "anchor1", "mark" ] );
915 assert.t( "Nth-of-type(odd)", "#ap :nth-of-type(odd)", [ "google", "code1", "anchor1", "mark" ] );
916 assert.t( "Nth-of-type(-n+2)", "#qunit-fixture > :nth-of-type(-n+2)", [ "firstp", "ap", "foo", "nothiddendiv", "name+value", "firstUL", "empty", "form", "floatTest", "iframe", "lengthtest", "table", "last" ] );
919 QUnit.test( "pseudo - nth-last-of-type", function( assert ) {
921 assert.t( "Nth-last-of-type(-1)", ":nth-last-of-type(-1)", [] );
922 assert.t( "Nth-last-of-type(3)", "#ap :nth-last-of-type(3)", [ "google" ] );
923 assert.t( "Nth-last-of-type(n)", "#ap :nth-last-of-type(n)", [ "google", "groups", "code1", "anchor1", "mark" ] );
924 assert.t( "Nth-last-of-type(0n+3)", "#ap :nth-last-of-type(0n+3)", [ "google" ] );
925 assert.t( "Nth-last-of-type(2n)", "#ap :nth-last-of-type(2n)", [ "groups" ] );
926 assert.t( "Nth-last-of-type(even)", "#ap :nth-last-of-type(even)", [ "groups" ] );
927 assert.t( "Nth-last-of-type(2n+1)", "#ap :nth-last-of-type(2n+1)", [ "google", "code1", "anchor1", "mark" ] );
928 assert.t( "Nth-last-of-type(odd)", "#ap :nth-last-of-type(odd)", [ "google", "code1", "anchor1", "mark" ] );
929 assert.t( "Nth-last-of-type(-n+2)", "#qunit-fixture > :nth-last-of-type(-n+2)", [ "ap", "name+value", "first", "firstUL", "empty", "floatTest", "iframe", "table", "testForm", "disabled-tests", "siblingTest", "fx-test-group", "last" ] );
932 QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "pseudo - has", function( assert ) {
935 assert.t( "Basic test", "p:has(a)", [ "firstp", "ap", "en", "sap" ] );
936 assert.t( "Basic test (irrelevant whitespace)", "p:has( a )", [ "firstp", "ap", "en", "sap" ] );
937 assert.t( "Nested with overlapping candidates",
938 "#qunit-fixture div:has(div:has(div:not([id])))",
939 [ "moretests", "t2037", "fx-test-group", "fx-queue" ] );
942 QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "pseudo - contains", function( assert ) {
945 var gh335 = document.getElementById( "qunit-fixture" ).appendChild(
946 document.createElement( "mark" ) );
948 gh335.appendChild( document.createTextNode( "raw line 1\nline 2" ) );
950 assert.ok( jQuery( "a:contains('')" ).length, "empty string" );
951 assert.t( "unquoted argument", "a:contains(Google)", [ "google", "groups" ] );
952 assert.t( "unquoted argument with whitespace", "a:contains(Google Groups)", [ "groups" ] );
953 assert.t( "quoted argument with whitespace and parentheses",
954 "a:contains('Google Groups (Link)')", [ "groups" ] );
955 assert.t( "quoted argument with double quotes and parentheses",
956 "a:contains(\"(Link)\")", [ "groups" ] );
957 assert.t( "unquoted argument with whitespace and paired parentheses",
958 "a:contains(Google Groups (Link))", [ "groups" ] );
959 assert.t( "unquoted argument with paired parentheses", "a:contains((Link))", [ "groups" ] );
960 assert.t( "quoted argument with CSS escapes",
961 "span:contains(\"\\\"'\\53F0 \\5317 Ta\\301 ibe\\30C i\")",
964 assert.t( "collapsed whitespace", "mark:contains('line 1\\A line')", [ "gh-335" ] );
967 QUnit.test( "pseudo - misc", function( assert ) {
970 var select, tmp, input;
972 jQuery( "<h1 id='h1'></h1><h2 id='h2'></h2><h2 id='h2-2'></h2>" ).prependTo( "#qunit-fixture" );
974 if ( QUnit.jQuerySelectors ) {
975 assert.t( "Headers", "#qunit-fixture :header", [ "h1", "h2", "h2-2" ] );
976 assert.t( "Headers(case-insensitive)", "#qunit-fixture :Header", [ "h1", "h2", "h2-2" ] );
978 assert.ok( "skip", ":header not supported in selector-native" );
979 assert.ok( "skip", ":header not supported in selector-native" );
982 if ( QUnit.jQuerySelectors ) {
983 assert.t( "Multiple matches with the same context (cache check)",
984 "#form select:has(option:first-child:contains('o'))",
985 [ "select1", "select2", "select3", "select4" ]
987 assert.ok( jQuery( "#qunit-fixture :not(:has(:has(*)))" ).length, "All not grandparents" );
989 select = document.getElementById( "select1" );
990 assert.ok( jQuery( select ).is( ":has(option)" ), "Has Option Matches" );
992 assert.ok( "skip", ":has not supported in selector-native" );
993 assert.ok( "skip", ":has not supported in selector-native" );
994 assert.ok( "skip", ":has not supported in selector-native" );
997 tmp = document.createElement( "div" );
998 tmp.id = "tmp_input";
999 document.body.appendChild( tmp );
1001 jQuery.each( [ "button", "submit", "reset" ], function( i, type ) {
1003 "<input id='input_%' type='%'/><button id='button_%' type='%'>test</button>"
1004 .replace( /%/g, type )
1007 if ( QUnit.jQuerySelectors ) {
1008 assert.t( "Input Buttons :" + type, "#tmp_input :" + type, [ "input_" + type, "button_" + type ] );
1010 assert.ok( jQuery( els[ 0 ] ).is( ":" + type ), "Input Matches :" + type );
1011 assert.ok( jQuery( els[ 1 ] ).is( ":" + type ), "Button Matches :" + type );
1013 assert.ok( "skip", ":" + type + " not supported in selector-native" );
1014 assert.ok( "skip", ":" + type + " not supported in selector-native" );
1015 assert.ok( "skip", ":" + type + " not supported in selector-native" );
1019 document.body.removeChild( tmp );
1022 tmp = document.createElement( "div" );
1023 tmp.id = "tmp_input";
1024 tmp.innerHTML = "<span>Hello I am focusable.</span>";
1025 // Setting tabIndex should make the element focusable
1026 // https://html.spec.whatwg.org/#the-tabindex-attribute
1027 document.body.appendChild( tmp );
1030 if ( document.activeElement !== tmp || ( document.hasFocus && !document.hasFocus() ) ||
1031 ( document.querySelectorAll && !document.querySelectorAll( "div:focus" ).length ) ) {
1032 assert.ok( true, "The div was not focused. Skip checking the :focus match." );
1033 assert.ok( true, "The div was not focused. Skip checking the :focus match." );
1035 assert.t( "tabIndex element focused", ":focus", [ "tmp_input" ] );
1036 assert.ok( jQuery( tmp ).is( ":focus" ), ":focus matches tabIndex div" );
1041 document.body.focus();
1042 assert.ok( !jQuery( tmp ).is( ":focus" ), ":focus doesn't match tabIndex div" );
1043 document.body.removeChild( tmp );
1045 // Input focus/active
1046 input = document.createElement( "input" );
1047 input.type = "text";
1048 input.id = "focus-input";
1050 document.body.appendChild( input );
1053 // Inputs can't be focused unless the document has focus
1054 if ( document.activeElement !== input || ( document.hasFocus && !document.hasFocus() ) ||
1055 ( document.querySelectorAll && !document.querySelectorAll( "input:focus" ).length ) ) {
1056 assert.ok( true, "The input was not focused. Skip checking the :focus match." );
1057 assert.ok( true, "The input was not focused. Skip checking the :focus match." );
1059 assert.t( "Element focused", "input:focus", [ "focus-input" ] );
1060 assert.ok( jQuery( input ).is( ":focus" ), ":focus matches" );
1065 // When IE is out of focus, blur does not work. Force it here.
1066 if ( document.activeElement === input ) {
1067 document.body.focus();
1070 assert.ok( !jQuery( input ).is( ":focus" ), ":focus doesn't match" );
1071 document.body.removeChild( input );
1075 jQuery( "[id='select1'] *:not(:last-child), [id='select2'] *:not(:last-child)", q( "qunit-fixture" )[ 0 ] ).get(),
1076 q( "option1a", "option1b", "option1c", "option2a", "option2b", "option2c" ),
1077 "caching system tolerates recursive selection"
1080 if ( QUnit.jQuerySelectors ) {
1081 // Tokenization edge cases
1082 assert.t( "Sequential pseudos", "#qunit-fixture p:has(:contains(mark)):has(code)", [ "ap" ] );
1083 assert.t( "Sequential pseudos", "#qunit-fixture p:has(:contains(mark)):has(code):contains(This link)", [ "ap" ] );
1085 assert.t( "Pseudo argument containing ')'", "p:has(>a.GROUPS[src!=')'])", [ "ap" ] );
1086 assert.t( "Pseudo argument containing ')'", "p:has(>a.GROUPS[src!=')'])", [ "ap" ] );
1087 assert.t( "Pseudo followed by token containing ')'", "p:contains(id=\"foo\")[id!=\\)]", [ "sndp" ] );
1088 assert.t( "Pseudo followed by token containing ')'", "p:contains(id=\"foo\")[id!=')']", [ "sndp" ] );
1090 assert.t( "Multi-pseudo", "#ap:has(*), #ap:has(*)", [ "ap" ] );
1091 assert.t( "Multi-pseudo with leading nonexistent id", "#nonexistent:has(*), #ap:has(*)", [ "ap" ] );
1093 assert.t( "Tokenization stressor", "a[class*=blog]:not(:has(*, :contains(!)), :contains(!)), br:contains(]), p:contains(]):not(.qunit-source), :not(:empty):not(:parent):not(.qunit-source)", [ "ap", "mark", "yahoo", "simon" ] );
1095 assert.ok( "skip", ":has not supported in selector-native" );
1096 assert.ok( "skip", ":has not supported in selector-native" );
1098 assert.ok( "skip", ":has not supported in selector-native" );
1099 assert.ok( "skip", ":has not supported in selector-native" );
1100 assert.ok( "skip", ":contains not supported in selector-native" );
1101 assert.ok( "skip", ":contains not supported in selector-native" );
1103 assert.ok( "skip", ":has not supported in selector-native" );
1104 assert.ok( "skip", ":has supported in selector-native" );
1106 assert.ok( "skip", ":has not supported in selector-native" );
1109 if ( QUnit.jQuerySelectorsPos ) {
1110 assert.t( "Multi-positional", "#ap:gt(0), #ap:lt(1)", [ "ap" ] );
1111 assert.t( "Multi-positional with leading nonexistent id", "#nonexistent:gt(0), #ap:lt(1)", [ "ap" ] );
1113 assert.ok( "skip", "Positional selectors are not supported" );
1114 assert.ok( "skip", "Positional selectors are not supported" );
1118 QUnit.test( "pseudo - :not", function( assert ) {
1119 assert.expect( 43 );
1121 assert.t( "Not", "a.blog:not(.link)", [ "mark" ] );
1123 if ( QUnit.jQuerySelectors ) {
1124 assert.t( "Not - multiple", "#form option:not(:contains(Nothing),#option1b,:selected)", [ "option1c", "option1d", "option2b", "option2c", "option3d", "option3e", "option4e", "option5b", "option5c" ] );
1125 assert.t( "Not - recursive", "#form option:not(:not(:selected))[id^='option3']", [ "option3b", "option3c" ] );
1127 assert.ok( "skip", ":contains not supported in selector-native" );
1128 assert.ok( "skip", ":selected not supported in selector-native" );
1131 if ( QUnit.jQuerySelectorsPos ) {
1132 assert.t( ":not() with :first", "#foo p:not(:first) .link", [ "simon" ] );
1134 assert.ok( "skip", "Positional selectors are not supported" );
1137 assert.t( ":not() failing interior", "#qunit-fixture p:not(.foo)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1138 assert.t( ":not() failing interior", "#qunit-fixture p:not(#blargh)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1140 if ( QUnit.jQuerySelectors || !QUnit.isIE ) {
1141 assert.t( ":not() failing interior", "#qunit-fixture p:not(div.foo)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1142 assert.t( ":not() failing interior", "#qunit-fixture p:not(p.foo)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1143 assert.t( ":not() failing interior", "#qunit-fixture p:not(div#blargh)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1144 assert.t( ":not() failing interior", "#qunit-fixture p:not(p#blargh)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1147 // IE doesn't support `:not(complex selector)`.
1148 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
1149 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
1150 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
1151 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
1154 assert.t( ":not Multiple", "#qunit-fixture p:not(a)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1155 assert.t( ":not Multiple", "#qunit-fixture p:not( a )", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1156 assert.t( ":not Multiple", "#qunit-fixture p:not( p )", [] );
1157 assert.t( ":not Multiple", "p:not(p)", [] );
1159 if ( QUnit.jQuerySelectors || !QUnit.isIE ) {
1160 assert.t( ":not Multiple", "#qunit-fixture p:not(a, b)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1161 assert.t( ":not Multiple", "#qunit-fixture p:not(a, b, div)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1162 assert.t( ":not Multiple", "p:not(a,p)", [] );
1163 assert.t( ":not Multiple", "p:not(p,a)", [] );
1164 assert.t( ":not Multiple", "p:not(a,p,b)", [] );
1167 // IE doesn't support `:not(complex selector)`.
1168 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
1169 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
1170 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
1171 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
1172 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
1175 if ( QUnit.jQuerySelectors ) {
1176 assert.t( ":not Multiple", ":input:not(:image,:input,:submit)", [] );
1177 assert.t( ":not Multiple", "#qunit-fixture p:not(:has(a), :nth-child(1))", [ "first" ] );
1179 assert.ok( "skip", ":image, :input, :submit not supported in selector-native" );
1180 assert.ok( "skip", ":has not supported in selector-native" );
1183 assert.t( "No element not selector", ".container div:not(.excluded) div", [] );
1185 assert.t( ":not() Existing attribute", "#form select:not([multiple])", [ "select1", "select2", "select5" ] );
1186 assert.t( ":not() Equals attribute", "#form select:not([name=select1])", [ "select2", "select3", "select4", "select5" ] );
1187 assert.t( ":not() Equals quoted attribute", "#form select:not([name='select1'])", [ "select2", "select3", "select4", "select5" ] );
1189 assert.t( ":not() Multiple Class", "#foo a:not(.blog)", [ "yahoo", "anchor2" ] );
1190 assert.t( ":not() Multiple Class", "#foo a:not(.link)", [ "yahoo", "anchor2" ] );
1192 if ( QUnit.jQuerySelectors || !QUnit.isIE ) {
1193 assert.t( ":not() Multiple Class", "#foo a:not(.blog.link)", [ "yahoo", "anchor2" ] );
1196 // IE doesn't support `:not(complex selector)`.
1197 assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
1200 if ( QUnit.jQuerySelectors ) {
1201 assert.t( ":not chaining (compound)", "#qunit-fixture div[id]:not(:has(div, span)):not(:has(*))", [ "nothiddendivchild", "divWithNoTabIndex", "fx-tests" ] );
1202 assert.t( ":not chaining (with attribute)", "#qunit-fixture form[id]:not([action$='formaction']):not(:button)", [ "lengthtest", "name-tests", "testForm", "disabled-tests" ] );
1203 assert.t( ":not chaining (colon in attribute)", "#qunit-fixture form[id]:not([action='form:action']):not(:button)", [ "form", "lengthtest", "name-tests", "testForm", "disabled-tests" ] );
1204 assert.t( ":not chaining (colon in attribute and nested chaining)", "#qunit-fixture form[id]:not([action='form:action']:button):not(:input)", [ "form", "lengthtest", "name-tests", "testForm", "disabled-tests" ] );
1205 assert.t( ":not chaining", "#form select:not(.select1):contains(Nothing) > option:not(option)", [] );
1207 assert.ok( "skip", ":has not supported in selector-native" );
1208 assert.ok( "skip", ":button not supported in selector-native" );
1209 assert.ok( "skip", ":button not supported in selector-native" );
1210 assert.ok( "skip", ":button not supported in selector-native" );
1211 assert.ok( "skip", ":contains not supported in selector-native" );
1214 if ( QUnit.jQuerySelectorsPos ) {
1215 assert.t( "positional :not()", "#foo p:not(:last)", [ "sndp", "en" ] );
1216 assert.t( "positional :not() prefix", "#foo p:not(:last) a", [ "yahoo" ] );
1217 assert.t( "compound positional :not()", "#foo p:not(:first, :last)", [ "en" ] );
1218 assert.t( "compound positional :not()", "#foo p:not(:first, :even)", [ "en" ] );
1219 assert.t( "compound positional :not()", "#foo p:not(:first, :odd)", [ "sap" ] );
1220 assert.t( "reordered compound positional :not()", "#foo p:not(:odd, :first)", [ "sap" ] );
1222 assert.t( "positional :not() with pre-filter", "#foo p:not([id]:first)", [ "en", "sap" ] );
1223 assert.t( "positional :not() with post-filter", "#foo p:not(:first[id])", [ "en", "sap" ] );
1224 assert.t( "positional :not() with pre-filter", "#foo p:not([lang]:first)", [ "sndp", "sap" ] );
1225 assert.t( "positional :not() with post-filter", "#foo p:not(:first[lang])", [ "sndp", "en", "sap" ] );
1227 assert.ok( "skip", "Positional selectors are not supported" );
1228 assert.ok( "skip", "Positional selectors are not supported" );
1229 assert.ok( "skip", "Positional selectors are not supported" );
1230 assert.ok( "skip", "Positional selectors are not supported" );
1231 assert.ok( "skip", "Positional selectors are not supported" );
1232 assert.ok( "skip", "Positional selectors are not supported" );
1234 assert.ok( "skip", "Positional selectors are not supported" );
1235 assert.ok( "skip", "Positional selectors are not supported" );
1236 assert.ok( "skip", "Positional selectors are not supported" );
1237 assert.ok( "skip", "Positional selectors are not supported" );
1241 QUnit[ QUnit.jQuerySelectorsPos ? "test" : "skip" ]( "pseudo - position", function( assert ) {
1242 assert.expect( 34 );
1244 assert.t( "First element", "#qunit-fixture p:first", [ "firstp" ] );
1245 assert.t( "First element(case-insensitive)", "#qunit-fixture p:fiRst", [ "firstp" ] );
1246 assert.t( "nth Element", "#qunit-fixture p:nth(1)", [ "ap" ] );
1247 assert.t( "First Element", "#qunit-fixture p:first", [ "firstp" ] );
1248 assert.t( "Last Element", "p:last", [ "first" ] );
1249 assert.t( "Even Elements", "#qunit-fixture p:even", [ "firstp", "sndp", "sap" ] );
1250 assert.t( "Odd Elements", "#qunit-fixture p:odd", [ "ap", "en", "first" ] );
1251 assert.t( "Position Equals", "#qunit-fixture p:eq(1)", [ "ap" ] );
1252 assert.t( "Position Equals (negative)", "#qunit-fixture p:eq(-1)", [ "first" ] );
1253 assert.t( "Position Greater Than", "#qunit-fixture p:gt(0)", [ "ap", "sndp", "en", "sap", "first" ] );
1254 assert.t( "Position Less Than", "#qunit-fixture p:lt(3)", [ "firstp", "ap", "sndp" ] );
1255 assert.t( "Position Less Than Big Number", "#qunit-fixture p:lt(9007199254740991)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1257 assert.t( "Check position filtering", "div#nothiddendiv:eq(0)", [ "nothiddendiv" ] );
1258 assert.t( "Check position filtering", "div#nothiddendiv:last", [ "nothiddendiv" ] );
1259 assert.t( "Check position filtering", "div#nothiddendiv:not(:gt(0))", [ "nothiddendiv" ] );
1260 assert.t( "Check position filtering", "#foo > :not(:first)", [ "en", "sap" ] );
1261 assert.t( "Check position filtering", "#qunit-fixture select > :not(:gt(2))", [ "option1a", "option1b", "option1c" ] );
1262 assert.t( "Check position filtering", "#qunit-fixture select:lt(2) :not(:first)", [ "option1b", "option1c", "option1d", "option2a", "option2b", "option2c", "option2d" ] );
1263 assert.t( "Check position filtering", "div.nothiddendiv:eq(0)", [ "nothiddendiv" ] );
1264 assert.t( "Check position filtering", "div.nothiddendiv:last", [ "nothiddendiv" ] );
1265 assert.t( "Check position filtering", "div.nothiddendiv:not(:lt(0))", [ "nothiddendiv" ] );
1267 assert.t( "Check element position", "#qunit-fixture div div:eq(0)", [ "nothiddendivchild" ] );
1268 assert.t( "Check element position", "#select1 option:eq(3)", [ "option1d" ] );
1269 assert.t( "Check element position", "#qunit-fixture div div:eq(10)", [ "no-clone-exception" ] );
1270 assert.t( "Check element position", "#qunit-fixture div div:first", [ "nothiddendivchild" ] );
1271 assert.t( "Check element position", "#qunit-fixture div > div:first", [ "nothiddendivchild" ] );
1272 assert.t( "Check element position", "#qunit-fixture div:first a:first", [ "yahoo" ] );
1273 assert.t( "Check element position", "#qunit-fixture div:first > p:first", [ "sndp" ] );
1274 assert.t( "Check element position", "div#nothiddendiv:first > div:first", [ "nothiddendivchild" ] );
1275 assert.t( "Chained pseudo after a pos pseudo", "#listWithTabIndex li:eq(0):contains(Rice)", [ "foodWithNegativeTabIndex" ] );
1277 assert.t( "Check sort order with POS and comma", "#qunit-fixture em>em>em>em:first-child,div>em:first", [ "siblingfirst", "siblinggreatgrandchild" ] );
1279 assert.t( "Isolated position", "#qunit-fixture :last", [ "last" ] );
1282 jQuery( "#qunit-fixture > p" ).filter( "*:lt(2) + *" ).get(),
1284 "Seeded pos with trailing relative" );
1287 var context = jQuery( "#qunit-fixture" ).append( "<div id='jquery12526'></div>" )[ 0 ];
1288 assert.deepEqual( jQuery( ":last", context ).get(), q( "jquery12526" ),
1289 "Post-manipulation positional" );
1292 QUnit.test( "pseudo - form", function( assert ) {
1293 assert.expect( 16 );
1295 var extraTexts = jQuery( "<input id=\"impliedText\"/><input id=\"capitalText\" type=\"TEXT\">" ).appendTo( "#form" );
1297 if ( QUnit.jQuerySelectors ) {
1298 assert.t( "Form element :radio", "#form :radio", [ "radio1", "radio2" ] );
1299 assert.t( "Form element :checkbox", "#form :checkbox", [ "check1", "check2" ] );
1300 assert.t( "Form element :text", "#form :text", [ "text1", "text2", "hidden2", "name", "impliedText", "capitalText" ] );
1301 assert.t( "Form element :radio:checked", "#form :radio:checked", [ "radio2" ] );
1302 assert.t( "Form element :checkbox:checked", "#form :checkbox:checked", [ "check1" ] );
1303 assert.t( "Form element :radio:checked, :checkbox:checked", "#form :radio:checked, #form :checkbox:checked", [ "radio2", "check1" ] );
1305 assert.ok( "skip", ":radio not supported in selector-native" );
1306 assert.ok( "skip", ":checkbox not supported in selector-native" );
1307 assert.ok( "skip", ":text not supported in selector-native" );
1308 assert.ok( "skip", ":radio not supported in selector-native" );
1309 assert.ok( "skip", ":checkbox not supported in selector-native" );
1310 assert.ok( "skip", ":radio not supported in selector-native" );
1313 if ( QUnit.jQuerySelectors ) {
1314 assert.t( "Selected option element",
1315 "#form option:selected",
1316 [ "option1a", "option2d", "option3b", "option3c", "option4b", "option4c", "option4d",
1318 assert.t( "Select options via :selected", "#select1 option:selected", [ "option1a" ] );
1319 assert.t( "Select options via :selected", "#select2 option:selected", [ "option2d" ] );
1320 assert.t( "Select options via :selected", "#select3 option:selected", [ "option3b", "option3c" ] );
1321 assert.t( "Select options via :selected", "select[name='select2'] option:selected", [ "option2d" ] );
1323 assert.ok( "skip", ":selected not supported in selector-native" );
1324 assert.ok( "skip", ":selected not supported in selector-native" );
1325 assert.ok( "skip", ":selected not supported in selector-native" );
1326 assert.ok( "skip", ":selected not supported in selector-native" );
1327 assert.ok( "skip", ":selected not supported in selector-native" );
1330 if ( QUnit.jQuerySelectors ) {
1331 assert.t( "Form element :input", "#form :input", [ "text1", "text2", "radio1", "radio2", "check1", "check2", "hidden1", "hidden2", "name", "search", "button", "area1", "select1", "select2", "select3", "select4", "select5", "impliedText", "capitalText" ] );
1335 jQuery( "<select value='12600'><option value='option' selected='selected'></option><option value=''></option></select>" )
1336 .prop( "value", "option" )
1337 .is( ":input[value='12600']" ),
1339 ":input[value=foo] selects select by attribute"
1341 assert.ok( jQuery( "<input type='text' value='12600'/>" ).prop( "value", "option" ).is( ":input[value='12600']" ),
1342 ":input[value=foo] selects text input by attribute"
1345 assert.ok( "skip", ":input not supported in selector-native" );
1346 assert.ok( "skip", ":input not supported in selector-native" );
1347 assert.ok( "skip", ":input not supported in selector-native" );
1350 assert.t( "Selected option elements are also :checked", "#form option:checked",
1351 [ "option1a", "option2d", "option3b", "option3c", "option4b", "option4c", "option4d",
1353 assert.t( "Hidden inputs are still :enabled",
1357 extraTexts.remove();
1360 QUnit.test( "pseudo - :(dis|en)abled, explicitly disabled", function( assert ) {
1363 // Set a meaningless disabled property on a common ancestor
1364 var container = document.getElementById( "disabled-tests" );
1365 container.disabled = true;
1367 // Support: IE 6 - 11
1368 // Unset the property where it is not meaningless
1369 if ( document.getElementById( "enabled-input" ).isDisabled ) {
1370 container.disabled = undefined;
1374 "Explicitly disabled elements",
1375 "#enabled-fieldset :disabled",
1376 [ "disabled-input", "disabled-textarea", "disabled-button",
1377 "disabled-select", "disabled-optgroup", "disabled-option" ]
1380 if ( QUnit.jQuerySelectors ) {
1383 "#enabled-fieldset :enabled",
1384 [ "enabled-input", "enabled-textarea", "enabled-button",
1385 "enabled-select", "enabled-optgroup", "enabled-option" ]
1388 assert.ok( "skip", ":enabled broken in Chrome in selector-native" );
1392 QUnit.test( "pseudo - :(dis|en)abled, optgroup and option", function( assert ) {
1397 "#disabled-select-inherit :disabled, #enabled-select-inherit :disabled",
1398 [ "disabled-optgroup-inherit", "disabled-optgroup-option", "en_disabled-optgroup-inherit",
1399 "en_disabled-optgroup-option" ]
1404 "#disabled-select-inherit :enabled, #enabled-select-inherit :enabled",
1405 [ "enabled-optgroup-inherit", "enabled-optgroup-option", "enabled-select-option" ]
1409 QUnit.test( "pseudo - fieldset:(dis|en)abled", function( assert ) {
1412 assert.t( "Disabled fieldset", "fieldset:disabled", [ "disabled-fieldset" ] );
1413 assert.t( "Enabled fieldset", "fieldset:enabled", [ "enabled-fieldset" ] );
1416 QUnit.test( "pseudo - :disabled by ancestry", function( assert ) {
1420 "Inputs inherit disabled from fieldset",
1421 "#disabled-fieldset :disabled",
1422 [ "disabled-fieldset-input", "disabled-fieldset-textarea",
1423 "disabled-fieldset-button" ]
1427 QUnit.test( "pseudo - a:(dis|en)abled", function( assert ) {
1430 var enabled, disabled,
1431 container = jQuery( "<div></div>" ),
1432 anchor = jQuery( "<a href='#'>Link</a>" );
1434 container.appendTo( "#qunit-fixture" );
1436 enabled = container.find( "a:enabled" );
1437 disabled = container.find( "a:disabled" );
1439 assert.strictEqual( enabled.length, 0, ":enabled doesn't match anchor elements" );
1440 assert.strictEqual( disabled.length, 0, ":disabled doesn't match anchor elements" );
1443 QUnit.test( "pseudo - :target and :root", function( assert ) {
1448 $link = jQuery( "<a></a>" ).attr( {
1451 } ).appendTo( "#qunit-fixture" );
1453 oldHash = window.location.hash;
1454 window.location.hash = "new-link";
1456 assert.t( ":target", ":target", [ "new-link" ] );
1459 window.location.hash = oldHash;
1462 assert.equal( jQuery( ":root" )[ 0 ], document.documentElement, ":root selector" );
1465 QUnit.test( "pseudo - :lang", function( assert ) {
1466 assert.expect( QUnit.jQuerySelectors ? 105 : 55 );
1468 var docElem = document.documentElement,
1469 docXmlLang = docElem.getAttribute( "xml:lang" ),
1470 docLang = docElem.lang,
1471 foo = document.getElementById( "foo" ),
1472 anchor = document.getElementById( "anchor2" ),
1473 xml = createWithFriesXML(),
1474 testLang = function( text, elem, container, lang, extra ) {
1476 full = lang + "-" + extra;
1478 message = "lang=" + lang + " " + text;
1479 container.setAttribute( container.ownerDocument.documentElement.nodeName === "HTML" ? "lang" : "xml:lang", lang );
1480 assertMatch( message, elem, ":lang(" + lang + ")" );
1481 assertMatch( message, elem, ":lang(" + mixCase( lang ) + ")" );
1482 assertNoMatch( message, elem, ":lang(" + full + ")" );
1483 assertNoMatch( message, elem, ":lang(" + mixCase( full ) + ")" );
1484 assertNoMatch( message, elem, ":lang(" + lang + "-)" );
1485 assertNoMatch( message, elem, ":lang(" + full + "-)" );
1486 assertNoMatch( message, elem, ":lang(" + lang + "glish)" );
1487 assertNoMatch( message, elem, ":lang(" + full + "glish)" );
1489 message = "lang=" + full + " " + text;
1490 container.setAttribute( container.ownerDocument.documentElement.nodeName === "HTML" ? "lang" : "xml:lang", full );
1491 assertMatch( message, elem, ":lang(" + lang + ")" );
1492 assertMatch( message, elem, ":lang(" + mixCase( lang ) + ")" );
1493 assertMatch( message, elem, ":lang(" + full + ")" );
1494 assertMatch( message, elem, ":lang(" + mixCase( full ) + ")" );
1495 assertNoMatch( message, elem, ":lang(" + lang + "-)" );
1496 assertNoMatch( message, elem, ":lang(" + full + "-)" );
1497 assertNoMatch( message, elem, ":lang(" + lang + "glish)" );
1498 assertNoMatch( message, elem, ":lang(" + full + "glish)" );
1500 mixCase = function( str ) {
1501 var ret = str.split( "" ),
1505 ret[ i ] = ret[ i ].toUpperCase();
1508 return ret.join( "" );
1510 assertMatch = function( text, elem, selector ) {
1511 assert.ok( jQuery( elem ).is( selector ), text + " match " + selector );
1513 assertNoMatch = function( text, elem, selector ) {
1514 assert.ok( !jQuery( elem ).is( selector ), text + " fail " + selector );
1517 // Prefixing and inheritance
1518 assert.ok( jQuery( docElem ).is( ":lang(" + docElem.lang + ")" ), "starting :lang" );
1519 testLang( "document", anchor, docElem, "en", "us" );
1520 testLang( "grandparent", anchor, anchor.parentNode.parentNode, "yue", "hk" );
1521 assert.ok( !jQuery( anchor ).is( ":lang(en), :lang(en-us)" ),
1522 ":lang does not look above an ancestor with specified lang" );
1523 testLang( "self", anchor, anchor, "es", "419" );
1525 !jQuery( anchor ).is( ":lang(en), :lang(en-us), :lang(yue), :lang(yue-hk)" ),
1526 ":lang does not look above self with specified lang"
1529 // Searching by language tag
1530 anchor.parentNode.parentNode.lang = "arab";
1531 anchor.parentNode.lang = anchor.parentNode.id = "ara-sa";
1532 anchor.lang = "ara";
1533 assert.deepEqual( jQuery( ":lang(ara)", foo ).get(), [ anchor.parentNode, anchor ], "Find by :lang" );
1535 // Selector validity
1536 anchor.parentNode.lang = "ara";
1537 anchor.lang = "ara\\b";
1538 assert.deepEqual( jQuery( ":lang(ara\\b)", foo ).get(), [], ":lang respects backslashes" );
1539 assert.deepEqual( jQuery( ":lang(ara\\\\b)", foo ).get(), [ anchor ],
1540 ":lang respects escaped backslashes" );
1541 assert.throws( function() {
1542 jQuery( "#qunit-fixture:lang(c++)" );
1543 }, ":lang value must be a valid identifier" );
1545 if ( QUnit.jQuerySelectors ) {
1548 foo = jQuery( "response", xml )[ 0 ];
1549 anchor = jQuery( "#seite1", xml )[ 0 ];
1550 testLang( "XML document", anchor, xml.documentElement, "en", "us" );
1551 testLang( "XML grandparent", anchor, foo, "yue", "hk" );
1552 assert.ok( !jQuery( anchor ).is( ":lang(en), :lang(en-us)" ),
1553 "XML :lang does not look above an ancestor with specified lang" );
1554 testLang( "XML self", anchor, anchor, "es", "419" );
1556 !jQuery( anchor ).is( ":lang(en), :lang(en-us), :lang(yue), :lang(yue-hk)" ),
1557 "XML :lang does not look above self with specified lang" );
1561 if ( docXmlLang == null ) {
1562 docElem.removeAttribute( "xml:lang" );
1564 docElem.setAttribute( "xml:lang", docXmlLang );
1566 docElem.lang = docLang;
1569 QUnit.test( "context", function( assert ) {
1570 assert.expect( 21 );
1574 expected = q( "mark", "simon" ),
1575 iframe = document.getElementById( "iframe" ),
1576 iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
1578 assert.deepEqual( jQuery( selector, document ).get(), expected, "explicit document context" );
1579 assert.deepEqual( jQuery( selector ).get(), expected, "unspecified context becomes document" );
1580 assert.deepEqual( jQuery( selector, undefined ).get(), expected,
1581 "undefined context becomes document" );
1582 assert.deepEqual( jQuery( selector, null ).get(), expected, "null context becomes document" );
1585 iframeDoc.write( "<body><p id='foo'>bar</p></body>" );
1587 expected = [ iframeDoc.getElementById( "foo" ) ];
1588 assert.deepEqual( jQuery( "p", iframeDoc ).get(), expected, "Other document context (simple)" );
1590 if ( QUnit.jQuerySelectors ) {
1591 assert.deepEqual( jQuery( "p:contains(ar)", iframeDoc ).get(), expected,
1592 "Other document context (complex)" );
1594 assert.ok( "skip", ":contains not supported in selector-native" );
1597 assert.deepEqual( jQuery( "span", iframeDoc ).get(), [],
1598 "Other document context (simple, no results)" );
1599 assert.deepEqual( jQuery( "* span", iframeDoc ).get(), [],
1600 "Other document context (complex, no results)" );
1602 context = document.getElementById( "nothiddendiv" );
1603 assert.deepEqual( jQuery( "*", context ).get(), q( "nothiddendivchild" ), "<div> context" );
1605 if ( QUnit.jQuerySelectors ) {
1606 assert.deepEqual( jQuery( "* > *", context ).get(), [], "<div> context (no results)" );
1608 assert.ok( "skip", "The whole selector not required to be under context in selector-native" );
1611 context.removeAttribute( "id" );
1612 assert.deepEqual( jQuery( "*", context ).get(), q( "nothiddendivchild" ), "no-id element context" );
1614 if ( QUnit.jQuerySelectors ) {
1615 assert.deepEqual( jQuery( "* > *", context ).get(), [], "no-id element context (no results)" );
1617 assert.ok( "skip", ":contains not supported in selector-native" );
1620 assert.strictEqual( context.getAttribute( "id" ) || "", "", "id not added by no-id selection" );
1622 context = document.getElementById( "lengthtest" );
1623 assert.deepEqual( jQuery( "input", context ).get(), q( "length", "idTest" ), "<form> context" );
1624 assert.deepEqual( jQuery( "select", context ).get(), [], "<form> context (no results)" );
1626 context = document.getElementById( "台北Táiběi" );
1627 expected = q( "台北Táiběi-child" );
1628 assert.deepEqual( jQuery( "span[id]", context ).get(), expected, "context with non-ASCII id" );
1629 assert.deepEqual( jQuery( "#台北Táiběi span[id]", context.parentNode ).get(), expected,
1630 "context with non-ASCII id selector prefix" );
1632 context = document.createDocumentFragment();
1634 // Capture *independent* expected nodes before they're detached from the page
1635 expected = q( "siblingnext", "siblingspan" );
1636 context.appendChild( document.getElementById( "siblingTest" ) );
1638 if ( QUnit.jQuerySelectors ) {
1640 jQuery( "em:nth-child(2)", context ).get(),
1641 expected.slice( 0, 1 ),
1642 "DocumentFragment context"
1644 assert.deepEqual( jQuery( "span", context ).get(), expected.slice( 1 ),
1645 "DocumentFragment context by tag name" );
1646 assert.deepEqual( jQuery( "p", context ).get(), [], "DocumentFragment context (no results)" );
1648 assert.ok( "skip", "selection on document fragments not supported in selector-native" );
1649 assert.ok( "skip", "selection on document fragments not supported in selector-native" );
1650 assert.ok( "skip", "selection on document fragments not supported in selector-native" );
1653 if ( QUnit.jQuerySelectors ) {
1655 jQuery( "em + :not(:has(*)):not(:empty), foo", context.firstChild ).get(),
1656 expected.slice( 0, 1 ),
1657 "Non-qSA path correctly sets detached context for sibling selectors (jQuery #14351)"
1660 assert.ok( "skip", ":has not supported in selector-native" );
1665 // IE doesn't support the :scope pseudo-class so it will trigger MutationObservers.
1666 // The test is skipped there.
1667 QUnit.testUnlessIE( "selectors maintaining context don't trigger mutation observers", function( assert ) {
1671 done = assert.async(),
1672 container = jQuery( "<div></div>" ),
1673 child = jQuery( "<div></div>" );
1675 child.appendTo( container );
1676 container.appendTo( "#qunit-fixture" );
1678 var observer = new MutationObserver( function() {
1679 clearTimeout( timeout );
1680 observer.disconnect();
1681 assert.ok( false, "Mutation observer fired during selection" );
1684 observer.observe( container[ 0 ], { attributes: true } );
1686 container.find( "div div" );
1688 timeout = setTimeout( function() {
1689 observer.disconnect();
1690 assert.ok( true, "Mutation observer didn't fire during selection" );
1695 QUnit.test( "caching does not introduce bugs", function( assert ) {
1698 var sap = document.getElementById( "sap" );
1700 jQuery( ":not(code)", document.getElementById( "ap" ) );
1702 jQuery( ":not(code)", document.getElementById( "foo" ) ).get(),
1703 q( "sndp", "en", "yahoo", "sap", "anchor2", "simon" ),
1704 "Reusing selector with new context"
1707 if ( QUnit.jQuerySelectorsPos ) {
1708 assert.t( "Deep ancestry caching in post-positional element matcher (jQuery #14657)",
1709 "#qunit-fixture a:lt(3):parent",
1710 [ "simon1", "google", "groups" ] );
1712 assert.ok( "skip", "Positional selectors are not supported" );
1715 sap.className = "original";
1716 jQuery( "#qunit-fixture .original" );
1717 document.getElementById( "nothiddendiv" ).appendChild(
1718 sap.cloneNode( true ) ).className = "clone";
1719 assert.equal( jQuery( "#qunit-fixture .clone [href*='2']" ).length, 1,
1720 "Cloning does not poison caches" );
1724 QUnit.test( "disconnected nodes", function( assert ) {
1727 var $div = jQuery( "<div></div>" );
1728 assert.equal( $div.is( "div" ), true, "Make sure .is('nodeName') works on disconnected nodes." );
1731 QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "disconnected nodes", function( assert ) {
1734 var $opt = jQuery( "<option></option>" ).attr( "value", "whipit" ).appendTo( "#qunit-fixture" ).detach();
1735 assert.equal( $opt.val(), "whipit", "option value" );
1736 assert.equal( $opt.is( ":selected" ), false, "unselected option" );
1737 $opt.prop( "selected", true );
1738 assert.equal( $opt.is( ":selected" ), true, "selected option" );
1742 // IE doesn't support Shadow DOM.
1743 // selector-native doesn't support querying inside of Shadow DOM.
1744 QUnit[ QUnit.jQuerySelectors && !QUnit.isIE ? "test" : "skip" ](
1745 "Shadow DOM nodes supported as root", function( assert ) {
1748 var shadowHost = jQuery( "<div></div>" ).appendTo( "#qunit-fixture" )[ 0 ];
1749 var shadowRoot = shadowHost.attachShadow( { mode: "open" } );
1751 shadowRoot.innerHTML = "<div class='vagabond'><p></p></div>";
1752 assert.equal( jQuery( shadowRoot ).find( ".vagabond" ).length, 1,
1753 "Selection by class with shadow root" );
1754 assert.equal( jQuery( shadowRoot ).find( "p" ).length, 1,
1755 "Paragraph element selected from shadow root" );
1759 "attributes - jQuery.attr",
1760 "selector/html5_selector.html",
1761 function( assert, jQuery, window, document ) {
1762 assert.expect( 38 );
1765 * Returns an array of elements with the given IDs
1766 * q & t are added here for the iFrame's context
1772 for ( ; i < arguments.length; i++ ) {
1773 r.push( document.getElementById( arguments[ i ] ) );
1779 * Asserts that a select matches the given IDs
1780 * @example t("Check for something", "//[a]", ["foo", "bar"]);
1781 * @param {String} message - Assertion name
1782 * @param {String} selector - jQuery selector
1783 * @param {Array} expectedIds - Array of ids to construct what is expected
1785 function t( message, selector, expectedIds ) {
1786 var elems = jQuery( selector ).get();
1788 assert.deepEqual( elems, q.apply( q, expectedIds ), message + " (" + selector + ")" );
1791 // ====== All known boolean attributes, including html5 booleans ======
1792 // autobuffer, autofocus, autoplay, async, checked,
1793 // compact, controls, declare, defer, disabled,
1794 // formnovalidate, hidden, indeterminate (property only),
1795 // ismap, itemscope, loop, multiple, muted, nohref, noresize,
1796 // noshade, nowrap, novalidate, open, pubdate, readonly, required,
1797 // reversed, scoped, seamless, selected, truespeed, visible (skipping visible attribute, which is on a barprop object)
1799 t( "Attribute Exists", "[autobuffer]", [ "video1" ] );
1800 t( "Attribute Exists", "[autofocus]", [ "text1" ] );
1801 t( "Attribute Exists", "[autoplay]", [ "video1" ] );
1802 t( "Attribute Exists", "[async]", [ "script1" ] );
1803 t( "Attribute Exists", "[checked]", [ "check1" ] );
1804 t( "Attribute Exists", "[compact]", [ "dl" ] );
1805 t( "Attribute Exists", "[controls]", [ "video1" ] );
1806 t( "Attribute Exists", "[declare]", [ "object1" ] );
1807 t( "Attribute Exists", "[defer]", [ "script1" ] );
1808 t( "Attribute Exists", "[disabled]", [ "check1" ] );
1809 t( "Attribute Exists", "[formnovalidate]", [ "form1" ] );
1810 t( "Attribute Exists", "[hidden]", [ "div1" ] );
1811 t( "Attribute Exists", "[indeterminate]", [] );
1812 t( "Attribute Exists", "[ismap]", [ "img1" ] );
1813 t( "Attribute Exists", "[itemscope]", [ "div1" ] );
1814 t( "Attribute Exists", "[loop]", [ "video1" ] );
1815 t( "Attribute Exists", "[multiple]", [ "select1" ] );
1816 t( "Attribute Exists", "[muted]", [ "audio1" ] );
1817 t( "Attribute Exists", "[nohref]", [ "area1" ] );
1818 t( "Attribute Exists", "[noresize]", [ "textarea1" ] );
1819 t( "Attribute Exists", "[noshade]", [ "hr1" ] );
1820 t( "Attribute Exists", "[nowrap]", [ "td1", "div1" ] );
1821 t( "Attribute Exists", "[novalidate]", [ "form1" ] );
1822 t( "Attribute Exists", "[open]", [ "details1" ] );
1823 t( "Attribute Exists", "[pubdate]", [ "article1" ] );
1824 t( "Attribute Exists", "[readonly]", [ "text1" ] );
1825 t( "Attribute Exists", "[required]", [ "text1" ] );
1826 t( "Attribute Exists", "[reversed]", [ "ol1" ] );
1827 t( "Attribute Exists", "[scoped]", [ "style1" ] );
1828 t( "Attribute Exists", "[seamless]", [ "iframe1" ] );
1829 t( "Attribute Exists", "[selected]", [ "option1" ] );
1830 t( "Attribute Exists", "[truespeed]", [ "marquee1" ] );
1832 // Enumerated attributes (these are not boolean content attributes)
1833 jQuery.expandedEach = jQuery.each;
1834 jQuery.expandedEach( [ "draggable", "contenteditable", "aria-disabled" ], function( i, val ) {
1835 t( "Enumerated attribute", "[" + val + "]", [ "div1" ] );
1837 t( "Enumerated attribute", "[spellcheck]", [ "span1" ] );
1839 t( "tabindex selector does not retrieve all elements in IE6/7 (#8473)",
1840 "form, [tabindex]", [ "form1", "text1" ] );
1841 t( "Improperly named form elements do not interfere with form selections (#9570)", "form[name='formName']", [ "form1" ] );
1845 QUnit.test( "jQuery.contains", function( assert ) {
1846 assert.expect( 16 );
1848 var container = document.getElementById( "nonnodes" ),
1849 element = container.firstChild,
1850 text = element.nextSibling,
1851 nonContained = container.nextSibling,
1852 detached = document.createElement( "a" );
1853 assert.ok( element && element.nodeType === 1, "preliminary: found element" );
1854 assert.ok( text && text.nodeType === 3, "preliminary: found text" );
1855 assert.ok( nonContained, "preliminary: found non-descendant" );
1856 assert.ok( jQuery.contains( container, element ), "child" );
1857 assert.ok( jQuery.contains( container.parentNode, element ), "grandchild" );
1858 assert.ok( jQuery.contains( container, text ), "text child" );
1859 assert.ok( jQuery.contains( container.parentNode, text ), "text grandchild" );
1860 assert.ok( !jQuery.contains( container, container ), "self" );
1861 assert.ok( !jQuery.contains( element, container ), "parent" );
1862 assert.ok( !jQuery.contains( container, nonContained ), "non-descendant" );
1863 assert.ok( !jQuery.contains( container, document ), "document" );
1864 assert.ok( !jQuery.contains( container, document.documentElement ), "documentElement (negative)" );
1865 assert.ok( !jQuery.contains( container, null ), "Passing null does not throw an error" );
1866 assert.ok( jQuery.contains( document, document.documentElement ), "documentElement (positive)" );
1867 assert.ok( jQuery.contains( document, element ), "document container (positive)" );
1868 assert.ok( !jQuery.contains( document, detached ), "document container (negative)" );
1871 QUnit.test( "jQuery.contains in SVG (jQuery trac-10832)", function( assert ) {
1875 "<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='1' width='1'>" +
1876 "<g><circle cx='1' cy='1' r='1' /></g>" +
1878 ).appendTo( "#qunit-fixture" )[ 0 ];
1880 assert.ok( jQuery.contains( svg, svg.firstChild ), "root child" );
1881 assert.ok( jQuery.contains( svg.firstChild, svg.firstChild.firstChild ), "element child" );
1882 assert.ok( jQuery.contains( svg, svg.firstChild.firstChild ), "root granchild" );
1883 assert.ok( !jQuery.contains( svg.firstChild.firstChild, svg.firstChild ),
1884 "parent (negative)" );
1887 QUnit.test( "jQuery.uniqueSort", function( assert ) {
1888 assert.expect( 14 );
1890 function Arrayish( arr ) {
1891 var i = this.length = arr.length;
1893 this[ i ] = arr[ i ];
1896 Arrayish.prototype = {
1904 body = document.body,
1905 fixture = document.getElementById( "qunit-fixture" ),
1906 detached1 = document.createElement( "p" ),
1907 detached2 = document.createElement( "ul" ),
1908 detachedChild = detached1.appendChild( document.createElement( "a" ) ),
1909 detachedGrandchild = detachedChild.appendChild( document.createElement( "b" ) );
1911 for ( i = 0; i < 12; i++ ) {
1912 detached.push( document.createElement( "li" ) );
1913 detached[ i ].id = "detached" + i;
1914 detached2.appendChild( document.createElement( "li" ) ).id = "detachedChild" + i;
1924 expected: [ fixture ]
1927 input: [ fixture, body ],
1928 expected: [ body, fixture ]
1931 input: [ body, fixture, fixture, body ],
1932 expected: [ body, fixture ]
1935 input: detached.slice( 0 ),
1936 expected: detached.slice( 0 )
1938 "Detached children": {
1940 detached2.childNodes[ 3 ],
1941 detached2.childNodes[ 0 ],
1942 detached2.childNodes[ 2 ],
1943 detached2.childNodes[ 1 ]
1946 detached2.childNodes[ 0 ],
1947 detached2.childNodes[ 1 ],
1948 detached2.childNodes[ 2 ],
1949 detached2.childNodes[ 3 ]
1952 "Attached/detached mixture": {
1953 input: [ detached1, fixture, detached2, document, detachedChild, body, detachedGrandchild ],
1954 expected: [ document, body, fixture ],
1959 jQuery.each( tests, function( label, test ) {
1960 var length = test.length || test.input.length;
1961 assert.deepEqual( jQuery.uniqueSort( test.input ).slice( 0, length ), test.expected, label + " (array)" );
1962 assert.deepEqual( jQuery.uniqueSort( new Arrayish( test.input ) ).slice( 0, length ), test.expected, label + " (quasi-array)" );
1967 "jQuery.uniqueSort works cross-window (trac-14381)",
1968 "selector/mixed_sort.html",
1969 function( assert, jQuery, window, document, actual, expected ) {
1972 assert.deepEqual( actual, expected, "Mixed array was sorted correctly" );
1977 "jQuery selector cache collides with multiple jQueries on a page",
1978 "selector/cache.html",
1979 function( assert, jQuery, window, document ) {
1980 var $cached = window.$cached;
1983 assert.notStrictEqual( jQuery, $cached, "Loaded two engines" );
1984 assert.deepEqual( $cached( ".test a" ).get(), [ document.getElementById( "collision" ) ], "Select collision anchor with first sizzle" );
1985 assert.equal( jQuery( ".evil a" ).length, 0, "Select nothing with second sizzle" );
1986 assert.equal( jQuery( ".evil a" ).length, 0, "Select nothing again with second sizzle" );
1990 QUnit.test( "Iframe dispatch should not affect jQuery (#13936)", function( assert ) {
1994 iframe = document.getElementById( "iframe" ),
1995 iframeDoc = iframe.contentDocument || iframe.contentWindow.document,
1996 done = assert.async();
1998 jQuery( iframe ).on( "load", function() {
2002 iframeDoc = this.contentDocument || this.contentWindow.document;
2003 form = jQuery( "#navigate", iframeDoc )[ 0 ];
2009 assert.strictEqual( thrown, false, "No error thrown from post-reload jQuery call" );
2012 jQuery( iframe ).off();
2022 iframeDoc.write( "<body><form id='navigate' action='?'></form></body>" );
2026 QUnit.test( "jQuery.escapeSelector", function( assert ) {
2027 assert.expect( 58 );
2030 assert.equal( jQuery.escapeSelector(), "undefined", "Converts undefined to string" );
2031 assert.equal( jQuery.escapeSelector( "-" ), "\\-", "Escapes standalone dash" );
2032 assert.equal( jQuery.escapeSelector( "-a" ), "-a", "Doesn't escape leading dash followed by non-number" );
2033 assert.equal( jQuery.escapeSelector( "--" ), "--", "Doesn't escape standalone double dash" );
2034 assert.equal( jQuery.escapeSelector( "\uFFFD" ), "\uFFFD",
2035 "Doesn't escape standalone replacement character" );
2036 assert.equal( jQuery.escapeSelector( "a\uFFFD" ), "a\uFFFD",
2037 "Doesn't escape trailing replacement character" );
2038 assert.equal( jQuery.escapeSelector( "\uFFFDb" ), "\uFFFDb",
2039 "Doesn't escape leading replacement character" );
2040 assert.equal( jQuery.escapeSelector( "a\uFFFDb" ), "a\uFFFDb",
2041 "Doesn't escape embedded replacement character" );
2043 // Derived from CSSOM tests
2044 // https://test.csswg.org/harness/test/cssom-1_dev/section/7.1/
2046 // String conversion
2047 assert.equal( jQuery.escapeSelector( true ), "true", "Converts boolean true to string" );
2048 assert.equal( jQuery.escapeSelector( false ), "false", "Converts boolean true to string" );
2049 assert.equal( jQuery.escapeSelector( null ), "null", "Converts null to string" );
2050 assert.equal( jQuery.escapeSelector( "" ), "", "Doesn't modify empty string" );
2053 assert.equal( jQuery.escapeSelector( "\0" ), "\uFFFD",
2054 "Escapes null-character input as replacement character" );
2055 assert.equal( jQuery.escapeSelector( "a\0" ), "a\uFFFD",
2056 "Escapes trailing-null input as replacement character" );
2057 assert.equal( jQuery.escapeSelector( "\0b" ), "\uFFFDb",
2058 "Escapes leading-null input as replacement character" );
2059 assert.equal( jQuery.escapeSelector( "a\0b" ), "a\uFFFDb",
2060 "Escapes embedded-null input as replacement character" );
2063 assert.equal( jQuery.escapeSelector( "0a" ), "\\30 a", "Escapes leading 0" );
2064 assert.equal( jQuery.escapeSelector( "1a" ), "\\31 a", "Escapes leading 1" );
2065 assert.equal( jQuery.escapeSelector( "2a" ), "\\32 a", "Escapes leading 2" );
2066 assert.equal( jQuery.escapeSelector( "3a" ), "\\33 a", "Escapes leading 3" );
2067 assert.equal( jQuery.escapeSelector( "4a" ), "\\34 a", "Escapes leading 4" );
2068 assert.equal( jQuery.escapeSelector( "5a" ), "\\35 a", "Escapes leading 5" );
2069 assert.equal( jQuery.escapeSelector( "6a" ), "\\36 a", "Escapes leading 6" );
2070 assert.equal( jQuery.escapeSelector( "7a" ), "\\37 a", "Escapes leading 7" );
2071 assert.equal( jQuery.escapeSelector( "8a" ), "\\38 a", "Escapes leading 8" );
2072 assert.equal( jQuery.escapeSelector( "9a" ), "\\39 a", "Escapes leading 9" );
2074 // Letter-number prefix
2075 assert.equal( jQuery.escapeSelector( "a0b" ), "a0b", "Doesn't escape embedded 0" );
2076 assert.equal( jQuery.escapeSelector( "a1b" ), "a1b", "Doesn't escape embedded 1" );
2077 assert.equal( jQuery.escapeSelector( "a2b" ), "a2b", "Doesn't escape embedded 2" );
2078 assert.equal( jQuery.escapeSelector( "a3b" ), "a3b", "Doesn't escape embedded 3" );
2079 assert.equal( jQuery.escapeSelector( "a4b" ), "a4b", "Doesn't escape embedded 4" );
2080 assert.equal( jQuery.escapeSelector( "a5b" ), "a5b", "Doesn't escape embedded 5" );
2081 assert.equal( jQuery.escapeSelector( "a6b" ), "a6b", "Doesn't escape embedded 6" );
2082 assert.equal( jQuery.escapeSelector( "a7b" ), "a7b", "Doesn't escape embedded 7" );
2083 assert.equal( jQuery.escapeSelector( "a8b" ), "a8b", "Doesn't escape embedded 8" );
2084 assert.equal( jQuery.escapeSelector( "a9b" ), "a9b", "Doesn't escape embedded 9" );
2086 // Dash-number prefix
2087 assert.equal( jQuery.escapeSelector( "-0a" ), "-\\30 a", "Escapes 0 after leading dash" );
2088 assert.equal( jQuery.escapeSelector( "-1a" ), "-\\31 a", "Escapes 1 after leading dash" );
2089 assert.equal( jQuery.escapeSelector( "-2a" ), "-\\32 a", "Escapes 2 after leading dash" );
2090 assert.equal( jQuery.escapeSelector( "-3a" ), "-\\33 a", "Escapes 3 after leading dash" );
2091 assert.equal( jQuery.escapeSelector( "-4a" ), "-\\34 a", "Escapes 4 after leading dash" );
2092 assert.equal( jQuery.escapeSelector( "-5a" ), "-\\35 a", "Escapes 5 after leading dash" );
2093 assert.equal( jQuery.escapeSelector( "-6a" ), "-\\36 a", "Escapes 6 after leading dash" );
2094 assert.equal( jQuery.escapeSelector( "-7a" ), "-\\37 a", "Escapes 7 after leading dash" );
2095 assert.equal( jQuery.escapeSelector( "-8a" ), "-\\38 a", "Escapes 8 after leading dash" );
2096 assert.equal( jQuery.escapeSelector( "-9a" ), "-\\39 a", "Escapes 9 after leading dash" );
2098 // Double dash prefix
2099 assert.equal( jQuery.escapeSelector( "--a" ), "--a", "Doesn't escape leading double dash" );
2102 assert.equal( jQuery.escapeSelector( "\x01\x02\x1E\x1F" ), "\\1 \\2 \\1e \\1f ",
2103 "Escapes C0 control characters" );
2104 assert.equal( jQuery.escapeSelector( "\x80\x2D\x5F\xA9" ), "\x80\x2D\x5F\xA9",
2105 "Doesn't escape general punctuation or non-ASCII ISO-8859-1 characters" );
2107 jQuery.escapeSelector( "\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90" +
2108 "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F" ),
2109 "\\7f \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90" +
2110 "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F",
2111 "Escapes DEL control character"
2113 assert.equal( jQuery.escapeSelector( "\xA0\xA1\xA2" ), "\xA0\xA1\xA2",
2114 "Doesn't escape non-ASCII ISO-8859-1 characters" );
2115 assert.equal( jQuery.escapeSelector( "a0123456789b" ), "a0123456789b",
2116 "Doesn't escape embedded numbers" );
2117 assert.equal( jQuery.escapeSelector( "abcdefghijklmnopqrstuvwxyz" ), "abcdefghijklmnopqrstuvwxyz",
2118 "Doesn't escape lowercase ASCII letters" );
2119 assert.equal( jQuery.escapeSelector( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ), "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
2120 "Doesn't escape uppercase ASCII letters" );
2121 assert.equal( jQuery.escapeSelector( "\x20\x21\x78\x79" ), "\\ \\!xy",
2122 "Escapes non-word ASCII characters" );
2124 // Astral symbol (U+1D306 TETRAGRAM FOR CENTRE)
2125 assert.equal( jQuery.escapeSelector( "\uD834\uDF06" ), "\uD834\uDF06",
2126 "Doesn't escape astral characters" );
2129 assert.equal( jQuery.escapeSelector( "\uDF06" ), "\uDF06", "Doesn't escape lone low surrogate" );
2130 assert.equal( jQuery.escapeSelector( "\uD834" ), "\uD834", "Doesn't escape lone high surrogate" );