diff --git a/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Libraries/LibWeb/CSS/Parser/Parser.cpp index 0d85225db8f..7b9a7e28b41 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -768,6 +768,8 @@ Vector Parser::consume_a_list_of_component_values(TokenStream } } } +template Vector Parser::consume_a_list_of_component_values(TokenStream& input, Optional stop_token, Nested nested); +template Vector Parser::consume_a_list_of_component_values(TokenStream& input, Optional stop_token, Nested nested); // https://drafts.csswg.org/css-syntax/#consume-simple-block template diff --git a/Libraries/LibWeb/CSS/Parser/SelectorParsing.cpp b/Libraries/LibWeb/CSS/Parser/SelectorParsing.cpp index 109dcb53d5b..724292cb64c 100644 --- a/Libraries/LibWeb/CSS/Parser/SelectorParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/SelectorParsing.cpp @@ -86,10 +86,9 @@ static NonnullRefPtr create_invalid_selector(Selector::Combinator comb template Parser::ParseErrorOr Parser::parse_a_selector_list(TokenStream& tokens, SelectorType mode, SelectorParsingMode parsing_mode) { - auto comma_separated_lists = parse_a_comma_separated_list_of_component_values(tokens); - SelectorList selectors; - for (auto& selector_parts : comma_separated_lists) { + for (;;) { + auto selector_parts = consume_a_list_of_component_values(tokens, Token::Type::Comma); auto stream = TokenStream(selector_parts); auto selector = parse_complex_selector(stream, mode); if (selector.is_error()) { @@ -97,11 +96,17 @@ Parser::ParseErrorOr Parser::parse_a_selector_list(TokenStream& // Keep the invalid selector around for serialization and nesting auto combinator = mode == SelectorType::Standalone ? Selector::Combinator::None : Selector::Combinator::Descendant; selectors.append(create_invalid_selector(combinator, move(selector_parts))); - continue; + } else { + return selector.error(); } - return selector.error(); + } else { + selectors.append(selector.release_value()); } - selectors.append(selector.release_value()); + + if (tokens.is_empty()) + break; + + tokens.discard_a_token(); } if (selectors.is_empty() && parsing_mode != SelectorParsingMode::Forgiving) diff --git a/Tests/LibWeb/TestConfig.ini b/Tests/LibWeb/TestConfig.ini index 0a44d0dcae5..60ca3299bb3 100644 --- a/Tests/LibWeb/TestConfig.ini +++ b/Tests/LibWeb/TestConfig.ini @@ -165,3 +165,6 @@ Text/input/wpt-import/css/css-backgrounds/animations/discrete-no-interpolation.h ; https://github.com/LadybirdBrowser/ladybird/issues/2314 Text/input/test-http-test-server.html + +; Too slow for CI +Text/input/wpt-import/dom/nodes/ParentNode-querySelector-All.html diff --git a/Tests/LibWeb/Text/data/ParentNode-querySelector-All-content.html b/Tests/LibWeb/Text/data/ParentNode-querySelector-All-content.html new file mode 100644 index 00000000000..8dc13545516 --- /dev/null +++ b/Tests/LibWeb/Text/data/ParentNode-querySelector-All-content.html @@ -0,0 +1,377 @@ + + + + + Selectors-API Test Suite: HTML with Selectors Level 2 using TestHarness: Test Document + + + + + + + + +
+
+ +
+

Universal selector tests inside element with id="universal".

+
+
Some preformatted text with some embedded code
+

This is a normal link: W3C

+
Some more nested elements code hyperlink
+
+ +
+
+
+
+
+

+

+    
+
    + + + + +
    + +
    +
    +
    +
    +
    + +
    + + + + + + + + + +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + + + + + + + + + +

    +
    + +
    +
    +
    +
    +
    +
    + +
    + + + + +
    +
    +
    +
    +
    + +

    +
    + +
    + + + + +
    +
    +
    +
    + +

    +
    + +
    + + + + +
    +
    +
    +
    +
    +
    + +

    +
    + +
    + + + + +
    + +
      +
    1. +
    2. +
    3. +
    4. +
    5. +
    6. +
    7. +
    8. +
    9. +
    10. +
    11. +
    12. +
    + +

    + span1 + em1 + + em2 + span2 + strong1 + em3 + span3 + span4 + strong2 + em4 +

    +
    + +
    +
    +
    +
    + +

    +

    +

    +
    + +
    +

    +

    +

    + +
    +
    +
    +
    + +
    +

    + +

    +

    + + +

    +

    + + + +

    +
    > + +
    +

    +

    +

    +

    Text node

    +

    +
    + + + +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +
    + +

    +

    +

    +
    + +
    All pseudo-element tests
    + +
    +

    +

    +

    + + +
    +
    +

    +
    +

    +
    +
    +
    +
    + + + + + + +
    + +
    +
    +
    + +
      +
    • +
    • +
    • +
    • +
    + + + + + + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    +
    +
    +
    +

    +

    +
    + +
    +
    +
    +
    +
    +
    +

    +
    +
    +
    +

    +

    +
    + +
    + + +
    +
    + + diff --git a/Tests/LibWeb/Text/expected/wpt-import/dom/nodes/ParentNode-querySelector-All.txt b/Tests/LibWeb/Text/expected/wpt-import/dom/nodes/ParentNode-querySelector-All.txt new file mode 100644 index 00000000000..b0d3625ff6a --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/dom/nodes/ParentNode-querySelector-All.txt @@ -0,0 +1,1986 @@ +Summary + +Harness status: OK + +Rerun + +Found 1975 tests + +1903 Pass +72 Fail +Details +Result Test Name MessagePass Selectors-API Test Suite: HTML +Pass Document supports querySelector +Pass Document supports querySelectorAll +Pass Document.querySelectorAll returns NodeList instance +Pass Detached Element supports querySelector +Pass Detached Element supports querySelectorAll +Pass Detached Element.querySelectorAll returns NodeList instance +Pass Fragment supports querySelector +Pass Fragment supports querySelectorAll +Pass Fragment.querySelectorAll returns NodeList instance +Pass In-document Element supports querySelector +Pass In-document Element supports querySelectorAll +Pass In-document Element.querySelectorAll returns NodeList instance +Pass Document.querySelectorAll null +Pass Document.querySelectorAll undefined +Pass Document.querySelectorAll no parameter +Pass Document.querySelector null +Pass Document.querySelector undefined +Pass Document.querySelector no parameter +Pass Document.querySelectorAll tree order +Pass Detached Element.querySelectorAll null +Pass Detached Element.querySelectorAll undefined +Pass Detached Element.querySelectorAll no parameter +Pass Detached Element.querySelector null +Pass Detached Element.querySelector undefined +Pass Detached Element.querySelector no parameter +Pass Detached Element.querySelectorAll tree order +Pass Fragment.querySelectorAll null +Pass Fragment.querySelectorAll undefined +Pass Fragment.querySelectorAll no parameter +Pass Fragment.querySelector null +Pass Fragment.querySelector undefined +Pass Fragment.querySelector no parameter +Pass Fragment.querySelectorAll tree order +Pass In-document Element.querySelectorAll null +Pass In-document Element.querySelectorAll undefined +Pass In-document Element.querySelectorAll no parameter +Pass In-document Element.querySelector null +Pass In-document Element.querySelector undefined +Pass In-document Element.querySelector no parameter +Pass In-document Element.querySelectorAll tree order +Pass Document: static NodeList +Pass Document: new NodeList +Pass Detached Element: static NodeList +Pass Detached Element: new NodeList +Pass Fragment: static NodeList +Pass Fragment: new NodeList +Pass In-document Element: static NodeList +Pass In-document Element: new NodeList +Pass Document.querySelector: Empty String: +Pass Document.querySelectorAll: Empty String: +Pass Document.querySelector: Invalid character: [ +Pass Document.querySelectorAll: Invalid character: [ +Pass Document.querySelector: Invalid character: ] +Pass Document.querySelectorAll: Invalid character: ] +Pass Document.querySelector: Invalid character: ( +Pass Document.querySelectorAll: Invalid character: ( +Pass Document.querySelector: Invalid character: ) +Pass Document.querySelectorAll: Invalid character: ) +Pass Document.querySelector: Invalid character: { +Pass Document.querySelectorAll: Invalid character: { +Pass Document.querySelector: Invalid character: } +Pass Document.querySelectorAll: Invalid character: } +Pass Document.querySelector: Invalid character: < +Pass Document.querySelectorAll: Invalid character: < +Pass Document.querySelector: Invalid character: > +Pass Document.querySelectorAll: Invalid character: > +Pass Document.querySelector: Invalid ID: # +Pass Document.querySelectorAll: Invalid ID: # +Pass Document.querySelector: Invalid group of selectors: div, +Pass Document.querySelectorAll: Invalid group of selectors: div, +Pass Document.querySelector: Invalid class: . +Pass Document.querySelectorAll: Invalid class: . +Pass Document.querySelector: Invalid class: .5cm +Pass Document.querySelectorAll: Invalid class: .5cm +Pass Document.querySelector: Invalid class: ..test +Pass Document.querySelectorAll: Invalid class: ..test +Pass Document.querySelector: Invalid class: .foo..quux +Pass Document.querySelectorAll: Invalid class: .foo..quux +Pass Document.querySelector: Invalid class: .bar. +Pass Document.querySelectorAll: Invalid class: .bar. +Pass Document.querySelector: Invalid combinator: div % address, p +Pass Document.querySelectorAll: Invalid combinator: div % address, p +Fail Document.querySelector: Invalid combinator: div ++ address, p +Fail Document.querySelectorAll: Invalid combinator: div ++ address, p +Fail Document.querySelector: Invalid combinator: div ~~ address, p +Fail Document.querySelectorAll: Invalid combinator: div ~~ address, p +Pass Document.querySelector: Invalid [att=value] selector: [*=test] +Pass Document.querySelectorAll: Invalid [att=value] selector: [*=test] +Pass Document.querySelector: Invalid [att=value] selector: [*|*=test] +Pass Document.querySelectorAll: Invalid [att=value] selector: [*|*=test] +Pass Document.querySelector: Invalid [att=value] selector: [class= space unquoted ] +Pass Document.querySelectorAll: Invalid [att=value] selector: [class= space unquoted ] +Pass Document.querySelector: Unknown pseudo-class: div:example +Pass Document.querySelectorAll: Unknown pseudo-class: div:example +Pass Document.querySelector: Unknown pseudo-class: :example +Pass Document.querySelectorAll: Unknown pseudo-class: :example +Pass Document.querySelector: Unknown pseudo-class: div:linkexample +Pass Document.querySelectorAll: Unknown pseudo-class: div:linkexample +Pass Document.querySelector: Unknown pseudo-element: div::example +Pass Document.querySelectorAll: Unknown pseudo-element: div::example +Pass Document.querySelector: Unknown pseudo-element: ::example +Pass Document.querySelectorAll: Unknown pseudo-element: ::example +Pass Document.querySelector: Invalid pseudo-element: :::before +Pass Document.querySelectorAll: Invalid pseudo-element: :::before +Pass Document.querySelector: Invalid pseudo-element: :: before +Pass Document.querySelectorAll: Invalid pseudo-element: :: before +Fail Document.querySelector: Undeclared namespace: ns|div +Fail Document.querySelectorAll: Undeclared namespace: ns|div +Fail Document.querySelector: Undeclared namespace: :not(ns|div) +Fail Document.querySelectorAll: Undeclared namespace: :not(ns|div) +Pass Document.querySelector: Invalid namespace: ^|div +Pass Document.querySelectorAll: Invalid namespace: ^|div +Pass Document.querySelector: Invalid namespace: $|div +Pass Document.querySelectorAll: Invalid namespace: $|div +Pass Document.querySelector: Relative selector: >* +Pass Document.querySelectorAll: Relative selector: >* +Pass Detached Element.querySelector: Empty String: +Pass Detached Element.querySelectorAll: Empty String: +Pass Detached Element.querySelector: Invalid character: [ +Pass Detached Element.querySelectorAll: Invalid character: [ +Pass Detached Element.querySelector: Invalid character: ] +Pass Detached Element.querySelectorAll: Invalid character: ] +Pass Detached Element.querySelector: Invalid character: ( +Pass Detached Element.querySelectorAll: Invalid character: ( +Pass Detached Element.querySelector: Invalid character: ) +Pass Detached Element.querySelectorAll: Invalid character: ) +Pass Detached Element.querySelector: Invalid character: { +Pass Detached Element.querySelectorAll: Invalid character: { +Pass Detached Element.querySelector: Invalid character: } +Pass Detached Element.querySelectorAll: Invalid character: } +Pass Detached Element.querySelector: Invalid character: < +Pass Detached Element.querySelectorAll: Invalid character: < +Pass Detached Element.querySelector: Invalid character: > +Pass Detached Element.querySelectorAll: Invalid character: > +Pass Detached Element.querySelector: Invalid ID: # +Pass Detached Element.querySelectorAll: Invalid ID: # +Pass Detached Element.querySelector: Invalid group of selectors: div, +Pass Detached Element.querySelectorAll: Invalid group of selectors: div, +Pass Detached Element.querySelector: Invalid class: . +Pass Detached Element.querySelectorAll: Invalid class: . +Pass Detached Element.querySelector: Invalid class: .5cm +Pass Detached Element.querySelectorAll: Invalid class: .5cm +Pass Detached Element.querySelector: Invalid class: ..test +Pass Detached Element.querySelectorAll: Invalid class: ..test +Pass Detached Element.querySelector: Invalid class: .foo..quux +Pass Detached Element.querySelectorAll: Invalid class: .foo..quux +Pass Detached Element.querySelector: Invalid class: .bar. +Pass Detached Element.querySelectorAll: Invalid class: .bar. +Pass Detached Element.querySelector: Invalid combinator: div % address, p +Pass Detached Element.querySelectorAll: Invalid combinator: div % address, p +Fail Detached Element.querySelector: Invalid combinator: div ++ address, p +Fail Detached Element.querySelectorAll: Invalid combinator: div ++ address, p +Fail Detached Element.querySelector: Invalid combinator: div ~~ address, p +Fail Detached Element.querySelectorAll: Invalid combinator: div ~~ address, p +Pass Detached Element.querySelector: Invalid [att=value] selector: [*=test] +Pass Detached Element.querySelectorAll: Invalid [att=value] selector: [*=test] +Pass Detached Element.querySelector: Invalid [att=value] selector: [*|*=test] +Pass Detached Element.querySelectorAll: Invalid [att=value] selector: [*|*=test] +Pass Detached Element.querySelector: Invalid [att=value] selector: [class= space unquoted ] +Pass Detached Element.querySelectorAll: Invalid [att=value] selector: [class= space unquoted ] +Pass Detached Element.querySelector: Unknown pseudo-class: div:example +Pass Detached Element.querySelectorAll: Unknown pseudo-class: div:example +Pass Detached Element.querySelector: Unknown pseudo-class: :example +Pass Detached Element.querySelectorAll: Unknown pseudo-class: :example +Pass Detached Element.querySelector: Unknown pseudo-class: div:linkexample +Pass Detached Element.querySelectorAll: Unknown pseudo-class: div:linkexample +Pass Detached Element.querySelector: Unknown pseudo-element: div::example +Pass Detached Element.querySelectorAll: Unknown pseudo-element: div::example +Pass Detached Element.querySelector: Unknown pseudo-element: ::example +Pass Detached Element.querySelectorAll: Unknown pseudo-element: ::example +Pass Detached Element.querySelector: Invalid pseudo-element: :::before +Pass Detached Element.querySelectorAll: Invalid pseudo-element: :::before +Pass Detached Element.querySelector: Invalid pseudo-element: :: before +Pass Detached Element.querySelectorAll: Invalid pseudo-element: :: before +Fail Detached Element.querySelector: Undeclared namespace: ns|div +Fail Detached Element.querySelectorAll: Undeclared namespace: ns|div +Fail Detached Element.querySelector: Undeclared namespace: :not(ns|div) +Fail Detached Element.querySelectorAll: Undeclared namespace: :not(ns|div) +Pass Detached Element.querySelector: Invalid namespace: ^|div +Pass Detached Element.querySelectorAll: Invalid namespace: ^|div +Pass Detached Element.querySelector: Invalid namespace: $|div +Pass Detached Element.querySelectorAll: Invalid namespace: $|div +Pass Detached Element.querySelector: Relative selector: >* +Pass Detached Element.querySelectorAll: Relative selector: >* +Pass Fragment.querySelector: Empty String: +Pass Fragment.querySelectorAll: Empty String: +Pass Fragment.querySelector: Invalid character: [ +Pass Fragment.querySelectorAll: Invalid character: [ +Pass Fragment.querySelector: Invalid character: ] +Pass Fragment.querySelectorAll: Invalid character: ] +Pass Fragment.querySelector: Invalid character: ( +Pass Fragment.querySelectorAll: Invalid character: ( +Pass Fragment.querySelector: Invalid character: ) +Pass Fragment.querySelectorAll: Invalid character: ) +Pass Fragment.querySelector: Invalid character: { +Pass Fragment.querySelectorAll: Invalid character: { +Pass Fragment.querySelector: Invalid character: } +Pass Fragment.querySelectorAll: Invalid character: } +Pass Fragment.querySelector: Invalid character: < +Pass Fragment.querySelectorAll: Invalid character: < +Pass Fragment.querySelector: Invalid character: > +Pass Fragment.querySelectorAll: Invalid character: > +Pass Fragment.querySelector: Invalid ID: # +Pass Fragment.querySelectorAll: Invalid ID: # +Pass Fragment.querySelector: Invalid group of selectors: div, +Pass Fragment.querySelectorAll: Invalid group of selectors: div, +Pass Fragment.querySelector: Invalid class: . +Pass Fragment.querySelectorAll: Invalid class: . +Pass Fragment.querySelector: Invalid class: .5cm +Pass Fragment.querySelectorAll: Invalid class: .5cm +Pass Fragment.querySelector: Invalid class: ..test +Pass Fragment.querySelectorAll: Invalid class: ..test +Pass Fragment.querySelector: Invalid class: .foo..quux +Pass Fragment.querySelectorAll: Invalid class: .foo..quux +Pass Fragment.querySelector: Invalid class: .bar. +Pass Fragment.querySelectorAll: Invalid class: .bar. +Pass Fragment.querySelector: Invalid combinator: div % address, p +Pass Fragment.querySelectorAll: Invalid combinator: div % address, p +Fail Fragment.querySelector: Invalid combinator: div ++ address, p +Fail Fragment.querySelectorAll: Invalid combinator: div ++ address, p +Fail Fragment.querySelector: Invalid combinator: div ~~ address, p +Fail Fragment.querySelectorAll: Invalid combinator: div ~~ address, p +Pass Fragment.querySelector: Invalid [att=value] selector: [*=test] +Pass Fragment.querySelectorAll: Invalid [att=value] selector: [*=test] +Pass Fragment.querySelector: Invalid [att=value] selector: [*|*=test] +Pass Fragment.querySelectorAll: Invalid [att=value] selector: [*|*=test] +Pass Fragment.querySelector: Invalid [att=value] selector: [class= space unquoted ] +Pass Fragment.querySelectorAll: Invalid [att=value] selector: [class= space unquoted ] +Pass Fragment.querySelector: Unknown pseudo-class: div:example +Pass Fragment.querySelectorAll: Unknown pseudo-class: div:example +Pass Fragment.querySelector: Unknown pseudo-class: :example +Pass Fragment.querySelectorAll: Unknown pseudo-class: :example +Pass Fragment.querySelector: Unknown pseudo-class: div:linkexample +Pass Fragment.querySelectorAll: Unknown pseudo-class: div:linkexample +Pass Fragment.querySelector: Unknown pseudo-element: div::example +Pass Fragment.querySelectorAll: Unknown pseudo-element: div::example +Pass Fragment.querySelector: Unknown pseudo-element: ::example +Pass Fragment.querySelectorAll: Unknown pseudo-element: ::example +Pass Fragment.querySelector: Invalid pseudo-element: :::before +Pass Fragment.querySelectorAll: Invalid pseudo-element: :::before +Pass Fragment.querySelector: Invalid pseudo-element: :: before +Pass Fragment.querySelectorAll: Invalid pseudo-element: :: before +Fail Fragment.querySelector: Undeclared namespace: ns|div +Fail Fragment.querySelectorAll: Undeclared namespace: ns|div +Fail Fragment.querySelector: Undeclared namespace: :not(ns|div) +Fail Fragment.querySelectorAll: Undeclared namespace: :not(ns|div) +Pass Fragment.querySelector: Invalid namespace: ^|div +Pass Fragment.querySelectorAll: Invalid namespace: ^|div +Pass Fragment.querySelector: Invalid namespace: $|div +Pass Fragment.querySelectorAll: Invalid namespace: $|div +Pass Fragment.querySelector: Relative selector: >* +Pass Fragment.querySelectorAll: Relative selector: >* +Pass In-document Element.querySelector: Empty String: +Pass In-document Element.querySelectorAll: Empty String: +Pass In-document Element.querySelector: Invalid character: [ +Pass In-document Element.querySelectorAll: Invalid character: [ +Pass In-document Element.querySelector: Invalid character: ] +Pass In-document Element.querySelectorAll: Invalid character: ] +Pass In-document Element.querySelector: Invalid character: ( +Pass In-document Element.querySelectorAll: Invalid character: ( +Pass In-document Element.querySelector: Invalid character: ) +Pass In-document Element.querySelectorAll: Invalid character: ) +Pass In-document Element.querySelector: Invalid character: { +Pass In-document Element.querySelectorAll: Invalid character: { +Pass In-document Element.querySelector: Invalid character: } +Pass In-document Element.querySelectorAll: Invalid character: } +Pass In-document Element.querySelector: Invalid character: < +Pass In-document Element.querySelectorAll: Invalid character: < +Pass In-document Element.querySelector: Invalid character: > +Pass In-document Element.querySelectorAll: Invalid character: > +Pass In-document Element.querySelector: Invalid ID: # +Pass In-document Element.querySelectorAll: Invalid ID: # +Pass In-document Element.querySelector: Invalid group of selectors: div, +Pass In-document Element.querySelectorAll: Invalid group of selectors: div, +Pass In-document Element.querySelector: Invalid class: . +Pass In-document Element.querySelectorAll: Invalid class: . +Pass In-document Element.querySelector: Invalid class: .5cm +Pass In-document Element.querySelectorAll: Invalid class: .5cm +Pass In-document Element.querySelector: Invalid class: ..test +Pass In-document Element.querySelectorAll: Invalid class: ..test +Pass In-document Element.querySelector: Invalid class: .foo..quux +Pass In-document Element.querySelectorAll: Invalid class: .foo..quux +Pass In-document Element.querySelector: Invalid class: .bar. +Pass In-document Element.querySelectorAll: Invalid class: .bar. +Pass In-document Element.querySelector: Invalid combinator: div % address, p +Pass In-document Element.querySelectorAll: Invalid combinator: div % address, p +Fail In-document Element.querySelector: Invalid combinator: div ++ address, p +Fail In-document Element.querySelectorAll: Invalid combinator: div ++ address, p +Fail In-document Element.querySelector: Invalid combinator: div ~~ address, p +Fail In-document Element.querySelectorAll: Invalid combinator: div ~~ address, p +Pass In-document Element.querySelector: Invalid [att=value] selector: [*=test] +Pass In-document Element.querySelectorAll: Invalid [att=value] selector: [*=test] +Pass In-document Element.querySelector: Invalid [att=value] selector: [*|*=test] +Pass In-document Element.querySelectorAll: Invalid [att=value] selector: [*|*=test] +Pass In-document Element.querySelector: Invalid [att=value] selector: [class= space unquoted ] +Pass In-document Element.querySelectorAll: Invalid [att=value] selector: [class= space unquoted ] +Pass In-document Element.querySelector: Unknown pseudo-class: div:example +Pass In-document Element.querySelectorAll: Unknown pseudo-class: div:example +Pass In-document Element.querySelector: Unknown pseudo-class: :example +Pass In-document Element.querySelectorAll: Unknown pseudo-class: :example +Pass In-document Element.querySelector: Unknown pseudo-class: div:linkexample +Pass In-document Element.querySelectorAll: Unknown pseudo-class: div:linkexample +Pass In-document Element.querySelector: Unknown pseudo-element: div::example +Pass In-document Element.querySelectorAll: Unknown pseudo-element: div::example +Pass In-document Element.querySelector: Unknown pseudo-element: ::example +Pass In-document Element.querySelectorAll: Unknown pseudo-element: ::example +Pass In-document Element.querySelector: Invalid pseudo-element: :::before +Pass In-document Element.querySelectorAll: Invalid pseudo-element: :::before +Pass In-document Element.querySelector: Invalid pseudo-element: :: before +Pass In-document Element.querySelectorAll: Invalid pseudo-element: :: before +Fail In-document Element.querySelector: Undeclared namespace: ns|div +Fail In-document Element.querySelectorAll: Undeclared namespace: ns|div +Fail In-document Element.querySelector: Undeclared namespace: :not(ns|div) +Fail In-document Element.querySelectorAll: Undeclared namespace: :not(ns|div) +Pass In-document Element.querySelector: Invalid namespace: ^|div +Pass In-document Element.querySelectorAll: Invalid namespace: ^|div +Pass In-document Element.querySelector: Invalid namespace: $|div +Pass In-document Element.querySelectorAll: Invalid namespace: $|div +Pass In-document Element.querySelector: Relative selector: >* +Pass In-document Element.querySelectorAll: Relative selector: >* +Pass Empty Element.querySelector: Empty String: +Pass Empty Element.querySelectorAll: Empty String: +Pass Empty Element.querySelector: Invalid character: [ +Pass Empty Element.querySelectorAll: Invalid character: [ +Pass Empty Element.querySelector: Invalid character: ] +Pass Empty Element.querySelectorAll: Invalid character: ] +Pass Empty Element.querySelector: Invalid character: ( +Pass Empty Element.querySelectorAll: Invalid character: ( +Pass Empty Element.querySelector: Invalid character: ) +Pass Empty Element.querySelectorAll: Invalid character: ) +Pass Empty Element.querySelector: Invalid character: { +Pass Empty Element.querySelectorAll: Invalid character: { +Pass Empty Element.querySelector: Invalid character: } +Pass Empty Element.querySelectorAll: Invalid character: } +Pass Empty Element.querySelector: Invalid character: < +Pass Empty Element.querySelectorAll: Invalid character: < +Pass Empty Element.querySelector: Invalid character: > +Pass Empty Element.querySelectorAll: Invalid character: > +Pass Empty Element.querySelector: Invalid ID: # +Pass Empty Element.querySelectorAll: Invalid ID: # +Pass Empty Element.querySelector: Invalid group of selectors: div, +Pass Empty Element.querySelectorAll: Invalid group of selectors: div, +Pass Empty Element.querySelector: Invalid class: . +Pass Empty Element.querySelectorAll: Invalid class: . +Pass Empty Element.querySelector: Invalid class: .5cm +Pass Empty Element.querySelectorAll: Invalid class: .5cm +Pass Empty Element.querySelector: Invalid class: ..test +Pass Empty Element.querySelectorAll: Invalid class: ..test +Pass Empty Element.querySelector: Invalid class: .foo..quux +Pass Empty Element.querySelectorAll: Invalid class: .foo..quux +Pass Empty Element.querySelector: Invalid class: .bar. +Pass Empty Element.querySelectorAll: Invalid class: .bar. +Pass Empty Element.querySelector: Invalid combinator: div % address, p +Pass Empty Element.querySelectorAll: Invalid combinator: div % address, p +Fail Empty Element.querySelector: Invalid combinator: div ++ address, p +Fail Empty Element.querySelectorAll: Invalid combinator: div ++ address, p +Fail Empty Element.querySelector: Invalid combinator: div ~~ address, p +Fail Empty Element.querySelectorAll: Invalid combinator: div ~~ address, p +Pass Empty Element.querySelector: Invalid [att=value] selector: [*=test] +Pass Empty Element.querySelectorAll: Invalid [att=value] selector: [*=test] +Pass Empty Element.querySelector: Invalid [att=value] selector: [*|*=test] +Pass Empty Element.querySelectorAll: Invalid [att=value] selector: [*|*=test] +Pass Empty Element.querySelector: Invalid [att=value] selector: [class= space unquoted ] +Pass Empty Element.querySelectorAll: Invalid [att=value] selector: [class= space unquoted ] +Pass Empty Element.querySelector: Unknown pseudo-class: div:example +Pass Empty Element.querySelectorAll: Unknown pseudo-class: div:example +Pass Empty Element.querySelector: Unknown pseudo-class: :example +Pass Empty Element.querySelectorAll: Unknown pseudo-class: :example +Pass Empty Element.querySelector: Unknown pseudo-class: div:linkexample +Pass Empty Element.querySelectorAll: Unknown pseudo-class: div:linkexample +Pass Empty Element.querySelector: Unknown pseudo-element: div::example +Pass Empty Element.querySelectorAll: Unknown pseudo-element: div::example +Pass Empty Element.querySelector: Unknown pseudo-element: ::example +Pass Empty Element.querySelectorAll: Unknown pseudo-element: ::example +Pass Empty Element.querySelector: Invalid pseudo-element: :::before +Pass Empty Element.querySelectorAll: Invalid pseudo-element: :::before +Pass Empty Element.querySelector: Invalid pseudo-element: :: before +Pass Empty Element.querySelectorAll: Invalid pseudo-element: :: before +Fail Empty Element.querySelector: Undeclared namespace: ns|div +Fail Empty Element.querySelectorAll: Undeclared namespace: ns|div +Fail Empty Element.querySelector: Undeclared namespace: :not(ns|div) +Fail Empty Element.querySelectorAll: Undeclared namespace: :not(ns|div) +Pass Empty Element.querySelector: Invalid namespace: ^|div +Pass Empty Element.querySelectorAll: Invalid namespace: ^|div +Pass Empty Element.querySelector: Invalid namespace: $|div +Pass Empty Element.querySelectorAll: Invalid namespace: $|div +Pass Empty Element.querySelector: Relative selector: >* +Pass Empty Element.querySelectorAll: Relative selector: >* +Pass Document.querySelectorAll: Type selector, matching html element: html +Pass Document.querySelector: Type selector, matching html element: html +Pass Document.querySelectorAll: Type selector, matching body element: body +Pass Document.querySelector: Type selector, matching body element: body +Pass Document.querySelectorAll: Universal selector, matching all children of element with specified ID: #universal>* +Pass Document.querySelector: Universal selector, matching all children of element with specified ID: #universal>* +Pass Document.querySelectorAll: Universal selector, matching all grandchildren of element with specified ID: #universal>*>* +Pass Document.querySelector: Universal selector, matching all grandchildren of element with specified ID: #universal>*>* +Pass Document.querySelectorAll: Universal selector, matching all children of empty element with specified ID: #empty>* +Pass Document.querySelector: Universal selector, matching all children of empty element with specified ID: #empty>* +Pass Document.querySelectorAll: Universal selector, matching all descendants of element with specified ID: #universal * +Pass Document.querySelector: Universal selector, matching all descendants of element with specified ID: #universal * +Pass Document.querySelectorAll: Attribute presence selector, matching align attribute with value: .attr-presence-div1[align] +Pass Document.querySelector: Attribute presence selector, matching align attribute with value: .attr-presence-div1[align] +Pass Document.querySelectorAll: Attribute presence selector, matching align attribute with empty value: .attr-presence-div2[align] +Pass Document.querySelector: Attribute presence selector, matching align attribute with empty value: .attr-presence-div2[align] +Fail Document.querySelectorAll: Attribute presence selector, matching title attribute, case insensitivity: #attr-presence [*|TiTlE] +Fail Document.querySelector: Attribute presence selector, matching title attribute, case insensitivity: #attr-presence [*|TiTlE] +Pass Document.querySelectorAll: Attribute presence selector, matching custom data-* attribute: [data-attr-presence] +Pass Document.querySelector: Attribute presence selector, matching custom data-* attribute: [data-attr-presence] +Pass Document.querySelectorAll: Attribute presence selector, not matching attribute with similar name: .attr-presence-div3[align], .attr-presence-div4[align] +Pass Document.querySelector: Attribute presence selector, not matching attribute with similar name: .attr-presence-div3[align], .attr-presence-div4[align] +Pass Document.querySelectorAll: Attribute presence selector, matching attribute with non-ASCII characters: ul[data-中文] +Pass Document.querySelector: Attribute presence selector, matching attribute with non-ASCII characters: ul[data-中文] +Pass Document.querySelectorAll: Attribute presence selector, not matching default option without selected attribute: #attr-presence-select1 option[selected] +Pass Document.querySelector: Attribute presence selector, not matching default option without selected attribute: #attr-presence-select1 option[selected] +Pass Document.querySelectorAll: Attribute presence selector, matching option with selected attribute: #attr-presence-select2 option[selected] +Pass Document.querySelector: Attribute presence selector, matching option with selected attribute: #attr-presence-select2 option[selected] +Pass Document.querySelectorAll: Attribute presence selector, matching multiple options with selected attributes: #attr-presence-select3 option[selected] +Pass Document.querySelector: Attribute presence selector, matching multiple options with selected attributes: #attr-presence-select3 option[selected] +Pass Document.querySelectorAll: Attribute value selector, matching align attribute with value: #attr-value [align="center"] +Pass Document.querySelector: Attribute value selector, matching align attribute with value: #attr-value [align="center"] +Pass Document.querySelectorAll: Attribute value selector, matching align attribute with value, unclosed bracket: #attr-value [align="center" +Pass Document.querySelector: Attribute value selector, matching align attribute with value, unclosed bracket: #attr-value [align="center" +Pass Document.querySelectorAll: Attribute value selector, matching align attribute with empty value: #attr-value [align=""] +Pass Document.querySelector: Attribute value selector, matching align attribute with empty value: #attr-value [align=""] +Pass Document.querySelectorAll: Attribute value selector, not matching align attribute with partial value: #attr-value [align="c"] +Pass Document.querySelector: Attribute value selector, not matching align attribute with partial value: #attr-value [align="c"] +Pass Document.querySelectorAll: Attribute value selector, not matching align attribute with incorrect value: #attr-value [align="centera"] +Pass Document.querySelector: Attribute value selector, not matching align attribute with incorrect value: #attr-value [align="centera"] +Pass Document.querySelectorAll: Attribute value selector, matching custom data-* attribute with unicode escaped value: [data-attr-value="\e9"] +Pass Document.querySelector: Attribute value selector, matching custom data-* attribute with unicode escaped value: [data-attr-value="\e9"] +Pass Document.querySelectorAll: Attribute value selector, matching custom data-* attribute with escaped character: [data-attr-value_foo="\e9"] +Pass Document.querySelector: Attribute value selector, matching custom data-* attribute with escaped character: [data-attr-value_foo="\e9"] +Pass Document.querySelectorAll: Attribute value selector with single-quoted value, matching multiple inputs with type attributes: #attr-value input[type='hidden'],#attr-value input[type='radio'] +Pass Document.querySelector: Attribute value selector with single-quoted value, matching multiple inputs with type attributes: #attr-value input[type='hidden'],#attr-value input[type='radio'] +Pass Document.querySelectorAll: Attribute value selector with double-quoted value, matching multiple inputs with type attributes: #attr-value input[type="hidden"],#attr-value input[type='radio'] +Pass Document.querySelector: Attribute value selector with double-quoted value, matching multiple inputs with type attributes: #attr-value input[type="hidden"],#attr-value input[type='radio'] +Pass Document.querySelectorAll: Attribute value selector with unquoted value, matching multiple inputs with type attributes: #attr-value input[type=hidden],#attr-value input[type=radio] +Pass Document.querySelector: Attribute value selector with unquoted value, matching multiple inputs with type attributes: #attr-value input[type=hidden],#attr-value input[type=radio] +Pass Document.querySelectorAll: Attribute value selector, matching attribute with value using non-ASCII characters: [data-attr-value=中文] +Pass Document.querySelector: Attribute value selector, matching attribute with value using non-ASCII characters: [data-attr-value=中文] +Pass Document.querySelectorAll: Attribute whitespace-separated list selector, matching class attribute with value: #attr-whitespace [class~="div1"] +Pass Document.querySelector: Attribute whitespace-separated list selector, matching class attribute with value: #attr-whitespace [class~="div1"] +Pass Document.querySelectorAll: Attribute whitespace-separated list selector, not matching class attribute with empty value: #attr-whitespace [class~=""] +Pass Document.querySelector: Attribute whitespace-separated list selector, not matching class attribute with empty value: #attr-whitespace [class~=""] +Pass Document.querySelectorAll: Attribute whitespace-separated list selector, not matching class attribute with partial value: [data-attr-whitespace~="div"] +Pass Document.querySelector: Attribute whitespace-separated list selector, not matching class attribute with partial value: [data-attr-whitespace~="div"] +Pass Document.querySelectorAll: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value: [data-attr-whitespace~="\0000e9"] +Pass Document.querySelector: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value: [data-attr-whitespace~="\0000e9"] +Pass Document.querySelectorAll: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character: [data-attr-whitespace_foo~="\e9"] +Pass Document.querySelector: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character: [data-attr-whitespace_foo~="\e9"] +Pass Document.querySelectorAll: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +Pass Document.querySelector: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +Pass Document.querySelectorAll: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +Pass Document.querySelector: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +Pass Document.querySelectorAll: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +Pass Document.querySelector: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +Pass Document.querySelectorAll: Attribute whitespace-separated list selector with double-quoted value, not matching value with space: #attr-whitespace a[rel~="book mark"] +Pass Document.querySelector: Attribute whitespace-separated list selector with double-quoted value, not matching value with space: #attr-whitespace a[rel~="book mark"] +Pass Document.querySelectorAll: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters: #attr-whitespace [title~=中文] +Pass Document.querySelector: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters: #attr-whitespace [title~=中文] +Pass Document.querySelectorAll: Attribute hyphen-separated list selector, not matching unspecified lang attribute: #attr-hyphen-div1[lang|="en"] +Pass Document.querySelector: Attribute hyphen-separated list selector, not matching unspecified lang attribute: #attr-hyphen-div1[lang|="en"] +Pass Document.querySelectorAll: Attribute hyphen-separated list selector, matching lang attribute with exact value: #attr-hyphen-div2[lang|="fr"] +Pass Document.querySelector: Attribute hyphen-separated list selector, matching lang attribute with exact value: #attr-hyphen-div2[lang|="fr"] +Pass Document.querySelectorAll: Attribute hyphen-separated list selector, matching lang attribute with partial value: #attr-hyphen-div3[lang|="en"] +Pass Document.querySelector: Attribute hyphen-separated list selector, matching lang attribute with partial value: #attr-hyphen-div3[lang|="en"] +Pass Document.querySelectorAll: Attribute hyphen-separated list selector, not matching incorrect value: #attr-hyphen-div4[lang|="es-AR"] +Pass Document.querySelector: Attribute hyphen-separated list selector, not matching incorrect value: #attr-hyphen-div4[lang|="es-AR"] +Pass Document.querySelectorAll: Attribute begins with selector, matching href attributes beginning with specified substring: #attr-begins a[href^="http://www"] +Pass Document.querySelector: Attribute begins with selector, matching href attributes beginning with specified substring: #attr-begins a[href^="http://www"] +Pass Document.querySelectorAll: Attribute begins with selector, matching lang attributes beginning with specified substring, : #attr-begins [lang^="en-"] +Pass Document.querySelector: Attribute begins with selector, matching lang attributes beginning with specified substring, : #attr-begins [lang^="en-"] +Pass Document.querySelectorAll: Attribute begins with selector, not matching class attribute with empty value: #attr-begins [class^=""] +Pass Document.querySelector: Attribute begins with selector, not matching class attribute with empty value: #attr-begins [class^=""] +Pass Document.querySelectorAll: Attribute begins with selector, not matching class attribute not beginning with specified substring: #attr-begins [class^=apple] +Pass Document.querySelector: Attribute begins with selector, not matching class attribute not beginning with specified substring: #attr-begins [class^=apple] +Pass Document.querySelectorAll: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=' apple'] +Pass Document.querySelector: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=' apple'] +Pass Document.querySelectorAll: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=" apple"] +Pass Document.querySelector: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=" apple"] +Pass Document.querySelectorAll: Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring: #attr-begins [class^= apple] +Pass Document.querySelector: Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring: #attr-begins [class^= apple] +Pass Document.querySelectorAll: Attribute ends with selector, matching href attributes ending with specified substring: #attr-ends a[href$=".org"] +Pass Document.querySelector: Attribute ends with selector, matching href attributes ending with specified substring: #attr-ends a[href$=".org"] +Pass Document.querySelectorAll: Attribute ends with selector, matching lang attributes ending with specified substring, : #attr-ends [lang$="-CH"] +Pass Document.querySelector: Attribute ends with selector, matching lang attributes ending with specified substring, : #attr-ends [lang$="-CH"] +Pass Document.querySelectorAll: Attribute ends with selector, not matching class attribute with empty value: #attr-ends [class$=""] +Pass Document.querySelector: Attribute ends with selector, not matching class attribute with empty value: #attr-ends [class$=""] +Pass Document.querySelectorAll: Attribute ends with selector, not matching class attribute not ending with specified substring: #attr-ends [class$=apple] +Pass Document.querySelector: Attribute ends with selector, not matching class attribute not ending with specified substring: #attr-ends [class$=apple] +Pass Document.querySelectorAll: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring: #attr-ends [class$='apple '] +Pass Document.querySelector: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring: #attr-ends [class$='apple '] +Pass Document.querySelectorAll: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring: #attr-ends [class$="apple "] +Pass Document.querySelector: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring: #attr-ends [class$="apple "] +Pass Document.querySelectorAll: Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring: #attr-ends [class$=apple ] +Pass Document.querySelector: Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring: #attr-ends [class$=apple ] +Pass Document.querySelectorAll: Attribute contains selector, matching href attributes beginning with specified substring: #attr-contains a[href*="http://www"] +Pass Document.querySelector: Attribute contains selector, matching href attributes beginning with specified substring: #attr-contains a[href*="http://www"] +Pass Document.querySelectorAll: Attribute contains selector, matching href attributes ending with specified substring: #attr-contains a[href*=".org"] +Pass Document.querySelector: Attribute contains selector, matching href attributes ending with specified substring: #attr-contains a[href*=".org"] +Pass Document.querySelectorAll: Attribute contains selector, matching href attributes containing specified substring: #attr-contains a[href*=".example."] +Pass Document.querySelector: Attribute contains selector, matching href attributes containing specified substring: #attr-contains a[href*=".example."] +Pass Document.querySelectorAll: Attribute contains selector, matching lang attributes beginning with specified substring, : #attr-contains [lang*="en-"] +Pass Document.querySelector: Attribute contains selector, matching lang attributes beginning with specified substring, : #attr-contains [lang*="en-"] +Pass Document.querySelectorAll: Attribute contains selector, matching lang attributes ending with specified substring, : #attr-contains [lang*="-CH"] +Pass Document.querySelector: Attribute contains selector, matching lang attributes ending with specified substring, : #attr-contains [lang*="-CH"] +Pass Document.querySelectorAll: Attribute contains selector, not matching class attribute with empty value: #attr-contains [class*=""] +Pass Document.querySelector: Attribute contains selector, not matching class attribute with empty value: #attr-contains [class*=""] +Pass Document.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=' apple'] +Pass Document.querySelector: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=' apple'] +Pass Document.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring: #attr-contains [class*='orange '] +Pass Document.querySelector: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring: #attr-contains [class*='orange '] +Pass Document.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute containing specified substring: #attr-contains [class*='ple banana ora'] +Pass Document.querySelector: Attribute contains selector with single-quoted value, matching class attribute containing specified substring: #attr-contains [class*='ple banana ora'] +Pass Document.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=" apple"] +Pass Document.querySelector: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=" apple"] +Pass Document.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring: #attr-contains [class*="orange "] +Pass Document.querySelector: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring: #attr-contains [class*="orange "] +Pass Document.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute containing specified substring: #attr-contains [class*="ple banana ora"] +Pass Document.querySelector: Attribute contains selector with double-quoted value, matching class attribute containing specified substring: #attr-contains [class*="ple banana ora"] +Pass Document.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring: #attr-contains [class*= apple] +Pass Document.querySelector: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring: #attr-contains [class*= apple] +Pass Document.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute ending with specified substring: #attr-contains [class*=orange ] +Pass Document.querySelector: Attribute contains selector with unquoted value, matching class attribute ending with specified substring: #attr-contains [class*=orange ] +Pass Document.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute containing specified substring: #attr-contains [class*= banana ] +Pass Document.querySelector: Attribute contains selector with unquoted value, matching class attribute containing specified substring: #attr-contains [class*= banana ] +Pass Document.querySelectorAll: :root pseudo-class selector, matching document root element: :root +Pass Document.querySelector: :root pseudo-class selector, matching document root element: :root +Pass Document.querySelectorAll: :nth-child selector, matching the third child element: #pseudo-nth-table1 :nth-child(3) +Pass Document.querySelector: :nth-child selector, matching the third child element: #pseudo-nth-table1 :nth-child(3) +Pass Document.querySelectorAll: :nth-child selector, matching every third child element: #pseudo-nth li:nth-child(3n) +Pass Document.querySelector: :nth-child selector, matching every third child element: #pseudo-nth li:nth-child(3n) +Pass Document.querySelectorAll: :nth-child selector, matching every second child element, starting from the fourth: #pseudo-nth li:nth-child(2n+4) +Pass Document.querySelector: :nth-child selector, matching every second child element, starting from the fourth: #pseudo-nth li:nth-child(2n+4) +Pass Document.querySelectorAll: :nth-child selector, matching every fourth child element, starting from the third: #pseudo-nth-p1 :nth-child(4n-1) +Pass Document.querySelector: :nth-child selector, matching every fourth child element, starting from the third: #pseudo-nth-p1 :nth-child(4n-1) +Pass Document.querySelectorAll: :nth-last-child selector, matching the third last child element: #pseudo-nth-table1 :nth-last-child(3) +Pass Document.querySelector: :nth-last-child selector, matching the third last child element: #pseudo-nth-table1 :nth-last-child(3) +Pass Document.querySelectorAll: :nth-last-child selector, matching every third child element from the end: #pseudo-nth li:nth-last-child(3n) +Pass Document.querySelector: :nth-last-child selector, matching every third child element from the end: #pseudo-nth li:nth-last-child(3n) +Pass Document.querySelectorAll: :nth-last-child selector, matching every second child element from the end, starting from the fourth last: #pseudo-nth li:nth-last-child(2n+4) +Pass Document.querySelector: :nth-last-child selector, matching every second child element from the end, starting from the fourth last: #pseudo-nth li:nth-last-child(2n+4) +Pass Document.querySelectorAll: :nth-last-child selector, matching every fourth element from the end, starting from the third last: #pseudo-nth-p1 :nth-last-child(4n-1) +Pass Document.querySelector: :nth-last-child selector, matching every fourth element from the end, starting from the third last: #pseudo-nth-p1 :nth-last-child(4n-1) +Pass Document.querySelectorAll: :nth-of-type selector, matching the third em element: #pseudo-nth-p1 em:nth-of-type(3) +Pass Document.querySelector: :nth-of-type selector, matching the third em element: #pseudo-nth-p1 em:nth-of-type(3) +Pass Document.querySelectorAll: :nth-of-type selector, matching every second element of their type: #pseudo-nth-p1 :nth-of-type(2n) +Pass Document.querySelector: :nth-of-type selector, matching every second element of their type: #pseudo-nth-p1 :nth-of-type(2n) +Pass Document.querySelectorAll: :nth-of-type selector, matching every second elemetn of their type, starting from the first: #pseudo-nth-p1 span:nth-of-type(2n-1) +Pass Document.querySelector: :nth-of-type selector, matching every second elemetn of their type, starting from the first: #pseudo-nth-p1 span:nth-of-type(2n-1) +Pass Document.querySelectorAll: :nth-last-of-type selector, matching the third last em element: #pseudo-nth-p1 em:nth-last-of-type(3) +Pass Document.querySelector: :nth-last-of-type selector, matching the third last em element: #pseudo-nth-p1 em:nth-last-of-type(3) +Pass Document.querySelectorAll: :nth-last-of-type selector, matching every second last element of their type: #pseudo-nth-p1 :nth-last-of-type(2n) +Pass Document.querySelector: :nth-last-of-type selector, matching every second last element of their type: #pseudo-nth-p1 :nth-last-of-type(2n) +Pass Document.querySelectorAll: :nth-last-of-type selector, matching every second last element of their type, starting from the last: #pseudo-nth-p1 span:nth-last-of-type(2n-1) +Pass Document.querySelector: :nth-last-of-type selector, matching every second last element of their type, starting from the last: #pseudo-nth-p1 span:nth-last-of-type(2n-1) +Pass Document.querySelectorAll: :first-of-type selector, matching the first em element: #pseudo-nth-p1 em:first-of-type +Pass Document.querySelector: :first-of-type selector, matching the first em element: #pseudo-nth-p1 em:first-of-type +Pass Document.querySelectorAll: :first-of-type selector, matching the first of every type of element: #pseudo-nth-p1 :first-of-type +Pass Document.querySelector: :first-of-type selector, matching the first of every type of element: #pseudo-nth-p1 :first-of-type +Pass Document.querySelectorAll: :first-of-type selector, matching the first td element in each table row: #pseudo-nth-table1 tr :first-of-type +Pass Document.querySelector: :first-of-type selector, matching the first td element in each table row: #pseudo-nth-table1 tr :first-of-type +Pass Document.querySelectorAll: :last-of-type selector, matching the last em elemnet: #pseudo-nth-p1 em:last-of-type +Pass Document.querySelector: :last-of-type selector, matching the last em elemnet: #pseudo-nth-p1 em:last-of-type +Pass Document.querySelectorAll: :last-of-type selector, matching the last of every type of element: #pseudo-nth-p1 :last-of-type +Pass Document.querySelector: :last-of-type selector, matching the last of every type of element: #pseudo-nth-p1 :last-of-type +Pass Document.querySelectorAll: :last-of-type selector, matching the last td element in each table row: #pseudo-nth-table1 tr :last-of-type +Pass Document.querySelector: :last-of-type selector, matching the last td element in each table row: #pseudo-nth-table1 tr :last-of-type +Pass Document.querySelectorAll: :first-child pseudo-class selector, matching first child div element: #pseudo-first-child div:first-child +Pass Document.querySelector: :first-child pseudo-class selector, matching first child div element: #pseudo-first-child div:first-child +Pass Document.querySelectorAll: :first-child pseudo-class selector, doesn't match non-first-child elements: .pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child +Pass Document.querySelector: :first-child pseudo-class selector, doesn't match non-first-child elements: .pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child +Pass Document.querySelectorAll: :first-child pseudo-class selector, matching first-child of multiple elements: #pseudo-first-child span:first-child +Pass Document.querySelector: :first-child pseudo-class selector, matching first-child of multiple elements: #pseudo-first-child span:first-child +Pass Document.querySelectorAll: :last-child pseudo-class selector, matching last child div element: #pseudo-last-child div:last-child +Pass Document.querySelector: :last-child pseudo-class selector, matching last child div element: #pseudo-last-child div:last-child +Pass Document.querySelectorAll: :last-child pseudo-class selector, doesn't match non-last-child elements: .pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child +Pass Document.querySelector: :last-child pseudo-class selector, doesn't match non-last-child elements: .pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child +Pass Document.querySelectorAll: :last-child pseudo-class selector, matching first-child of multiple elements: #pseudo-last-child span:last-child +Pass Document.querySelector: :last-child pseudo-class selector, matching first-child of multiple elements: #pseudo-last-child span:last-child +Pass Document.querySelectorAll: :pseudo-only-child pseudo-class selector, matching all only-child elements: #pseudo-only :only-child +Pass Document.querySelector: :pseudo-only-child pseudo-class selector, matching all only-child elements: #pseudo-only :only-child +Pass Document.querySelectorAll: :pseudo-only-child pseudo-class selector, matching only-child em elements: #pseudo-only em:only-child +Pass Document.querySelector: :pseudo-only-child pseudo-class selector, matching only-child em elements: #pseudo-only em:only-child +Pass Document.querySelectorAll: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type: #pseudo-only :only-of-type +Pass Document.querySelector: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type: #pseudo-only :only-of-type +Pass Document.querySelectorAll: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type: #pseudo-only em:only-of-type +Pass Document.querySelector: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type: #pseudo-only em:only-of-type +Pass Document.querySelectorAll: :empty pseudo-class selector, matching empty p elements: #pseudo-empty p:empty +Pass Document.querySelector: :empty pseudo-class selector, matching empty p elements: #pseudo-empty p:empty +Pass Document.querySelectorAll: :empty pseudo-class selector, matching all empty elements: #pseudo-empty :empty +Pass Document.querySelector: :empty pseudo-class selector, matching all empty elements: #pseudo-empty :empty +Pass Document.querySelectorAll: :link and :visited pseudo-class selectors, matching a and area elements with href attributes: #pseudo-link :link, #pseudo-link :visited +Pass Document.querySelector: :link and :visited pseudo-class selectors, matching a and area elements with href attributes: #pseudo-link :link, #pseudo-link :visited +Pass Document.querySelectorAll: :link and :visited pseudo-class selectors, matching no elements: #head :link, #head :visited +Pass Document.querySelector: :link and :visited pseudo-class selectors, matching no elements: #head :link, #head :visited +Fail Document.querySelectorAll: :target pseudo-class selector, matching the element referenced by the URL fragment identifier: :target +Fail Document.querySelector: :target pseudo-class selector, matching the element referenced by the URL fragment identifier: :target +Pass Document.querySelectorAll: :lang pseudo-class selector, matching inherited language: #pseudo-lang-div1:lang(en) +Pass Document.querySelector: :lang pseudo-class selector, matching inherited language: #pseudo-lang-div1:lang(en) +Pass Document.querySelectorAll: :lang pseudo-class selector, matching specified language with exact value: #pseudo-lang-div2:lang(fr) +Pass Document.querySelector: :lang pseudo-class selector, matching specified language with exact value: #pseudo-lang-div2:lang(fr) +Pass Document.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en) +Pass Document.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en) +Pass Document.querySelectorAll: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) +Pass Document.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) +Pass Document.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled +Pass Document.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled +Pass Document.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +Pass Document.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +Pass Document.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +Pass Document.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +Pass Document.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +Pass Document.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +Pass Document.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked +Pass Document.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked +Pass Document.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div) +Pass Document.querySelector: :not pseudo-class selector, matching : #not>:not(div) +Pass Document.querySelectorAll: :not pseudo-class selector, matching : #not * :not(:first-child) +Pass Document.querySelector: :not pseudo-class selector, matching : #not * :not(:first-child) +Pass Document.querySelectorAll: :not pseudo-class selector, matching nothing: :not(*) +Pass Document.querySelector: :not pseudo-class selector, matching nothing: :not(*) +Pass Document.querySelectorAll: :not pseudo-class selector, matching nothing: :not(*|*) +Pass Document.querySelector: :not pseudo-class selector, matching nothing: :not(*|*) +Pass Document.querySelectorAll: :not pseudo-class selector argument surrounded by spaces, matching : #not>:not( div ) +Pass Document.querySelector: :not pseudo-class selector argument surrounded by spaces, matching : #not>:not( div ) +Pass Document.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line +Pass Document.querySelector: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line +Pass Document.querySelectorAll: ::first-line pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-line +Pass Document.querySelector: ::first-line pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-line +Pass Document.querySelectorAll: :first-letter pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-letter +Pass Document.querySelector: :first-letter pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-letter +Pass Document.querySelectorAll: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter +Pass Document.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter +Pass Document.querySelectorAll: :before pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:before +Pass Document.querySelector: :before pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:before +Pass Document.querySelectorAll: ::before pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::before +Pass Document.querySelector: ::before pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::before +Pass Document.querySelectorAll: :after pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:after +Pass Document.querySelector: :after pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:after +Pass Document.querySelectorAll: ::after pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::after +Pass Document.querySelector: ::after pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::after +Pass Document.querySelectorAll: Class selector, matching element with specified class: .class-p +Pass Document.querySelector: Class selector, matching element with specified class: .class-p +Pass Document.querySelectorAll: Class selector, chained, matching only elements with all specified classes: #class .apple.orange.banana +Pass Document.querySelector: Class selector, chained, matching only elements with all specified classes: #class .apple.orange.banana +Pass Document.querySelectorAll: Class Selector, chained, with type selector: div.apple.banana.orange +Pass Document.querySelector: Class Selector, chained, with type selector: div.apple.banana.orange +Pass Document.querySelectorAll: Class selector, matching element with class value using non-ASCII characters (1): .台北Táiběi +Pass Document.querySelector: Class selector, matching element with class value using non-ASCII characters (1): .台北Táiběi +Pass Document.querySelectorAll: Class selector, matching multiple elements with class value using non-ASCII characters: .台北 +Pass Document.querySelector: Class selector, matching multiple elements with class value using non-ASCII characters: .台北 +Pass Document.querySelectorAll: Class selector, chained, matching element with multiple class values using non-ASCII characters (1): .台北Táiběi.台北 +Pass Document.querySelector: Class selector, chained, matching element with multiple class values using non-ASCII characters (1): .台北Táiběi.台北 +Pass Document.querySelectorAll: Class selector, matching element with class with escaped character: .foo\:bar +Pass Document.querySelector: Class selector, matching element with class with escaped character: .foo\:bar +Pass Document.querySelectorAll: Class selector, matching element with class with escaped character: .test\.foo\[5\]bar +Pass Document.querySelector: Class selector, matching element with class with escaped character: .test\.foo\[5\]bar +Pass Document.querySelectorAll: ID selector, matching element with specified id: #id #id-div1 +Pass Document.querySelector: ID selector, matching element with specified id: #id #id-div1 +Fail Document.querySelectorAll: ID selector, chained, matching element with specified id: #id-div1, #id-div1 +Pass Document.querySelector: ID selector, chained, matching element with specified id: #id-div1, #id-div1 +Pass Document.querySelectorAll: ID selector, chained, matching element with specified id: #id-div1, #id-div2 +Pass Document.querySelector: ID selector, chained, matching element with specified id: #id-div1, #id-div2 +Pass Document.querySelectorAll: ID Selector, chained, with type selector: div#id-div1, div#id-div2 +Pass Document.querySelector: ID Selector, chained, with type selector: div#id-div1, div#id-div2 +Pass Document.querySelectorAll: ID selector, not matching non-existent descendant: #id #none +Pass Document.querySelector: ID selector, not matching non-existent descendant: #id #none +Pass Document.querySelectorAll: ID selector, not matching non-existent ancestor: #none #id-div1 +Pass Document.querySelector: ID selector, not matching non-existent ancestor: #none #id-div1 +Pass Document.querySelectorAll: ID selector, matching multiple elements with duplicate id: #id-li-duplicate +Pass Document.querySelector: ID selector, matching multiple elements with duplicate id: #id-li-duplicate +Pass Document.querySelectorAll: ID selector, matching id value using non-ASCII characters (1): #台北Táiběi +Pass Document.querySelector: ID selector, matching id value using non-ASCII characters (1): #台北Táiběi +Pass Document.querySelectorAll: ID selector, matching id value using non-ASCII characters (2): #台北 +Pass Document.querySelector: ID selector, matching id value using non-ASCII characters (2): #台北 +Pass Document.querySelectorAll: ID selector, matching id values using non-ASCII characters (1): #台北Táiběi, #台北 +Pass Document.querySelector: ID selector, matching id values using non-ASCII characters (1): #台北Táiběi, #台北 +Pass Document.querySelectorAll: ID selector, matching element with id with escaped character: #\#foo\:bar +Pass Document.querySelector: ID selector, matching element with id with escaped character: #\#foo\:bar +Pass Document.querySelectorAll: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar +Pass Document.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar +Pass Document.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div +Pass Document.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div +Pass Document.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div +Pass Document.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div +Pass Document.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* +Pass Document.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* +Pass Document.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div +Pass Document.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div +Pass Document.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: body #descendant-div1 +Pass Document.querySelector: Descendant combinator, matching element with id that is a descendant of an element: body #descendant-div1 +Pass Document.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 +Pass Document.querySelector: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 +Pass Document.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element with id: #descendant #descendant-div2 +Pass Document.querySelector: Descendant combinator, matching element with id that is a descendant of an element with id: #descendant #descendant-div2 +Pass Document.querySelectorAll: Descendant combinator, matching element with class that is a descendant of an element with id: #descendant .descendant-div2 +Pass Document.querySelector: Descendant combinator, matching element with class that is a descendant of an element with id: #descendant .descendant-div2 +Pass Document.querySelectorAll: Descendant combinator, matching element with class that is a descendant of an element with class: .descendant-div1 .descendant-div3 +Pass Document.querySelector: Descendant combinator, matching element with class that is a descendant of an element with class: .descendant-div1 .descendant-div3 +Pass Document.querySelectorAll: Descendant combinator, not matching element with id that is not a descendant of an element with id: #descendant-div1 #descendant-div4 +Pass Document.querySelector: Descendant combinator, not matching element with id that is not a descendant of an element with id: #descendant-div1 #descendant-div4 +Pass Document.querySelectorAll: Descendant combinator, whitespace characters: #descendant #descendant-div2 +Pass Document.querySelector: Descendant combinator, whitespace characters: #descendant #descendant-div2 +Pass Document.querySelectorAll: Child combinator, matching element that is a child of an element with id: #child>div +Pass Document.querySelector: Child combinator, matching element that is a child of an element with id: #child>div +Pass Document.querySelectorAll: Child combinator, matching element with id that is a child of an element: div>#child-div1 +Pass Document.querySelector: Child combinator, matching element with id that is a child of an element: div>#child-div1 +Pass Document.querySelectorAll: Child combinator, matching element with id that is a child of an element with id: #child>#child-div1 +Pass Document.querySelector: Child combinator, matching element with id that is a child of an element with id: #child>#child-div1 +Pass Document.querySelectorAll: Child combinator, matching element with id that is a child of an element with class: #child-div1>.child-div2 +Pass Document.querySelector: Child combinator, matching element with id that is a child of an element with class: #child-div1>.child-div2 +Pass Document.querySelectorAll: Child combinator, matching element with class that is a child of an element with class: .child-div1>.child-div2 +Pass Document.querySelector: Child combinator, matching element with class that is a child of an element with class: .child-div1>.child-div2 +Pass Document.querySelectorAll: Child combinator, not matching element with id that is not a child of an element with id: #child>#child-div3 +Pass Document.querySelector: Child combinator, not matching element with id that is not a child of an element with id: #child>#child-div3 +Pass Document.querySelectorAll: Child combinator, not matching element with id that is not a child of an element with class: #child-div1>.child-div3 +Pass Document.querySelector: Child combinator, not matching element with id that is not a child of an element with class: #child-div1>.child-div3 +Pass Document.querySelectorAll: Child combinator, not matching element with class that is not a child of an element with class: .child-div1>.child-div3 +Pass Document.querySelector: Child combinator, not matching element with class that is not a child of an element with class: .child-div1>.child-div3 +Pass Document.querySelectorAll: Child combinator, surrounded by whitespace: #child-div1 > #child-div2 +Pass Document.querySelector: Child combinator, surrounded by whitespace: #child-div1 > #child-div2 +Pass Document.querySelectorAll: Child combinator, whitespace after: #child-div1> #child-div2 +Pass Document.querySelector: Child combinator, whitespace after: #child-div1> #child-div2 +Pass Document.querySelectorAll: Child combinator, whitespace before: #child-div1 >#child-div2 +Pass Document.querySelector: Child combinator, whitespace before: #child-div1 >#child-div2 +Pass Document.querySelectorAll: Child combinator, no whitespace: #child-div1>#child-div2 +Pass Document.querySelector: Child combinator, no whitespace: #child-div1>#child-div2 +Pass Document.querySelectorAll: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id: #adjacent-div2+div +Pass Document.querySelector: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id: #adjacent-div2+div +Pass Document.querySelectorAll: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element: div+#adjacent-div4 +Pass Document.querySelector: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element: div+#adjacent-div4 +Pass Document.querySelectorAll: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id: #adjacent-div2+#adjacent-div4 +Pass Document.querySelector: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id: #adjacent-div2+#adjacent-div4 +Pass Document.querySelectorAll: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id: #adjacent-div2+.adjacent-div4 +Pass Document.querySelector: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id: #adjacent-div2+.adjacent-div4 +Pass Document.querySelectorAll: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class: .adjacent-div2+.adjacent-div4 +Pass Document.querySelector: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class: .adjacent-div2+.adjacent-div4 +Pass Document.querySelectorAll: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element: #adjacent div+p +Pass Document.querySelector: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element: #adjacent div+p +Pass Document.querySelectorAll: Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id: #adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1 +Pass Document.querySelector: Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id: #adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1 +Pass Document.querySelectorAll: Adjacent sibling combinator, surrounded by whitespace: #adjacent-p2 + #adjacent-p3 +Pass Document.querySelector: Adjacent sibling combinator, surrounded by whitespace: #adjacent-p2 + #adjacent-p3 +Pass Document.querySelectorAll: Adjacent sibling combinator, whitespace after: #adjacent-p2+ #adjacent-p3 +Pass Document.querySelector: Adjacent sibling combinator, whitespace after: #adjacent-p2+ #adjacent-p3 +Pass Document.querySelectorAll: Adjacent sibling combinator, whitespace before: #adjacent-p2 +#adjacent-p3 +Pass Document.querySelector: Adjacent sibling combinator, whitespace before: #adjacent-p2 +#adjacent-p3 +Pass Document.querySelectorAll: Adjacent sibling combinator, no whitespace: #adjacent-p2+#adjacent-p3 +Pass Document.querySelector: Adjacent sibling combinator, no whitespace: #adjacent-p2+#adjacent-p3 +Pass Document.querySelectorAll: General sibling combinator, matching element that is a sibling of an element with id: #sibling-div2~div +Pass Document.querySelector: General sibling combinator, matching element that is a sibling of an element with id: #sibling-div2~div +Pass Document.querySelectorAll: General sibling combinator, matching element with id that is a sibling of an element: div~#sibling-div4 +Pass Document.querySelector: General sibling combinator, matching element with id that is a sibling of an element: div~#sibling-div4 +Pass Document.querySelectorAll: General sibling combinator, matching element with id that is a sibling of an element with id: #sibling-div2~#sibling-div4 +Pass Document.querySelector: General sibling combinator, matching element with id that is a sibling of an element with id: #sibling-div2~#sibling-div4 +Pass Document.querySelectorAll: General sibling combinator, matching element with class that is a sibling of an element with id: #sibling-div2~.sibling-div +Pass Document.querySelector: General sibling combinator, matching element with class that is a sibling of an element with id: #sibling-div2~.sibling-div +Pass Document.querySelectorAll: General sibling combinator, matching p element that is a sibling of a div element: #sibling div~p +Pass Document.querySelector: General sibling combinator, matching p element that is a sibling of a div element: #sibling div~p +Pass Document.querySelectorAll: General sibling combinator, not matching element with id that is not a sibling after a p element: #sibling>p~div +Pass Document.querySelector: General sibling combinator, not matching element with id that is not a sibling after a p element: #sibling>p~div +Pass Document.querySelectorAll: General sibling combinator, not matching element with id that is not a sibling after an element with id: #sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1 +Pass Document.querySelector: General sibling combinator, not matching element with id that is not a sibling after an element with id: #sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1 +Pass Document.querySelectorAll: General sibling combinator, surrounded by whitespace: #sibling-p2 ~ #sibling-p3 +Pass Document.querySelector: General sibling combinator, surrounded by whitespace: #sibling-p2 ~ #sibling-p3 +Pass Document.querySelectorAll: General sibling combinator, whitespace after: #sibling-p2~ #sibling-p3 +Pass Document.querySelector: General sibling combinator, whitespace after: #sibling-p2~ #sibling-p3 +Pass Document.querySelectorAll: General sibling combinator, whitespace before: #sibling-p2 ~#sibling-p3 +Pass Document.querySelector: General sibling combinator, whitespace before: #sibling-p2 ~#sibling-p3 +Pass Document.querySelectorAll: General sibling combinator, no whitespace: #sibling-p2~#sibling-p3 +Pass Document.querySelector: General sibling combinator, no whitespace: #sibling-p2~#sibling-p3 +Pass Document.querySelectorAll: Syntax, group of selectors separator, surrounded by whitespace: #group em , #group strong +Pass Document.querySelector: Syntax, group of selectors separator, surrounded by whitespace: #group em , #group strong +Pass Document.querySelectorAll: Syntax, group of selectors separator, whitespace after: #group em, #group strong +Pass Document.querySelector: Syntax, group of selectors separator, whitespace after: #group em, #group strong +Pass Document.querySelectorAll: Syntax, group of selectors separator, whitespace before: #group em ,#group strong +Pass Document.querySelector: Syntax, group of selectors separator, whitespace before: #group em ,#group strong +Pass Document.querySelectorAll: Syntax, group of selectors separator, no whitespace: #group em,#group strong +Pass Document.querySelector: Syntax, group of selectors separator, no whitespace: #group em,#group strong +Fail Document.querySelectorAll: Slotted selector: ::slotted(foo) Failed to parse selector +Fail Document.querySelector: Slotted selector: ::slotted(foo) Failed to parse selector +Fail Document.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo Failed to parse selector +Fail Document.querySelector: Slotted selector (no matching closing paren): ::slotted(foo Failed to parse selector +Pass Detached Element.querySelectorAll: Type selector, matching html element: html +Pass Detached Element.querySelector: Type selector, matching html element: html +Pass Detached Element.querySelectorAll: Type selector, matching body element: body +Pass Detached Element.querySelector: Type selector, matching body element: body +Pass Detached Element.querySelectorAll: Universal selector, matching all children of element with specified ID: #universal>* +Pass Detached Element.querySelector: Universal selector, matching all children of element with specified ID: #universal>* +Pass Detached Element.querySelectorAll: Universal selector, matching all grandchildren of element with specified ID: #universal>*>* +Pass Detached Element.querySelector: Universal selector, matching all grandchildren of element with specified ID: #universal>*>* +Pass Detached Element.querySelectorAll: Universal selector, matching all children of empty element with specified ID: #empty>* +Pass Detached Element.querySelector: Universal selector, matching all children of empty element with specified ID: #empty>* +Pass Detached Element.querySelectorAll: Universal selector, matching all descendants of element with specified ID: #universal * +Pass Detached Element.querySelector: Universal selector, matching all descendants of element with specified ID: #universal * +Pass Detached Element.querySelectorAll: Attribute presence selector, matching align attribute with value: .attr-presence-div1[align] +Pass Detached Element.querySelector: Attribute presence selector, matching align attribute with value: .attr-presence-div1[align] +Pass Detached Element.querySelectorAll: Attribute presence selector, matching align attribute with empty value: .attr-presence-div2[align] +Pass Detached Element.querySelector: Attribute presence selector, matching align attribute with empty value: .attr-presence-div2[align] +Fail Detached Element.querySelectorAll: Attribute presence selector, matching title attribute, case insensitivity: #attr-presence [*|TiTlE] +Fail Detached Element.querySelector: Attribute presence selector, matching title attribute, case insensitivity: #attr-presence [*|TiTlE] +Pass Detached Element.querySelectorAll: Attribute presence selector, matching custom data-* attribute: [data-attr-presence] +Pass Detached Element.querySelector: Attribute presence selector, matching custom data-* attribute: [data-attr-presence] +Pass Detached Element.querySelectorAll: Attribute presence selector, not matching attribute with similar name: .attr-presence-div3[align], .attr-presence-div4[align] +Pass Detached Element.querySelector: Attribute presence selector, not matching attribute with similar name: .attr-presence-div3[align], .attr-presence-div4[align] +Pass Detached Element.querySelectorAll: Attribute presence selector, matching attribute with non-ASCII characters: ul[data-中文] +Pass Detached Element.querySelector: Attribute presence selector, matching attribute with non-ASCII characters: ul[data-中文] +Pass Detached Element.querySelectorAll: Attribute presence selector, not matching default option without selected attribute: #attr-presence-select1 option[selected] +Pass Detached Element.querySelector: Attribute presence selector, not matching default option without selected attribute: #attr-presence-select1 option[selected] +Pass Detached Element.querySelectorAll: Attribute presence selector, matching option with selected attribute: #attr-presence-select2 option[selected] +Pass Detached Element.querySelector: Attribute presence selector, matching option with selected attribute: #attr-presence-select2 option[selected] +Pass Detached Element.querySelectorAll: Attribute presence selector, matching multiple options with selected attributes: #attr-presence-select3 option[selected] +Pass Detached Element.querySelector: Attribute presence selector, matching multiple options with selected attributes: #attr-presence-select3 option[selected] +Pass Detached Element.querySelectorAll: Attribute value selector, matching align attribute with value: #attr-value [align="center"] +Pass Detached Element.querySelector: Attribute value selector, matching align attribute with value: #attr-value [align="center"] +Pass Detached Element.querySelectorAll: Attribute value selector, matching align attribute with value, unclosed bracket: #attr-value [align="center" +Pass Detached Element.querySelector: Attribute value selector, matching align attribute with value, unclosed bracket: #attr-value [align="center" +Pass Detached Element.querySelectorAll: Attribute value selector, matching align attribute with empty value: #attr-value [align=""] +Pass Detached Element.querySelector: Attribute value selector, matching align attribute with empty value: #attr-value [align=""] +Pass Detached Element.querySelectorAll: Attribute value selector, not matching align attribute with partial value: #attr-value [align="c"] +Pass Detached Element.querySelector: Attribute value selector, not matching align attribute with partial value: #attr-value [align="c"] +Pass Detached Element.querySelectorAll: Attribute value selector, not matching align attribute with incorrect value: #attr-value [align="centera"] +Pass Detached Element.querySelector: Attribute value selector, not matching align attribute with incorrect value: #attr-value [align="centera"] +Pass Detached Element.querySelectorAll: Attribute value selector, matching custom data-* attribute with unicode escaped value: [data-attr-value="\e9"] +Pass Detached Element.querySelector: Attribute value selector, matching custom data-* attribute with unicode escaped value: [data-attr-value="\e9"] +Pass Detached Element.querySelectorAll: Attribute value selector, matching custom data-* attribute with escaped character: [data-attr-value_foo="\e9"] +Pass Detached Element.querySelector: Attribute value selector, matching custom data-* attribute with escaped character: [data-attr-value_foo="\e9"] +Pass Detached Element.querySelectorAll: Attribute value selector with single-quoted value, matching multiple inputs with type attributes: #attr-value input[type='hidden'],#attr-value input[type='radio'] +Pass Detached Element.querySelector: Attribute value selector with single-quoted value, matching multiple inputs with type attributes: #attr-value input[type='hidden'],#attr-value input[type='radio'] +Pass Detached Element.querySelectorAll: Attribute value selector with double-quoted value, matching multiple inputs with type attributes: #attr-value input[type="hidden"],#attr-value input[type='radio'] +Pass Detached Element.querySelector: Attribute value selector with double-quoted value, matching multiple inputs with type attributes: #attr-value input[type="hidden"],#attr-value input[type='radio'] +Pass Detached Element.querySelectorAll: Attribute value selector with unquoted value, matching multiple inputs with type attributes: #attr-value input[type=hidden],#attr-value input[type=radio] +Pass Detached Element.querySelector: Attribute value selector with unquoted value, matching multiple inputs with type attributes: #attr-value input[type=hidden],#attr-value input[type=radio] +Pass Detached Element.querySelectorAll: Attribute value selector, matching attribute with value using non-ASCII characters: [data-attr-value=中文] +Pass Detached Element.querySelector: Attribute value selector, matching attribute with value using non-ASCII characters: [data-attr-value=中文] +Pass Detached Element.querySelectorAll: Attribute whitespace-separated list selector, matching class attribute with value: #attr-whitespace [class~="div1"] +Pass Detached Element.querySelector: Attribute whitespace-separated list selector, matching class attribute with value: #attr-whitespace [class~="div1"] +Pass Detached Element.querySelectorAll: Attribute whitespace-separated list selector, not matching class attribute with empty value: #attr-whitespace [class~=""] +Pass Detached Element.querySelector: Attribute whitespace-separated list selector, not matching class attribute with empty value: #attr-whitespace [class~=""] +Pass Detached Element.querySelectorAll: Attribute whitespace-separated list selector, not matching class attribute with partial value: [data-attr-whitespace~="div"] +Pass Detached Element.querySelector: Attribute whitespace-separated list selector, not matching class attribute with partial value: [data-attr-whitespace~="div"] +Pass Detached Element.querySelectorAll: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value: [data-attr-whitespace~="\0000e9"] +Pass Detached Element.querySelector: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value: [data-attr-whitespace~="\0000e9"] +Pass Detached Element.querySelectorAll: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character: [data-attr-whitespace_foo~="\e9"] +Pass Detached Element.querySelector: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character: [data-attr-whitespace_foo~="\e9"] +Pass Detached Element.querySelectorAll: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +Pass Detached Element.querySelector: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +Pass Detached Element.querySelectorAll: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +Pass Detached Element.querySelector: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +Pass Detached Element.querySelectorAll: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +Pass Detached Element.querySelector: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +Pass Detached Element.querySelectorAll: Attribute whitespace-separated list selector with double-quoted value, not matching value with space: #attr-whitespace a[rel~="book mark"] +Pass Detached Element.querySelector: Attribute whitespace-separated list selector with double-quoted value, not matching value with space: #attr-whitespace a[rel~="book mark"] +Pass Detached Element.querySelectorAll: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters: #attr-whitespace [title~=中文] +Pass Detached Element.querySelector: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters: #attr-whitespace [title~=中文] +Pass Detached Element.querySelectorAll: Attribute hyphen-separated list selector, not matching unspecified lang attribute: #attr-hyphen-div1[lang|="en"] +Pass Detached Element.querySelector: Attribute hyphen-separated list selector, not matching unspecified lang attribute: #attr-hyphen-div1[lang|="en"] +Pass Detached Element.querySelectorAll: Attribute hyphen-separated list selector, matching lang attribute with exact value: #attr-hyphen-div2[lang|="fr"] +Pass Detached Element.querySelector: Attribute hyphen-separated list selector, matching lang attribute with exact value: #attr-hyphen-div2[lang|="fr"] +Pass Detached Element.querySelectorAll: Attribute hyphen-separated list selector, matching lang attribute with partial value: #attr-hyphen-div3[lang|="en"] +Pass Detached Element.querySelector: Attribute hyphen-separated list selector, matching lang attribute with partial value: #attr-hyphen-div3[lang|="en"] +Pass Detached Element.querySelectorAll: Attribute hyphen-separated list selector, not matching incorrect value: #attr-hyphen-div4[lang|="es-AR"] +Pass Detached Element.querySelector: Attribute hyphen-separated list selector, not matching incorrect value: #attr-hyphen-div4[lang|="es-AR"] +Pass Detached Element.querySelectorAll: Attribute begins with selector, matching href attributes beginning with specified substring: #attr-begins a[href^="http://www"] +Pass Detached Element.querySelector: Attribute begins with selector, matching href attributes beginning with specified substring: #attr-begins a[href^="http://www"] +Pass Detached Element.querySelectorAll: Attribute begins with selector, matching lang attributes beginning with specified substring, : #attr-begins [lang^="en-"] +Pass Detached Element.querySelector: Attribute begins with selector, matching lang attributes beginning with specified substring, : #attr-begins [lang^="en-"] +Pass Detached Element.querySelectorAll: Attribute begins with selector, not matching class attribute with empty value: #attr-begins [class^=""] +Pass Detached Element.querySelector: Attribute begins with selector, not matching class attribute with empty value: #attr-begins [class^=""] +Pass Detached Element.querySelectorAll: Attribute begins with selector, not matching class attribute not beginning with specified substring: #attr-begins [class^=apple] +Pass Detached Element.querySelector: Attribute begins with selector, not matching class attribute not beginning with specified substring: #attr-begins [class^=apple] +Pass Detached Element.querySelectorAll: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=' apple'] +Pass Detached Element.querySelector: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=' apple'] +Pass Detached Element.querySelectorAll: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=" apple"] +Pass Detached Element.querySelector: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=" apple"] +Pass Detached Element.querySelectorAll: Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring: #attr-begins [class^= apple] +Pass Detached Element.querySelector: Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring: #attr-begins [class^= apple] +Pass Detached Element.querySelectorAll: Attribute ends with selector, matching href attributes ending with specified substring: #attr-ends a[href$=".org"] +Pass Detached Element.querySelector: Attribute ends with selector, matching href attributes ending with specified substring: #attr-ends a[href$=".org"] +Pass Detached Element.querySelectorAll: Attribute ends with selector, matching lang attributes ending with specified substring, : #attr-ends [lang$="-CH"] +Pass Detached Element.querySelector: Attribute ends with selector, matching lang attributes ending with specified substring, : #attr-ends [lang$="-CH"] +Pass Detached Element.querySelectorAll: Attribute ends with selector, not matching class attribute with empty value: #attr-ends [class$=""] +Pass Detached Element.querySelector: Attribute ends with selector, not matching class attribute with empty value: #attr-ends [class$=""] +Pass Detached Element.querySelectorAll: Attribute ends with selector, not matching class attribute not ending with specified substring: #attr-ends [class$=apple] +Pass Detached Element.querySelector: Attribute ends with selector, not matching class attribute not ending with specified substring: #attr-ends [class$=apple] +Pass Detached Element.querySelectorAll: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring: #attr-ends [class$='apple '] +Pass Detached Element.querySelector: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring: #attr-ends [class$='apple '] +Pass Detached Element.querySelectorAll: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring: #attr-ends [class$="apple "] +Pass Detached Element.querySelector: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring: #attr-ends [class$="apple "] +Pass Detached Element.querySelectorAll: Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring: #attr-ends [class$=apple ] +Pass Detached Element.querySelector: Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring: #attr-ends [class$=apple ] +Pass Detached Element.querySelectorAll: Attribute contains selector, matching href attributes beginning with specified substring: #attr-contains a[href*="http://www"] +Pass Detached Element.querySelector: Attribute contains selector, matching href attributes beginning with specified substring: #attr-contains a[href*="http://www"] +Pass Detached Element.querySelectorAll: Attribute contains selector, matching href attributes ending with specified substring: #attr-contains a[href*=".org"] +Pass Detached Element.querySelector: Attribute contains selector, matching href attributes ending with specified substring: #attr-contains a[href*=".org"] +Pass Detached Element.querySelectorAll: Attribute contains selector, matching href attributes containing specified substring: #attr-contains a[href*=".example."] +Pass Detached Element.querySelector: Attribute contains selector, matching href attributes containing specified substring: #attr-contains a[href*=".example."] +Pass Detached Element.querySelectorAll: Attribute contains selector, matching lang attributes beginning with specified substring, : #attr-contains [lang*="en-"] +Pass Detached Element.querySelector: Attribute contains selector, matching lang attributes beginning with specified substring, : #attr-contains [lang*="en-"] +Pass Detached Element.querySelectorAll: Attribute contains selector, matching lang attributes ending with specified substring, : #attr-contains [lang*="-CH"] +Pass Detached Element.querySelector: Attribute contains selector, matching lang attributes ending with specified substring, : #attr-contains [lang*="-CH"] +Pass Detached Element.querySelectorAll: Attribute contains selector, not matching class attribute with empty value: #attr-contains [class*=""] +Pass Detached Element.querySelector: Attribute contains selector, not matching class attribute with empty value: #attr-contains [class*=""] +Pass Detached Element.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=' apple'] +Pass Detached Element.querySelector: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=' apple'] +Pass Detached Element.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring: #attr-contains [class*='orange '] +Pass Detached Element.querySelector: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring: #attr-contains [class*='orange '] +Pass Detached Element.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute containing specified substring: #attr-contains [class*='ple banana ora'] +Pass Detached Element.querySelector: Attribute contains selector with single-quoted value, matching class attribute containing specified substring: #attr-contains [class*='ple banana ora'] +Pass Detached Element.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=" apple"] +Pass Detached Element.querySelector: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=" apple"] +Pass Detached Element.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring: #attr-contains [class*="orange "] +Pass Detached Element.querySelector: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring: #attr-contains [class*="orange "] +Pass Detached Element.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute containing specified substring: #attr-contains [class*="ple banana ora"] +Pass Detached Element.querySelector: Attribute contains selector with double-quoted value, matching class attribute containing specified substring: #attr-contains [class*="ple banana ora"] +Pass Detached Element.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring: #attr-contains [class*= apple] +Pass Detached Element.querySelector: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring: #attr-contains [class*= apple] +Pass Detached Element.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute ending with specified substring: #attr-contains [class*=orange ] +Pass Detached Element.querySelector: Attribute contains selector with unquoted value, matching class attribute ending with specified substring: #attr-contains [class*=orange ] +Pass Detached Element.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute containing specified substring: #attr-contains [class*= banana ] +Pass Detached Element.querySelector: Attribute contains selector with unquoted value, matching class attribute containing specified substring: #attr-contains [class*= banana ] +Pass Detached Element.querySelectorAll: :root pseudo-class selector, not matching document root element: :root +Pass Detached Element.querySelector: :root pseudo-class selector, not matching document root element: :root +Pass Detached Element.querySelectorAll: :nth-child selector, matching the third child element: #pseudo-nth-table1 :nth-child(3) +Pass Detached Element.querySelector: :nth-child selector, matching the third child element: #pseudo-nth-table1 :nth-child(3) +Pass Detached Element.querySelectorAll: :nth-child selector, matching every third child element: #pseudo-nth li:nth-child(3n) +Pass Detached Element.querySelector: :nth-child selector, matching every third child element: #pseudo-nth li:nth-child(3n) +Pass Detached Element.querySelectorAll: :nth-child selector, matching every second child element, starting from the fourth: #pseudo-nth li:nth-child(2n+4) +Pass Detached Element.querySelector: :nth-child selector, matching every second child element, starting from the fourth: #pseudo-nth li:nth-child(2n+4) +Pass Detached Element.querySelectorAll: :nth-child selector, matching every fourth child element, starting from the third: #pseudo-nth-p1 :nth-child(4n-1) +Pass Detached Element.querySelector: :nth-child selector, matching every fourth child element, starting from the third: #pseudo-nth-p1 :nth-child(4n-1) +Pass Detached Element.querySelectorAll: :nth-last-child selector, matching the third last child element: #pseudo-nth-table1 :nth-last-child(3) +Pass Detached Element.querySelector: :nth-last-child selector, matching the third last child element: #pseudo-nth-table1 :nth-last-child(3) +Pass Detached Element.querySelectorAll: :nth-last-child selector, matching every third child element from the end: #pseudo-nth li:nth-last-child(3n) +Pass Detached Element.querySelector: :nth-last-child selector, matching every third child element from the end: #pseudo-nth li:nth-last-child(3n) +Pass Detached Element.querySelectorAll: :nth-last-child selector, matching every second child element from the end, starting from the fourth last: #pseudo-nth li:nth-last-child(2n+4) +Pass Detached Element.querySelector: :nth-last-child selector, matching every second child element from the end, starting from the fourth last: #pseudo-nth li:nth-last-child(2n+4) +Pass Detached Element.querySelectorAll: :nth-last-child selector, matching every fourth element from the end, starting from the third last: #pseudo-nth-p1 :nth-last-child(4n-1) +Pass Detached Element.querySelector: :nth-last-child selector, matching every fourth element from the end, starting from the third last: #pseudo-nth-p1 :nth-last-child(4n-1) +Pass Detached Element.querySelectorAll: :nth-of-type selector, matching the third em element: #pseudo-nth-p1 em:nth-of-type(3) +Pass Detached Element.querySelector: :nth-of-type selector, matching the third em element: #pseudo-nth-p1 em:nth-of-type(3) +Pass Detached Element.querySelectorAll: :nth-of-type selector, matching every second element of their type: #pseudo-nth-p1 :nth-of-type(2n) +Pass Detached Element.querySelector: :nth-of-type selector, matching every second element of their type: #pseudo-nth-p1 :nth-of-type(2n) +Pass Detached Element.querySelectorAll: :nth-of-type selector, matching every second elemetn of their type, starting from the first: #pseudo-nth-p1 span:nth-of-type(2n-1) +Pass Detached Element.querySelector: :nth-of-type selector, matching every second elemetn of their type, starting from the first: #pseudo-nth-p1 span:nth-of-type(2n-1) +Pass Detached Element.querySelectorAll: :nth-last-of-type selector, matching the third last em element: #pseudo-nth-p1 em:nth-last-of-type(3) +Pass Detached Element.querySelector: :nth-last-of-type selector, matching the third last em element: #pseudo-nth-p1 em:nth-last-of-type(3) +Pass Detached Element.querySelectorAll: :nth-last-of-type selector, matching every second last element of their type: #pseudo-nth-p1 :nth-last-of-type(2n) +Pass Detached Element.querySelector: :nth-last-of-type selector, matching every second last element of their type: #pseudo-nth-p1 :nth-last-of-type(2n) +Pass Detached Element.querySelectorAll: :nth-last-of-type selector, matching every second last element of their type, starting from the last: #pseudo-nth-p1 span:nth-last-of-type(2n-1) +Pass Detached Element.querySelector: :nth-last-of-type selector, matching every second last element of their type, starting from the last: #pseudo-nth-p1 span:nth-last-of-type(2n-1) +Pass Detached Element.querySelectorAll: :first-of-type selector, matching the first em element: #pseudo-nth-p1 em:first-of-type +Pass Detached Element.querySelector: :first-of-type selector, matching the first em element: #pseudo-nth-p1 em:first-of-type +Pass Detached Element.querySelectorAll: :first-of-type selector, matching the first of every type of element: #pseudo-nth-p1 :first-of-type +Pass Detached Element.querySelector: :first-of-type selector, matching the first of every type of element: #pseudo-nth-p1 :first-of-type +Pass Detached Element.querySelectorAll: :first-of-type selector, matching the first td element in each table row: #pseudo-nth-table1 tr :first-of-type +Pass Detached Element.querySelector: :first-of-type selector, matching the first td element in each table row: #pseudo-nth-table1 tr :first-of-type +Pass Detached Element.querySelectorAll: :last-of-type selector, matching the last em elemnet: #pseudo-nth-p1 em:last-of-type +Pass Detached Element.querySelector: :last-of-type selector, matching the last em elemnet: #pseudo-nth-p1 em:last-of-type +Pass Detached Element.querySelectorAll: :last-of-type selector, matching the last of every type of element: #pseudo-nth-p1 :last-of-type +Pass Detached Element.querySelector: :last-of-type selector, matching the last of every type of element: #pseudo-nth-p1 :last-of-type +Pass Detached Element.querySelectorAll: :last-of-type selector, matching the last td element in each table row: #pseudo-nth-table1 tr :last-of-type +Pass Detached Element.querySelector: :last-of-type selector, matching the last td element in each table row: #pseudo-nth-table1 tr :last-of-type +Pass Detached Element.querySelectorAll: :first-child pseudo-class selector, matching first child div element: #pseudo-first-child div:first-child +Pass Detached Element.querySelector: :first-child pseudo-class selector, matching first child div element: #pseudo-first-child div:first-child +Pass Detached Element.querySelectorAll: :first-child pseudo-class selector, doesn't match non-first-child elements: .pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child +Pass Detached Element.querySelector: :first-child pseudo-class selector, doesn't match non-first-child elements: .pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child +Pass Detached Element.querySelectorAll: :first-child pseudo-class selector, matching first-child of multiple elements: #pseudo-first-child span:first-child +Pass Detached Element.querySelector: :first-child pseudo-class selector, matching first-child of multiple elements: #pseudo-first-child span:first-child +Pass Detached Element.querySelectorAll: :last-child pseudo-class selector, matching last child div element: #pseudo-last-child div:last-child +Pass Detached Element.querySelector: :last-child pseudo-class selector, matching last child div element: #pseudo-last-child div:last-child +Pass Detached Element.querySelectorAll: :last-child pseudo-class selector, doesn't match non-last-child elements: .pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child +Pass Detached Element.querySelector: :last-child pseudo-class selector, doesn't match non-last-child elements: .pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child +Pass Detached Element.querySelectorAll: :last-child pseudo-class selector, matching first-child of multiple elements: #pseudo-last-child span:last-child +Pass Detached Element.querySelector: :last-child pseudo-class selector, matching first-child of multiple elements: #pseudo-last-child span:last-child +Pass Detached Element.querySelectorAll: :pseudo-only-child pseudo-class selector, matching all only-child elements: #pseudo-only :only-child +Pass Detached Element.querySelector: :pseudo-only-child pseudo-class selector, matching all only-child elements: #pseudo-only :only-child +Pass Detached Element.querySelectorAll: :pseudo-only-child pseudo-class selector, matching only-child em elements: #pseudo-only em:only-child +Pass Detached Element.querySelector: :pseudo-only-child pseudo-class selector, matching only-child em elements: #pseudo-only em:only-child +Pass Detached Element.querySelectorAll: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type: #pseudo-only :only-of-type +Pass Detached Element.querySelector: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type: #pseudo-only :only-of-type +Pass Detached Element.querySelectorAll: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type: #pseudo-only em:only-of-type +Pass Detached Element.querySelector: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type: #pseudo-only em:only-of-type +Pass Detached Element.querySelectorAll: :empty pseudo-class selector, matching empty p elements: #pseudo-empty p:empty +Pass Detached Element.querySelector: :empty pseudo-class selector, matching empty p elements: #pseudo-empty p:empty +Pass Detached Element.querySelectorAll: :empty pseudo-class selector, matching all empty elements: #pseudo-empty :empty +Pass Detached Element.querySelector: :empty pseudo-class selector, matching all empty elements: #pseudo-empty :empty +Pass Detached Element.querySelectorAll: :link and :visited pseudo-class selectors, matching a and area elements with href attributes: #pseudo-link :link, #pseudo-link :visited +Pass Detached Element.querySelector: :link and :visited pseudo-class selectors, matching a and area elements with href attributes: #pseudo-link :link, #pseudo-link :visited +Pass Detached Element.querySelectorAll: :link and :visited pseudo-class selectors, not matching link elements with href attributes: #head :link, #head :visited +Pass Detached Element.querySelector: :link and :visited pseudo-class selectors, not matching link elements with href attributes: #head :link, #head :visited +Pass Detached Element.querySelectorAll: :link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing: :link:visited +Pass Detached Element.querySelector: :link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing: :link:visited +Pass Detached Element.querySelectorAll: :target pseudo-class selector, matching the element referenced by the URL fragment identifier: :target +Pass Detached Element.querySelector: :target pseudo-class selector, matching the element referenced by the URL fragment identifier: :target +Pass Detached Element.querySelectorAll: :lang pseudo-class selector, not matching element with no inherited language: #pseudo-lang-div1:lang(en) +Pass Detached Element.querySelector: :lang pseudo-class selector, not matching element with no inherited language: #pseudo-lang-div1:lang(en) +Pass Detached Element.querySelectorAll: :lang pseudo-class selector, matching specified language with exact value: #pseudo-lang-div2:lang(fr) +Pass Detached Element.querySelector: :lang pseudo-class selector, matching specified language with exact value: #pseudo-lang-div2:lang(fr) +Pass Detached Element.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en) +Pass Detached Element.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en) +Pass Detached Element.querySelectorAll: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) +Pass Detached Element.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) +Pass Detached Element.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled +Pass Detached Element.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled +Pass Detached Element.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +Pass Detached Element.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +Pass Detached Element.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +Pass Detached Element.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +Pass Detached Element.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +Pass Detached Element.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +Pass Detached Element.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked +Pass Detached Element.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked +Pass Detached Element.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div) +Pass Detached Element.querySelector: :not pseudo-class selector, matching : #not>:not(div) +Pass Detached Element.querySelectorAll: :not pseudo-class selector, matching : #not * :not(:first-child) +Pass Detached Element.querySelector: :not pseudo-class selector, matching : #not * :not(:first-child) +Pass Detached Element.querySelectorAll: :not pseudo-class selector, matching nothing: :not(*) +Pass Detached Element.querySelector: :not pseudo-class selector, matching nothing: :not(*) +Pass Detached Element.querySelectorAll: :not pseudo-class selector, matching nothing: :not(*|*) +Pass Detached Element.querySelector: :not pseudo-class selector, matching nothing: :not(*|*) +Pass Detached Element.querySelectorAll: :not pseudo-class selector argument surrounded by spaces, matching : #not>:not( div ) +Pass Detached Element.querySelector: :not pseudo-class selector argument surrounded by spaces, matching : #not>:not( div ) +Pass Detached Element.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line +Pass Detached Element.querySelector: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line +Pass Detached Element.querySelectorAll: ::first-line pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-line +Pass Detached Element.querySelector: ::first-line pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-line +Pass Detached Element.querySelectorAll: :first-letter pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-letter +Pass Detached Element.querySelector: :first-letter pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-letter +Pass Detached Element.querySelectorAll: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter +Pass Detached Element.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter +Pass Detached Element.querySelectorAll: :before pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:before +Pass Detached Element.querySelector: :before pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:before +Pass Detached Element.querySelectorAll: ::before pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::before +Pass Detached Element.querySelector: ::before pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::before +Pass Detached Element.querySelectorAll: :after pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:after +Pass Detached Element.querySelector: :after pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:after +Pass Detached Element.querySelectorAll: ::after pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::after +Pass Detached Element.querySelector: ::after pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::after +Pass Detached Element.querySelectorAll: Class selector, matching element with specified class: .class-p +Pass Detached Element.querySelector: Class selector, matching element with specified class: .class-p +Pass Detached Element.querySelectorAll: Class selector, chained, matching only elements with all specified classes: #class .apple.orange.banana +Pass Detached Element.querySelector: Class selector, chained, matching only elements with all specified classes: #class .apple.orange.banana +Pass Detached Element.querySelectorAll: Class Selector, chained, with type selector: div.apple.banana.orange +Pass Detached Element.querySelector: Class Selector, chained, with type selector: div.apple.banana.orange +Pass Detached Element.querySelectorAll: Class selector, matching element with class value using non-ASCII characters (1): .台北Táiběi +Pass Detached Element.querySelector: Class selector, matching element with class value using non-ASCII characters (1): .台北Táiběi +Pass Detached Element.querySelectorAll: Class selector, matching multiple elements with class value using non-ASCII characters: .台北 +Pass Detached Element.querySelector: Class selector, matching multiple elements with class value using non-ASCII characters: .台北 +Pass Detached Element.querySelectorAll: Class selector, chained, matching element with multiple class values using non-ASCII characters (1): .台北Táiběi.台北 +Pass Detached Element.querySelector: Class selector, chained, matching element with multiple class values using non-ASCII characters (1): .台北Táiběi.台北 +Pass Detached Element.querySelectorAll: Class selector, matching element with class with escaped character: .foo\:bar +Pass Detached Element.querySelector: Class selector, matching element with class with escaped character: .foo\:bar +Pass Detached Element.querySelectorAll: Class selector, matching element with class with escaped character: .test\.foo\[5\]bar +Pass Detached Element.querySelector: Class selector, matching element with class with escaped character: .test\.foo\[5\]bar +Pass Detached Element.querySelectorAll: ID selector, matching element with specified id: #id #id-div1 +Pass Detached Element.querySelector: ID selector, matching element with specified id: #id #id-div1 +Fail Detached Element.querySelectorAll: ID selector, chained, matching element with specified id: #id-div1, #id-div1 +Pass Detached Element.querySelector: ID selector, chained, matching element with specified id: #id-div1, #id-div1 +Pass Detached Element.querySelectorAll: ID selector, chained, matching element with specified id: #id-div1, #id-div2 +Pass Detached Element.querySelector: ID selector, chained, matching element with specified id: #id-div1, #id-div2 +Pass Detached Element.querySelectorAll: ID Selector, chained, with type selector: div#id-div1, div#id-div2 +Pass Detached Element.querySelector: ID Selector, chained, with type selector: div#id-div1, div#id-div2 +Pass Detached Element.querySelectorAll: ID selector, not matching non-existent descendant: #id #none +Pass Detached Element.querySelector: ID selector, not matching non-existent descendant: #id #none +Pass Detached Element.querySelectorAll: ID selector, not matching non-existent ancestor: #none #id-div1 +Pass Detached Element.querySelector: ID selector, not matching non-existent ancestor: #none #id-div1 +Pass Detached Element.querySelectorAll: ID selector, matching multiple elements with duplicate id: #id-li-duplicate +Pass Detached Element.querySelector: ID selector, matching multiple elements with duplicate id: #id-li-duplicate +Pass Detached Element.querySelectorAll: ID selector, matching id value using non-ASCII characters (1): #台北Táiběi +Pass Detached Element.querySelector: ID selector, matching id value using non-ASCII characters (1): #台北Táiběi +Pass Detached Element.querySelectorAll: ID selector, matching id value using non-ASCII characters (2): #台北 +Pass Detached Element.querySelector: ID selector, matching id value using non-ASCII characters (2): #台北 +Pass Detached Element.querySelectorAll: ID selector, matching id values using non-ASCII characters (1): #台北Táiběi, #台北 +Pass Detached Element.querySelector: ID selector, matching id values using non-ASCII characters (1): #台北Táiběi, #台北 +Pass Detached Element.querySelectorAll: ID selector, matching element with id with escaped character: #\#foo\:bar +Pass Detached Element.querySelector: ID selector, matching element with id with escaped character: #\#foo\:bar +Pass Detached Element.querySelectorAll: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar +Pass Detached Element.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar +Pass Detached Element.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div +Pass Detached Element.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div +Pass Detached Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div +Pass Detached Element.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div +Pass Detached Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* +Pass Detached Element.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* +Pass Detached Element.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div +Pass Detached Element.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div +Pass Detached Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 +Pass Detached Element.querySelector: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 +Pass Detached Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element with id: #descendant #descendant-div2 +Pass Detached Element.querySelector: Descendant combinator, matching element with id that is a descendant of an element with id: #descendant #descendant-div2 +Pass Detached Element.querySelectorAll: Descendant combinator, matching element with class that is a descendant of an element with id: #descendant .descendant-div2 +Pass Detached Element.querySelector: Descendant combinator, matching element with class that is a descendant of an element with id: #descendant .descendant-div2 +Pass Detached Element.querySelectorAll: Descendant combinator, matching element with class that is a descendant of an element with class: .descendant-div1 .descendant-div3 +Pass Detached Element.querySelector: Descendant combinator, matching element with class that is a descendant of an element with class: .descendant-div1 .descendant-div3 +Pass Detached Element.querySelectorAll: Descendant combinator, not matching element with id that is not a descendant of an element with id: #descendant-div1 #descendant-div4 +Pass Detached Element.querySelector: Descendant combinator, not matching element with id that is not a descendant of an element with id: #descendant-div1 #descendant-div4 +Pass Detached Element.querySelectorAll: Descendant combinator, whitespace characters: #descendant #descendant-div2 +Pass Detached Element.querySelector: Descendant combinator, whitespace characters: #descendant #descendant-div2 +Pass Detached Element.querySelectorAll: Child combinator, matching element that is a child of an element with id: #child>div +Pass Detached Element.querySelector: Child combinator, matching element that is a child of an element with id: #child>div +Pass Detached Element.querySelectorAll: Child combinator, matching element with id that is a child of an element: div>#child-div1 +Pass Detached Element.querySelector: Child combinator, matching element with id that is a child of an element: div>#child-div1 +Pass Detached Element.querySelectorAll: Child combinator, matching element with id that is a child of an element with id: #child>#child-div1 +Pass Detached Element.querySelector: Child combinator, matching element with id that is a child of an element with id: #child>#child-div1 +Pass Detached Element.querySelectorAll: Child combinator, matching element with id that is a child of an element with class: #child-div1>.child-div2 +Pass Detached Element.querySelector: Child combinator, matching element with id that is a child of an element with class: #child-div1>.child-div2 +Pass Detached Element.querySelectorAll: Child combinator, matching element with class that is a child of an element with class: .child-div1>.child-div2 +Pass Detached Element.querySelector: Child combinator, matching element with class that is a child of an element with class: .child-div1>.child-div2 +Pass Detached Element.querySelectorAll: Child combinator, not matching element with id that is not a child of an element with id: #child>#child-div3 +Pass Detached Element.querySelector: Child combinator, not matching element with id that is not a child of an element with id: #child>#child-div3 +Pass Detached Element.querySelectorAll: Child combinator, not matching element with id that is not a child of an element with class: #child-div1>.child-div3 +Pass Detached Element.querySelector: Child combinator, not matching element with id that is not a child of an element with class: #child-div1>.child-div3 +Pass Detached Element.querySelectorAll: Child combinator, not matching element with class that is not a child of an element with class: .child-div1>.child-div3 +Pass Detached Element.querySelector: Child combinator, not matching element with class that is not a child of an element with class: .child-div1>.child-div3 +Pass Detached Element.querySelectorAll: Child combinator, surrounded by whitespace: #child-div1 > #child-div2 +Pass Detached Element.querySelector: Child combinator, surrounded by whitespace: #child-div1 > #child-div2 +Pass Detached Element.querySelectorAll: Child combinator, whitespace after: #child-div1> #child-div2 +Pass Detached Element.querySelector: Child combinator, whitespace after: #child-div1> #child-div2 +Pass Detached Element.querySelectorAll: Child combinator, whitespace before: #child-div1 >#child-div2 +Pass Detached Element.querySelector: Child combinator, whitespace before: #child-div1 >#child-div2 +Pass Detached Element.querySelectorAll: Child combinator, no whitespace: #child-div1>#child-div2 +Pass Detached Element.querySelector: Child combinator, no whitespace: #child-div1>#child-div2 +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id: #adjacent-div2+div +Pass Detached Element.querySelector: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id: #adjacent-div2+div +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element: div+#adjacent-div4 +Pass Detached Element.querySelector: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element: div+#adjacent-div4 +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id: #adjacent-div2+#adjacent-div4 +Pass Detached Element.querySelector: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id: #adjacent-div2+#adjacent-div4 +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id: #adjacent-div2+.adjacent-div4 +Pass Detached Element.querySelector: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id: #adjacent-div2+.adjacent-div4 +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class: .adjacent-div2+.adjacent-div4 +Pass Detached Element.querySelector: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class: .adjacent-div2+.adjacent-div4 +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element: #adjacent div+p +Pass Detached Element.querySelector: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element: #adjacent div+p +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id: #adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1 +Pass Detached Element.querySelector: Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id: #adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1 +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, surrounded by whitespace: #adjacent-p2 + #adjacent-p3 +Pass Detached Element.querySelector: Adjacent sibling combinator, surrounded by whitespace: #adjacent-p2 + #adjacent-p3 +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, whitespace after: #adjacent-p2+ #adjacent-p3 +Pass Detached Element.querySelector: Adjacent sibling combinator, whitespace after: #adjacent-p2+ #adjacent-p3 +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, whitespace before: #adjacent-p2 +#adjacent-p3 +Pass Detached Element.querySelector: Adjacent sibling combinator, whitespace before: #adjacent-p2 +#adjacent-p3 +Pass Detached Element.querySelectorAll: Adjacent sibling combinator, no whitespace: #adjacent-p2+#adjacent-p3 +Pass Detached Element.querySelector: Adjacent sibling combinator, no whitespace: #adjacent-p2+#adjacent-p3 +Pass Detached Element.querySelectorAll: General sibling combinator, matching element that is a sibling of an element with id: #sibling-div2~div +Pass Detached Element.querySelector: General sibling combinator, matching element that is a sibling of an element with id: #sibling-div2~div +Pass Detached Element.querySelectorAll: General sibling combinator, matching element with id that is a sibling of an element: div~#sibling-div4 +Pass Detached Element.querySelector: General sibling combinator, matching element with id that is a sibling of an element: div~#sibling-div4 +Pass Detached Element.querySelectorAll: General sibling combinator, matching element with id that is a sibling of an element with id: #sibling-div2~#sibling-div4 +Pass Detached Element.querySelector: General sibling combinator, matching element with id that is a sibling of an element with id: #sibling-div2~#sibling-div4 +Pass Detached Element.querySelectorAll: General sibling combinator, matching element with class that is a sibling of an element with id: #sibling-div2~.sibling-div +Pass Detached Element.querySelector: General sibling combinator, matching element with class that is a sibling of an element with id: #sibling-div2~.sibling-div +Pass Detached Element.querySelectorAll: General sibling combinator, matching p element that is a sibling of a div element: #sibling div~p +Pass Detached Element.querySelector: General sibling combinator, matching p element that is a sibling of a div element: #sibling div~p +Pass Detached Element.querySelectorAll: General sibling combinator, not matching element with id that is not a sibling after a p element: #sibling>p~div +Pass Detached Element.querySelector: General sibling combinator, not matching element with id that is not a sibling after a p element: #sibling>p~div +Pass Detached Element.querySelectorAll: General sibling combinator, not matching element with id that is not a sibling after an element with id: #sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1 +Pass Detached Element.querySelector: General sibling combinator, not matching element with id that is not a sibling after an element with id: #sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1 +Pass Detached Element.querySelectorAll: General sibling combinator, surrounded by whitespace: #sibling-p2 ~ #sibling-p3 +Pass Detached Element.querySelector: General sibling combinator, surrounded by whitespace: #sibling-p2 ~ #sibling-p3 +Pass Detached Element.querySelectorAll: General sibling combinator, whitespace after: #sibling-p2~ #sibling-p3 +Pass Detached Element.querySelector: General sibling combinator, whitespace after: #sibling-p2~ #sibling-p3 +Pass Detached Element.querySelectorAll: General sibling combinator, whitespace before: #sibling-p2 ~#sibling-p3 +Pass Detached Element.querySelector: General sibling combinator, whitespace before: #sibling-p2 ~#sibling-p3 +Pass Detached Element.querySelectorAll: General sibling combinator, no whitespace: #sibling-p2~#sibling-p3 +Pass Detached Element.querySelector: General sibling combinator, no whitespace: #sibling-p2~#sibling-p3 +Pass Detached Element.querySelectorAll: Syntax, group of selectors separator, surrounded by whitespace: #group em , #group strong +Pass Detached Element.querySelector: Syntax, group of selectors separator, surrounded by whitespace: #group em , #group strong +Pass Detached Element.querySelectorAll: Syntax, group of selectors separator, whitespace after: #group em, #group strong +Pass Detached Element.querySelector: Syntax, group of selectors separator, whitespace after: #group em, #group strong +Pass Detached Element.querySelectorAll: Syntax, group of selectors separator, whitespace before: #group em ,#group strong +Pass Detached Element.querySelector: Syntax, group of selectors separator, whitespace before: #group em ,#group strong +Pass Detached Element.querySelectorAll: Syntax, group of selectors separator, no whitespace: #group em,#group strong +Pass Detached Element.querySelector: Syntax, group of selectors separator, no whitespace: #group em,#group strong +Fail Detached Element.querySelectorAll: Slotted selector: ::slotted(foo) Failed to parse selector +Fail Detached Element.querySelector: Slotted selector: ::slotted(foo) Failed to parse selector +Fail Detached Element.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo Failed to parse selector +Fail Detached Element.querySelector: Slotted selector (no matching closing paren): ::slotted(foo Failed to parse selector +Pass Fragment.querySelectorAll: Type selector, matching html element: html +Pass Fragment.querySelector: Type selector, matching html element: html +Pass Fragment.querySelectorAll: Type selector, matching body element: body +Pass Fragment.querySelector: Type selector, matching body element: body +Pass Fragment.querySelectorAll: Universal selector, matching all children of element with specified ID: #universal>* +Pass Fragment.querySelector: Universal selector, matching all children of element with specified ID: #universal>* +Pass Fragment.querySelectorAll: Universal selector, matching all grandchildren of element with specified ID: #universal>*>* +Pass Fragment.querySelector: Universal selector, matching all grandchildren of element with specified ID: #universal>*>* +Pass Fragment.querySelectorAll: Universal selector, matching all children of empty element with specified ID: #empty>* +Pass Fragment.querySelector: Universal selector, matching all children of empty element with specified ID: #empty>* +Pass Fragment.querySelectorAll: Universal selector, matching all descendants of element with specified ID: #universal * +Pass Fragment.querySelector: Universal selector, matching all descendants of element with specified ID: #universal * +Pass Fragment.querySelectorAll: Attribute presence selector, matching align attribute with value: .attr-presence-div1[align] +Pass Fragment.querySelector: Attribute presence selector, matching align attribute with value: .attr-presence-div1[align] +Pass Fragment.querySelectorAll: Attribute presence selector, matching align attribute with empty value: .attr-presence-div2[align] +Pass Fragment.querySelector: Attribute presence selector, matching align attribute with empty value: .attr-presence-div2[align] +Fail Fragment.querySelectorAll: Attribute presence selector, matching title attribute, case insensitivity: #attr-presence [*|TiTlE] +Fail Fragment.querySelector: Attribute presence selector, matching title attribute, case insensitivity: #attr-presence [*|TiTlE] +Pass Fragment.querySelectorAll: Attribute presence selector, matching custom data-* attribute: [data-attr-presence] +Pass Fragment.querySelector: Attribute presence selector, matching custom data-* attribute: [data-attr-presence] +Pass Fragment.querySelectorAll: Attribute presence selector, not matching attribute with similar name: .attr-presence-div3[align], .attr-presence-div4[align] +Pass Fragment.querySelector: Attribute presence selector, not matching attribute with similar name: .attr-presence-div3[align], .attr-presence-div4[align] +Pass Fragment.querySelectorAll: Attribute presence selector, matching attribute with non-ASCII characters: ul[data-中文] +Pass Fragment.querySelector: Attribute presence selector, matching attribute with non-ASCII characters: ul[data-中文] +Pass Fragment.querySelectorAll: Attribute presence selector, not matching default option without selected attribute: #attr-presence-select1 option[selected] +Pass Fragment.querySelector: Attribute presence selector, not matching default option without selected attribute: #attr-presence-select1 option[selected] +Pass Fragment.querySelectorAll: Attribute presence selector, matching option with selected attribute: #attr-presence-select2 option[selected] +Pass Fragment.querySelector: Attribute presence selector, matching option with selected attribute: #attr-presence-select2 option[selected] +Pass Fragment.querySelectorAll: Attribute presence selector, matching multiple options with selected attributes: #attr-presence-select3 option[selected] +Pass Fragment.querySelector: Attribute presence selector, matching multiple options with selected attributes: #attr-presence-select3 option[selected] +Pass Fragment.querySelectorAll: Attribute value selector, matching align attribute with value: #attr-value [align="center"] +Pass Fragment.querySelector: Attribute value selector, matching align attribute with value: #attr-value [align="center"] +Pass Fragment.querySelectorAll: Attribute value selector, matching align attribute with value, unclosed bracket: #attr-value [align="center" +Pass Fragment.querySelector: Attribute value selector, matching align attribute with value, unclosed bracket: #attr-value [align="center" +Pass Fragment.querySelectorAll: Attribute value selector, matching align attribute with empty value: #attr-value [align=""] +Pass Fragment.querySelector: Attribute value selector, matching align attribute with empty value: #attr-value [align=""] +Pass Fragment.querySelectorAll: Attribute value selector, not matching align attribute with partial value: #attr-value [align="c"] +Pass Fragment.querySelector: Attribute value selector, not matching align attribute with partial value: #attr-value [align="c"] +Pass Fragment.querySelectorAll: Attribute value selector, not matching align attribute with incorrect value: #attr-value [align="centera"] +Pass Fragment.querySelector: Attribute value selector, not matching align attribute with incorrect value: #attr-value [align="centera"] +Pass Fragment.querySelectorAll: Attribute value selector, matching custom data-* attribute with unicode escaped value: [data-attr-value="\e9"] +Pass Fragment.querySelector: Attribute value selector, matching custom data-* attribute with unicode escaped value: [data-attr-value="\e9"] +Pass Fragment.querySelectorAll: Attribute value selector, matching custom data-* attribute with escaped character: [data-attr-value_foo="\e9"] +Pass Fragment.querySelector: Attribute value selector, matching custom data-* attribute with escaped character: [data-attr-value_foo="\e9"] +Pass Fragment.querySelectorAll: Attribute value selector with single-quoted value, matching multiple inputs with type attributes: #attr-value input[type='hidden'],#attr-value input[type='radio'] +Pass Fragment.querySelector: Attribute value selector with single-quoted value, matching multiple inputs with type attributes: #attr-value input[type='hidden'],#attr-value input[type='radio'] +Pass Fragment.querySelectorAll: Attribute value selector with double-quoted value, matching multiple inputs with type attributes: #attr-value input[type="hidden"],#attr-value input[type='radio'] +Pass Fragment.querySelector: Attribute value selector with double-quoted value, matching multiple inputs with type attributes: #attr-value input[type="hidden"],#attr-value input[type='radio'] +Pass Fragment.querySelectorAll: Attribute value selector with unquoted value, matching multiple inputs with type attributes: #attr-value input[type=hidden],#attr-value input[type=radio] +Pass Fragment.querySelector: Attribute value selector with unquoted value, matching multiple inputs with type attributes: #attr-value input[type=hidden],#attr-value input[type=radio] +Pass Fragment.querySelectorAll: Attribute value selector, matching attribute with value using non-ASCII characters: [data-attr-value=中文] +Pass Fragment.querySelector: Attribute value selector, matching attribute with value using non-ASCII characters: [data-attr-value=中文] +Pass Fragment.querySelectorAll: Attribute whitespace-separated list selector, matching class attribute with value: #attr-whitespace [class~="div1"] +Pass Fragment.querySelector: Attribute whitespace-separated list selector, matching class attribute with value: #attr-whitespace [class~="div1"] +Pass Fragment.querySelectorAll: Attribute whitespace-separated list selector, not matching class attribute with empty value: #attr-whitespace [class~=""] +Pass Fragment.querySelector: Attribute whitespace-separated list selector, not matching class attribute with empty value: #attr-whitespace [class~=""] +Pass Fragment.querySelectorAll: Attribute whitespace-separated list selector, not matching class attribute with partial value: [data-attr-whitespace~="div"] +Pass Fragment.querySelector: Attribute whitespace-separated list selector, not matching class attribute with partial value: [data-attr-whitespace~="div"] +Pass Fragment.querySelectorAll: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value: [data-attr-whitespace~="\0000e9"] +Pass Fragment.querySelector: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value: [data-attr-whitespace~="\0000e9"] +Pass Fragment.querySelectorAll: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character: [data-attr-whitespace_foo~="\e9"] +Pass Fragment.querySelector: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character: [data-attr-whitespace_foo~="\e9"] +Pass Fragment.querySelectorAll: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +Pass Fragment.querySelector: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +Pass Fragment.querySelectorAll: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +Pass Fragment.querySelector: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +Pass Fragment.querySelectorAll: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +Pass Fragment.querySelector: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +Pass Fragment.querySelectorAll: Attribute whitespace-separated list selector with double-quoted value, not matching value with space: #attr-whitespace a[rel~="book mark"] +Pass Fragment.querySelector: Attribute whitespace-separated list selector with double-quoted value, not matching value with space: #attr-whitespace a[rel~="book mark"] +Pass Fragment.querySelectorAll: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters: #attr-whitespace [title~=中文] +Pass Fragment.querySelector: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters: #attr-whitespace [title~=中文] +Pass Fragment.querySelectorAll: Attribute hyphen-separated list selector, not matching unspecified lang attribute: #attr-hyphen-div1[lang|="en"] +Pass Fragment.querySelector: Attribute hyphen-separated list selector, not matching unspecified lang attribute: #attr-hyphen-div1[lang|="en"] +Pass Fragment.querySelectorAll: Attribute hyphen-separated list selector, matching lang attribute with exact value: #attr-hyphen-div2[lang|="fr"] +Pass Fragment.querySelector: Attribute hyphen-separated list selector, matching lang attribute with exact value: #attr-hyphen-div2[lang|="fr"] +Pass Fragment.querySelectorAll: Attribute hyphen-separated list selector, matching lang attribute with partial value: #attr-hyphen-div3[lang|="en"] +Pass Fragment.querySelector: Attribute hyphen-separated list selector, matching lang attribute with partial value: #attr-hyphen-div3[lang|="en"] +Pass Fragment.querySelectorAll: Attribute hyphen-separated list selector, not matching incorrect value: #attr-hyphen-div4[lang|="es-AR"] +Pass Fragment.querySelector: Attribute hyphen-separated list selector, not matching incorrect value: #attr-hyphen-div4[lang|="es-AR"] +Pass Fragment.querySelectorAll: Attribute begins with selector, matching href attributes beginning with specified substring: #attr-begins a[href^="http://www"] +Pass Fragment.querySelector: Attribute begins with selector, matching href attributes beginning with specified substring: #attr-begins a[href^="http://www"] +Pass Fragment.querySelectorAll: Attribute begins with selector, matching lang attributes beginning with specified substring, : #attr-begins [lang^="en-"] +Pass Fragment.querySelector: Attribute begins with selector, matching lang attributes beginning with specified substring, : #attr-begins [lang^="en-"] +Pass Fragment.querySelectorAll: Attribute begins with selector, not matching class attribute with empty value: #attr-begins [class^=""] +Pass Fragment.querySelector: Attribute begins with selector, not matching class attribute with empty value: #attr-begins [class^=""] +Pass Fragment.querySelectorAll: Attribute begins with selector, not matching class attribute not beginning with specified substring: #attr-begins [class^=apple] +Pass Fragment.querySelector: Attribute begins with selector, not matching class attribute not beginning with specified substring: #attr-begins [class^=apple] +Pass Fragment.querySelectorAll: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=' apple'] +Pass Fragment.querySelector: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=' apple'] +Pass Fragment.querySelectorAll: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=" apple"] +Pass Fragment.querySelector: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=" apple"] +Pass Fragment.querySelectorAll: Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring: #attr-begins [class^= apple] +Pass Fragment.querySelector: Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring: #attr-begins [class^= apple] +Pass Fragment.querySelectorAll: Attribute ends with selector, matching href attributes ending with specified substring: #attr-ends a[href$=".org"] +Pass Fragment.querySelector: Attribute ends with selector, matching href attributes ending with specified substring: #attr-ends a[href$=".org"] +Pass Fragment.querySelectorAll: Attribute ends with selector, matching lang attributes ending with specified substring, : #attr-ends [lang$="-CH"] +Pass Fragment.querySelector: Attribute ends with selector, matching lang attributes ending with specified substring, : #attr-ends [lang$="-CH"] +Pass Fragment.querySelectorAll: Attribute ends with selector, not matching class attribute with empty value: #attr-ends [class$=""] +Pass Fragment.querySelector: Attribute ends with selector, not matching class attribute with empty value: #attr-ends [class$=""] +Pass Fragment.querySelectorAll: Attribute ends with selector, not matching class attribute not ending with specified substring: #attr-ends [class$=apple] +Pass Fragment.querySelector: Attribute ends with selector, not matching class attribute not ending with specified substring: #attr-ends [class$=apple] +Pass Fragment.querySelectorAll: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring: #attr-ends [class$='apple '] +Pass Fragment.querySelector: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring: #attr-ends [class$='apple '] +Pass Fragment.querySelectorAll: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring: #attr-ends [class$="apple "] +Pass Fragment.querySelector: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring: #attr-ends [class$="apple "] +Pass Fragment.querySelectorAll: Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring: #attr-ends [class$=apple ] +Pass Fragment.querySelector: Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring: #attr-ends [class$=apple ] +Pass Fragment.querySelectorAll: Attribute contains selector, matching href attributes beginning with specified substring: #attr-contains a[href*="http://www"] +Pass Fragment.querySelector: Attribute contains selector, matching href attributes beginning with specified substring: #attr-contains a[href*="http://www"] +Pass Fragment.querySelectorAll: Attribute contains selector, matching href attributes ending with specified substring: #attr-contains a[href*=".org"] +Pass Fragment.querySelector: Attribute contains selector, matching href attributes ending with specified substring: #attr-contains a[href*=".org"] +Pass Fragment.querySelectorAll: Attribute contains selector, matching href attributes containing specified substring: #attr-contains a[href*=".example."] +Pass Fragment.querySelector: Attribute contains selector, matching href attributes containing specified substring: #attr-contains a[href*=".example."] +Pass Fragment.querySelectorAll: Attribute contains selector, matching lang attributes beginning with specified substring, : #attr-contains [lang*="en-"] +Pass Fragment.querySelector: Attribute contains selector, matching lang attributes beginning with specified substring, : #attr-contains [lang*="en-"] +Pass Fragment.querySelectorAll: Attribute contains selector, matching lang attributes ending with specified substring, : #attr-contains [lang*="-CH"] +Pass Fragment.querySelector: Attribute contains selector, matching lang attributes ending with specified substring, : #attr-contains [lang*="-CH"] +Pass Fragment.querySelectorAll: Attribute contains selector, not matching class attribute with empty value: #attr-contains [class*=""] +Pass Fragment.querySelector: Attribute contains selector, not matching class attribute with empty value: #attr-contains [class*=""] +Pass Fragment.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=' apple'] +Pass Fragment.querySelector: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=' apple'] +Pass Fragment.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring: #attr-contains [class*='orange '] +Pass Fragment.querySelector: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring: #attr-contains [class*='orange '] +Pass Fragment.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute containing specified substring: #attr-contains [class*='ple banana ora'] +Pass Fragment.querySelector: Attribute contains selector with single-quoted value, matching class attribute containing specified substring: #attr-contains [class*='ple banana ora'] +Pass Fragment.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=" apple"] +Pass Fragment.querySelector: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=" apple"] +Pass Fragment.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring: #attr-contains [class*="orange "] +Pass Fragment.querySelector: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring: #attr-contains [class*="orange "] +Pass Fragment.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute containing specified substring: #attr-contains [class*="ple banana ora"] +Pass Fragment.querySelector: Attribute contains selector with double-quoted value, matching class attribute containing specified substring: #attr-contains [class*="ple banana ora"] +Pass Fragment.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring: #attr-contains [class*= apple] +Pass Fragment.querySelector: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring: #attr-contains [class*= apple] +Pass Fragment.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute ending with specified substring: #attr-contains [class*=orange ] +Pass Fragment.querySelector: Attribute contains selector with unquoted value, matching class attribute ending with specified substring: #attr-contains [class*=orange ] +Pass Fragment.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute containing specified substring: #attr-contains [class*= banana ] +Pass Fragment.querySelector: Attribute contains selector with unquoted value, matching class attribute containing specified substring: #attr-contains [class*= banana ] +Pass Fragment.querySelectorAll: :root pseudo-class selector, not matching document root element: :root +Pass Fragment.querySelector: :root pseudo-class selector, not matching document root element: :root +Pass Fragment.querySelectorAll: :nth-child selector, matching the third child element: #pseudo-nth-table1 :nth-child(3) +Pass Fragment.querySelector: :nth-child selector, matching the third child element: #pseudo-nth-table1 :nth-child(3) +Pass Fragment.querySelectorAll: :nth-child selector, matching every third child element: #pseudo-nth li:nth-child(3n) +Pass Fragment.querySelector: :nth-child selector, matching every third child element: #pseudo-nth li:nth-child(3n) +Pass Fragment.querySelectorAll: :nth-child selector, matching every second child element, starting from the fourth: #pseudo-nth li:nth-child(2n+4) +Pass Fragment.querySelector: :nth-child selector, matching every second child element, starting from the fourth: #pseudo-nth li:nth-child(2n+4) +Pass Fragment.querySelectorAll: :nth-child selector, matching every fourth child element, starting from the third: #pseudo-nth-p1 :nth-child(4n-1) +Pass Fragment.querySelector: :nth-child selector, matching every fourth child element, starting from the third: #pseudo-nth-p1 :nth-child(4n-1) +Pass Fragment.querySelectorAll: :nth-last-child selector, matching the third last child element: #pseudo-nth-table1 :nth-last-child(3) +Pass Fragment.querySelector: :nth-last-child selector, matching the third last child element: #pseudo-nth-table1 :nth-last-child(3) +Pass Fragment.querySelectorAll: :nth-last-child selector, matching every third child element from the end: #pseudo-nth li:nth-last-child(3n) +Pass Fragment.querySelector: :nth-last-child selector, matching every third child element from the end: #pseudo-nth li:nth-last-child(3n) +Pass Fragment.querySelectorAll: :nth-last-child selector, matching every second child element from the end, starting from the fourth last: #pseudo-nth li:nth-last-child(2n+4) +Pass Fragment.querySelector: :nth-last-child selector, matching every second child element from the end, starting from the fourth last: #pseudo-nth li:nth-last-child(2n+4) +Pass Fragment.querySelectorAll: :nth-last-child selector, matching every fourth element from the end, starting from the third last: #pseudo-nth-p1 :nth-last-child(4n-1) +Pass Fragment.querySelector: :nth-last-child selector, matching every fourth element from the end, starting from the third last: #pseudo-nth-p1 :nth-last-child(4n-1) +Pass Fragment.querySelectorAll: :nth-of-type selector, matching the third em element: #pseudo-nth-p1 em:nth-of-type(3) +Pass Fragment.querySelector: :nth-of-type selector, matching the third em element: #pseudo-nth-p1 em:nth-of-type(3) +Pass Fragment.querySelectorAll: :nth-of-type selector, matching every second element of their type: #pseudo-nth-p1 :nth-of-type(2n) +Pass Fragment.querySelector: :nth-of-type selector, matching every second element of their type: #pseudo-nth-p1 :nth-of-type(2n) +Pass Fragment.querySelectorAll: :nth-of-type selector, matching every second elemetn of their type, starting from the first: #pseudo-nth-p1 span:nth-of-type(2n-1) +Pass Fragment.querySelector: :nth-of-type selector, matching every second elemetn of their type, starting from the first: #pseudo-nth-p1 span:nth-of-type(2n-1) +Pass Fragment.querySelectorAll: :nth-last-of-type selector, matching the third last em element: #pseudo-nth-p1 em:nth-last-of-type(3) +Pass Fragment.querySelector: :nth-last-of-type selector, matching the third last em element: #pseudo-nth-p1 em:nth-last-of-type(3) +Pass Fragment.querySelectorAll: :nth-last-of-type selector, matching every second last element of their type: #pseudo-nth-p1 :nth-last-of-type(2n) +Pass Fragment.querySelector: :nth-last-of-type selector, matching every second last element of their type: #pseudo-nth-p1 :nth-last-of-type(2n) +Pass Fragment.querySelectorAll: :nth-last-of-type selector, matching every second last element of their type, starting from the last: #pseudo-nth-p1 span:nth-last-of-type(2n-1) +Pass Fragment.querySelector: :nth-last-of-type selector, matching every second last element of their type, starting from the last: #pseudo-nth-p1 span:nth-last-of-type(2n-1) +Pass Fragment.querySelectorAll: :first-of-type selector, matching the first em element: #pseudo-nth-p1 em:first-of-type +Pass Fragment.querySelector: :first-of-type selector, matching the first em element: #pseudo-nth-p1 em:first-of-type +Pass Fragment.querySelectorAll: :first-of-type selector, matching the first of every type of element: #pseudo-nth-p1 :first-of-type +Pass Fragment.querySelector: :first-of-type selector, matching the first of every type of element: #pseudo-nth-p1 :first-of-type +Pass Fragment.querySelectorAll: :first-of-type selector, matching the first td element in each table row: #pseudo-nth-table1 tr :first-of-type +Pass Fragment.querySelector: :first-of-type selector, matching the first td element in each table row: #pseudo-nth-table1 tr :first-of-type +Pass Fragment.querySelectorAll: :last-of-type selector, matching the last em elemnet: #pseudo-nth-p1 em:last-of-type +Pass Fragment.querySelector: :last-of-type selector, matching the last em elemnet: #pseudo-nth-p1 em:last-of-type +Pass Fragment.querySelectorAll: :last-of-type selector, matching the last of every type of element: #pseudo-nth-p1 :last-of-type +Pass Fragment.querySelector: :last-of-type selector, matching the last of every type of element: #pseudo-nth-p1 :last-of-type +Pass Fragment.querySelectorAll: :last-of-type selector, matching the last td element in each table row: #pseudo-nth-table1 tr :last-of-type +Pass Fragment.querySelector: :last-of-type selector, matching the last td element in each table row: #pseudo-nth-table1 tr :last-of-type +Pass Fragment.querySelectorAll: :first-child pseudo-class selector, matching first child div element: #pseudo-first-child div:first-child +Pass Fragment.querySelector: :first-child pseudo-class selector, matching first child div element: #pseudo-first-child div:first-child +Pass Fragment.querySelectorAll: :first-child pseudo-class selector, doesn't match non-first-child elements: .pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child +Pass Fragment.querySelector: :first-child pseudo-class selector, doesn't match non-first-child elements: .pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child +Pass Fragment.querySelectorAll: :first-child pseudo-class selector, matching first-child of multiple elements: #pseudo-first-child span:first-child +Pass Fragment.querySelector: :first-child pseudo-class selector, matching first-child of multiple elements: #pseudo-first-child span:first-child +Pass Fragment.querySelectorAll: :last-child pseudo-class selector, matching last child div element: #pseudo-last-child div:last-child +Pass Fragment.querySelector: :last-child pseudo-class selector, matching last child div element: #pseudo-last-child div:last-child +Pass Fragment.querySelectorAll: :last-child pseudo-class selector, doesn't match non-last-child elements: .pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child +Pass Fragment.querySelector: :last-child pseudo-class selector, doesn't match non-last-child elements: .pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child +Pass Fragment.querySelectorAll: :last-child pseudo-class selector, matching first-child of multiple elements: #pseudo-last-child span:last-child +Pass Fragment.querySelector: :last-child pseudo-class selector, matching first-child of multiple elements: #pseudo-last-child span:last-child +Pass Fragment.querySelectorAll: :pseudo-only-child pseudo-class selector, matching all only-child elements: #pseudo-only :only-child +Pass Fragment.querySelector: :pseudo-only-child pseudo-class selector, matching all only-child elements: #pseudo-only :only-child +Pass Fragment.querySelectorAll: :pseudo-only-child pseudo-class selector, matching only-child em elements: #pseudo-only em:only-child +Pass Fragment.querySelector: :pseudo-only-child pseudo-class selector, matching only-child em elements: #pseudo-only em:only-child +Pass Fragment.querySelectorAll: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type: #pseudo-only :only-of-type +Pass Fragment.querySelector: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type: #pseudo-only :only-of-type +Pass Fragment.querySelectorAll: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type: #pseudo-only em:only-of-type +Pass Fragment.querySelector: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type: #pseudo-only em:only-of-type +Pass Fragment.querySelectorAll: :empty pseudo-class selector, matching empty p elements: #pseudo-empty p:empty +Pass Fragment.querySelector: :empty pseudo-class selector, matching empty p elements: #pseudo-empty p:empty +Pass Fragment.querySelectorAll: :empty pseudo-class selector, matching all empty elements: #pseudo-empty :empty +Pass Fragment.querySelector: :empty pseudo-class selector, matching all empty elements: #pseudo-empty :empty +Pass Fragment.querySelectorAll: :link and :visited pseudo-class selectors, matching a and area elements with href attributes: #pseudo-link :link, #pseudo-link :visited +Pass Fragment.querySelector: :link and :visited pseudo-class selectors, matching a and area elements with href attributes: #pseudo-link :link, #pseudo-link :visited +Pass Fragment.querySelectorAll: :link and :visited pseudo-class selectors, not matching link elements with href attributes: #head :link, #head :visited +Pass Fragment.querySelector: :link and :visited pseudo-class selectors, not matching link elements with href attributes: #head :link, #head :visited +Pass Fragment.querySelectorAll: :link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing: :link:visited +Pass Fragment.querySelector: :link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing: :link:visited +Pass Fragment.querySelectorAll: :target pseudo-class selector, matching the element referenced by the URL fragment identifier: :target +Pass Fragment.querySelector: :target pseudo-class selector, matching the element referenced by the URL fragment identifier: :target +Pass Fragment.querySelectorAll: :lang pseudo-class selector, not matching element with no inherited language: #pseudo-lang-div1:lang(en) +Pass Fragment.querySelector: :lang pseudo-class selector, not matching element with no inherited language: #pseudo-lang-div1:lang(en) +Pass Fragment.querySelectorAll: :lang pseudo-class selector, matching specified language with exact value: #pseudo-lang-div2:lang(fr) +Pass Fragment.querySelector: :lang pseudo-class selector, matching specified language with exact value: #pseudo-lang-div2:lang(fr) +Pass Fragment.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en) +Pass Fragment.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en) +Pass Fragment.querySelectorAll: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) +Pass Fragment.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) +Pass Fragment.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled +Pass Fragment.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled +Pass Fragment.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +Pass Fragment.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +Pass Fragment.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +Pass Fragment.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +Pass Fragment.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +Pass Fragment.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +Pass Fragment.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked +Pass Fragment.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked +Pass Fragment.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div) +Pass Fragment.querySelector: :not pseudo-class selector, matching : #not>:not(div) +Pass Fragment.querySelectorAll: :not pseudo-class selector, matching : #not * :not(:first-child) +Pass Fragment.querySelector: :not pseudo-class selector, matching : #not * :not(:first-child) +Pass Fragment.querySelectorAll: :not pseudo-class selector, matching nothing: :not(*) +Pass Fragment.querySelector: :not pseudo-class selector, matching nothing: :not(*) +Pass Fragment.querySelectorAll: :not pseudo-class selector, matching nothing: :not(*|*) +Pass Fragment.querySelector: :not pseudo-class selector, matching nothing: :not(*|*) +Pass Fragment.querySelectorAll: :not pseudo-class selector argument surrounded by spaces, matching : #not>:not( div ) +Pass Fragment.querySelector: :not pseudo-class selector argument surrounded by spaces, matching : #not>:not( div ) +Pass Fragment.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line +Pass Fragment.querySelector: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line +Pass Fragment.querySelectorAll: ::first-line pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-line +Pass Fragment.querySelector: ::first-line pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-line +Pass Fragment.querySelectorAll: :first-letter pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-letter +Pass Fragment.querySelector: :first-letter pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-letter +Pass Fragment.querySelectorAll: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter +Pass Fragment.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter +Pass Fragment.querySelectorAll: :before pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:before +Pass Fragment.querySelector: :before pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:before +Pass Fragment.querySelectorAll: ::before pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::before +Pass Fragment.querySelector: ::before pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::before +Pass Fragment.querySelectorAll: :after pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:after +Pass Fragment.querySelector: :after pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:after +Pass Fragment.querySelectorAll: ::after pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::after +Pass Fragment.querySelector: ::after pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::after +Pass Fragment.querySelectorAll: Class selector, matching element with specified class: .class-p +Pass Fragment.querySelector: Class selector, matching element with specified class: .class-p +Pass Fragment.querySelectorAll: Class selector, chained, matching only elements with all specified classes: #class .apple.orange.banana +Pass Fragment.querySelector: Class selector, chained, matching only elements with all specified classes: #class .apple.orange.banana +Pass Fragment.querySelectorAll: Class Selector, chained, with type selector: div.apple.banana.orange +Pass Fragment.querySelector: Class Selector, chained, with type selector: div.apple.banana.orange +Pass Fragment.querySelectorAll: Class selector, matching element with class value using non-ASCII characters (1): .台北Táiběi +Pass Fragment.querySelector: Class selector, matching element with class value using non-ASCII characters (1): .台北Táiběi +Pass Fragment.querySelectorAll: Class selector, matching multiple elements with class value using non-ASCII characters: .台北 +Pass Fragment.querySelector: Class selector, matching multiple elements with class value using non-ASCII characters: .台北 +Pass Fragment.querySelectorAll: Class selector, chained, matching element with multiple class values using non-ASCII characters (1): .台北Táiběi.台北 +Pass Fragment.querySelector: Class selector, chained, matching element with multiple class values using non-ASCII characters (1): .台北Táiběi.台北 +Pass Fragment.querySelectorAll: Class selector, matching element with class with escaped character: .foo\:bar +Pass Fragment.querySelector: Class selector, matching element with class with escaped character: .foo\:bar +Pass Fragment.querySelectorAll: Class selector, matching element with class with escaped character: .test\.foo\[5\]bar +Pass Fragment.querySelector: Class selector, matching element with class with escaped character: .test\.foo\[5\]bar +Pass Fragment.querySelectorAll: ID selector, matching element with specified id: #id #id-div1 +Pass Fragment.querySelector: ID selector, matching element with specified id: #id #id-div1 +Fail Fragment.querySelectorAll: ID selector, chained, matching element with specified id: #id-div1, #id-div1 +Pass Fragment.querySelector: ID selector, chained, matching element with specified id: #id-div1, #id-div1 +Pass Fragment.querySelectorAll: ID selector, chained, matching element with specified id: #id-div1, #id-div2 +Pass Fragment.querySelector: ID selector, chained, matching element with specified id: #id-div1, #id-div2 +Pass Fragment.querySelectorAll: ID Selector, chained, with type selector: div#id-div1, div#id-div2 +Pass Fragment.querySelector: ID Selector, chained, with type selector: div#id-div1, div#id-div2 +Pass Fragment.querySelectorAll: ID selector, not matching non-existent descendant: #id #none +Pass Fragment.querySelector: ID selector, not matching non-existent descendant: #id #none +Pass Fragment.querySelectorAll: ID selector, not matching non-existent ancestor: #none #id-div1 +Pass Fragment.querySelector: ID selector, not matching non-existent ancestor: #none #id-div1 +Pass Fragment.querySelectorAll: ID selector, matching multiple elements with duplicate id: #id-li-duplicate +Pass Fragment.querySelector: ID selector, matching multiple elements with duplicate id: #id-li-duplicate +Pass Fragment.querySelectorAll: ID selector, matching id value using non-ASCII characters (1): #台北Táiběi +Pass Fragment.querySelector: ID selector, matching id value using non-ASCII characters (1): #台北Táiběi +Pass Fragment.querySelectorAll: ID selector, matching id value using non-ASCII characters (2): #台北 +Pass Fragment.querySelector: ID selector, matching id value using non-ASCII characters (2): #台北 +Pass Fragment.querySelectorAll: ID selector, matching id values using non-ASCII characters (1): #台北Táiběi, #台北 +Pass Fragment.querySelector: ID selector, matching id values using non-ASCII characters (1): #台北Táiběi, #台北 +Pass Fragment.querySelectorAll: ID selector, matching element with id with escaped character: #\#foo\:bar +Pass Fragment.querySelector: ID selector, matching element with id with escaped character: #\#foo\:bar +Pass Fragment.querySelectorAll: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar +Pass Fragment.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar +Pass Fragment.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div +Pass Fragment.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div +Pass Fragment.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div +Pass Fragment.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div +Pass Fragment.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* +Pass Fragment.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* +Pass Fragment.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div +Pass Fragment.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div +Pass Fragment.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 +Pass Fragment.querySelector: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 +Pass Fragment.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element with id: #descendant #descendant-div2 +Pass Fragment.querySelector: Descendant combinator, matching element with id that is a descendant of an element with id: #descendant #descendant-div2 +Pass Fragment.querySelectorAll: Descendant combinator, matching element with class that is a descendant of an element with id: #descendant .descendant-div2 +Pass Fragment.querySelector: Descendant combinator, matching element with class that is a descendant of an element with id: #descendant .descendant-div2 +Pass Fragment.querySelectorAll: Descendant combinator, matching element with class that is a descendant of an element with class: .descendant-div1 .descendant-div3 +Pass Fragment.querySelector: Descendant combinator, matching element with class that is a descendant of an element with class: .descendant-div1 .descendant-div3 +Pass Fragment.querySelectorAll: Descendant combinator, not matching element with id that is not a descendant of an element with id: #descendant-div1 #descendant-div4 +Pass Fragment.querySelector: Descendant combinator, not matching element with id that is not a descendant of an element with id: #descendant-div1 #descendant-div4 +Pass Fragment.querySelectorAll: Descendant combinator, whitespace characters: #descendant #descendant-div2 +Pass Fragment.querySelector: Descendant combinator, whitespace characters: #descendant #descendant-div2 +Pass Fragment.querySelectorAll: Child combinator, matching element that is a child of an element with id: #child>div +Pass Fragment.querySelector: Child combinator, matching element that is a child of an element with id: #child>div +Pass Fragment.querySelectorAll: Child combinator, matching element with id that is a child of an element: div>#child-div1 +Pass Fragment.querySelector: Child combinator, matching element with id that is a child of an element: div>#child-div1 +Pass Fragment.querySelectorAll: Child combinator, matching element with id that is a child of an element with id: #child>#child-div1 +Pass Fragment.querySelector: Child combinator, matching element with id that is a child of an element with id: #child>#child-div1 +Pass Fragment.querySelectorAll: Child combinator, matching element with id that is a child of an element with class: #child-div1>.child-div2 +Pass Fragment.querySelector: Child combinator, matching element with id that is a child of an element with class: #child-div1>.child-div2 +Pass Fragment.querySelectorAll: Child combinator, matching element with class that is a child of an element with class: .child-div1>.child-div2 +Pass Fragment.querySelector: Child combinator, matching element with class that is a child of an element with class: .child-div1>.child-div2 +Pass Fragment.querySelectorAll: Child combinator, not matching element with id that is not a child of an element with id: #child>#child-div3 +Pass Fragment.querySelector: Child combinator, not matching element with id that is not a child of an element with id: #child>#child-div3 +Pass Fragment.querySelectorAll: Child combinator, not matching element with id that is not a child of an element with class: #child-div1>.child-div3 +Pass Fragment.querySelector: Child combinator, not matching element with id that is not a child of an element with class: #child-div1>.child-div3 +Pass Fragment.querySelectorAll: Child combinator, not matching element with class that is not a child of an element with class: .child-div1>.child-div3 +Pass Fragment.querySelector: Child combinator, not matching element with class that is not a child of an element with class: .child-div1>.child-div3 +Pass Fragment.querySelectorAll: Child combinator, surrounded by whitespace: #child-div1 > #child-div2 +Pass Fragment.querySelector: Child combinator, surrounded by whitespace: #child-div1 > #child-div2 +Pass Fragment.querySelectorAll: Child combinator, whitespace after: #child-div1> #child-div2 +Pass Fragment.querySelector: Child combinator, whitespace after: #child-div1> #child-div2 +Pass Fragment.querySelectorAll: Child combinator, whitespace before: #child-div1 >#child-div2 +Pass Fragment.querySelector: Child combinator, whitespace before: #child-div1 >#child-div2 +Pass Fragment.querySelectorAll: Child combinator, no whitespace: #child-div1>#child-div2 +Pass Fragment.querySelector: Child combinator, no whitespace: #child-div1>#child-div2 +Pass Fragment.querySelectorAll: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id: #adjacent-div2+div +Pass Fragment.querySelector: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id: #adjacent-div2+div +Pass Fragment.querySelectorAll: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element: div+#adjacent-div4 +Pass Fragment.querySelector: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element: div+#adjacent-div4 +Pass Fragment.querySelectorAll: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id: #adjacent-div2+#adjacent-div4 +Pass Fragment.querySelector: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id: #adjacent-div2+#adjacent-div4 +Pass Fragment.querySelectorAll: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id: #adjacent-div2+.adjacent-div4 +Pass Fragment.querySelector: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id: #adjacent-div2+.adjacent-div4 +Pass Fragment.querySelectorAll: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class: .adjacent-div2+.adjacent-div4 +Pass Fragment.querySelector: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class: .adjacent-div2+.adjacent-div4 +Pass Fragment.querySelectorAll: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element: #adjacent div+p +Pass Fragment.querySelector: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element: #adjacent div+p +Pass Fragment.querySelectorAll: Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id: #adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1 +Pass Fragment.querySelector: Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id: #adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1 +Pass Fragment.querySelectorAll: Adjacent sibling combinator, surrounded by whitespace: #adjacent-p2 + #adjacent-p3 +Pass Fragment.querySelector: Adjacent sibling combinator, surrounded by whitespace: #adjacent-p2 + #adjacent-p3 +Pass Fragment.querySelectorAll: Adjacent sibling combinator, whitespace after: #adjacent-p2+ #adjacent-p3 +Pass Fragment.querySelector: Adjacent sibling combinator, whitespace after: #adjacent-p2+ #adjacent-p3 +Pass Fragment.querySelectorAll: Adjacent sibling combinator, whitespace before: #adjacent-p2 +#adjacent-p3 +Pass Fragment.querySelector: Adjacent sibling combinator, whitespace before: #adjacent-p2 +#adjacent-p3 +Pass Fragment.querySelectorAll: Adjacent sibling combinator, no whitespace: #adjacent-p2+#adjacent-p3 +Pass Fragment.querySelector: Adjacent sibling combinator, no whitespace: #adjacent-p2+#adjacent-p3 +Pass Fragment.querySelectorAll: General sibling combinator, matching element that is a sibling of an element with id: #sibling-div2~div +Pass Fragment.querySelector: General sibling combinator, matching element that is a sibling of an element with id: #sibling-div2~div +Pass Fragment.querySelectorAll: General sibling combinator, matching element with id that is a sibling of an element: div~#sibling-div4 +Pass Fragment.querySelector: General sibling combinator, matching element with id that is a sibling of an element: div~#sibling-div4 +Pass Fragment.querySelectorAll: General sibling combinator, matching element with id that is a sibling of an element with id: #sibling-div2~#sibling-div4 +Pass Fragment.querySelector: General sibling combinator, matching element with id that is a sibling of an element with id: #sibling-div2~#sibling-div4 +Pass Fragment.querySelectorAll: General sibling combinator, matching element with class that is a sibling of an element with id: #sibling-div2~.sibling-div +Pass Fragment.querySelector: General sibling combinator, matching element with class that is a sibling of an element with id: #sibling-div2~.sibling-div +Pass Fragment.querySelectorAll: General sibling combinator, matching p element that is a sibling of a div element: #sibling div~p +Pass Fragment.querySelector: General sibling combinator, matching p element that is a sibling of a div element: #sibling div~p +Pass Fragment.querySelectorAll: General sibling combinator, not matching element with id that is not a sibling after a p element: #sibling>p~div +Pass Fragment.querySelector: General sibling combinator, not matching element with id that is not a sibling after a p element: #sibling>p~div +Pass Fragment.querySelectorAll: General sibling combinator, not matching element with id that is not a sibling after an element with id: #sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1 +Pass Fragment.querySelector: General sibling combinator, not matching element with id that is not a sibling after an element with id: #sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1 +Pass Fragment.querySelectorAll: General sibling combinator, surrounded by whitespace: #sibling-p2 ~ #sibling-p3 +Pass Fragment.querySelector: General sibling combinator, surrounded by whitespace: #sibling-p2 ~ #sibling-p3 +Pass Fragment.querySelectorAll: General sibling combinator, whitespace after: #sibling-p2~ #sibling-p3 +Pass Fragment.querySelector: General sibling combinator, whitespace after: #sibling-p2~ #sibling-p3 +Pass Fragment.querySelectorAll: General sibling combinator, whitespace before: #sibling-p2 ~#sibling-p3 +Pass Fragment.querySelector: General sibling combinator, whitespace before: #sibling-p2 ~#sibling-p3 +Pass Fragment.querySelectorAll: General sibling combinator, no whitespace: #sibling-p2~#sibling-p3 +Pass Fragment.querySelector: General sibling combinator, no whitespace: #sibling-p2~#sibling-p3 +Pass Fragment.querySelectorAll: Syntax, group of selectors separator, surrounded by whitespace: #group em , #group strong +Pass Fragment.querySelector: Syntax, group of selectors separator, surrounded by whitespace: #group em , #group strong +Pass Fragment.querySelectorAll: Syntax, group of selectors separator, whitespace after: #group em, #group strong +Pass Fragment.querySelector: Syntax, group of selectors separator, whitespace after: #group em, #group strong +Pass Fragment.querySelectorAll: Syntax, group of selectors separator, whitespace before: #group em ,#group strong +Pass Fragment.querySelector: Syntax, group of selectors separator, whitespace before: #group em ,#group strong +Pass Fragment.querySelectorAll: Syntax, group of selectors separator, no whitespace: #group em,#group strong +Pass Fragment.querySelector: Syntax, group of selectors separator, no whitespace: #group em,#group strong +Fail Fragment.querySelectorAll: Slotted selector: ::slotted(foo) Failed to parse selector +Fail Fragment.querySelector: Slotted selector: ::slotted(foo) Failed to parse selector +Fail Fragment.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo Failed to parse selector +Fail Fragment.querySelector: Slotted selector (no matching closing paren): ::slotted(foo Failed to parse selector +Pass In-document Element.querySelectorAll: Type selector, matching html element: html +Pass In-document Element.querySelector: Type selector, matching html element: html +Pass In-document Element.querySelectorAll: Type selector, matching body element: body +Pass In-document Element.querySelector: Type selector, matching body element: body +Pass In-document Element.querySelectorAll: Universal selector, matching all children of element with specified ID: #universal>* +Pass In-document Element.querySelector: Universal selector, matching all children of element with specified ID: #universal>* +Pass In-document Element.querySelectorAll: Universal selector, matching all grandchildren of element with specified ID: #universal>*>* +Pass In-document Element.querySelector: Universal selector, matching all grandchildren of element with specified ID: #universal>*>* +Pass In-document Element.querySelectorAll: Universal selector, matching all children of empty element with specified ID: #empty>* +Pass In-document Element.querySelector: Universal selector, matching all children of empty element with specified ID: #empty>* +Pass In-document Element.querySelectorAll: Universal selector, matching all descendants of element with specified ID: #universal * +Pass In-document Element.querySelector: Universal selector, matching all descendants of element with specified ID: #universal * +Pass In-document Element.querySelectorAll: Attribute presence selector, matching align attribute with value: .attr-presence-div1[align] +Pass In-document Element.querySelector: Attribute presence selector, matching align attribute with value: .attr-presence-div1[align] +Pass In-document Element.querySelectorAll: Attribute presence selector, matching align attribute with empty value: .attr-presence-div2[align] +Pass In-document Element.querySelector: Attribute presence selector, matching align attribute with empty value: .attr-presence-div2[align] +Fail In-document Element.querySelectorAll: Attribute presence selector, matching title attribute, case insensitivity: #attr-presence [*|TiTlE] +Fail In-document Element.querySelector: Attribute presence selector, matching title attribute, case insensitivity: #attr-presence [*|TiTlE] +Pass In-document Element.querySelectorAll: Attribute presence selector, matching custom data-* attribute: [data-attr-presence] +Pass In-document Element.querySelector: Attribute presence selector, matching custom data-* attribute: [data-attr-presence] +Pass In-document Element.querySelectorAll: Attribute presence selector, not matching attribute with similar name: .attr-presence-div3[align], .attr-presence-div4[align] +Pass In-document Element.querySelector: Attribute presence selector, not matching attribute with similar name: .attr-presence-div3[align], .attr-presence-div4[align] +Pass In-document Element.querySelectorAll: Attribute presence selector, matching attribute with non-ASCII characters: ul[data-中文] +Pass In-document Element.querySelector: Attribute presence selector, matching attribute with non-ASCII characters: ul[data-中文] +Pass In-document Element.querySelectorAll: Attribute presence selector, not matching default option without selected attribute: #attr-presence-select1 option[selected] +Pass In-document Element.querySelector: Attribute presence selector, not matching default option without selected attribute: #attr-presence-select1 option[selected] +Pass In-document Element.querySelectorAll: Attribute presence selector, matching option with selected attribute: #attr-presence-select2 option[selected] +Pass In-document Element.querySelector: Attribute presence selector, matching option with selected attribute: #attr-presence-select2 option[selected] +Pass In-document Element.querySelectorAll: Attribute presence selector, matching multiple options with selected attributes: #attr-presence-select3 option[selected] +Pass In-document Element.querySelector: Attribute presence selector, matching multiple options with selected attributes: #attr-presence-select3 option[selected] +Pass In-document Element.querySelectorAll: Attribute value selector, matching align attribute with value: #attr-value [align="center"] +Pass In-document Element.querySelector: Attribute value selector, matching align attribute with value: #attr-value [align="center"] +Pass In-document Element.querySelectorAll: Attribute value selector, matching align attribute with value, unclosed bracket: #attr-value [align="center" +Pass In-document Element.querySelector: Attribute value selector, matching align attribute with value, unclosed bracket: #attr-value [align="center" +Pass In-document Element.querySelectorAll: Attribute value selector, matching align attribute with empty value: #attr-value [align=""] +Pass In-document Element.querySelector: Attribute value selector, matching align attribute with empty value: #attr-value [align=""] +Pass In-document Element.querySelectorAll: Attribute value selector, not matching align attribute with partial value: #attr-value [align="c"] +Pass In-document Element.querySelector: Attribute value selector, not matching align attribute with partial value: #attr-value [align="c"] +Pass In-document Element.querySelectorAll: Attribute value selector, not matching align attribute with incorrect value: #attr-value [align="centera"] +Pass In-document Element.querySelector: Attribute value selector, not matching align attribute with incorrect value: #attr-value [align="centera"] +Pass In-document Element.querySelectorAll: Attribute value selector, matching custom data-* attribute with unicode escaped value: [data-attr-value="\e9"] +Pass In-document Element.querySelector: Attribute value selector, matching custom data-* attribute with unicode escaped value: [data-attr-value="\e9"] +Pass In-document Element.querySelectorAll: Attribute value selector, matching custom data-* attribute with escaped character: [data-attr-value_foo="\e9"] +Pass In-document Element.querySelector: Attribute value selector, matching custom data-* attribute with escaped character: [data-attr-value_foo="\e9"] +Pass In-document Element.querySelectorAll: Attribute value selector with single-quoted value, matching multiple inputs with type attributes: #attr-value input[type='hidden'],#attr-value input[type='radio'] +Pass In-document Element.querySelector: Attribute value selector with single-quoted value, matching multiple inputs with type attributes: #attr-value input[type='hidden'],#attr-value input[type='radio'] +Pass In-document Element.querySelectorAll: Attribute value selector with double-quoted value, matching multiple inputs with type attributes: #attr-value input[type="hidden"],#attr-value input[type='radio'] +Pass In-document Element.querySelector: Attribute value selector with double-quoted value, matching multiple inputs with type attributes: #attr-value input[type="hidden"],#attr-value input[type='radio'] +Pass In-document Element.querySelectorAll: Attribute value selector with unquoted value, matching multiple inputs with type attributes: #attr-value input[type=hidden],#attr-value input[type=radio] +Pass In-document Element.querySelector: Attribute value selector with unquoted value, matching multiple inputs with type attributes: #attr-value input[type=hidden],#attr-value input[type=radio] +Pass In-document Element.querySelectorAll: Attribute value selector, matching attribute with value using non-ASCII characters: [data-attr-value=中文] +Pass In-document Element.querySelector: Attribute value selector, matching attribute with value using non-ASCII characters: [data-attr-value=中文] +Pass In-document Element.querySelectorAll: Attribute whitespace-separated list selector, matching class attribute with value: #attr-whitespace [class~="div1"] +Pass In-document Element.querySelector: Attribute whitespace-separated list selector, matching class attribute with value: #attr-whitespace [class~="div1"] +Pass In-document Element.querySelectorAll: Attribute whitespace-separated list selector, not matching class attribute with empty value: #attr-whitespace [class~=""] +Pass In-document Element.querySelector: Attribute whitespace-separated list selector, not matching class attribute with empty value: #attr-whitespace [class~=""] +Pass In-document Element.querySelectorAll: Attribute whitespace-separated list selector, not matching class attribute with partial value: [data-attr-whitespace~="div"] +Pass In-document Element.querySelector: Attribute whitespace-separated list selector, not matching class attribute with partial value: [data-attr-whitespace~="div"] +Pass In-document Element.querySelectorAll: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value: [data-attr-whitespace~="\0000e9"] +Pass In-document Element.querySelector: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value: [data-attr-whitespace~="\0000e9"] +Pass In-document Element.querySelectorAll: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character: [data-attr-whitespace_foo~="\e9"] +Pass In-document Element.querySelector: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character: [data-attr-whitespace_foo~="\e9"] +Pass In-document Element.querySelectorAll: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +Pass In-document Element.querySelector: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +Pass In-document Element.querySelectorAll: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +Pass In-document Element.querySelector: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +Pass In-document Element.querySelectorAll: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +Pass In-document Element.querySelector: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +Pass In-document Element.querySelectorAll: Attribute whitespace-separated list selector with double-quoted value, not matching value with space: #attr-whitespace a[rel~="book mark"] +Pass In-document Element.querySelector: Attribute whitespace-separated list selector with double-quoted value, not matching value with space: #attr-whitespace a[rel~="book mark"] +Pass In-document Element.querySelectorAll: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters: #attr-whitespace [title~=中文] +Pass In-document Element.querySelector: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters: #attr-whitespace [title~=中文] +Pass In-document Element.querySelectorAll: Attribute hyphen-separated list selector, not matching unspecified lang attribute: #attr-hyphen-div1[lang|="en"] +Pass In-document Element.querySelector: Attribute hyphen-separated list selector, not matching unspecified lang attribute: #attr-hyphen-div1[lang|="en"] +Pass In-document Element.querySelectorAll: Attribute hyphen-separated list selector, matching lang attribute with exact value: #attr-hyphen-div2[lang|="fr"] +Pass In-document Element.querySelector: Attribute hyphen-separated list selector, matching lang attribute with exact value: #attr-hyphen-div2[lang|="fr"] +Pass In-document Element.querySelectorAll: Attribute hyphen-separated list selector, matching lang attribute with partial value: #attr-hyphen-div3[lang|="en"] +Pass In-document Element.querySelector: Attribute hyphen-separated list selector, matching lang attribute with partial value: #attr-hyphen-div3[lang|="en"] +Pass In-document Element.querySelectorAll: Attribute hyphen-separated list selector, not matching incorrect value: #attr-hyphen-div4[lang|="es-AR"] +Pass In-document Element.querySelector: Attribute hyphen-separated list selector, not matching incorrect value: #attr-hyphen-div4[lang|="es-AR"] +Pass In-document Element.querySelectorAll: Attribute begins with selector, matching href attributes beginning with specified substring: #attr-begins a[href^="http://www"] +Pass In-document Element.querySelector: Attribute begins with selector, matching href attributes beginning with specified substring: #attr-begins a[href^="http://www"] +Pass In-document Element.querySelectorAll: Attribute begins with selector, matching lang attributes beginning with specified substring, : #attr-begins [lang^="en-"] +Pass In-document Element.querySelector: Attribute begins with selector, matching lang attributes beginning with specified substring, : #attr-begins [lang^="en-"] +Pass In-document Element.querySelectorAll: Attribute begins with selector, not matching class attribute with empty value: #attr-begins [class^=""] +Pass In-document Element.querySelector: Attribute begins with selector, not matching class attribute with empty value: #attr-begins [class^=""] +Pass In-document Element.querySelectorAll: Attribute begins with selector, not matching class attribute not beginning with specified substring: #attr-begins [class^=apple] +Pass In-document Element.querySelector: Attribute begins with selector, not matching class attribute not beginning with specified substring: #attr-begins [class^=apple] +Pass In-document Element.querySelectorAll: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=' apple'] +Pass In-document Element.querySelector: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=' apple'] +Pass In-document Element.querySelectorAll: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=" apple"] +Pass In-document Element.querySelector: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=" apple"] +Pass In-document Element.querySelectorAll: Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring: #attr-begins [class^= apple] +Pass In-document Element.querySelector: Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring: #attr-begins [class^= apple] +Pass In-document Element.querySelectorAll: Attribute ends with selector, matching href attributes ending with specified substring: #attr-ends a[href$=".org"] +Pass In-document Element.querySelector: Attribute ends with selector, matching href attributes ending with specified substring: #attr-ends a[href$=".org"] +Pass In-document Element.querySelectorAll: Attribute ends with selector, matching lang attributes ending with specified substring, : #attr-ends [lang$="-CH"] +Pass In-document Element.querySelector: Attribute ends with selector, matching lang attributes ending with specified substring, : #attr-ends [lang$="-CH"] +Pass In-document Element.querySelectorAll: Attribute ends with selector, not matching class attribute with empty value: #attr-ends [class$=""] +Pass In-document Element.querySelector: Attribute ends with selector, not matching class attribute with empty value: #attr-ends [class$=""] +Pass In-document Element.querySelectorAll: Attribute ends with selector, not matching class attribute not ending with specified substring: #attr-ends [class$=apple] +Pass In-document Element.querySelector: Attribute ends with selector, not matching class attribute not ending with specified substring: #attr-ends [class$=apple] +Pass In-document Element.querySelectorAll: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring: #attr-ends [class$='apple '] +Pass In-document Element.querySelector: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring: #attr-ends [class$='apple '] +Pass In-document Element.querySelectorAll: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring: #attr-ends [class$="apple "] +Pass In-document Element.querySelector: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring: #attr-ends [class$="apple "] +Pass In-document Element.querySelectorAll: Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring: #attr-ends [class$=apple ] +Pass In-document Element.querySelector: Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring: #attr-ends [class$=apple ] +Pass In-document Element.querySelectorAll: Attribute contains selector, matching href attributes beginning with specified substring: #attr-contains a[href*="http://www"] +Pass In-document Element.querySelector: Attribute contains selector, matching href attributes beginning with specified substring: #attr-contains a[href*="http://www"] +Pass In-document Element.querySelectorAll: Attribute contains selector, matching href attributes ending with specified substring: #attr-contains a[href*=".org"] +Pass In-document Element.querySelector: Attribute contains selector, matching href attributes ending with specified substring: #attr-contains a[href*=".org"] +Pass In-document Element.querySelectorAll: Attribute contains selector, matching href attributes containing specified substring: #attr-contains a[href*=".example."] +Pass In-document Element.querySelector: Attribute contains selector, matching href attributes containing specified substring: #attr-contains a[href*=".example."] +Pass In-document Element.querySelectorAll: Attribute contains selector, matching lang attributes beginning with specified substring, : #attr-contains [lang*="en-"] +Pass In-document Element.querySelector: Attribute contains selector, matching lang attributes beginning with specified substring, : #attr-contains [lang*="en-"] +Pass In-document Element.querySelectorAll: Attribute contains selector, matching lang attributes ending with specified substring, : #attr-contains [lang*="-CH"] +Pass In-document Element.querySelector: Attribute contains selector, matching lang attributes ending with specified substring, : #attr-contains [lang*="-CH"] +Pass In-document Element.querySelectorAll: Attribute contains selector, not matching class attribute with empty value: #attr-contains [class*=""] +Pass In-document Element.querySelector: Attribute contains selector, not matching class attribute with empty value: #attr-contains [class*=""] +Pass In-document Element.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=' apple'] +Pass In-document Element.querySelector: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=' apple'] +Pass In-document Element.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring: #attr-contains [class*='orange '] +Pass In-document Element.querySelector: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring: #attr-contains [class*='orange '] +Pass In-document Element.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute containing specified substring: #attr-contains [class*='ple banana ora'] +Pass In-document Element.querySelector: Attribute contains selector with single-quoted value, matching class attribute containing specified substring: #attr-contains [class*='ple banana ora'] +Pass In-document Element.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=" apple"] +Pass In-document Element.querySelector: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=" apple"] +Pass In-document Element.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring: #attr-contains [class*="orange "] +Pass In-document Element.querySelector: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring: #attr-contains [class*="orange "] +Pass In-document Element.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute containing specified substring: #attr-contains [class*="ple banana ora"] +Pass In-document Element.querySelector: Attribute contains selector with double-quoted value, matching class attribute containing specified substring: #attr-contains [class*="ple banana ora"] +Pass In-document Element.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring: #attr-contains [class*= apple] +Pass In-document Element.querySelector: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring: #attr-contains [class*= apple] +Pass In-document Element.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute ending with specified substring: #attr-contains [class*=orange ] +Pass In-document Element.querySelector: Attribute contains selector with unquoted value, matching class attribute ending with specified substring: #attr-contains [class*=orange ] +Pass In-document Element.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute containing specified substring: #attr-contains [class*= banana ] +Pass In-document Element.querySelector: Attribute contains selector with unquoted value, matching class attribute containing specified substring: #attr-contains [class*= banana ] +Pass In-document Element.querySelectorAll: :root pseudo-class selector, not matching document root element: :root +Pass In-document Element.querySelector: :root pseudo-class selector, not matching document root element: :root +Pass In-document Element.querySelectorAll: :nth-child selector, matching the third child element: #pseudo-nth-table1 :nth-child(3) +Pass In-document Element.querySelector: :nth-child selector, matching the third child element: #pseudo-nth-table1 :nth-child(3) +Pass In-document Element.querySelectorAll: :nth-child selector, matching every third child element: #pseudo-nth li:nth-child(3n) +Pass In-document Element.querySelector: :nth-child selector, matching every third child element: #pseudo-nth li:nth-child(3n) +Pass In-document Element.querySelectorAll: :nth-child selector, matching every second child element, starting from the fourth: #pseudo-nth li:nth-child(2n+4) +Pass In-document Element.querySelector: :nth-child selector, matching every second child element, starting from the fourth: #pseudo-nth li:nth-child(2n+4) +Pass In-document Element.querySelectorAll: :nth-child selector, matching every fourth child element, starting from the third: #pseudo-nth-p1 :nth-child(4n-1) +Pass In-document Element.querySelector: :nth-child selector, matching every fourth child element, starting from the third: #pseudo-nth-p1 :nth-child(4n-1) +Pass In-document Element.querySelectorAll: :nth-last-child selector, matching the third last child element: #pseudo-nth-table1 :nth-last-child(3) +Pass In-document Element.querySelector: :nth-last-child selector, matching the third last child element: #pseudo-nth-table1 :nth-last-child(3) +Pass In-document Element.querySelectorAll: :nth-last-child selector, matching every third child element from the end: #pseudo-nth li:nth-last-child(3n) +Pass In-document Element.querySelector: :nth-last-child selector, matching every third child element from the end: #pseudo-nth li:nth-last-child(3n) +Pass In-document Element.querySelectorAll: :nth-last-child selector, matching every second child element from the end, starting from the fourth last: #pseudo-nth li:nth-last-child(2n+4) +Pass In-document Element.querySelector: :nth-last-child selector, matching every second child element from the end, starting from the fourth last: #pseudo-nth li:nth-last-child(2n+4) +Pass In-document Element.querySelectorAll: :nth-last-child selector, matching every fourth element from the end, starting from the third last: #pseudo-nth-p1 :nth-last-child(4n-1) +Pass In-document Element.querySelector: :nth-last-child selector, matching every fourth element from the end, starting from the third last: #pseudo-nth-p1 :nth-last-child(4n-1) +Pass In-document Element.querySelectorAll: :nth-of-type selector, matching the third em element: #pseudo-nth-p1 em:nth-of-type(3) +Pass In-document Element.querySelector: :nth-of-type selector, matching the third em element: #pseudo-nth-p1 em:nth-of-type(3) +Pass In-document Element.querySelectorAll: :nth-of-type selector, matching every second element of their type: #pseudo-nth-p1 :nth-of-type(2n) +Pass In-document Element.querySelector: :nth-of-type selector, matching every second element of their type: #pseudo-nth-p1 :nth-of-type(2n) +Pass In-document Element.querySelectorAll: :nth-of-type selector, matching every second elemetn of their type, starting from the first: #pseudo-nth-p1 span:nth-of-type(2n-1) +Pass In-document Element.querySelector: :nth-of-type selector, matching every second elemetn of their type, starting from the first: #pseudo-nth-p1 span:nth-of-type(2n-1) +Pass In-document Element.querySelectorAll: :nth-last-of-type selector, matching the third last em element: #pseudo-nth-p1 em:nth-last-of-type(3) +Pass In-document Element.querySelector: :nth-last-of-type selector, matching the third last em element: #pseudo-nth-p1 em:nth-last-of-type(3) +Pass In-document Element.querySelectorAll: :nth-last-of-type selector, matching every second last element of their type: #pseudo-nth-p1 :nth-last-of-type(2n) +Pass In-document Element.querySelector: :nth-last-of-type selector, matching every second last element of their type: #pseudo-nth-p1 :nth-last-of-type(2n) +Pass In-document Element.querySelectorAll: :nth-last-of-type selector, matching every second last element of their type, starting from the last: #pseudo-nth-p1 span:nth-last-of-type(2n-1) +Pass In-document Element.querySelector: :nth-last-of-type selector, matching every second last element of their type, starting from the last: #pseudo-nth-p1 span:nth-last-of-type(2n-1) +Pass In-document Element.querySelectorAll: :first-of-type selector, matching the first em element: #pseudo-nth-p1 em:first-of-type +Pass In-document Element.querySelector: :first-of-type selector, matching the first em element: #pseudo-nth-p1 em:first-of-type +Pass In-document Element.querySelectorAll: :first-of-type selector, matching the first of every type of element: #pseudo-nth-p1 :first-of-type +Pass In-document Element.querySelector: :first-of-type selector, matching the first of every type of element: #pseudo-nth-p1 :first-of-type +Pass In-document Element.querySelectorAll: :first-of-type selector, matching the first td element in each table row: #pseudo-nth-table1 tr :first-of-type +Pass In-document Element.querySelector: :first-of-type selector, matching the first td element in each table row: #pseudo-nth-table1 tr :first-of-type +Pass In-document Element.querySelectorAll: :last-of-type selector, matching the last em elemnet: #pseudo-nth-p1 em:last-of-type +Pass In-document Element.querySelector: :last-of-type selector, matching the last em elemnet: #pseudo-nth-p1 em:last-of-type +Pass In-document Element.querySelectorAll: :last-of-type selector, matching the last of every type of element: #pseudo-nth-p1 :last-of-type +Pass In-document Element.querySelector: :last-of-type selector, matching the last of every type of element: #pseudo-nth-p1 :last-of-type +Pass In-document Element.querySelectorAll: :last-of-type selector, matching the last td element in each table row: #pseudo-nth-table1 tr :last-of-type +Pass In-document Element.querySelector: :last-of-type selector, matching the last td element in each table row: #pseudo-nth-table1 tr :last-of-type +Pass In-document Element.querySelectorAll: :first-child pseudo-class selector, matching first child div element: #pseudo-first-child div:first-child +Pass In-document Element.querySelector: :first-child pseudo-class selector, matching first child div element: #pseudo-first-child div:first-child +Pass In-document Element.querySelectorAll: :first-child pseudo-class selector, doesn't match non-first-child elements: .pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child +Pass In-document Element.querySelector: :first-child pseudo-class selector, doesn't match non-first-child elements: .pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child +Pass In-document Element.querySelectorAll: :first-child pseudo-class selector, matching first-child of multiple elements: #pseudo-first-child span:first-child +Pass In-document Element.querySelector: :first-child pseudo-class selector, matching first-child of multiple elements: #pseudo-first-child span:first-child +Pass In-document Element.querySelectorAll: :last-child pseudo-class selector, matching last child div element: #pseudo-last-child div:last-child +Pass In-document Element.querySelector: :last-child pseudo-class selector, matching last child div element: #pseudo-last-child div:last-child +Pass In-document Element.querySelectorAll: :last-child pseudo-class selector, doesn't match non-last-child elements: .pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child +Pass In-document Element.querySelector: :last-child pseudo-class selector, doesn't match non-last-child elements: .pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child +Pass In-document Element.querySelectorAll: :last-child pseudo-class selector, matching first-child of multiple elements: #pseudo-last-child span:last-child +Pass In-document Element.querySelector: :last-child pseudo-class selector, matching first-child of multiple elements: #pseudo-last-child span:last-child +Pass In-document Element.querySelectorAll: :pseudo-only-child pseudo-class selector, matching all only-child elements: #pseudo-only :only-child +Pass In-document Element.querySelector: :pseudo-only-child pseudo-class selector, matching all only-child elements: #pseudo-only :only-child +Pass In-document Element.querySelectorAll: :pseudo-only-child pseudo-class selector, matching only-child em elements: #pseudo-only em:only-child +Pass In-document Element.querySelector: :pseudo-only-child pseudo-class selector, matching only-child em elements: #pseudo-only em:only-child +Pass In-document Element.querySelectorAll: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type: #pseudo-only :only-of-type +Pass In-document Element.querySelector: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type: #pseudo-only :only-of-type +Pass In-document Element.querySelectorAll: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type: #pseudo-only em:only-of-type +Pass In-document Element.querySelector: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type: #pseudo-only em:only-of-type +Pass In-document Element.querySelectorAll: :empty pseudo-class selector, matching empty p elements: #pseudo-empty p:empty +Pass In-document Element.querySelector: :empty pseudo-class selector, matching empty p elements: #pseudo-empty p:empty +Pass In-document Element.querySelectorAll: :empty pseudo-class selector, matching all empty elements: #pseudo-empty :empty +Pass In-document Element.querySelector: :empty pseudo-class selector, matching all empty elements: #pseudo-empty :empty +Pass In-document Element.querySelectorAll: :link and :visited pseudo-class selectors, matching a and area elements with href attributes: #pseudo-link :link, #pseudo-link :visited +Pass In-document Element.querySelector: :link and :visited pseudo-class selectors, matching a and area elements with href attributes: #pseudo-link :link, #pseudo-link :visited +Pass In-document Element.querySelectorAll: :link and :visited pseudo-class selectors, not matching link elements with href attributes: #head :link, #head :visited +Pass In-document Element.querySelector: :link and :visited pseudo-class selectors, not matching link elements with href attributes: #head :link, #head :visited +Pass In-document Element.querySelectorAll: :link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing: :link:visited +Pass In-document Element.querySelector: :link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing: :link:visited +Fail In-document Element.querySelectorAll: :target pseudo-class selector, matching the element referenced by the URL fragment identifier: :target +Fail In-document Element.querySelector: :target pseudo-class selector, matching the element referenced by the URL fragment identifier: :target +Pass In-document Element.querySelectorAll: :lang pseudo-class selector, matching inherited language: #pseudo-lang-div1:lang(en) +Pass In-document Element.querySelector: :lang pseudo-class selector, matching inherited language: #pseudo-lang-div1:lang(en) +Pass In-document Element.querySelectorAll: :lang pseudo-class selector, matching specified language with exact value: #pseudo-lang-div2:lang(fr) +Pass In-document Element.querySelector: :lang pseudo-class selector, matching specified language with exact value: #pseudo-lang-div2:lang(fr) +Pass In-document Element.querySelectorAll: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en) +Pass In-document Element.querySelector: :lang pseudo-class selector, matching specified language with partial value: #pseudo-lang-div3:lang(en) +Pass In-document Element.querySelectorAll: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) +Pass In-document Element.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) +Pass In-document Element.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled +Pass In-document Element.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled +Pass In-document Element.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +Pass In-document Element.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +Pass In-document Element.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +Pass In-document Element.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +Pass In-document Element.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +Pass In-document Element.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +Pass In-document Element.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked +Pass In-document Element.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked +Pass In-document Element.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div) +Pass In-document Element.querySelector: :not pseudo-class selector, matching : #not>:not(div) +Pass In-document Element.querySelectorAll: :not pseudo-class selector, matching : #not * :not(:first-child) +Pass In-document Element.querySelector: :not pseudo-class selector, matching : #not * :not(:first-child) +Pass In-document Element.querySelectorAll: :not pseudo-class selector, matching nothing: :not(*) +Pass In-document Element.querySelector: :not pseudo-class selector, matching nothing: :not(*) +Pass In-document Element.querySelectorAll: :not pseudo-class selector, matching nothing: :not(*|*) +Pass In-document Element.querySelector: :not pseudo-class selector, matching nothing: :not(*|*) +Pass In-document Element.querySelectorAll: :not pseudo-class selector argument surrounded by spaces, matching : #not>:not( div ) +Pass In-document Element.querySelector: :not pseudo-class selector argument surrounded by spaces, matching : #not>:not( div ) +Pass In-document Element.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line +Pass In-document Element.querySelector: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line +Pass In-document Element.querySelectorAll: ::first-line pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-line +Pass In-document Element.querySelector: ::first-line pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-line +Pass In-document Element.querySelectorAll: :first-letter pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-letter +Pass In-document Element.querySelector: :first-letter pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-letter +Pass In-document Element.querySelectorAll: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter +Pass In-document Element.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter +Pass In-document Element.querySelectorAll: :before pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:before +Pass In-document Element.querySelector: :before pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:before +Pass In-document Element.querySelectorAll: ::before pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::before +Pass In-document Element.querySelector: ::before pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::before +Pass In-document Element.querySelectorAll: :after pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:after +Pass In-document Element.querySelector: :after pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:after +Pass In-document Element.querySelectorAll: ::after pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::after +Pass In-document Element.querySelector: ::after pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::after +Pass In-document Element.querySelectorAll: Class selector, matching element with specified class: .class-p +Pass In-document Element.querySelector: Class selector, matching element with specified class: .class-p +Pass In-document Element.querySelectorAll: Class selector, chained, matching only elements with all specified classes: #class .apple.orange.banana +Pass In-document Element.querySelector: Class selector, chained, matching only elements with all specified classes: #class .apple.orange.banana +Pass In-document Element.querySelectorAll: Class Selector, chained, with type selector: div.apple.banana.orange +Pass In-document Element.querySelector: Class Selector, chained, with type selector: div.apple.banana.orange +Pass In-document Element.querySelectorAll: Class selector, matching element with class value using non-ASCII characters (1): .台北Táiběi +Pass In-document Element.querySelector: Class selector, matching element with class value using non-ASCII characters (1): .台北Táiběi +Pass In-document Element.querySelectorAll: Class selector, matching multiple elements with class value using non-ASCII characters: .台北 +Pass In-document Element.querySelector: Class selector, matching multiple elements with class value using non-ASCII characters: .台北 +Pass In-document Element.querySelectorAll: Class selector, chained, matching element with multiple class values using non-ASCII characters (1): .台北Táiběi.台北 +Pass In-document Element.querySelector: Class selector, chained, matching element with multiple class values using non-ASCII characters (1): .台北Táiběi.台北 +Pass In-document Element.querySelectorAll: Class selector, matching element with class with escaped character: .foo\:bar +Pass In-document Element.querySelector: Class selector, matching element with class with escaped character: .foo\:bar +Pass In-document Element.querySelectorAll: Class selector, matching element with class with escaped character: .test\.foo\[5\]bar +Pass In-document Element.querySelector: Class selector, matching element with class with escaped character: .test\.foo\[5\]bar +Pass In-document Element.querySelectorAll: ID selector, matching element with specified id: #id #id-div1 +Pass In-document Element.querySelector: ID selector, matching element with specified id: #id #id-div1 +Fail In-document Element.querySelectorAll: ID selector, chained, matching element with specified id: #id-div1, #id-div1 +Pass In-document Element.querySelector: ID selector, chained, matching element with specified id: #id-div1, #id-div1 +Pass In-document Element.querySelectorAll: ID selector, chained, matching element with specified id: #id-div1, #id-div2 +Pass In-document Element.querySelector: ID selector, chained, matching element with specified id: #id-div1, #id-div2 +Pass In-document Element.querySelectorAll: ID Selector, chained, with type selector: div#id-div1, div#id-div2 +Pass In-document Element.querySelector: ID Selector, chained, with type selector: div#id-div1, div#id-div2 +Pass In-document Element.querySelectorAll: ID selector, not matching non-existent descendant: #id #none +Pass In-document Element.querySelector: ID selector, not matching non-existent descendant: #id #none +Pass In-document Element.querySelectorAll: ID selector, not matching non-existent ancestor: #none #id-div1 +Pass In-document Element.querySelector: ID selector, not matching non-existent ancestor: #none #id-div1 +Pass In-document Element.querySelectorAll: ID selector, matching multiple elements with duplicate id: #id-li-duplicate +Pass In-document Element.querySelector: ID selector, matching multiple elements with duplicate id: #id-li-duplicate +Pass In-document Element.querySelectorAll: ID selector, matching id value using non-ASCII characters (1): #台北Táiběi +Pass In-document Element.querySelector: ID selector, matching id value using non-ASCII characters (1): #台北Táiběi +Pass In-document Element.querySelectorAll: ID selector, matching id value using non-ASCII characters (2): #台北 +Pass In-document Element.querySelector: ID selector, matching id value using non-ASCII characters (2): #台北 +Pass In-document Element.querySelectorAll: ID selector, matching id values using non-ASCII characters (1): #台北Táiběi, #台北 +Pass In-document Element.querySelector: ID selector, matching id values using non-ASCII characters (1): #台北Táiběi, #台北 +Pass In-document Element.querySelectorAll: ID selector, matching element with id with escaped character: #\#foo\:bar +Pass In-document Element.querySelector: ID selector, matching element with id with escaped character: #\#foo\:bar +Pass In-document Element.querySelectorAll: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar +Pass In-document Element.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar +Pass In-document Element.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div +Pass In-document Element.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div +Pass In-document Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div +Pass In-document Element.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div +Pass In-document Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* +Pass In-document Element.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* +Pass In-document Element.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div +Pass In-document Element.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div +Pass In-document Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: body #descendant-div1 +Pass In-document Element.querySelector: Descendant combinator, matching element with id that is a descendant of an element: body #descendant-div1 +Pass In-document Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 +Pass In-document Element.querySelector: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 +Pass In-document Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element with id: #descendant #descendant-div2 +Pass In-document Element.querySelector: Descendant combinator, matching element with id that is a descendant of an element with id: #descendant #descendant-div2 +Pass In-document Element.querySelectorAll: Descendant combinator, matching element with class that is a descendant of an element with id: #descendant .descendant-div2 +Pass In-document Element.querySelector: Descendant combinator, matching element with class that is a descendant of an element with id: #descendant .descendant-div2 +Pass In-document Element.querySelectorAll: Descendant combinator, matching element with class that is a descendant of an element with class: .descendant-div1 .descendant-div3 +Pass In-document Element.querySelector: Descendant combinator, matching element with class that is a descendant of an element with class: .descendant-div1 .descendant-div3 +Pass In-document Element.querySelectorAll: Descendant combinator, not matching element with id that is not a descendant of an element with id: #descendant-div1 #descendant-div4 +Pass In-document Element.querySelector: Descendant combinator, not matching element with id that is not a descendant of an element with id: #descendant-div1 #descendant-div4 +Pass In-document Element.querySelectorAll: Descendant combinator, whitespace characters: #descendant #descendant-div2 +Pass In-document Element.querySelector: Descendant combinator, whitespace characters: #descendant #descendant-div2 +Pass In-document Element.querySelectorAll: Child combinator, matching element that is a child of an element with id: #child>div +Pass In-document Element.querySelector: Child combinator, matching element that is a child of an element with id: #child>div +Pass In-document Element.querySelectorAll: Child combinator, matching element with id that is a child of an element: div>#child-div1 +Pass In-document Element.querySelector: Child combinator, matching element with id that is a child of an element: div>#child-div1 +Pass In-document Element.querySelectorAll: Child combinator, matching element with id that is a child of an element with id: #child>#child-div1 +Pass In-document Element.querySelector: Child combinator, matching element with id that is a child of an element with id: #child>#child-div1 +Pass In-document Element.querySelectorAll: Child combinator, matching element with id that is a child of an element with class: #child-div1>.child-div2 +Pass In-document Element.querySelector: Child combinator, matching element with id that is a child of an element with class: #child-div1>.child-div2 +Pass In-document Element.querySelectorAll: Child combinator, matching element with class that is a child of an element with class: .child-div1>.child-div2 +Pass In-document Element.querySelector: Child combinator, matching element with class that is a child of an element with class: .child-div1>.child-div2 +Pass In-document Element.querySelectorAll: Child combinator, not matching element with id that is not a child of an element with id: #child>#child-div3 +Pass In-document Element.querySelector: Child combinator, not matching element with id that is not a child of an element with id: #child>#child-div3 +Pass In-document Element.querySelectorAll: Child combinator, not matching element with id that is not a child of an element with class: #child-div1>.child-div3 +Pass In-document Element.querySelector: Child combinator, not matching element with id that is not a child of an element with class: #child-div1>.child-div3 +Pass In-document Element.querySelectorAll: Child combinator, not matching element with class that is not a child of an element with class: .child-div1>.child-div3 +Pass In-document Element.querySelector: Child combinator, not matching element with class that is not a child of an element with class: .child-div1>.child-div3 +Pass In-document Element.querySelectorAll: Child combinator, surrounded by whitespace: #child-div1 > #child-div2 +Pass In-document Element.querySelector: Child combinator, surrounded by whitespace: #child-div1 > #child-div2 +Pass In-document Element.querySelectorAll: Child combinator, whitespace after: #child-div1> #child-div2 +Pass In-document Element.querySelector: Child combinator, whitespace after: #child-div1> #child-div2 +Pass In-document Element.querySelectorAll: Child combinator, whitespace before: #child-div1 >#child-div2 +Pass In-document Element.querySelector: Child combinator, whitespace before: #child-div1 >#child-div2 +Pass In-document Element.querySelectorAll: Child combinator, no whitespace: #child-div1>#child-div2 +Pass In-document Element.querySelector: Child combinator, no whitespace: #child-div1>#child-div2 +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id: #adjacent-div2+div +Pass In-document Element.querySelector: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id: #adjacent-div2+div +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element: div+#adjacent-div4 +Pass In-document Element.querySelector: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element: div+#adjacent-div4 +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id: #adjacent-div2+#adjacent-div4 +Pass In-document Element.querySelector: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id: #adjacent-div2+#adjacent-div4 +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id: #adjacent-div2+.adjacent-div4 +Pass In-document Element.querySelector: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id: #adjacent-div2+.adjacent-div4 +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class: .adjacent-div2+.adjacent-div4 +Pass In-document Element.querySelector: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class: .adjacent-div2+.adjacent-div4 +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element: #adjacent div+p +Pass In-document Element.querySelector: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element: #adjacent div+p +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id: #adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1 +Pass In-document Element.querySelector: Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id: #adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1 +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, surrounded by whitespace: #adjacent-p2 + #adjacent-p3 +Pass In-document Element.querySelector: Adjacent sibling combinator, surrounded by whitespace: #adjacent-p2 + #adjacent-p3 +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, whitespace after: #adjacent-p2+ #adjacent-p3 +Pass In-document Element.querySelector: Adjacent sibling combinator, whitespace after: #adjacent-p2+ #adjacent-p3 +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, whitespace before: #adjacent-p2 +#adjacent-p3 +Pass In-document Element.querySelector: Adjacent sibling combinator, whitespace before: #adjacent-p2 +#adjacent-p3 +Pass In-document Element.querySelectorAll: Adjacent sibling combinator, no whitespace: #adjacent-p2+#adjacent-p3 +Pass In-document Element.querySelector: Adjacent sibling combinator, no whitespace: #adjacent-p2+#adjacent-p3 +Pass In-document Element.querySelectorAll: General sibling combinator, matching element that is a sibling of an element with id: #sibling-div2~div +Pass In-document Element.querySelector: General sibling combinator, matching element that is a sibling of an element with id: #sibling-div2~div +Pass In-document Element.querySelectorAll: General sibling combinator, matching element with id that is a sibling of an element: div~#sibling-div4 +Pass In-document Element.querySelector: General sibling combinator, matching element with id that is a sibling of an element: div~#sibling-div4 +Pass In-document Element.querySelectorAll: General sibling combinator, matching element with id that is a sibling of an element with id: #sibling-div2~#sibling-div4 +Pass In-document Element.querySelector: General sibling combinator, matching element with id that is a sibling of an element with id: #sibling-div2~#sibling-div4 +Pass In-document Element.querySelectorAll: General sibling combinator, matching element with class that is a sibling of an element with id: #sibling-div2~.sibling-div +Pass In-document Element.querySelector: General sibling combinator, matching element with class that is a sibling of an element with id: #sibling-div2~.sibling-div +Pass In-document Element.querySelectorAll: General sibling combinator, matching p element that is a sibling of a div element: #sibling div~p +Pass In-document Element.querySelector: General sibling combinator, matching p element that is a sibling of a div element: #sibling div~p +Pass In-document Element.querySelectorAll: General sibling combinator, not matching element with id that is not a sibling after a p element: #sibling>p~div +Pass In-document Element.querySelector: General sibling combinator, not matching element with id that is not a sibling after a p element: #sibling>p~div +Pass In-document Element.querySelectorAll: General sibling combinator, not matching element with id that is not a sibling after an element with id: #sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1 +Pass In-document Element.querySelector: General sibling combinator, not matching element with id that is not a sibling after an element with id: #sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1 +Pass In-document Element.querySelectorAll: General sibling combinator, surrounded by whitespace: #sibling-p2 ~ #sibling-p3 +Pass In-document Element.querySelector: General sibling combinator, surrounded by whitespace: #sibling-p2 ~ #sibling-p3 +Pass In-document Element.querySelectorAll: General sibling combinator, whitespace after: #sibling-p2~ #sibling-p3 +Pass In-document Element.querySelector: General sibling combinator, whitespace after: #sibling-p2~ #sibling-p3 +Pass In-document Element.querySelectorAll: General sibling combinator, whitespace before: #sibling-p2 ~#sibling-p3 +Pass In-document Element.querySelector: General sibling combinator, whitespace before: #sibling-p2 ~#sibling-p3 +Pass In-document Element.querySelectorAll: General sibling combinator, no whitespace: #sibling-p2~#sibling-p3 +Pass In-document Element.querySelector: General sibling combinator, no whitespace: #sibling-p2~#sibling-p3 +Pass In-document Element.querySelectorAll: Syntax, group of selectors separator, surrounded by whitespace: #group em , #group strong +Pass In-document Element.querySelector: Syntax, group of selectors separator, surrounded by whitespace: #group em , #group strong +Pass In-document Element.querySelectorAll: Syntax, group of selectors separator, whitespace after: #group em, #group strong +Pass In-document Element.querySelector: Syntax, group of selectors separator, whitespace after: #group em, #group strong +Pass In-document Element.querySelectorAll: Syntax, group of selectors separator, whitespace before: #group em ,#group strong +Pass In-document Element.querySelector: Syntax, group of selectors separator, whitespace before: #group em ,#group strong +Pass In-document Element.querySelectorAll: Syntax, group of selectors separator, no whitespace: #group em,#group strong +Pass In-document Element.querySelector: Syntax, group of selectors separator, no whitespace: #group em,#group strong +Fail In-document Element.querySelectorAll: Slotted selector: ::slotted(foo) Failed to parse selector +Fail In-document Element.querySelector: Slotted selector: ::slotted(foo) Failed to parse selector +Fail In-document Element.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo Failed to parse selector +Fail In-document Element.querySelector: Slotted selector (no matching closing paren): ::slotted(foo Failed to parse selector \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/dom/nodes/ParentNode-querySelector-All.html b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/ParentNode-querySelector-All.html new file mode 100644 index 00000000000..4244606205f --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/ParentNode-querySelector-All.html @@ -0,0 +1,120 @@ + + + +Selectors-API Test Suite: HTML + + + + + + +
    This test requires JavaScript.
    + + diff --git a/Tests/LibWeb/Text/input/wpt-import/dom/nodes/ParentNode-querySelector-All.js b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/ParentNode-querySelector-All.js new file mode 100644 index 00000000000..3c6c5031798 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/ParentNode-querySelector-All.js @@ -0,0 +1,261 @@ +// Require selectors.js to be included before this. + +/* + * Create and append special elements that cannot be created correctly with HTML markup alone. + */ +function setupSpecialElements(doc, parent) { + // Setup null and undefined tests + parent.appendChild(doc.createElement("null")); + parent.appendChild(doc.createElement("undefined")); + + // Setup namespace tests + var anyNS = doc.createElement("div"); + var noNS = doc.createElement("div"); + anyNS.id = "any-namespace"; + noNS.id = "no-namespace"; + + var divs; + div = [doc.createElement("div"), + doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), + doc.createElementNS("", "div"), + doc.createElementNS("http://www.example.org/ns", "div")]; + + div[0].id = "any-namespace-div1"; + div[1].id = "any-namespace-div2"; + div[2].setAttribute("id", "any-namespace-div3"); // Non-HTML elements can't use .id property + div[3].setAttribute("id", "any-namespace-div4"); + + for (var i = 0; i < div.length; i++) { + anyNS.appendChild(div[i]) + } + + div = [doc.createElement("div"), + doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), + doc.createElementNS("", "div"), + doc.createElementNS("http://www.example.org/ns", "div")]; + + div[0].id = "no-namespace-div1"; + div[1].id = "no-namespace-div2"; + div[2].setAttribute("id", "no-namespace-div3"); // Non-HTML elements can't use .id property + div[3].setAttribute("id", "no-namespace-div4"); + + for (i = 0; i < div.length; i++) { + noNS.appendChild(div[i]) + } + + parent.appendChild(anyNS); + parent.appendChild(noNS); + + var span = doc.getElementById("attr-presence-i1"); + span.setAttributeNS("http://www.example.org/ns", "title", ""); +} + +/* + * Check that the querySelector and querySelectorAll methods exist on the given Node + */ +function interfaceCheck(type, obj) { + test(function() { + var q = typeof obj.querySelector === "function"; + assert_true(q, type + " supports querySelector."); + }, type + " supports querySelector") + + test(function() { + var qa = typeof obj.querySelectorAll === "function"; + assert_true( qa, type + " supports querySelectorAll."); + }, type + " supports querySelectorAll") + + test(function() { + var list = obj.querySelectorAll("div"); + if (obj.ownerDocument) { // The object is not a Document + assert_true(list instanceof obj.ownerDocument.defaultView.NodeList, "The result should be an instance of a NodeList") + } else { // The object is a Document + assert_true(list instanceof obj.defaultView.NodeList, "The result should be an instance of a NodeList") + } + }, type + ".querySelectorAll returns NodeList instance") +} + +/* + * Verify that the NodeList returned by querySelectorAll is static and and that a new list is created after + * each call. A static list should not be affected by subsequent changes to the DOM. + */ +function verifyStaticList(type, doc, root) { + var pre, post, preLength; + + test(function() { + pre = root.querySelectorAll("div"); + preLength = pre.length; + + var div = doc.createElement("div"); + (root.body || root).appendChild(div); + + assert_equals(pre.length, preLength, "The length of the NodeList should not change.") + }, type + ": static NodeList") + + test(function() { + post = root.querySelectorAll("div"), + assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list.") + }, type + ": new NodeList") +} + +/* + * Verify handling of special values for the selector parameter, including stringification of + * null and undefined, and the handling of the empty string. + */ +function runSpecialSelectorTests(type, root) { + let global = (root.ownerDocument || root).defaultView; + + test(function() { // 1 + assert_equals(root.querySelectorAll(null).length, 1, "This should find one element with the tag name 'NULL'."); + }, type + ".querySelectorAll null") + + test(function() { // 2 + assert_equals(root.querySelectorAll(undefined).length, 1, "This should find one element with the tag name 'UNDEFINED'."); + }, type + ".querySelectorAll undefined") + + test(function() { // 3 + assert_throws_js(global.TypeError, function() { + root.querySelectorAll(); + }, "This should throw a TypeError.") + }, type + ".querySelectorAll no parameter") + + test(function() { // 4 + var elm = root.querySelector(null) + assert_not_equals(elm, null, "This should find an element."); + assert_equals(elm.tagName.toUpperCase(), "NULL", "The tag name should be 'NULL'.") + }, type + ".querySelector null") + + test(function() { // 5 + var elm = root.querySelector(undefined) + assert_not_equals(elm, undefined, "This should find an element."); + assert_equals(elm.tagName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'.") + }, type + ".querySelector undefined") + + test(function() { // 6 + assert_throws_js(global.TypeError, function() { + root.querySelector(); + }, "This should throw a TypeError.") + }, type + ".querySelector no parameter") + + test(function() { // 7 + result = root.querySelectorAll("*"); + var i = 0; + traverse(root, function(elem) { + if (elem !== root) { + assert_equals(elem, result[i], "The result in index " + i + " should be in tree order."); + i++; + } + }) + }, type + ".querySelectorAll tree order"); +} + +/* + * Execute queries with the specified valid selectors for both querySelector() and querySelectorAll() + * Only run these tests when results are expected. Don't run for syntax error tests. + */ +function runValidSelectorTest(type, root, selectors, testType, docType) { + var nodeType = ""; + switch (root.nodeType) { + case Node.DOCUMENT_NODE: + nodeType = "document"; + break; + case Node.ELEMENT_NODE: + nodeType = root.parentNode ? "element" : "detached"; + break; + case Node.DOCUMENT_FRAGMENT_NODE: + nodeType = "fragment"; + break; + default: + assert_unreached(); + nodeType = "unknown"; // This should never happen. + } + + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + var e = s["expect"]; + + if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) + && (s["testType"] & testType) ) { + var foundall, found; + + test(function() { + foundall = root.querySelectorAll(q); + assert_not_equals(foundall, null, "The method should not return null.") + assert_equals(foundall.length, e.length, "The method should return the expected number of matches.") + + for (var i = 0; i < e.length; i++) { + assert_not_equals(foundall[i], null, "The item in index " + i + " should not be null.") + assert_equals(foundall[i].getAttribute("id"), e[i], "The item in index " + i + " should have the expected ID."); + assert_false(foundall[i].hasAttribute("data-clone"), "This should not be a cloned element."); + } + }, type + ".querySelectorAll: " + n + ": " + q); + + test(function() { + found = root.querySelector(q); + + if (e.length > 0) { + assert_not_equals(found, null, "The method should return a match.") + assert_equals(found.getAttribute("id"), e[0], "The method should return the first match."); + assert_equals(found, foundall[0], "The result should match the first item from querySelectorAll."); + assert_false(found.hasAttribute("data-clone"), "This should not be annotated as a cloned element."); + } else { + assert_equals(found, null, "The method should not match anything."); + } + }, type + ".querySelector: " + n + ": " + q); + } + } +} + +function windowFor(root) { + return root.defaultView || root.ownerDocument.defaultView; +} + +/* + * Execute queries with the specified invalid selectors for both querySelector() and querySelectorAll() + * Only run these tests when errors are expected. Don't run for valid selector tests. + */ +function runInvalidSelectorTest(type, root, selectors) { + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + + test(function() { + assert_throws_dom("SyntaxError", windowFor(root).DOMException, function() { + root.querySelector(q) + }); + }, type + ".querySelector: " + n + ": " + q); + + test(function() { + assert_throws_dom("SyntaxError", windowFor(root).DOMException, function() { + root.querySelectorAll(q) + }); + }, type + ".querySelectorAll: " + n + ": " + q); + } +} + +function traverse(elem, fn) { + if (elem.nodeType === elem.ELEMENT_NODE) { + fn(elem); + } + elem = elem.firstChild; + while (elem) { + traverse(elem, fn); + elem = elem.nextSibling; + } +} + +function getNodeType(node) { + switch (node.nodeType) { + case Node.DOCUMENT_NODE: + return "document"; + case Node.ELEMENT_NODE: + return node.parentNode ? "element" : "detached"; + case Node.DOCUMENT_FRAGMENT_NODE: + return "fragment"; + default: + assert_unreached(); + return "unknown"; // This should never happen. + } +} diff --git a/Tests/LibWeb/Text/input/wpt-import/dom/nodes/selectors.js b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/selectors.js new file mode 100644 index 00000000000..5e05547c9ac --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/dom/nodes/selectors.js @@ -0,0 +1,755 @@ +// Bit-mapped flags to indicate which tests the selector is suitable for +var TEST_QSA = 0x01; // querySelector() and querySelectorAll() tests +var TEST_FIND = 0x04; // find() and findAll() tests, may be unsuitable for querySelector[All] +var TEST_MATCH = 0x10; // matches() tests + +/* + * All of these invalid selectors should result in a SyntaxError being thrown by the APIs. + * + * name: A descriptive name of the selector being tested + * selector: The selector to test + */ +var invalidSelectors = [ + {name: "Empty String", selector: ""}, + {name: "Invalid character", selector: "["}, + {name: "Invalid character", selector: "]"}, + {name: "Invalid character", selector: "("}, + {name: "Invalid character", selector: ")"}, + {name: "Invalid character", selector: "{"}, + {name: "Invalid character", selector: "}"}, + {name: "Invalid character", selector: "<"}, + {name: "Invalid character", selector: ">"}, + {name: "Invalid ID", selector: "#"}, + {name: "Invalid group of selectors", selector: "div,"}, + {name: "Invalid class", selector: "."}, + {name: "Invalid class", selector: ".5cm"}, + {name: "Invalid class", selector: "..test"}, + {name: "Invalid class", selector: ".foo..quux"}, + {name: "Invalid class", selector: ".bar."}, + {name: "Invalid combinator", selector: "div % address, p"}, + {name: "Invalid combinator", selector: "div ++ address, p"}, + {name: "Invalid combinator", selector: "div ~~ address, p"}, + {name: "Invalid [att=value] selector", selector: "[*=test]"}, + {name: "Invalid [att=value] selector", selector: "[*|*=test]"}, + {name: "Invalid [att=value] selector", selector: "[class= space unquoted ]"}, + {name: "Unknown pseudo-class", selector: "div:example"}, + {name: "Unknown pseudo-class", selector: ":example"}, + {name: "Unknown pseudo-class", selector: "div:linkexample"}, + {name: "Unknown pseudo-element", selector: "div::example"}, + {name: "Unknown pseudo-element", selector: "::example"}, + {name: "Invalid pseudo-element", selector: ":::before"}, + {name: "Invalid pseudo-element", selector: ":: before"}, + {name: "Undeclared namespace", selector: "ns|div"}, + {name: "Undeclared namespace", selector: ":not(ns|div)"}, + {name: "Invalid namespace", selector: "^|div"}, + {name: "Invalid namespace", selector: "$|div"}, + {name: "Relative selector", selector: ">*"}, +]; + +/* + * All of these should be valid selectors, expected to match zero or more elements in the document. + * None should throw any errors. + * + * name: A descriptive name of the selector being tested + * selector: The selector to test + * expect: A list of IDs of the elements expected to be matched. List must be given in tree order. + * exclude: An array of contexts to exclude from testing. The valid values are: + * ["document", "element", "fragment", "detached", "html", "xhtml"] + * The "html" and "xhtml" values represent the type of document being queried. These are useful + * for tests that are affected by differences between HTML and XML, such as case sensitivity. + * level: An integer indicating the CSS or Selectors level in which the selector being tested was introduced. + * testType: A bit-mapped flag indicating the type of test. + * + * Note: Interactive pseudo-classes (:active :hover and :focus) have not been tested in this test suite. + */ +var validSelectors = [ + // Type Selector + {name: "Type selector, matching html element", selector: "html", expect: ["html"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Type selector, matching html element", selector: "html", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA}, + {name: "Type selector, matching body element", selector: "body", expect: ["body"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Type selector, matching body element", selector: "body", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA}, + + // Universal Selector + {name: "Universal selector, matching all elements", selector: "*", expect: ["universal", "universal-p1", "universal-code1", "universal-hr1", "universal-pre1", "universal-span1", "universal-p2", "universal-a1", "universal-address1", "universal-code2", "universal-a2"], level: 2, testType: TEST_MATCH}, + {name: "Universal selector, matching all children of element with specified ID", selector: "#universal>*", expect: ["universal-p1", "universal-hr1", "universal-pre1", "universal-p2", "universal-address1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Universal selector, matching all grandchildren of element with specified ID", selector: "#universal>*>*", expect: ["universal-code1", "universal-span1", "universal-a1", "universal-code2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Universal selector, matching all children of empty element with specified ID", selector: "#empty>*", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Universal selector, matching all descendants of element with specified ID", selector: "#universal *", expect: ["universal-p1", "universal-code1", "universal-hr1", "universal-pre1", "universal-span1", "universal-p2", "universal-a1", "universal-address1", "universal-code2", "universal-a2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // Attribute Selectors + // - presence [att] + {name: "Attribute presence selector, matching align attribute with value", selector: ".attr-presence-div1[align]", expect: ["attr-presence-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, matching align attribute with empty value", selector: ".attr-presence-div2[align]", expect: ["attr-presence-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, matching title attribute, case insensitivity", selector: "#attr-presence [*|TiTlE]", expect: ["attr-presence-a1", "attr-presence-span1", "attr-presence-i1"], exclude: ["xhtml"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, not matching title attribute, case sensitivity", selector: "#attr-presence [*|TiTlE]", expect: [], exclude: ["html"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, matching custom data-* attribute", selector: "[data-attr-presence]", expect: ["attr-presence-pre1", "attr-presence-blockquote1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, not matching attribute with similar name", selector: ".attr-presence-div3[align], .attr-presence-div4[align]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Attribute presence selector, matching attribute with non-ASCII characters", selector: "ul[data-中文]", expect: ["attr-presence-ul1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, not matching default option without selected attribute", selector: "#attr-presence-select1 option[selected]", expect: [] /* no matches */, level: 2, testType: TEST_QSA}, + {name: "Attribute presence selector, matching option with selected attribute", selector: "#attr-presence-select2 option[selected]", expect: ["attr-presence-select2-option4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, matching multiple options with selected attributes", selector: "#attr-presence-select3 option[selected]", expect: ["attr-presence-select3-option2", "attr-presence-select3-option3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - value [att=val] + {name: "Attribute value selector, matching align attribute with value", selector: "#attr-value [align=\"center\"]", expect: ["attr-value-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector, matching align attribute with value, unclosed bracket", selector: "#attr-value [align=\"center\"", expect: ["attr-value-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector, matching align attribute with empty value", selector: "#attr-value [align=\"\"]", expect: ["attr-value-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector, not matching align attribute with partial value", selector: "#attr-value [align=\"c\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Attribute value selector, not matching align attribute with incorrect value", selector: "#attr-value [align=\"centera\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Attribute value selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-value=\"\\e9\"]", expect: ["attr-value-div3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector, matching custom data-* attribute with escaped character", selector: "[data-attr-value\_foo=\"\\e9\"]", expect: ["attr-value-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type='hidden'],#attr-value input[type='radio']", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type=\"hidden\"],#attr-value input[type='radio']", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector with unquoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type=hidden],#attr-value input[type=radio]", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector, matching attribute with value using non-ASCII characters", selector: "[data-attr-value=中文]", expect: ["attr-value-div5"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - whitespace-separated list [att~=val] + {name: "Attribute whitespace-separated list selector, matching class attribute with value", selector: "#attr-whitespace [class~=\"div1\"]", expect: ["attr-whitespace-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector, not matching class attribute with empty value", selector: "#attr-whitespace [class~=\"\"]", expect: [] /*no matches*/ , level: 2, testType: TEST_QSA}, + {name: "Attribute whitespace-separated list selector, not matching class attribute with partial value", selector: "[data-attr-whitespace~=\"div\"]", expect: [] /*no matches*/ , level: 2, testType: TEST_QSA}, + {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-whitespace~=\"\\0000e9\"]", expect: ["attr-whitespace-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character", selector: "[data-attr-whitespace\_foo~=\"\\e9\"]", expect: ["attr-whitespace-div5"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow']", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with double-quoted value, not matching value with space", selector: "#attr-whitespace a[rel~=\"book mark\"]", expect: [] /* no matches */, level: 2, testType: TEST_QSA}, + {name: "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters", selector: "#attr-whitespace [title~=中文]", expect: ["attr-whitespace-p1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - hyphen-separated list [att|=val] + {name: "Attribute hyphen-separated list selector, not matching unspecified lang attribute", selector: "#attr-hyphen-div1[lang|=\"en\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Attribute hyphen-separated list selector, matching lang attribute with exact value", selector: "#attr-hyphen-div2[lang|=\"fr\"]", expect: ["attr-hyphen-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute hyphen-separated list selector, matching lang attribute with partial value", selector: "#attr-hyphen-div3[lang|=\"en\"]", expect: ["attr-hyphen-div3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute hyphen-separated list selector, not matching incorrect value", selector: "#attr-hyphen-div4[lang|=\"es-AR\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + + // - substring begins-with [att^=val] (Level 3) + {name: "Attribute begins with selector, matching href attributes beginning with specified substring", selector: "#attr-begins a[href^=\"http://www\"]", expect: ["attr-begins-a1", "attr-begins-a3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute begins with selector, matching lang attributes beginning with specified substring, ", selector: "#attr-begins [lang^=\"en-\"]", expect: ["attr-begins-div2", "attr-begins-div4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute begins with selector, not matching class attribute with empty value", selector: "#attr-begins [class^=\"\"]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "Attribute begins with selector, not matching class attribute not beginning with specified substring", selector: "#attr-begins [class^=apple]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring", selector: "#attr-begins [class^=' apple']", expect: ["attr-begins-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring", selector: "#attr-begins [class^=\" apple\"]", expect: ["attr-begins-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", selector: "#attr-begins [class^= apple]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - substring ends-with [att$=val] (Level 3) + {name: "Attribute ends with selector, matching href attributes ending with specified substring", selector: "#attr-ends a[href$=\".org\"]", expect: ["attr-ends-a1", "attr-ends-a3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute ends with selector, matching lang attributes ending with specified substring, ", selector: "#attr-ends [lang$=\"-CH\"]", expect: ["attr-ends-div2", "attr-ends-div4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute ends with selector, not matching class attribute with empty value", selector: "#attr-ends [class$=\"\"]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "Attribute ends with selector, not matching class attribute not ending with specified substring", selector: "#attr-ends [class$=apple]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring", selector: "#attr-ends [class$='apple ']", expect: ["attr-ends-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring", selector: "#attr-ends [class$=\"apple \"]", expect: ["attr-ends-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", selector: "#attr-ends [class$=apple ]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - substring contains [att*=val] (Level 3) + {name: "Attribute contains selector, matching href attributes beginning with specified substring", selector: "#attr-contains a[href*=\"http://www\"]", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector, matching href attributes ending with specified substring", selector: "#attr-contains a[href*=\".org\"]", expect: ["attr-contains-a1", "attr-contains-a2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector, matching href attributes containing specified substring", selector: "#attr-contains a[href*=\".example.\"]", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector, matching lang attributes beginning with specified substring, ", selector: "#attr-contains [lang*=\"en-\"]", expect: ["attr-contains-div2", "attr-contains-div6"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector, matching lang attributes ending with specified substring, ", selector: "#attr-contains [lang*=\"-CH\"]", expect: ["attr-contains-div3", "attr-contains-div5"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector, not matching class attribute with empty value", selector: "#attr-contains [class*=\"\"]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*=' apple']", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring", selector: "#attr-contains [class*='orange ']", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with single-quoted value, matching class attribute containing specified substring", selector: "#attr-contains [class*='ple banana ora']", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*=\" apple\"]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring", selector: "#attr-contains [class*=\"orange \"]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute containing specified substring", selector: "#attr-contains [class*=\"ple banana ora\"]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*= apple]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute ending with specified substring", selector: "#attr-contains [class*=orange ]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute containing specified substring", selector: "#attr-contains [class*= banana ]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // Pseudo-classes + // - :root (Level 3) + {name: ":root pseudo-class selector, matching document root element", selector: ":root", expect: ["html"], exclude: ["element", "fragment", "detached"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":root pseudo-class selector, not matching document root element", selector: ":root", expect: [] /*no matches*/, exclude: ["document"], level: 3, testType: TEST_QSA}, + + // - :nth-child(n) (Level 3) + // XXX write descriptions + {name: ":nth-child selector, matching the third child element", selector: "#pseudo-nth-table1 :nth-child(3)", expect: ["pseudo-nth-td3", "pseudo-nth-td9", "pseudo-nth-tr3", "pseudo-nth-td15"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-child selector, matching every third child element", selector: "#pseudo-nth li:nth-child(3n)", expect: ["pseudo-nth-li3", "pseudo-nth-li6", "pseudo-nth-li9", "pseudo-nth-li12"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-child selector, matching every second child element, starting from the fourth", selector: "#pseudo-nth li:nth-child(2n+4)", expect: ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-child selector, matching every fourth child element, starting from the third", selector: "#pseudo-nth-p1 :nth-child(4n-1)", expect: ["pseudo-nth-em2", "pseudo-nth-span3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :nth-last-child (Level 3) + {name: ":nth-last-child selector, matching the third last child element", selector: "#pseudo-nth-table1 :nth-last-child(3)", expect: ["pseudo-nth-tr1", "pseudo-nth-td4", "pseudo-nth-td10", "pseudo-nth-td16"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-last-child selector, matching every third child element from the end", selector: "#pseudo-nth li:nth-last-child(3n)", expect: ["pseudo-nth-li1", "pseudo-nth-li4", "pseudo-nth-li7", "pseudo-nth-li10"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", selector: "#pseudo-nth li:nth-last-child(2n+4)", expect: ["pseudo-nth-li1", "pseudo-nth-li3", "pseudo-nth-li5", "pseudo-nth-li7", "pseudo-nth-li9"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-last-child selector, matching every fourth element from the end, starting from the third last", selector: "#pseudo-nth-p1 :nth-last-child(4n-1)", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :nth-of-type(n) (Level 3) + {name: ":nth-of-type selector, matching the third em element", selector: "#pseudo-nth-p1 em:nth-of-type(3)", expect: ["pseudo-nth-em3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-of-type selector, matching every second element of their type", selector: "#pseudo-nth-p1 :nth-of-type(2n)", expect: ["pseudo-nth-em2", "pseudo-nth-span2", "pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-of-type selector, matching every second elemetn of their type, starting from the first", selector: "#pseudo-nth-p1 span:nth-of-type(2n-1)", expect: ["pseudo-nth-span1", "pseudo-nth-span3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :nth-last-of-type(n) (Level 3) + {name: ":nth-last-of-type selector, matching the third last em element", selector: "#pseudo-nth-p1 em:nth-last-of-type(3)", expect: ["pseudo-nth-em2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-last-of-type selector, matching every second last element of their type", selector: "#pseudo-nth-p1 :nth-last-of-type(2n)", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1", "pseudo-nth-em3", "pseudo-nth-span3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-last-of-type selector, matching every second last element of their type, starting from the last", selector: "#pseudo-nth-p1 span:nth-last-of-type(2n-1)", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :first-of-type (Level 3) + {name: ":first-of-type selector, matching the first em element", selector: "#pseudo-nth-p1 em:first-of-type", expect: ["pseudo-nth-em1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":first-of-type selector, matching the first of every type of element", selector: "#pseudo-nth-p1 :first-of-type", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":first-of-type selector, matching the first td element in each table row", selector: "#pseudo-nth-table1 tr :first-of-type", expect: ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :last-of-type (Level 3) + {name: ":last-of-type selector, matching the last em elemnet", selector: "#pseudo-nth-p1 em:last-of-type", expect: ["pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":last-of-type selector, matching the last of every type of element", selector: "#pseudo-nth-p1 :last-of-type", expect: ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":last-of-type selector, matching the last td element in each table row", selector: "#pseudo-nth-table1 tr :last-of-type", expect: ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :first-child + {name: ":first-child pseudo-class selector, matching first child div element", selector: "#pseudo-first-child div:first-child", expect: ["pseudo-first-child-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: ":first-child pseudo-class selector, doesn't match non-first-child elements", selector: ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: ":first-child pseudo-class selector, matching first-child of multiple elements", selector: "#pseudo-first-child span:first-child", expect: ["pseudo-first-child-span1", "pseudo-first-child-span3", "pseudo-first-child-span5"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - :last-child (Level 3) + {name: ":last-child pseudo-class selector, matching last child div element", selector: "#pseudo-last-child div:last-child", expect: ["pseudo-last-child-div3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":last-child pseudo-class selector, doesn't match non-last-child elements", selector: ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: ":last-child pseudo-class selector, matching first-child of multiple elements", selector: "#pseudo-last-child span:last-child", expect: ["pseudo-last-child-span2", "pseudo-last-child-span4", "pseudo-last-child-span6"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :only-child (Level 3) + {name: ":pseudo-only-child pseudo-class selector, matching all only-child elements", selector: "#pseudo-only :only-child", expect: ["pseudo-only-span1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":pseudo-only-child pseudo-class selector, matching only-child em elements", selector: "#pseudo-only em:only-child", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - :only-of-type (Level 3) + {name: ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", selector: "#pseudo-only :only-of-type", expect: ["pseudo-only-span1", "pseudo-only-em1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type", selector: "#pseudo-only em:only-of-type", expect: ["pseudo-only-em1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :empty (Level 3) + {name: ":empty pseudo-class selector, matching empty p elements", selector: "#pseudo-empty p:empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":empty pseudo-class selector, matching all empty elements", selector: "#pseudo-empty :empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :link and :visited + // Implementations may treat all visited links as unvisited, so these cannot be tested separately. + // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets. + {name: ":link and :visited pseudo-class selectors, matching a and area elements with href attributes", selector: "#pseudo-link :link, #pseudo-link :visited", expect: ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: ":link and :visited pseudo-class selectors, matching no elements", selector: "#head :link, #head :visited", expect: [] /*no matches*/, exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: ":link and :visited pseudo-class selectors, not matching link elements with href attributes", selector: "#head :link, #head :visited", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA}, + {name: ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", selector: ":link:visited", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA}, + + // - :target (Level 3) + {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", expect: [] /*no matches*/, exclude: ["document", "element"], level: 3, testType: TEST_QSA}, + {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", expect: ["target"], exclude: ["fragment", "detached"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :lang() + {name: ":lang pseudo-class selector, matching inherited language", selector: "#pseudo-lang-div1:lang(en)", expect: ["pseudo-lang-div1"], exclude: ["detached", "fragment"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: ":lang pseudo-class selector, not matching element with no inherited language", selector: "#pseudo-lang-div1:lang(en)", expect: [] /*no matches*/, exclude: ["document", "element"], level: 2, testType: TEST_QSA}, + {name: ":lang pseudo-class selector, matching specified language with exact value", selector: "#pseudo-lang-div2:lang(fr)", expect: ["pseudo-lang-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: ":lang pseudo-class selector, matching specified language with partial value", selector: "#pseudo-lang-div3:lang(en)", expect: ["pseudo-lang-div3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: ":lang pseudo-class selector, not matching incorrect language", selector: "#pseudo-lang-div4:lang(es-AR)", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + + // - :enabled (Level 3) + {name: ":enabled pseudo-class selector, matching all enabled form controls", selector: "#pseudo-ui :enabled", expect: ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6", + "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":enabled pseudo-class selector, not matching link elements", selector: "#pseudo-link :enabled", expect: [] /*no matches*/, unexpected: ["pseudo-link-a1","pseudo-link-a2","pseudo-link-a3","pseudo-link-map1","pseudo-link-area1","pseudo-link-area2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :disabled (Level 3) + {name: ":disabled pseudo-class selector, matching all disabled form controls", selector: "#pseudo-ui :disabled", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15", + "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":disabled pseudo-class selector, not matching link elements", selector: "#pseudo-link :disabled", expect: [] /*no matches*/, unexpected: ["pseudo-link-a1","pseudo-link-a2","pseudo-link-a3","pseudo-link-map1","pseudo-link-area1","pseudo-link-area2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :checked (Level 3) + {name: ":checked pseudo-class selector, matching checked radio buttons and checkboxes", selector: "#pseudo-ui :checked", expect: ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :not(s) (Level 3) + {name: ":not pseudo-class selector, matching ", selector: "#not>:not(div)", expect: ["not-p1", "not-p2", "not-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":not pseudo-class selector, matching ", selector: "#not * :not(:first-child)", expect: ["not-em1", "not-em2", "not-em3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":not pseudo-class selector, matching nothing", selector: ":not(*)", expect: [] /* no matches */, level: 3, testType: TEST_QSA}, + {name: ":not pseudo-class selector, matching nothing", selector: ":not(*|*)", expect: [] /* no matches */, level: 3, testType: TEST_QSA}, + {name: ":not pseudo-class selector argument surrounded by spaces, matching ", selector: "#not>:not( div )", expect: ["not-p1", "not-p2", "not-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // Pseudo-elements + // - ::first-line + {name: ":first-line pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-line", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "::first-line pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-line", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - ::first-letter + {name: ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-letter", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-letter", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - ::before + {name: ":before pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:before", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "::before pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::before", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - ::after + {name: ":after pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:after", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "::after pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::after", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // Class Selectors + {name: "Class selector, matching element with specified class", selector: ".class-p", expect: ["class-p1","class-p2", "class-p3"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, chained, matching only elements with all specified classes", selector: "#class .apple.orange.banana", expect: ["class-div1", "class-div2", "class-p4", "class-div3", "class-p6", "class-div4"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class Selector, chained, with type selector", selector: "div.apple.banana.orange", expect: ["class-div1", "class-div2", "class-div3", "class-div4"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, matching element with class value using non-ASCII characters (1)", selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci", expect: ["class-span1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, matching multiple elements with class value using non-ASCII characters", selector: ".\u53F0\u5317", expect: ["class-span1","class-span2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, chained, matching element with multiple class values using non-ASCII characters (1)", selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci.\u53F0\u5317", expect: ["class-span1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, matching element with class with escaped character", selector: ".foo\\:bar", expect: ["class-span3"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, matching element with class with escaped character", selector: ".test\\.foo\\[5\\]bar", expect: ["class-span4"], level: 1, testType: TEST_QSA | TEST_MATCH}, + + // ID Selectors + {name: "ID selector, matching element with specified id", selector: "#id #id-div1", expect: ["id-div1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID selector, chained, matching element with specified id", selector: "#id-div1, #id-div1", expect: ["id-div1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID selector, chained, matching element with specified id", selector: "#id-div1, #id-div2", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID Selector, chained, with type selector", selector: "div#id-div1, div#id-div2", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID selector, not matching non-existent descendant", selector: "#id #none", expect: [] /*no matches*/, level: 1, testType: TEST_QSA}, + {name: "ID selector, not matching non-existent ancestor", selector: "#none #id-div1", expect: [] /*no matches*/, level: 1, testType: TEST_QSA}, + {name: "ID selector, matching multiple elements with duplicate id", selector: "#id-li-duplicate", expect: ["id-li-duplicate", "id-li-duplicate", "id-li-duplicate", "id-li-duplicate"], level: 1, testType: TEST_QSA | TEST_MATCH}, + + {name: "ID selector, matching id value using non-ASCII characters (1)", selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci", expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID selector, matching id value using non-ASCII characters (2)", selector: "#\u53F0\u5317", expect: ["\u53F0\u5317"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID selector, matching id values using non-ASCII characters (1)", selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci, #\u53F0\u5317", expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci", "\u53F0\u5317"], level: 1, testType: TEST_QSA | TEST_MATCH}, + + // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values + {name: "ID selector, matching element with id with escaped character", selector: "#\\#foo\\:bar", expect: ["#foo:bar"], level: 1, testType: TEST_QSA}, + {name: "ID selector, matching element with id with escaped character", selector: "#test\\.foo\\[5\\]bar", expect: ["test.foo[5]bar"], level: 1, testType: TEST_QSA}, + + // Namespaces + // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id + {name: "Namespace selector, matching element with any namespace", selector: "#any-namespace *|div", expect: ["any-namespace-div1", "any-namespace-div2", "any-namespace-div3", "any-namespace-div4"], level: 3, testType: TEST_QSA}, + {name: "Namespace selector, matching div elements in no namespace only", selector: "#no-namespace |div", expect: ["no-namespace-div3"], level: 3, testType: TEST_QSA}, + {name: "Namespace selector, matching any elements in no namespace only", selector: "#no-namespace |*", expect: ["no-namespace-div3"], level: 3, testType: TEST_QSA}, + + // Combinators + // - Descendant combinator ' ' + {name: "Descendant combinator, matching element that is a descendant of an element with id", selector: "#descendant div", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element", selector: "body #descendant-div1", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element", selector: "div #descendant-div1", expect: ["descendant-div1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element with id", selector: "#descendant #descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, matching element with class that is a descendant of an element with id", selector: "#descendant .descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, matching element with class that is a descendant of an element with class", selector: ".descendant-div1 .descendant-div3", expect: ["descendant-div3"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1 #descendant-div4", expect: [] /*no matches*/, level: 1, testType: TEST_QSA}, + {name: "Descendant combinator, whitespace characters", selector: "#descendant\t\r\n#descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + + /* The future of this combinator is uncertain, see + * https://github.com/w3c/csswg-drafts/issues/641 + * These tests are commented out until a final decision is made on whether to + * keep the feature in the spec. + */ + + // // - Descendant combinator '>>' + // {name: "Descendant combinator '>>', matching element that is a descendant of an element with id", selector: "#descendant>>div", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_QSA | TEST_MATCH}, + // {name: "Descendant combinator '>>', matching element with id that is a descendant of an element", selector: "body>>#descendant-div1", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_QSA | TEST_MATCH}, + // {name: "Descendant combinator '>>', matching element with id that is a descendant of an element", selector: "div>>#descendant-div1", expect: ["descendant-div1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + // {name: "Descendant combinator '>>', matching element with id that is a descendant of an element with id", selector: "#descendant>>#descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + // {name: "Descendant combinator '>>', matching element with class that is a descendant of an element with id", selector: "#descendant>>.descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + // {name: "Descendant combinator '>>', matching element with class that is a descendant of an element with class", selector: ".descendant-div1>>.descendant-div3", expect: ["descendant-div3"], level: 1, testType: TEST_QSA | TEST_MATCH}, + // {name: "Descendant combinator '>>', not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1>>#descendant-div4", expect: [] /*no matches*/, level: 1, testType: TEST_QSA}, + + // - Child combinator '>' + {name: "Child combinator, matching element that is a child of an element with id", selector: "#child>div", expect: ["child-div1", "child-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element", selector: "div>#child-div1", expect: ["child-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element with id", selector: "#child>#child-div1", expect: ["child-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element with class", selector: "#child-div1>.child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, matching element with class that is a child of an element with class", selector: ".child-div1>.child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, not matching element with id that is not a child of an element with id", selector: "#child>#child-div3", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Child combinator, not matching element with id that is not a child of an element with class", selector: "#child-div1>.child-div3", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Child combinator, not matching element with class that is not a child of an element with class", selector: ".child-div1>.child-div3", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Child combinator, surrounded by whitespace", selector: "#child-div1\t\r\n>\t\r\n#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, whitespace after", selector: "#child-div1>\t\r\n#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, whitespace before", selector: "#child-div1\t\r\n>#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, no whitespace", selector: "#child-div1>#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - Adjacent sibling combinator '+' + {name: "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id", selector: "#adjacent-div2+div", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element", selector: "div+#adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id", selector: "#adjacent-div2+.adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class", selector: ".adjacent-div2+.adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element", selector: "#adjacent div+p", expect: ["adjacent-p2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Adjacent sibling combinator, surrounded by whitespace", selector: "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, whitespace after", selector: "#adjacent-p2+\t\r\n#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, whitespace before", selector: "#adjacent-p2\t\r\n+#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, no whitespace", selector: "#adjacent-p2+#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - General sibling combinator ~ (Level 3) + {name: "General sibling combinator, matching element that is a sibling of an element with id", selector: "#sibling-div2~div", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, matching element with id that is a sibling of an element", selector: "div~#sibling-div4", expect: ["sibling-div4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, matching element with id that is a sibling of an element with id", selector: "#sibling-div2~#sibling-div4", expect: ["sibling-div4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, matching element with class that is a sibling of an element with id", selector: "#sibling-div2~.sibling-div", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, matching p element that is a sibling of a div element", selector: "#sibling div~p", expect: ["sibling-p2", "sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, not matching element with id that is not a sibling after a p element", selector: "#sibling>p~div", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "General sibling combinator, not matching element with id that is not a sibling after an element with id", selector: "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "General sibling combinator, surrounded by whitespace", selector: "#sibling-p2\t\r\n~\t\r\n#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, whitespace after", selector: "#sibling-p2~\t\r\n#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, whitespace before", selector: "#sibling-p2\t\r\n~#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, no whitespace", selector: "#sibling-p2~#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // Group of selectors (comma) + {name: "Syntax, group of selectors separator, surrounded by whitespace", selector: "#group em\t\r \n,\t\r \n#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Syntax, group of selectors separator, whitespace after", selector: "#group em,\t\r\n#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Syntax, group of selectors separator, whitespace before", selector: "#group em\t\r\n,#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Syntax, group of selectors separator, no whitespace", selector: "#group em,#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + + // ::slotted (shouldn't match anything, but is a valid selector) + {name: "Slotted selector", selector: "::slotted(foo)", expect: [], level: 3, testType: TEST_QSA}, + {name: "Slotted selector (no matching closing paren)", selector: "::slotted(foo", expect: [], level: 3, testType: TEST_QSA}, +]; + + +/* + * These selectors are intended to be used with the find(), findAll() and matches() methods. Expected results + * should be determined under the assumption that :scope will be prepended to the selector where appropriate, + * in accordance with the specification. + * + * All of these should be valid relative selectors, expected to match zero or more elements in the document. + * None should throw any errors. + * + * name: A descriptive name of the selector being tested + * + * selector: The selector to test + * + * ctx: A selector to obtain the context object to use for tests invoking context.find(), + * and to use as a single reference node for tests invoking document.find(). + * Note: context = root.querySelector(ctx); + * + * ref: A selector to obtain the reference nodes to be used for the selector. + * Note: If root is the document or an in-document element: + * refNodes = document.querySelectorAll(ref); + * Otherwise, if root is a fragment or detached element: + * refNodes = root.querySelectorAll(ref); + * + * expect: A list of IDs of the elements expected to be matched. List must be given in tree order. + * + * unexpected: A list of IDs of some elements that are not expected to match the given selector. + * This is used to verify that unexpected.matches(selector, refNode) does not match. + * + * exclude: An array of contexts to exclude from testing. The valid values are: + * ["document", "element", "fragment", "detached", "html", "xhtml"] + * The "html" and "xhtml" values represent the type of document being queried. These are useful + * for tests that are affected by differences between HTML and XML, such as case sensitivity. + * + * level: An integer indicating the CSS or Selectors level in which the selector being tested was introduced. + * + * testType: A bit-mapped flag indicating the type of test. + * + * The test function for these tests accepts a specified root node, on which the methods will be invoked during the tests. + * + * Based on whether either 'context' or 'refNodes', or both, are specified the tests will execute the following methods: + * + * Where testType is TEST_FIND: + * + * context.findAll(selector, refNodes) + * context.findAll(selector) // Only if refNodes is not specified + * root.findAll(selector, context) // Only if refNodes is not specified + * root.findAll(selector, refNodes) // Only if context is not specified + * root.findAll(selector) // Only if neither context nor refNodes is specified + * + * Where testType is TEST_QSA + * + * context.querySelectorAll(selector) + * root.querySelectorAll(selector) // Only if neither context nor refNodes is specified + * + * Equivalent tests will be run for .find() as well. + * Note: Do not specify a testType of TEST_QSA where either implied :scope or explicit refNodes + * are required. + * + * Where testType is TEST_MATCH: + * For each expected result given, within the specified root: + * + * expect.matches(selector, context) // Only where refNodes is not specified + * expect.matches(selector, refNodes) + * expect.matches(selector) // Only if neither context nor refNodes is specified + * + * The tests involving refNodes for both find(), findAll() and matches() will each be run by passing the + * collection as a NodeList, an Array and, if there is only a single element, an Element node. + * + * Note: Interactive pseudo-classes (:active :hover and :focus) have not been tested in this test suite. + */ + +var scopedSelectors = [ + //{name: "", selector: "", ctx: "", ref: "", expect: [], level: 1, testType: TEST_FIND | TEST_MATCH}, + + // Attribute Selectors + // - presence [att] + {name: "Attribute presence selector, matching align attribute with value", selector: ".attr-presence-div1[align]", ctx: "#attr-presence", expect: ["attr-presence-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, matching align attribute with empty value", selector: ".attr-presence-div2[align]", ctx: "#attr-presence", expect: ["attr-presence-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, matching title attribute, case insensitivity", selector: "[TiTlE]", ctx: "#attr-presence", expect: ["attr-presence-a1", "attr-presence-span1"], exclude: ["xhtml"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, not matching title attribute, case sensitivity", selector: "[TiTlE]", ctx: "#attr-presence", expect: [], exclude: ["html"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, matching custom data-* attribute", selector: "[data-attr-presence]", ctx: "#attr-presence", expect: ["attr-presence-pre1", "attr-presence-blockquote1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, not matching attribute with similar name", selector: ".attr-presence-div3[align], .attr-presence-div4[align]", ctx: "#attr-presence", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Attribute presence selector, matching attribute with non-ASCII characters", selector: "ul[data-中文]", ctx: "#attr-presence", expect: ["attr-presence-ul1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, not matching default option without selected attribute", selector: "#attr-presence-select1 option[selected]", ctx: "#attr-presence", expect: [] /* no matches */, level: 2, testType: TEST_FIND}, + {name: "Attribute presence selector, matching option with selected attribute", selector: "#attr-presence-select2 option[selected]", ctx: "#attr-presence", expect: ["attr-presence-select2-option4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, matching multiple options with selected attributes", selector: "#attr-presence-select3 option[selected]", ctx: "#attr-presence", expect: ["attr-presence-select3-option2", "attr-presence-select3-option3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - value [att=val] + {name: "Attribute value selector, matching align attribute with value", selector: "[align=\"center\"]", ctx: "#attr-value", expect: ["attr-value-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector, matching align attribute with empty value", selector: "[align=\"\"]", ctx: "#attr-value", expect: ["attr-value-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector, not matching align attribute with partial value", selector: "[align=\"c\"]", ctx: "#attr-value", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Attribute value selector, not matching align attribute with incorrect value", selector: "[align=\"centera\"]", ctx: "#attr-value", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Attribute value selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-value=\"\\e9\"]", ctx: "#attr-value", expect: ["attr-value-div3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector, matching custom data-* attribute with escaped character", selector: "[data-attr-value\_foo=\"\\e9\"]", ctx: "#attr-value", expect: ["attr-value-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", selector: "input[type='hidden'],#attr-value input[type='radio']", ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", selector: "input[type=\"hidden\"],#attr-value input[type='radio']", ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector with unquoted value, matching multiple inputs with type attributes", selector: "input[type=hidden],#attr-value input[type=radio]", ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector, matching attribute with value using non-ASCII characters", selector: "[data-attr-value=中文]", ctx: "#attr-value", expect: ["attr-value-div5"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - whitespace-separated list [att~=val] + {name: "Attribute whitespace-separated list selector, matching class attribute with value", selector: "[class~=\"div1\"]", ctx: "#attr-whitespace", expect: ["attr-whitespace-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector, not matching class attribute with empty value", selector: "[class~=\"\"]", ctx: "#attr-whitespace", expect: [] /*no matches*/ , level: 2, testType: TEST_FIND}, + {name: "Attribute whitespace-separated list selector, not matching class attribute with partial value", selector: "[data-attr-whitespace~=\"div\"]", ctx: "#attr-whitespace", expect: [] /*no matches*/ , level: 2, testType: TEST_FIND}, + {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-whitespace~=\"\\0000e9\"]", ctx: "#attr-whitespace", expect: ["attr-whitespace-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character", selector: "[data-attr-whitespace\_foo~=\"\\e9\"]", ctx: "#attr-whitespace", expect: ["attr-whitespace-div5"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", selector: "a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow']", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", selector: "a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes", selector: "a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with double-quoted value, not matching value with space", selector: "a[rel~=\"book mark\"]", ctx: "#attr-whitespace", expect: [] /* no matches */, level: 2, testType: TEST_FIND}, + {name: "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters", selector: "[title~=中文]", ctx: "#attr-whitespace", expect: ["attr-whitespace-p1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - hyphen-separated list [att|=val] + {name: "Attribute hyphen-separated list selector, not matching unspecified lang attribute", selector: "#attr-hyphen-div1[lang|=\"en\"]", ctx: "#attr-hyphen", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Attribute hyphen-separated list selector, matching lang attribute with exact value", selector: "#attr-hyphen-div2[lang|=\"fr\"]", ctx: "#attr-hyphen", expect: ["attr-hyphen-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute hyphen-separated list selector, matching lang attribute with partial value", selector: "#attr-hyphen-div3[lang|=\"en\"]", ctx: "#attr-hyphen", expect: ["attr-hyphen-div3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute hyphen-separated list selector, not matching incorrect value", selector: "#attr-hyphen-div4[lang|=\"es-AR\"]", ctx: "#attr-hyphen", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + + // - substring begins-with [att^=val] (Level 3) + {name: "Attribute begins with selector, matching href attributes beginning with specified substring", selector: "a[href^=\"http://www\"]", ctx: "#attr-begins", expect: ["attr-begins-a1", "attr-begins-a3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute begins with selector, matching lang attributes beginning with specified substring, ", selector: "[lang^=\"en-\"]", ctx: "#attr-begins", expect: ["attr-begins-div2", "attr-begins-div4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute begins with selector, not matching class attribute with empty value", selector: "[class^=\"\"]", ctx: "#attr-begins", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "Attribute begins with selector, not matching class attribute not beginning with specified substring", selector: "[class^=apple]", ctx: "#attr-begins", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring", selector: "[class^=' apple']", ctx: "#attr-begins", expect: ["attr-begins-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring", selector: "[class^=\" apple\"]", ctx: "#attr-begins", expect: ["attr-begins-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", selector: "[class^= apple]", ctx: "#attr-begins", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - substring ends-with [att$=val] (Level 3) + {name: "Attribute ends with selector, matching href attributes ending with specified substring", selector: "a[href$=\".org\"]", ctx: "#attr-ends", expect: ["attr-ends-a1", "attr-ends-a3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute ends with selector, matching lang attributes ending with specified substring, ", selector: "[lang$=\"-CH\"]", ctx: "#attr-ends", expect: ["attr-ends-div2", "attr-ends-div4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute ends with selector, not matching class attribute with empty value", selector: "[class$=\"\"]", ctx: "#attr-ends", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "Attribute ends with selector, not matching class attribute not ending with specified substring", selector: "[class$=apple]", ctx: "#attr-ends", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring", selector: "[class$='apple ']", ctx: "#attr-ends", expect: ["attr-ends-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring", selector: "[class$=\"apple \"]", ctx: "#attr-ends", expect: ["attr-ends-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", selector: "[class$=apple ]", ctx: "#attr-ends", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - substring contains [att*=val] (Level 3) + {name: "Attribute contains selector, matching href attributes beginning with specified substring", selector: "a[href*=\"http://www\"]", ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector, matching href attributes ending with specified substring", selector: "a[href*=\".org\"]", ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a2"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector, matching href attributes containing specified substring", selector: "a[href*=\".example.\"]", ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector, matching lang attributes beginning with specified substring, ", selector: "[lang*=\"en-\"]", ctx: "#attr-contains", expect: ["attr-contains-div2", "attr-contains-div6"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector, matching lang attributes ending with specified substring, ", selector: "[lang*=\"-CH\"]", ctx: "#attr-contains", expect: ["attr-contains-div3", "attr-contains-div5"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector, not matching class attribute with empty value", selector: "[class*=\"\"]", ctx: "#attr-contains", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", selector: "[class*=' apple']", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring", selector: "[class*='orange ']", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with single-quoted value, matching class attribute containing specified substring", selector: "[class*='ple banana ora']", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", selector: "[class*=\" apple\"]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring", selector: "[class*=\"orange \"]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute containing specified substring", selector: "[class*=\"ple banana ora\"]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring", selector: "[class*= apple]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute ending with specified substring", selector: "[class*=orange ]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute containing specified substring", selector: "[class*= banana ]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // Pseudo-classes + // - :root (Level 3) + {name: ":root pseudo-class selector, matching document root element", selector: ":root", expect: ["html"], exclude: ["element", "fragment", "detached"], level: 3, testType: TEST_FIND}, + {name: ":root pseudo-class selector, not matching document root element", selector: ":root", expect: [] /*no matches*/, exclude: ["document"], level: 3, testType: TEST_FIND}, + {name: ":root pseudo-class selector, not matching document root element", selector: ":root", ctx: "#html", expect: [] /*no matches*/, exclude: ["fragment", "detached"], level: 3, testType: TEST_FIND}, + + // - :nth-child(n) (Level 3) + {name: ":nth-child selector, matching the third child element", selector: ":nth-child(3)", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td3", "pseudo-nth-td9", "pseudo-nth-tr3", "pseudo-nth-td15"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-child selector, matching every third child element", selector: "li:nth-child(3n)", ctx: "#pseudo-nth", expect: ["pseudo-nth-li3", "pseudo-nth-li6", "pseudo-nth-li9", "pseudo-nth-li12"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-child selector, matching every second child element, starting from the fourth", selector: "li:nth-child(2n+4)", ctx: "#pseudo-nth", expect: ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-child selector, matching every second child element, starting from the fourth, with whitespace", selector: "li:nth-child(2n \t\r\n+ \t\r\n4)", ctx: "#pseudo-nth", expect: ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-child selector, matching every fourth child element, starting from the third", selector: ":nth-child(4n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-child selector, matching every fourth child element, starting from the third, with whitespace", selector: ":nth-child(4n \t\r\n- \t\r\n1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-child selector used twice, matching ", selector: ":nth-child(1) :nth-child(1)", ctx: "#pseudo-nth", expect: ["pseudo-nth-table1", "pseudo-nth-tr1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :nth-last-child (Level 3) + {name: ":nth-last-child selector, matching the third last child element", selector: ":nth-last-child(3)", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-tr1", "pseudo-nth-td4", "pseudo-nth-td10", "pseudo-nth-td16"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-last-child selector, matching every third child element from the end", selector: "li:nth-last-child(3n)", ctx: "pseudo-nth", expect: ["pseudo-nth-li1", "pseudo-nth-li4", "pseudo-nth-li7", "pseudo-nth-li10"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", selector: "li:nth-last-child(2n+4)", ctx: "pseudo-nth", expect: ["pseudo-nth-li1", "pseudo-nth-li3", "pseudo-nth-li5", "pseudo-nth-li7", "pseudo-nth-li9"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-last-child selector, matching every fourth element from the end, starting from the third last", selector: ":nth-last-child(4n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :nth-of-type(n) (Level 3) + {name: ":nth-of-type selector, matching the third em element", selector: "em:nth-of-type(3)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-of-type selector, matching every second element of their type", selector: ":nth-of-type(2n)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2", "pseudo-nth-span2", "pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-of-type selector, matching every second elemetn of their type, starting from the first", selector: "span:nth-of-type(2n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :nth-last-of-type(n) (Level 3) + {name: ":nth-last-of-type selector, matching the third last em element", selector: "em:nth-last-of-type(3)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-last-of-type selector, matching every second last element of their type", selector: ":nth-last-of-type(2n)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1", "pseudo-nth-em3", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-last-of-type selector, matching every second last element of their type, starting from the last", selector: "span:nth-last-of-type(2n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :first-of-type (Level 3) + {name: ":first-of-type selector, matching the first em element", selector: "em:first-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":first-of-type selector, matching the first of every type of element", selector: ":first-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":first-of-type selector, matching the first td element in each table row", selector: "tr :first-of-type", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :last-of-type (Level 3) + {name: ":last-of-type selector, matching the last em elemnet", selector: "em:last-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":last-of-type selector, matching the last of every type of element", selector: ":last-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":last-of-type selector, matching the last td element in each table row", selector: "tr :last-of-type", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :first-child + {name: ":first-child pseudo-class selector, matching first child div element", selector: "div:first-child", ctx: "#pseudo-first-child", expect: ["pseudo-first-child-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: ":first-child pseudo-class selector, doesn't match non-first-child elements", selector: ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", ctx: "#pseudo-first-child", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: ":first-child pseudo-class selector, matching first-child of multiple elements", selector: "span:first-child", ctx: "#pseudo-first-child", expect: ["pseudo-first-child-span1", "pseudo-first-child-span3", "pseudo-first-child-span5"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - :last-child (Level 3) + {name: ":last-child pseudo-class selector, matching last child div element", selector: "div:last-child", ctx: "#pseudo-last-child", expect: ["pseudo-last-child-div3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":last-child pseudo-class selector, doesn't match non-last-child elements", selector: ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", ctx: "#pseudo-last-child", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: ":last-child pseudo-class selector, matching first-child of multiple elements", selector: "span:last-child", ctx: "#pseudo-last-child", expect: ["pseudo-last-child-span2", "pseudo-last-child-span4", "pseudo-last-child-span6"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :only-child (Level 3) + {name: ":pseudo-only-child pseudo-class selector, matching all only-child elements", selector: ":only-child", ctx: "#pseudo-only", expect: ["pseudo-only-span1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":pseudo-only-child pseudo-class selector, matching only-child em elements", selector: "em:only-child", ctx: "#pseudo-only", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - :only-of-type (Level 3) + {name: ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", selector: " :only-of-type", ctx: "#pseudo-only", expect: ["pseudo-only-span1", "pseudo-only-em1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type", selector: " em:only-of-type", ctx: "#pseudo-only", expect: ["pseudo-only-em1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :empty (Level 3) + {name: ":empty pseudo-class selector, matching empty p elements", selector: "p:empty", ctx: "#pseudo-empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":empty pseudo-class selector, matching all empty elements", selector: ":empty", ctx: "#pseudo-empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :link and :visited + // Implementations may treat all visited links as unvisited, so these cannot be tested separately. + // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets. + {name: ":link and :visited pseudo-class selectors, matching a and area elements with href attributes", selector: " :link, #pseudo-link :visited", ctx: "#pseudo-link", expect: ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: ":link and :visited pseudo-class selectors, matching no elements", selector: " :link, #head :visited", ctx: "#head", expect: [] /*no matches*/, exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: ":link and :visited pseudo-class selectors, not matching link elements with href attributes", selector: " :link, #head :visited", ctx: "#head", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_FIND}, + {name: ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", selector: ":link:visited", ctx: "#html", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_FIND}, + +// XXX Figure out context or refNodes for this + // - :target (Level 3) + {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", ctx: "", expect: [] /*no matches*/, exclude: ["document", "element"], level: 3, testType: TEST_FIND}, + {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", ctx: "", expect: ["target"], exclude: ["fragment", "detached"], level: 3, testType: TEST_FIND}, + +// XXX Fix ctx in tests below + + // - :lang() + {name: ":lang pseudo-class selector, matching inherited language (1)", selector: "#pseudo-lang-div1:lang(en)", ctx: "", expect: ["pseudo-lang-div1"], exclude: ["detached", "fragment"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: ":lang pseudo-class selector, not matching element with no inherited language", selector: "#pseudo-lang-div1:lang(en)", ctx: "", expect: [] /*no matches*/, exclude: ["document", "element"], level: 2, testType: TEST_FIND}, + {name: ":lang pseudo-class selector, matching specified language with exact value (1)", selector: "#pseudo-lang-div2:lang(fr)", ctx: "", expect: ["pseudo-lang-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: ":lang pseudo-class selector, matching specified language with partial value (1)", selector: "#pseudo-lang-div3:lang(en)", ctx: "", expect: ["pseudo-lang-div3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: ":lang pseudo-class selector, not matching incorrect language", selector: "#pseudo-lang-div4:lang(es-AR)", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + + // - :enabled (Level 3) + {name: ":enabled pseudo-class selector, matching all enabled form controls (1)", selector: "#pseudo-ui :enabled", ctx: "", expect: ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6", + "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":enabled pseudo-class selector, not matching link elements (1)", selector: "#pseudo-link :enabled", ctx: "", expect: [] /*no matches*/, unexpected: ["pseudo-link-a1","pseudo-link-a2","pseudo-link-a3","pseudo-link-map1","pseudo-link-area1","pseudo-link-area2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :disabled (Level 3) + {name: ":disabled pseudo-class selector, matching all disabled form controls (1)", selector: "#pseudo-ui :disabled", ctx: "", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15", + "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":disabled pseudo-class selector, not matching link elements (1)", selector: "#pseudo-link :disabled", ctx: "", expect: [] /*no matches*/, unexpected: ["pseudo-link-a1","pseudo-link-a2","pseudo-link-a3","pseudo-link-map1","pseudo-link-area1","pseudo-link-area2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :checked (Level 3) + {name: ":checked pseudo-class selector, matching checked radio buttons and checkboxes (1)", selector: "#pseudo-ui :checked", ctx: "", expect: ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :not(s) (Level 3) + {name: ":not pseudo-class selector, matching (1)", selector: "#not>:not(div)", ctx: "", expect: ["not-p1", "not-p2", "not-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":not pseudo-class selector, matching (1)", selector: "#not * :not(:first-child)", ctx: "", expect: ["not-em1", "not-em2", "not-em3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":not pseudo-class selector, matching nothing", selector: ":not(*)", ctx: "", expect: [] /* no matches */, level: 3, testType: TEST_FIND}, + {name: ":not pseudo-class selector, matching nothing", selector: ":not(*|*)", ctx: "", expect: [] /* no matches */, level: 3, testType: TEST_FIND}, + + // Pseudo-elements + // - ::first-line + {name: ":first-line pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-line", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "::first-line pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-line", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - ::first-letter + {name: ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-letter", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-letter", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - ::before + {name: ":before pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:before", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "::before pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::before", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - ::after + {name: ":after pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:after", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "::after pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::after", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // Class Selectors + {name: "Class selector, matching element with specified class (1)", selector: ".class-p", ctx: "", expect: ["class-p1","class-p2", "class-p3"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, chained, matching only elements with all specified classes (1)", selector: "#class .apple.orange.banana", ctx: "", expect: ["class-div1", "class-div2", "class-p4", "class-div3", "class-p6", "class-div4"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class Selector, chained, with type selector (1)", selector: "div.apple.banana.orange", ctx: "", expect: ["class-div1", "class-div2", "class-div3", "class-div4"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, matching element with class value using non-ASCII characters (2)", selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci", ctx: "", expect: ["class-span1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, matching multiple elements with class value using non-ASCII characters (1)", selector: ".\u53F0\u5317", ctx: "", expect: ["class-span1","class-span2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, chained, matching element with multiple class values using non-ASCII characters (2)", selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci.\u53F0\u5317", ctx: "", expect: ["class-span1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, matching element with class with escaped character (1)", selector: ".foo\\:bar", ctx: "", expect: ["class-span3"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, matching element with class with escaped character (1)", selector: ".test\\.foo\\[5\\]bar", ctx: "", expect: ["class-span4"], level: 1, testType: TEST_FIND | TEST_MATCH}, + + // ID Selectors + {name: "ID selector, matching element with specified id (1)", selector: "#id #id-div1", ctx: "", expect: ["id-div1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID selector, chained, matching element with specified id (1)", selector: "#id-div1, #id-div1", ctx: "", expect: ["id-div1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID selector, chained, matching element with specified id (1)", selector: "#id-div1, #id-div2", ctx: "", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID Selector, chained, with type selector (1)", selector: "div#id-div1, div#id-div2", ctx: "", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID selector, not matching non-existent descendant", selector: "#id #none", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND}, + {name: "ID selector, not matching non-existent ancestor", selector: "#none #id-div1", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND}, + {name: "ID selector, matching multiple elements with duplicate id (1)", selector: "#id-li-duplicate", ctx: "", expect: ["id-li-duplicate", "id-li-duplicate", "id-li-duplicate", "id-li-duplicate"], level: 1, testType: TEST_FIND | TEST_MATCH}, + + {name: "ID selector, matching id value using non-ASCII characters (3)", selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci", ctx: "", expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID selector, matching id value using non-ASCII characters (4)", selector: "#\u53F0\u5317", ctx: "", expect: ["\u53F0\u5317"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID selector, matching id values using non-ASCII characters (2)", selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci, #\u53F0\u5317", ctx: "", expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci", "\u53F0\u5317"], level: 1, testType: TEST_FIND | TEST_MATCH}, + + // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values + {name: "ID selector, matching element with id with escaped character", selector: "#\\#foo\\:bar", ctx: "", expect: ["#foo:bar"], level: 1, testType: TEST_FIND}, + {name: "ID selector, matching element with id with escaped character", selector: "#test\\.foo\\[5\\]bar", ctx: "", expect: ["test.foo[5]bar"], level: 1, testType: TEST_FIND}, + + // Namespaces + // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id + {name: "Namespace selector, matching element with any namespace", selector: "#any-namespace *|div", ctx: "", expect: ["any-namespace-div1", "any-namespace-div2", "any-namespace-div3", "any-namespace-div4"], level: 3, testType: TEST_FIND}, + {name: "Namespace selector, matching div elements in no namespace only", selector: "#no-namespace |div", ctx: "", expect: ["no-namespace-div3"], level: 3, testType: TEST_FIND}, + {name: "Namespace selector, matching any elements in no namespace only", selector: "#no-namespace |*", ctx: "", expect: ["no-namespace-div3"], level: 3, testType: TEST_FIND}, + + // Combinators + // - Descendant combinator ' ' + {name: "Descendant combinator, matching element that is a descendant of an element with id (1)", selector: "#descendant div", ctx: "", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element (1)", selector: "body #descendant-div1", ctx: "", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element (1)", selector: "div #descendant-div1", ctx: "", expect: ["descendant-div1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element with id (1)", selector: "#descendant #descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, matching element with class that is a descendant of an element with id (1)", selector: "#descendant .descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, matching element with class that is a descendant of an element with class (1)", selector: ".descendant-div1 .descendant-div3", ctx: "", expect: ["descendant-div3"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1 #descendant-div4", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND}, + {name: "Descendant combinator, whitespace characters (1)", selector: "#descendant\t\r\n#descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + + // // - Descendant combinator '>>' + // {name: "Descendant combinator '>>', matching element that is a descendant of an element with id (1)", selector: "#descendant>>div", ctx: "", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_FIND | TEST_MATCH}, + // {name: "Descendant combinator '>>', matching element with id that is a descendant of an element (1)", selector: "body>>#descendant-div1", ctx: "", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_FIND | TEST_MATCH}, + // {name: "Descendant combinator '>>', matching element with id that is a descendant of an element (1)", selector: "div>>#descendant-div1", ctx: "", expect: ["descendant-div1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + // {name: "Descendant combinator '>>', matching element with id that is a descendant of an element with id (1)", selector: "#descendant>>#descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + // {name: "Descendant combinator '>>', matching element with class that is a descendant of an element with id (1)", selector: "#descendant>>.descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + // {name: "Descendant combinator, '>>', matching element with class that is a descendant of an element with class (1)", selector: ".descendant-div1>>.descendant-div3", ctx: "", expect: ["descendant-div3"], level: 1, testType: TEST_FIND | TEST_MATCH}, + // {name: "Descendant combinator '>>', not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1>>#descendant-div4", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND}, + + // - Child combinator '>' + {name: "Child combinator, matching element that is a child of an element with id (1)", selector: "#child>div", ctx: "", expect: ["child-div1", "child-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element (1)", selector: "div>#child-div1", ctx: "", expect: ["child-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element with id (1)", selector: "#child>#child-div1", ctx: "", expect: ["child-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element with class (1)", selector: "#child-div1>.child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, matching element with class that is a child of an element with class (1)", selector: ".child-div1>.child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, not matching element with id that is not a child of an element with id", selector: "#child>#child-div3", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Child combinator, not matching element with id that is not a child of an element with class", selector: "#child-div1>.child-div3", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Child combinator, not matching element with class that is not a child of an element with class", selector: ".child-div1>.child-div3", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Child combinator, surrounded by whitespace (1)", selector: "#child-div1\t\r\n>\t\r\n#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, whitespace after (1)", selector: "#child-div1>\t\r\n#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, whitespace before (1)", selector: "#child-div1\t\r\n>#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, no whitespace (1)", selector: "#child-div1>#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - Adjacent sibling combinator '+' + {name: "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id (1)", selector: "#adjacent-div2+div", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element (1)", selector: "div+#adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id (1)", selector: "#adjacent-div2+#adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id (1)", selector: "#adjacent-div2+.adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class (1)", selector: ".adjacent-div2+.adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element (1)", selector: "#adjacent div+p", ctx: "", expect: ["adjacent-p2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Adjacent sibling combinator, surrounded by whitespace (1)", selector: "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, whitespace after (1)", selector: "#adjacent-p2+\t\r\n#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, whitespace before (1)", selector: "#adjacent-p2\t\r\n+#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, no whitespace (1)", selector: "#adjacent-p2+#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - General sibling combinator ~ (Level 3) + {name: "General sibling combinator, matching element that is a sibling of an element with id (1)", selector: "#sibling-div2~div", ctx: "", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, matching element with id that is a sibling of an element (1)", selector: "div~#sibling-div4", ctx: "", expect: ["sibling-div4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, matching element with id that is a sibling of an element with id (1)", selector: "#sibling-div2~#sibling-div4", ctx: "", expect: ["sibling-div4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, matching element with class that is a sibling of an element with id (1)", selector: "#sibling-div2~.sibling-div", ctx: "", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, matching p element that is a sibling of a div element (1)", selector: "#sibling div~p", ctx: "", expect: ["sibling-p2", "sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, not matching element with id that is not a sibling after a p element (1)", selector: "#sibling>p~div", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "General sibling combinator, not matching element with id that is not a sibling after an element with id", selector: "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "General sibling combinator, surrounded by whitespace (1)", selector: "#sibling-p2\t\r\n~\t\r\n#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, whitespace after (1)", selector: "#sibling-p2~\t\r\n#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, whitespace before (1)", selector: "#sibling-p2\t\r\n~#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, no whitespace (1)", selector: "#sibling-p2~#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // Group of selectors (comma) + {name: "Syntax, group of selectors separator, surrounded by whitespace (1)", selector: "#group em\t\r \n,\t\r \n#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Syntax, group of selectors separator, whitespace after (1)", selector: "#group em,\t\r\n#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Syntax, group of selectors separator, whitespace before (1)", selector: "#group em\t\r\n,#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Syntax, group of selectors separator, no whitespace (1)", selector: "#group em,#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH}, +];