QUnit.module( "selector", { beforeEach: function() { // Playwright WebKit on macOS doesn't expose `Safari` in its user agent // string; use the "AppleWebKit" token. This token is also present // in the Chromium UA, but it is locked to an older version there. // Modern WebKit (Safari 13+) locks it to `605.1.15`. // Since the `3.x` branch is also tested on older WebKit UAs, we // need the `Safari` check as well. Chrome also includes the `Safari` // token, though, so we need to explicitly exclude it. this.safari = /\bapplewebkit\/605\.1\.15\b/i.test( navigator.userAgent ) || ( /\bsafari\b/i.test( navigator.userAgent ) && !/\b(?:headless)?chrome\b/i.test( navigator.userAgent ) ); }, afterEach: moduleTeardown } ); QUnit.test( "empty", function( assert ) { assert.expect( 5 ); var form; assert.strictEqual( jQuery.find( "" ).length, 0, "Empty selector returns an empty array" ); assert.deepEqual( jQuery.find( "div", document.createTextNode( "" ) ), [], "Text element as context fails silently" ); form = document.getElementById( "form" ); assert.ok( !jQuery( form ).is( "" ), "Empty string passed to .is() does not match" ); if ( QUnit.jQuerySelectors ) { assert.equal( jQuery.find( " " ).length, 0, "Empty selector returns an empty array" ); assert.equal( jQuery.find( "\t" ).length, 0, "Empty selector returns an empty array" ); } else { assert.ok( "skip", "whitespace-only selector not supported in selector-native" ); assert.ok( "skip", "whitespace-only selector not supported in selector-native" ); } } ); QUnit.test( "star", function( assert ) { assert.expect( 2 ); var good, i, all = jQuery.find( "*" ); assert.ok( all.length >= 30, "Select all" ); good = true; for ( i = 0; i < all.length; i++ ) { if ( all[ i ].nodeType === 8 ) { good = false; } } assert.ok( good, "Select all elements, no comment nodes" ); } ); QUnit.test( "element", function( assert ) { assert.expect( 37 ); var i, lengthtest, siblingTest, html, fixture = document.getElementById( "qunit-fixture" ); assert.deepEqual( jQuery( "p", fixture ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a Node context." ); assert.deepEqual( jQuery( "p", "#qunit-fixture" ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a selector context." ); assert.deepEqual( jQuery( "p", jQuery( "#qunit-fixture" ) ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a jQuery object context." ); assert.deepEqual( jQuery( "#qunit-fixture" ).find( "p" ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a context via .find()." ); assert.ok( jQuery( "#length" ).length, " cannot be found under IE, see trac-945" ); assert.ok( jQuery( "#lengthtest input" ).length, " cannot be found under IE, see trac-945" ); // trac-7533 assert.equal( jQuery( "

foo

" ).find( "p" ).length, 1, "Find where context root is a node and has an ID with CSS3 meta characters" ); assert.equal( jQuery.find( "" ).length, 0, "Empty selector returns an empty array" ); assert.deepEqual( jQuery.find( "div", document.createTextNode( "" ) ), [], "Text element as context fails silently" ); assert.t( "Element Selector", "html", [ "html" ] ); assert.t( "Element Selector", "body", [ "body" ] ); assert.t( "Element Selector", "#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.t( "Leading space", " #qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.t( "Leading tab", "\t#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.t( "Leading carriage return", "\r#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.t( "Leading line feed", "\n#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.t( "Leading form feed", "\f#qunit-fixture p", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.t( "Trailing space", "#qunit-fixture p ", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.t( "Trailing tab", "#qunit-fixture p\t", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.t( "Trailing carriage return", "#qunit-fixture p\r", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.t( "Trailing line feed", "#qunit-fixture p\n", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.t( "Trailing form feed", "#qunit-fixture p\f", [ "firstp", "ap", "sndp", "en", "sap", "first" ] ); assert.deepEqual( jQuery( jQuery.find( "div ol" ) ).filter( "#qunit-fixture *" ).get(), q( "empty", "listWithTabIndex" ), "Parent Element" ); assert.deepEqual( jQuery( jQuery.find( "div\tol" ) ).filter( "#qunit-fixture *" ).get(), q( "empty", "listWithTabIndex" ), "Parent Element (non-space descendant combinator)" ); // Check for unique-ness and sort order assert.deepEqual( jQuery.find( "p, div p" ), jQuery.find( "p" ), "Check for duplicates: p, div p" ); jQuery( "

" ).prependTo( "#qunit-fixture" ); assert.t( "Checking sort order", "#qunit-fixture h2, #qunit-fixture h1", [ "h1", "h2", "h2-2" ] ); if ( QUnit.jQuerySelectorsPos ) { assert.t( "Checking sort order", "#qunit-fixture h2:first, #qunit-fixture h1:first", [ "h1", "h2" ] ); } else { assert.ok( "skip", "Positional selectors are not supported" ); } assert.t( "Checking sort order", "#qunit-fixture p, #qunit-fixture p a", [ "firstp", "simon1", "ap", "google", "groups", "anchor1", "mark", "sndp", "en", "yahoo", "sap", "anchor2", "simon", "first" ] ); // Test Conflict ID lengthtest = document.getElementById( "lengthtest" ); assert.deepEqual( jQuery.find( "#idTest", lengthtest ), q( "idTest" ), "Finding element with id of ID." ); assert.deepEqual( jQuery.find( "[name='id']", lengthtest ), q( "idTest" ), "Finding element with id of ID." ); assert.deepEqual( jQuery.find( "input[id='idTest']", lengthtest ), q( "idTest" ), "Finding elements with id of ID." ); if ( QUnit.jQuerySelectors ) { siblingTest = document.getElementById( "siblingTest" ); assert.deepEqual( jQuery.find( "div em", siblingTest ), [], "Element-rooted QSA does not select based on document context" ); assert.deepEqual( jQuery.find( "div em, div em, div em:not(div em)", siblingTest ), [], "Element-rooted QSA does not select based on document context" ); assert.deepEqual( jQuery.find( "div em, em\\,", siblingTest ), [], "Escaped commas do not get treated with an id in element-rooted QSA" ); } else { assert.ok( "skip", "Element-rooted QSA behavior different in selector-native" ); assert.ok( "skip", "Element-rooted QSA behavior different in selector-native" ); assert.ok( "skip", "Element-rooted QSA behavior different in selector-native" ); } html = ""; for ( i = 0; i < 100; i++ ) { html = "
" + html + "
"; } html = jQuery( html ).appendTo( document.body ); assert.ok( !!jQuery.find( "body div div div" ).length, "No stack or performance problems with large amounts of descendants" ); assert.ok( !!jQuery.find( "body>div div div" ).length, "No stack or performance problems with large amounts of descendants" ); html.remove(); // Real use case would be using .watch in browsers with window.watch (see Issue #157) q( "qunit-fixture" )[ 0 ].appendChild( document.createElement( "toString" ) ).id = "toString"; assert.t( "Element name matches Object.prototype property", "toString#toString", [ "toString" ] ); } ); QUnit.test( "XML Document Selectors", function( assert ) { assert.expect( 11 ); var xml = createWithFriesXML(); assert.equal( jQuery.find( "foo_bar", xml ).length, 1, "Element Selector with underscore" ); assert.equal( jQuery.find( ".component", xml ).length, 1, "Class selector" ); assert.equal( jQuery.find( "[class*=component]", xml ).length, 1, "Attribute selector for class" ); assert.equal( jQuery.find( "property[name=prop2]", xml ).length, 1, "Attribute selector with name" ); assert.equal( jQuery.find( "[name=prop2]", xml ).length, 1, "Attribute selector with name" ); assert.equal( jQuery.find( "#seite1", xml ).length, 1, "Attribute selector with ID" ); assert.equal( jQuery.find( "component#seite1", xml ).length, 1, "Attribute selector with ID" ); assert.equal( jQuery( "component", xml ).filter( "#seite1" ).length, 1, "Attribute selector filter with ID" ); assert.equal( jQuery.find( "meta property thing", xml ).length, 2, "Descendent selector and dir caching" ); if ( QUnit.jQuerySelectors ) { assert.ok( jQuery( xml.lastChild ).is( "soap\\:Envelope" ), "Check for namespaced element" ); xml = jQuery.parseXML( "" ); assert.equal( jQuery.find( "elem:not(:has(*))", xml ).length, 1, "Non-qSA path correctly handles numeric ids (jQuery #14142)" ); } else { assert.ok( "skip", "namespaced elements not matching correctly in selector-native" ); assert.ok( "skip", ":not(complex selector) not supported in selector-native" ); } } ); QUnit.test( "broken selectors throw", function( assert ) { assert.expect( document.documentMode === 9 ? 32 : 33 ); function broken( name, selector ) { assert.throws( function() { jQuery( selector ); }, name + ": " + selector ); } broken( "Broken Selector", "[" ); broken( "Broken Selector", "(" ); broken( "Broken Selector", "{" ); broken( "Broken Selector", "<" ); broken( "Broken Selector", "()" ); broken( "Broken Selector", "<>" ); broken( "Broken Selector", "{}" ); broken( "Broken Selector", "," ); broken( "Broken Selector", ",a" ); broken( "Broken Selector", "a," ); broken( "Post-comma invalid selector", "*,:x" ); broken( "Identifier with bad escape", "foo\\\fbaz" ); broken( "Broken Selector", "[id=012345678901234567890123456789" ); broken( "Doesn't exist", ":visble" ); broken( "Nth-child", ":nth-child" ); // Support: IE 9 only // IE 9 thinks this is a real selector. // It's not super critical that we fix this case. if ( document.documentMode !== 9 ) { broken( "Nth-child", ":nth-child(-)" ); } broken( "Nth-child", ":nth-child(asdf)", [] ); broken( "Nth-child", ":nth-child(2n+-0)" ); broken( "Nth-child", ":nth-child(2+0)" ); broken( "Nth-child", ":nth-child(- 1n)" ); broken( "Nth-child", ":nth-child(-1 n)" ); broken( "First-child", ":first-child(n)" ); broken( "Last-child", ":last-child(n)" ); broken( "Only-child", ":only-child(n)" ); broken( "Nth-last-last-child", ":nth-last-last-child(1)" ); broken( "First-last-child", ":first-last-child" ); broken( "Last-last-child", ":last-last-child" ); broken( "Only-last-child", ":only-last-child" ); // Make sure attribute value quoting works correctly. See: trac-6093 jQuery( "" + "" ) .appendTo( "#qunit-fixture" ); broken( "Attribute equals non-value", "input[name=]" ); broken( "Attribute equals unquoted non-identifier", "input[name=foo.baz]" ); broken( "Attribute equals unquoted non-identifier", "input[name=foo[baz]]" ); broken( "Attribute equals bad string", "input[name=''double-quoted'']" ); broken( "Attribute equals bad string", "input[name='apostrophe'd']" ); } ); QUnit.test( "id", function( assert ) { assert.expect( 35 ); var fiddle, a, lengthtest; assert.t( "ID Selector", "#body", [ "body" ] ); assert.t( "ID Selector w/ Element", "body#body", [ "body" ] ); assert.t( "ID Selector w/ Element", "ul#first", [] ); assert.t( "ID selector with existing ID descendant", "#firstp #simon1", [ "simon1" ] ); assert.t( "ID selector with non-existent descendant", "#firstp #foobar", [] ); assert.t( "ID selector using UTF8", "#台北Táiběi", [ "台北Táiběi" ] ); assert.t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", [ "台北Táiběi", "台北" ] ); assert.t( "Descendant ID selector using UTF8", "div #台北", [ "台北" ] ); assert.t( "Child ID selector using UTF8", "form > #台北", [ "台北" ] ); assert.t( "Escaped ID", "#foo\\:bar", [ "foo:bar" ] ); if ( QUnit.jQuerySelectors ) { assert.t( "Escaped ID with descendant", "#foo\\:bar span:not(:input)", [ "foo_descendant" ] ); } else { assert.ok( "skip", ":input not supported in selector-native" ); } assert.t( "Escaped ID", "#test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] ); assert.t( "Descendant escaped ID", "div #foo\\:bar", [ "foo:bar" ] ); assert.t( "Descendant escaped ID", "div #test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] ); assert.t( "Child escaped ID", "form > #foo\\:bar", [ "foo:bar" ] ); assert.t( "Child escaped ID", "form > #test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] ); fiddle = jQuery( "
" ) .appendTo( "#qunit-fixture" ); if ( QUnit.jQuerySelectors ) { assert.deepEqual( jQuery.find( "> span", jQuery( "#fiddle\\\\Foo" )[ 0 ] ), q( [ "fiddleSpan" ] ), "Escaped ID as context" ); } else { assert.ok( "skip", "leading > not supported in selector-native" ); } fiddle.remove(); assert.t( "ID Selector, child ID present", "#form > #radio1", [ "radio1" ] ); // bug trac-267 assert.t( "ID Selector, not an ancestor ID", "#form #first", [] ); assert.t( "ID Selector, not a child ID", "#form > #option1a", [] ); assert.t( "All Children of ID", "#foo > *", [ "sndp", "en", "sap" ] ); assert.t( "All Children of ID with no children", "#firstUL > *", [] ); assert.equal( jQuery( "#tName1" )[ 0 ].id, "tName1", "ID selector with same value for a name attribute" ); assert.t( "ID selector non-existing but name attribute on an A tag", "#tName2", [] ); assert.t( "Leading ID selector non-existing but name attribute on an A tag", "#tName2 span", [] ); assert.t( "Leading ID selector existing, retrieving the child", "#tName1 span", [ "tName1-span" ] ); assert.equal( jQuery( "div > div #tName1" )[ 0 ].id, jQuery( "#tName1-span" )[ 0 ].parentNode.id, "Ending with ID" ); a = jQuery( "" ).appendTo( "#qunit-fixture" ); assert.t( "ID Selector contains backslash", "#backslash\\\\foo", [ "backslash\\foo" ] ); a.remove(); assert.t( "ID Selector on Form with an input that has a name of 'id'", "#lengthtest", [ "lengthtest" ] ); // Run the above test again but with `jQuery.find` directly to avoid the jQuery // quick path that avoids running the selector engine. lengthtest = jQuery.find( "#lengthtest" ); assert.strictEqual( lengthtest && lengthtest[ 0 ], document.getElementById( "lengthtest" ), "ID Selector on Form with an input that has a name of 'id' - no quick path (#lengthtest)" ); assert.t( "ID selector with non-existent ancestor", "#asdfasdf #foobar", [] ); // bug trac-986 assert.deepEqual( jQuery.find( "div#form", document.body ), [], "ID selector within the context of another element" ); assert.t( "Underscore ID", "#types_all", [ "types_all" ] ); assert.t( "Dash ID", "#qunit-fixture", [ "qunit-fixture" ] ); assert.t( "ID with weird characters in it", "#name\\+value", [ "name+value" ] ); } ); QUnit.test( "class", function( assert ) { assert.expect( 32 ); assert.deepEqual( jQuery( ".blog", document.getElementsByTagName( "p" ) ).get(), q( "mark", "simon" ), "Finding elements with a context." ); assert.deepEqual( jQuery( ".blog", "p" ).get(), q( "mark", "simon" ), "Finding elements with a context." ); assert.deepEqual( jQuery( ".blog", jQuery( "p" ) ).get(), q( "mark", "simon" ), "Finding elements with a context." ); assert.deepEqual( jQuery( "p" ).find( ".blog" ).get(), q( "mark", "simon" ), "Finding elements with a context." ); assert.t( "Class Selector", ".blog", [ "mark", "simon" ] ); assert.t( "Class Selector", ".GROUPS", [ "groups" ] ); assert.t( "Class Selector", ".blog.link", [ "simon" ] ); assert.t( "Class Selector w/ Element", "a.blog", [ "mark", "simon" ] ); assert.t( "Parent Class Selector", "p .blog", [ "mark", "simon" ] ); assert.t( "Class selector using UTF8", ".台北Táiběi", [ "utf8class1" ] ); assert.t( "Class selector using UTF8", ".台北", [ "utf8class1", "utf8class2" ] ); assert.t( "Class selector using UTF8", ".台北Táiběi.台北", [ "utf8class1" ] ); assert.t( "Class selector using UTF8", ".台北Táiběi, .台北", [ "utf8class1", "utf8class2" ] ); assert.t( "Descendant class selector using UTF8", "div .台北Táiběi", [ "utf8class1" ] ); assert.t( "Child class selector using UTF8", "form > .台北Táiběi", [ "utf8class1" ] ); assert.t( "Escaped Class", ".foo\\:bar", [ "foo:bar" ] ); assert.t( "Escaped Class", ".test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] ); assert.t( "Descendant escaped Class", "div .foo\\:bar", [ "foo:bar" ] ); assert.t( "Descendant escaped Class", "div .test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] ); assert.t( "Child escaped Class", "form > .foo\\:bar", [ "foo:bar" ] ); assert.t( "Child escaped Class", "form > .test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] ); var div = document.createElement( "div" ); div.innerHTML = "
"; assert.deepEqual( jQuery.find( ".e", div ), [ div.firstChild ], "Finding a second class." ); div.lastChild.className = "e"; assert.ok( !jQuery( div ).is( ".null" ), ".null does not match an element with no class" ); assert.ok( !jQuery( div.firstChild ).is( ".null div" ), ".null does not match an element with no class" ); div.className = "null"; assert.ok( jQuery( div ).is( ".null" ), ".null matches element with class 'null'" ); assert.ok( jQuery( div.firstChild ).is( ".null div" ), "caching system respects DOM changes" ); assert.ok( !jQuery( document ).is( ".foo" ), "testing class on document doesn't error" ); assert.ok( !jQuery( window ).is( ".foo" ), "testing class on window doesn't error" ); assert.deepEqual( jQuery.find( ".e", div ), [ div.firstChild, div.lastChild ], "Finding a modified class." ); div.lastChild.className += " hasOwnProperty toString"; assert.deepEqual( jQuery.find( ".e.hasOwnProperty.toString", div ), [ div.lastChild ], "Classes match Object.prototype properties" ); div = jQuery( "
" )[ 0 ]; assert.equal( jQuery.find( ".foo", div ).length, 1, "Class selector against SVG container" ); assert.equal( jQuery.find( ".foo", div.firstChild ).length, 1, "Class selector directly against SVG" ); } ); QUnit.test( "name", function( assert ) { assert.expect( 14 ); var form; assert.t( "Name selector", "input[name=action]", [ "text1" ] ); assert.t( "Name selector with single quotes", "input[name='action']", [ "text1" ] ); assert.t( "Name selector with double quotes", "input[name=\"action\"]", [ "text1" ] ); assert.t( "Name selector non-input", "[name=example]", [ "name-is-example" ] ); assert.t( "Name selector non-input", "[name=div]", [ "name-is-div" ] ); assert.t( "Name selector non-input", "*[name=iframe]", [ "iframe" ] ); assert.t( "Name selector for grouped input", "input[name='types[]']", [ "types_all", "types_anime", "types_movie" ] ); form = document.getElementById( "form" ); assert.deepEqual( jQuery.find( "input[name=action]", form ), q( "text1" ), "Name selector within the context of another element" ); assert.deepEqual( jQuery.find( "input[name='foo[bar]']", form ), q( "hidden2" ), "Name selector for grouped form element within the context of another element" ); form = jQuery( "
" ).appendTo( "body" ); assert.equal( jQuery.find( "input", form[ 0 ] ).length, 1, "Make sure that rooted queries on forms (with possible expandos) work." ); form.remove(); assert.t( "Find elements that have similar IDs", "[name=tName1]", [ "tName1ID" ] ); assert.t( "Find elements that have similar IDs", "[name=tName2]", [ "tName2ID" ] ); assert.t( "Find elements that have similar IDs", "#tName2ID", [ "tName2ID" ] ); assert.t( "Case-sensitivity", "[name=tname1]", [] ); } ); QUnit.test( "comma-separated", function( assert ) { assert.expect( 10 ); var fixture = jQuery( "

" ); assert.equal( fixture.find( "h2, div p" ).filter( "p" ).length, 2, "has to find two

" ); assert.equal( fixture.find( "h2, div p" ).filter( "h2" ).length, 1, "has to find one

" ); assert.equal( fixture.find( "h2 , div p" ).filter( "p" ).length, 2, "has to find two

" ); assert.equal( fixture.find( "h2 , div p" ).filter( "h2" ).length, 1, "has to find one

" ); assert.equal( fixture.find( "h2 ,div p" ).filter( "p" ).length, 2, "has to find two

" ); assert.equal( fixture.find( "h2 ,div p" ).filter( "h2" ).length, 1, "has to find one

" ); assert.equal( fixture.find( "h2,div p" ).filter( "p" ).length, 2, "has to find two

" ); assert.equal( fixture.find( "h2,div p" ).filter( "h2" ).length, 1, "has to find one

" ); assert.equal( fixture.find( "h2\t,\rdiv p" ).filter( "p" ).length, 2, "has to find two

" ); assert.equal( fixture.find( "h2\t,\rdiv p" ).filter( "h2" ).length, 1, "has to find one

" ); } ); // Support: IE 9 only // IE 9 doesn't support the `:valid` pseudo natively; skip the test there. QUnit[ /msie 9\.0/i.test( window.navigator.userAgent ) ? "skip" : "test" ]( "comma-separated, only supported natively (gh-5177)", function( assert ) { assert.expect( 5 ); var fixture = jQuery( "
" ); fixture.appendTo( "#qunit-fixture" ); assert.equal( fixture.find( "input:valid, span" ).length, 2, "has to find two elements" ); assert.equal( fixture.find( "input:valid , span" ).length, 2, "has to find two elements" ); assert.equal( fixture.find( "input:valid ,span" ).length, 2, "has to find two elements" ); assert.equal( fixture.find( "input:valid,span" ).length, 2, "has to find two elements" ); assert.equal( fixture.find( "input:valid\t,\rspan" ).length, 2, "has to find two elements" ); } ); QUnit.test( "child and adjacent", function( assert ) { assert.expect( 43 ); var siblingFirst, en, nothiddendiv; assert.t( "Child", "p > a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] ); assert.t( "Child minus leading whitespace", "p> a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] ); assert.t( "Child minus trailing whitespace", "p >a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] ); assert.t( "Child minus whitespace", "p>a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] ); assert.t( "Child w/ Class", "p > a.blog", [ "mark", "simon" ] ); assert.t( "All Children", "code > *", [ "anchor1", "anchor2" ] ); assert.selectInFixture( "All Grandchildren", "p > * > *", [ "anchor1", "anchor2" ] ); assert.t( "Rooted tag adjacent", "#qunit-fixture a + a", [ "groups", "tName2ID" ] ); assert.t( "Rooted tag adjacent minus whitespace", "#qunit-fixture a+a", [ "groups", "tName2ID" ] ); assert.t( "Rooted tag adjacent minus leading whitespace", "#qunit-fixture a +a", [ "groups", "tName2ID" ] ); assert.t( "Rooted tag adjacent minus trailing whitespace", "#qunit-fixture a+ a", [ "groups", "tName2ID" ] ); assert.t( "Tag adjacent", "p + p", [ "ap", "en", "sap" ] ); assert.t( "#id adjacent", "#firstp + p", [ "ap" ] ); assert.t( "Tag#id adjacent", "p#firstp + p", [ "ap" ] ); assert.t( "Tag[attr] adjacent", "p[lang=en] + p", [ "sap" ] ); assert.t( "Tag.class adjacent", "a.GROUPS + code + a", [ "mark" ] ); assert.t( "Comma, Child, and Adjacent", "#qunit-fixture a + a, code > a", [ "groups", "anchor1", "anchor2", "tName2ID" ] ); assert.t( "Element Preceded By", "#qunit-fixture p ~ div", [ "foo", "nothiddendiv", "moretests", "tabindex-tests", "liveHandlerOrder", "siblingTest", "fx-test-group" ] ); assert.t( "Element Preceded By", "#first ~ div", [ "moretests", "tabindex-tests", "liveHandlerOrder", "siblingTest", "fx-test-group" ] ); assert.t( "Element Preceded By", "#groups ~ a", [ "mark" ] ); assert.t( "Element Preceded By", "#length ~ input", [ "idTest" ] ); assert.t( "Element Preceded By", "#siblingfirst ~ em", [ "siblingnext", "siblingthird" ] ); assert.t( "Element Preceded By (multiple)", "#siblingTest em ~ em ~ em ~ span", [ "siblingspan" ] ); siblingFirst = document.getElementById( "siblingfirst" ); if ( QUnit.jQuerySelectors ) { assert.deepEqual( jQuery.find( "+ em", siblingFirst ), q( "siblingnext" ), "Element Directly Preceded By with a context." ); assert.deepEqual( jQuery.find( "~ em", siblingFirst ), q( "siblingnext", "siblingthird" ), "Element Preceded By with a context." ); } else { assert.ok( "skip", "leading + not supported in selector-native" ); assert.ok( "skip", "leading ~ not supported in selector-native" ); } if ( QUnit.jQuerySelectorsPos ) { assert.deepEqual( jQuery.find( "~ em:first", siblingFirst ), q( "siblingnext" ), "Element Preceded By positional with a context." ); } else { assert.ok( "skip", "Positional selectors are not supported" ); } if ( QUnit.jQuerySelectors ) { en = document.getElementById( "en" ); assert.deepEqual( jQuery.find( "+ p, a", en ), q( "yahoo", "sap" ), "Compound selector with context, beginning with sibling test." ); assert.deepEqual( jQuery.find( "a, + p", en ), q( "yahoo", "sap" ), "Compound selector with context, containing sibling test." ); } else { assert.ok( "skip", "leading + not supported in selector-native" ); assert.ok( "skip", "leading + not supported in selector-native" ); } if ( QUnit.jQuerySelectors ) { assert.t( "Element Preceded By, Containing", "#liveHandlerOrder ~ div em:contains('1')", [ "siblingfirst" ] ); assert.t( "Combinators are not skipped when mixing general and specific", "#siblingTest > em:contains('x') + em ~ span", [] ); } else { assert.ok( "skip", ":contains not supported in selector-native" ); assert.ok( "skip", ":contains not supported in selector-native" ); } if ( QUnit.jQuerySelectorsPos ) { assert.equal( jQuery( "#listWithTabIndex li:eq(2) ~ li" ).length, 1, "Find by general sibling combinator (trac-8310)" ); nothiddendiv = document.getElementById( "nothiddendiv" ); assert.deepEqual( jQuery.find( "> :first", nothiddendiv ), q( "nothiddendivchild" ), "Verify child context positional selector" ); assert.deepEqual( jQuery.find( "> :eq(0)", nothiddendiv ), q( "nothiddendivchild" ), "Verify child context positional selector" ); assert.deepEqual( jQuery.find( "> *:first", nothiddendiv ), q( "nothiddendivchild" ), "Verify child context positional selector" ); } else { assert.ok( "skip", "Positional selectors are not supported" ); assert.ok( "skip", "Positional selectors are not supported" ); assert.ok( "skip", "Positional selectors are not supported" ); assert.ok( "skip", "Positional selectors are not supported" ); } assert.t( "Multiple combinators selects all levels", "#siblingTest em *", [ "siblingchild", "siblinggrandchild", "siblinggreatgrandchild" ] ); assert.t( "Multiple combinators selects all levels", "#siblingTest > em *", [ "siblingchild", "siblinggrandchild", "siblinggreatgrandchild" ] ); assert.t( "Multiple sibling combinators doesn't miss general siblings", "#siblingTest > em:first-child + em ~ span", [ "siblingspan" ] ); assert.equal( jQuery( "#listWithTabIndex" ).length, 1, "Parent div for next test is found via ID (trac-8310)" ); assert.equal( jQuery( "#__sizzle__" ).length, 0, "Make sure the temporary id assigned by sizzle is cleared out (trac-8310)" ); assert.equal( jQuery( "#listWithTabIndex" ).length, 1, "Parent div for previous test is still found via ID (trac-8310)" ); assert.t( "Verify deep class selector", "div.blah > p > a", [] ); assert.t( "No element deep selector", "div.foo > span > a", [] ); assert.t( "Non-existent ancestors", ".fototab > .thumbnails > a", [] ); } ); QUnit.test( "attributes - existence", function( assert ) { assert.expect( 7 ); assert.t( "On element", "#qunit-fixture a[title]", [ "google" ] ); assert.t( "On element (whitespace ignored)", "#qunit-fixture a[ title ]", [ "google" ] ); assert.t( "On element (case-insensitive)", "#qunit-fixture a[TITLE]", [ "google" ] ); assert.t( "On any element", "#qunit-fixture *[title]", [ "google" ] ); assert.t( "On implicit element", "#qunit-fixture [title]", [ "google" ] ); assert.t( "Boolean", "#select2 option[selected]", [ "option2d" ] ); assert.t( "For attribute on label", "#qunit-fixture form label[for]", [ "label-for" ] ); } ); QUnit.test( "attributes - equals", function( assert ) { assert.expect( 20 ); var withScript; assert.t( "Identifier", "#qunit-fixture a[rel=bookmark]", [ "simon1" ] ); assert.t( "Identifier with underscore", "input[id=types_all]", [ "types_all" ] ); assert.t( "String", "#qunit-fixture a[rel='bookmark']", [ "simon1" ] ); assert.t( "String (whitespace ignored)", "#qunit-fixture a[ rel = 'bookmark' ]", [ "simon1" ] ); assert.t( "Non-identifier string", "#qunit-fixture a[href='http://www.google.com/']", [ "google" ] ); assert.t( "Empty string", "#select1 option[value='']", [ "option1a" ] ); if ( QUnit.jQuerySelectors ) { assert.t( "Number", "#qunit-fixture option[value=1]", [ "option1b", "option2b", "option3b", "option4b", "option5c" ] ); assert.t( "negative number", "#qunit-fixture li[tabIndex=-1]", [ "foodWithNegativeTabIndex" ] ); } else { assert.ok( "skip", "Number value not supported in selector-native" ); assert.ok( "skip", "Negative number value not supported in selector-native" ); } assert.t( "Non-ASCII identifier", "span[lang=中文]", [ "台北" ] ); assert.t( "input[type=text]", "#form input[type=text]", [ "text1", "text2", "hidden2", "name" ] ); assert.t( "input[type=search]", "#form input[type=search]", [ "search" ] ); withScript = supportjQuery( "