--- a/devtools/client/webconsole/new-console-output/components/GripMessageBody.js
+++ b/devtools/client/webconsole/new-console-output/components/GripMessageBody.js
@@ -1,129 +1,178 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
-/* 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/. */
-
-"use strict";
-
-// If this is being run from Mocha, then the browser loader hasn't set up
-// define. We need to do that before loading Rep.
-if (typeof define === "undefined") {
- require("amd-loader");
-}
-
-// React
-const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
-const {
- MESSAGE_TYPE,
- JSTERM_COMMANDS,
-} = require("../constants");
-const { getObjectInspector } = require("devtools/client/webconsole/new-console-output/utils/object-inspector");
-
-const reps = require("devtools/client/shared/components/reps/reps");
-const { MODE } = reps;
-
-GripMessageBody.displayName = "GripMessageBody";
-
-GripMessageBody.propTypes = {
- grip: PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- PropTypes.object,
- ]).isRequired,
- serviceContainer: PropTypes.shape({
- createElement: PropTypes.func.isRequired,
- hudProxy: PropTypes.object.isRequired,
- onViewSourceInDebugger: PropTypes.func.isRequired,
- }),
- userProvidedStyle: PropTypes.string,
- useQuotes: PropTypes.bool,
- escapeWhitespace: PropTypes.bool,
- type: PropTypes.string,
- helperType: PropTypes.string,
-};
-
-GripMessageBody.defaultProps = {
- mode: MODE.LONG,
-};
-
-function GripMessageBody(props) {
- const {
- grip,
- userProvidedStyle,
- serviceContainer,
- useQuotes,
- escapeWhitespace,
- mode = MODE.LONG,
- } = props;
-
- let styleObject;
- if (userProvidedStyle && userProvidedStyle !== "") {
- styleObject = cleanupStyle(userProvidedStyle, serviceContainer.createElement);
- }
-
- let objectInspectorProps = {
- autoExpandDepth: shouldAutoExpandObjectInspector(props) ? 1 : 0,
- mode,
- };
-
- if (typeof grip === "string" || (grip && grip.type === "longString")) {
- Object.assign(objectInspectorProps, {
- useQuotes,
- escapeWhitespace,
- style: styleObject
- });
- }
-
- return getObjectInspector(grip, serviceContainer, objectInspectorProps);
-}
-
-// Regular expression that matches the allowed CSS property names.
-const allowedStylesRegex = new RegExp(
- "^(?:-moz-)?(?:background|border|box|clear|color|cursor|display|float|font|line|" +
- "margin|padding|text|transition|outline|white-space|word|writing|" +
- "(?:min-|max-)?width|(?:min-|max-)?height)"
-);
-
-// Regular expression that matches the forbidden CSS property values.
-const forbiddenValuesRegexs = [
- // url(), -moz-element()
- /\b(?:url|(?:-moz-)?element)[\s('"]+/gi,
-
- // various URL protocols
- /['"(]*(?:chrome|resource|about|app|data|https?|ftp|file):+\/*/gi,
-];
-
-function cleanupStyle(userProvidedStyle, createElement) {
- // Use a dummy element to parse the style string.
- let dummy = createElement("div");
- dummy.style = userProvidedStyle;
-
- // Return a style object as expected by React DOM components, e.g.
- // {color: "red"}
- // without forbidden properties and values.
- return [...dummy.style]
- .filter(name => {
- return allowedStylesRegex.test(name)
- && !forbiddenValuesRegexs.some(regex => regex.test(dummy.style[name]));
- })
- .reduce((object, name) => {
- return Object.assign({
- [name]: dummy.style[name]
- }, object);
- }, {});
-}
-
-function shouldAutoExpandObjectInspector(props) {
- const {
- helperType,
- type,
- } = props;
-
- return (
- type === MESSAGE_TYPE.DIR
- || helperType === JSTERM_COMMANDS.INSPECT
- );
-}
-
-module.exports = GripMessageBody;
+Stud-snippets
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+"use strict";
+
+// If this is being run from Mocha, then the browser loader hasn't set up
+// define. We need to do that before loading Rep.
+if (typeof define === "undefined") {
+ require("amd-loader");
+}
+
+// React
+const {
+ createFactory,
+ PropTypes,
+} = require("devtools/client/shared/vendor/react");
+const ObjectClient = require("devtools/shared/client/object-client");
+const {
+ MESSAGE_TYPE,
+ JSTERM_COMMANDS,
+} = require("../constants");
+
+const reps = require("devtools/client/shared/components/reps/reps");
+const { REPS, MODE } = reps;
+const ObjectInspector = createFactory(reps.ObjectInspector);
+const { Grip } = REPS;
+
+GripMessageBody.displayName = "GripMessageBody";
+
+GripMessageBody.propTypes = {
+ grip: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.object,
+ ]).isRequired,
+ serviceContainer: PropTypes.shape({
+ createElement: PropTypes.func.isRequired,
+ hudProxy: PropTypes.object.isRequired,
+ }),
+ userProvidedStyle: PropTypes.string,
+ useQuotes: PropTypes.bool,
+ escapeWhitespace: PropTypes.bool,
+ type: PropTypes.string,
+ helperType: PropTypes.string,
+};
+
+GripMessageBody.defaultProps = {
+ mode: MODE.LONG,
+};
+
+function GripMessageBody(props) {
+ const {
+ grip,
+ userProvidedStyle,
+ serviceContainer,
+ useQuotes,
+ escapeWhitespace,
+ mode = MODE.LONG,
+ } = props;
+
+ let styleObject;
+ if (userProvidedStyle && userProvidedStyle !== "") {
+ styleObject = cleanupStyle(userProvidedStyle, serviceContainer.createElement);
+ }
+
+ let onDOMNodeMouseOver;
+ let onDOMNodeMouseOut;
+ let onInspectIconClick;
+ if (serviceContainer) {
+ onDOMNodeMouseOver = serviceContainer.highlightDomElement
+ ? (object) => serviceContainer.highlightDomElement(object)
+ : null;
+ onDOMNodeMouseOut = serviceContainer.unHighlightDomElement;
+ onInspectIconClick = serviceContainer.openNodeInInspector
+ ? (object, e) => {
+ // Stop the event propagation so we don't trigger ObjectInspector expand/collapse.
+ e.stopPropagation();
+ serviceContainer.openNodeInInspector(object);
+ }
+ : null;
+ }
+
+ const objectInspectorProps = {
+ // Auto-expand the ObjectInspector when the message is a console.dir one.
+ autoExpandDepth: shouldAutoExpandObjectInspector(props) ? 1 : 0,
+ mode,
+ // TODO: we disable focus since it's not currently working well in ObjectInspector.
+ // Let's remove the property below when problem are fixed in OI.
+ disabledFocus: true,
+ roots: [{
+ path: (grip && grip.actor) || JSON.stringify(grip),
+ contents: {
+ value: grip
+ }
+ }],
+ createObjectClient: object =>
+ new ObjectClient(serviceContainer.hudProxy.client, object),
+ releaseActor: actor => {
+ if (!actor || !serviceContainer.hudProxy.releaseActor) {
+ return;
+ }
+ serviceContainer.hudProxy.releaseActor(actor);
+ },
+ openLink: serviceContainer.openLink,
+ };
+
+ if (typeof grip === "string" || (grip && grip.type === "longString")) {
+ Object.assign(objectInspectorProps, {
+ useQuotes,
+ escapeWhitespace,
+ style: styleObject
+ });
+ } else {
+ Object.assign(objectInspectorProps, {
+ onDOMNodeMouseOver,
+ onDOMNodeMouseOut,
+ onInspectIconClick,
+ defaultRep: Grip,
+ });
+ }
+
+ return ObjectInspector(objectInspectorProps);
+}
+
+// Regular expression that matches the allowed CSS property names.
+const allowedStylesRegex = new RegExp(
+ "^(?:-moz-)?(?:background|border|box|clear|color|cursor|display|float|font|line|" +
+ "margin|padding|text|transition|outline|white-space|word|writing|" +
+ "(?:min-|max-)?width|(?:min-|max-)?height)"
+);
+
+// Regular expression that matches the forbidden CSS property values.
+const forbiddenValuesRegexs = [
+ // url(), -moz-element()
+ /\b(?:url|(?:-moz-)?element)[\s('"]+/gi,
+
+ // various URL protocols
+ /['"(]*(?:chrome|resource|about|app|data|https?|ftp|file):+\/*/gi,
+];
+
+function cleanupStyle(userProvidedStyle, createElement) {
+ // Use a dummy element to parse the style string.
+ let dummy = createElement("div");
+ dummy.style = userProvidedStyle;
+
+ const cssToIdlDictionnary = {
+ "line-height": "lineHeight"
+ };
+
+ return [...dummy.style]
+ .filter(name => {
+ return allowedStylesRegex.test(name)
+ && !forbiddenValuesRegexs.some(regex => regex.test(dummy.style[name]));
+ })
+ .reduce((object, name) => {
+ return Object.assign({
+ [cssToIdlDictionnary[name] || name]: dummy.style[name]
+ }, object);
+ }, {});
+}
+
+function shouldAutoExpandObjectInspector(props) {
+ const {
+ helperType,
+ type,
+ } = props;
+
+ return (
+ type === MESSAGE_TYPE.DIR
+ || helperType === JSTERM_COMMANDS.INSPECT
+ );
+}
+
+module.exports = GripMessageBody;
--- a/devtools/client/webconsole/new-console-output/test/components/console-api-call.test.js
+++ b/devtools/client/webconsole/new-console-output/test/components/console-api-call.test.js
@@ -1,343 +1,344 @@
-/* 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("devtools/client/shared/vendor/react");
-const Provider = createFactory(require("react-redux").Provider);
-const { setupStore } = require("devtools/client/webconsole/new-console-output/test/helpers");
-
-// Components under test.
-const ConsoleApiCall = createFactory(require("devtools/client/webconsole/new-console-output/components/message-types/ConsoleApiCall"));
-const {
- MESSAGE_OPEN,
- MESSAGE_CLOSE,
-} = require("devtools/client/webconsole/new-console-output/constants");
-const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/MessageIndent");
-
-// Test fakes.
-const { stubPreparedMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
-const serviceContainer = require("devtools/client/webconsole/new-console-output/test/fixtures/serviceContainer");
-
-describe("ConsoleAPICall component:", () => {
- describe("console.log", () => {
- it("renders string grips", () => {
- const message = stubPreparedMessages.get("console.log('foobar', 'test')");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- expect(wrapper.find(".message-body").text()).toBe("foobar test");
- expect(wrapper.find(".objectBox-string").length).toBe(2);
- let selector = "div.message.cm-s-mozilla span span.message-flex-body " +
- "span.message-body.devtools-monospace";
- expect(wrapper.find(selector).length).toBe(1);
-
- // There should be the location
- const locationLink = wrapper.find(`.message-location`);
- expect(locationLink.length).toBe(1);
- expect(locationLink.text()).toBe("test-console-api.html:1:27");
- });
-
- it("renders string grips with custom style", () => {
- const message = stubPreparedMessages.get("console.log(%cfoobar)");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- const elements = wrapper.find(".objectBox-string");
- expect(elements.text()).toBe("foobar");
- expect(elements.length).toBe(2);
-
- const firstElementStyle = elements.eq(0).prop("style");
- // Allowed styles are applied accordingly on the first element.
- expect(firstElementStyle.color).toBe(`blue`);
- expect(firstElementStyle["font-size"]).toBe(`1.3em`);
- // Forbidden styles are not applied.
- expect(firstElementStyle["background-image"]).toBe(undefined);
- expect(firstElementStyle.position).toBe(undefined);
- expect(firstElementStyle.top).toBe(undefined);
-
- const secondElementStyle = elements.eq(1).prop("style");
- // Allowed styles are applied accordingly on the second element.
- expect(secondElementStyle.color).toBe(`red`);
- // Forbidden styles are not applied.
- expect(secondElementStyle.background).toBe(undefined);
- });
-
- it("renders repeat node", () => {
- const message = stubPreparedMessages.get("console.log('foobar', 'test')");
- const wrapper = render(ConsoleApiCall({
- message,
- serviceContainer,
- repeat: 107
- }));
-
- expect(wrapper.find(".message-repeats").text()).toBe("107");
- expect(wrapper.find(".message-repeats").prop("title")).toBe("107 repeats");
-
- let selector = "span > span.message-flex-body > " +
- "span.message-body.devtools-monospace + span.message-repeats";
- expect(wrapper.find(selector).length).toBe(1);
- });
-
- it("has the expected indent", () => {
- const message = stubPreparedMessages.get("console.log('foobar', 'test')");
-
- const indent = 10;
- let wrapper = render(ConsoleApiCall({
- message: Object.assign({}, message, {indent}),
- serviceContainer
- }));
- let indentEl = wrapper.find(".indent");
- expect(indentEl.prop("style").width).toBe(`${indent * INDENT_WIDTH}px`);
- expect(indentEl.prop("data-indent")).toBe(`${indent}`);
-
- wrapper = render(ConsoleApiCall({ message, serviceContainer}));
- indentEl = wrapper.find(".indent");
- expect(indentEl.prop("style").width).toBe(`0`);
- expect(indentEl.prop("data-indent")).toBe(`0`);
- });
-
- it("renders a timestamp when passed a truthy timestampsVisible prop", () => {
- const message = stubPreparedMessages.get("console.log('foobar', 'test')");
- const wrapper = render(ConsoleApiCall({
- message,
- serviceContainer,
- timestampsVisible: true,
- }));
- const { timestampString } = require("devtools/client/webconsole/webconsole-l10n");
-
- expect(wrapper.find(".timestamp").text()).toBe(timestampString(message.timeStamp));
- });
-
- it("does not render a timestamp when not asked to", () => {
- const message = stubPreparedMessages.get("console.log('foobar', 'test')");
- const wrapper = render(ConsoleApiCall({
- message,
- serviceContainer,
- }));
-
- expect(wrapper.find(".timestamp").length).toBe(0);
- });
- });
-
- describe("console.count", () => {
- it("renders", () => {
- const message = stubPreparedMessages.get("console.count('bar')");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- expect(wrapper.find(".message-body").text()).toBe("bar: 1");
- });
- });
-
- describe("console.assert", () => {
- it("renders", () => {
- const message = stubPreparedMessages.get(
- "console.assert(false, {message: 'foobar'})");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- expect(wrapper.find(".message-body").text())
- .toBe("Assertion failed: Object { message: \"foobar\" }");
- });
- });
-
- describe("console.time", () => {
- it("does not show anything", () => {
- const message = stubPreparedMessages.get("console.time('bar')");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- expect(wrapper.find(".message-body").text()).toBe("");
- });
- it("shows an error if called again", () => {
- const message = stubPreparedMessages.get("timerAlreadyExists");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- expect(wrapper.find(".message-body").text()).toBe("Timer “bar” already exists.");
- });
- });
-
- describe("console.timeEnd", () => {
- it("renders as expected", () => {
- const message = stubPreparedMessages.get("console.timeEnd('bar')");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- expect(wrapper.find(".message-body").text()).toBe(message.messageText);
- expect(wrapper.find(".message-body").text()).toMatch(/^bar: \d+(\.\d+)?ms$/);
- });
- it("shows an error if the timer doesn't exist", () => {
- const message = stubPreparedMessages.get("timerDoesntExist");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- expect(wrapper.find(".message-body").text()).toBe("Timer “bar” doesn’t exist.");
- });
- });
-
- describe("console.trace", () => {
- it("renders", () => {
- const message = stubPreparedMessages.get("console.trace()");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: true }));
- const filepath = "http://example.com/browser/devtools/client/webconsole/" +
- "new-console-output/test/fixtures/stub-generators/" +
- "test-console-api.html";
-
- expect(wrapper.find(".message-body").text()).toBe("console.trace()");
-
- const frameLinks = wrapper.find(
- `.stack-trace span.frame-link[data-url]`);
- expect(frameLinks.length).toBe(3);
-
- expect(frameLinks.eq(0).find(".frame-link-function-display-name").text())
- .toBe("testStacktraceFiltering");
- expect(frameLinks.eq(0).find(".frame-link-filename").text())
- .toBe(filepath);
-
- expect(frameLinks.eq(1).find(".frame-link-function-display-name").text())
- .toBe("foo");
- expect(frameLinks.eq(1).find(".frame-link-filename").text())
- .toBe(filepath);
-
- expect(frameLinks.eq(2).find(".frame-link-function-display-name").text())
- .toBe("triggerPacket");
- expect(frameLinks.eq(2).find(".frame-link-filename").text())
- .toBe(filepath);
-
- // it should not be collapsible.
- expect(wrapper.find(`.theme-twisty`).length).toBe(0);
- });
- });
-
- describe("console.group", () => {
- it("renders", () => {
- const message = stubPreparedMessages.get("console.group('bar')");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: true }));
-
- expect(wrapper.find(".message-body").text()).toBe("bar");
- expect(wrapper.find(".theme-twisty.open").length).toBe(1);
- });
-
- it("renders group with custom style", () => {
- const message = stubPreparedMessages.get("console.group(%cfoo%cbar)");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
- expect(wrapper.find(".message-body").text()).toBe("foobar");
-
- const elements = wrapper.find(".objectBox-string");
- expect(elements.length).toBe(2);
-
- const firstElementStyle = elements.eq(0).prop("style");
- // Allowed styles are applied accordingly on the first element.
- expect(firstElementStyle.color).toBe(`blue`);
- expect(firstElementStyle["font-size"]).toBe(`1.3em`);
- // Forbidden styles are not applied.
- expect(firstElementStyle["background-image"]).toBe(undefined);
- expect(firstElementStyle.position).toBe(undefined);
- expect(firstElementStyle.top).toBe(undefined);
-
- const secondElementStyle = elements.eq(1).prop("style");
- // Allowed styles are applied accordingly on the second element.
- expect(secondElementStyle.color).toBe(`red`);
- // Forbidden styles are not applied.
- expect(secondElementStyle.background).toBe(undefined);
- });
-
- it("toggle the group when the collapse button is clicked", () => {
- const store = setupStore([]);
- store.dispatch = sinon.spy();
- const message = stubPreparedMessages.get("console.group('bar')");
-
- let wrapper = mount(Provider({store},
- ConsoleApiCall({
- message,
- open: true,
- dispatch: store.dispatch,
- serviceContainer,
- })
- ));
- wrapper.find(".theme-twisty.open").simulate("click");
- let call = store.dispatch.getCall(0);
- expect(call.args[0]).toEqual({
- id: message.id,
- type: MESSAGE_CLOSE
- });
-
- wrapper = mount(Provider({store},
- ConsoleApiCall({
- message,
- open: false,
- dispatch: store.dispatch,
- serviceContainer,
- })
- ));
- wrapper.find(".theme-twisty").simulate("click");
- call = store.dispatch.getCall(1);
- expect(call.args[0]).toEqual({
- id: message.id,
- type: MESSAGE_OPEN
- });
- });
- });
-
- describe("console.groupEnd", () => {
- it("does not show anything", () => {
- const message = stubPreparedMessages.get("console.groupEnd('bar')");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- expect(wrapper.find(".message-body").text()).toBe("");
- });
- });
-
- describe("console.groupCollapsed", () => {
- it("renders", () => {
- const message = stubPreparedMessages.get("console.groupCollapsed('foo')");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: false}));
-
- expect(wrapper.find(".message-body").text()).toBe("foo");
- expect(wrapper.find(".theme-twisty:not(.open)").length).toBe(1);
- });
-
- it("renders group with custom style", () => {
- const message = stubPreparedMessages.get("console.groupCollapsed(%cfoo%cbaz)");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- const elements = wrapper.find(".objectBox-string");
- expect(elements.text()).toBe("foobaz");
- expect(elements.length).toBe(2);
-
- const firstElementStyle = elements.eq(0).prop("style");
- // Allowed styles are applied accordingly on the first element.
- expect(firstElementStyle.color).toBe(`blue`);
- expect(firstElementStyle["font-size"]).toBe(`1.3em`);
- // Forbidden styles are not applied.
- expect(firstElementStyle["background-image"]).toBe(undefined);
- expect(firstElementStyle.position).toBe(undefined);
- expect(firstElementStyle.top).toBe(undefined);
-
- const secondElementStyle = elements.eq(1).prop("style");
- // Allowed styles are applied accordingly on the second element.
- expect(secondElementStyle.color).toBe(`red`);
- // Forbidden styles are not applied.
- expect(secondElementStyle.background).toBe(undefined);
- });
- });
-
- describe("console.dirxml", () => {
- it("renders", () => {
- const message = stubPreparedMessages.get("console.dirxml(window)");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- expect(wrapper.find(".message-body").text())
- .toBe("Window http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html");
- });
- });
-
- describe("console.dir", () => {
- it("renders", () => {
- const message = stubPreparedMessages.get("console.dir({C, M, Y, K})");
- const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
-
- expect(wrapper.find(".message-body").text())
- .toBe(`Object { cyan: "C", magenta: "M", yellow: "Y", black: "K" }`);
- });
- });
-});
+/* 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("devtools/client/shared/vendor/react");
+const Provider = createFactory(require("react-redux").Provider);
+const { setupStore } = require("devtools/client/webconsole/new-console-output/test/helpers");
+
+// Components under test.
+const ConsoleApiCall = createFactory(require("devtools/client/webconsole/new-console-output/components/message-types/ConsoleApiCall"));
+const {
+ MESSAGE_OPEN,
+ MESSAGE_CLOSE,
+} = require("devtools/client/webconsole/new-console-output/constants");
+const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/MessageIndent");
+
+// Test fakes.
+const { stubPreparedMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
+const serviceContainer = require("devtools/client/webconsole/new-console-output/test/fixtures/serviceContainer");
+
+describe("ConsoleAPICall component:", () => {
+ describe("console.log", () => {
+ it("renders string grips", () => {
+ const message = stubPreparedMessages.get("console.log('foobar', 'test')");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ expect(wrapper.find(".message-body").text()).toBe("foobar test");
+ expect(wrapper.find(".objectBox-string").length).toBe(2);
+ let selector = "div.message.cm-s-mozilla span span.message-flex-body " +
+ "span.message-body.devtools-monospace";
+ expect(wrapper.find(selector).length).toBe(1);
+
+ // There should be the location
+ const locationLink = wrapper.find(`.message-location`);
+ expect(locationLink.length).toBe(1);
+ expect(locationLink.text()).toBe("test-console-api.html:1:27");
+ });
+
+ it("renders string grips with custom style", () => {
+ const message = stubPreparedMessages.get("console.log(%cfoobar)");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ const elements = wrapper.find(".objectBox-string");
+ expect(elements.text()).toBe("foobar");
+ expect(elements.length).toBe(2);
+
+ const firstElementStyle = elements.eq(0).prop("style");
+ // Allowed styles are applied accordingly on the first element.
+ expect(firstElementStyle.color).toBe(`blue`);
+ expect(firstElementStyle["font-size"]).toBe(`1.3em`);
+ // Forbidden styles are not applied.
+ expect(firstElementStyle["background-image"]).toBe(undefined);
+ expect(firstElementStyle.position).toBe(undefined);
+ expect(firstElementStyle.top).toBe(undefined);
+
+ const secondElementStyle = elements.eq(1).prop("style");
+ // Allowed styles are applied accordingly on the second element.
+ expect(secondElementStyle.color).toBe(`red`);
+ expect(secondElementStyle.lineHeight).toBe(1.5);
+ // Forbidden styles are not applied.
+ expect(secondElementStyle.background).toBe(undefined);
+ });
+
+ it("renders repeat node", () => {
+ const message = stubPreparedMessages.get("console.log('foobar', 'test')");
+ const wrapper = render(ConsoleApiCall({
+ message,
+ serviceContainer,
+ repeat: 107
+ }));
+
+ expect(wrapper.find(".message-repeats").text()).toBe("107");
+ expect(wrapper.find(".message-repeats").prop("title")).toBe("107 repeats");
+
+ let selector = "span > span.message-flex-body > " +
+ "span.message-body.devtools-monospace + span.message-repeats";
+ expect(wrapper.find(selector).length).toBe(1);
+ });
+
+ it("has the expected indent", () => {
+ const message = stubPreparedMessages.get("console.log('foobar', 'test')");
+
+ const indent = 10;
+ let wrapper = render(ConsoleApiCall({
+ message: Object.assign({}, message, {indent}),
+ serviceContainer
+ }));
+ let indentEl = wrapper.find(".indent");
+ expect(indentEl.prop("style").width).toBe(`${indent * INDENT_WIDTH}px`);
+ expect(indentEl.prop("data-indent")).toBe(`${indent}`);
+
+ wrapper = render(ConsoleApiCall({ message, serviceContainer}));
+ indentEl = wrapper.find(".indent");
+ expect(indentEl.prop("style").width).toBe(`0`);
+ expect(indentEl.prop("data-indent")).toBe(`0`);
+ });
+
+ it("renders a timestamp when passed a truthy timestampsVisible prop", () => {
+ const message = stubPreparedMessages.get("console.log('foobar', 'test')");
+ const wrapper = render(ConsoleApiCall({
+ message,
+ serviceContainer,
+ timestampsVisible: true,
+ }));
+ const { timestampString } = require("devtools/client/webconsole/webconsole-l10n");
+
+ expect(wrapper.find(".timestamp").text()).toBe(timestampString(message.timeStamp));
+ });
+
+ it("does not render a timestamp when not asked to", () => {
+ const message = stubPreparedMessages.get("console.log('foobar', 'test')");
+ const wrapper = render(ConsoleApiCall({
+ message,
+ serviceContainer,
+ }));
+
+ expect(wrapper.find(".timestamp").length).toBe(0);
+ });
+ });
+
+ describe("console.count", () => {
+ it("renders", () => {
+ const message = stubPreparedMessages.get("console.count('bar')");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ expect(wrapper.find(".message-body").text()).toBe("bar: 1");
+ });
+ });
+
+ describe("console.assert", () => {
+ it("renders", () => {
+ const message = stubPreparedMessages.get(
+ "console.assert(false, {message: 'foobar'})");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ expect(wrapper.find(".message-body").text())
+ .toBe("Assertion failed: Object { message: \"foobar\" }");
+ });
+ });
+
+ describe("console.time", () => {
+ it("does not show anything", () => {
+ const message = stubPreparedMessages.get("console.time('bar')");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ expect(wrapper.find(".message-body").text()).toBe("");
+ });
+ it("shows an error if called again", () => {
+ const message = stubPreparedMessages.get("timerAlreadyExists");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ expect(wrapper.find(".message-body").text()).toBe("Timer “bar” already exists.");
+ });
+ });
+
+ describe("console.timeEnd", () => {
+ it("renders as expected", () => {
+ const message = stubPreparedMessages.get("console.timeEnd('bar')");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ expect(wrapper.find(".message-body").text()).toBe(message.messageText);
+ expect(wrapper.find(".message-body").text()).toMatch(/^bar: \d+(\.\d+)?ms$/);
+ });
+ it("shows an error if the timer doesn't exist", () => {
+ const message = stubPreparedMessages.get("timerDoesntExist");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ expect(wrapper.find(".message-body").text()).toBe("Timer “bar” doesn’t exist.");
+ });
+ });
+
+ describe("console.trace", () => {
+ it("renders", () => {
+ const message = stubPreparedMessages.get("console.trace()");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: true }));
+ const filepath = "http://example.com/browser/devtools/client/webconsole/" +
+ "new-console-output/test/fixtures/stub-generators/" +
+ "test-console-api.html";
+
+ expect(wrapper.find(".message-body").text()).toBe("console.trace()");
+
+ const frameLinks = wrapper.find(
+ `.stack-trace span.frame-link[data-url]`);
+ expect(frameLinks.length).toBe(3);
+
+ expect(frameLinks.eq(0).find(".frame-link-function-display-name").text())
+ .toBe("testStacktraceFiltering");
+ expect(frameLinks.eq(0).find(".frame-link-filename").text())
+ .toBe(filepath);
+
+ expect(frameLinks.eq(1).find(".frame-link-function-display-name").text())
+ .toBe("foo");
+ expect(frameLinks.eq(1).find(".frame-link-filename").text())
+ .toBe(filepath);
+
+ expect(frameLinks.eq(2).find(".frame-link-function-display-name").text())
+ .toBe("triggerPacket");
+ expect(frameLinks.eq(2).find(".frame-link-filename").text())
+ .toBe(filepath);
+
+ // it should not be collapsible.
+ expect(wrapper.find(`.theme-twisty`).length).toBe(0);
+ });
+ });
+
+ describe("console.group", () => {
+ it("renders", () => {
+ const message = stubPreparedMessages.get("console.group('bar')");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: true }));
+
+ expect(wrapper.find(".message-body").text()).toBe("bar");
+ expect(wrapper.find(".theme-twisty.open").length).toBe(1);
+ });
+
+ it("renders group with custom style", () => {
+ const message = stubPreparedMessages.get("console.group(%cfoo%cbar)");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ const elements = wrapper.find(".objectBox-string");
+ expect(elements.text()).toBe("foobar");
+ expect(elements.length).toBe(2);
+
+ const firstElementStyle = elements.eq(0).prop("style");
+ // Allowed styles are applied accordingly on the first element.
+ expect(firstElementStyle.color).toBe(`blue`);
+ expect(firstElementStyle["font-size"]).toBe(`1.3em`);
+ // Forbidden styles are not applied.
+ expect(firstElementStyle["background-image"]).toBe(undefined);
+ expect(firstElementStyle.position).toBe(undefined);
+ expect(firstElementStyle.top).toBe(undefined);
+
+ const secondElementStyle = elements.eq(1).prop("style");
+ // Allowed styles are applied accordingly on the second element.
+ expect(secondElementStyle.color).toBe(`red`);
+ // Forbidden styles are not applied.
+ expect(secondElementStyle.background).toBe(undefined);
+ });
+
+ it("toggle the group when the collapse button is clicked", () => {
+ const store = setupStore([]);
+ store.dispatch = sinon.spy();
+ const message = stubPreparedMessages.get("console.group('bar')");
+
+ let wrapper = mount(Provider({store},
+ ConsoleApiCall({
+ message,
+ open: true,
+ dispatch: store.dispatch,
+ serviceContainer,
+ })
+ ));
+ wrapper.find(".theme-twisty.open").simulate("click");
+ let call = store.dispatch.getCall(0);
+ expect(call.args[0]).toEqual({
+ id: message.id,
+ type: MESSAGE_CLOSE
+ });
+
+ wrapper = mount(Provider({store},
+ ConsoleApiCall({
+ message,
+ open: false,
+ dispatch: store.dispatch,
+ serviceContainer,
+ })
+ ));
+ wrapper.find(".theme-twisty").simulate("click");
+ call = store.dispatch.getCall(1);
+ expect(call.args[0]).toEqual({
+ id: message.id,
+ type: MESSAGE_OPEN
+ });
+ });
+ });
+
+ describe("console.groupEnd", () => {
+ it("does not show anything", () => {
+ const message = stubPreparedMessages.get("console.groupEnd('bar')");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ expect(wrapper.find(".message-body").text()).toBe("");
+ });
+ });
+
+ describe("console.groupCollapsed", () => {
+ it("renders", () => {
+ const message = stubPreparedMessages.get("console.groupCollapsed('foo')");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: false}));
+
+ expect(wrapper.find(".message-body").text()).toBe("foo");
+ expect(wrapper.find(".theme-twisty:not(.open)").length).toBe(1);
+ });
+
+ it("renders group with custom style", () => {
+ const message = stubPreparedMessages.get("console.groupCollapsed(%cfoo%cbaz)");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ const elements = wrapper.find(".objectBox-string");
+ expect(elements.text()).toBe("foobaz");
+ expect(elements.length).toBe(2);
+
+ const firstElementStyle = elements.eq(0).prop("style");
+ // Allowed styles are applied accordingly on the first element.
+ expect(firstElementStyle.color).toBe(`blue`);
+ expect(firstElementStyle["font-size"]).toBe(`1.3em`);
+ // Forbidden styles are not applied.
+ expect(firstElementStyle["background-image"]).toBe(undefined);
+ expect(firstElementStyle.position).toBe(undefined);
+ expect(firstElementStyle.top).toBe(undefined);
+
+ const secondElementStyle = elements.eq(1).prop("style");
+ // Allowed styles are applied accordingly on the second element.
+ expect(secondElementStyle.color).toBe(`red`);
+ // Forbidden styles are not applied.
+ expect(secondElementStyle.background).toBe(undefined);
+ });
+ });
+
+ describe("console.dirxml", () => {
+ it("renders", () => {
+ const message = stubPreparedMessages.get("console.dirxml(window)");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ expect(wrapper.find(".message-body").text())
+ .toBe("Window http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html");
+ });
+ });
+
+ describe("console.dir", () => {
+ it("renders", () => {
+ const message = stubPreparedMessages.get("console.dir({C, M, Y, K})");
+ const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
+
+ expect(wrapper.find(".message-body").text())
+ .toBe(`Object { cyan: "C", magenta: "M", yellow: "Y", black: "K" }`);
+ });
+ });
+});
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/stub-snippets.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/stub-snippets.js
@@ -1,221 +1,226 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Console API
-
-const consoleApiCommands = [
- "console.log('foobar', 'test')",
- "console.log(undefined)",
- "console.warn('danger, will robinson!')",
- "console.log(NaN)",
- "console.log(null)",
- "console.log('\u9f2c')",
- "console.clear()",
- "console.count('bar')",
- "console.assert(false, {message: 'foobar'})",
- "console.log('hello \\nfrom \\rthe \\\"string world!')",
- "console.log('\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165')",
- "console.dirxml(window)",
- "console.log('myarray', ['red', 'green', 'blue'])",
- "console.log('myregex', /a.b.c/)",
- "console.table(['red', 'green', 'blue']);",
- "console.log('myobject', {red: 'redValue', green: 'greenValue', blue: 'blueValue'});",
- "console.debug('debug message');",
- "console.info('info message');",
- "console.error('error message');",
-];
-
-let consoleApi = new Map(consoleApiCommands.map(
- cmd => [cmd, {keys: [cmd], code: cmd}]));
-
-consoleApi.set("console.log('mymap')", {
- keys: ["console.log('mymap')"],
- code: `
-var map = new Map();
-map.set("key1", "value1");
-map.set("key2", "value2");
-console.log('mymap', map);
-`});
-
-consoleApi.set("console.log('myset')", {
- keys: ["console.log('myset')"],
- code: `
-console.log('myset', new Set(["a", "b"]));
-`});
-
-consoleApi.set("console.trace()", {
- keys: ["console.trace()"],
- code: `
-function testStacktraceFiltering() {
- console.trace()
-}
-function foo() {
- testStacktraceFiltering()
-}
-
-foo()
-`});
-
-consoleApi.set("console.time('bar')", {
- keys: ["console.time('bar')", "timerAlreadyExists",
- "console.timeEnd('bar')", "timerDoesntExist"],
- code: `
-console.time("bar");
-console.time("bar");
-console.timeEnd("bar");
-console.timeEnd("bar");
-`});
-
-consoleApi.set("console.table('bar')", {
- keys: ["console.table('bar')"],
- code: `
-console.table('bar');
-`});
-
-consoleApi.set("console.table(['a', 'b', 'c'])", {
- keys: ["console.table(['a', 'b', 'c'])"],
- code: `
-console.table(['a', 'b', 'c']);
-`});
-
-consoleApi.set("console.group('bar')", {
- keys: ["console.group('bar')", "console.groupEnd('bar')"],
- code: `
-console.group("bar");
-console.groupEnd();
-`});
-
-consoleApi.set("console.groupCollapsed('foo')", {
- keys: ["console.groupCollapsed('foo')", "console.groupEnd('foo')"],
- code: `
-console.groupCollapsed("foo");
-console.groupEnd();
-`});
-
-consoleApi.set("console.group()", {
- keys: ["console.group()", "console.groupEnd()"],
- code: `
-console.group();
-console.groupEnd();
-`});
-
-consoleApi.set("console.log(%cfoobar)", {
- keys: ["console.log(%cfoobar)"],
- code: `
-console.log(
- "%cfoo%cbar",
- "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
- "color:red;background:\\165rl('http://example.com/test')");
-`});
-
-consoleApi.set("console.group(%cfoo%cbar)", {
- keys: ["console.group(%cfoo%cbar)", "console.groupEnd(%cfoo%cbar)"],
- code: `
-console.group(
- "%cfoo%cbar",
- "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
- "color:red;background:\\165rl('http://example.com/test')");
-console.groupEnd();
-`});
-
-consoleApi.set("console.groupCollapsed(%cfoo%cbaz)", {
- keys: ["console.groupCollapsed(%cfoo%cbaz)", "console.groupEnd(%cfoo%cbaz)"],
- code: `
-console.groupCollapsed(
- "%cfoo%cbaz",
- "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
- "color:red;background:\\165rl('http://example.com/test')");
-console.groupEnd();
-`});
-
-consoleApi.set("console.dir({C, M, Y, K})", {
- keys: ["console.dir({C, M, Y, K})"],
- code: "console.dir({cyan: 'C', magenta: 'M', yellow: 'Y', black: 'K'});"
-});
-
-// CSS messages
-const cssMessage = new Map();
-
-cssMessage.set("Unknown property", `
-p {
- such-unknown-property: wow;
-}
-`);
-
-cssMessage.set("Invalid property value", `
-p {
- padding-top: invalid value;
-}
-`);
-
-// Evaluation Result
-const evaluationResultCommands = [
- "new Date(0)",
- "asdf()",
- "1 + @",
- "inspect({a: 1})",
- "cd(document)"
-];
-
-let evaluationResult = new Map(evaluationResultCommands.map(cmd => [cmd, cmd]));
-evaluationResult.set("longString message Error",
- `throw new Error("Long error ".repeat(10000))`);
-
-// Network Event
-
-let networkEvent = new Map();
-
-networkEvent.set("GET request", {
- keys: ["GET request"],
- code: `
-let i = document.createElement("img");
-i.src = "inexistent.html";
-`});
-
-networkEvent.set("XHR GET request", {
- keys: ["XHR GET request"],
- code: `
-const xhr = new XMLHttpRequest();
-xhr.open("GET", "inexistent.html");
-xhr.send();
-`});
-
-networkEvent.set("XHR POST request", {
- keys: ["XHR POST request"],
- code: `
-const xhr = new XMLHttpRequest();
-xhr.open("POST", "inexistent.html");
-xhr.send();
-`});
-
-// Page Error
-
-let pageError = new Map();
-
-pageError.set("ReferenceError: asdf is not defined", `
- function bar() {
- asdf()
- }
- function foo() {
- bar()
- }
-
- foo()
-`);
-
-pageError.set("SyntaxError: redeclaration of let a", `
- let a, a;
-`);
-
-pageError.set("TypeError longString message",
- `throw new Error("Long error ".repeat(10000))`);
-
-module.exports = {
- consoleApi,
- cssMessage,
- evaluationResult,
- networkEvent,
- pageError,
-};
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Console API
+
+const consoleApiCommands = [
+ "console.log('foobar', 'test')",
+ "console.log(undefined)",
+ "console.warn('danger, will robinson!')",
+ "console.log(NaN)",
+ "console.log(null)",
+ "console.log('\u9f2c')",
+ "console.clear()",
+ "console.count('bar')",
+ "console.assert(false, {message: 'foobar'})",
+ "console.log('hello \\nfrom \\rthe \\\"string world!')",
+ "console.log('\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165')",
+ "console.dirxml(window)",
+ "console.log('myarray', ['red', 'green', 'blue'])",
+ "console.log('myregex', /a.b.c/)",
+ "console.table(['red', 'green', 'blue']);",
+ "console.log('myobject', {red: 'redValue', green: 'greenValue', blue: 'blueValue'});",
+ "console.debug('debug message');",
+ "console.info('info message');",
+ "console.error('error message');",
+];
+
+let consoleApi = new Map(consoleApiCommands.map(
+ cmd => [cmd, {keys: [cmd], code: cmd}]));
+
+consoleApi.set("console.log('mymap')", {
+ keys: ["console.log('mymap')"],
+ code: `
+var map = new Map();
+map.set("key1", "value1");
+map.set("key2", "value2");
+console.log('mymap', map);
+`});
+
+consoleApi.set("console.log('myset')", {
+ keys: ["console.log('myset')"],
+ code: `
+console.log('myset', new Set(["a", "b"]));
+`});
+
+consoleApi.set("console.trace()", {
+ keys: ["console.trace()"],
+ code: `
+function testStacktraceFiltering() {
+ console.trace()
+}
+function foo() {
+ testStacktraceFiltering()
+}
+
+foo()
+`});
+
+consoleApi.set("console.time('bar')", {
+ keys: ["console.time('bar')", "timerAlreadyExists",
+ "console.timeEnd('bar')", "timerDoesntExist"],
+ code: `
+console.time("bar");
+console.time("bar");
+console.timeEnd("bar");
+console.timeEnd("bar");
+`});
+
+consoleApi.set("console.table('bar')", {
+ keys: ["console.table('bar')"],
+ code: `
+console.table('bar');
+`});
+
+consoleApi.set("console.table(['a', 'b', 'c'])", {
+ keys: ["console.table(['a', 'b', 'c'])"],
+ code: `
+console.table(['a', 'b', 'c']);
+`});
+
+consoleApi.set("console.group('bar')", {
+ keys: ["console.group('bar')", "console.groupEnd('bar')"],
+ code: `
+console.group("bar");
+console.groupEnd();
+`});
+
+consoleApi.set("console.groupCollapsed('foo')", {
+ keys: ["console.groupCollapsed('foo')", "console.groupEnd('foo')"],
+ code: `
+console.groupCollapsed("foo");
+console.groupEnd();
+`});
+
+consoleApi.set("console.group()", {
+ keys: ["console.group()", "console.groupEnd()"],
+ code: `
+console.group();
+console.groupEnd();
+`});
+
+consoleApi.set("console.log(%cfoobar)", {
+ keys: ["console.log(%cfoobar)"],
+ code: `
+console.log(
+ "%cfoo%cbar",
+ "color:blue;
+ font-size:1.3em;
+ background:url('http://example.com/test');
+ position:absolute;
+ top:10px",
+ "color:red;
+ line-height: 1.5;
+ background:\\165rl('http://example.com/test')"),
+`});
+
+consoleApi.set("console.group(%cfoo%cbar)", {
+ keys: ["console.group(%cfoo%cbar)", "console.groupEnd(%cfoo%cbar)"],
+ code: `
+console.group(
+ "%cfoo%cbar",
+ "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
+ "color:red;background:\\165rl('http://example.com/test')");
+console.groupEnd();
+`});
+
+consoleApi.set("console.groupCollapsed(%cfoo%cbaz)", {
+ keys: ["console.groupCollapsed(%cfoo%cbaz)", "console.groupEnd(%cfoo%cbaz)"],
+ code: `
+console.groupCollapsed(
+ "%cfoo%cbaz",
+ "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
+ "color:red;background:\\165rl('http://example.com/test')");
+console.groupEnd();
+`});
+
+consoleApi.set("console.dir({C, M, Y, K})", {
+ keys: ["console.dir({C, M, Y, K})"],
+ code: "console.dir({cyan: 'C', magenta: 'M', yellow: 'Y', black: 'K'});"
+});
+
+// CSS messages
+const cssMessage = new Map();
+
+cssMessage.set("Unknown property", `
+p {
+ such-unknown-property: wow;
+}
+`);
+
+cssMessage.set("Invalid property value", `
+p {
+ padding-top: invalid value;
+}
+`);
+
+// Evaluation Result
+const evaluationResultCommands = [
+ "new Date(0)",
+ "asdf()",
+ "1 + @",
+ "inspect({a: 1})"
+];
+
+let evaluationResult = new Map(evaluationResultCommands.map(cmd => [cmd, cmd]));
+evaluationResult.set("longString message Error",
+ `throw new Error("Long error ".repeat(10000))`);
+
+// Network Event
+
+let networkEvent = new Map();
+
+networkEvent.set("GET request", {
+ keys: ["GET request"],
+ code: `
+let i = document.createElement("img");
+i.src = "inexistent.html";
+`});
+
+networkEvent.set("XHR GET request", {
+ keys: ["XHR GET request"],
+ code: `
+const xhr = new XMLHttpRequest();
+xhr.open("GET", "inexistent.html");
+xhr.send();
+`});
+
+networkEvent.set("XHR POST request", {
+ keys: ["XHR POST request"],
+ code: `
+const xhr = new XMLHttpRequest();
+xhr.open("POST", "inexistent.html");
+xhr.send();
+`});
+
+// Page Error
+
+let pageError = new Map();
+
+pageError.set("ReferenceError: asdf is not defined", `
+ function bar() {
+ asdf()
+ }
+ function foo() {
+ bar()
+ }
+
+ foo()
+`);
+
+pageError.set("SyntaxError: redeclaration of let a", `
+ let a, a;
+`);
+
+pageError.set("TypeError longString message",
+ `throw new Error("Long error ".repeat(10000))`);
+
+module.exports = {
+ consoleApi,
+ cssMessage,
+ evaluationResult,
+ networkEvent,
+ pageError,
+};