summaryrefslogtreecommitdiffstats
path: root/devtools/client/inspector/rules/test/browser_rules_selector_warnings.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/client/inspector/rules/test/browser_rules_selector_warnings.js154
1 files changed, 154 insertions, 0 deletions
diff --git a/devtools/client/inspector/rules/test/browser_rules_selector_warnings.js b/devtools/client/inspector/rules/test/browser_rules_selector_warnings.js
new file mode 100644
index 0000000000..1e5c7da302
--- /dev/null
+++ b/devtools/client/inspector/rules/test/browser_rules_selector_warnings.js
@@ -0,0 +1,154 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that selector warnings are displayed in the rule-view.
+const TEST_URI = `
+ <!DOCTYPE html>
+ <style>
+ main, :has(form) {
+ /* /!\ space between & and : is important */
+ & :has(input),
+ & :has(select),
+ &:has(button) {
+ background: gold;
+ }
+ }
+ </style>
+ <body>
+ <main>
+ <form>
+ <input>
+ </form>
+ </main>
+ </body>`;
+
+const UNCONSTRAINED_HAS_WARNING_MESSAGE =
+ "This selector uses unconstrained :has(), which can be slow";
+
+add_task(async function () {
+ await addTab(
+ "https://example.com/document-builder.sjs?html=" +
+ encodeURIComponent(TEST_URI)
+ );
+ const { inspector, view } = await openRuleView();
+
+ await selectNode("main", inspector);
+ const { ancestorDataEl, selectorText } = getRuleViewRuleEditor(view, 1);
+
+ info(
+ "Check that unconstrained :has() warnings are displayed for the rules selectors"
+ );
+ const ruleSelectors = Array.from(
+ selectorText.querySelectorAll(".ruleview-selector")
+ );
+
+ await assertSelectorWarnings({
+ view,
+ selectorEl: ruleSelectors[0],
+ selectorText: "& :has(input)",
+ expectedWarnings: [UNCONSTRAINED_HAS_WARNING_MESSAGE],
+ });
+ await assertSelectorWarnings({
+ view,
+ selectorEl: ruleSelectors[1],
+ selectorText: "& :has(select)",
+ expectedWarnings: [UNCONSTRAINED_HAS_WARNING_MESSAGE],
+ });
+ // Warning is not displayed when the selector does not have warnings
+ await assertSelectorWarnings({
+ view,
+ selectorEl: ruleSelectors[2],
+ selectorText: "&:has(button)",
+ expectedWarnings: [],
+ });
+
+ info(
+ "Check that unconstrained :has() warnings are displayed for the parent rules selectors"
+ );
+ const parentRuleSelectors = Array.from(
+ ancestorDataEl.querySelectorAll(".ruleview-selector")
+ );
+ await assertSelectorWarnings({
+ view,
+ selectorEl: parentRuleSelectors[0],
+ selectorText: "main",
+ expectedWarnings: [],
+ });
+ await assertSelectorWarnings({
+ view,
+ selectorEl: parentRuleSelectors[1],
+ selectorText: ":has(form)",
+ expectedWarnings: [UNCONSTRAINED_HAS_WARNING_MESSAGE],
+ });
+});
+
+async function assertSelectorWarnings({
+ view,
+ selectorEl,
+ selectorText,
+ expectedWarnings,
+}) {
+ is(
+ selectorEl.textContent,
+ selectorText,
+ "Passed selector element is the expected one"
+ );
+
+ const selectorWarningsContainerEl = selectorEl.querySelector(
+ ".ruleview-selector-warnings"
+ );
+
+ if (expectedWarnings.length === 0) {
+ Assert.strictEqual(
+ selectorWarningsContainerEl,
+ null,
+ `"${selectorText}" does not have warnings`
+ );
+ return;
+ }
+
+ Assert.notStrictEqual(
+ selectorWarningsContainerEl,
+ null,
+ `"${selectorText}" does have warnings`
+ );
+
+ is(
+ selectorWarningsContainerEl
+ .getAttribute("data-selector-warning-kind")
+ ?.split(",")?.length || 0,
+ expectedWarnings.length,
+ `"${selectorText}" has expected number of warnings`
+ );
+
+ // Ensure that the element can be targetted from EventUtils.
+ selectorWarningsContainerEl.scrollIntoView();
+
+ const tooltip = view.tooltips.getTooltip("interactiveTooltip");
+ const onTooltipReady = tooltip.once("shown");
+ EventUtils.synthesizeMouseAtCenter(
+ selectorWarningsContainerEl,
+ { type: "mousemove" },
+ selectorWarningsContainerEl.ownerDocument.defaultView
+ );
+ await onTooltipReady;
+
+ const lis = Array.from(tooltip.panel.querySelectorAll("li")).map(
+ li => li.textContent
+ );
+ Assert.deepEqual(lis, expectedWarnings, "Tooltip has expected items");
+
+ info("Hide the tooltip");
+ const onHidden = tooltip.once("hidden");
+ // Move the mouse elsewhere to hide the tooltip
+ EventUtils.synthesizeMouse(
+ selectorWarningsContainerEl.ownerDocument.body,
+ 1,
+ 1,
+ { type: "mousemove" },
+ selectorWarningsContainerEl.ownerDocument.defaultView
+ );
+ await onHidden;
+}