From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../base/tests/browser_stylesheet_change_events.js | 227 +++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 layout/base/tests/browser_stylesheet_change_events.js (limited to 'layout/base/tests/browser_stylesheet_change_events.js') diff --git a/layout/base/tests/browser_stylesheet_change_events.js b/layout/base/tests/browser_stylesheet_change_events.js new file mode 100644 index 0000000000..c867197050 --- /dev/null +++ b/layout/base/tests/browser_stylesheet_change_events.js @@ -0,0 +1,227 @@ +const gTestRoot = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "http://127.0.0.1:8888/" +); + +add_task(async function test() { + await BrowserTestUtils.withNewTab( + { gBrowser, url: gTestRoot + "file_stylesheet_change_events.html" }, + async function (browser) { + await SpecialPowers.spawn( + browser, + [gTestRoot], + testApplicableStateChangeEvent + ); + } + ); +}); + +// This function runs entirely in the content process. It doesn't have access +// any free variables in this file. +async function testApplicableStateChangeEvent(testRoot) { + // We've seen the original stylesheet in the document. + // Now add a stylesheet on the fly and make sure we see it. + let doc = content.document; + doc.styleSheetChangeEventsEnabled = true; + + const unexpectedContentEvent = event => + ok(false, "Received a " + event.type + " event on content"); + doc.addEventListener( + "StyleSheetApplicableStateChanged", + unexpectedContentEvent + ); + doc.defaultView.addEventListener( + "StyleSheetApplicableStateChanged", + unexpectedContentEvent + ); + doc.addEventListener("StyleSheetRemoved", unexpectedContentEvent); + doc.defaultView.addEventListener("StyleSheetRemoved", unexpectedContentEvent); + + function shouldIgnoreEvent(e) { + // accessiblecaret.css might be reported, interfering with the test + // assertions, so let's ignore it + return ( + e.stylesheet?.href === "resource://content-accessible/accessiblecaret.css" + ); + } + + function waitForStyleApplicableStateChanged() { + return ContentTaskUtils.waitForEvent( + docShell.chromeEventHandler, + "StyleSheetApplicableStateChanged", + true, + e => !shouldIgnoreEvent(e) + ); + } + + function waitForStyleSheetRemovedEvent() { + return ContentTaskUtils.waitForEvent( + docShell.chromeEventHandler, + "StyleSheetRemoved", + true, + e => !shouldIgnoreEvent(e) + ); + } + + function checkApplicableStateChangeEvent(event, { applicable, stylesheet }) { + is( + event.type, + "StyleSheetApplicableStateChanged", + "event.type has expected value" + ); + is(event.target, doc, "event targets correct document"); + is(event.stylesheet, stylesheet, "event.stylesheet has the expected value"); + is(event.applicable, applicable, "event.applicable has the expected value"); + } + + function checkStyleSheetRemovedEvent(event, { stylesheet }) { + is(event.type, "StyleSheetRemoved", "event.type has expected value"); + is(event.target, doc, "event targets correct document"); + is(event.stylesheet, stylesheet, "event.stylesheet has the expected value"); + } + + // Updating the text content will actually create a new StyleSheet instance, + // and so we should get one event for the new instance, and another one for + // the removal of the "previous"one. + function waitForTextContentChange() { + return Promise.all([ + waitForStyleSheetRemovedEvent(), + waitForStyleApplicableStateChanged(), + ]); + } + + let stateChanged, evt; + + { + const gStyleSheet = "stylesheet_change_events.css"; + + info("Add and wait for applicable state change event"); + let linkEl = doc.createElement("link"); + linkEl.setAttribute("rel", "stylesheet"); + linkEl.setAttribute("type", "text/css"); + linkEl.setAttribute("href", testRoot + gStyleSheet); + + stateChanged = waitForStyleApplicableStateChanged(); + doc.body.appendChild(linkEl); + evt = await stateChanged; + + ok(true, "received dynamic style sheet applicable state change event"); + checkApplicableStateChangeEvent(evt, { + stylesheet: linkEl.sheet, + applicable: true, + }); + + stateChanged = waitForStyleApplicableStateChanged(); + linkEl.sheet.disabled = true; + evt = await stateChanged; + + ok(true, "received dynamic style sheet applicable state change event"); + checkApplicableStateChangeEvent(evt, { + stylesheet: linkEl.sheet, + applicable: false, + }); + + info("Remove stylesheet and wait for removed event"); + const removedStylesheet = linkEl.sheet; + const onStyleSheetRemoved = waitForStyleSheetRemovedEvent(); + doc.body.removeChild(linkEl); + const removedStyleSheetEvt = await onStyleSheetRemoved; + + ok(true, "received removed sheet event"); + checkStyleSheetRemovedEvent(removedStyleSheetEvt, { + stylesheet: removedStylesheet, + }); + } + + { + info("Add `; + evt = await stateChanged; + + ok(true, "received dynamic style sheet applicable state change event"); + const shadowStyleEl = shadowRoot.querySelector("style"); + checkApplicableStateChangeEvent(evt, { + stylesheet: shadowStyleEl.sheet, + applicable: true, + }); + + info("Updating