| <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; border: 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, '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, '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> |