1 QUnit
.module( "selector", {
2 beforeEach: function() {
4 // Playwright WebKit on macOS doesn't expose `Safari` in its user agent
5 // string; use the "AppleWebKit" token. This token is also present
6 // in the Chromium UA, but it is locked to an older version there.
7 // Modern WebKit (Safari 13+) locks it to `605.1.15`.
8 this.safari
= /\bapplewebkit\/605\.1\.15\b/i.test( navigator
.userAgent
);
10 afterEach
: moduleTeardown
13 QUnit
.test( "empty", function( assert
) {
18 assert
.strictEqual( jQuery( "" ).length
, 0,
19 "Empty selector returns an empty array" );
21 assert
.deepEqual( jQuery( "div", document
.createTextNode( "" ) ).get(), [],
22 "Text element as context fails silently" );
23 form
= document
.getElementById( "form" );
24 assert
.ok( !jQuery( form
).is( "" ), "Empty string passed to .is() does not match" );
26 if ( QUnit
.jQuerySelectors
) {
27 assert
.equal( jQuery( " " ).length
, 0, "Empty selector returns an empty array" );
28 assert
.equal( jQuery( "\t" ).length
, 0, "Empty selector returns an empty array" );
30 assert
.ok( "skip", "whitespace-only selector not supported in selector-native" );
31 assert
.ok( "skip", "whitespace-only selector not supported in selector-native" );
35 QUnit
.test( "star", function( assert
) {
39 var all
= jQuery( "*" );
41 assert
.ok( all
.length
>= 30, "Select all" );
43 for ( i
= 0; i
< all
.length
; i
++ ) {
44 if ( all
[ i
].nodeType
=== 8 ) {
48 assert
.ok( good
, "Select all elements, no comment nodes" );
51 QUnit
.test( "element", function( assert
) {
54 var i
, lengthtest
, siblingTest
, html
;
55 var fixture
= document
.getElementById( "qunit-fixture" );
57 assert
.deepEqual( jQuery( "p", fixture
).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a Node context." );
58 assert
.deepEqual( jQuery( "p", "#qunit-fixture" ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a selector context." );
59 assert
.deepEqual( jQuery( "p", jQuery( "#qunit-fixture" ) ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a jQuery object context." );
60 assert
.deepEqual( jQuery( "#qunit-fixture" ).find( "p" ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a context via .find()." );
62 assert
.ok( jQuery( "#length" ).length
, "<input name=\"length\"> cannot be found under IE, see trac-945" );
63 assert
.ok( jQuery( "#lengthtest input" ).length
, "<input name=\"length\"> cannot be found under IE, see trac-945" );
66 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" );
68 assert
.equal( jQuery( "" ).length
, 0, "Empty selector returns an empty array" );
69 assert
.deepEqual( jQuery( "div", document
.createTextNode( "" ) ).get(), [],
70 "Text element as context fails silently" );
72 assert
.t( "Element Selector", "html", [ "html" ] );
73 assert
.t( "Element Selector", "body", [ "body" ] );
74 assert
.t( "Element Selector", "#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
76 assert
.t( "Leading space", " #qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
77 assert
.t( "Leading tab", "\t#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
78 assert
.t( "Leading carriage return", "\r#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
79 assert
.t( "Leading line feed", "\n#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
80 assert
.t( "Leading form feed", "\f#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
81 assert
.t( "Trailing space", "#qunit-fixture p ", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
82 assert
.t( "Trailing tab", "#qunit-fixture p\t", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
83 assert
.t( "Trailing carriage return", "#qunit-fixture p\r",
84 [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
85 assert
.t( "Trailing line feed", "#qunit-fixture p\n", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
86 assert
.t( "Trailing form feed", "#qunit-fixture p\f", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
89 jQuery( jQuery( "div ol" ) ).filter( "#qunit-fixture *" ).get(),
90 q( "empty", "listWithTabIndex" ),
94 jQuery( jQuery( "div\tol" ) ).filter( "#qunit-fixture *" ).get(),
95 q( "empty", "listWithTabIndex" ),
96 "Parent Element (non-space descendant combinator)"
99 // Check for unique-ness and sort order
100 assert
.deepEqual( jQuery( "p, div p" ), jQuery( "p" ), "Check for duplicates: p, div p" );
102 jQuery( "<h1 id='h1'></h1><h2 id='h2'></h2><h2 id='h2-2'></h2>" ).prependTo( "#qunit-fixture" );
103 assert
.t( "Checking sort order", "#qunit-fixture h2, #qunit-fixture h1", [ "h1", "h2", "h2-2" ] );
105 if ( QUnit
.jQuerySelectorsPos
) {
106 assert
.t( "Checking sort order", "#qunit-fixture h2:first, #qunit-fixture h1:first", [ "h1", "h2" ] );
108 assert
.ok( "skip", "Positional selectors are not supported" );
111 assert
.t( "Checking sort order", "#qunit-fixture p, #qunit-fixture p a",
112 [ "firstp", "simon1", "ap", "google", "groups", "anchor1", "mark", "sndp", "en", "yahoo",
113 "sap", "anchor2", "simon", "first" ] );
116 lengthtest
= document
.getElementById( "lengthtest" );
117 assert
.deepEqual( jQuery( "#idTest", lengthtest
).get(), q( "idTest" ),
118 "Finding element with id of ID." );
119 assert
.deepEqual( jQuery( "[name='id']", lengthtest
).get(), q( "idTest" ),
120 "Finding element with id of ID." );
121 assert
.deepEqual( jQuery( "input[id='idTest']", lengthtest
).get(), q( "idTest" ),
122 "Finding elements with id of ID." );
124 siblingTest
= document
.getElementById( "siblingTest" );
125 assert
.deepEqual( jQuery( "div em", siblingTest
).get(), [],
126 "Element-rooted QSA does not select based on document context" );
127 assert
.deepEqual( jQuery( "div em, div em, div em:not(div em)", siblingTest
).get(), [],
128 "Element-rooted QSA does not select based on document context" );
129 assert
.deepEqual( jQuery( "div em, em\\,", siblingTest
).get(), [],
130 "Escaped commas do not get treated with an id in element-rooted QSA" );
133 for ( i
= 0; i
< 100; i
++ ) {
134 html
= "<div>" + html
+ "</div>";
136 html
= jQuery( html
).appendTo( document
.body
);
137 assert
.ok( !!jQuery( "body div div div" ).length
,
138 "No stack or performance problems with large amounts of descendants" );
139 assert
.ok( !!jQuery( "body>div div div" ).length
,
140 "No stack or performance problems with large amounts of descendants" );
143 // Real use case would be using .watch in browsers with window.watch
144 // (see https://github.com/jquery/sizzle/pull/157)
145 q( "qunit-fixture" )[ 0 ].appendChild( document
.createElement( "toString" ) ).id
= "toString";
146 assert
.t( "Element name matches Object.prototype property", "toString#toString", [ "toString" ] );
149 QUnit
.test( "XML Document Selectors", function( assert
) {
152 var xml
= createWithFriesXML();
154 assert
.equal( jQuery( "foo_bar", xml
).length
, 1, "Element Selector with underscore" );
155 assert
.equal( jQuery( ".component", xml
).length
, 1, "Class selector" );
156 assert
.equal( jQuery( "[class*=component]", xml
).length
, 1, "Attribute selector for class" );
157 assert
.equal( jQuery( "property[name=prop2]", xml
).length
, 1, "Attribute selector with name" );
158 assert
.equal( jQuery( "[name=prop2]", xml
).length
, 1, "Attribute selector with name" );
159 assert
.equal( jQuery( "#seite1", xml
).length
, 1, "Attribute selector with ID" );
160 assert
.equal( jQuery( "component#seite1", xml
).length
, 1, "Attribute selector with ID" );
161 assert
.equal( jQuery( "component", xml
).filter( "#seite1" ).length
, 1,
162 "Attribute selector filter with ID" );
163 assert
.equal( jQuery( "meta property thing", xml
).length
, 2,
164 "Descendent selector and dir caching" );
165 if ( QUnit
.jQuerySelectors
) {
166 assert
.ok( jQuery( xml
.lastChild
).is( "soap\\:Envelope" ), "Check for namespaced element" );
168 xml
= jQuery
.parseXML( "<?xml version='1.0' encoding='UTF-8'?><root><elem id='1'/></root>" );
170 assert
.equal( jQuery( "elem:not(:has(*))", xml
).length
, 1,
171 "Non-qSA path correctly handles numeric ids (jQuery trac-14142)" );
173 assert
.ok( "skip", "namespaced elements not matching correctly in selector-native" );
174 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
178 QUnit
.test( "broken selectors throw", function( assert
) {
181 function broken( name
, selector
) {
182 assert
.throws( function() {
184 }, name
+ ": " + selector
);
187 broken( "Broken 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", ",a" );
196 broken( "Broken Selector", "a," );
197 broken( "Post-comma invalid selector", "*,:x" );
198 broken( "Identifier with bad escape", "foo\\\fbaz" );
199 broken( "Broken Selector", "[id=012345678901234567890123456789" );
200 broken( "Doesn't exist", ":visble" );
201 broken( "Nth-child", ":nth-child" );
202 broken( "Nth-child", ":nth-child(-)" );
203 broken( "Nth-child", ":nth-child(asdf)", [] );
204 broken( "Nth-child", ":nth-child(2n+-0)" );
205 broken( "Nth-child", ":nth-child(2+0)" );
206 broken( "Nth-child", ":nth-child(- 1n)" );
207 broken( "Nth-child", ":nth-child(-1 n)" );
208 broken( "First-child", ":first-child(n)" );
209 broken( "Last-child", ":last-child(n)" );
210 broken( "Only-child", ":only-child(n)" );
211 broken( "Nth-last-last-child", ":nth-last-last-child(1)" );
212 broken( "First-last-child", ":first-last-child" );
213 broken( "Last-last-child", ":last-last-child" );
214 broken( "Only-last-child", ":only-last-child" );
216 // Make sure attribute value quoting works correctly. See: trac-6093
217 jQuery( "<input type='hidden' value='2' name='foo.baz' id='attrbad1'/>" +
218 "<input type='hidden' value='2' name='foo[baz]' id='attrbad2'/>" )
219 .appendTo( "#qunit-fixture" );
221 broken( "Attribute equals non-value", "input[name=]" );
222 broken( "Attribute equals unquoted non-identifier", "input[name=foo.baz]" );
223 broken( "Attribute equals unquoted non-identifier", "input[name=foo[baz]]" );
224 broken( "Attribute equals bad string", "input[name=''double-quoted'']" );
225 broken( "Attribute equals bad string", "input[name='apostrophe'd']" );
228 QUnit
.test( "id", function( assert
) {
233 assert
.t( "ID Selector", "#body", [ "body" ] );
234 assert
.t( "ID Selector w/ Element", "body#body", [ "body" ] );
235 assert
.t( "ID Selector w/ Element", "ul#first", [] );
236 assert
.t( "ID selector with existing ID descendant", "#firstp #simon1", [ "simon1" ] );
237 assert
.t( "ID selector with non-existent descendant", "#firstp #foobar", [] );
238 assert
.t( "ID selector using UTF8", "#台北Táiběi", [ "台北Táiběi" ] );
239 assert
.t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", [ "台北Táiběi", "台北" ] );
240 assert
.t( "Descendant ID selector using UTF8", "div #台北", [ "台北" ] );
241 assert
.t( "Child ID selector using UTF8", "form > #台北", [ "台北" ] );
243 assert
.t( "Escaped ID", "#foo\\:bar", [ "foo:bar" ] );
245 if ( QUnit
.jQuerySelectors
) {
246 assert
.t( "Escaped ID with descendant", "#foo\\:bar span:not(:input)", [ "foo_descendant" ] );
248 assert
.ok( "skip", ":input not supported in selector-native" );
251 assert
.t( "Escaped ID", "#test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
252 assert
.t( "Descendant escaped ID", "div #foo\\:bar", [ "foo:bar" ] );
253 assert
.t( "Descendant escaped ID", "div #test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
254 assert
.t( "Child escaped ID", "form > #foo\\:bar", [ "foo:bar" ] );
255 assert
.t( "Child escaped ID", "form > #test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
257 fiddle
= jQuery( "<div id='fiddle\\Foo'><span id='fiddleSpan'></span></div>" )
258 .appendTo( "#qunit-fixture" );
260 assert
.deepEqual( jQuery( "> span", jQuery( "#fiddle\\\\Foo" )[ 0 ] ).get(),
261 q( [ "fiddleSpan" ] ), "Escaped ID as context" );
265 assert
.t( "ID Selector, child ID present", "#form > #radio1", [ "radio1" ] ); // bug trac-267
266 assert
.t( "ID Selector, not an ancestor ID", "#form #first", [] );
267 assert
.t( "ID Selector, not a child ID", "#form > #option1a", [] );
269 assert
.t( "All Children of ID", "#foo > *", [ "sndp", "en", "sap" ] );
270 assert
.t( "All Children of ID with no children", "#firstUL > *", [] );
272 assert
.equal( jQuery( "#tName1" )[ 0 ].id
, "tName1",
273 "ID selector with same value for a name attribute" );
274 assert
.t( "ID selector non-existing but name attribute on an A tag", "#tName2", [] );
275 assert
.t( "Leading ID selector non-existing but name attribute on an A tag", "#tName2 span", [] );
276 assert
.t( "Leading ID selector existing, retrieving the child", "#tName1 span", [ "tName1-span" ] );
277 assert
.equal( jQuery( "div > div #tName1" )[ 0 ].id
, jQuery( "#tName1-span" )[ 0 ].parentNode
.id
,
280 a
= jQuery( "<a id='backslash\\foo'></a>" ).appendTo( "#qunit-fixture" );
281 assert
.t( "ID Selector contains backslash", "#backslash\\\\foo", [ "backslash\\foo" ] );
284 assert
.t( "ID Selector on Form with an input that has a name of 'id'", "#lengthtest", [ "lengthtest" ] );
286 assert
.t( "ID selector with non-existent ancestor", "#asdfasdf #foobar", [] ); // bug trac-986
288 assert
.deepEqual( jQuery( "div#form", document
.body
).get(), [],
289 "ID selector within the context of another element" );
291 assert
.t( "Underscore ID", "#types_all", [ "types_all" ] );
292 assert
.t( "Dash ID", "#qunit-fixture", [ "qunit-fixture" ] );
294 assert
.t( "ID with weird characters in it", "#name\\+value", [ "name+value" ] );
297 QUnit
.test( "class", function( assert
) {
300 assert
.deepEqual( jQuery( ".blog", document
.getElementsByTagName( "p" ) ).get(),
301 q( "mark", "simon" ), "Finding elements with a context." );
302 assert
.deepEqual( jQuery( ".blog", "p" ).get(),
303 q( "mark", "simon" ), "Finding elements with a context." );
304 assert
.deepEqual( jQuery( ".blog", jQuery( "p" ) ).get(),
305 q( "mark", "simon" ), "Finding elements with a context." );
306 assert
.deepEqual( jQuery( "p" ).find( ".blog" ).get(),
307 q( "mark", "simon" ), "Finding elements with a context." );
309 assert
.t( "Class Selector", ".blog", [ "mark", "simon" ] );
310 assert
.t( "Class Selector", ".GROUPS", [ "groups" ] );
311 assert
.t( "Class Selector", ".blog.link", [ "simon" ] );
312 assert
.t( "Class Selector w/ Element", "a.blog", [ "mark", "simon" ] );
313 assert
.t( "Parent Class Selector", "p .blog", [ "mark", "simon" ] );
315 assert
.t( "Class selector using UTF8", ".台北Táiběi", [ "utf8class1" ] );
316 assert
.t( "Class selector using UTF8", ".台北", [ "utf8class1", "utf8class2" ] );
317 assert
.t( "Class selector using UTF8", ".台北Táiběi.台北", [ "utf8class1" ] );
318 assert
.t( "Class selector using UTF8", ".台北Táiběi, .台北", [ "utf8class1", "utf8class2" ] );
319 assert
.t( "Descendant class selector using UTF8", "div .台北Táiběi", [ "utf8class1" ] );
320 assert
.t( "Child class selector using UTF8", "form > .台北Táiběi", [ "utf8class1" ] );
322 assert
.t( "Escaped Class", ".foo\\:bar", [ "foo:bar" ] );
323 assert
.t( "Escaped Class", ".test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
324 assert
.t( "Descendant escaped Class", "div .foo\\:bar", [ "foo:bar" ] );
325 assert
.t( "Descendant escaped Class", "div .test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
326 assert
.t( "Child escaped Class", "form > .foo\\:bar", [ "foo:bar" ] );
327 assert
.t( "Child escaped Class", "form > .test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] );
329 var div
= document
.createElement( "div" );
330 div
.innerHTML
= "<div class='test e'></div><div class='test'></div>";
331 assert
.deepEqual( jQuery( ".e", div
).get(), [ div
.firstChild
], "Finding a second class." );
333 div
.lastChild
.className
= "e";
335 assert
.ok( !jQuery( div
).is( ".null" ),
336 ".null does not match an element with no class" );
337 assert
.ok( !jQuery( div
.firstChild
).is( ".null div" ),
338 ".null does not match an element with no class" );
339 div
.className
= "null";
340 assert
.ok( jQuery( div
).is( ".null" ), ".null matches element with class 'null'" );
341 assert
.ok( jQuery( div
.firstChild
).is( ".null div" ),
342 "caching system respects DOM changes" );
343 assert
.ok( !jQuery( document
).is( ".foo" ),
344 "testing class on document doesn't error" );
345 assert
.ok( !jQuery( window
).is( ".foo" ), "testing class on window doesn't error" );
347 assert
.deepEqual( jQuery( ".e", div
).get(), [ div
.firstChild
, div
.lastChild
],
348 "Finding a modified class." );
350 div
.lastChild
.className
+= " hasOwnProperty toString";
351 assert
.deepEqual( jQuery( ".e.hasOwnProperty.toString", div
).get(), [ div
.lastChild
],
352 "Classes match Object.prototype properties" );
354 div
= jQuery( "<div><svg width='200' height='250' version='1.1'" +
355 " xmlns='http://www.w3.org/2000/svg'><rect x='10' y='10' width='30' height='30'" +
356 "class='foo'></rect></svg></div>" )[ 0 ];
357 assert
.equal( jQuery( ".foo", div
).length
, 1, "Class selector against SVG container" );
358 assert
.equal( jQuery( ".foo", div
.firstChild
).length
, 1,
359 "Class selector directly against SVG" );
362 QUnit
.test( "name", function( assert
) {
367 assert
.t( "Name selector", "input[name=action]", [ "text1" ] );
368 assert
.t( "Name selector with single quotes", "input[name='action']", [ "text1" ] );
369 assert
.t( "Name selector with double quotes", "input[name=\"action\"]", [ "text1" ] );
371 assert
.t( "Name selector non-input", "[name=example]", [ "name-is-example" ] );
372 assert
.t( "Name selector non-input", "[name=div]", [ "name-is-div" ] );
373 assert
.t( "Name selector non-input", "*[name=iframe]", [ "iframe" ] );
375 assert
.t( "Name selector for grouped input", "input[name='types[]']", [ "types_all", "types_anime", "types_movie" ] );
377 form
= document
.getElementById( "form" );
378 assert
.deepEqual( jQuery( "input[name=action]", form
).get(), q( "text1" ),
379 "Name selector within the context of another element" );
380 assert
.deepEqual( jQuery( "input[name='foo[bar]']", form
).get(), q( "hidden2" ),
381 "Name selector for grouped form element within the context of another element" );
383 form
= jQuery( "<form><input name='id'/></form>" ).appendTo( "body" );
384 assert
.equal( jQuery( "input", form
[ 0 ] ).length
, 1,
385 "Make sure that rooted queries on forms (with possible expandos) work." );
389 assert
.t( "Find elements that have similar IDs", "[name=tName1]", [ "tName1ID" ] );
390 assert
.t( "Find elements that have similar IDs", "[name=tName2]", [ "tName2ID" ] );
391 assert
.t( "Find elements that have similar IDs", "#tName2ID", [ "tName2ID" ] );
393 assert
.t( "Case-sensitivity", "[name=tname1]", [] );
396 QUnit
.test( "comma-separated", function( assert
) {
399 var fixture
= jQuery( "<div><h2><span></span></h2><div><p><span></span></p><p></p></div></div>" );
401 assert
.equal( fixture
.find( "h2, div p" ).filter( "p" ).length
, 2, "has to find two <p>" );
402 assert
.equal( fixture
.find( "h2, div p" ).filter( "h2" ).length
, 1, "has to find one <h2>" );
403 assert
.equal( fixture
.find( "h2 , div p" ).filter( "p" ).length
, 2, "has to find two <p>" );
404 assert
.equal( fixture
.find( "h2 , div p" ).filter( "h2" ).length
, 1, "has to find one <h2>" );
405 assert
.equal( fixture
.find( "h2 ,div p" ).filter( "p" ).length
, 2, "has to find two <p>" );
406 assert
.equal( fixture
.find( "h2 ,div p" ).filter( "h2" ).length
, 1, "has to find one <h2>" );
407 assert
.equal( fixture
.find( "h2,div p" ).filter( "p" ).length
, 2, "has to find two <p>" );
408 assert
.equal( fixture
.find( "h2,div p" ).filter( "h2" ).length
, 1, "has to find one <h2>" );
409 assert
.equal( fixture
.find( "h2\t,\rdiv p" ).filter( "p" ).length
, 2, "has to find two <p>" );
410 assert
.equal( fixture
.find( "h2\t,\rdiv p" ).filter( "h2" ).length
, 1, "has to find one <h2>" );
413 QUnit
.test( "comma-separated, only supported natively (gh-5177)", function( assert
) {
416 var fixture
= jQuery( "<div><input/><span></span></div>" );
418 fixture
.appendTo( "#qunit-fixture" );
420 assert
.equal( fixture
.find( "input:valid, span" ).length
, 2, "has to find two elements" );
421 assert
.equal( fixture
.find( "input:valid , span" ).length
, 2, "has to find two elements" );
422 assert
.equal( fixture
.find( "input:valid ,span" ).length
, 2, "has to find two elements" );
423 assert
.equal( fixture
.find( "input:valid,span" ).length
, 2, "has to find two elements" );
424 assert
.equal( fixture
.find( "input:valid\t,\rspan" ).length
, 2, "has to find two elements" );
427 QUnit
.test( "child and adjacent", function( assert
) {
430 var siblingFirst
, en
, nothiddendiv
;
432 assert
.t( "Child", "p > a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] );
433 assert
.t( "Child minus leading whitespace", "p> a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] );
434 assert
.t( "Child minus trailing whitespace", "p >a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] );
435 assert
.t( "Child minus whitespace", "p>a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] );
436 assert
.t( "Child w/ Class", "p > a.blog", [ "mark", "simon" ] );
437 assert
.t( "All Children", "code > *", [ "anchor1", "anchor2" ] );
438 assert
.selectInFixture( "All Grandchildren", "p > * > *", [ "anchor1", "anchor2" ] );
440 assert
.t( "Rooted tag adjacent", "#qunit-fixture a + a", [ "groups", "tName2ID" ] );
441 assert
.t( "Rooted tag adjacent minus whitespace", "#qunit-fixture a+a", [ "groups", "tName2ID" ] );
442 assert
.t( "Rooted tag adjacent minus leading whitespace", "#qunit-fixture a +a",
443 [ "groups", "tName2ID" ] );
444 assert
.t( "Rooted tag adjacent minus trailing whitespace", "#qunit-fixture a+ a",
445 [ "groups", "tName2ID" ] );
447 assert
.t( "Tag adjacent", "p + p", [ "ap", "en", "sap" ] );
448 assert
.t( "#id adjacent", "#firstp + p", [ "ap" ] );
449 assert
.t( "Tag#id adjacent", "p#firstp + p", [ "ap" ] );
450 assert
.t( "Tag[attr] adjacent", "p[lang=en] + p", [ "sap" ] );
451 assert
.t( "Tag.class adjacent", "a.GROUPS + code + a", [ "mark" ] );
452 assert
.t( "Comma, Child, and Adjacent", "#qunit-fixture a + a, code > a",
453 [ "groups", "anchor1", "anchor2", "tName2ID" ] );
455 assert
.t( "Element Preceded By", "#qunit-fixture p ~ div",
456 [ "foo", "nothiddendiv", "moretests", "tabindex-tests", "liveHandlerOrder", "siblingTest", "fx-test-group" ] );
457 assert
.t( "Element Preceded By", "#first ~ div",
458 [ "moretests", "tabindex-tests", "liveHandlerOrder", "siblingTest", "fx-test-group" ] );
459 assert
.t( "Element Preceded By", "#groups ~ a", [ "mark" ] );
460 assert
.t( "Element Preceded By", "#length ~ input", [ "idTest" ] );
461 assert
.t( "Element Preceded By", "#siblingfirst ~ em", [ "siblingnext", "siblingthird" ] );
462 assert
.t( "Element Preceded By (multiple)", "#siblingTest em ~ em ~ em ~ span", [ "siblingspan" ] );
464 siblingFirst
= document
.getElementById( "siblingfirst" );
466 assert
.deepEqual( jQuery( "+ em", siblingFirst
).get(), q( "siblingnext" ),
467 "Element Directly Preceded By with a context." );
468 assert
.deepEqual( jQuery( "~ em", siblingFirst
).get(), q( "siblingnext", "siblingthird" ),
469 "Element Preceded By with a context." );
471 if ( QUnit
.jQuerySelectorsPos
) {
472 assert
.deepEqual( jQuery( "~ em:first", siblingFirst
).get(), q( "siblingnext" ),
473 "Element Preceded By positional with a context." );
475 assert
.ok( "skip", "Positional selectors are not supported" );
478 en
= document
.getElementById( "en" );
479 assert
.deepEqual( jQuery( "+ p, a", en
).get(), q( "yahoo", "sap" ),
480 "Compound selector with context, beginning with sibling test." );
481 assert
.deepEqual( jQuery( "a, + p", en
).get(), q( "yahoo", "sap" ),
482 "Compound selector with context, containing sibling test." );
484 if ( QUnit
.jQuerySelectors
) {
485 assert
.t( "Element Preceded By, Containing", "#liveHandlerOrder ~ div em:contains('1')", [ "siblingfirst" ] );
486 assert
.t( "Combinators are not skipped when mixing general and specific", "#siblingTest > em:contains('x') + em ~ span", [] );
488 assert
.ok( "skip", ":contains not supported in selector-native" );
489 assert
.ok( "skip", ":contains not supported in selector-native" );
492 if ( QUnit
.jQuerySelectorsPos
) {
493 assert
.equal( jQuery( "#listWithTabIndex li:eq(2) ~ li" ).length
, 1, "Find by general sibling combinator (trac-8310)" );
495 nothiddendiv
= document
.getElementById( "nothiddendiv" );
496 assert
.deepEqual( jQuery( "> :first", nothiddendiv
).get(), q( "nothiddendivchild" ),
497 "Verify child context positional selector" );
498 assert
.deepEqual( jQuery( "> :eq(0)", nothiddendiv
).get(), q( "nothiddendivchild" ),
499 "Verify child context positional selector" );
500 assert
.deepEqual( jQuery( "> *:first", nothiddendiv
).get(), q( "nothiddendivchild" ),
501 "Verify child context positional selector" );
503 assert
.ok( "skip", "Positional selectors are not supported" );
504 assert
.ok( "skip", "Positional selectors are not supported" );
505 assert
.ok( "skip", "Positional selectors are not supported" );
506 assert
.ok( "skip", "Positional selectors are not supported" );
509 assert
.t( "Multiple combinators selects all levels", "#siblingTest em *", [ "siblingchild", "siblinggrandchild", "siblinggreatgrandchild" ] );
510 assert
.t( "Multiple combinators selects all levels", "#siblingTest > em *", [ "siblingchild", "siblinggrandchild", "siblinggreatgrandchild" ] );
511 assert
.t( "Multiple sibling combinators doesn't miss general siblings", "#siblingTest > em:first-child + em ~ span", [ "siblingspan" ] );
513 assert
.equal( jQuery( "#listWithTabIndex" ).length
, 1, "Parent div for next test is found via ID (trac-8310)" );
514 assert
.equal( jQuery( "#__sizzle__" ).length
, 0, "Make sure the temporary id assigned by sizzle is cleared out (trac-8310)" );
515 assert
.equal( jQuery( "#listWithTabIndex" ).length
, 1, "Parent div for previous test is still found via ID (trac-8310)" );
517 assert
.t( "Verify deep class selector", "div.blah > p > a", [] );
518 assert
.t( "No element deep selector", "div.foo > span > a", [] );
519 assert
.t( "Non-existent ancestors", ".fototab > .thumbnails > a", [] );
522 QUnit
.test( "attributes - existence", function( assert
) {
525 assert
.t( "On element", "#qunit-fixture a[title]", [ "google" ] );
526 assert
.t( "On element (whitespace ignored)", "#qunit-fixture a[ title ]", [ "google" ] );
527 assert
.t( "On element (case-insensitive)", "#qunit-fixture a[TITLE]", [ "google" ] );
528 assert
.t( "On any element", "#qunit-fixture *[title]", [ "google" ] );
529 assert
.t( "On implicit element", "#qunit-fixture [title]", [ "google" ] );
530 assert
.t( "Boolean", "#select2 option[selected]", [ "option2d" ] );
531 assert
.t( "For attribute on label", "form label[for]", [ "label-for" ] );
534 QUnit
.test( "attributes - equals", function( assert
) {
539 assert
.t( "Identifier", "#qunit-fixture a[rel=bookmark]", [ "simon1" ] );
540 assert
.t( "Identifier with underscore", "input[id=types_all]", [ "types_all" ] );
541 assert
.t( "String", "#qunit-fixture a[rel='bookmark']", [ "simon1" ] );
542 assert
.t( "String (whitespace ignored)", "#qunit-fixture a[ rel = 'bookmark' ]", [ "simon1" ] );
543 assert
.t( "Non-identifier string", "#qunit-fixture a[href='https://www.google.com/']", [ "google" ] );
544 assert
.t( "Empty string", "#select1 option[value='']", [ "option1a" ] );
546 if ( QUnit
.jQuerySelectors
) {
548 "#qunit-fixture option[value=1]",
549 [ "option1b", "option2b", "option3b", "option4b", "option5c" ] );
550 assert
.t( "negative number",
551 "#qunit-fixture li[tabIndex=-1]", [ "foodWithNegativeTabIndex" ] );
553 assert
.ok( "skip", "Number value not supported in selector-native" );
554 assert
.ok( "skip", "Negative number value not supported in selector-native" );
557 assert
.t( "Non-ASCII identifier", "span[lang=中文]", [ "台北" ] );
559 assert
.t( "input[type=text]", "#form input[type=text]", [ "text1", "text2", "hidden2", "name" ] );
560 assert
.t( "input[type=search]", "#form input[type=search]", [ "search" ] );
562 withScript
= supportjQuery( "<div><span><script src=''></script></span></div>" );
563 assert
.ok( withScript
.find( "#moretests script[src]" ).has( "script" ), "script[src] (jQuery trac-13777)" );
565 assert
.t( "Boolean attribute equals name", "#select2 option[selected='selected']", [ "option2d" ] );
566 assert
.t( "for Attribute in form", "#form [for=action]", [ "label-for" ] );
567 assert
.t( "Grouped Form Elements - name", "input[name='foo[bar]']", [ "hidden2" ] );
568 assert
.t( "Value", "input[value=Test]", [ "text1", "text2" ] );
571 jQuery( "input[data-comma='0,1']" ).get(),
573 "Without context, single-quoted attribute containing ','" );
575 jQuery( "input[data-comma=\"0,1\"]" ).get(),
577 "Without context, double-quoted attribute containing ','" );
579 jQuery( "input[data-comma='0,1']", document
.getElementById( "t12087" ) ).get(),
581 "With context, single-quoted attribute containing ','" );
583 jQuery( "input[data-comma=\"0,1\"]", document
.getElementById( "t12087" ) ).get(),
585 "With context, double-quoted attribute containing ','" );
588 QUnit
[ QUnit
.jQuerySelectors
? "test" : "skip" ]( "attributes - does not equal", function( assert
) {
591 assert
.t( "string", "#ap a[hreflang!='en']", [ "google", "groups", "anchor1" ] );
592 assert
.t( "Empty values", "#select1 option[value!='']", [ "option1b", "option1c", "option1d" ] );
595 QUnit
.test( "attributes - starts with", function( assert
) {
598 assert
.t( "string (whitespace ignored)", "a[href ^= 'https://www']", [ "google", "yahoo" ] );
599 assert
.t( "href starts with hash", "p a[href^='#']", [ "anchor2" ] );
600 assert
.t( "string containing '['", "input[name^='foo[']", [ "hidden2" ] );
601 assert
.t( "string containing '[' ... ']'", "input[name^='foo[bar]']", [ "hidden2" ] );
604 QUnit
.test( "attributes - contains", function( assert
) {
607 assert
.t( "string (whitespace ignored)", "a[href *= 'google']", [ "google", "groups" ] );
608 assert
.t( "string like '[' ... ']']", "input[name*='[bar]']", [ "hidden2" ] );
609 assert
.t( "string containing '['...']", "input[name*='foo[bar]']", [ "hidden2" ] );
610 assert
.t( "href contains hash", "p a[href*='#']", [ "simon1", "anchor2" ] );
613 QUnit
.test( "attributes - ends with", function( assert
) {
616 assert
.t( "string (whitespace ignored)", "a[href $= 'org/']", [ "mark" ] );
617 assert
.t( "string ending with ']'", "input[name$='bar]']", [ "hidden2" ] );
618 assert
.t( "string like '[' ... ']'", "input[name$='[bar]']", [ "hidden2" ] );
619 assert
.t( "Attribute containing []", "input[name$='foo[bar]']", [ "hidden2" ] );
622 QUnit
.test( "attributes - whitespace list includes", function( assert
) {
625 assert
.t( "string found at the beginning",
626 "input[data-15233~='foo']",
627 [ "t15233-single", "t15233-double", "t15233-double-tab", "t15233-double-nl", "t15233-triple" ] );
628 assert
.t( "string found in the middle",
629 "input[data-15233~='bar']",
630 [ "t15233-double", "t15233-double-tab", "t15233-double-nl", "t15233-triple" ] );
631 assert
.t( "string found at the end", "input[data-15233~='baz']", [ "t15233-triple" ] );
634 QUnit
.test( "attributes - hyphen-prefix matches", function( assert
) {
637 assert
.t( "string", "#names-group span[id|='name']", [ "name-is-example", "name-is-div" ] );
638 assert
.t( "string containing hyphen",
639 "#names-group span[id|='name-is']",
640 [ "name-is-example", "name-is-div" ] );
641 assert
.t( "string ending with hyphen", "#names-group span[id|='name-is-']", [] );
644 QUnit
.test( "attributes - special characters", function( assert
) {
648 var div
= document
.createElement( "div" );
651 div
.innerHTML
= "<div id='foo' xml:test='something'></div>";
652 assert
.deepEqual( jQuery( "[xml\\:test]", div
).get(),
654 "attribute name containing colon" );
656 // Make sure attribute value quoting works correctly.
657 // See jQuery trac-6093; trac-6428; trac-13894.
658 // Use seeded results to bypass querySelectorAll optimizations.
660 "<input type='hidden' id='attrbad_space' name='foo bar'/>" +
661 "<input type='hidden' id='attrbad_dot' value='2' name='foo.baz'/>" +
662 "<input type='hidden' id='attrbad_brackets' value='2' name='foo[baz]'/>" +
663 "<input type='hidden' id='attrbad_leading_digits' name='agent' value='007'/>" +
664 "<input type='hidden' id='attrbad_injection' data-attr='foo_baz']'/>" +
665 "<input type='hidden' id='attrbad_quote' data-attr='''/>" +
666 "<input type='hidden' id='attrbad_backslash' data-attr='\'/>" +
667 "<input type='hidden' id='attrbad_backslash_quote' data-attr='\''/>" +
668 "<input type='hidden' id='attrbad_backslash_backslash' data-attr='\\'/>" +
669 "<input type='hidden' id='attrbad_unicode' data-attr='一'/>"
670 ).appendTo( "#qunit-fixture" ).get();
673 assert
.deepEqual( jQuery( attrbad
).filter( "input[name=foo\\ bar]" ).get(),
674 q( "attrbad_space" ),
675 "identifier containing space" );
676 assert
.deepEqual( jQuery( attrbad
).filter( "input[name=foo\\.baz]" ).get(),
678 "identifier containing dot" );
679 assert
.deepEqual( jQuery( attrbad
).filter( "input[name=foo\\[baz\\]]" ).get(),
680 q( "attrbad_brackets" ),
681 "identifier containing brackets" );
682 assert
.deepEqual( jQuery( attrbad
).filter( "input[data-attr='foo_baz\\']']" ).get(),
683 q( "attrbad_injection" ),
684 "string containing quote and right bracket" );
686 assert
.deepEqual( jQuery( attrbad
).filter( "input[value=\\30 \\30\\37 ]" ).get(),
687 q( "attrbad_leading_digits" ),
688 "identifier containing escaped leading digits with whitespace termination" );
689 assert
.deepEqual( jQuery( attrbad
).filter( "input[value=\\00003007]" ).get(),
690 q( "attrbad_leading_digits" ),
691 "identifier containing escaped leading digits without whitespace termination" );
693 assert
.deepEqual( jQuery( attrbad
).filter( "input[data-attr='\\'']" ).get(),
694 q( "attrbad_quote" ),
695 "string containing quote" );
696 assert
.deepEqual( jQuery( attrbad
).filter( "input[data-attr='\\\\']" ).get(),
697 q( "attrbad_backslash" ),
698 "string containing backslash" );
699 assert
.deepEqual( jQuery( attrbad
).filter( "input[data-attr='\\\\\\'']" ).get(),
700 q( "attrbad_backslash_quote" ),
701 "string containing backslash and quote" );
702 assert
.deepEqual( jQuery( attrbad
).filter( "input[data-attr='\\\\\\\\']" ).get(),
703 q( "attrbad_backslash_backslash" ),
704 "string containing adjacent backslashes" );
706 assert
.deepEqual( jQuery( attrbad
).filter( "input[data-attr='\\5C\\\\']" ).get(),
707 q( "attrbad_backslash_backslash" ),
708 "string containing numeric-escape backslash and backslash" );
709 assert
.deepEqual( jQuery( attrbad
).filter( "input[data-attr='\\5C \\\\']" ).get(),
710 q( "attrbad_backslash_backslash" ),
711 "string containing numeric-escape-with-trailing-space backslash and backslash" );
712 assert
.deepEqual( jQuery( attrbad
).filter( "input[data-attr='\\5C\t\\\\']" ).get(),
713 q( "attrbad_backslash_backslash" ),
714 "string containing numeric-escape-with-trailing-tab backslash and backslash" );
715 assert
.deepEqual( jQuery( attrbad
).filter( "input[data-attr='\\04e00']" ).get(),
716 q( "attrbad_unicode" ),
717 "Long numeric escape (BMP)" );
719 document
.getElementById( "attrbad_unicode" ).setAttribute( "data-attr", "\uD834\uDF06A" );
720 assert
.deepEqual( jQuery( attrbad
).filter( "input[data-attr='\\01D306A']" ).get(),
721 q( "attrbad_unicode" ),
722 "Long numeric escape (non-BMP)" );
725 QUnit
.test( "attributes - others", function( assert
) {
728 var div
= document
.getElementById( "foo" );
730 assert
.t( "Find elements with a tabindex attribute", "[tabindex]", [ "listWithTabIndex", "foodWithNegativeTabIndex", "linkWithTabIndex", "linkWithNegativeTabIndex", "linkWithNoHrefWithTabIndex", "linkWithNoHrefWithNegativeTabIndex" ] );
732 assert
.t( "Selector list with multiple quoted attribute-equals",
733 "#form input[type='radio'], #form input[type='hidden']",
734 [ "radio1", "radio2", "hidden1" ] );
735 assert
.t( "Selector list with differently-quoted attribute-equals",
736 "#form input[type='radio'], #form input[type=\"hidden\"]",
737 [ "radio1", "radio2", "hidden1" ] );
738 assert
.t( "Selector list with quoted and unquoted attribute-equals",
739 "#form input[type='radio'], #form input[type=hidden]",
740 [ "radio1", "radio2", "hidden1" ] );
742 assert
.t( "Object.prototype property \"constructor\" (negative)", "[constructor]", [] );
743 assert
.t( "Gecko Object.prototype property \"watch\" (negative)", "[watch]", [] );
744 div
.setAttribute( "constructor", "foo" );
745 div
.setAttribute( "watch", "bar" );
746 assert
.t( "Object.prototype property \"constructor\"", "[constructor='foo']", [ "foo" ] );
747 assert
.t( "Gecko Object.prototype property \"watch\"", "[watch='bar']", [ "foo" ] );
750 assert
.ok( jQuery( "<input type='checkbox' checked='checked'/>" ).prop( "checked", false ).is( "[checked]" ),
751 "[checked] selects by attribute (positive)"
753 assert
.ok( !jQuery( "<input type='checkbox'/>" ).prop( "checked", true ).is( "[checked]" ),
754 "[checked] selects by attribute (negative)"
757 assert
.t( "empty name", "[name='']", [ "name-empty" ] );
758 assert
.t( "prefixed empty name", "#empty-name-parent [name='']", [ "name-empty" ] );
760 var emptyNameContainer
= jQuery( ".empty-name-container" );
761 assert
.deepEqual( emptyNameContainer
.find( "[name='']" ).get(),
763 "empty name with context" );
764 assert
.deepEqual( emptyNameContainer
.find( "#empty-name-parent [name='']" ).get(),
766 "prefixed empty name with context" );
769 QUnit
.test( "pseudo - (parent|empty)", function( assert
) {
771 assert
.t( "Empty", "#qunit-fixture ul:empty", [ "firstUL" ] );
772 assert
.t( "Empty with comment node", "#qunit-fixture ol:empty", [ "empty" ] );
774 if ( QUnit
.jQuerySelectors
) {
775 assert
.t( "Is A Parent", "#qunit-fixture p:parent",
776 [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
778 assert
.ok( "skip", ":parent not supported in selector-native" );
782 QUnit
.test( "pseudo - (first|last|only)-(child|of-type)", function( assert
) {
785 assert
.t( "First Child", "#qunit-fixture p:first-child", [ "firstp", "sndp" ] );
786 assert
.t( "First Child (leading id)", "#qunit-fixture p:first-child", [ "firstp", "sndp" ] );
787 assert
.t( "First Child (leading class)", ".nothiddendiv div:first-child", [ "nothiddendivchild" ] );
788 assert
.t( "First Child (case-insensitive)", "#qunit-fixture p:FIRST-CHILD", [ "firstp", "sndp" ] );
790 assert
.t( "Last Child", "#qunit-fixture p:last-child", [ "sap" ] );
791 assert
.t( "Last Child (leading id)", "#qunit-fixture a:last-child", [ "simon1", "anchor1", "mark", "yahoo", "anchor2", "simon", "liveLink1", "liveLink2" ] );
793 assert
.t( "Only Child", "#qunit-fixture a:only-child", [ "simon1", "anchor1", "yahoo", "anchor2", "liveLink1", "liveLink2" ] );
795 assert
.t( "First-of-type", "#qunit-fixture > p:first-of-type", [ "firstp" ] );
796 assert
.t( "Last-of-type", "#qunit-fixture > p:last-of-type", [ "first" ] );
797 assert
.t( "Only-of-type", "#qunit-fixture > :only-of-type", [ "name+value", "firstUL", "empty", "floatTest", "iframe", "table", "last" ] );
799 // Verify that the child position isn't being cached improperly
800 var secondChildren
= jQuery( "p:nth-child(2)" ).before( "<div></div>" );
802 assert
.t( "No longer second child", "p:nth-child(2)", [] );
803 secondChildren
.prev().remove();
804 assert
.t( "Restored second child", "p:nth-child(2)", [ "ap", "en" ] );
807 QUnit
.test( "pseudo - nth-child", function( assert
) {
810 assert
.t( "Nth-child", "p:nth-child(1)", [ "firstp", "sndp" ] );
811 assert
.t( "Nth-child (with whitespace)", "p:nth-child( 1 )", [ "firstp", "sndp" ] );
812 assert
.t( "Nth-child (case-insensitive)", "#form #select1 option:NTH-child(3)", [ "option1c" ] );
813 assert
.t( "Not nth-child", "#qunit-fixture p:not(:nth-child(1))", [ "ap", "en", "sap", "first" ] );
815 assert
.t( "Nth-child(2)", "#qunit-fixture form#form > *:nth-child(2)", [ "text1" ] );
816 assert
.t( "Nth-child(2)", "#qunit-fixture form#form > :nth-child(2)", [ "text1" ] );
818 assert
.t( "Nth-child(-1)", "#form #select1 option:nth-child(-1)", [] );
819 assert
.t( "Nth-child(3)", "#form #select1 option:nth-child(3)", [ "option1c" ] );
820 assert
.t( "Nth-child(0n+3)", "#form #select1 option:nth-child(0n+3)", [ "option1c" ] );
821 assert
.t( "Nth-child(1n+0)", "#form #select1 option:nth-child(1n+0)", [ "option1a", "option1b", "option1c", "option1d" ] );
822 assert
.t( "Nth-child(1n)", "#form #select1 option:nth-child(1n)", [ "option1a", "option1b", "option1c", "option1d" ] );
823 assert
.t( "Nth-child(n)", "#form #select1 option:nth-child(n)", [ "option1a", "option1b", "option1c", "option1d" ] );
824 assert
.t( "Nth-child(even)", "#form #select1 option:nth-child(even)", [ "option1b", "option1d" ] );
825 assert
.t( "Nth-child(odd)", "#form #select1 option:nth-child(odd)", [ "option1a", "option1c" ] );
826 assert
.t( "Nth-child(2n)", "#form #select1 option:nth-child(2n)", [ "option1b", "option1d" ] );
827 assert
.t( "Nth-child(2n+1)", "#form #select1 option:nth-child(2n+1)", [ "option1a", "option1c" ] );
828 assert
.t( "Nth-child(2n + 1)", "#form #select1 option:nth-child(2n + 1)", [ "option1a", "option1c" ] );
829 assert
.t( "Nth-child(+2n + 1)", "#form #select1 option:nth-child(+2n + 1)", [ "option1a", "option1c" ] );
830 assert
.t( "Nth-child(3n)", "#form #select1 option:nth-child(3n)", [ "option1c" ] );
831 assert
.t( "Nth-child(3n+1)", "#form #select1 option:nth-child(3n+1)", [ "option1a", "option1d" ] );
832 assert
.t( "Nth-child(3n+2)", "#form #select1 option:nth-child(3n+2)", [ "option1b" ] );
833 assert
.t( "Nth-child(3n+3)", "#form #select1 option:nth-child(3n+3)", [ "option1c" ] );
834 assert
.t( "Nth-child(3n-1)", "#form #select1 option:nth-child(3n-1)", [ "option1b" ] );
835 assert
.t( "Nth-child(3n-2)", "#form #select1 option:nth-child(3n-2)", [ "option1a", "option1d" ] );
836 assert
.t( "Nth-child(3n-3)", "#form #select1 option:nth-child(3n-3)", [ "option1c" ] );
837 assert
.t( "Nth-child(3n+0)", "#form #select1 option:nth-child(3n+0)", [ "option1c" ] );
838 assert
.t( "Nth-child(-1n+3)", "#form #select1 option:nth-child(-1n+3)", [ "option1a", "option1b", "option1c" ] );
839 assert
.t( "Nth-child(-n+3)", "#form #select1 option:nth-child(-n+3)", [ "option1a", "option1b", "option1c" ] );
840 assert
.t( "Nth-child(-1n + 3)", "#form #select1 option:nth-child(-1n + 3)", [ "option1a", "option1b", "option1c" ] );
842 if ( QUnit
.jQuerySelectors
|| this.safari
) {
844 jQuery( [ document
.createElement( "a" ) ].concat( q( "ap" ) ) )
845 .filter( ":nth-child(n)" )
851 // Support: Chrome 75+, Firefox 67+
852 // Some browsers mark disconnected elements as matching `:nth-child(n)`
853 // so let's skip the test.
854 assert
.ok( "skip", "disconnected elements match ':nth-child(n)' in Chrome/Firefox" );
858 QUnit
.test( "pseudo - nth-last-child", function( assert
) {
861 jQuery( "#qunit-fixture" ).append( "<form id='nth-last-child-form'></form><i></i><i></i><i></i><i></i>" );
862 assert
.t( "Nth-last-child", "form:nth-last-child(5)", [ "nth-last-child-form" ] );
863 assert
.t( "Nth-last-child (with whitespace)", "form:nth-last-child( 5 )", [ "nth-last-child-form" ] );
866 assert
.t( "Nth-last-child (case-insensitive)", "#form #select1 option:NTH-last-child(3)", [ "option1b" ] );
867 assert
.t( "Not nth-last-child", "#qunit-fixture p:not(:nth-last-child(1))", [ "firstp", "ap", "sndp", "en", "first" ] );
869 assert
.t( "Nth-last-child(-1)", "#form #select1 option:nth-last-child(-1)", [] );
870 assert
.t( "Nth-last-child(3)", "#form #select1 :nth-last-child(3)", [ "option1b" ] );
871 assert
.t( "Nth-last-child(3)", "#form #select1 *:nth-last-child(3)", [ "option1b" ] );
872 assert
.t( "Nth-last-child(3)", "#form #select1 option:nth-last-child(3)", [ "option1b" ] );
873 assert
.t( "Nth-last-child(0n+3)", "#form #select1 option:nth-last-child(0n+3)", [ "option1b" ] );
874 assert
.t( "Nth-last-child(1n+0)", "#form #select1 option:nth-last-child(1n+0)", [ "option1a", "option1b", "option1c", "option1d" ] );
875 assert
.t( "Nth-last-child(1n)", "#form #select1 option:nth-last-child(1n)", [ "option1a", "option1b", "option1c", "option1d" ] );
876 assert
.t( "Nth-last-child(n)", "#form #select1 option:nth-last-child(n)", [ "option1a", "option1b", "option1c", "option1d" ] );
877 assert
.t( "Nth-last-child(even)", "#form #select1 option:nth-last-child(even)", [ "option1a", "option1c" ] );
878 assert
.t( "Nth-last-child(odd)", "#form #select1 option:nth-last-child(odd)", [ "option1b", "option1d" ] );
879 assert
.t( "Nth-last-child(2n)", "#form #select1 option:nth-last-child(2n)", [ "option1a", "option1c" ] );
880 assert
.t( "Nth-last-child(2n+1)", "#form #select1 option:nth-last-child(2n+1)", [ "option1b", "option1d" ] );
881 assert
.t( "Nth-last-child(2n + 1)", "#form #select1 option:nth-last-child(2n + 1)", [ "option1b", "option1d" ] );
882 assert
.t( "Nth-last-child(+2n + 1)", "#form #select1 option:nth-last-child(+2n + 1)", [ "option1b", "option1d" ] );
883 assert
.t( "Nth-last-child(3n)", "#form #select1 option:nth-last-child(3n)", [ "option1b" ] );
884 assert
.t( "Nth-last-child(3n+1)", "#form #select1 option:nth-last-child(3n+1)", [ "option1a", "option1d" ] );
885 assert
.t( "Nth-last-child(3n+2)", "#form #select1 option:nth-last-child(3n+2)", [ "option1c" ] );
886 assert
.t( "Nth-last-child(3n+3)", "#form #select1 option:nth-last-child(3n+3)", [ "option1b" ] );
887 assert
.t( "Nth-last-child(3n-1)", "#form #select1 option:nth-last-child(3n-1)", [ "option1c" ] );
888 assert
.t( "Nth-last-child(3n-2)", "#form #select1 option:nth-last-child(3n-2)", [ "option1a", "option1d" ] );
889 assert
.t( "Nth-last-child(3n-3)", "#form #select1 option:nth-last-child(3n-3)", [ "option1b" ] );
890 assert
.t( "Nth-last-child(3n+0)", "#form #select1 option:nth-last-child(3n+0)", [ "option1b" ] );
891 assert
.t( "Nth-last-child(-1n+3)", "#form #select1 option:nth-last-child(-1n+3)", [ "option1b", "option1c", "option1d" ] );
892 assert
.t( "Nth-last-child(-n+3)", "#form #select1 option:nth-last-child(-n+3)", [ "option1b", "option1c", "option1d" ] );
893 assert
.t( "Nth-last-child(-1n + 3)", "#form #select1 option:nth-last-child(-1n + 3)", [ "option1b", "option1c", "option1d" ] );
895 if ( QUnit
.jQuerySelectors
|| this.safari
) {
897 jQuery( [ document
.createElement( "a" ) ].concat( q( "ap" ) ) )
898 .filter( ":nth-last-child(n)" )
901 "Seeded nth-last-child"
904 // Support: Chrome 75+, Firefox 67+
905 // Some browsers mark disconnected elements as matching `:nth-last-child(n)`
906 // so let's skip the test.
907 assert
.ok( "skip", "disconnected elements match ':nth-last-child(n)' in Chrome/Firefox" );
911 QUnit
.test( "pseudo - nth-of-type", function( assert
) {
913 assert
.t( "Nth-of-type(-1)", ":nth-of-type(-1)", [] );
914 assert
.t( "Nth-of-type(3)", "#ap :nth-of-type(3)", [ "mark" ] );
915 assert
.t( "Nth-of-type(n)", "#ap :nth-of-type(n)", [ "google", "groups", "code1", "anchor1", "mark" ] );
916 assert
.t( "Nth-of-type(0n+3)", "#ap :nth-of-type(0n+3)", [ "mark" ] );
917 assert
.t( "Nth-of-type(2n)", "#ap :nth-of-type(2n)", [ "groups" ] );
918 assert
.t( "Nth-of-type(even)", "#ap :nth-of-type(even)", [ "groups" ] );
919 assert
.t( "Nth-of-type(2n+1)", "#ap :nth-of-type(2n+1)", [ "google", "code1", "anchor1", "mark" ] );
920 assert
.t( "Nth-of-type(odd)", "#ap :nth-of-type(odd)", [ "google", "code1", "anchor1", "mark" ] );
921 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" ] );
924 QUnit
.test( "pseudo - nth-last-of-type", function( assert
) {
926 assert
.t( "Nth-last-of-type(-1)", ":nth-last-of-type(-1)", [] );
927 assert
.t( "Nth-last-of-type(3)", "#ap :nth-last-of-type(3)", [ "google" ] );
928 assert
.t( "Nth-last-of-type(n)", "#ap :nth-last-of-type(n)", [ "google", "groups", "code1", "anchor1", "mark" ] );
929 assert
.t( "Nth-last-of-type(0n+3)", "#ap :nth-last-of-type(0n+3)", [ "google" ] );
930 assert
.t( "Nth-last-of-type(2n)", "#ap :nth-last-of-type(2n)", [ "groups" ] );
931 assert
.t( "Nth-last-of-type(even)", "#ap :nth-last-of-type(even)", [ "groups" ] );
932 assert
.t( "Nth-last-of-type(2n+1)", "#ap :nth-last-of-type(2n+1)", [ "google", "code1", "anchor1", "mark" ] );
933 assert
.t( "Nth-last-of-type(odd)", "#ap :nth-last-of-type(odd)", [ "google", "code1", "anchor1", "mark" ] );
934 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" ] );
937 QUnit
[ QUnit
.jQuerySelectors
? "test" : "skip" ]( "pseudo - has", function( assert
) {
940 assert
.t( "Basic test", "p:has(a)", [ "firstp", "ap", "en", "sap" ] );
941 assert
.t( "Basic test (irrelevant whitespace)", "p:has( a )", [ "firstp", "ap", "en", "sap" ] );
942 assert
.t( "Nested with overlapping candidates",
943 "#qunit-fixture div:has(div:has(div:not([id])))",
944 [ "moretests", "t2037", "fx-test-group", "fx-queue" ] );
946 // Support: Safari 15.4+, Chrome 105+
947 // `qSA` in Safari/Chrome throws for `:has()` with only unsupported arguments
948 // but if you add a supported arg to the list, it will run and just potentially
949 // return no results. Make sure this is accounted for. (gh-5098)
950 // Note: Chrome 105 has this behavior only in 105.0.5195.125 or newer;
951 // initially it shipped with a fully forgiving parsing in `:has()`.
952 assert
.t( "Nested with list arguments",
953 "#qunit-fixture div:has(faketag, div:has(faketag, div:not([id])))",
954 [ "moretests", "t2037", "fx-test-group", "fx-queue" ] );
957 QUnit
[ QUnit
.jQuerySelectors
? "test" : "skip" ]( "pseudo - contains", function( assert
) {
960 var gh335
= document
.getElementById( "qunit-fixture" ).appendChild(
961 document
.createElement( "mark" ) );
963 gh335
.appendChild( document
.createTextNode( "raw line 1\nline 2" ) );
965 assert
.ok( jQuery( "a:contains('')" ).length
, "empty string" );
966 assert
.t( "unquoted argument", "a:contains(Google)", [ "google", "groups" ] );
967 assert
.t( "unquoted argument with whitespace", "a:contains(Google Groups)", [ "groups" ] );
968 assert
.t( "quoted argument with whitespace and parentheses",
969 "a:contains('Google Groups (Link)')", [ "groups" ] );
970 assert
.t( "quoted argument with double quotes and parentheses",
971 "a:contains(\"(Link)\")", [ "groups" ] );
972 assert
.t( "unquoted argument with whitespace and paired parentheses",
973 "a:contains(Google Groups (Link))", [ "groups" ] );
974 assert
.t( "unquoted argument with paired parentheses", "a:contains((Link))", [ "groups" ] );
975 assert
.t( "quoted argument with CSS escapes",
976 "span:contains(\"\\\"'\\53F0 \\5317 Ta\\301 ibe\\30C i\")",
979 assert
.t( "collapsed whitespace", "mark:contains('line 1\\A line')", [ "gh-335" ] );
982 QUnit
.test( "pseudo - misc", function( assert
) {
985 var select
, tmp
, input
;
987 jQuery( "<h1 id='h1'></h1><h2 id='h2'></h2><h2 id='h2-2'></h2>" ).prependTo( "#qunit-fixture" );
989 if ( QUnit
.jQuerySelectors
) {
990 assert
.t( "Headers", "#qunit-fixture :header", [ "h1", "h2", "h2-2" ] );
991 assert
.t( "Headers(case-insensitive)", "#qunit-fixture :Header", [ "h1", "h2", "h2-2" ] );
993 assert
.ok( "skip", ":header not supported in selector-native" );
994 assert
.ok( "skip", ":header not supported in selector-native" );
997 if ( QUnit
.jQuerySelectors
) {
998 assert
.t( "Multiple matches with the same context (cache check)",
999 "#form select:has(option:first-child:contains('o'))",
1000 [ "select1", "select2", "select3", "select4" ]
1002 assert
.ok( jQuery( "#qunit-fixture :not(:has(:has(*)))" ).length
, "All not grandparents" );
1004 select
= document
.getElementById( "select1" );
1005 assert
.ok( jQuery( select
).is( ":has(option)" ), "Has Option Matches" );
1007 assert
.ok( "skip", ":has not supported in selector-native" );
1008 assert
.ok( "skip", ":has not supported in selector-native" );
1009 assert
.ok( "skip", ":has not supported in selector-native" );
1012 tmp
= document
.createElement( "div" );
1013 tmp
.id
= "tmp_input";
1014 document
.body
.appendChild( tmp
);
1016 jQuery
.each( [ "button", "submit", "reset" ], function( i
, type
) {
1018 "<input id='input_%' type='%'/><button id='button_%' type='%'>test</button>"
1019 .replace( /%/g
, type
)
1022 if ( QUnit
.jQuerySelectors
) {
1023 assert
.t( "Input Buttons :" + type
, "#tmp_input :" + type
, [ "input_" + type
, "button_" + type
] );
1025 assert
.ok( jQuery( els
[ 0 ] ).is( ":" + type
), "Input Matches :" + type
);
1026 assert
.ok( jQuery( els
[ 1 ] ).is( ":" + type
), "Button Matches :" + type
);
1028 assert
.ok( "skip", ":" + type
+ " not supported in selector-native" );
1029 assert
.ok( "skip", ":" + type
+ " not supported in selector-native" );
1030 assert
.ok( "skip", ":" + type
+ " not supported in selector-native" );
1034 document
.body
.removeChild( tmp
);
1037 tmp
= document
.createElement( "div" );
1038 tmp
.id
= "tmp_input";
1039 tmp
.innerHTML
= "<span>Hello I am focusable.</span>";
1040 // Setting tabIndex should make the element focusable
1041 // https://html.spec.whatwg.org/#the-tabindex-attribute
1042 document
.body
.appendChild( tmp
);
1045 if ( document
.activeElement
!== tmp
|| ( document
.hasFocus
&& !document
.hasFocus() ) ||
1046 ( document
.querySelectorAll
&& !document
.querySelectorAll( "div:focus" ).length
) ) {
1047 assert
.ok( true, "The div was not focused. Skip checking the :focus match." );
1048 assert
.ok( true, "The div was not focused. Skip checking the :focus match." );
1050 assert
.t( "tabIndex element focused", ":focus", [ "tmp_input" ] );
1051 assert
.ok( jQuery( tmp
).is( ":focus" ), ":focus matches tabIndex div" );
1056 document
.body
.focus();
1057 assert
.ok( !jQuery( tmp
).is( ":focus" ), ":focus doesn't match tabIndex div" );
1058 document
.body
.removeChild( tmp
);
1060 // Input focus/active
1061 input
= document
.createElement( "input" );
1062 input
.type
= "text";
1063 input
.id
= "focus-input";
1065 document
.body
.appendChild( input
);
1068 // Inputs can't be focused unless the document has focus
1069 if ( document
.activeElement
!== input
|| ( document
.hasFocus
&& !document
.hasFocus() ) ||
1070 ( document
.querySelectorAll
&& !document
.querySelectorAll( "input:focus" ).length
) ) {
1071 assert
.ok( true, "The input was not focused. Skip checking the :focus match." );
1072 assert
.ok( true, "The input was not focused. Skip checking the :focus match." );
1074 assert
.t( "Element focused", "input:focus", [ "focus-input" ] );
1075 assert
.ok( jQuery( input
).is( ":focus" ), ":focus matches" );
1080 // When IE is out of focus, blur does not work. Force it here.
1081 if ( document
.activeElement
=== input
) {
1082 document
.body
.focus();
1085 assert
.ok( !jQuery( input
).is( ":focus" ), ":focus doesn't match" );
1086 document
.body
.removeChild( input
);
1090 jQuery( "[id='select1'] *:not(:last-child), [id='select2'] *:not(:last-child)", q( "qunit-fixture" )[ 0 ] ).get(),
1091 q( "option1a", "option1b", "option1c", "option2a", "option2b", "option2c" ),
1092 "caching system tolerates recursive selection"
1095 if ( QUnit
.jQuerySelectors
) {
1096 // Tokenization edge cases
1097 assert
.t( "Sequential pseudos", "#qunit-fixture p:has(:contains(mark)):has(code)", [ "ap" ] );
1098 assert
.t( "Sequential pseudos", "#qunit-fixture p:has(:contains(mark)):has(code):contains(This link)", [ "ap" ] );
1100 assert
.t( "Pseudo argument containing ')'", "p:has(>a.GROUPS[src!=')'])", [ "ap" ] );
1101 assert
.t( "Pseudo argument containing ')'", "p:has(>a.GROUPS[src!=')'])", [ "ap" ] );
1102 assert
.t( "Pseudo followed by token containing ')'", "p:contains(id=\"foo\")[id!=\\)]", [ "sndp" ] );
1103 assert
.t( "Pseudo followed by token containing ')'", "p:contains(id=\"foo\")[id!=')']", [ "sndp" ] );
1105 assert
.t( "Multi-pseudo", "#ap:has(*), #ap:has(*)", [ "ap" ] );
1106 assert
.t( "Multi-pseudo with leading nonexistent id", "#nonexistent:has(*), #ap:has(*)", [ "ap" ] );
1108 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" ] );
1110 assert
.ok( "skip", ":has not supported in selector-native" );
1111 assert
.ok( "skip", ":has not supported in selector-native" );
1113 assert
.ok( "skip", ":has not supported in selector-native" );
1114 assert
.ok( "skip", ":has not supported in selector-native" );
1115 assert
.ok( "skip", ":contains not supported in selector-native" );
1116 assert
.ok( "skip", ":contains not supported in selector-native" );
1118 assert
.ok( "skip", ":has not supported in selector-native" );
1119 assert
.ok( "skip", ":has supported in selector-native" );
1121 assert
.ok( "skip", ":has not supported in selector-native" );
1124 if ( QUnit
.jQuerySelectorsPos
) {
1125 assert
.t( "Multi-positional", "#ap:gt(0), #ap:lt(1)", [ "ap" ] );
1126 assert
.t( "Multi-positional with leading nonexistent id", "#nonexistent:gt(0), #ap:lt(1)", [ "ap" ] );
1128 assert
.ok( "skip", "Positional selectors are not supported" );
1129 assert
.ok( "skip", "Positional selectors are not supported" );
1133 QUnit
.test( "pseudo - :not", function( assert
) {
1134 assert
.expect( 43 );
1136 assert
.t( "Not", "a.blog:not(.link)", [ "mark" ] );
1138 if ( QUnit
.jQuerySelectors
) {
1139 assert
.t( "Not - multiple", "#form option:not(:contains(Nothing),#option1b,:selected)", [ "option1c", "option1d", "option2b", "option2c", "option3d", "option3e", "option4e", "option5b", "option5c" ] );
1140 assert
.t( "Not - recursive", "#form option:not(:not(:selected))[id^='option3']", [ "option3b", "option3c" ] );
1142 assert
.ok( "skip", ":contains not supported in selector-native" );
1143 assert
.ok( "skip", ":selected not supported in selector-native" );
1146 if ( QUnit
.jQuerySelectorsPos
) {
1147 assert
.t( ":not() with :first", "#foo p:not(:first) .link", [ "simon" ] );
1149 assert
.ok( "skip", "Positional selectors are not supported" );
1152 assert
.t( ":not() failing interior", "#qunit-fixture p:not(.foo)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1153 assert
.t( ":not() failing interior", "#qunit-fixture p:not(#blargh)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1155 if ( QUnit
.jQuerySelectors
|| !QUnit
.isIE
) {
1156 assert
.t( ":not() failing interior", "#qunit-fixture p:not(div.foo)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1157 assert
.t( ":not() failing interior", "#qunit-fixture p:not(p.foo)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1158 assert
.t( ":not() failing interior", "#qunit-fixture p:not(div#blargh)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1159 assert
.t( ":not() failing interior", "#qunit-fixture p:not(p#blargh)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1162 // IE doesn't support `:not(complex selector)`.
1163 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
1164 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
1165 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
1166 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
1169 assert
.t( ":not Multiple", "#qunit-fixture p:not(a)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1170 assert
.t( ":not Multiple", "#qunit-fixture p:not( a )", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1171 assert
.t( ":not Multiple", "#qunit-fixture p:not( p )", [] );
1172 assert
.t( ":not Multiple", "p:not(p)", [] );
1174 if ( QUnit
.jQuerySelectors
|| !QUnit
.isIE
) {
1175 assert
.t( ":not Multiple", "#qunit-fixture p:not(a, b)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1176 assert
.t( ":not Multiple", "#qunit-fixture p:not(a, b, div)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1177 assert
.t( ":not Multiple", "p:not(a,p)", [] );
1178 assert
.t( ":not Multiple", "p:not(p,a)", [] );
1179 assert
.t( ":not Multiple", "p:not(a,p,b)", [] );
1182 // IE doesn't support `:not(complex selector)`.
1183 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
1184 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
1185 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
1186 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
1187 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
1190 if ( QUnit
.jQuerySelectors
) {
1191 assert
.t( ":not Multiple", ":input:not(:image,:input,:submit)", [] );
1192 assert
.t( ":not Multiple", "#qunit-fixture p:not(:has(a), :nth-child(1))", [ "first" ] );
1194 assert
.ok( "skip", ":image, :input, :submit not supported in selector-native" );
1195 assert
.ok( "skip", ":has not supported in selector-native" );
1198 assert
.t( "No element not selector", ".container div:not(.excluded) div", [] );
1200 assert
.t( ":not() Existing attribute", "#form select:not([multiple])", [ "select1", "select2", "select5" ] );
1201 assert
.t( ":not() Equals attribute", "#form select:not([name=select1])", [ "select2", "select3", "select4", "select5" ] );
1202 assert
.t( ":not() Equals quoted attribute", "#form select:not([name='select1'])", [ "select2", "select3", "select4", "select5" ] );
1204 assert
.t( ":not() Multiple Class", "#foo a:not(.blog)", [ "yahoo", "anchor2" ] );
1205 assert
.t( ":not() Multiple Class", "#foo a:not(.link)", [ "yahoo", "anchor2" ] );
1207 if ( QUnit
.jQuerySelectors
|| !QUnit
.isIE
) {
1208 assert
.t( ":not() Multiple Class", "#foo a:not(.blog.link)", [ "yahoo", "anchor2" ] );
1211 // IE doesn't support `:not(complex selector)`.
1212 assert
.ok( "skip", ":not(complex selector) not supported in selector-native" );
1215 if ( QUnit
.jQuerySelectors
) {
1216 assert
.t( ":not chaining (compound)", "#qunit-fixture div[id]:not(:has(div, span)):not(:has(*))", [ "nothiddendivchild", "divWithNoTabIndex", "fx-tests" ] );
1217 assert
.t( ":not chaining (with attribute)", "#qunit-fixture form[id]:not([action$='formaction']):not(:button)", [ "lengthtest", "name-tests", "testForm", "disabled-tests" ] );
1218 assert
.t( ":not chaining (colon in attribute)", "#qunit-fixture form[id]:not([action='form:action']):not(:button)", [ "form", "lengthtest", "name-tests", "testForm", "disabled-tests" ] );
1219 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" ] );
1220 assert
.t( ":not chaining", "#form select:not(.select1):contains(Nothing) > option:not(option)", [] );
1222 assert
.ok( "skip", ":has not supported in selector-native" );
1223 assert
.ok( "skip", ":button not supported in selector-native" );
1224 assert
.ok( "skip", ":button not supported in selector-native" );
1225 assert
.ok( "skip", ":button not supported in selector-native" );
1226 assert
.ok( "skip", ":contains not supported in selector-native" );
1229 if ( QUnit
.jQuerySelectorsPos
) {
1230 assert
.t( "positional :not()", "#foo p:not(:last)", [ "sndp", "en" ] );
1231 assert
.t( "positional :not() prefix", "#foo p:not(:last) a", [ "yahoo" ] );
1232 assert
.t( "compound positional :not()", "#foo p:not(:first, :last)", [ "en" ] );
1233 assert
.t( "compound positional :not()", "#foo p:not(:first, :even)", [ "en" ] );
1234 assert
.t( "compound positional :not()", "#foo p:not(:first, :odd)", [ "sap" ] );
1235 assert
.t( "reordered compound positional :not()", "#foo p:not(:odd, :first)", [ "sap" ] );
1237 assert
.t( "positional :not() with pre-filter", "#foo p:not([id]:first)", [ "en", "sap" ] );
1238 assert
.t( "positional :not() with post-filter", "#foo p:not(:first[id])", [ "en", "sap" ] );
1239 assert
.t( "positional :not() with pre-filter", "#foo p:not([lang]:first)", [ "sndp", "sap" ] );
1240 assert
.t( "positional :not() with post-filter", "#foo p:not(:first[lang])", [ "sndp", "en", "sap" ] );
1242 assert
.ok( "skip", "Positional selectors are not supported" );
1243 assert
.ok( "skip", "Positional selectors are not supported" );
1244 assert
.ok( "skip", "Positional selectors are not supported" );
1245 assert
.ok( "skip", "Positional selectors are not supported" );
1246 assert
.ok( "skip", "Positional selectors are not supported" );
1247 assert
.ok( "skip", "Positional selectors are not supported" );
1249 assert
.ok( "skip", "Positional selectors are not supported" );
1250 assert
.ok( "skip", "Positional selectors are not supported" );
1251 assert
.ok( "skip", "Positional selectors are not supported" );
1252 assert
.ok( "skip", "Positional selectors are not supported" );
1256 QUnit
[ QUnit
.jQuerySelectorsPos
? "test" : "skip" ]( "pseudo - position", function( assert
) {
1257 assert
.expect( 34 );
1259 assert
.t( "First element", "#qunit-fixture p:first", [ "firstp" ] );
1260 assert
.t( "First element(case-insensitive)", "#qunit-fixture p:fiRst", [ "firstp" ] );
1261 assert
.t( "nth Element", "#qunit-fixture p:nth(1)", [ "ap" ] );
1262 assert
.t( "First Element", "#qunit-fixture p:first", [ "firstp" ] );
1263 assert
.t( "Last Element", "p:last", [ "first" ] );
1264 assert
.t( "Even Elements", "#qunit-fixture p:even", [ "firstp", "sndp", "sap" ] );
1265 assert
.t( "Odd Elements", "#qunit-fixture p:odd", [ "ap", "en", "first" ] );
1266 assert
.t( "Position Equals", "#qunit-fixture p:eq(1)", [ "ap" ] );
1267 assert
.t( "Position Equals (negative)", "#qunit-fixture p:eq(-1)", [ "first" ] );
1268 assert
.t( "Position Greater Than", "#qunit-fixture p:gt(0)", [ "ap", "sndp", "en", "sap", "first" ] );
1269 assert
.t( "Position Less Than", "#qunit-fixture p:lt(3)", [ "firstp", "ap", "sndp" ] );
1270 assert
.t( "Position Less Than Big Number", "#qunit-fixture p:lt(9007199254740991)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
1272 assert
.t( "Check position filtering", "div#nothiddendiv:eq(0)", [ "nothiddendiv" ] );
1273 assert
.t( "Check position filtering", "div#nothiddendiv:last", [ "nothiddendiv" ] );
1274 assert
.t( "Check position filtering", "div#nothiddendiv:not(:gt(0))", [ "nothiddendiv" ] );
1275 assert
.t( "Check position filtering", "#foo > :not(:first)", [ "en", "sap" ] );
1276 assert
.t( "Check position filtering", "#qunit-fixture select > :not(:gt(2))", [ "option1a", "option1b", "option1c" ] );
1277 assert
.t( "Check position filtering", "#qunit-fixture select:lt(2) :not(:first)", [ "option1b", "option1c", "option1d", "option2a", "option2b", "option2c", "option2d" ] );
1278 assert
.t( "Check position filtering", "div.nothiddendiv:eq(0)", [ "nothiddendiv" ] );
1279 assert
.t( "Check position filtering", "div.nothiddendiv:last", [ "nothiddendiv" ] );
1280 assert
.t( "Check position filtering", "div.nothiddendiv:not(:lt(0))", [ "nothiddendiv" ] );
1282 assert
.t( "Check element position", "#qunit-fixture div div:eq(0)", [ "nothiddendivchild" ] );
1283 assert
.t( "Check element position", "#select1 option:eq(3)", [ "option1d" ] );
1284 assert
.t( "Check element position", "#qunit-fixture div div:eq(10)", [ "no-clone-exception" ] );
1285 assert
.t( "Check element position", "#qunit-fixture div div:first", [ "nothiddendivchild" ] );
1286 assert
.t( "Check element position", "#qunit-fixture div > div:first", [ "nothiddendivchild" ] );
1287 assert
.t( "Check element position", "#qunit-fixture div:first a:first", [ "yahoo" ] );
1288 assert
.t( "Check element position", "#qunit-fixture div:first > p:first", [ "sndp" ] );
1289 assert
.t( "Check element position", "div#nothiddendiv:first > div:first", [ "nothiddendivchild" ] );
1290 assert
.t( "Chained pseudo after a pos pseudo", "#listWithTabIndex li:eq(0):contains(Rice)", [ "foodWithNegativeTabIndex" ] );
1292 assert
.t( "Check sort order with POS and comma", "#qunit-fixture em>em>em>em:first-child,div>em:first", [ "siblingfirst", "siblinggreatgrandchild" ] );
1294 assert
.t( "Isolated position", "#qunit-fixture :last", [ "last" ] );
1297 jQuery( "#qunit-fixture > p" ).filter( "*:lt(2) + *" ).get(),
1299 "Seeded pos with trailing relative" );
1301 // jQuery trac-12526
1302 var context
= jQuery( "#qunit-fixture" ).append( "<div id='jquery12526'></div>" )[ 0 ];
1303 assert
.deepEqual( jQuery( ":last", context
).get(), q( "jquery12526" ),
1304 "Post-manipulation positional" );
1307 QUnit
.test( "pseudo - form", function( assert
) {
1308 assert
.expect( 16 );
1310 var extraTexts
= jQuery( "<input id=\"impliedText\"/><input id=\"capitalText\" type=\"TEXT\">" ).appendTo( "#form" );
1312 if ( QUnit
.jQuerySelectors
) {
1313 assert
.t( "Form element :radio", "#form :radio", [ "radio1", "radio2" ] );
1314 assert
.t( "Form element :checkbox", "#form :checkbox", [ "check1", "check2" ] );
1315 assert
.t( "Form element :text", "#form :text", [ "text1", "text2", "hidden2", "name", "impliedText", "capitalText" ] );
1316 assert
.t( "Form element :radio:checked", "#form :radio:checked", [ "radio2" ] );
1317 assert
.t( "Form element :checkbox:checked", "#form :checkbox:checked", [ "check1" ] );
1318 assert
.t( "Form element :radio:checked, :checkbox:checked", "#form :radio:checked, #form :checkbox:checked", [ "radio2", "check1" ] );
1320 assert
.ok( "skip", ":radio not supported in selector-native" );
1321 assert
.ok( "skip", ":checkbox not supported in selector-native" );
1322 assert
.ok( "skip", ":text not supported in selector-native" );
1323 assert
.ok( "skip", ":radio not supported in selector-native" );
1324 assert
.ok( "skip", ":checkbox not supported in selector-native" );
1325 assert
.ok( "skip", ":radio not supported in selector-native" );
1328 if ( QUnit
.jQuerySelectors
) {
1329 assert
.t( "Selected option element",
1330 "#form option:selected",
1331 [ "option1a", "option2d", "option3b", "option3c", "option4b", "option4c", "option4d",
1333 assert
.t( "Select options via :selected", "#select1 option:selected", [ "option1a" ] );
1334 assert
.t( "Select options via :selected", "#select2 option:selected", [ "option2d" ] );
1335 assert
.t( "Select options via :selected", "#select3 option:selected", [ "option3b", "option3c" ] );
1336 assert
.t( "Select options via :selected", "select[name='select2'] option:selected", [ "option2d" ] );
1338 assert
.ok( "skip", ":selected not supported in selector-native" );
1339 assert
.ok( "skip", ":selected not supported in selector-native" );
1340 assert
.ok( "skip", ":selected not supported in selector-native" );
1341 assert
.ok( "skip", ":selected not supported in selector-native" );
1342 assert
.ok( "skip", ":selected not supported in selector-native" );
1345 if ( QUnit
.jQuerySelectors
) {
1346 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" ] );
1350 jQuery( "<select value='12600'><option value='option' selected='selected'></option><option value=''></option></select>" )
1351 .prop( "value", "option" )
1352 .is( ":input[value='12600']" ),
1354 ":input[value=foo] selects select by attribute"
1356 assert
.ok( jQuery( "<input type='text' value='12600'/>" ).prop( "value", "option" ).is( ":input[value='12600']" ),
1357 ":input[value=foo] selects text input by attribute"
1360 assert
.ok( "skip", ":input not supported in selector-native" );
1361 assert
.ok( "skip", ":input not supported in selector-native" );
1362 assert
.ok( "skip", ":input not supported in selector-native" );
1365 assert
.t( "Selected option elements are also :checked", "#form option:checked",
1366 [ "option1a", "option2d", "option3b", "option3c", "option4b", "option4c", "option4d",
1368 assert
.t( "Hidden inputs are still :enabled",
1372 extraTexts
.remove();
1375 QUnit
.test( "pseudo - :(dis|en)abled, explicitly disabled", function( assert
) {
1378 // Set a meaningless disabled property on a common ancestor
1379 var container
= document
.getElementById( "disabled-tests" );
1380 container
.disabled
= true;
1382 // Support: IE 6 - 11
1383 // Unset the property where it is not meaningless
1384 if ( document
.getElementById( "enabled-input" ).isDisabled
) {
1385 container
.disabled
= undefined;
1389 "Explicitly disabled elements",
1390 "#enabled-fieldset :disabled",
1391 [ "disabled-input", "disabled-textarea", "disabled-button",
1392 "disabled-select", "disabled-optgroup", "disabled-option" ]
1397 "#enabled-fieldset :enabled",
1398 [ "enabled-input", "enabled-textarea", "enabled-button",
1399 "enabled-select", "enabled-optgroup", "enabled-option" ]
1403 QUnit
.test( "pseudo - :(dis|en)abled, optgroup and option", function( assert
) {
1408 "#disabled-select-inherit :disabled, #enabled-select-inherit :disabled",
1409 [ "disabled-optgroup-inherit", "disabled-optgroup-option", "en_disabled-optgroup-inherit",
1410 "en_disabled-optgroup-option" ]
1415 "#disabled-select-inherit :enabled, #enabled-select-inherit :enabled",
1416 [ "enabled-optgroup-inherit", "enabled-optgroup-option", "enabled-select-option" ]
1420 QUnit
.test( "pseudo - fieldset:(dis|en)abled", function( assert
) {
1423 assert
.t( "Disabled fieldset", "fieldset:disabled", [ "disabled-fieldset" ] );
1424 assert
.t( "Enabled fieldset", "fieldset:enabled", [ "enabled-fieldset" ] );
1427 QUnit
.test( "pseudo - :disabled by ancestry", function( assert
) {
1431 "Inputs inherit disabled from fieldset",
1432 "#disabled-fieldset :disabled",
1433 [ "disabled-fieldset-input", "disabled-fieldset-textarea",
1434 "disabled-fieldset-button" ]
1438 QUnit
.test( "pseudo - a:(dis|en)abled", function( assert
) {
1441 var enabled
, disabled
,
1442 container
= jQuery( "<div></div>" ),
1443 anchor
= jQuery( "<a href='#'>Link</a>" );
1445 container
.appendTo( "#qunit-fixture" );
1447 enabled
= container
.find( "a:enabled" );
1448 disabled
= container
.find( "a:disabled" );
1450 assert
.strictEqual( enabled
.length
, 0, ":enabled doesn't match anchor elements" );
1451 assert
.strictEqual( disabled
.length
, 0, ":disabled doesn't match anchor elements" );
1454 QUnit
.test( "pseudo - :target and :root", function( assert
) {
1459 $link
= jQuery( "<a></a>" ).attr( {
1462 } ).appendTo( "#qunit-fixture" );
1464 oldHash
= window
.location
.hash
;
1465 window
.location
.hash
= "new-link";
1467 assert
.t( ":target", ":target", [ "new-link" ] );
1470 window
.location
.hash
= oldHash
;
1473 assert
.equal( jQuery( ":root" )[ 0 ], document
.documentElement
, ":root selector" );
1476 QUnit
.test( "pseudo - :lang", function( assert
) {
1477 assert
.expect( QUnit
.jQuerySelectors
? 104 : 54 );
1479 var docElem
= document
.documentElement
,
1480 docXmlLang
= docElem
.getAttribute( "xml:lang" ),
1481 docLang
= docElem
.lang
,
1482 foo
= document
.getElementById( "foo" ),
1483 anchor
= document
.getElementById( "anchor2" ),
1484 xml
= createWithFriesXML(),
1485 testLang = function( text
, elem
, container
, lang
, extra
) {
1487 full
= lang
+ "-" + extra
;
1489 message
= "lang=" + lang
+ " " + text
;
1490 container
.setAttribute( container
.ownerDocument
.documentElement
.nodeName
=== "HTML" ? "lang" : "xml:lang", lang
);
1491 assertMatch( message
, elem
, ":lang(" + lang
+ ")" );
1492 assertMatch( message
, elem
, ":lang(" + mixCase( lang
) + ")" );
1493 assertNoMatch( message
, elem
, ":lang(" + full
+ ")" );
1494 assertNoMatch( 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 message
= "lang=" + full
+ " " + text
;
1501 container
.setAttribute( container
.ownerDocument
.documentElement
.nodeName
=== "HTML" ? "lang" : "xml:lang", full
);
1502 assertMatch( message
, elem
, ":lang(" + lang
+ ")" );
1503 assertMatch( message
, elem
, ":lang(" + mixCase( lang
) + ")" );
1504 assertMatch( message
, elem
, ":lang(" + full
+ ")" );
1505 assertMatch( message
, elem
, ":lang(" + mixCase( full
) + ")" );
1506 assertNoMatch( message
, elem
, ":lang(" + lang
+ "-)" );
1507 assertNoMatch( message
, elem
, ":lang(" + full
+ "-)" );
1508 assertNoMatch( message
, elem
, ":lang(" + lang
+ "glish)" );
1509 assertNoMatch( message
, elem
, ":lang(" + full
+ "glish)" );
1511 mixCase = function( str
) {
1512 var ret
= str
.split( "" ),
1516 ret
[ i
] = ret
[ i
].toUpperCase();
1519 return ret
.join( "" );
1521 assertMatch = function( text
, elem
, selector
) {
1522 assert
.ok( jQuery( elem
).is( selector
), text
+ " match " + selector
);
1524 assertNoMatch = function( text
, elem
, selector
) {
1525 assert
.ok( !jQuery( elem
).is( selector
), text
+ " fail " + selector
);
1528 // Prefixing and inheritance
1529 assert
.ok( jQuery( docElem
).is( ":lang(" + docElem
.lang
+ ")" ), "starting :lang" );
1530 testLang( "document", anchor
, docElem
, "en", "us" );
1531 testLang( "grandparent", anchor
, anchor
.parentNode
.parentNode
, "yue", "hk" );
1532 assert
.ok( !jQuery( anchor
).is( ":lang(en), :lang(en-us)" ),
1533 ":lang does not look above an ancestor with specified lang" );
1534 testLang( "self", anchor
, anchor
, "es", "419" );
1536 !jQuery( anchor
).is( ":lang(en), :lang(en-us), :lang(yue), :lang(yue-hk)" ),
1537 ":lang does not look above self with specified lang"
1540 // Searching by language tag
1541 anchor
.parentNode
.parentNode
.lang
= "arab";
1542 anchor
.parentNode
.lang
= anchor
.parentNode
.id
= "ara-sa";
1543 anchor
.lang
= "ara";
1544 assert
.deepEqual( jQuery( ":lang(ara)", foo
).get(), [ anchor
.parentNode
, anchor
], "Find by :lang" );
1546 // Selector validity
1547 anchor
.parentNode
.lang
= "ara";
1548 anchor
.lang
= "ara\\b";
1549 assert
.deepEqual( jQuery( ":lang(ara\\b)", foo
).get(), [], ":lang respects backslashes" );
1551 // Support: Firefox 114+
1552 // Firefox 114+ no longer match on backslashes in `:lang()`, even when escaped.
1553 // It is an intentional change as `:lang()` parameters are supposed to be valid
1554 // BCP 47 strings. Therefore, we won't attempt to patch it.
1555 // We'll keep this test here until other browsers match the behavior.
1556 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1839747#c1
1557 // See https://github.com/w3c/csswg-drafts/issues/8720#issuecomment-1509242961
1559 // assert.deepEqual( jQuery( ":lang(ara\\\\b)", foo ).get(), [ anchor ],
1560 // ":lang respects escaped backslashes" );
1562 assert
.throws( function() {
1563 jQuery( "#qunit-fixture:lang(c++)" );
1564 }, ":lang value must be a valid identifier" );
1566 if ( QUnit
.jQuerySelectors
) {
1569 foo
= jQuery( "response", xml
)[ 0 ];
1570 anchor
= jQuery( "#seite1", xml
)[ 0 ];
1571 testLang( "XML document", anchor
, xml
.documentElement
, "en", "us" );
1572 testLang( "XML grandparent", anchor
, foo
, "yue", "hk" );
1573 assert
.ok( !jQuery( anchor
).is( ":lang(en), :lang(en-us)" ),
1574 "XML :lang does not look above an ancestor with specified lang" );
1575 testLang( "XML self", anchor
, anchor
, "es", "419" );
1577 !jQuery( anchor
).is( ":lang(en), :lang(en-us), :lang(yue), :lang(yue-hk)" ),
1578 "XML :lang does not look above self with specified lang" );
1582 if ( docXmlLang
== null ) {
1583 docElem
.removeAttribute( "xml:lang" );
1585 docElem
.setAttribute( "xml:lang", docXmlLang
);
1587 docElem
.lang
= docLang
;
1590 QUnit
.test( "context", function( assert
) {
1591 assert
.expect( 21 );
1595 expected
= q( "mark", "simon" ),
1596 iframe
= document
.getElementById( "iframe" ),
1597 iframeDoc
= iframe
.contentDocument
|| iframe
.contentWindow
.document
;
1599 assert
.deepEqual( jQuery( selector
, document
).get(), expected
, "explicit document context" );
1600 assert
.deepEqual( jQuery( selector
).get(), expected
, "unspecified context becomes document" );
1601 assert
.deepEqual( jQuery( selector
, undefined ).get(), expected
,
1602 "undefined context becomes document" );
1603 assert
.deepEqual( jQuery( selector
, null ).get(), expected
, "null context becomes document" );
1606 iframeDoc
.write( "<body><p id='foo'>bar</p></body>" );
1608 expected
= [ iframeDoc
.getElementById( "foo" ) ];
1609 assert
.deepEqual( jQuery( "p", iframeDoc
).get(), expected
, "Other document context (simple)" );
1611 if ( QUnit
.jQuerySelectors
) {
1612 assert
.deepEqual( jQuery( "p:contains(ar)", iframeDoc
).get(), expected
,
1613 "Other document context (complex)" );
1615 assert
.ok( "skip", ":contains not supported in selector-native" );
1618 assert
.deepEqual( jQuery( "span", iframeDoc
).get(), [],
1619 "Other document context (simple, no results)" );
1620 assert
.deepEqual( jQuery( "* span", iframeDoc
).get(), [],
1621 "Other document context (complex, no results)" );
1623 context
= document
.getElementById( "nothiddendiv" );
1624 assert
.deepEqual( jQuery( "*", context
).get(), q( "nothiddendivchild" ), "<div> context" );
1626 assert
.deepEqual( jQuery( "* > *", context
).get(), [], "<div> context (no results)" );
1628 context
.removeAttribute( "id" );
1629 assert
.deepEqual( jQuery( "*", context
).get(), q( "nothiddendivchild" ), "no-id element context" );
1631 if ( QUnit
.jQuerySelectors
) {
1632 assert
.deepEqual( jQuery( "* > *", context
).get(), [], "no-id element context (no results)" );
1634 assert
.ok( "skip", ":contains not supported in selector-native" );
1637 assert
.strictEqual( context
.getAttribute( "id" ) || "", "", "id not added by no-id selection" );
1639 context
= document
.getElementById( "lengthtest" );
1640 assert
.deepEqual( jQuery( "input", context
).get(), q( "length", "idTest" ), "<form> context" );
1641 assert
.deepEqual( jQuery( "select", context
).get(), [], "<form> context (no results)" );
1643 context
= document
.getElementById( "台北Táiběi" );
1644 expected
= q( "台北Táiběi-child" );
1645 assert
.deepEqual( jQuery( "span[id]", context
).get(), expected
, "context with non-ASCII id" );
1646 assert
.deepEqual( jQuery( "#台北Táiběi span[id]", context
.parentNode
).get(), expected
,
1647 "context with non-ASCII id selector prefix" );
1649 context
= document
.createDocumentFragment();
1651 // Capture *independent* expected nodes before they're detached from the page
1652 expected
= q( "siblingnext", "siblingspan" );
1653 context
.appendChild( document
.getElementById( "siblingTest" ) );
1656 jQuery( "em:nth-child(2)", context
).get(),
1657 expected
.slice( 0, 1 ),
1658 "DocumentFragment context"
1660 assert
.deepEqual( jQuery( "span", context
).get(), expected
.slice( 1 ),
1661 "DocumentFragment context by tag name" );
1662 assert
.deepEqual( jQuery( "p", context
).get(), [], "DocumentFragment context (no results)" );
1664 if ( QUnit
.jQuerySelectors
) {
1666 jQuery( "em + :not(:has(*)):not(:empty), foo", context
.firstChild
).get(),
1667 expected
.slice( 0, 1 ),
1668 "Non-qSA path correctly sets detached context for sibling selectors (jQuery trac-14351)"
1671 assert
.ok( "skip", ":has not supported in selector-native" );
1676 // IE doesn't support the :scope pseudo-class so it will trigger MutationObservers.
1677 // The test is skipped there.
1678 QUnit
.testUnlessIE( "selectors maintaining context don't trigger mutation observers", function( assert
) {
1682 done
= assert
.async(),
1683 container
= jQuery( "<div></div>" ),
1684 child
= jQuery( "<div></div>" );
1686 child
.appendTo( container
);
1687 container
.appendTo( "#qunit-fixture" );
1689 var observer
= new MutationObserver( function() {
1690 clearTimeout( timeout
);
1691 observer
.disconnect();
1692 assert
.ok( false, "Mutation observer fired during selection" );
1695 observer
.observe( container
[ 0 ], { attributes
: true } );
1697 container
.find( "div div" );
1699 timeout
= setTimeout( function() {
1700 observer
.disconnect();
1701 assert
.ok( true, "Mutation observer didn't fire during selection" );
1706 QUnit
.test( "caching does not introduce bugs", function( assert
) {
1709 var sap
= document
.getElementById( "sap" );
1711 jQuery( ":not(code)", document
.getElementById( "ap" ) );
1713 jQuery( ":not(code)", document
.getElementById( "foo" ) ).get(),
1714 q( "sndp", "en", "yahoo", "sap", "anchor2", "simon" ),
1715 "Reusing selector with new context"
1718 if ( QUnit
.jQuerySelectorsPos
) {
1719 assert
.t( "Deep ancestry caching in post-positional element matcher (jQuery trac-14657)",
1720 "#qunit-fixture a:lt(3):parent",
1721 [ "simon1", "google", "groups" ] );
1723 assert
.ok( "skip", "Positional selectors are not supported" );
1726 sap
.className
= "original";
1727 jQuery( "#qunit-fixture .original" );
1728 document
.getElementById( "nothiddendiv" ).appendChild(
1729 sap
.cloneNode( true ) ).className
= "clone";
1730 assert
.equal( jQuery( "#qunit-fixture .clone [href*='2']" ).length
, 1,
1731 "Cloning does not poison caches" );
1735 QUnit
.test( "disconnected nodes", function( assert
) {
1738 var $div
= jQuery( "<div></div>" );
1739 assert
.equal( $div
.is( "div" ), true, "Make sure .is('nodeName') works on disconnected nodes." );
1742 QUnit
[ QUnit
.jQuerySelectors
? "test" : "skip" ]( "disconnected nodes", function( assert
) {
1745 var $opt
= jQuery( "<option></option>" ).attr( "value", "whipit" ).appendTo( "#qunit-fixture" ).detach();
1746 assert
.equal( $opt
.val(), "whipit", "option value" );
1747 assert
.equal( $opt
.is( ":selected" ), false, "unselected option" );
1748 $opt
.prop( "selected", true );
1749 assert
.equal( $opt
.is( ":selected" ), true, "selected option" );
1753 // IE doesn't support Shadow DOM.
1754 QUnit
.testUnlessIE( "Shadow DOM nodes supported as root", function( assert
) {
1757 var shadowHost
= jQuery( "<div></div>" ).appendTo( "#qunit-fixture" )[ 0 ];
1758 var shadowRoot
= shadowHost
.attachShadow( { mode
: "open" } );
1760 shadowRoot
.innerHTML
= "<div class='vagabond'><p></p></div>";
1761 assert
.equal( jQuery( shadowRoot
).find( ".vagabond" ).length
, 1,
1762 "Selection by class with shadow root" );
1763 assert
.equal( jQuery( shadowRoot
).find( "p" ).length
, 1,
1764 "Paragraph element selected from shadow root" );
1768 "attributes - jQuery.attr",
1769 "selector/html5_selector.html",
1770 function( assert
, jQuery
, window
, document
) {
1771 assert
.expect( 38 );
1774 * Returns an array of elements with the given IDs
1775 * q & t are added here for the iFrame's context
1781 for ( ; i
< arguments
.length
; i
++ ) {
1782 r
.push( document
.getElementById( arguments
[ i
] ) );
1788 * Asserts that a select matches the given IDs
1789 * @example t("Check for something", "//[a]", ["foo", "bar"]);
1790 * @param {String} message - Assertion name
1791 * @param {String} selector - jQuery selector
1792 * @param {Array} expectedIds - Array of ids to construct what is expected
1794 function t( message
, selector
, expectedIds
) {
1795 var elems
= jQuery( selector
).get();
1797 assert
.deepEqual( elems
, q
.apply( q
, expectedIds
), message
+ " (" + selector
+ ")" );
1800 // ====== All known boolean attributes, including html5 booleans ======
1801 // autobuffer, autofocus, autoplay, async, checked,
1802 // compact, controls, declare, defer, disabled,
1803 // formnovalidate, hidden, indeterminate (property only),
1804 // ismap, itemscope, loop, multiple, muted, nohref, noresize,
1805 // noshade, nowrap, novalidate, open, pubdate, readonly, required,
1806 // reversed, scoped, seamless, selected, truespeed, visible (skipping visible attribute, which is on a barprop object)
1808 t( "Attribute Exists", "[autobuffer]", [ "video1" ] );
1809 t( "Attribute Exists", "[autofocus]", [ "text1" ] );
1810 t( "Attribute Exists", "[autoplay]", [ "video1" ] );
1811 t( "Attribute Exists", "[async]", [ "script1" ] );
1812 t( "Attribute Exists", "[checked]", [ "check1" ] );
1813 t( "Attribute Exists", "[compact]", [ "dl" ] );
1814 t( "Attribute Exists", "[controls]", [ "video1" ] );
1815 t( "Attribute Exists", "[declare]", [ "object1" ] );
1816 t( "Attribute Exists", "[defer]", [ "script1" ] );
1817 t( "Attribute Exists", "[disabled]", [ "check1" ] );
1818 t( "Attribute Exists", "[formnovalidate]", [ "form1" ] );
1819 t( "Attribute Exists", "[hidden]", [ "div1" ] );
1820 t( "Attribute Exists", "[indeterminate]", [] );
1821 t( "Attribute Exists", "[ismap]", [ "img1" ] );
1822 t( "Attribute Exists", "[itemscope]", [ "div1" ] );
1823 t( "Attribute Exists", "[loop]", [ "video1" ] );
1824 t( "Attribute Exists", "[multiple]", [ "select1" ] );
1825 t( "Attribute Exists", "[muted]", [ "audio1" ] );
1826 t( "Attribute Exists", "[nohref]", [ "area1" ] );
1827 t( "Attribute Exists", "[noresize]", [ "textarea1" ] );
1828 t( "Attribute Exists", "[noshade]", [ "hr1" ] );
1829 t( "Attribute Exists", "[nowrap]", [ "td1", "div1" ] );
1830 t( "Attribute Exists", "[novalidate]", [ "form1" ] );
1831 t( "Attribute Exists", "[open]", [ "details1" ] );
1832 t( "Attribute Exists", "[pubdate]", [ "article1" ] );
1833 t( "Attribute Exists", "[readonly]", [ "text1" ] );
1834 t( "Attribute Exists", "[required]", [ "text1" ] );
1835 t( "Attribute Exists", "[reversed]", [ "ol1" ] );
1836 t( "Attribute Exists", "[scoped]", [ "style1" ] );
1837 t( "Attribute Exists", "[seamless]", [ "iframe1" ] );
1838 t( "Attribute Exists", "[selected]", [ "option1" ] );
1839 t( "Attribute Exists", "[truespeed]", [ "marquee1" ] );
1841 // Enumerated attributes (these are not boolean content attributes)
1842 jQuery
.expandedEach
= jQuery
.each
;
1843 jQuery
.expandedEach( [ "draggable", "contenteditable", "aria-disabled" ], function( i
, val
) {
1844 t( "Enumerated attribute", "[" + val
+ "]", [ "div1" ] );
1846 t( "Enumerated attribute", "[spellcheck]", [ "span1" ] );
1848 t( "tabindex selector does not retrieve all elements in IE6/7 (trac-8473)",
1849 "form, [tabindex]", [ "form1", "text1" ] );
1850 t( "Improperly named form elements do not interfere with form selections (trac-9570)", "form[name='formName']", [ "form1" ] );
1854 QUnit
.test( "find in document fragments", function( assert
) {
1858 nonnodes
= jQuery( "#nonnodes" ).contents(),
1859 fragment
= document
.createDocumentFragment();
1861 nonnodes
.each( function() {
1862 fragment
.appendChild( this );
1865 elem
= jQuery( fragment
).find( "#nonnodesElement" );
1866 assert
.strictEqual( elem
.length
, 1, "Selection works" );
1869 function getUniqueSortFixtures() {
1872 body
= document
.body
,
1873 fixture
= document
.getElementById( "qunit-fixture" ),
1874 detached1
= document
.createElement( "p" ),
1875 detached2
= document
.createElement( "ul" ),
1876 detachedChild
= detached1
.appendChild( document
.createElement( "a" ) ),
1877 detachedGrandchild
= detachedChild
.appendChild( document
.createElement( "b" ) );
1879 for ( i
= 0; i
< 12; i
++ ) {
1880 detached
.push( document
.createElement( "li" ) );
1881 detached
[ i
].id
= "detached" + i
;
1882 detached2
.appendChild( document
.createElement( "li" ) ).id
= "detachedChild" + i
;
1892 expected
: [ fixture
]
1895 input
: [ fixture
, body
],
1896 expected
: [ body
, fixture
]
1899 input
: [ body
, fixture
, fixture
, body
],
1900 expected
: [ body
, fixture
]
1903 input
: detached
.slice( 0 ),
1904 expected
: detached
.slice( 0 )
1906 "Detached children": {
1908 detached2
.childNodes
[ 3 ],
1909 detached2
.childNodes
[ 0 ],
1910 detached2
.childNodes
[ 2 ],
1911 detached2
.childNodes
[ 1 ]
1914 detached2
.childNodes
[ 0 ],
1915 detached2
.childNodes
[ 1 ],
1916 detached2
.childNodes
[ 2 ],
1917 detached2
.childNodes
[ 3 ]
1920 "Attached/detached mixture": {
1921 input
: [ detached1
, fixture
, detached2
, document
, detachedChild
, body
, detachedGrandchild
],
1922 expected
: [ document
, body
, fixture
],
1928 QUnit
.test( "jQuery.uniqueSort", function( assert
) {
1929 assert
.expect( 14 );
1931 var fixtures
= getUniqueSortFixtures();
1933 function Arrayish( arr
) {
1934 var i
= this.length
= arr
.length
;
1936 this[ i
] = arr
[ i
];
1939 Arrayish
.prototype = {
1940 sliceForTestOnly
: [].slice
1943 jQuery
.each( fixtures
, function( label
, fixture
) {
1944 var length
= fixture
.length
|| fixture
.input
.length
;
1946 // We duplicate `fixture.input` because otherwise it is modified by `uniqueSort`
1947 // and the second test becomes worthless.
1949 jQuery
.uniqueSort( fixture
.input
.slice( 0 ) )
1950 .slice( 0, length
),
1956 jQuery
.uniqueSort( new Arrayish( fixture
.input
) )
1957 .sliceForTestOnly( 0, length
),
1959 label
+ " (quasi-array)"
1964 QUnit
.test( "uniqueSort()", function( assert
) {
1965 assert
.expect( 28 );
1967 var fixtures
= getUniqueSortFixtures();
1969 jQuery
.each( fixtures
, function( label
, fixture
) {
1970 var length
= fixture
.length
|| fixture
.input
.length
,
1971 fixtureInputCopy
= fixture
.input
.slice( 0 ),
1972 sortedElem
= jQuery( fixture
.input
).uniqueSort();
1974 assert
.deepEqual( fixture
.input
, fixtureInputCopy
, "Fixture not modified (" + label
+ ")" );
1976 assert
.deepEqual( sortedElem
.slice( 0, length
).toArray(), fixture
.expected
, label
);
1979 assert
.ok( sortedElem
instanceof jQuery
, "chaining" );
1980 assert
.deepEqual( sortedElem
.end().toArray(), fixture
.input
, label
);
1985 "jQuery.uniqueSort works cross-window (trac-14381)",
1986 "selector/mixed_sort.html",
1987 function( assert
, jQuery
, window
, document
, actual
, expected
) {
1990 assert
.deepEqual( actual
, expected
, "Mixed array was sorted correctly" );
1995 "jQuery selector cache collides with multiple jQueries on a page",
1996 "selector/cache.html",
1997 function( assert
, jQuery
, window
, document
) {
1998 var $cached
= window
.$cached
;
2001 assert
.notStrictEqual( jQuery
, $cached
, "Loaded two engines" );
2002 assert
.deepEqual( $cached( ".test a" ).get(), [ document
.getElementById( "collision" ) ], "Select collision anchor with first sizzle" );
2003 assert
.equal( jQuery( ".evil a" ).length
, 0, "Select nothing with second sizzle" );
2004 assert
.equal( jQuery( ".evil a" ).length
, 0, "Select nothing again with second sizzle" );
2008 QUnit
.test( "Iframe dispatch should not affect jQuery (trac-13936)", function( assert
) {
2012 iframe
= document
.getElementById( "iframe" ),
2013 iframeDoc
= iframe
.contentDocument
|| iframe
.contentWindow
.document
,
2014 done
= assert
.async();
2016 jQuery( iframe
).on( "load", function() {
2020 iframeDoc
= this.contentDocument
|| this.contentWindow
.document
;
2021 form
= jQuery( "#navigate", iframeDoc
)[ 0 ];
2027 assert
.strictEqual( thrown
, false, "No error thrown from post-reload jQuery call" );
2030 jQuery( iframe
).off();
2040 iframeDoc
.write( "<body><form id='navigate' action='?'></form></body>" );
2044 QUnit
.test( "jQuery.escapeSelector", function( assert
) {
2045 assert
.expect( 58 );
2048 assert
.equal( jQuery
.escapeSelector(), "undefined", "Converts undefined to string" );
2049 assert
.equal( jQuery
.escapeSelector( "-" ), "\\-", "Escapes standalone dash" );
2050 assert
.equal( jQuery
.escapeSelector( "-a" ), "-a", "Doesn't escape leading dash followed by non-number" );
2051 assert
.equal( jQuery
.escapeSelector( "--" ), "--", "Doesn't escape standalone double dash" );
2052 assert
.equal( jQuery
.escapeSelector( "\uFFFD" ), "\uFFFD",
2053 "Doesn't escape standalone replacement character" );
2054 assert
.equal( jQuery
.escapeSelector( "a\uFFFD" ), "a\uFFFD",
2055 "Doesn't escape trailing replacement character" );
2056 assert
.equal( jQuery
.escapeSelector( "\uFFFDb" ), "\uFFFDb",
2057 "Doesn't escape leading replacement character" );
2058 assert
.equal( jQuery
.escapeSelector( "a\uFFFDb" ), "a\uFFFDb",
2059 "Doesn't escape embedded replacement character" );
2061 // Derived from CSSOM tests
2062 // https://test.csswg.org/harness/test/cssom-1_dev/section/7.1/
2064 // String conversion
2065 assert
.equal( jQuery
.escapeSelector( true ), "true", "Converts boolean true to string" );
2066 assert
.equal( jQuery
.escapeSelector( false ), "false", "Converts boolean true to string" );
2067 assert
.equal( jQuery
.escapeSelector( null ), "null", "Converts null to string" );
2068 assert
.equal( jQuery
.escapeSelector( "" ), "", "Doesn't modify empty string" );
2071 assert
.equal( jQuery
.escapeSelector( "\0" ), "\uFFFD",
2072 "Escapes null-character input as replacement character" );
2073 assert
.equal( jQuery
.escapeSelector( "a\0" ), "a\uFFFD",
2074 "Escapes trailing-null input as replacement character" );
2075 assert
.equal( jQuery
.escapeSelector( "\0b" ), "\uFFFDb",
2076 "Escapes leading-null input as replacement character" );
2077 assert
.equal( jQuery
.escapeSelector( "a\0b" ), "a\uFFFDb",
2078 "Escapes embedded-null input as replacement character" );
2081 assert
.equal( jQuery
.escapeSelector( "0a" ), "\\30 a", "Escapes leading 0" );
2082 assert
.equal( jQuery
.escapeSelector( "1a" ), "\\31 a", "Escapes leading 1" );
2083 assert
.equal( jQuery
.escapeSelector( "2a" ), "\\32 a", "Escapes leading 2" );
2084 assert
.equal( jQuery
.escapeSelector( "3a" ), "\\33 a", "Escapes leading 3" );
2085 assert
.equal( jQuery
.escapeSelector( "4a" ), "\\34 a", "Escapes leading 4" );
2086 assert
.equal( jQuery
.escapeSelector( "5a" ), "\\35 a", "Escapes leading 5" );
2087 assert
.equal( jQuery
.escapeSelector( "6a" ), "\\36 a", "Escapes leading 6" );
2088 assert
.equal( jQuery
.escapeSelector( "7a" ), "\\37 a", "Escapes leading 7" );
2089 assert
.equal( jQuery
.escapeSelector( "8a" ), "\\38 a", "Escapes leading 8" );
2090 assert
.equal( jQuery
.escapeSelector( "9a" ), "\\39 a", "Escapes leading 9" );
2092 // Letter-number prefix
2093 assert
.equal( jQuery
.escapeSelector( "a0b" ), "a0b", "Doesn't escape embedded 0" );
2094 assert
.equal( jQuery
.escapeSelector( "a1b" ), "a1b", "Doesn't escape embedded 1" );
2095 assert
.equal( jQuery
.escapeSelector( "a2b" ), "a2b", "Doesn't escape embedded 2" );
2096 assert
.equal( jQuery
.escapeSelector( "a3b" ), "a3b", "Doesn't escape embedded 3" );
2097 assert
.equal( jQuery
.escapeSelector( "a4b" ), "a4b", "Doesn't escape embedded 4" );
2098 assert
.equal( jQuery
.escapeSelector( "a5b" ), "a5b", "Doesn't escape embedded 5" );
2099 assert
.equal( jQuery
.escapeSelector( "a6b" ), "a6b", "Doesn't escape embedded 6" );
2100 assert
.equal( jQuery
.escapeSelector( "a7b" ), "a7b", "Doesn't escape embedded 7" );
2101 assert
.equal( jQuery
.escapeSelector( "a8b" ), "a8b", "Doesn't escape embedded 8" );
2102 assert
.equal( jQuery
.escapeSelector( "a9b" ), "a9b", "Doesn't escape embedded 9" );
2104 // Dash-number prefix
2105 assert
.equal( jQuery
.escapeSelector( "-0a" ), "-\\30 a", "Escapes 0 after leading dash" );
2106 assert
.equal( jQuery
.escapeSelector( "-1a" ), "-\\31 a", "Escapes 1 after leading dash" );
2107 assert
.equal( jQuery
.escapeSelector( "-2a" ), "-\\32 a", "Escapes 2 after leading dash" );
2108 assert
.equal( jQuery
.escapeSelector( "-3a" ), "-\\33 a", "Escapes 3 after leading dash" );
2109 assert
.equal( jQuery
.escapeSelector( "-4a" ), "-\\34 a", "Escapes 4 after leading dash" );
2110 assert
.equal( jQuery
.escapeSelector( "-5a" ), "-\\35 a", "Escapes 5 after leading dash" );
2111 assert
.equal( jQuery
.escapeSelector( "-6a" ), "-\\36 a", "Escapes 6 after leading dash" );
2112 assert
.equal( jQuery
.escapeSelector( "-7a" ), "-\\37 a", "Escapes 7 after leading dash" );
2113 assert
.equal( jQuery
.escapeSelector( "-8a" ), "-\\38 a", "Escapes 8 after leading dash" );
2114 assert
.equal( jQuery
.escapeSelector( "-9a" ), "-\\39 a", "Escapes 9 after leading dash" );
2116 // Double dash prefix
2117 assert
.equal( jQuery
.escapeSelector( "--a" ), "--a", "Doesn't escape leading double dash" );
2120 assert
.equal( jQuery
.escapeSelector( "\x01\x02\x1E\x1F" ), "\\1 \\2 \\1e \\1f ",
2121 "Escapes C0 control characters" );
2122 assert
.equal( jQuery
.escapeSelector( "\x80\x2D\x5F\xA9" ), "\x80\x2D\x5F\xA9",
2123 "Doesn't escape general punctuation or non-ASCII ISO-8859-1 characters" );
2125 jQuery
.escapeSelector( "\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90" +
2126 "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F" ),
2127 "\\7f \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90" +
2128 "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F",
2129 "Escapes DEL control character"
2131 assert
.equal( jQuery
.escapeSelector( "\xA0\xA1\xA2" ), "\xA0\xA1\xA2",
2132 "Doesn't escape non-ASCII ISO-8859-1 characters" );
2133 assert
.equal( jQuery
.escapeSelector( "a0123456789b" ), "a0123456789b",
2134 "Doesn't escape embedded numbers" );
2135 assert
.equal( jQuery
.escapeSelector( "abcdefghijklmnopqrstuvwxyz" ), "abcdefghijklmnopqrstuvwxyz",
2136 "Doesn't escape lowercase ASCII letters" );
2137 assert
.equal( jQuery
.escapeSelector( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ), "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
2138 "Doesn't escape uppercase ASCII letters" );
2139 assert
.equal( jQuery
.escapeSelector( "\x20\x21\x78\x79" ), "\\ \\!xy",
2140 "Escapes non-word ASCII characters" );
2142 // Astral symbol (U+1D306 TETRAGRAM FOR CENTRE)
2143 assert
.equal( jQuery
.escapeSelector( "\uD834\uDF06" ), "\uD834\uDF06",
2144 "Doesn't escape astral characters" );
2147 assert
.equal( jQuery
.escapeSelector( "\uDF06" ), "\uDF06", "Doesn't escape lone low surrogate" );
2148 assert
.equal( jQuery
.escapeSelector( "\uD834" ), "\uD834", "Doesn't escape lone high surrogate" );
2151 QUnit
[ QUnit
.jQuerySelectors
? "test" : "skip" ]( "custom pseudos", function( assert
) {
2155 jQuery
.expr
.filters
.foundation
= jQuery
.expr
.filters
.root
;
2156 assert
.deepEqual( jQuery
.find( ":foundation" ), [ document
.documentElement
], "Copy element filter with new name" );
2158 delete jQuery
.expr
.filters
.foundation
;
2162 jQuery
.expr
.setFilters
.primary
= jQuery
.expr
.setFilters
.first
;
2163 assert
.t( "Copy set filter with new name", "div#qunit-fixture :primary", [ "firstp" ] );
2165 delete jQuery
.expr
.setFilters
.primary
;
2169 jQuery
.expr
.filters
.aristotlean
= jQuery
.expr
.createPseudo( function() {
2170 return function( elem
) {
2174 assert
.t( "Custom element filter", "#foo :aristotlean", [ "sndp", "en", "yahoo", "sap", "anchor2", "simon" ] );
2176 delete jQuery
.expr
.filters
.aristotlean
;
2180 jQuery
.expr
.filters
.endswith
= jQuery
.expr
.createPseudo( function( text
) {
2181 return function( elem
) {
2182 return jQuery
.text( elem
).slice( -text
.length
) === text
;
2185 assert
.t( "Custom element filter with argument", "a:endswith(ogle)", [ "google" ] );
2187 delete jQuery
.expr
.filters
.endswith
;
2191 jQuery
.expr
.setFilters
.second
= jQuery
.expr
.createPseudo( function() {
2192 return jQuery
.expr
.createPseudo( function( seed
, matches
) {
2194 matches
[ 1 ] = seed
[ 1 ];
2199 assert
.t( "Custom set filter", "#qunit-fixture p:second", [ "ap" ] );
2201 delete jQuery
.expr
.filters
.second
;
2205 jQuery
.expr
.setFilters
.slice
= jQuery
.expr
.createPseudo( function( argument
) {
2206 var bounds
= argument
.split( ":" );
2207 return jQuery
.expr
.createPseudo( function( seed
, matches
) {
2208 var i
= bounds
[ 1 ];
2210 // Match elements found at the specified indexes
2211 while ( --i
>= bounds
[ 0 ] ) {
2213 matches
[ i
] = seed
[ i
];
2219 assert
.t( "Custom set filter with argument", "#qunit-fixture p:slice(1:3)", [ "ap", "sndp" ] );
2221 delete jQuery
.expr
.filters
.slice
;
2225 QUnit
.test( "jQuery.find.matchesSelector", function( assert
) {
2226 assert
.expect( 15 );
2228 var link
= document
.getElementById( "simon1" ),
2229 input
= document
.getElementById( "text1" ),
2230 option
= document
.getElementById( "option1a" ),
2231 disconnected
= document
.createElement( "div" );
2233 link
.title
= "Don't click me";
2234 assert
.ok( jQuery
.find
.matchesSelector( link
, "[rel='bookmark']" ), "attribute-equals string" );
2235 assert
.ok( jQuery
.find
.matchesSelector( link
, "[rel=bookmark]" ), "attribute-equals identifier" );
2236 assert
.ok( jQuery
.find
.matchesSelector( link
, "[\nrel = bookmark\t]" ),
2237 "attribute-equals identifier (whitespace ignored)" );
2238 assert
.ok( jQuery
.find
.matchesSelector( link
, "a[title=\"Don't click me\"]" ),
2239 "attribute-equals string containing single quote" );
2242 input
.setAttribute( "data-pos", ":first" );
2243 assert
.ok( jQuery
.find
.matchesSelector( input
, "input[data-pos=\\:first]" ),
2244 "attribute-equals POS in identifier" );
2245 assert
.ok( jQuery
.find
.matchesSelector( input
, "input[data-pos=':first']" ),
2246 "attribute-equals POS in string" );
2247 if ( QUnit
.jQuerySelectors
) {
2248 assert
.ok( jQuery
.find
.matchesSelector( input
, ":input[data-pos=':first']" ),
2249 "attribute-equals POS in string after pseudo" );
2251 assert
.ok( "skip", ":input not supported in selector-native" );
2254 option
.setAttribute( "test", "" );
2255 assert
.ok( jQuery
.find
.matchesSelector( option
, "[id=option1a]" ),
2256 "id attribute-equals identifier" );
2257 if ( QUnit
.jQuerySelectors
) {
2258 assert
.ok( jQuery
.find
.matchesSelector( option
, "[id*=option1][type!=checkbox]" ),
2259 "attribute-not-equals identifier" );
2261 assert
.ok( "skip", "[key!=value] not supported in selector-native" );
2263 assert
.ok( jQuery
.find
.matchesSelector( option
, "[id*=option1]" ), "attribute-contains identifier" );
2264 assert
.ok( !jQuery
.find
.matchesSelector( option
, "[test^='']" ),
2265 "attribute-starts-with empty string (negative)" );
2267 option
.className
= "=]";
2268 assert
.ok( jQuery
.find
.matchesSelector( option
, ".\\=\\]" ),
2269 "class selector with attribute-equals confusable" );
2271 assert
.ok( jQuery
.find
.matchesSelector( disconnected
, "div" ), "disconnected element" );
2272 assert
.ok( jQuery
.find
.matchesSelector( link
, "* > *" ), "child combinator matches in document" );
2273 assert
.ok( !jQuery
.find
.matchesSelector( disconnected
, "* > *" ), "child combinator fails in fragment" );
2276 QUnit
.test( "jQuery.find.matches", function( assert
) {
2280 input
= document
.getElementById( "text1" ),
2281 div
= document
.createElement( "div" ),
2282 iframe
= document
.getElementById( "iframe" ),
2283 iframeDoc
= iframe
.contentDocument
|| iframe
.contentWindow
.document
;
2285 assert
.deepEqual( jQuery
.find
.matches( "input", [ input
] ), [ input
],
2286 "jQuery.find.matches with seed of input element" );
2287 assert
.deepEqual( jQuery
.find
.matches( "div", [ div
] ), [ div
],
2288 "jQuery.find.matches with disconnected element" );
2291 iframeDoc
.write( "<body><div id='foo'><div id='bar'></div></div></body>" );
2294 iframeChild
= iframeDoc
.getElementById( "bar" );
2297 jQuery
.find
.matches( ":root > body > #foo > #bar", [ iframeChild
] ),
2299 "jQuery.find.matches infers context from element"
2303 jQuery
.find
.matches( ":root *", [ div
, iframeChild
, input
] ),
2304 [ iframeChild
, input
],
2305 "jQuery.find.matches infers context from each seed element"
2309 QUnit
[ QUnit
.jQuerySelectors
? "test" : "skip" ]( "jQuery.find.select with pre-compiled function", function( assert
) {
2312 supportjQuery
.each( [
2313 "#qunit-fixture #first",
2314 "ol#listWithTabIndex > li[tabindex]",
2316 ], function( i
, selector
) {
2317 var compiled
= jQuery
.find
.compile( selector
);
2318 assert
.equal( jQuery
.find
.select( compiled
, document
).length
,
2319 1, "Should match using a compiled selector function" );
2321 jQuery
.find
.select( compiled
, jQuery( "#first" )[ 0 ] ).length
,
2322 0, "Should not match with different context" );
2326 // Internal, but we test it for backwards compatibility for edge cases
2327 QUnit
[ QUnit
.jQuerySelectors
? "test" : "skip" ]( "jQuery.find.tokenize", function( assert
) {
2330 var selector
= "#id .class > div[prop=\"value\"] + input:nth-child(1):button, span:contains(\"Text\") ~ div:has(div:has(span)):not(.not-this.not-that > div)",
2363 "value": "[prop=\"value\"]",
2383 "value": ":nth-child(1)",
2414 "value": ":contains(\"Text\")",
2433 "value": ":has(div:has(span))",
2441 "value": ":not(.not-this.not-that > div)",
2445 ".not-this.not-that > div"
2451 assert
.deepEqual( jQuery
.find
.tokenize( selector
), tokens
, "Tokenization successful" );