/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; // Test that the Changes panel works with nested rules. // Declare rule individually so we can use them for the assertions as well // In the end, we should have nested rule looking like: // - @media screen and (height > 5px) { // -- @layer myLayer { // --- @container myContainer (width > 10px) { // ----- div { // ------- & > span { … } // ------- & .mySpan { // --------- &:not(:focus) { const spanNotFocusedRule = `&:not(:focus) { text-decoration: underline; }`; const spanClassRule = `.mySpan { font-weight: bold; ${spanNotFocusedRule} }`; const spanRule = `& > span { outline: 1px solid gold; }`; const divRule = `div { color: tomato; ${spanRule} ${spanClassRule} }`; const containerRule = `@container myContainer (width > 10px) { /* in container */ ${divRule} }`; const layerRule = `@layer myLayer { /* in layer */ ${containerRule} }`; const mediaRule = `@media screen and (height > 5px) { /* in media */ ${layerRule} }`; const TEST_URI = `
hello world
`; const applyModificationAfterDivPropertyChange = ruleText => ruleText.replace("tomato", "cyan"); const EXPECTED_AFTER_DIV_PROP_CHANGE = [ { text: "@media screen and (height > 5px) {", copyRuleClipboard: applyModificationAfterDivPropertyChange(mediaRule), }, { text: "@layer myLayer {", copyRuleClipboard: applyModificationAfterDivPropertyChange(layerRule), }, { text: "@container myContainer (width > 10px) {", copyRuleClipboard: applyModificationAfterDivPropertyChange(containerRule), }, { text: "div {", copyRuleClipboard: applyModificationAfterDivPropertyChange(divRule), }, ]; const applyModificationAfterSpanPropertiesChange = ruleText => ruleText .replace("1px solid gold", "4px solid gold") .replace("bold", "bolder") .replace("underline", "underline dotted"); const EXPECTED_AFTER_SPAN_PROP_CHANGES = EXPECTED_AFTER_DIV_PROP_CHANGE.map( expected => ({ ...expected, copyRuleClipboard: applyModificationAfterSpanPropertiesChange( expected.copyRuleClipboard ), }) ).concat([ { text: "& .mySpan {", copyRuleClipboard: applyModificationAfterSpanPropertiesChange(spanClassRule), }, { text: "&:not(:focus) {", copyRuleClipboard: applyModificationAfterSpanPropertiesChange(spanNotFocusedRule), }, { text: "& > span {", copyRuleClipboard: applyModificationAfterSpanPropertiesChange(spanRule), }, ]); add_task(async function () { await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); const { inspector, view: ruleView } = await openRuleView(); const changesView = await selectChangesView(inspector); const { document: panelDoc, store } = changesView; const panel = panelDoc.querySelector("#sidebar-panel-changes"); await selectNode("div", inspector); let onTrackChange = waitForDispatch(store, "TRACK_CHANGE"); await updateDeclaration(ruleView, 1, { color: "tomato" }, { color: "cyan" }); await onTrackChange; await assertSelectors(panel, EXPECTED_AFTER_DIV_PROP_CHANGE); await selectNode(".mySpan", inspector); onTrackChange = waitForDispatch(store, "TRACK_CHANGE"); await updateDeclaration( ruleView, 1, { "text-decoration": "underline" }, { "text-decoration": "underline dotted" } ); await onTrackChange; onTrackChange = waitForDispatch(store, "TRACK_CHANGE"); await updateDeclaration( ruleView, 2, { "font-weight": "bold" }, { "font-weight": "bolder" } ); await onTrackChange; onTrackChange = waitForDispatch(store, "TRACK_CHANGE"); await updateDeclaration( ruleView, 3, { outline: "1px solid gold" }, { outline: "4px solid gold" } ); await onTrackChange; await assertSelectors(panel, EXPECTED_AFTER_SPAN_PROP_CHANGES); }); async function assertSelectors(panel, expected) { await waitFor( () => getSelectors(panel).length === expected.length, "Wait for the expected number of selectors item" ); const selectorsEl = getSelectors(panel); is( selectorsEl.length, expected.length, "Got the expected number of selectors item" ); for (let i = 0; i < expected.length; i++) { const selectorEl = selectorsEl[i]; const expectedItem = expected[i]; is( selectorEl.innerText, expectedItem.text, `Got expected selector text at index ${i}` ); info(`Click the Copy Rule button for the "${expectedItem.text}" rule`); const button = selectorEl .closest(".changes__rule") .querySelector(".changes__copy-rule-button"); await waitForClipboardPromise( () => button.click(), () => checkClipboardData(expectedItem.copyRuleClipboard) ); } } function checkClipboardData(expected) { const actual = SpecialPowers.getClipboardData("text/plain"); return actual.trim() === expected.trim(); }