summaryrefslogtreecommitdiffstats
path: root/devtools/client/styleeditor/test/browser_styleeditor_at_rules_sidebar.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/styleeditor/test/browser_styleeditor_at_rules_sidebar.js')
-rw-r--r--devtools/client/styleeditor/test/browser_styleeditor_at_rules_sidebar.js340
1 files changed, 340 insertions, 0 deletions
diff --git a/devtools/client/styleeditor/test/browser_styleeditor_at_rules_sidebar.js b/devtools/client/styleeditor/test/browser_styleeditor_at_rules_sidebar.js
new file mode 100644
index 0000000000..a0a9bc93fd
--- /dev/null
+++ b/devtools/client/styleeditor/test/browser_styleeditor_at_rules_sidebar.js
@@ -0,0 +1,340 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// https rather than chrome to improve coverage
+const TESTCASE_URI = TEST_BASE_HTTPS + "media-rules.html";
+const SIDEBAR_PREF = "devtools.styleeditor.showAtRulesSidebar";
+
+const RESIZE_W = 300;
+const RESIZE_H = 450;
+const LABELS = [
+ "not all",
+ "all",
+ "(max-width: 550px)",
+ "(min-height: 300px) and (max-height: 320px)",
+ "(max-width: 750px)",
+ "",
+ "print",
+];
+const LINE_NOS = [1, 7, 19, 25, 31, 34, 39];
+const NEW_RULE = `
+ @media (max-width: 750px) {
+ div {
+ color: blue;
+ @layer {
+ border-color: tomato;
+ }
+ }
+
+ @media print {
+ body {
+ filter: grayscale(100%);
+ }
+ }
+ }`;
+
+waitForExplicitFinish();
+
+add_task(async function () {
+ await pushPref("layout.css.container-queries.enabled", true);
+
+ const { ui } = await openStyleEditorForURL(TESTCASE_URI);
+
+ is(ui.editors.length, 4, "correct number of editors");
+
+ info("Test first plain css editor");
+ const plainEditor = ui.editors[0];
+ await openEditor(plainEditor);
+ testPlainEditor(plainEditor);
+
+ info("Test editor for inline sheet with @media rules");
+ const inlineMediaEditor = ui.editors[3];
+ await openEditor(inlineMediaEditor);
+ await testInlineMediaEditor(ui, inlineMediaEditor);
+
+ info("Test editor with @media rules");
+ const mediaEditor = ui.editors[1];
+ await openEditor(mediaEditor);
+ await testMediaEditor(ui, mediaEditor);
+
+ info("Test that sidebar hides when flipping pref");
+ await testShowHide(ui, mediaEditor);
+
+ info("Test adding a rule updates the list");
+ await testMediaRuleAdded(ui, mediaEditor);
+
+ info("Test resizing and seeing @media matching state change");
+ const originalWidth = window.outerWidth;
+ const originalHeight = window.outerHeight;
+
+ const onMatchesChange = ui.once("at-rules-list-changed");
+ window.resizeTo(RESIZE_W, RESIZE_H);
+ await onMatchesChange;
+
+ testMediaMatchChanged(mediaEditor);
+
+ window.resizeTo(originalWidth, originalHeight);
+});
+
+function testPlainEditor(editor) {
+ const sidebar = editor.details.querySelector(".stylesheet-sidebar");
+ is(sidebar.hidden, true, "sidebar is hidden on editor without @media");
+}
+
+async function testInlineMediaEditor(ui, editor) {
+ const sidebar = editor.details.querySelector(".stylesheet-sidebar");
+ is(sidebar.hidden, false, "sidebar is showing on editor with @media");
+
+ const entries = sidebar.querySelectorAll(".at-rule-label");
+ is(entries.length, 6, "6 @media rules displayed in sidebar");
+
+ await testRule({
+ ui,
+ editor,
+ rule: entries[0],
+ conditionText: "screen",
+ matches: true,
+ line: 2,
+ type: "media",
+ });
+
+ await testRule({
+ ui,
+ editor,
+ rule: entries[1],
+ conditionText: "(display: flex)",
+ line: 7,
+ type: "support",
+ });
+
+ await testRule({
+ ui,
+ editor,
+ rule: entries[2],
+ conditionText: "(1px < height < 10000px)",
+ matches: true,
+ line: 8,
+ type: "media",
+ });
+
+ await testRule({
+ ui,
+ editor,
+ rule: entries[3],
+ conditionText: "",
+ line: 16,
+ type: "layer",
+ layerName: "myLayer",
+ });
+
+ await testRule({
+ ui,
+ editor,
+ rule: entries[4],
+ conditionText: "(min-width: 1px)",
+ line: 17,
+ type: "container",
+ });
+
+ await testRule({
+ ui,
+ editor,
+ rule: entries[5],
+ conditionText: "selector(&)",
+ line: 21,
+ type: "support",
+ });
+}
+
+async function testMediaEditor(ui, editor) {
+ const sidebar = editor.details.querySelector(".stylesheet-sidebar");
+ is(sidebar.hidden, false, "sidebar is showing on editor with @media");
+
+ const entries = [...sidebar.querySelectorAll(".at-rule-label")];
+ is(entries.length, 4, "four @media rules displayed in sidebar");
+
+ await testRule({
+ ui,
+ editor,
+ rule: entries[0],
+ conditionText: LABELS[0],
+ matches: false,
+ line: LINE_NOS[0],
+ });
+ await testRule({
+ ui,
+ editor,
+ rule: entries[1],
+ conditionText: LABELS[1],
+ matches: true,
+ line: LINE_NOS[1],
+ });
+ await testRule({
+ ui,
+ editor,
+ rule: entries[2],
+ conditionText: LABELS[2],
+ matches: false,
+ line: LINE_NOS[2],
+ });
+ await testRule({
+ ui,
+ editor,
+ rule: entries[3],
+ conditionText: LABELS[3],
+ matches: false,
+ line: LINE_NOS[3],
+ });
+}
+
+function testMediaMatchChanged(editor) {
+ const sidebar = editor.details.querySelector(".stylesheet-sidebar");
+
+ const cond = sidebar.querySelectorAll(".at-rule-condition")[2];
+ is(
+ cond.textContent,
+ "(max-width: 550px)",
+ "third rule condition text is correct"
+ );
+ ok(
+ !cond.classList.contains("media-condition-unmatched"),
+ "media rule is now matched after resizing"
+ );
+}
+
+async function testShowHide(ui, editor) {
+ let sidebarChange = ui.once("at-rules-list-changed");
+ Services.prefs.setBoolPref(SIDEBAR_PREF, false);
+ await sidebarChange;
+
+ const sidebar = editor.details.querySelector(".stylesheet-sidebar");
+ is(sidebar.hidden, true, "sidebar is hidden after flipping pref");
+
+ sidebarChange = ui.once("at-rules-list-changed");
+ Services.prefs.clearUserPref(SIDEBAR_PREF);
+ await sidebarChange;
+
+ is(sidebar.hidden, false, "sidebar is showing after flipping pref back");
+}
+
+async function testMediaRuleAdded(ui, editor) {
+ await editor.getSourceEditor();
+ const sidebar = editor.details.querySelector(".stylesheet-sidebar");
+ is(
+ sidebar.querySelectorAll(".at-rule-label").length,
+ 4,
+ "4 @media rules after changing text"
+ );
+
+ let text = editor.sourceEditor.getText();
+ text += NEW_RULE;
+
+ const listChange = ui.once("at-rules-list-changed");
+ editor.sourceEditor.setText(text);
+ await listChange;
+
+ const entries = [...sidebar.querySelectorAll(".at-rule-label")];
+ is(entries.length, 7, "7 @media rules after changing text");
+
+ await testRule({
+ ui,
+ editor,
+ rule: entries[4],
+ conditionText: LABELS[4],
+ matches: false,
+ line: LINE_NOS[4],
+ });
+
+ await testRule({
+ ui,
+ editor,
+ rule: entries[5],
+ type: "layer",
+ conditionText: LABELS[5],
+ line: LINE_NOS[5],
+ });
+
+ await testRule({
+ ui,
+ editor,
+ rule: entries[6],
+ conditionText: LABELS[6],
+ matches: false,
+ line: LINE_NOS[6],
+ });
+}
+
+/**
+ * Run assertion on given rule
+ *
+ * @param {Object} options
+ * @param {StyleEditorUI} options.ui
+ * @param {StyleSheetEditor} options.editor: The editor the rule is displayed in
+ * @param {Element} options.rule: The rule element in the media sidebar
+ * @param {String} options.conditionText: media query condition text
+ * @param {Boolean} options.matches: Whether or not the document matches the rule
+ * @param {String} options.layerName: Optional name of the @layer
+ * @param {Number} options.line: Line of the rule
+ * @param {String} options.type: The type of the rule (container, layer, media, support ).
+ * Defaults to "media".
+ */
+async function testRule({
+ ui,
+ editor,
+ rule,
+ conditionText,
+ matches,
+ layerName,
+ line,
+ type = "media",
+}) {
+ const atTypeEl = rule.querySelector(".at-rule-type");
+ is(
+ atTypeEl.textContent,
+ `@${type}\u00A0${layerName ? `${layerName}\u00A0` : ""}`,
+ "label for at-rule type is correct"
+ );
+
+ const cond = rule.querySelector(".at-rule-condition");
+ is(
+ cond.textContent,
+ conditionText,
+ "condition label is correct for " + conditionText
+ );
+
+ if (type == "media") {
+ const matched = !cond.classList.contains("media-condition-unmatched");
+ ok(
+ matches ? matched : !matched,
+ "media rule is " + (matches ? "matched" : "unmatched")
+ );
+ }
+
+ const ruleLine = rule.querySelector(".at-rule-line");
+ is(ruleLine.textContent, ":" + line, "correct line number shown");
+
+ info(
+ "Check that clicking on the rule jumps to the expected position in the stylesheet"
+ );
+ rule.click();
+ await waitFor(
+ () =>
+ ui.selectedEditor == editor &&
+ editor.sourceEditor.getCursor().line == line - 1
+ );
+ ok(true, "Jumped to the expected location");
+}
+
+/* Helpers */
+
+function openEditor(editor) {
+ getLinkFor(editor).click();
+
+ return editor.getSourceEditor();
+}
+
+function getLinkFor(editor) {
+ return editor.summary.querySelector(".stylesheet-name");
+}