forked from mirrors/gecko-dev
Instead of rendering the cropped URL, we split the URL in 3 parts, so the full URL text will be in the DOM, but we visually hide the middle part and replace it with an ellipsis. This way copying the message will still put the full URL in the clipboard. A test case is added to ensure this works as expected. Differential Revision: https://phabricator.services.mozilla.com/D165805
661 lines
21 KiB
JavaScript
661 lines
21 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
"use strict";
|
|
|
|
// Test utils.
|
|
const expect = require("expect");
|
|
const { render, mount } = require("enzyme");
|
|
const sinon = require("sinon");
|
|
|
|
// React
|
|
const {
|
|
createFactory,
|
|
} = require("resource://devtools/client/shared/vendor/react.js");
|
|
const Provider = createFactory(
|
|
require("resource://devtools/client/shared/vendor/react-redux.js").Provider
|
|
);
|
|
const {
|
|
formatErrorTextWithCausedBy,
|
|
setupStore,
|
|
} = require("resource://devtools/client/webconsole/test/node/helpers.js");
|
|
const {
|
|
prepareMessage,
|
|
} = require("resource://devtools/client/webconsole/utils/messages.js");
|
|
|
|
// Components under test.
|
|
const PageError = require("resource://devtools/client/webconsole/components/Output/message-types/PageError.js");
|
|
const {
|
|
MESSAGE_OPEN,
|
|
MESSAGE_CLOSE,
|
|
} = require("resource://devtools/client/webconsole/constants.js");
|
|
const {
|
|
INDENT_WIDTH,
|
|
} = require("resource://devtools/client/webconsole/components/Output/MessageIndent.js");
|
|
|
|
// Test fakes.
|
|
const {
|
|
stubPackets,
|
|
stubPreparedMessages,
|
|
} = require("resource://devtools/client/webconsole/test/node/fixtures/stubs/index.js");
|
|
const serviceContainer = require("resource://devtools/client/webconsole/test/node/fixtures/serviceContainer.js");
|
|
|
|
describe("PageError component:", () => {
|
|
it("renders", () => {
|
|
const message = stubPreparedMessages.get(
|
|
"ReferenceError: asdf is not defined"
|
|
);
|
|
const wrapper = render(
|
|
PageError({
|
|
message,
|
|
serviceContainer,
|
|
timestampsVisible: true,
|
|
})
|
|
);
|
|
const {
|
|
timestampString,
|
|
} = require("resource://devtools/client/webconsole/utils/l10n.js");
|
|
|
|
expect(wrapper.find(".timestamp").text()).toBe(
|
|
timestampString(message.timeStamp)
|
|
);
|
|
|
|
expect(wrapper.find(".message-body").text()).toBe(
|
|
"Uncaught ReferenceError: asdf is not defined[Learn More]"
|
|
);
|
|
|
|
// The stacktrace should be closed by default.
|
|
const frameLinks = wrapper.find(`.stack-trace`);
|
|
expect(frameLinks.length).toBe(0);
|
|
|
|
// There should be the location.
|
|
const locationLink = wrapper.find(`.message-location`);
|
|
expect(locationLink.length).toBe(1);
|
|
// @TODO Will likely change. See bug 1307952
|
|
expect(locationLink.text()).toBe("test-console-api.html:3:5");
|
|
});
|
|
|
|
it("does not have a timestamp when timestampsVisible prop is falsy", () => {
|
|
const message = stubPreparedMessages.get(
|
|
"ReferenceError: asdf is not defined"
|
|
);
|
|
const wrapper = render(
|
|
PageError({
|
|
message,
|
|
serviceContainer,
|
|
timestampsVisible: false,
|
|
})
|
|
);
|
|
|
|
expect(wrapper.find(".timestamp").length).toBe(0);
|
|
});
|
|
|
|
it("renders an error with a longString exception message", () => {
|
|
const message = stubPreparedMessages.get("TypeError longString message");
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text.startsWith("Uncaught Error: Long error Long error")).toBe(true);
|
|
});
|
|
|
|
it("renders thrown empty string", () => {
|
|
const message = stubPreparedMessages.get(`throw ""`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe("Uncaught <empty string>");
|
|
});
|
|
|
|
it("renders thrown string", () => {
|
|
const message = stubPreparedMessages.get(`throw "tomato"`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught tomato`);
|
|
});
|
|
|
|
it("renders thrown boolean", () => {
|
|
const message = stubPreparedMessages.get(`throw false`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught false`);
|
|
});
|
|
|
|
it("renders thrown number ", () => {
|
|
const message = stubPreparedMessages.get(`throw 0`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught 0`);
|
|
});
|
|
|
|
it("renders thrown null", () => {
|
|
const message = stubPreparedMessages.get(`throw null`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught null`);
|
|
});
|
|
|
|
it("renders thrown undefined", () => {
|
|
const message = stubPreparedMessages.get(`throw undefined`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught undefined`);
|
|
});
|
|
|
|
it("renders thrown Symbol", () => {
|
|
const message = stubPreparedMessages.get(`throw Symbol`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught Symbol("potato")`);
|
|
});
|
|
|
|
it("renders thrown object", () => {
|
|
const message = stubPreparedMessages.get(`throw Object`);
|
|
|
|
// We need to wrap the PageError in a Provider in order for the
|
|
// ObjectInspector to work.
|
|
const wrapper = render(
|
|
Provider(
|
|
{ store: setupStore() },
|
|
PageError({ message, serviceContainer })
|
|
)
|
|
);
|
|
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught Object { vegetable: "cucumber" }`);
|
|
});
|
|
|
|
it("renders thrown error", () => {
|
|
const message = stubPreparedMessages.get(`throw Error Object`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught Error: pumpkin`);
|
|
});
|
|
|
|
it("renders thrown Error with custom name", () => {
|
|
const message = stubPreparedMessages.get(
|
|
`throw Error Object with custom name`
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught JuicyError: pineapple`);
|
|
});
|
|
|
|
it("renders thrown Error with error cause", () => {
|
|
const message = stubPreparedMessages.get(
|
|
`throw Error Object with error cause`
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const text = formatErrorTextWithCausedBy(
|
|
wrapper.find(".message-body").text()
|
|
);
|
|
expect(text).toBe(
|
|
"Uncaught Error: something went wrong\nCaused by: SyntaxError: original error"
|
|
);
|
|
expect(wrapper.hasClass("error")).toBe(true);
|
|
});
|
|
|
|
it("renders thrown Error with error cause chain", () => {
|
|
const message = stubPreparedMessages.get(
|
|
`throw Error Object with cause chain`
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const text = formatErrorTextWithCausedBy(
|
|
wrapper.find(".message-body").text()
|
|
);
|
|
expect(text).toBe(
|
|
[
|
|
"Uncaught Error: err-d",
|
|
"Caused by: Error: err-c",
|
|
"Caused by: Error: err-b",
|
|
"Caused by: Error: err-a",
|
|
].join("\n")
|
|
);
|
|
expect(wrapper.hasClass("error")).toBe(true);
|
|
});
|
|
|
|
it("renders thrown Error with cyclical cause chain", () => {
|
|
const message = stubPreparedMessages.get(
|
|
`throw Error Object with cyclical cause chain`
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const text = formatErrorTextWithCausedBy(
|
|
wrapper.find(".message-body").text()
|
|
);
|
|
// TODO: This is not how we should display cyclical cause chain, but we have it here
|
|
// to ensure it's displaying something that makes _some_ sense.
|
|
// This should be properly handled in Bug 1719605.
|
|
expect(text).toBe(
|
|
[
|
|
"Uncaught Error: err-b",
|
|
"Caused by: Error: err-a",
|
|
"Caused by: Error: err-b",
|
|
"Caused by: Error: err-a",
|
|
].join("\n")
|
|
);
|
|
expect(wrapper.hasClass("error")).toBe(true);
|
|
});
|
|
|
|
it("renders thrown Error with null cause", () => {
|
|
const message = stubPreparedMessages.get(
|
|
`throw Error Object with falsy cause`
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const text = formatErrorTextWithCausedBy(
|
|
wrapper.find(".message-body").text()
|
|
);
|
|
expect(text).toBe("Uncaught Error: null cause\nCaused by: null");
|
|
expect(wrapper.hasClass("error")).toBe(true);
|
|
});
|
|
|
|
it("renders thrown Error with number cause", () => {
|
|
const message = stubPreparedMessages.get(
|
|
`throw Error Object with number cause`
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const text = formatErrorTextWithCausedBy(
|
|
wrapper.find(".message-body").text()
|
|
);
|
|
expect(text).toBe("Uncaught Error: number cause\nCaused by: 0");
|
|
expect(wrapper.hasClass("error")).toBe(true);
|
|
});
|
|
|
|
it("renders thrown Error with string cause", () => {
|
|
const message = stubPreparedMessages.get(
|
|
`throw Error Object with string cause`
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const text = formatErrorTextWithCausedBy(
|
|
wrapper.find(".message-body").text()
|
|
);
|
|
expect(text).toBe(
|
|
`Uncaught Error: string cause\nCaused by: "cause message"`
|
|
);
|
|
expect(wrapper.hasClass("error")).toBe(true);
|
|
});
|
|
|
|
it("renders thrown Error with object cause", () => {
|
|
const message = stubPreparedMessages.get(
|
|
`throw Error Object with object cause`
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const text = formatErrorTextWithCausedBy(
|
|
wrapper.find(".message-body").text()
|
|
);
|
|
expect(text).toBe("Uncaught Error: object cause\nCaused by: Object { … }");
|
|
expect(wrapper.hasClass("error")).toBe(true);
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with empty string", () => {
|
|
const message = stubPreparedMessages.get(`Promise reject ""`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe("Uncaught (in promise) <empty string>");
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with string", () => {
|
|
const message = stubPreparedMessages.get(`Promise reject "tomato"`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught (in promise) tomato`);
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with boolean", () => {
|
|
const message = stubPreparedMessages.get(`Promise reject false`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught (in promise) false`);
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with number ", () => {
|
|
const message = stubPreparedMessages.get(`Promise reject 0`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught (in promise) 0`);
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with null", () => {
|
|
const message = stubPreparedMessages.get(`Promise reject null`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught (in promise) null`);
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with undefined", () => {
|
|
const message = stubPreparedMessages.get(`Promise reject undefined`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught (in promise) undefined`);
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with Symbol", () => {
|
|
const message = stubPreparedMessages.get(`Promise reject Symbol`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught (in promise) Symbol("potato")`);
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with object", () => {
|
|
const message = stubPreparedMessages.get(`Promise reject Object`);
|
|
// We need to wrap the PageError in a Provider in order for the
|
|
// ObjectInspector to work.
|
|
const wrapper = render(
|
|
Provider(
|
|
{ store: setupStore() },
|
|
PageError({ message, serviceContainer })
|
|
)
|
|
);
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught (in promise) Object { vegetable: "cucumber" }`);
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with error", () => {
|
|
const message = stubPreparedMessages.get(`Promise reject Error Object`);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught (in promise) Error: pumpkin`);
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with Error with custom name", () => {
|
|
const message = stubPreparedMessages.get(
|
|
`Promise reject Error Object with custom name`
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(`Uncaught (in promise) JuicyError: pineapple`);
|
|
});
|
|
|
|
it("renders uncaught rejected Promise with Error with cause", () => {
|
|
const message = stubPreparedMessages.get(
|
|
`Promise reject Error Object with error cause`
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const text = formatErrorTextWithCausedBy(
|
|
wrapper.find(".message-body").text()
|
|
);
|
|
expect(text).toBe(
|
|
[
|
|
`Uncaught (in promise) Error: something went wrong`,
|
|
`Caused by: ReferenceError: unknownFunc is not defined`,
|
|
].join("\n")
|
|
);
|
|
expect(wrapper.hasClass("error")).toBe(true);
|
|
});
|
|
|
|
it("renders URLs in message as actual, cropped, links", () => {
|
|
// Let's replace the packet data in order to mimick a pageError.
|
|
const packet = stubPackets.get("throw string with URL");
|
|
|
|
const evilDomain = `https://evil.com/?`;
|
|
const badDomain = `https://not-so-evil.com/?`;
|
|
const paramLength = 200;
|
|
const longParam = "a".repeat(paramLength);
|
|
|
|
const evilURL = `${evilDomain}${longParam}`;
|
|
const badURL = `${badDomain}${longParam}`;
|
|
|
|
// We remove the exceptionDocURL to not have the "learn more" link.
|
|
packet.pageError.exceptionDocURL = null;
|
|
|
|
const message = prepareMessage(packet, { getNextId: () => "1" });
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const text = wrapper.find(".message-body").text();
|
|
expect(text).toBe(
|
|
`Uncaught “${evilURL}“ is evil and “${badURL}“ is not good either`
|
|
);
|
|
|
|
// There should be 2 cropped links.
|
|
const links = wrapper.find(".message-body a.cropped-url");
|
|
expect(links.length).toBe(2);
|
|
|
|
expect(links.eq(0).attr("href")).toBe(evilURL);
|
|
expect(links.eq(0).attr("title")).toBe(evilURL);
|
|
|
|
expect(links.eq(1).attr("href")).toBe(badURL);
|
|
expect(links.eq(1).attr("title")).toBe(badURL);
|
|
});
|
|
|
|
it("displays a [Learn more] link", () => {
|
|
const store = setupStore();
|
|
|
|
const message = stubPreparedMessages.get(
|
|
"ReferenceError: asdf is not defined"
|
|
);
|
|
|
|
serviceContainer.openLink = sinon.spy();
|
|
const wrapper = mount(
|
|
Provider(
|
|
{ store },
|
|
PageError({
|
|
message,
|
|
serviceContainer,
|
|
dispatch: () => {},
|
|
})
|
|
)
|
|
);
|
|
|
|
// There should be a [Learn more] link.
|
|
const url =
|
|
"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined";
|
|
const learnMore = wrapper.find(".learn-more-link");
|
|
expect(learnMore.length).toBe(1);
|
|
expect(learnMore.prop("title")).toBe(url);
|
|
|
|
learnMore.simulate("click");
|
|
const call = serviceContainer.openLink.getCall(0);
|
|
expect(call.args[0]).toEqual(message.exceptionDocURL);
|
|
});
|
|
|
|
// Unskip will happen in Bug 1529548.
|
|
it.skip("has a stacktrace which can be opened", () => {
|
|
const message = stubPreparedMessages.get(
|
|
"ReferenceError: asdf is not defined"
|
|
);
|
|
const wrapper = render(
|
|
PageError({ message, serviceContainer, open: true })
|
|
);
|
|
|
|
// There should be a collapse button.
|
|
expect(wrapper.find(".collapse-button[aria-expanded=true]").length).toBe(1);
|
|
|
|
// There should be five stacktrace items.
|
|
const frameLinks = wrapper.find(`.stack-trace span.frame-link`);
|
|
expect(frameLinks.length).toBe(5);
|
|
});
|
|
|
|
// Unskip will happen in Bug 1529548.
|
|
it.skip("toggle the stacktrace when the collapse button is clicked", () => {
|
|
const store = setupStore();
|
|
store.dispatch = sinon.spy();
|
|
const message = stubPreparedMessages.get(
|
|
"ReferenceError: asdf is not defined"
|
|
);
|
|
|
|
let wrapper = mount(
|
|
Provider(
|
|
{ store },
|
|
PageError({
|
|
message,
|
|
open: true,
|
|
dispatch: store.dispatch,
|
|
serviceContainer,
|
|
})
|
|
)
|
|
);
|
|
|
|
wrapper.find(".collapse-button[aria-expanded='true']").simulate("click");
|
|
let call = store.dispatch.getCall(0);
|
|
expect(call.args[0]).toEqual({
|
|
id: message.id,
|
|
type: MESSAGE_CLOSE,
|
|
});
|
|
|
|
wrapper = mount(
|
|
Provider(
|
|
{ store },
|
|
PageError({
|
|
message,
|
|
open: false,
|
|
dispatch: store.dispatch,
|
|
serviceContainer,
|
|
})
|
|
)
|
|
);
|
|
wrapper.find(".collapse-button[aria-expanded='false']").simulate("click");
|
|
call = store.dispatch.getCall(1);
|
|
expect(call.args[0]).toEqual({
|
|
id: message.id,
|
|
type: MESSAGE_OPEN,
|
|
});
|
|
});
|
|
|
|
it("has the expected indent", () => {
|
|
const message = stubPreparedMessages.get(
|
|
"ReferenceError: asdf is not defined"
|
|
);
|
|
const indent = 10;
|
|
let wrapper = render(
|
|
PageError({
|
|
message: Object.assign({}, message, { indent }),
|
|
serviceContainer,
|
|
})
|
|
);
|
|
expect(wrapper.prop("data-indent")).toBe(`${indent}`);
|
|
const indentEl = wrapper.find(".indent");
|
|
expect(indentEl.prop("style").width).toBe(`${indent * INDENT_WIDTH}px`);
|
|
|
|
wrapper = render(PageError({ message, serviceContainer }));
|
|
expect(wrapper.prop("data-indent")).toBe(`0`);
|
|
// there's no indent element where the indent is 0
|
|
expect(wrapper.find(".indent").length).toBe(0);
|
|
});
|
|
|
|
it("has empty error notes", () => {
|
|
const message = stubPreparedMessages.get(
|
|
"ReferenceError: asdf is not defined"
|
|
);
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const notes = wrapper.find(".error-note");
|
|
|
|
expect(notes.length).toBe(0);
|
|
});
|
|
|
|
it("can show an error note", () => {
|
|
const origMessage = stubPreparedMessages.get(
|
|
"ReferenceError: asdf is not defined"
|
|
);
|
|
const message = Object.assign({}, origMessage, {
|
|
notes: [
|
|
{
|
|
messageBody: "test note",
|
|
frame: {
|
|
source: "https://example.com/test.js",
|
|
line: 2,
|
|
column: 6,
|
|
},
|
|
},
|
|
],
|
|
});
|
|
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const notes = wrapper.find(".error-note");
|
|
expect(notes.length).toBe(1);
|
|
|
|
const note = notes.eq(0);
|
|
expect(note.find(".message-body").text()).toBe("note: test note");
|
|
|
|
// There should be the location.
|
|
const locationLink = note.find(`.message-location`);
|
|
expect(locationLink.length).toBe(1);
|
|
expect(locationLink.text()).toBe("test.js:2:6");
|
|
});
|
|
|
|
it("can show multiple error notes", () => {
|
|
const origMessage = stubPreparedMessages.get(
|
|
"ReferenceError: asdf is not defined"
|
|
);
|
|
const message = Object.assign({}, origMessage, {
|
|
notes: [
|
|
{
|
|
messageBody: "test note 1",
|
|
frame: {
|
|
source: "https://example.com/test1.js",
|
|
line: 2,
|
|
column: 6,
|
|
},
|
|
},
|
|
{
|
|
messageBody: "test note 2",
|
|
frame: {
|
|
source: "https://example.com/test2.js",
|
|
line: 10,
|
|
column: 18,
|
|
},
|
|
},
|
|
{
|
|
messageBody: "test note 3",
|
|
frame: {
|
|
source: "https://example.com/test3.js",
|
|
line: 9,
|
|
column: 4,
|
|
},
|
|
},
|
|
],
|
|
});
|
|
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const notes = wrapper.find(".error-note");
|
|
expect(notes.length).toBe(3);
|
|
|
|
const note1 = notes.eq(0);
|
|
expect(note1.find(".message-body").text()).toBe("note: test note 1");
|
|
|
|
const locationLink1 = note1.find(`.message-location`);
|
|
expect(locationLink1.length).toBe(1);
|
|
expect(locationLink1.text()).toBe("test1.js:2:6");
|
|
|
|
const note2 = notes.eq(1);
|
|
expect(note2.find(".message-body").text()).toBe("note: test note 2");
|
|
|
|
const locationLink2 = note2.find(`.message-location`);
|
|
expect(locationLink2.length).toBe(1);
|
|
expect(locationLink2.text()).toBe("test2.js:10:18");
|
|
|
|
const note3 = notes.eq(2);
|
|
expect(note3.find(".message-body").text()).toBe("note: test note 3");
|
|
|
|
const locationLink3 = note3.find(`.message-location`);
|
|
expect(locationLink3.length).toBe(1);
|
|
expect(locationLink3.text()).toBe("test3.js:9:4");
|
|
});
|
|
|
|
it("displays error notes", () => {
|
|
const message = stubPreparedMessages.get(
|
|
"SyntaxError: redeclaration of let a"
|
|
);
|
|
|
|
const wrapper = render(PageError({ message, serviceContainer }));
|
|
|
|
const notes = wrapper.find(".error-note");
|
|
expect(notes.length).toBe(1);
|
|
|
|
const note = notes.eq(0);
|
|
expect(note.find(".message-body").text()).toBe(
|
|
"note: Previously declared at line 2, column 6"
|
|
);
|
|
|
|
// There should be the location.
|
|
const locationLink = note.find(`.message-location`);
|
|
expect(locationLink.length).toBe(1);
|
|
expect(locationLink.text()).toBe("test-console-api.html:2:6");
|
|
});
|
|
});
|