1 /* Any copyright is dedicated to the Public Domain.
2 * http://creativecommons.org/publicdomain/zero/1.0/ */
6 // Check display of custom formatters.
8 "https://example.com/browser/devtools/client/webconsole/" +
9 "test/browser/test-console-custom-formatters-errors.html";
11 add_task(async function () {
12 await pushPref("devtools.custom-formatters.enabled", true);
14 // enable "can't access property "y", x is undefined" error message
15 await pushPref("javascript.options.property_error_message_fix", true);
17 const hud = await openNewTabAndConsole(TEST_URI);
19 // Reload the browser to ensure the custom formatters are picked up
20 await reloadBrowser();
22 await testHeaderNotAFunction(hud);
23 await testHeaderNotReturningJsonMl(hud);
24 await testHeaderNotReturningElementType(hud);
25 await testHeaderThrowing(hud);
26 await testHasBodyNotAFunction(hud);
27 await testHasBodyThrowing(hud);
28 await testBodyNotAFunction(hud);
29 await testBodyReturningNull(hud);
30 await testBodyNotReturningJsonMl(hud);
31 await testBodyNotReturningElementType(hud);
32 await testBodyThrowing(hud);
33 await testIncorrectObjectTag(hud);
34 await testInvalidTagname(hud);
35 await testNoPrivilegedAccess(hud);
36 await testErrorsLoggedOnce(hud);
39 async function testHeaderNotAFunction(hud) {
40 info(`Test for "header" not being a function`);
41 await testCustomFormatting(hud, {
42 messageText: `Custom formatter failed: devtoolsFormatters[0].header should be a function, got number`,
46 async function testHeaderNotReturningJsonMl(hud) {
47 info(`Test for "header" not returning JsonML`);
48 await testCustomFormatting(hud, {
49 messageText: `Custom formatter failed: devtoolsFormatters[1].header should return an array, got number`,
50 source: "test-console-custom-formatters-errors.html:19:18",
54 async function testHeaderNotReturningElementType(hud) {
55 info(`Test for "header" function returning array without element type`);
56 await testCustomFormatting(hud, {
57 messageText: `Custom formatter failed: devtoolsFormatters[2].header returned an empty array`,
61 async function testHeaderThrowing(hud) {
62 info(`Test for "header" function throwing`);
63 await testCustomFormatting(hud, {
64 messageText: `Custom formatter failed: devtoolsFormatters[3].header threw: ERROR`,
68 async function testHasBodyNotAFunction(hud) {
69 info(`Test for "hasBody" not being a function`);
70 await testCustomFormatting(hud, {
71 messageText: `Custom formatter failed: devtoolsFormatters[4].hasBody should be a function, got number`,
75 async function testHasBodyThrowing(hud) {
76 info(`Test for "hasBody" function throwing`);
77 await testCustomFormatting(hud, {
78 messageText: `Custom formatter failed: devtoolsFormatters[5].hasBody threw: ERROR`,
82 async function testBodyNotAFunction(hud) {
83 info(`Test for "body" not being a function`);
84 await testCustomFormatting(hud, {
85 messageText: "body not a function",
86 bodyText: `Custom formatter failed: devtoolsFormatters[6].body should be a function, got number`,
90 async function testBodyReturningNull(hud) {
91 info(`Test for "body" returning null`);
92 await testCustomFormatting(hud, {
93 messageText: "body returns null",
94 bodyText: `Custom formatter failed: devtoolsFormatters[7].body should return an array, got null`,
98 async function testBodyNotReturningJsonMl(hud) {
99 info(`Test for "body" not returning JsonML`);
100 await testCustomFormatting(hud, {
101 messageText: "body doesn't return JsonML",
102 bodyText: `Custom formatter failed: devtoolsFormatters[8].body should return an array, got number`,
106 async function testBodyNotReturningElementType(hud) {
107 info(`Test for "body" function returning array without element type`);
108 await testCustomFormatting(hud, {
109 messageText: "body array misses element type",
110 bodyText: `Custom formatter failed: devtoolsFormatters[9].body returned an empty array`,
114 async function testBodyThrowing(hud) {
115 info(`Test for "body" function throwing`);
116 await testCustomFormatting(hud, {
117 messageText: "body throws",
118 bodyText: `Custom formatter failed: devtoolsFormatters[10].body threw: ERROR`,
122 async function testErrorsLoggedOnce(hud) {
123 const messages = findMessagesByType(hud, "custom formatter failed", ".error");
125 messages.forEach(async message => {
126 await checkUniqueMessageExists(hud, message.textContent, ".error");
130 async function testIncorrectObjectTag(hud) {
131 info(`Test for "object" tag without attribute`);
132 await testCustomFormatting(hud, {
133 messageText: `Custom formatter failed: devtoolsFormatters[11] couldn't be run: "object" tag should have attributes`,
136 info(`Test for "object" tag without "object" attribute`);
137 await testCustomFormatting(hud, {
138 messageText: `Custom formatter failed: devtoolsFormatters[12] couldn't be run: attribute of "object" tag should have an "object" property`,
141 info(`Test for infinite "object" tag`);
142 await testCustomFormatting(hud, {
143 messageText: `Custom formatter failed: Too deep hierarchy of inlined custom previews`,
147 async function testInvalidTagname(hud) {
148 info(`Test invalid tagname in the returned JsonML`);
149 await testCustomFormatting(hud, {
150 messageText: `Custom formatter failed: devtoolsFormatters[14] couldn't be run: tagName should be a string, got number`,
154 async function testNoPrivilegedAccess(hud) {
155 info(`Test for denied access to windowUtils from hook`);
156 await testCustomFormatting(hud, {
157 messageText: `Custom formatter failed: devtoolsFormatters[17].header threw: can't access property "garbageCollect", window.windowUtils is undefined`,
161 async function testCustomFormatting(hud, { messageText, source, bodyText }) {
162 const headerNode = bodyText
163 ? await waitFor(() => {
164 return findConsoleAPIMessage(hud, messageText);
166 : await waitFor(() => {
167 return findErrorMessage(hud, messageText);
170 ok(true, `Got expected message: ${messageText}`);
173 const sourceLink = headerNode.querySelector(".message-location");
174 is(sourceLink?.textContent, source, "Source location is correct");
178 const arrow = headerNode.querySelector(".collapse-button");
180 ok(arrow, "There must be a toggle arrow for the header");
182 info("Expanding the Object");
183 const bodyErrorNode = waitFor(() => {
184 return findErrorMessage(hud, bodyText);
192 .querySelector(".collapse-button")
193 .classList.contains("expanded"),
194 "The arrow of the node has the expected class after clicking on it"