<html>
<head id="head">
<script src="../../resources/js-test.js"></script>
</head>
<body>
<script>

description("This tests setting and re-serialization of some CSS selectors.");

var bogusSelector = "_foo";

function setThenReadSelectorText(selector)
{
    var styleElement = document.getElementById("style");
    var head = document.getElementById("head");
    if (styleElement)
        head.removeChild(styleElement);

    styleElement = document.createElement("style");
    styleElement.id = "style";
    var head = document.getElementById("head");
    head.appendChild(styleElement);

    // First, create a rule with a bogus selector.
    styleElement.appendChild(document.createTextNode(bogusSelector + " { }"));
    // Now, set the desired selector text.
    styleElement.sheet.cssRules[0].selectorText = selector;
    return styleElement.sheet.cssRules[0].selectorText;
}

function expectedSerializedLangSelector(selector)
{
    var args = /:lang\(([^)]+)/.exec(selector);
    if (!args || !args[1])
        return selector;

    args = args[1].split(/\s*,\s*/);
    var expected = ':lang(';
    for (var i = 0; i < args.length; ++i) {
        expected += args[i];
        if (i < args.length - 1)
            expected += ', ';
    }
    expected += ')';
    return expected;
}

function testSelectorSerialization(selector, expectedSelector)
{
    shouldBeEqualToString("setThenReadSelectorText('" + selector + "')", expectedSelector);
}

function testSelectorRoundTrip(selector, expectFailure)
{
    var expected = selector.indexOf(":lang") == 0 ? expectedSerializedLangSelector(selector) : selector;
    shouldBeEqualToString("setThenReadSelectorText('" + selector + "')", expectFailure ? bogusSelector : expected);
}

testSelectorRoundTrip('', true);
testSelectorRoundTrip('123', true);
testSelectorRoundTrip('-', true);
testSelectorRoundTrip('$', true);
testSelectorRoundTrip(':', true);
testSelectorRoundTrip('.', true);
testSelectorRoundTrip('#', true);
testSelectorRoundTrip('[]', true);
testSelectorRoundTrip('()', true);

debug('');

testSelectorRoundTrip('*');
testSelectorRoundTrip('a');
testSelectorRoundTrip('#a');
testSelectorRoundTrip('.a');
testSelectorRoundTrip(':active');
testSelectorRoundTrip('[a]');
testSelectorRoundTrip('[a="b"]');
testSelectorRoundTrip('[a~="b"]');
testSelectorRoundTrip('[a|="b"]');
testSelectorRoundTrip('[a^="b"]');
testSelectorRoundTrip('[a$="b"]');
testSelectorRoundTrip('[a*="b"]');
testSelectorRoundTrip('[a="b" i]');
testSelectorRoundTrip('[a~="b" i]');
testSelectorRoundTrip('[a|="b" i]');
testSelectorRoundTrip('[a^="b" i]');
testSelectorRoundTrip('[a$="b" i]');
testSelectorRoundTrip('[a*="b" i]');

debug('');

shouldBeEqualToString("setThenReadSelectorText('*|a')", "a");
shouldBeEqualToString("setThenReadSelectorText('*|*')", "*");
testSelectorRoundTrip('[*|a]');
testSelectorRoundTrip('|*');
testSelectorRoundTrip('[*|a]');
shouldBeEqualToString("setThenReadSelectorText('[|a]')", "[a]");

debug('');

testSelectorRoundTrip('a:active');
testSelectorRoundTrip('a b');
testSelectorRoundTrip('a + b');
testSelectorRoundTrip('a ~ b');
testSelectorRoundTrip('a > b');

debug('');

testSelectorRoundTrip(":active");
testSelectorRoundTrip(":any-link");
testSelectorRoundTrip(":checked");
testSelectorRoundTrip(":disabled");
testSelectorRoundTrip(":empty");
testSelectorRoundTrip(":enabled");
testSelectorRoundTrip(":first-child");
testSelectorRoundTrip(":first-of-type");
testSelectorRoundTrip(":focus");
testSelectorRoundTrip(":hover");
testSelectorRoundTrip(":indeterminate");
testSelectorRoundTrip(":link");
testSelectorRoundTrip(":not(:placeholder-shown)");
testSelectorRoundTrip(":placeholder-shown");
testSelectorRoundTrip(":root");
testSelectorRoundTrip(":target");
testSelectorRoundTrip(":visited");

debug('');

testSelectorRoundTrip(":dir(a)");
testSelectorRoundTrip(':lang("a")');
testSelectorRoundTrip(":lang(a)");
testSelectorRoundTrip(":not(a)");
testSelectorRoundTrip(":-webkit-any(a, b, p)");

debug('');

testSelectorRoundTrip("::after");
testSelectorRoundTrip("::before");
testSelectorRoundTrip("::first-letter");
testSelectorRoundTrip("::first-line");
testSelectorRoundTrip("::selection");

debug('');

testSelectorRoundTrip(":-webkit-any-link");
testSelectorRoundTrip(":-webkit-drag");
testSelectorRoundTrip(":autofill");
testSelectorSerialization(":-webkit-autofill", ":autofill");

testSelectorRoundTrip('a:any-link');
testSelectorRoundTrip('a :any-link');
testSelectorRoundTrip('div:any-link');
testSelectorRoundTrip('div :any-link');
testSelectorRoundTrip(':any-link > div');
testSelectorRoundTrip(':any-link + div');
testSelectorRoundTrip(':not(:any-link)');

debug('');

testSelectorSerialization(":nth-child(odd)", ":nth-child(2n+1)");
testSelectorSerialization(":nth-child(even)", ":nth-child(2n)");
testSelectorRoundTrip(":nth-child(n)");
testSelectorRoundTrip(":nth-child(-n)");
testSelectorRoundTrip(":nth-child(5)");
testSelectorRoundTrip(":nth-child(-5)");
testSelectorRoundTrip(":nth-child(5n+7)");
testSelectorRoundTrip(":nth-child(-5n+7)");
testSelectorRoundTrip(":nth-child(5n-7)");
testSelectorRoundTrip(":nth-child(-5n-7)");

debug('');

testSelectorSerialization(":nth-child(odd of .foo, :nth-child(odd))", ":nth-child(2n+1 of .foo, :nth-child(2n+1))");
testSelectorSerialization(":nth-child(even of .foo, :nth-child(odd))", ":nth-child(2n of .foo, :nth-child(2n+1))");
testSelectorSerialization(":nth-child(n of .foo, :nth-child(odd))", ":nth-child(n of .foo, :nth-child(2n+1))");
testSelectorSerialization(":nth-child(-n of .foo, :nth-child(odd))", ":nth-child(-n of .foo, :nth-child(2n+1))");
testSelectorSerialization(":nth-child(5 of .foo, :nth-child(odd))", ":nth-child(5 of .foo, :nth-child(2n+1))");
testSelectorSerialization(":nth-child(-5 of .foo, :nth-child(odd))", ":nth-child(-5 of .foo, :nth-child(2n+1))");
testSelectorSerialization(":nth-child(5n+7 of .foo, :nth-child(odd))", ":nth-child(5n+7 of .foo, :nth-child(2n+1))");
testSelectorSerialization(":nth-child(-5n+7 of .foo, :nth-child(odd))", ":nth-child(-5n+7 of .foo, :nth-child(2n+1))");
testSelectorSerialization(":nth-child(5n-7 of .foo, :nth-child(odd))", ":nth-child(5n-7 of .foo, :nth-child(2n+1))");
testSelectorSerialization(":nth-child(-5n-7 of .foo, :nth-child(odd))", ":nth-child(-5n-7 of .foo, :nth-child(2n+1))");

debug('');

testSelectorSerialization(":nth-last-child(odd of .foo, :nth-last-child(odd))", ":nth-last-child(2n+1 of .foo, :nth-last-child(2n+1))");
testSelectorSerialization(":nth-last-child(even of .foo, :nth-last-child(odd))", ":nth-last-child(2n of .foo, :nth-last-child(2n+1))");
testSelectorSerialization(":nth-last-child(n of .foo, :nth-last-child(odd))", ":nth-last-child(n of .foo, :nth-last-child(2n+1))");
testSelectorSerialization(":nth-last-child(-n of .foo, :nth-last-child(odd))", ":nth-last-child(-n of .foo, :nth-last-child(2n+1))");
testSelectorSerialization(":nth-last-child(5 of .foo, :nth-last-child(odd))", ":nth-last-child(5 of .foo, :nth-last-child(2n+1))");
testSelectorSerialization(":nth-last-child(-5 of .foo, :nth-last-child(odd))", ":nth-last-child(-5 of .foo, :nth-last-child(2n+1))");
testSelectorSerialization(":nth-last-child(5n+7 of .foo, :nth-last-child(odd))", ":nth-last-child(5n+7 of .foo, :nth-last-child(2n+1))");
testSelectorSerialization(":nth-last-child(-5n+7 of .foo, :nth-last-child(odd))", ":nth-last-child(-5n+7 of .foo, :nth-last-child(2n+1))");
testSelectorSerialization(":nth-last-child(5n-7 of .foo, :nth-last-child(odd))", ":nth-last-child(5n-7 of .foo, :nth-last-child(2n+1))");
testSelectorSerialization(":nth-last-child(-5n-7 of .foo, :nth-last-child(odd))", ":nth-last-child(-5n-7 of .foo, :nth-last-child(2n+1))");

debug('');

testSelectorRoundTrip(':is(single)');
testSelectorRoundTrip(':is(a, b, p)');
testSelectorRoundTrip(':is(#alice, #bob, #chris)');
testSelectorRoundTrip(':is(.selector, #tama, #hanayo, #midoriko)');
testSelectorRoundTrip(':is(.name, #ok, :visited)');
testSelectorRoundTrip(':is(.name, #ok, :visited, :link)');
testSelectorRoundTrip(':is(.name, #ok, :is(:visited))');
testSelectorRoundTrip(':is(.name, #ok, :not(:link))');
testSelectorRoundTrip(':is(.name, #ok, :not(:link))');
testSelectorRoundTrip(':is(.name, #ok, :-webkit-any(hello))');
testSelectorRoundTrip(':is(.name, #ok, :-webkit-any(.selector, #tama, #hanayo, #midoriko))');
testSelectorRoundTrip(':is([type="file"])');
testSelectorRoundTrip(':is(:hover)');
testSelectorRoundTrip('input:is([type="file"], :hover, :focus):enabled');
testSelectorRoundTrip(':is(input[type="file"], a:hover, button:focus)');
testSelectorRoundTrip(':is(.class1.class2.class3)');
testSelectorRoundTrip(':is(.class1:hover)');
testSelectorRoundTrip(':is(a.class1.class2.class3:hover)');
testSelectorRoundTrip(':where(single)');
testSelectorRoundTrip(':where(a, b, p)');
testSelectorRoundTrip(':where(#alice, #bob, #chris)');
testSelectorRoundTrip(':where(.selector, #tama, #hanayo, #midoriko)');
testSelectorRoundTrip(':where(.name, #ok, :visited)');
testSelectorRoundTrip(':where(.name, #ok, :visited, :link)');
testSelectorRoundTrip(':where(.name, #ok, :where(:visited))');
testSelectorRoundTrip(':where(.name, #ok, :not(:link))');
testSelectorRoundTrip(':where(.name, #ok, :not(:link))');
testSelectorRoundTrip(':where(.name, #ok, :where(hello))');
testSelectorRoundTrip(':where(.name, #ok, :where(.selector, #tama, #hanayo, #midoriko))');
testSelectorRoundTrip(':where([type="file"])');
testSelectorRoundTrip(':where(:hover)');
testSelectorRoundTrip('input:where([type="file"], :hover, :focus):enabled');
testSelectorRoundTrip(':where(input[type="file"], a:hover, button:focus)');
testSelectorRoundTrip(':where(.class1.class2.class3)');
testSelectorRoundTrip(':where(.class1:hover)');
testSelectorRoundTrip(':where(a.class1.class2.class3:hover)');
testSelectorRoundTrip(':matches(:is(single))');
testSelectorRoundTrip(':matches(:is(a, b, p))');
testSelectorRoundTrip(':matches(:is(#alice, #bob, #chris))');
testSelectorRoundTrip(':matches(:is(.selector, #tama, #hanayo, #midoriko))');
testSelectorRoundTrip(':matches(:is(.name, #ok, :visited))');
testSelectorRoundTrip(':matches(:is(.name, #ok, :visited, :link))');
testSelectorRoundTrip(':matches(:is(.name, #ok, :is(:visited)))');
testSelectorRoundTrip(':matches(:is(.name, #ok, :not(:link)))');
testSelectorRoundTrip(':matches(:is(.name, #ok, :not(:link)))');
testSelectorRoundTrip(':matches(:is(.name, #ok, :matches(hello)))');
testSelectorRoundTrip(':matches(:is(.name, #ok, :matches(.selector, #tama, #hanayo, #midoriko)))');
testSelectorRoundTrip(':matches(:is([type="file"]))');
testSelectorRoundTrip(':matches(:is(:hover))');
testSelectorRoundTrip(':matches(input:is([type="file"], :hover, :focus):enabled)');
testSelectorRoundTrip(':matches(:is(input[type="file"], a:hover, button:focus))');
testSelectorRoundTrip(':matches(:is(.class1.class2.class3))');
testSelectorRoundTrip(':matches(:is(.class1:hover))');
testSelectorRoundTrip(':matches(:is(a.class1.class2.class3:hover))');
testSelectorRoundTrip(':-webkit-any(:is(single))');
testSelectorRoundTrip(':-webkit-any(:is(a, b, p))');
testSelectorRoundTrip(':-webkit-any(:is(#alice, #bob, #chris))');
testSelectorRoundTrip(':-webkit-any(:is(.selector, #tama, #hanayo, #midoriko))');
testSelectorRoundTrip(':-webkit-any(:is(.name, #ok, :visited))');
testSelectorRoundTrip(':-webkit-any(:is(.name, #ok, :visited, :link))');
testSelectorRoundTrip(':-webkit-any(:is(.name, #ok, :is(:visited)))');
testSelectorRoundTrip(':-webkit-any(:is(.name, #ok, :not(:link)))');
testSelectorRoundTrip(':-webkit-any(:is(.name, #ok, :not(:link)))');
testSelectorRoundTrip(':-webkit-any(:is(.name, #ok, :-webkit-any(hello)))');
testSelectorRoundTrip(':-webkit-any(:is(.name, #ok, :-webkit-any(.selector, #tama, #hanayo, #midoriko)))');
testSelectorRoundTrip(':-webkit-any(:is([type="file"]))');
testSelectorRoundTrip(':-webkit-any(:is(:hover))');
testSelectorRoundTrip(':-webkit-any(input:is([type="file"], :hover, :focus):enabled)');
testSelectorRoundTrip(':-webkit-any(:is(input[type="file"], a:hover, button:focus))');
testSelectorRoundTrip(':-webkit-any(:is(.class1.class2.class3))');
testSelectorRoundTrip(':-webkit-any(:is(.class1:hover))');
testSelectorRoundTrip(':-webkit-any(:is(a.class1.class2.class3:hover))');

debug('');

testSelectorRoundTrip(':matches(single)');
testSelectorRoundTrip(':matches(a, b, p)');
testSelectorRoundTrip(':matches(#alice, #bob, #chris)');
testSelectorRoundTrip(':matches(.selector, #tama, #hanayo, #midoriko)');
testSelectorRoundTrip(':matches(.name, #ok, :visited)');
testSelectorRoundTrip(':matches(.name, #ok, :visited, :link)');
testSelectorRoundTrip(':matches(.name, #ok, :matches(:visited))');
testSelectorRoundTrip(':matches(.name, #ok, :not(:link))');
testSelectorRoundTrip(':matches(.name, #ok, :not(:link))');
testSelectorRoundTrip(':matches(.name, #ok, :-webkit-any(hello))');
testSelectorRoundTrip(':matches(.name, #ok, :-webkit-any(.selector, #tama, #hanayo, #midoriko))');
testSelectorRoundTrip(':matches([type="file"])');
testSelectorRoundTrip(':matches(:hover)');
testSelectorRoundTrip('input:matches([type="file"], :hover, :focus):enabled');
testSelectorRoundTrip(':matches(input[type="file"], a:hover, button:focus)');
testSelectorRoundTrip(':matches(.class1.class2.class3)');
testSelectorRoundTrip(':matches(.class1:hover)');
testSelectorRoundTrip(':matches(a.class1.class2.class3:hover)');
testSelectorRoundTrip(':is(:matches(single))');
testSelectorRoundTrip(':is(:matches(a, b, p))');
testSelectorRoundTrip(':is(:matches(#alice, #bob, #chris))');
testSelectorRoundTrip(':is(:matches(.selector, #tama, #hanayo, #midoriko))');
testSelectorRoundTrip(':is(:matches(.name, #ok, :visited))');
testSelectorRoundTrip(':is(:matches(.name, #ok, :visited, :link))');
testSelectorRoundTrip(':is(:matches(.name, #ok, :matches(:visited)))');
testSelectorRoundTrip(':is(:matches(.name, #ok, :not(:link)))');
testSelectorRoundTrip(':is(:matches(.name, #ok, :not(:link)))');
testSelectorRoundTrip(':is(:matches(.name, #ok, :is(hello)))');
testSelectorRoundTrip(':is(:matches(.name, #ok, :is(.selector, #tama, #hanayo, #midoriko)))');
testSelectorRoundTrip(':is(:matches([type="file"]))');
testSelectorRoundTrip(':is(:matches(:hover))');
testSelectorRoundTrip(':is(input:matches([type="file"], :hover, :focus):enabled)');
testSelectorRoundTrip(':is(:matches(input[type="file"], a:hover, button:focus))');
testSelectorRoundTrip(':is(:matches(.class1.class2.class3))');
testSelectorRoundTrip(':is(:matches(.class1:hover))');
testSelectorRoundTrip(':is(:matches(a.class1.class2.class3:hover))');
testSelectorRoundTrip(':-webkit-any(:matches(single))');
testSelectorRoundTrip(':-webkit-any(:matches(a, b, p))');
testSelectorRoundTrip(':-webkit-any(:matches(#alice, #bob, #chris))');
testSelectorRoundTrip(':-webkit-any(:matches(.selector, #tama, #hanayo, #midoriko))');
testSelectorRoundTrip(':-webkit-any(:matches(.name, #ok, :visited))');
testSelectorRoundTrip(':-webkit-any(:matches(.name, #ok, :visited, :link))');
testSelectorRoundTrip(':-webkit-any(:matches(.name, #ok, :matches(:visited)))');
testSelectorRoundTrip(':-webkit-any(:matches(.name, #ok, :not(:link)))');
testSelectorRoundTrip(':-webkit-any(:matches(.name, #ok, :not(:link)))');
testSelectorRoundTrip(':-webkit-any(:matches(.name, #ok, :-webkit-any(hello)))');
testSelectorRoundTrip(':-webkit-any(:matches(.name, #ok, :-webkit-any(.selector, #tama, #hanayo, #midoriko)))');
testSelectorRoundTrip(':-webkit-any(:matches([type="file"]))');
testSelectorRoundTrip(':-webkit-any(:matches(:hover))');
testSelectorRoundTrip(':-webkit-any(input:matches([type="file"], :hover, :focus):enabled)');
testSelectorRoundTrip(':-webkit-any(:matches(input[type="file"], a:hover, button:focus))');
testSelectorRoundTrip(':-webkit-any(:matches(.class1.class2.class3))');
testSelectorRoundTrip(':-webkit-any(:matches(.class1:hover))');
testSelectorRoundTrip(':-webkit-any(:matches(a.class1.class2.class3:hover))');

debug('');

testSelectorRoundTrip(':not(div)');
testSelectorRoundTrip(':not(.div)');
testSelectorRoundTrip(':not(#div)');
testSelectorRoundTrip(':not([div])');
testSelectorRoundTrip(':not(:empty)');
testSelectorRoundTrip(':not(div.div#div[div]:empty)');
testSelectorRoundTrip(':not(div.div:empty[div]#div)');
testSelectorRoundTrip(':not(div.div, #div[div], :empty)');
testSelectorRoundTrip(':not(div, .div, #div, [div], :empty)');

testSelectorRoundTrip(':not(:not(div))');
testSelectorRoundTrip(':not(:not(div)):not(:not(foo)):not(:not(bar))');
testSelectorRoundTrip(':not(:not(div, :not(foo, bar))):not(:not(foo)):not(:not(bar, baz))');

testSelectorRoundTrip(':not(:is(*))');
testSelectorRoundTrip(':not(:is(foo, bar))');
testSelectorRoundTrip(':not(:is(foo, bar), :is(.foo, .bar), :is(#foo, #bar), :is([foo], [bar]))');
testSelectorRoundTrip(':not(:is(foo, bar:not(:empty)), :is(.foo, .bar:not(:not(.mosaic))), :is(#foo, #bar), :is([foo], [bar]))');

testSelectorRoundTrip(':not(:matches(*))');
testSelectorRoundTrip(':not(:matches(foo, bar))');
testSelectorRoundTrip(':not(:matches(foo, bar), :matches(.foo, .bar), :matches(#foo, #bar), :matches([foo], [bar]))');
testSelectorRoundTrip(':not(:matches(foo, bar:not(:empty)), :matches(.foo, .bar:not(:not(.mosaic))), :matches(#foo, #bar), :matches([foo], [bar]))');

testSelectorRoundTrip(':nth-child(2n of :not(a.b, c#d.e))');
testSelectorRoundTrip(':not(:nth-child(2n of :not(a.b, c#d.e)))');

testSelectorRoundTrip(':not(a .b, #c > [d], e + f:empty, .g ~ #h:first-child)');
testSelectorRoundTrip('a:not(a .b, #c > [d], e + f:empty, .g ~ #h:first-child) b + c:not(a .b, #c > [d], e + f:empty, .g ~ #h:first-child) ~ d:not(a .b, #c > [d], e + f:empty, .g ~ #h:first-child) > d:not(a .b, #c > [d], e + f:empty, .g ~ #h:first-child)');

debug('');

shouldBeEqualToString("setThenReadSelectorText('::-webkit-file-upload-button')", "::-webkit-file-upload-button");
shouldBeEqualToString("setThenReadSelectorText('::-webkit-search-cancel-button')", "::-webkit-search-cancel-button");
shouldBeEqualToString("setThenReadSelectorText('::-webkit-search-decoration')", "::-webkit-search-decoration");
shouldBeEqualToString("setThenReadSelectorText('::-webkit-search-results-button')", "::-webkit-search-results-button");
shouldBeEqualToString("setThenReadSelectorText('::-webkit-search-results-decoration')", "::-webkit-search-results-decoration");
shouldBeEqualToString("setThenReadSelectorText('::-webkit-slider-thumb')", "::-webkit-slider-thumb");

debug('');

testSelectorRoundTrip("a::-webkit-slider-thumb");
shouldBeEqualToString("setThenReadSelectorText('a ::-webkit-slider-thumb')", "a ::-webkit-slider-thumb");
testSelectorRoundTrip("[a]::-webkit-slider-thumb");
shouldBeEqualToString("setThenReadSelectorText('[a] ::-webkit-slider-thumb')", "[a] ::-webkit-slider-thumb");
testSelectorRoundTrip(".a::-webkit-slider-thumb");
shouldBeEqualToString("setThenReadSelectorText('.a ::-webkit-slider-thumb')", ".a ::-webkit-slider-thumb");
testSelectorRoundTrip("#a::-webkit-slider-thumb");
shouldBeEqualToString("setThenReadSelectorText('#a ::-webkit-slider-thumb')", "#a ::-webkit-slider-thumb");
shouldBeEqualToString("setThenReadSelectorText('* ::-webkit-slider-thumb')", "* ::-webkit-slider-thumb");

debug('');

testSelectorRoundTrip("a[b]::-webkit-slider-thumb");
testSelectorRoundTrip("a.b::-webkit-slider-thumb");
testSelectorRoundTrip("a#b::-webkit-slider-thumb");
testSelectorRoundTrip("a[b].c#d::-webkit-slider-thumb");

debug('');

testSelectorRoundTrip("a[b]::placeholder");
testSelectorRoundTrip("a.b::placeholder");
testSelectorRoundTrip("a#b::placeholder");
testSelectorRoundTrip("a[b].c#d::placeholder");
testSelectorRoundTrip("a[b]::-webkit-input-placeholder");
testSelectorRoundTrip("a.b::-webkit-input-placeholder");
testSelectorRoundTrip("a#b::-webkit-input-placeholder");
testSelectorRoundTrip("a[b].c#d::-webkit-input-placeholder");

debug('');

testSelectorRoundTrip("a[b]:default");
testSelectorRoundTrip("a.b:default");
testSelectorRoundTrip("a#b:default");
testSelectorRoundTrip("a[b].c#d:default");

debug('');

testSelectorRoundTrip("a[b]:in-range");
testSelectorRoundTrip("a.b:in-range");
testSelectorRoundTrip("a#b:in-range");
testSelectorRoundTrip("a[b].c#d:in-range");

debug('');

testSelectorRoundTrip("a[b]:out-of-range");
testSelectorRoundTrip("a.b:out-of-range");
testSelectorRoundTrip("a#b:out-of-range");
testSelectorRoundTrip("a[b].c#d:out-of-range");

debug('');

testSelectorRoundTrip("a[b]:focus-within");
testSelectorRoundTrip("a.b:focus-within");
testSelectorRoundTrip("a#b:focus-within");
testSelectorRoundTrip("a[b].c#d:focus-within");

debug('');

testSelectorRoundTrip('input:not([type="file"]):focus');
testSelectorRoundTrip(':-webkit-any([type="file"])');
testSelectorRoundTrip(':-webkit-any(:hover)');
testSelectorRoundTrip('input:-webkit-any([type="file"], :hover, :focus):enabled');
testSelectorRoundTrip(':-webkit-any(input[type="file"], a:hover, button:focus)');
testSelectorRoundTrip(':-webkit-any(.class1.class2.class3)');
testSelectorRoundTrip(':-webkit-any(.class1:hover)');
testSelectorRoundTrip(':-webkit-any(a.class1.class2.class3:hover)');

debug('');

shouldBeEqualToString("setThenReadSelectorText('*:active')", ":active");

debug('');

shouldBeEqualToString("setThenReadSelectorText('input[type=file]:focus')", 'input[type="file"]:focus');

debug('');

shouldBeEqualToString("setThenReadSelectorText('a+b')", "a + b");
shouldBeEqualToString("setThenReadSelectorText('a~b')", "a ~ b");
shouldBeEqualToString("setThenReadSelectorText('a>b')", "a > b");

debug('');

shouldBeEqualToString("setThenReadSelectorText(':after')", "::after");
shouldBeEqualToString("setThenReadSelectorText(':before')", "::before");
shouldBeEqualToString("setThenReadSelectorText(':first-letter')", "::first-letter");
shouldBeEqualToString("setThenReadSelectorText(':first-line')", "::first-line");
shouldBeEqualToString("setThenReadSelectorText(':-webkit-any(    a.class1  ,  	#id,[attr]  )')", ":-webkit-any(a.class1, #id, [attr])");

debug('');

shouldBeEqualToString("setThenReadSelectorText(':is(single    )')", ":is(single)");
shouldBeEqualToString("setThenReadSelectorText(':is(a,b    ,p)')", ":is(a, b, p)");
shouldBeEqualToString("setThenReadSelectorText(':is(#alice,                   #bob,#chris)')", ":is(#alice, #bob, #chris)");
shouldBeEqualToString("setThenReadSelectorText(':is(  .selector,#tama,                #hanayo,#midoriko)')", ":is(.selector, #tama, #hanayo, #midoriko)");
shouldBeEqualToString("setThenReadSelectorText(':is(    .name,#ok,:visited   )')", ":is(.name, #ok, :visited)");
shouldBeEqualToString("setThenReadSelectorText(':is(    .name,#ok,    :visited, :link)')", ":is(.name, #ok, :visited, :link)");
shouldBeEqualToString("setThenReadSelectorText(':is(    .name,#ok,    :is(:visited    ))')", ":is(.name, #ok, :is(:visited))");
shouldBeEqualToString("setThenReadSelectorText(':is(.name,  #ok,:not(:link))')", ":is(.name, #ok, :not(:link))");
shouldBeEqualToString("setThenReadSelectorText(':is(.name,#ok,:not(:link))')", ":is(.name, #ok, :not(:link))");
shouldBeEqualToString("setThenReadSelectorText(':is(    .name,#ok,:-webkit-any(   hello))')", ":is(.name, #ok, :-webkit-any(hello))");
shouldBeEqualToString("setThenReadSelectorText(':is(    .name,#ok, :-webkit-any(.selector, #tama, #hanayo, #midoriko))')", ":is(.name, #ok, :-webkit-any(.selector, #tama, #hanayo, #midoriko))");
shouldBeEqualToString("setThenReadSelectorText(':is(       [type=\"file\"])')", ':is([type="file"])');
shouldBeEqualToString("setThenReadSelectorText(':is(  :hover    )')", ":is(:hover)");
shouldBeEqualToString("setThenReadSelectorText('input:is([type=\"file\"],:hover,:focus):enabled')", 'input:is([type="file"], :hover, :focus):enabled');
shouldBeEqualToString("setThenReadSelectorText(':is(input[type=\"file\"], a:hover, button:focus)')", ':is(input[type="file"], a:hover, button:focus)');
shouldBeEqualToString("setThenReadSelectorText(':is( .class1.class2.class3   )')", ":is(.class1.class2.class3)");
shouldBeEqualToString("setThenReadSelectorText(':is(.class1:hover   )')", ":is(.class1:hover)");
shouldBeEqualToString("setThenReadSelectorText(':is(a.class1.class2.class3:hover   )')", ":is(a.class1.class2.class3:hover)");

debug('');

shouldBeEqualToString("setThenReadSelectorText(':matches(single    )')", ":matches(single)");
shouldBeEqualToString("setThenReadSelectorText(':matches(a,b    ,p)')", ":matches(a, b, p)");
shouldBeEqualToString("setThenReadSelectorText(':matches(#alice,                   #bob,#chris)')", ":matches(#alice, #bob, #chris)");
shouldBeEqualToString("setThenReadSelectorText(':matches(  .selector,#tama,                #hanayo,#midoriko)')", ":matches(.selector, #tama, #hanayo, #midoriko)");
shouldBeEqualToString("setThenReadSelectorText(':matches(    .name,#ok,:visited   )')", ":matches(.name, #ok, :visited)");
shouldBeEqualToString("setThenReadSelectorText(':matches(    .name,#ok,    :visited, :link)')", ":matches(.name, #ok, :visited, :link)");
shouldBeEqualToString("setThenReadSelectorText(':matches(    .name,#ok,    :matches(:visited    ))')", ":matches(.name, #ok, :matches(:visited))");
shouldBeEqualToString("setThenReadSelectorText(':matches(.name,  #ok,:not(:link))')", ":matches(.name, #ok, :not(:link))");
shouldBeEqualToString("setThenReadSelectorText(':matches(.name,#ok,:not(:link))')", ":matches(.name, #ok, :not(:link))");
shouldBeEqualToString("setThenReadSelectorText(':matches(    .name,#ok,:-webkit-any(   hello))')", ":matches(.name, #ok, :-webkit-any(hello))");
shouldBeEqualToString("setThenReadSelectorText(':matches(    .name,#ok, :-webkit-any(.selector, #tama, #hanayo, #midoriko))')", ":matches(.name, #ok, :-webkit-any(.selector, #tama, #hanayo, #midoriko))");
shouldBeEqualToString("setThenReadSelectorText(':matches(       [type=\"file\"])')", ':matches([type="file"])');
shouldBeEqualToString("setThenReadSelectorText(':matches(  :hover    )')", ":matches(:hover)");
shouldBeEqualToString("setThenReadSelectorText('input:matches([type=\"file\"],:hover,:focus):enabled')", 'input:matches([type="file"], :hover, :focus):enabled');
shouldBeEqualToString("setThenReadSelectorText(':matches(input[type=\"file\"], a:hover, button:focus)')", ':matches(input[type="file"], a:hover, button:focus)');
shouldBeEqualToString("setThenReadSelectorText(':matches( .class1.class2.class3   )')", ":matches(.class1.class2.class3)");
shouldBeEqualToString("setThenReadSelectorText(':matches(.class1:hover   )')", ":matches(.class1:hover)");
shouldBeEqualToString("setThenReadSelectorText(':matches(a.class1.class2.class3:hover   )')", ":matches(a.class1.class2.class3:hover)");

debug('');

shouldBeEqualToString("setThenReadSelectorText(':not(single    )')", ":not(single)");
shouldBeEqualToString("setThenReadSelectorText(':not(a,b    ,p)')", ":not(a, b, p)");
shouldBeEqualToString("setThenReadSelectorText(':not(#alice,                   #bob,#chris)')", ":not(#alice, #bob, #chris)");
shouldBeEqualToString("setThenReadSelectorText(':not(  .selector,#tama,                #hanayo,#midoriko)')", ":not(.selector, #tama, #hanayo, #midoriko)");
shouldBeEqualToString("setThenReadSelectorText(':not(    .name,#ok,:visited   )')", ":not(.name, #ok, :visited)");
shouldBeEqualToString("setThenReadSelectorText(':not(    .name,#ok,    :visited, :link)')", ":not(.name, #ok, :visited, :link)");
shouldBeEqualToString("setThenReadSelectorText(':not(    .name,#ok,    :not(:visited    ))')", ":not(.name, #ok, :not(:visited))");
shouldBeEqualToString("setThenReadSelectorText(':not(.name,  #ok,:not(:link))')", ":not(.name, #ok, :not(:link))");
shouldBeEqualToString("setThenReadSelectorText(':not(.name,#ok,:not(:link))')", ":not(.name, #ok, :not(:link))");
shouldBeEqualToString("setThenReadSelectorText(':not(    .name,#ok,:-webkit-any(   hello))')", ":not(.name, #ok, :-webkit-any(hello))");
shouldBeEqualToString("setThenReadSelectorText(':not(    .name,#ok, :-webkit-any(.selector, #tama, #hanayo, #midoriko))')", ":not(.name, #ok, :-webkit-any(.selector, #tama, #hanayo, #midoriko))");
shouldBeEqualToString("setThenReadSelectorText(':not(       [type=\"file\"])')", ':not([type="file"])');
shouldBeEqualToString("setThenReadSelectorText(':not(  :hover    )')", ":not(:hover)");
shouldBeEqualToString("setThenReadSelectorText('input:not([type=\"file\"],:hover,:focus):enabled')", 'input:not([type="file"], :hover, :focus):enabled');
shouldBeEqualToString("setThenReadSelectorText(':not(input[type=\"file\"], a:hover, button:focus)')", ':not(input[type="file"], a:hover, button:focus)');
shouldBeEqualToString("setThenReadSelectorText(':not( .class1.class2.class3   )')", ":not(.class1.class2.class3)");
shouldBeEqualToString("setThenReadSelectorText(':not(.class1:hover   )')", ":not(.class1:hover)");
shouldBeEqualToString("setThenReadSelectorText(':not(a.class1.class2.class3:hover   )')", ":not(a.class1.class2.class3:hover)");
shouldBeEqualToString("setThenReadSelectorText(':not(:is(single    ),:is(a,b    ,p),:is(#alice,                   #bob,#chris))')", ":not(:is(single), :is(a, b, p), :is(#alice, #bob, #chris))");
shouldBeEqualToString("setThenReadSelectorText(':not(:matches(single    ),:matches(a,b    ,p),:matches(#alice,                   #bob,#chris))')", ":not(:matches(single), :matches(a, b, p), :matches(#alice, #bob, #chris))");

debug('');

</script>
</body>
</html>
