| <!DOCTYPE html> |
| <title>CSS Cascade Layers: Empty layer statements before import rules</title> |
| <link rel="author" href="mailto:xiaochengh@chromium.org"> |
| <link rel="help" href="https://www.w3.org/TR/css-cascade-5/#layering"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| |
| <div id="target"></div> |
| <div id="reference" style="color: green"></div> |
| |
| <script> |
| // In all test cases, the 'color' property value of #target should be green. |
| |
| const testCases = [ |
| { |
| title: 'length and item', |
| style: ` |
| @layer first, second; |
| @import url(data:text/css,); |
| @layer second { |
| #target { color: green; } |
| } |
| @layer first { |
| #target { color: red; } |
| } |
| `, |
| operations: function(sheet) { |
| assert_equals(sheet.cssRules.length, 4); |
| assert_equals(sheet.cssRules.item(0).cssText, '@layer first, second;'); |
| assert_equals(sheet.cssRules.item(1).cssText, `@import url("data:text/css,");`); |
| assert_equals(sheet.cssRules.item(2).cssText, |
| '@layer second {\n #target { color: green; }\n}'); |
| assert_equals(sheet.cssRules.item(3).cssText, |
| '@layer first {\n #target { color: red; }\n}'); |
| } |
| }, |
| { |
| title: 'insertRule before imports', |
| style: ` |
| @import url(data:text/css,); |
| @layer second { |
| #target { color: green; } |
| } |
| @layer first { |
| #target { color: red; } |
| } |
| `, |
| operations: function(sheet) { |
| sheet.insertRule('@layer first, second', 0); |
| } |
| }, |
| { |
| title: 'insertRule after imports', |
| style: ` |
| @layer first, second; |
| @import url(data:text/css,); |
| @layer first { |
| #target { color: red; } |
| } |
| `, |
| operations: function(sheet) { |
| sheet.insertRule('@layer second { #target { color: green; } }', 2); |
| } |
| }, |
| { |
| title: 'insert other rules to pre-import layer statements fails', |
| style: ` |
| @layer first, second; |
| @import url(data:text/css,); |
| @layer second { |
| #target { color: green; } |
| } |
| @layer first { |
| #target { color: red; } |
| } |
| `, |
| operations: function(sheet) { |
| assert_throws_dom('HierarchyRequestError', |
| () => sheet.insertRule('#target { color: red !important; }', 0)); |
| assert_throws_dom('HierarchyRequestError', |
| () => sheet.insertRule('#target { color: red !important; }', 1)); |
| } |
| }, |
| { |
| title: 'insert other rules before the first layer statement without imports', |
| style: ` |
| @layer first, second; |
| @layer second { |
| #target { color: red !important; } |
| } |
| `, |
| operations: function(sheet) { |
| sheet.insertRule(`@layer first { |
| #target { color: green !important; } |
| }`, 0); |
| } |
| }, |
| { |
| title: 'deleteRule before imports', |
| style: ` |
| @layer second, first; |
| @import url(data:text/css,); |
| @layer first { |
| #target { color: red; } |
| } |
| @layer second { |
| #target { color: green; } |
| } |
| `, |
| operations: function(sheet) { |
| sheet.deleteRule(0); |
| } |
| }, |
| { |
| title: 'deleteRule after imports', |
| style: ` |
| @layer first, second; |
| @import url(data:text/css,); |
| @layer second { |
| #target { color: green; } |
| } |
| @layer first { |
| #target { color: red; } |
| } |
| #target { |
| color: red; |
| } |
| `, |
| operations: function(sheet) { |
| sheet.deleteRule(4); |
| } |
| }, |
| { |
| title: 'replaceSync clears stale layer statements', |
| style: ` |
| @layer second, first; |
| @layer second { |
| #target { color: green; } |
| } |
| @layer first { |
| #target { color: red; } |
| } |
| `, |
| operations: function(sheet) { |
| sheet.replaceSync(` |
| @layer first { |
| #target { color: red; } |
| } |
| @layer second { |
| #target { color: green; } |
| } |
| `); |
| }, |
| constructedStyleSheet: true |
| } |
| ]; |
| |
| const target = document.getElementById('target'); |
| const reference = document.getElementById('reference'); |
| |
| for (let testCase of testCases) { |
| promise_test(async t => { |
| let styleElement; |
| let sheet; |
| if (!testCase.constructedStyleSheet) { |
| styleElement = document.createElement('style'); |
| styleElement.textContent = testCase.style; |
| await new Promise(resolve => { |
| styleElement.onload = resolve; |
| styleElement.onerror = resolve; |
| document.head.append(styleElement); |
| }); |
| sheet = styleElement.sheet; |
| } else { |
| sheet = new CSSStyleSheet(); |
| sheet.replaceSync(testCase.style); |
| document.adoptedStyleSheets = [sheet]; |
| } |
| |
| try { |
| testCase.operations(sheet); |
| assert_equals(getComputedStyle(target).color, getComputedStyle(reference).color); |
| } finally { |
| if (styleElement) |
| styleElement.remove(); |
| document.adoptedStyleSheets = []; |
| } |
| }, testCase.title); |
| } |
| </script> |