summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/test/mochitest/browser_dbg-pretty-print-inline-scripts.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/debugger/test/mochitest/browser_dbg-pretty-print-inline-scripts.js')
-rw-r--r--devtools/client/debugger/test/mochitest/browser_dbg-pretty-print-inline-scripts.js256
1 files changed, 256 insertions, 0 deletions
diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-pretty-print-inline-scripts.js b/devtools/client/debugger/test/mochitest/browser_dbg-pretty-print-inline-scripts.js
new file mode 100644
index 0000000000..2b263ad0a9
--- /dev/null
+++ b/devtools/client/debugger/test/mochitest/browser_dbg-pretty-print-inline-scripts.js
@@ -0,0 +1,256 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
+
+// Tests pretty-printing of HTML file and its inner scripts.
+
+"use strict";
+
+const TEST_FILENAME = `doc-pretty-print-inline-scripts.html`;
+const PRETTY_PRINTED_FILENAME = `${TEST_FILENAME}:formatted`;
+
+const BREAKABLE_LINE_HINT_CHAR = `➤`;
+
+// Import helpers for the inspector
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/devtools/client/inspector/test/shared-head.js",
+ this
+);
+
+add_task(async function () {
+ const dbg = await initDebugger(TEST_FILENAME);
+
+ await selectSource(dbg, TEST_FILENAME);
+ clickElement(dbg, "prettyPrintButton");
+
+ await waitForSelectedSource(dbg, PRETTY_PRINTED_FILENAME);
+ const prettyPrintedSource = findSourceContent(dbg, PRETTY_PRINTED_FILENAME);
+
+ ok(prettyPrintedSource, "Pretty-printed source exists");
+
+ info("Check that the HTML file was pretty-printed as expected");
+ const expectedPrettyHtml = getExpectedPrettyPrintedHtml();
+ is(
+ prettyPrintedSource.value,
+ // ➤ is used to indicate breakable lines, we remove them to assert the actual
+ // content of the editor.
+ expectedPrettyHtml.replaceAll(BREAKABLE_LINE_HINT_CHAR, ""),
+ "HTML file is pretty printed as expected"
+ );
+
+ info("Check breakable lines");
+ const htmlLines = expectedPrettyHtml.split("\n");
+ const expectedBreakableLines = [];
+ htmlLines.forEach((line, index) => {
+ if (line.startsWith(BREAKABLE_LINE_HINT_CHAR)) {
+ // Lines in the debugger are 1-based
+ expectedBreakableLines.push(index + 1);
+ }
+ });
+
+ await assertBreakableLines(
+ dbg,
+ PRETTY_PRINTED_FILENAME,
+ htmlLines.length,
+ expectedBreakableLines
+ );
+
+ info("Check that console messages are pointing to pretty-printed file");
+ const { toolbox } = dbg;
+ await toolbox.selectTool("webconsole");
+
+ const { hud } = await dbg.toolbox.getPanel("webconsole");
+ info("Wait until messages are sourcemapped");
+ await waitFor(
+ () => !!findMessageByType(hud, PRETTY_PRINTED_FILENAME, ".log")
+ );
+
+ const firstMessage = await waitFor(() =>
+ findMessageByType(hud, "User information", ".log")
+ );
+ const firstMessageLink = firstMessage.querySelector(".frame-link-source");
+ is(
+ firstMessageLink.innerText,
+ `${PRETTY_PRINTED_FILENAME}:18:8`,
+ "first console message has expected location"
+ );
+ info(
+ "Click on the link of the first message to open the file in the debugger"
+ );
+ firstMessageLink.click();
+ await waitForSelectedSource(dbg, PRETTY_PRINTED_FILENAME);
+ ok(true, "pretty printed file was selected in debugger…");
+ await waitForSelectedLocation(dbg, 18);
+ ok(true, "…at the expected location");
+
+ info("Go back to the console to check an other message");
+ await toolbox.selectTool("webconsole");
+
+ const secondMessage = await waitFor(() =>
+ findMessageByType(hud, "42 yay", ".log")
+ );
+ const secondMessageLink = secondMessage.querySelector(".frame-link-source");
+ is(
+ secondMessageLink.innerText,
+ `${PRETTY_PRINTED_FILENAME}:41:12`,
+ "second console message has expected location"
+ );
+ info(
+ "Click on the link of the second message to open the file in the debugger"
+ );
+ secondMessageLink.click();
+ await waitForSelectedSource(dbg, PRETTY_PRINTED_FILENAME);
+ ok(true, "pretty printed file was selected in debugger…");
+ await waitForSelectedLocation(dbg, 41);
+ ok(true, "…at the expected location");
+
+ info("Check that event listener popup is pointing to pretty-printed file");
+ const inspector = await toolbox.selectTool("inspector");
+
+ const nodeFront = await getNodeFront("h1", inspector);
+ const markupContainer = inspector.markup.getContainer(nodeFront);
+ const evHolder = markupContainer.elt.querySelector(
+ ".inspector-badge.interactive[data-event]"
+ );
+ const eventTooltip = inspector.markup.eventDetailsTooltip;
+
+ info("Open event tooltip.");
+ EventUtils.synthesizeMouseAtCenter(
+ evHolder,
+ {},
+ inspector.markup.doc.defaultView
+ );
+ await eventTooltip.once("shown");
+ ok(true, "event tooltip opened");
+ // wait for filename to be sourcemapped
+ await waitFor(() =>
+ eventTooltip.panel
+ .querySelector(".event-header")
+ ?.innerText.includes(PRETTY_PRINTED_FILENAME)
+ );
+ const header = eventTooltip.panel.querySelector(".event-header");
+ const headerFilename = header.querySelector(
+ ".event-tooltip-filename"
+ ).innerText;
+ ok(
+ headerFilename.endsWith(`${PRETTY_PRINTED_FILENAME}:51`),
+ `Location in event tooltip is the pretty printed one (${headerFilename})`
+ );
+ info(
+ "Check that clicking on open debugger icon selects the pretty printed file"
+ );
+ header.querySelector(".event-tooltip-debugger-icon").click();
+ await waitForSelectedSource(dbg, PRETTY_PRINTED_FILENAME);
+ ok(true, "pretty printed file was selected in debugger…");
+ await waitForSelectedLocation(dbg, 51);
+ ok(true, "…at the expected location");
+});
+
+add_task(async function prettyPrintSingleLineDataUrl() {
+ const TEST_URL = `data:text/html,<meta charset=utf8><script>{"use strict"; globalThis.foo = function() {}}</script>`;
+ const PRETTY_PRINTED_URL = `${TEST_URL}:formatted`;
+ const dbg = await initDebuggerWithAbsoluteURL(TEST_URL);
+
+ await selectSource(dbg, TEST_URL);
+ clickElement(dbg, "prettyPrintButton");
+
+ const prettySource = await waitForSource(dbg, PRETTY_PRINTED_URL);
+ await waitForSelectedSource(dbg, prettySource);
+ const prettyPrintedSource = findSourceContent(dbg, PRETTY_PRINTED_URL);
+
+ ok(prettyPrintedSource, "Pretty-printed source exists");
+
+ info("Check that the HTML file was pretty-printed as expected");
+ const expectedPrettyHtml = `<meta charset=utf8><script>
+{
+ 'use strict';
+ globalThis.foo = function () {
+ }
+}
+</script>`;
+ is(
+ prettyPrintedSource.value,
+ expectedPrettyHtml,
+ "HTML file is pretty printed as expected"
+ );
+});
+
+/**
+ * Return the expected pretty-printed HTML. Lines starting with ➤ indicate breakable
+ * lines for easier maintenance.
+ *
+ * @returns {String}
+ */
+function getExpectedPrettyPrintedHtml() {
+ return `<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<!doctype html>
+
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Debugger test page</title>
+ <!-- Added to check we don't handle non js scripts -->
+ <script id="json-data" type="application/json">
+ { "foo": "bar" }
+ </script>
+
+ <!-- the unusual formatting is wanted to check inline scripts pretty printing -->
+ <script id="inline" type="application/javascript">
+➤const userInfo = JSON.parse(document.getElementById('json-data').text);
+➤console.log('User information: %o', userInfo);
+➤document.addEventListener(
+ 'click',
+ function onClick(e) {
+➤ console.log('in inline script');
+ // this is
+ // something
+➤ e.target;
+➤ }
+);
+</script>
+ </head>
+
+ <body>
+ <h1>Minified</h1>
+ <!-- Checking that having empty inline scripts doesn't throw off pretty printing -->
+ <script></script>
+ <!-- Single line "minified" script -->
+ <script id="minified" type="module">
+➤for (const x of [
+ 42
+]) {
+➤ if (x > 0) {
+➤ console.log(x, 'yay')
+ } else {
+➤ console.log(x, 'booh')
+ }
+➤}
+</script>
+ <!-- Multiple line "minified" script, with content on the first line -->
+ <script>
+{
+ 'use strict';
+➤ document.querySelector('h1').addEventListener('mousedown', e => {
+➤ console.log('mousedown on h1')
+➤ })
+➤}
+</script>
+ <hr><script>
+➤const x = {
+ a: 1,
+ b: 2
+➤};
+</script><hr><!-- multiple scripts on same line --><script>
+➤const y = [
+ 1,
+ 2,
+ 3
+];
+➤y.map(i => i * 2)
+</script>
+ </body>
+</html>
+`;
+}