| <!doctype html> |
| <title>StyleSheet and CSSStyleSheet properties</title> |
| <link rel="help" href="https://drafts.csswg.org/cssom/#the-stylesheet-interface"> |
| <link rel="help" href="https://drafts.csswg.org/cssom/#the-cssstylesheet-interface"> |
| <link rel="help" href="https://drafts.csswg.org/cssom/#remove-a-css-style-sheet"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| |
| <style id="plain">div { color: green }</style> |
| <style id="with-title" title="My Sheet">span { color: red }</style> |
| <style id="with-media" media="screen">p { color: blue }</style> |
| <style id="with-import">@import url("/css/support/a-green.css");</style> |
| <link id="link-plain" rel="stylesheet" href="/css/support/a-green.css"> |
| <link id="link-titled" rel="stylesheet" href="/css/support/b-green.css" title="Link Sheet"> |
| <link id="link-media" rel="stylesheet" href="/css/support/c-red.css" media="screen"> |
| |
| <script> |
| "use strict"; |
| |
| // Wait for @import and <link> sheets to load |
| async_test(t => { |
| window.addEventListener("load", t.step_func_done(() => { |
| const plainSheet = document.getElementById("plain").sheet; |
| const titledSheet = document.getElementById("with-title").sheet; |
| const mediaSheet = document.getElementById("with-media").sheet; |
| const importSheet = document.getElementById("with-import").sheet; |
| const linkPlainSheet = document.getElementById("link-plain").sheet; |
| const linkTitledSheet = document.getElementById("link-titled").sheet; |
| const linkMediaSheet = document.getElementById("link-media").sheet; |
| |
| // --- <style> element sheets --- |
| |
| test(() => { |
| assert_equals(plainSheet.type, "text/css"); |
| }, "<style>: type is 'text/css'"); |
| |
| test(() => { |
| assert_equals(plainSheet.ownerNode, document.getElementById("plain")); |
| }, "<style>: ownerNode is the style element"); |
| |
| test(() => { |
| assert_equals(plainSheet.href, null); |
| }, "<style>: href is null for inline sheets"); |
| |
| test(() => { |
| assert_equals(plainSheet.title, null); |
| }, "<style>: title is null when the style element has no title attribute"); |
| |
| test(() => { |
| assert_equals(titledSheet.title, "My Sheet"); |
| }, "<style>: title reflects the style element's title attribute"); |
| |
| test(() => { |
| assert_equals(plainSheet.media.mediaText, ""); |
| assert_equals(plainSheet.media.length, 0); |
| }, "<style>: media is empty when the style element has no media attribute"); |
| |
| test(() => { |
| assert_equals(mediaSheet.media.mediaText, "screen"); |
| assert_equals(mediaSheet.media.length, 1); |
| }, "<style>: media reflects the style element's media attribute"); |
| |
| test(() => { |
| assert_false(plainSheet.disabled); |
| }, "<style>: disabled is false initially"); |
| |
| test(() => { |
| assert_equals(plainSheet.parentStyleSheet, null); |
| }, "<style>: parentStyleSheet is null for top-level sheets"); |
| |
| test(() => { |
| assert_equals(plainSheet.ownerRule, null); |
| }, "<style>: ownerRule is null for non-imported sheets"); |
| |
| test(() => { |
| assert_true(plainSheet.cssRules instanceof CSSRuleList); |
| assert_greater_than(plainSheet.cssRules.length, 0); |
| }, "<style>: cssRules is a CSSRuleList with rules"); |
| |
| // --- <link> element sheets --- |
| |
| test(() => { |
| assert_equals(linkPlainSheet.type, "text/css"); |
| }, "<link>: type is 'text/css'"); |
| |
| test(() => { |
| assert_equals(linkPlainSheet.ownerNode, document.getElementById("link-plain")); |
| }, "<link>: ownerNode is the link element"); |
| |
| test(() => { |
| assert_equals(linkPlainSheet.href, new URL("/css/support/a-green.css", document.baseURI).href); |
| }, "<link>: href is the resolved URL of the stylesheet"); |
| |
| test(() => { |
| assert_equals(linkPlainSheet.title, null); |
| }, "<link>: title is null when the link element has no title attribute"); |
| |
| test(() => { |
| assert_equals(linkTitledSheet.title, "Link Sheet"); |
| }, "<link>: title reflects the link element's title attribute"); |
| |
| test(() => { |
| assert_equals(linkPlainSheet.media.mediaText, ""); |
| assert_equals(linkPlainSheet.media.length, 0); |
| }, "<link>: media is empty when the link element has no media attribute"); |
| |
| test(() => { |
| assert_equals(linkMediaSheet.media.mediaText, "screen"); |
| assert_equals(linkMediaSheet.media.length, 1); |
| }, "<link>: media reflects the link element's media attribute"); |
| |
| test(() => { |
| assert_false(linkPlainSheet.disabled); |
| }, "<link>: disabled is false initially"); |
| |
| test(() => { |
| assert_equals(linkPlainSheet.parentStyleSheet, null); |
| }, "<link>: parentStyleSheet is null for top-level sheets"); |
| |
| test(() => { |
| assert_equals(linkPlainSheet.ownerRule, null); |
| }, "<link>: ownerRule is null for non-imported sheets"); |
| |
| test(() => { |
| assert_true(linkPlainSheet.cssRules instanceof CSSRuleList); |
| assert_greater_than(linkPlainSheet.cssRules.length, 0); |
| }, "<link>: cssRules is a CSSRuleList with rules"); |
| |
| // --- @import sheets --- |
| |
| test(() => { |
| const importRule = importSheet.cssRules[0]; |
| assert_equals(importRule.constructor.name, "CSSImportRule", "setup: should be an import rule"); |
| const imported = importRule.styleSheet; |
| assert_equals(imported.type, "text/css"); |
| }, "@import: imported sheet type is 'text/css'"); |
| |
| test(() => { |
| const imported = importSheet.cssRules[0].styleSheet; |
| assert_equals(imported.ownerNode, null); |
| }, "@import: imported sheet ownerNode is null"); |
| |
| test(() => { |
| const imported = importSheet.cssRules[0].styleSheet; |
| assert_equals(imported.href, new URL("/css/support/a-green.css", document.baseURI).href); |
| }, "@import: imported sheet href is the resolved URL"); |
| |
| test(() => { |
| const imported = importSheet.cssRules[0].styleSheet; |
| assert_equals(imported.title, null); |
| }, "@import: imported sheet title is null"); |
| |
| test(() => { |
| const imported = importSheet.cssRules[0].styleSheet; |
| assert_equals(imported.media.mediaText, ""); |
| assert_equals(imported.media.length, 0); |
| }, "@import: imported sheet media is empty when @import has no media query"); |
| |
| test(() => { |
| const imported = importSheet.cssRules[0].styleSheet; |
| assert_false(imported.disabled); |
| }, "@import: imported sheet disabled is false initially"); |
| |
| test(() => { |
| const imported = importSheet.cssRules[0].styleSheet; |
| assert_equals(imported.parentStyleSheet, importSheet); |
| }, "@import: imported sheet parentStyleSheet is the importing sheet"); |
| |
| test(() => { |
| const importRule = importSheet.cssRules[0]; |
| const imported = importRule.styleSheet; |
| assert_equals(imported.ownerRule, importRule); |
| }, "@import: imported sheet ownerRule is the CSSImportRule"); |
| |
| test(() => { |
| const imported = importSheet.cssRules[0].styleSheet; |
| assert_true(imported.cssRules instanceof CSSRuleList); |
| assert_greater_than(imported.cssRules.length, 0); |
| }, "@import: imported sheet cssRules is a CSSRuleList with rules"); |
| |
| // --- Removal --- |
| |
| test(() => { |
| const style = document.createElement("style"); |
| style.textContent = "div { color: green }"; |
| document.head.appendChild(style); |
| const { sheet } = style; |
| assert_equals(sheet.ownerNode, style); |
| |
| style.remove(); |
| |
| assert_equals(sheet.ownerNode, null, "ownerNode becomes null after removal"); |
| assert_equals(sheet.parentStyleSheet, null, "parentStyleSheet is null after removal"); |
| assert_equals(sheet.ownerRule, null, "ownerRule is null after removal"); |
| }, "Removing a <style> element nulls ownerNode, parentStyleSheet, and ownerRule"); |
| |
| test(() => { |
| const link = document.getElementById("link-plain"); |
| const { sheet } = link; |
| assert_equals(sheet.ownerNode, link); |
| |
| link.remove(); |
| |
| assert_equals(sheet.ownerNode, null, "ownerNode becomes null after removal"); |
| assert_equals(sheet.parentStyleSheet, null, "parentStyleSheet is null after removal"); |
| assert_equals(sheet.ownerRule, null, "ownerRule is null after removal"); |
| }, "Removing a <link> element nulls ownerNode, parentStyleSheet, and ownerRule"); |
| |
| // --- Programmatic title --- |
| |
| test(() => { |
| const style = document.createElement("style"); |
| style.title = "Dynamic Title"; |
| document.head.appendChild(style); |
| assert_equals(style.sheet.title, "Dynamic Title"); |
| style.remove(); |
| }, "Programmatically setting title on a <style> element is reflected in sheet.title"); |
| })); |
| }, "StyleSheet and CSSStyleSheet properties"); |
| </script> |