chromium/third_party/blink/web_tests/fast/dom/shadow/shadow-tree-styles-select-host.html

<!doctype html>
<html>
<head>
<script src="../../../resources/js-test.js"></script>
<script src="resources/shadow-dom.js"></script>
</head>
<body>
  <div id='sandbox'></div>
  <pre id='console'></pre>
</body>
<script>
description('Test for issue 247275: shadow tree styles selects shadow host.');

var sandbox = document.getElementById('sandbox');

function borderColorOf(selector) {
    return window.getComputedStyle(getNodeInComposedTree(selector)).borderColor;
}

function shouldHaveBorderColor(selector, color) {
    shouldBeEqualToString('borderColorOf(\'' + selector + '\')', color);
}

function shouldNotHaveBorderColor(selector, color) {
    var text = 'borderColorOf(\'' + selector + '\')';
    var unevaledString = '"' + color.replace(/\\/g, "\\\\").replace(/"/g, "\"") + '"';
    shouldNotBe(text, unevaledString);
}

function cleanUp() {
    sandbox.innerHTML = '';
}

debug('Test that tag selectors in a shadow tree cannot match without :host.');

sandbox.appendChild(
    createDOM('div', {'id': 'host'},
        createShadowRoot(
            createDOM('style', {},
                document.createTextNode('div { border: 1px solid green; }')),
            createDOM('content', {})),
        createDOM('div', {'id': 'host-child'},
            document.createTextNode('Hello, Host!'))));

shouldHaveBorderColor('host', 'rgb(0, 0, 0)');
shouldHaveBorderColor('host-child', 'rgb(0, 0, 0)');

cleanUp();

debug('Test that * in a shadow tree cannot match without :host.');

sandbox.appendChild(
    createDOM('div', {'id': 'host'},
        createShadowRoot(
            createDOM('style', {},
                document.createTextNode('* { border: 1px solid green; }')),
            createDOM('content', {})),
        createDOM('div', {'id': 'host-child'},
            document.createTextNode('Hello, Host!'))));

shouldNotHaveBorderColor('host', 'rgb(0, 128, 0)');
shouldHaveBorderColor('host-child', 'rgb(0, 0, 0)');

cleanUp();

debug('Test that :not(*) in a shadow tree cannot match without :host.');

sandbox.appendChild(
    createDOM('div', {'id': 'host'},
        createShadowRoot(
            createDOM('style', {},
                document.createTextNode(':not(*) { border: 1px solid green; }')),
            createDOM('content', {})),
        createDOM('div', {'id': 'host-child'},
            document.createTextNode('Hello, Host!'))));

shouldHaveBorderColor('host', 'rgb(0, 0, 0)');
shouldHaveBorderColor('host-child', 'rgb(0, 0, 0)');

cleanUp();

debug('Test that :first-child in a shadow tree cannot match without :host.');

sandbox.appendChild(
    createDOM('div', {'id': 'host'},
        createShadowRoot(
            createDOM('style', {},
                document.createTextNode(':first-child { border: 1px solid green; }')),
            createDOM('content', {})),
        createDOM('div', {'id': 'host-child'},
            document.createTextNode('Hello, Host!'))));

shouldHaveBorderColor('host', 'rgb(0, 0, 0)');

cleanUp();

debug('Test that styles in a containing treescope wins if specificities are the same.');

sandbox.appendChild(
    createDOM('style', {},
        document.createTextNode(':last-child { border: 1px solid green; }')));
sandbox.appendChild(
    createDOM('div', {'id': 'host'},
        createShadowRoot(
            createDOM('style', {},
                document.createTextNode(':host { border: 1px solid red; }')),
            createDOM('content', {})),
        createDOM('div', {'id': 'host-child'},
            document.createTextNode('Hello, Host!'))));

shouldHaveBorderColor('host', 'rgb(0, 128, 0)');

cleanUp();

debug('Test that rules which has higher specificity win.');

sandbox.appendChild(
    createDOM('style', {},
        document.createTextNode('div { border: 1px solid red; }')));
sandbox.appendChild(
    createDOM('div', {'id': 'host'},
        createShadowRoot(
            createDOM('style', {},
                document.createTextNode(':host { border: 1px solid green; }')),
            createDOM('content', {})),
        createDOM('div', {'id': 'host-child'},
            document.createTextNode('Hello, Host!'))));

shouldHaveBorderColor('host', 'rgb(255, 0, 0)');

cleanUp();

debug('Test that child selector with a shadow host and children of a shadow root of the shadow host works.');

sandbox.appendChild(
    createDOM('div', {'id': 'divA'},
        createDOM('div', {'id': 'host'},
            createShadowRoot(
                createDOM('style', {},
                    document.createTextNode('div { border: 1px solid green; } div > div { border: 1px solid red; }')),
                createDOM('div', {'id': 'divC'}),
                createDOM('content')),
            createDOM('div', {'id': 'host-child'},
                document.createTextNode('Hello, HostB!'))),
        createDOM('div', {'id': 'divA-child'},
            document.createTextNode('Hello, HostA!'))));

shouldHaveBorderColor('divA', 'rgb(0, 0, 0)');
shouldHaveBorderColor('divA-child', 'rgb(0, 0, 0)');
shouldHaveBorderColor('host', 'rgb(0, 0, 0)');
shouldHaveBorderColor('host/divC', 'rgb(0, 128, 0)');
shouldHaveBorderColor('host-child', 'rgb(0, 0, 0)');

cleanUp();

debug('Test that descendant selector with a shadow host and descendants of a shadow root of the shadow host works.');

sandbox.appendChild(
    createDOM('div', {'id': 'divA'},
        createDOM('div', {'id': 'host'},
            createShadowRoot(
                createDOM('style', {},
                    document.createTextNode('div { border: 1px solid green; } div span { border: 1px solid red; }')),
                createDOM('div', {'id': 'divC'},
                    createDOM('span', {'id': 'spanD'})),
                createDOM('content')),
            createDOM('div', {'id': 'host-child'},
                document.createTextNode('Hello, HostB!'))),
        createDOM('div', {'id': 'divA-child'},
            document.createTextNode('Hello, HostA!'))));

shouldHaveBorderColor('host/spanD', 'rgb(255, 0, 0)');

cleanUp();

debug('Test the case where there are no styles in a contanining treescope.');

sandbox.appendChild(
    createDOM('style', {},
        document.createTextNode('div { border: 1px solid red; }')));
sandbox.appendChild(
    createDOM('div', {'id': 'host'},
        createShadowRoot(
            createDOM('div', {'id': 'target'},
                createShadowRoot(
                    createDOM('style', {},
                        document.createTextNode(':host { border: 1px solid green; }')),
                    createDOM('content', {})),
                createDOM('div', {'id': 'host-child'},
                    document.createTextNode('Hello, Host!'))))));

shouldHaveBorderColor('host/target', 'rgb(0, 128, 0)');

cleanUp();

debug('Test that style sharing is disabled when styles in shadow trees would match shadow hosts.');

sandbox.appendChild(
    createDOM('div', {'id': 'hostA'},
        createShadowRoot(
            createDOM('style', {},
                document.createTextNode(':host { border: 1px solid red; }')),
            createDOM('content', {})),
        createDOM('div', {})));

sandbox.appendChild(
    createDOM('div', {'id': 'hostB'},
        createShadowRoot(
            createDOM('style', {},
                document.createTextNode(':host { border: 1px solid green; }')),
            createDOM('content', {})),
        createDOM('div', {})));

// for checking style sharing
shouldHaveBorderColor('hostA', 'rgb(255, 0, 0)');
shouldHaveBorderColor('hostB', 'rgb(0, 128, 0)');

cleanUp();
</script>
</html>