<!DOCTYPE html>
<html>
<body>
<p>Test passes if you see a single 200px by 200px green box below.</p>
<div id="container" style="width: 200px; height: 200px; background: green;"></div>
<script>

function style(pseudoClasses) {
    return `<style>
    .match, .not-match { display: block; float: left; width: 100px; height: 15px; color: green; font-size: 12px; overflow: hidden; }
    .match { background: red; }
    .not-match { background: green; }
    .match${pseudoClasses} { background: green; }
    .not-match${pseudoClasses} { background: red; }
</style>`;
}

function test(markup, action) {
    const host = document.createElement('div');
    const shadowRoot = host.attachShadow({mode: 'closed'});
    document.getElementById('container').appendChild(host);
    shadowRoot.innerHTML = markup;
    return () => action(shadowRoot);
}

const tests = [
    test(`<old-first></old-first><new-first class="match">newly first ${style(':first-child')}</new-first>`,
        shadowRoot => shadowRoot.querySelector('old-first').remove()),
    test(`<old-first class="not-match">old first ${style(':first-child')}</old-first>`,
        shadowRoot => shadowRoot.prepend(document.createElement('div'))),

    test(`<new-last class="match">newly last ${style(':last-child')}</new-last><old-last></old-last>`,
        shadowRoot => shadowRoot.querySelector('old-last').remove()),
    test(`<old-last class="not-match">old last ${style(':last-child')}</old-last>`,
        shadowRoot => shadowRoot.append(document.createElement('div'))),

    test(`<div></div><div class="match">only child 1 ${style(':only-child')}</div>`,
        shadowRoot => shadowRoot.firstChild.remove()),
    test(`<div class="match">only child 2 ${style(':only-child')}</div><div></div>`,
        shadowRoot => shadowRoot.lastChild.remove()),
    test(`<div class="not-match">only child 3 ${style(':only-child')}</div>`,
        shadowRoot => shadowRoot.prepend(document.createElement('div'))),
    test(`<div class="not-match">only child 4 ${style(':only-child')}</div>`,
        shadowRoot => shadowRoot.append(document.createElement('div'))),

    test(`<div></div><div class="match">1st child ${style(':nth-child(1)')}</div>`,
        shadowRoot => shadowRoot.firstChild.remove()),
    test(`<div></div><div class="not-match">2nd child ${style(':nth-child(2)')}</div>`,
        shadowRoot => shadowRoot.prepend(document.createElement('div'))),

    test(`<div class="match">3rd last child ${style(':nth-last-child(3)')}</div><div></div><div></div><div></div>`,
        shadowRoot => shadowRoot.lastChild.remove()),
    test(`<div></div><div class="not-match">4th last child ${style(':nth-last-child(4)')}</div><div></div><div></div><div></div>`,
        shadowRoot => shadowRoot.append(document.createElement('div'))),

    test(`<new-first></new-first><div></div><new-first class="match">first type 1 ${style(':first-of-type')}</new-first>`,
        shadowRoot => shadowRoot.querySelector('new-first').remove()),
    test(`<div></div><old-first class="not-match">first type 2 ${style(':first-of-type')}</old-first>`,
        shadowRoot => shadowRoot.prepend(document.createElement('old-first'))),

    test(`<new-last class="match">last of type 1 ${style(':last-of-type')}</new-last><div></div><new-last></new-last>`,
        shadowRoot => shadowRoot.lastChild.remove()),
    test(`<old-last class="not-match">last of type 2 ${style(':last-of-type')}</old-last><div></div>`,
        shadowRoot => shadowRoot.append(document.createElement('old-last'))),

    test(`<div></div><section></section><div class="match">only of type 1 ${style(':only-of-type')}</div>`,
        shadowRoot => shadowRoot.firstChild.remove()),
    test(`<section></section><div class="match">only of type 2 ${style(':only-of-type')}</div><div></div>`,
        shadowRoot => shadowRoot.lastChild.remove()),
    test(`<a-b></a-b><div class="not-match">only of type 3 ${style(':only-of-type')}</div><section></section>`,
        shadowRoot => shadowRoot.insertBefore(document.createElement('div'), shadowRoot.childNodes[2])),
    test(`<div class="not-match">only of type 4 ${style(':only-of-type')}</div><c-d></c-d>`,
        shadowRoot => shadowRoot.append(document.createElement('div'))),

    test(`<div></div><section></section><div class="match">1st of type ${style(':nth-of-type(1)')}</div>`,
        shadowRoot => shadowRoot.firstChild.remove()),
    test(`<div></div><section></section><div class="not-match">2nd of type ${style(':nth-of-type(2)')}</div>`,
        shadowRoot => shadowRoot.prepend(document.createElement('div'))),

    test(`<div class="match">3rd last of type ${style(':nth-last-of-type(3)')}</div><div></div><div></div><section></section><div></div>`,
        shadowRoot => shadowRoot.querySelector('section').previousSibling.remove()),
    test(`<div></div><div class="not-match">4th last of type ${style(':nth-last-of-type(4)')}</div><div></div><div></div><section></section><div></div>`,
        shadowRoot => shadowRoot.append(document.createElement('div'))),

    test(`<div></div><div class="match">1st, 3rd last of type ${style(':first-child:nth-last-of-type(3)')}</div><div></div><div></div><section></section><div></div>`,
        shadowRoot => { shadowRoot.querySelector('section').previousSibling.remove(); shadowRoot.firstChild.remove(); }),

    test(`<div></div><div class="match">2nd, 2rd last of type ${style(':nth-child(3):nth-of-type(2)')}</div>`,
        shadowRoot => { shadowRoot.prepend(document.createElement('a-b')); shadowRoot.append(document.createElement('div')); }),
];

if (window.internals)
    internals.updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks();
else
    window.rect = document.body.getBoundingClientRect();

for (const test of tests)
    test();

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