Repository: symfony/symfony
File: src/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php (PHP)

Code before:
            ['div > div', []],
            ['div>.c', ['first-ol']],
            ['div > .c', ['first-ol']],
            ['div + div', ['foobar-div']],
            ['a ~ a', ['tag-anchor', 'nofollow-anchor']],
            ['a[rel="tag"] ~ a', ['nofollow-anchor']],
            ['ol#first-ol li:last-child', ['seventh-li']],
            ['ol#first-ol *:last-child', ['li-div', 'seventh-li']],
            ['#outer-div:first-child', ['outer-div']],
            ['#outer-div :first-child', ['name-anchor', 'first-li', 'li-div', 'p-b', 'checkbox-fieldset-disabled', 'area-href']],
            ['a[href]', ['tag-anchor', 'nofollow-anchor']],
            [':not(*)', []],
            ['a:not([href])', ['name-anchor']],
            ['ol :Not(li[class])', ['first-li', 'second-li', 'li-div', 'fifth-li', 'sixth-li', 'seventh-li']],
            // HTML-specific
            [':link', ['link-href', 'tag-anchor', 'nofollow-anchor', 'area-href']],
            [':visited', []],
            [':enabled', ['link-href', 'tag-anchor', 'nofollow-anchor', 'checkbox-unchecked', 'text-checked', 'checkbox-checked', 'area-href']],
            [':disabled', ['checkbox-disabled', 'checkbox-disabled-checked', 'fieldset', 'checkbox-fieldset-disabled']],
            [':checked', ['checkbox-checked', 'checkbox-disabled-checked']],
            ['div:has(> span)', ['foobar-div']],
            ['ol:has(> .c)', ['first-ol']],
            ['div:has( .a)', ['outer-div']],
            ['a:has(~ a)', ['name-anchor', 'tag-anchor']],
            ['ol:has(+ p)', ['first-ol']],
            ['a:has(+ .b)', ['nofollow-anchor']],
        ];
    }

    public static function getHtmlShakespearTestData()
    {
        return [
            ['*', 246],
            ['div:contains(CELIA)', 26],
            ['div:only-child', 22], // ?
            ['div:nth-child(even)', 106],
            ['div:nth-child(2n)', 106],
            ['div:nth-child(odd)', 137],
            ['div:nth-child(2n+1)', 137],
            ['div:nth-child(n)', 243],
            ['div:last-child', 53],
            ['div:first-child', 51],
            ['div > div', 242],
            ['div + div', 190],
            ['div ~ div', 190],
            ['body', 1],
            ['body div', 243],
            ['div', 243],
            ['div div', 242],
            ['div div div', 241],
            ['div, div, div', 243],

Review comment (suggestion):
* Looks like this is missing a test case for multiple selectors. When `has` has multiple selectors, e.g. `:has(foo, bar)`, it will match if either `foo` **or** `bar` are present.
* We should also test for `:has(:not(foo, bar))` which will only match if `foo` **and** `bar` are not present.
---
Source: https://drafts.csswg.org/selectors-4/#relational

Code after:
            ['*.a', ['first-ol']],
            ['ol.a', ['first-ol']],
            ['.c', ['first-ol', 'third-li', 'fourth-li']],
            ['*.c', ['first-ol', 'third-li', 'fourth-li']],
            ['ol *.c', ['third-li', 'fourth-li']],
            ['ol li.c', ['third-li', 'fourth-li']],
            ['li ~ li.c', ['third-li', 'fourth-li']],
            ['ol > li.c', ['third-li', 'fourth-li']],
            ['#first-li', ['first-li']],
            ['li#first-li', ['first-li']],
            ['*#first-li', ['first-li']],
            ['li div', ['li-div']],
            ['li > div', ['li-div']],
            ['div div', ['li-div']],
            ['div > div', []],
            ['div>.c', ['first-ol']],
            ['div > .c', ['first-ol']],
            ['div + div', ['foobar-div']],
            ['a ~ a', ['tag-anchor', 'nofollow-anchor']],
            ['a[rel="tag"] ~ a', ['nofollow-anchor']],
            ['ol#first-ol li:last-child', ['seventh-li']],
            ['ol#first-ol *:last-child', ['li-div', 'seventh-li']],
            ['#outer-div:first-child', ['outer-div']],
            ['#outer-div :first-child', ['name-anchor', 'first-li', 'li-div', 'p-b', 'checkbox-fieldset-disabled', 'area-href']],
            ['a[href]', ['tag-anchor', 'nofollow-anchor']],
            [':not(*)', []],
            ['a:not([href])', ['name-anchor']],
            ['ol :Not(li[class])', ['first-li', 'second-li', 'li-div', 'fifth-li', 'sixth-li', 'seventh-li']],
            [':is(#first-li, #second-li)', ['first-li', 'second-li']],
            ['a:is(#name-anchor, #tag-anchor)', ['name-anchor', 'tag-anchor']],
            [':is(.c)', ['first-ol', 'third-li', 'fourth-li']],
            ['a:is(:not(#name-anchor))', ['tag-anchor', 'nofollow-anchor']],
            ['a:not(:is(#name-anchor))', ['tag-anchor', 'nofollow-anchor']],
            [':where(#first-li, #second-li)', ['first-li', 'second-li']],
            ['a:where(#name-anchor, #tag-anchor)', ['name-anchor', 'tag-anchor']],
            [':where(.c)', ['first-ol', 'third-li', 'fourth-li']],
            ['a:where(:not(#name-anchor))', ['tag-anchor', 'nofollow-anchor']],
            ['a:not(:where(#name-anchor))', ['tag-anchor', 'nofollow-anchor']],
            ['a:where(:is(#name-anchor), :where(#tag-anchor))', ['name-anchor', 'tag-anchor']],
            // HTML-specific
            [':link', ['link-href', 'tag-anchor', 'nofollow-anchor', 'area-href']],
            [':visited', []],
            [':enabled', ['link-href', 'tag-anchor', 'nofollow-anchor', 'checkbox-unchecked', 'text-checked', 'checkbox-checked', 'area-href']],
            [':disabled', ['checkbox-disabled', 'checkbox-disabled-checked', 'fieldset', 'checkbox-fieldset-disabled']],
            [':checked', ['checkbox-checked', 'checkbox-disabled-checked']],
        ];
    }

    public static function getHtmlShakespearTestData()
    {
        return [