<!DOCTYPE html>
<title>The CSSOM API for Cascade Layers</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layer-apis">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const testCases = [
  {
    style: `@layer foo { }`,
    expectedNames: ['foo'],
    title: 'Basic layer block name',
  },
  {
    style: `@layer { }`,
    expectedNames: [''],
    title: 'Anonymous layer block name',
  },
  {
    style: `
      @layer foo;
    `,
    expectedNames: [['foo']],
    title: 'Basic layer statement name',
  },
  {
    style: `
      @layer foo, bar;
    `,
    expectedNames: [['foo', 'bar']],
    title: 'Layer statement with multiple names',
  },
  {
    style: `
      @layer outer {
        @layer foo.bar { }
      }
      @layer outer.foo.bar { }
    `,
    expectedNames: ['outer', 'foo.bar', 'outer.foo.bar'],
    title: 'Nested layer block names',
  },
  {
    style: `
      @layer outer {
        @layer foo.bar, baz;
      }
      @layer outer.foo.bar, outer.baz;
    `,
    expectedNames: ['outer', ['foo.bar', 'baz'], ['outer.foo.bar', 'outer.baz']],
    title: 'Nested layer statement name lists',
  },
  {
    style: `
      @import url('data:text/css,') layer;
    `,
    expectedNames: [''],
    title: 'Import into anonymous layer',
  },
  {
    style: `
      @import url('data:text/css,') layer(foo);
    `,
    expectedNames: ['foo'],
    title: 'Import into named layer',
  },
  {
    style: `
      @import url('data:text/css,');
    `,
    expectedNames: [null],
    title: 'Import without layer',
  },
];

for (let testCase of testCases) {
  promise_test(async function (t) {
    assert_implements(window.CSSLayerBlockRule);
    assert_implements(window.CSSLayerStatementRule);

    const style = document.createElement('style');
    t.add_cleanup(() => style.remove());

    const isLoadAsync = testCase.style.includes("@import");
    const load = new Promise(resolve => {
      style.addEventListener("load", resolve, { once: true });
    });

    style.appendChild(document.createTextNode(testCase.style));
    document.head.appendChild(style);

    if (isLoadAsync) {
      await load;
    }

    let index = 0;
    function compareNames(ruleOrSheet) {
      if (ruleOrSheet instanceof CSSLayerBlockRule)
        assert_equals(ruleOrSheet.name, testCase.expectedNames[index++]);
      else if (ruleOrSheet instanceof CSSImportRule)
        assert_equals(ruleOrSheet.layerName, testCase.expectedNames[index++]);
      else if (ruleOrSheet instanceof CSSLayerStatementRule)
        assert_array_equals(ruleOrSheet.nameList, testCase.expectedNames[index++]);
      if (ruleOrSheet.cssRules) {
        for (let i = 0; i < ruleOrSheet.cssRules.length; ++i)
          compareNames(ruleOrSheet.cssRules.item(i));
      }
    }
    compareNames(style.sheet);
    assert_equals(index, testCase.expectedNames.length);
  }, testCase.title);
}
</script>
