diff options
Diffstat (limited to 'devtools/shared/commands/resource/tests/browser_resources_css_registered_properties.js')
-rw-r--r-- | devtools/shared/commands/resource/tests/browser_resources_css_registered_properties.js | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/devtools/shared/commands/resource/tests/browser_resources_css_registered_properties.js b/devtools/shared/commands/resource/tests/browser_resources_css_registered_properties.js new file mode 100644 index 0000000000..1429b55167 --- /dev/null +++ b/devtools/shared/commands/resource/tests/browser_resources_css_registered_properties.js @@ -0,0 +1,384 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test the ResourceCommand API around CSS_REGISTERED_PROPERTIES. + +const ResourceCommand = require("resource://devtools/shared/commands/resource/resource-command.js"); + +const IFRAME_URL = `https://example.org/document-builder.sjs?html=${encodeURIComponent(` + <style> + @property --css-a { + syntax: "<color>"; + inherits: true; + initial-value: gold; + } + </style> + <script> + CSS.registerProperty({ + name: "--js-a", + syntax: "<length>", + inherits: true, + initialValue: "20px" + }); + </script> + <h1>iframe</h1> +`)}`; + +const TEST_URL = `https://example.org/document-builder.sjs?html= + <head> + <style> + @property --css-a { + syntax: "*"; + inherits: false; + } + + @property --css-b { + syntax: "<color>"; + inherits: true; + initial-value: tomato; + } + </style> + <script> + CSS.registerProperty({ + name: "--js-a", + syntax: "*", + inherits: false, + }); + CSS.registerProperty({ + name: "--js-b", + syntax: "<length>", + inherits: true, + initialValue: "10px" + }); + </script> + </head> + <h1>CSS_REGISTERED_PROPERTIES</h1> + <iframe src="${encodeURIComponent(IFRAME_URL)}"></iframe>`; + +add_task(async function () { + await pushPref("layout.css.properties-and-values.enabled", true); + const tab = await addTab(TEST_URL); + + const { client, resourceCommand, targetCommand } = await initResourceCommand( + tab + ); + + // Wait for targets + await targetCommand.startListening(); + const targets = []; + const onAvailable = ({ targetFront }) => targets.push(targetFront); + await targetCommand.watchTargets({ + types: [targetCommand.TYPES.FRAME], + onAvailable, + }); + await waitFor(() => targets.length === 2); + const [topLevelTarget, iframeTarget] = targets.sort((a, b) => + a.isTopLevel ? -1 : 1 + ); + + // Watching for new stylesheets shouldn't be + const stylesheets = []; + await resourceCommand.watchResources([resourceCommand.TYPES.STYLESHEET], { + onAvailable: resources => stylesheets.push(...resources), + ignoreExistingResources: true, + }); + + info("Check that we get existing registered properties"); + const availableResources = []; + const updatedResources = []; + const destroyedResources = []; + await resourceCommand.watchResources( + [resourceCommand.TYPES.CSS_REGISTERED_PROPERTIES], + { + onAvailable: resources => availableResources.push(...resources), + onUpdated: resources => updatedResources.push(...resources), + onDestroyed: resources => destroyedResources.push(...resources), + } + ); + + is( + availableResources.length, + 6, + "The 6 existing registered properties where retrieved" + ); + + // Sort resources so we get them alphabetically ordered by their name, with the ones for + // the top level target displayed first. + availableResources.sort((a, b) => { + if (a.targetFront !== b.targetFront) { + return a.targetFront.isTopLevel ? -1 : 1; + } + return a.name < b.name ? -1 : 1; + }); + + assertResource(availableResources[0], { + name: "--css-a", + syntax: "*", + inherits: false, + initialValue: null, + fromJS: false, + targetFront: topLevelTarget, + }); + assertResource(availableResources[1], { + name: "--css-b", + syntax: "<color>", + inherits: true, + initialValue: "tomato", + fromJS: false, + targetFront: topLevelTarget, + }); + assertResource(availableResources[2], { + name: "--js-a", + syntax: "*", + inherits: false, + initialValue: null, + fromJS: true, + targetFront: topLevelTarget, + }); + assertResource(availableResources[3], { + name: "--js-b", + syntax: "<length>", + inherits: true, + initialValue: "10px", + fromJS: true, + targetFront: topLevelTarget, + }); + assertResource(availableResources[4], { + name: "--css-a", + syntax: "<color>", + inherits: true, + initialValue: "gold", + fromJS: false, + targetFront: iframeTarget, + }); + assertResource(availableResources[5], { + name: "--js-a", + syntax: "<length>", + inherits: true, + initialValue: "20px", + fromJS: true, + targetFront: iframeTarget, + }); + + info("Check that we didn't get notified about existing stylesheets"); + // wait a bit so we'd have the time to be notified about stylesheet resources + await wait(500); + is( + stylesheets.length, + 0, + "Watching for registered properties does not notify about existing stylesheets resources" + ); + + info("Check that we get properties from new stylesheets"); + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + const s = content.document.createElement("style"); + s.textContent = ` + @property --css-c { + syntax: "<custom-ident>"; + inherits: true; + initial-value: custom; + } + + @property --css-d { + syntax: "big | bigger"; + inherits: true; + initial-value: big; + } + `; + content.document.head.append(s); + }); + + info("Wait for registered properties to be available"); + await waitFor(() => availableResources.length === 8); + ok(true, "Got notified about 2 new registered properties"); + assertResource(availableResources[6], { + name: "--css-c", + syntax: "<custom-ident>", + inherits: true, + initialValue: "custom", + fromJS: false, + targetFront: topLevelTarget, + }); + assertResource(availableResources[7], { + name: "--css-d", + syntax: "big | bigger", + inherits: true, + initialValue: "big", + fromJS: false, + targetFront: topLevelTarget, + }); + + info("Wait to be notified about the new stylesheet"); + await waitFor(() => stylesheets.length === 1); + ok(true, "we do get notified about stylesheets"); + + info( + "Check that we get notified about properties registered via CSS.registerProperty" + ); + await SpecialPowers.spawn(tab.linkedBrowser, [], () => { + content.CSS.registerProperty({ + name: "--js-c", + syntax: "*", + inherits: false, + initialValue: 42, + }); + content.CSS.registerProperty({ + name: "--js-d", + syntax: "<color>#", + inherits: true, + initialValue: "blue,cyan", + }); + }); + + await waitFor(() => availableResources.length === 10); + ok(true, "Got notified about 2 new registered properties"); + assertResource(availableResources[8], { + name: "--js-c", + syntax: "*", + inherits: false, + initialValue: "42", + fromJS: true, + targetFront: topLevelTarget, + }); + assertResource(availableResources[9], { + name: "--js-d", + syntax: "<color>#", + inherits: true, + initialValue: "blue,cyan", + fromJS: true, + targetFront: topLevelTarget, + }); + + info( + "Check that we get notified about properties registered via CSS.registerProperty in iframe" + ); + const iframeBrowsingContext = await SpecialPowers.spawn( + tab.linkedBrowser, + [], + () => content.document.querySelector("iframe").browsingContext + ); + + await SpecialPowers.spawn(iframeBrowsingContext, [], () => { + content.CSS.registerProperty({ + name: "--js-iframe", + syntax: "<color>#", + inherits: true, + initialValue: "red,salmon", + }); + }); + + await waitFor(() => availableResources.length === 11); + ok(true, "Got notified about 2 new registered properties"); + assertResource(availableResources[10], { + name: "--js-iframe", + syntax: "<color>#", + inherits: true, + initialValue: "red,salmon", + fromJS: true, + targetFront: iframeTarget, + }); + + info( + "Check that we get notified about destroyed properties when removing stylesheet" + ); + // sanity check + is(destroyedResources.length, 0, "No destroyed resources yet"); + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + content.document.querySelector("style").remove(); + }); + await waitFor(() => destroyedResources.length == 2); + ok(true, "We got notified about destroyed resources"); + destroyedResources.sort((a, b) => a < b); + is( + destroyedResources[0].resourceType, + ResourceCommand.TYPES.CSS_REGISTERED_PROPERTIES, + "resource type is correct" + ); + is( + destroyedResources[0].resourceId, + `${topLevelTarget.actorID}:css-registered-property:--css-a`, + "expected css property was destroyed" + ); + is( + destroyedResources[1].resourceType, + ResourceCommand.TYPES.CSS_REGISTERED_PROPERTIES, + "resource type is correct" + ); + is( + destroyedResources[1].resourceId, + `${topLevelTarget.actorID}:css-registered-property:--css-b`, + "expected css property was destroyed" + ); + + info( + "Check that we get notified about updated properties when modifying stylesheet" + ); + is(updatedResources.length, 0, "No updated resources yet"); + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + content.document.querySelector("style").textContent = ` + /* not updated */ + @property --css-c { + syntax: "<custom-ident>"; + inherits: true; + initial-value: custom; + } + + @property --css-d { + syntax: "big | bigger"; + inherits: true; + /* only change initial value (was big) */ + initial-value: bigger; + } + + /* add a new property */ + @property --css-e { + syntax: "<color>"; + inherits: false; + initial-value: green; + } + `; + }); + await waitFor(() => updatedResources.length === 1); + ok(true, "One property was updated"); + assertResource(updatedResources[0].resource, { + name: "--css-d", + syntax: "big | bigger", + inherits: true, + initialValue: "bigger", + fromJS: false, + targetFront: topLevelTarget, + }); + + await waitFor(() => availableResources.length === 12); + ok(true, "We got notified about the new property"); + assertResource(availableResources.at(-1), { + name: "--css-e", + syntax: "<color>", + inherits: false, + initialValue: "green", + fromJS: false, + targetFront: topLevelTarget, + }); + + await client.close(); +}); + +async function assertResource(resource, expected) { + is( + resource.resourceType, + ResourceCommand.TYPES.CSS_REGISTERED_PROPERTIES, + "Resource type is correct" + ); + is(resource.name, expected.name, "name is correct"); + is(resource.syntax, expected.syntax, "syntax is correct"); + is(resource.inherits, expected.inherits, "inherits is correct"); + is(resource.initialValue, expected.initialValue, "initialValue is correct"); + is(resource.fromJS, expected.fromJS, "fromJS is correct"); + is( + resource.targetFront, + expected.targetFront, + "resource is associated with expected target" + ); +} |