diff options
Diffstat (limited to 'devtools/client/webconsole/test/browser/browser_webconsole_custom_formatters_errors.js')
-rw-r--r-- | devtools/client/webconsole/test/browser/browser_webconsole_custom_formatters_errors.js | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_custom_formatters_errors.js b/devtools/client/webconsole/test/browser/browser_webconsole_custom_formatters_errors.js new file mode 100644 index 0000000000..71013ab58f --- /dev/null +++ b/devtools/client/webconsole/test/browser/browser_webconsole_custom_formatters_errors.js @@ -0,0 +1,199 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Check display of custom formatters. +const TEST_URI = + "https://example.com/browser/devtools/client/webconsole/" + + "test/browser/test-console-custom-formatters-errors.html"; + +add_task(async function () { + // ToDo: This preference can be removed once the custom formatters feature is stable enough + await pushPref("devtools.custom-formatters", true); + await pushPref("devtools.custom-formatters.enabled", true); + + // enable "can't access property "y", x is undefined" error message + await pushPref("javascript.options.property_error_message_fix", true); + + const hud = await openNewTabAndConsole(TEST_URI); + + // Reload the browser to ensure the custom formatters are picked up + await reloadBrowser(); + + await testHeaderNotAFunction(hud); + await testHeaderNotReturningJsonMl(hud); + await testHeaderNotReturningElementType(hud); + await testHeaderThrowing(hud); + await testHasBodyNotAFunction(hud); + await testHasBodyThrowing(hud); + await testBodyNotAFunction(hud); + await testBodyReturningNull(hud); + await testBodyNotReturningJsonMl(hud); + await testBodyNotReturningElementType(hud); + await testBodyThrowing(hud); + await testIncorrectObjectTag(hud); + await testInvalidTagname(hud); + await testNoPrivilegedAccess(hud); + await testErrorsLoggedOnce(hud); +}); + +async function testHeaderNotAFunction(hud) { + info(`Test for "header" not being a function`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: devtoolsFormatters[0].header should be a function, got number`, + }); +} + +async function testHeaderNotReturningJsonMl(hud) { + info(`Test for "header" not returning JsonML`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: devtoolsFormatters[1].header should return an array, got number`, + source: "test-console-custom-formatters-errors.html:19:18", + }); +} + +async function testHeaderNotReturningElementType(hud) { + info(`Test for "header" function returning array without element type`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: devtoolsFormatters[2].header returned an empty array`, + }); +} + +async function testHeaderThrowing(hud) { + info(`Test for "header" function throwing`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: devtoolsFormatters[3].header threw: ERROR`, + }); +} + +async function testHasBodyNotAFunction(hud) { + info(`Test for "hasBody" not being a function`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: devtoolsFormatters[4].hasBody should be a function, got number`, + }); +} + +async function testHasBodyThrowing(hud) { + info(`Test for "hasBody" function throwing`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: devtoolsFormatters[5].hasBody threw: ERROR`, + }); +} + +async function testBodyNotAFunction(hud) { + info(`Test for "body" not being a function`); + await testCustomFormatting(hud, { + messageText: "body not a function", + bodyText: `Custom formatter failed: devtoolsFormatters[6].body should be a function, got number`, + }); +} + +async function testBodyReturningNull(hud) { + info(`Test for "body" returning null`); + await testCustomFormatting(hud, { + messageText: "body returns null", + bodyText: `Custom formatter failed: devtoolsFormatters[7].body should return an array, got null`, + }); +} + +async function testBodyNotReturningJsonMl(hud) { + info(`Test for "body" not returning JsonML`); + await testCustomFormatting(hud, { + messageText: "body doesn't return JsonML", + bodyText: `Custom formatter failed: devtoolsFormatters[8].body should return an array, got number`, + }); +} + +async function testBodyNotReturningElementType(hud) { + info(`Test for "body" function returning array without element type`); + await testCustomFormatting(hud, { + messageText: "body array misses element type", + bodyText: `Custom formatter failed: devtoolsFormatters[9].body returned an empty array`, + }); +} + +async function testBodyThrowing(hud) { + info(`Test for "body" function throwing`); + await testCustomFormatting(hud, { + messageText: "body throws", + bodyText: `Custom formatter failed: devtoolsFormatters[10].body threw: ERROR`, + }); +} + +async function testErrorsLoggedOnce(hud) { + const messages = findMessagesByType(hud, "custom formatter failed", ".error"); + + messages.forEach(async message => { + await checkUniqueMessageExists(hud, message.textContent, ".error"); + }); +} + +async function testIncorrectObjectTag(hud) { + info(`Test for "object" tag without attribute`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: devtoolsFormatters[11] couldn't be run: "object" tag should have attributes`, + }); + + info(`Test for "object" tag without "object" attribute`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: devtoolsFormatters[12] couldn't be run: attribute of "object" tag should have an "object" property`, + }); + + info(`Test for infinite "object" tag`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: Too deep hierarchy of inlined custom previews`, + }); +} + +async function testInvalidTagname(hud) { + info(`Test invalid tagname in the returned JsonML`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: devtoolsFormatters[14] couldn't be run: tagName should be a string, got number`, + }); +} + +async function testNoPrivilegedAccess(hud) { + info(`Test for denied access to windowUtils from hook`); + await testCustomFormatting(hud, { + messageText: `Custom formatter failed: devtoolsFormatters[17].header threw: can't access property "garbageCollect", window.windowUtils is undefined`, + }); +} + +async function testCustomFormatting(hud, { messageText, source, bodyText }) { + const headerNode = bodyText + ? await waitFor(() => { + return findConsoleAPIMessage(hud, messageText); + }) + : await waitFor(() => { + return findErrorMessage(hud, messageText); + }); + + ok(true, `Got expected message: ${messageText}`); + + if (source) { + const sourceLink = headerNode.querySelector(".message-location"); + is(sourceLink?.textContent, source, "Source location is correct"); + } + + if (bodyText) { + const arrow = headerNode.querySelector(".collapse-button"); + + ok(arrow, "There must be a toggle arrow for the header"); + + info("Expanding the Object"); + const bodyErrorNode = waitFor(() => { + return findErrorMessage(hud, bodyText); + }); + + arrow.click(); + await bodyErrorNode; + + ok( + headerNode + .querySelector(".collapse-button") + .classList.contains("expanded"), + "The arrow of the node has the expected class after clicking on it" + ); + } +} |