diff options
Diffstat (limited to '')
-rw-r--r-- | devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js b/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js new file mode 100644 index 0000000000..f9d245828e --- /dev/null +++ b/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js @@ -0,0 +1,255 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that properties can be selected and copied from the rule view + +const osString = Services.appinfo.OS; + +const TEST_URI = ` + <style type="text/css"> + html { + color: #000000; + } + span { + font-variant: small-caps; color: #000000; + } + .nomatches { + color: #ff0000; + } + + html { + body { + container-type: inline-size; + @container (1px < width) { + #nested { + background: tomato; + color: gold; + } + } + } + } + </style> + <div id="first" style="margin: 10em; + font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA"> + <h1>Some header text</h1> + <p id="salutation" style="font-size: 12pt">hi.</p> + <p id="body" style="font-size: 12pt">I am a test-case. This text exists + solely to provide some things to <span style="color: yellow"> + highlight</span> and <span style="font-weight: bold">count</span> + style list-items in the box at right. If you are reading this, + you should go do something else instead. Maybe read a book. Or better + yet, write some test-cases for another bit of code. + <span style="font-style: italic">some text</span></p> + <p id="closing">more text</p> + <p>even more text</p> + </div> + <section id=nested>Nested</section> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, view } = await openRuleView(); + await selectNode("div", inspector); + await checkCopySelection(view); + await checkSelectAll(view); + await checkCopyEditorValue(view); + + await selectNode("#nested", inspector); + await checkCopyNestedRule(view); +}); + +async function checkCopySelection(view) { + info("Testing selection copy"); + + const contentDoc = view.styleDocument; + const win = view.styleWindow; + const prop = contentDoc.querySelector(".ruleview-property"); + const values = contentDoc.querySelectorAll( + ".ruleview-propertyvaluecontainer" + ); + + let range = contentDoc.createRange(); + range.setStart(prop, 0); + range.setEnd(values[4], 2); + win.getSelection().addRange(range); + info("Checking that _Copy() returns the correct clipboard value"); + + const expectedPattern = + " margin: 10em;[\\r\\n]+" + + " font-size: 14pt;[\\r\\n]+" + + " font-family: helvetica, sans-serif;[\\r\\n]+" + + " color: #AAA;[\\r\\n]+" + + "}[\\r\\n]+" + + "html {[\\r\\n]+" + + " color: #000000;[\\r\\n]*"; + + const allMenuItems = openStyleContextMenuAndGetAllItems(view, prop); + const menuitemCopy = allMenuItems.find( + item => + item.label === + STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.copy") + ); + + ok(menuitemCopy.visible, "Copy menu item is displayed as expected"); + + try { + await waitForClipboardPromise( + () => menuitemCopy.click(), + () => checkClipboardData(expectedPattern) + ); + } catch (e) { + failedClipboard(expectedPattern); + } + + info("Check copying from keyboard"); + win.getSelection().removeRange(range); + // Selecting the declaration `margin: 10em;` + range = contentDoc.createRange(); + range.setStart(prop, 0); + range.setEnd(prop, 1); + win.getSelection().addRange(range); + + // Dispatching the copy event from the checkbox to make sure we cover Bug 1680893. + const declarationCheckbox = contentDoc.querySelector( + "input[type=checkbox].ruleview-enableproperty" + ); + const copyEvent = new win.Event("copy", { bubbles: true }); + await waitForClipboardPromise( + () => declarationCheckbox.dispatchEvent(copyEvent), + () => checkClipboardData("^ margin: 10em;$") + ); + win.getSelection().removeRange(range); +} + +async function checkSelectAll(view) { + info("Testing select-all copy"); + + const contentDoc = view.styleDocument; + const prop = contentDoc.querySelector(".ruleview-property"); + + info( + "Checking that _SelectAll() then copy returns the correct " + + "clipboard value" + ); + view.contextMenu._onSelectAll(); + const expectedPattern = + "element {[\\r\\n]+" + + " margin: 10em;[\\r\\n]+" + + " font-size: 14pt;[\\r\\n]+" + + " font-family: helvetica, sans-serif;[\\r\\n]+" + + " color: #AAA;[\\r\\n]+" + + "}[\\r\\n]+" + + "html {[\\r\\n]+" + + " color: #000000;[\\r\\n]+" + + "}[\\r\\n]*"; + + const allMenuItems = openStyleContextMenuAndGetAllItems(view, prop); + const menuitemCopy = allMenuItems.find( + item => + item.label === + STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.copy") + ); + + ok(menuitemCopy.visible, "Copy menu item is displayed as expected"); + + try { + await waitForClipboardPromise( + () => menuitemCopy.click(), + () => checkClipboardData(expectedPattern) + ); + } catch (e) { + failedClipboard(expectedPattern); + } +} + +async function checkCopyEditorValue(view) { + info("Testing CSS property editor value copy"); + + const ruleEditor = getRuleViewRuleEditor(view, 0); + const propEditor = ruleEditor.rule.textProps[0].editor; + + const editor = await focusEditableField(view, propEditor.valueSpan); + + info( + "Checking that copying a css property value editor returns the correct" + + " clipboard value" + ); + + const expectedPattern = "10em"; + + const allMenuItems = openStyleContextMenuAndGetAllItems(view, editor.input); + const menuitemCopy = allMenuItems.find( + item => + item.label === + STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.copy") + ); + + ok(menuitemCopy.visible, "Copy menu item is displayed as expected"); + + try { + await waitForClipboardPromise( + () => menuitemCopy.click(), + () => checkClipboardData(expectedPattern) + ); + } catch (e) { + failedClipboard(expectedPattern); + } +} + +async function checkCopyNestedRule(view) { + info("Select nested rule"); + const doc = view.styleDocument; + const range = doc.createRange(); + const nestedRule = doc.querySelector(".ruleview-rule:nth-of-type(2)"); + range.selectNode(nestedRule); + const win = view.styleWindow; + win.getSelection().addRange(range); + + const copyEvent = new win.Event("copy", { bubbles: true }); + const expectedNested = `html { + body { + @container (1px < width) { + #nested { + background: tomato; + color: gold; + } + } + } +} +`; + + await waitForClipboardPromise( + () => nestedRule.dispatchEvent(copyEvent), + expectedNested + ); +} + +function checkClipboardData(expectedPattern) { + const actual = SpecialPowers.getClipboardData("text/plain"); + const expectedRegExp = new RegExp(expectedPattern, "g"); + return expectedRegExp.test(actual); +} + +function failedClipboard(expectedPattern) { + // Format expected text for comparison + const terminator = osString == "WINNT" ? "\r\n" : "\n"; + expectedPattern = expectedPattern.replace(/\[\\r\\n\][+*]/g, terminator); + expectedPattern = expectedPattern.replace(/\\\(/g, "("); + expectedPattern = expectedPattern.replace(/\\\)/g, ")"); + + let actual = SpecialPowers.getClipboardData("text/plain"); + + // Trim the right hand side of our strings. This is because expectedPattern + // accounts for windows sometimes adding a newline to our copied data. + expectedPattern = expectedPattern.trimRight(); + actual = actual.trimRight(); + + dump( + "TEST-UNEXPECTED-FAIL | Clipboard text does not match expected ... " + + "results (escaped for accurate comparison):\n" + ); + info("Actual: " + escape(actual)); + info("Expected: " + escape(expectedPattern)); +} |