summaryrefslogtreecommitdiffstats
path: root/devtools/client/webconsole/test/browser/browser_webconsole_context_menu_copy_message_with_framework_stacktrace.js
blob: 66649020fb938fd74c15a1c02a0dabcf9dca7132 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

const httpServer = createTestHTTPServer();
httpServer.registerPathHandler(`/`, function (request, response) {
  response.setStatusLine(request.httpVersion, 200, "OK");
  response.write(`
    <meta charset=utf8>
    <h1>Test "copy message" context menu entry on message with framework stacktrace</h1>
    <script type="text/javascript" src="react.js"></script>
    <script type="text/javascript" src="test.js"></script>`);
});

httpServer.registerPathHandler("/test.js", function (_, response) {
  response.setHeader("Content-Type", "application/javascript");
  response.write(`
    window.myFunc = () => wrapper();
    const wrapper = () => console.trace("wrapperTrace");
  `);
});

httpServer.registerPathHandler("/react.js", function (_, response) {
  response.setHeader("Content-Type", "application/javascript");
  response.write(`
    window.render = function() {
      const renderFinal = () => window.myFunc();
      renderFinal();
    };
  `);
});

const TEST_URI = `http://localhost:${httpServer.identity.primaryPort}/`;

// Test the Copy menu item of the webconsole copies the expected clipboard text for
// a message with a "framework" stacktrace (i.e. with grouped frames).

add_task(async function () {
  const hud = await openNewTabAndConsole(TEST_URI);

  info("Call the log function defined in the test page");
  const onMessage = waitForMessageByType(hud, "wrapperTrace", ".console-api");
  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
    content.wrappedJSObject.render();
  });
  const message = await onMessage;
  const messageEl = message.node;
  await waitFor(() => messageEl.querySelector(".frames"));

  let clipboardText = await copyMessageContent(hud, messageEl);
  ok(true, "Clipboard text was found and saved");

  const newLineString = "\n";
  info("Check copied text for the console.trace message");
  let lines = clipboardText.split(newLineString);
  is(lines.length, 5, "Correct number of lines in the copied text");
  is(lines[lines.length - 1], "", "The last line is an empty new line");
  is(
    lines[0],
    `console.trace() wrapperTrace test.js:3:35`,
    "Message first line has the expected text"
  );
  is(
    lines[1],
    `    wrapper ${TEST_URI}test.js:3`,
    "Stacktrace first line has the expected text"
  );
  is(
    lines[2],
    `    myFunc ${TEST_URI}test.js:2`,
    "Stacktrace second line has the expected text"
  );
  is(lines[3], `    React 2`, "Stacktrace third line has the expected text");

  info("Expand the React group");
  const getFrames = () => messageEl.querySelectorAll(".frame");
  const frames = getFrames().length;
  messageEl.querySelector(".frames .group").click();
  // Let's wait until all React frames are displayed.
  await waitFor(() => getFrames().length > frames);

  clipboardText = await copyMessageContent(hud, messageEl);
  ok(true, "Clipboard text was found and saved");

  info(
    "Check copied text for the console.trace message with expanded React frames"
  );
  lines = clipboardText.split(newLineString);
  is(lines.length, 7, "Correct number of lines in the copied text");
  is(lines[lines.length - 1], "", "The last line is an empty new line");
  is(
    lines[0],
    `console.trace() wrapperTrace test.js:3:35`,
    "Message first line has the expected text"
  );
  is(
    lines[1],
    `    wrapper ${TEST_URI}test.js:3`,
    "Stacktrace first line has the expected text"
  );
  is(
    lines[2],
    `    myFunc ${TEST_URI}test.js:2`,
    "Stacktrace second line has the expected text"
  );
  is(lines[3], `    React 2`, "Stacktrace third line has the expected text");
  is(
    lines[4],
    `        renderFinal`,
    "Stacktrace fourth line has the expected text"
  );
  is(lines[5], `        render`, "Stacktrace fifth line has the expected text");
});

/**
 * Simple helper method to open the context menu on a given message, and click on the copy
 * menu item.
 */
async function copyMessageContent(hud, messageEl) {
  const menuPopup = await openContextMenu(hud, messageEl);
  const copyMenuItem = menuPopup.querySelector("#console-menu-copy");
  ok(copyMenuItem, "copy menu item is enabled");

  const text = await waitForClipboardPromise(
    () => copyMenuItem.click(),
    data => data
  );

  menuPopup.hidePopup();
  return text;
}