<html>
<head>
<title>Pseudo Element Matching in Shadow DOM</title>
<style>
    input[type=range] {
        -webkit-appearance: none;
    }
</style>
<script>

if (window.testRunner)
    testRunner.dumpAsText();

var head;
var input;
var logDiv;
var NAMESPACE_DECLARATION = '@namespace "http://example.com/foo/namespace";\n@namespace html "http://www.w3.org/1999/xhtml";\n';
var SELECTOR_TEST_PROPERTIES = ' { height: 1px; -webkit-appearance: none; }';
var SELECTORS = [
'::-webkit-slider-thumb',
'*::-webkit-slider-thumb',
'input::-webkit-slider-thumb',
'#foo::-webkit-slider-thumb',
'input#foo::-webkit-slider-thumb',
'input.bar::-webkit-slider-thumb',
'input[type=range]::-webkit-slider-thumb'
];
var DISABLED_SELECTORS = SELECTORS.map(function(selector) { return selector + ':disabled'; });
var HOVER_SELECTORS = SELECTORS.map(function(selector) { return selector + ':hover'; });
var DESCENDANT_ID_SELECTORS = SELECTORS.map(function(selector) { return '#baz ' + selector; });
var DESCENDANT_CLASS_SELECTORS = SELECTORS.map(function(selector) { return '.qux ' + selector; });
var DIRECT_SIBLING_ID_SELECTORS = SELECTORS.map(function(selector) { return '#sib + ' + selector; });
var INDIRECT_SIBLING_ID_SELECTORS = SELECTORS.map(function(selector) { return '#sib ~ ' + selector; });
var DIRECT_SIBLING_CLASS_SELECTORS = SELECTORS.map(function(selector) { return '.ling + ' + selector; });
var INDIRECT_SIBLING_CLASS_SELECTORS = SELECTORS.map(function(selector) { return '.ling ~ ' + selector; });

// convenience constants
var MATCH = true;
var NO_MATCH = false;
var WITH_NAMESPACES = true;

function log(msg, success)
{
    logDiv.appendChild(document.createElement('div')).innerHTML = msg + (arguments.length == 1 ? '' : (': ' + (success ? 'PASS' : 'FAIL')));
}

function hoverOverSliderThumb()
{
    if (!window.eventSender)
        return false;

    var x = input.offsetLeft + input.offsetWidth / 2;
    var y = input.offsetTop + input.offsetHeight / 2;
    eventSender.mouseMoveTo(x, y);
    return true;
}

function runSelectorTest(matchExpected, selector, useNamespaces)
{
    var style = document.createElement('style');
    style.textContent = (useNamespaces ? NAMESPACE_DECLARATION : '') + selector + SELECTOR_TEST_PROPERTIES;
    head.appendChild(style);
    var matched = input.offsetHeight == 1;
    log('<code>' + selector + '</code>' + (useNamespaces ? ', where  HTML is not default namespace' : '') + ' <strong>should' + (matchExpected ? '' : ' not') + '</strong> match', matchExpected ? matched : !matched);
    head.removeChild(style);
}

function runTest()
{
    head = document.getElementsByTagName('head')[0];
    input = document.getElementsByTagName('input')[0];
    testContainer = document.getElementById('baz');
    logDiv = document.getElementById('log');
    log('Basic selector tests:');
    runSelectorTest(MATCH, '::-webkit-slider-thumb');
    runSelectorTest(MATCH, '*::-webkit-slider-thumb');
    runSelectorTest(NO_MATCH, '::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, '*|::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, '*|*::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, 'html|::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, 'html|*::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, '#foo::-webkit-slider-thumb');
    runSelectorTest(MATCH, '.bar::-webkit-slider-thumb');
    runSelectorTest(NO_MATCH, '#foo::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(NO_MATCH, '.bar::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, 'html|#foo::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, 'html|.bar::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, '*|#foo::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, 'input::-webkit-slider-thumb');
    runSelectorTest(MATCH, 'input#foo::-webkit-slider-thumb');
    runSelectorTest(MATCH, 'input.bar::-webkit-slider-thumb');
    runSelectorTest(NO_MATCH, 'input::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(NO_MATCH, 'input#foo::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(NO_MATCH, 'input.bar::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, 'html|input::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, 'html|input#foo::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, 'html|input.bar::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, '*|input#foo::-webkit-slider-thumb', WITH_NAMESPACES);
    runSelectorTest(MATCH, 'input[type=range]::-webkit-slider-thumb');
    runSelectorTest(MATCH, 'input#foo[type=range]::-webkit-slider-thumb');
    runSelectorTest(MATCH, 'input.bar[type=range]::-webkit-slider-thumb');
    log('<br>Shouldn\'t ignore selector after the unknown pseudo element:');
    DISABLED_SELECTORS.forEach(expectNoMatch);
    input.disabled = true;
    log('<br>Should not match disabled input, because the disabled state is on the input, not the thumb:');
    DISABLED_SELECTORS.forEach(expectNoMatch);
    input.disabled = false;
    if (!hoverOverSliderThumb()) {
        log(':hover tests require DRT');
        return;
    }
    log('<br>Should match :hover when the mouse is over the slider thumb:');
    HOVER_SELECTORS.forEach(expectMatch);
    log('<br>Should match when combined with descendant selectors:');
    DESCENDANT_ID_SELECTORS.forEach(expectMatch);
    DESCENDANT_CLASS_SELECTORS.forEach(expectMatch);
    log('<br>Should match when combined with sibling selectors:');
    DIRECT_SIBLING_ID_SELECTORS.forEach(expectMatch);
    INDIRECT_SIBLING_ID_SELECTORS.forEach(expectMatch);
    DIRECT_SIBLING_CLASS_SELECTORS.forEach(expectMatch);
    INDIRECT_SIBLING_CLASS_SELECTORS.forEach(expectMatch);

    testContainer.parentNode.removeChild(testContainer);
}

function expectNoMatch(selector) {
    runSelectorTest(NO_MATCH, selector);
}

function expectMatch(selector) {
    runSelectorTest(MATCH, selector);
}

</script>
</head>
<body onload="runTest()">
    <p>Tests various selector combinations, containing unknown pseudo element selectors.</p>
    <div id="baz" class="qux">
        <span id="sib" class="ling">Sibling</span>
        <input id="foo" class="bar" type="range">
    </div>
    <div id="log"></div>
</body>
</html>
