diff options
Diffstat (limited to 'devtools/client/webconsole/new-console-output/test/components')
9 files changed, 746 insertions, 0 deletions
diff --git 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 new file mode 100644 index 000000000..3b4e2b196 --- /dev/null +++ b/devtools/client/webconsole/new-console-output/test/components/console-api-call.test.js @@ -0,0 +1,230 @@ +/* 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/console-api-call")); +const { + MESSAGE_OPEN, + MESSAGE_CLOSE, +} = require("devtools/client/webconsole/new-console-output/constants"); +const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/message-indent"); + +// 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"); + +const tempfilePath = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js"; + +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); + expect(wrapper.find("div.message.cm-s-mozilla span span.message-flex-body span.message-body.devtools-monospace").length).toBe(1); + + // There should be the location + const locationLink = wrapper.find(`.message-location`); + expect(locationLink.length).toBe(1); + expect(locationLink.text()).toBe("test-tempfile.js: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')") + .set("repeat", 107); + const wrapper = render(ConsoleApiCall({ message, serviceContainer })); + + expect(wrapper.find(".message-repeats").text()).toBe("107"); + expect(wrapper.find(".message-repeats").prop("title")).toBe("107 repeats"); + + expect(wrapper.find("span > span.message-flex-body > span.message-body.devtools-monospace + span.message-repeats").length).toBe(1); + }); + + it("has the expected indent", () => { + const message = stubPreparedMessages.get("console.log('foobar', 'test')"); + + const indent = 10; + let wrapper = render(ConsoleApiCall({ message, serviceContainer, indent })); + expect(wrapper.find(".indent").prop("style").width) + .toBe(`${indent * INDENT_WIDTH}px`); + + wrapper = render(ConsoleApiCall({ message, serviceContainer})); + expect(wrapper.find(".indent").prop("style").width).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(""); + }); + }); + + 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$/); + }); + }); + + describe("console.trace", () => { + it("renders", () => { + const message = stubPreparedMessages.get("console.trace()"); + const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: true })); + const filepath = `${tempfilePath}`; + + expect(wrapper.find(".message-body").text()).toBe("console.trace()"); + + const frameLinks = wrapper.find(`.stack-trace span.frame-link[data-url='${filepath}']`); + 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(message.messageText); + expect(wrapper.find(".theme-twisty.open").length).toBe(1); + }); + + 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(message.messageText); + expect(wrapper.find(".theme-twisty:not(.open)").length).toBe(1); + }); + }); + + 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"); + }); + }); +}); diff --git a/devtools/client/webconsole/new-console-output/test/components/evaluation-result.test.js b/devtools/client/webconsole/new-console-output/test/components/evaluation-result.test.js new file mode 100644 index 000000000..4d7890807 --- /dev/null +++ b/devtools/client/webconsole/new-console-output/test/components/evaluation-result.test.js @@ -0,0 +1,84 @@ +/* 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 EvaluationResult = createFactory(require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result")); +const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/message-indent"); + +// 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("EvaluationResult component:", () => { + it("renders a grip result", () => { + const message = stubPreparedMessages.get("new Date(0)"); + const wrapper = render(EvaluationResult({ message })); + + expect(wrapper.find(".message-body").text()).toBe("Date 1970-01-01T00:00:00.000Z"); + + expect(wrapper.find(".message.log").length).toBe(1); + }); + + it("renders an error", () => { + const message = stubPreparedMessages.get("asdf()"); + const wrapper = render(EvaluationResult({ message })); + + expect(wrapper.find(".message-body").text()) + .toBe("ReferenceError: asdf is not defined[Learn More]"); + + expect(wrapper.find(".message.error").length).toBe(1); + }); + + it("displays a [Learn more] link", () => { + const store = setupStore([]); + + const message = stubPreparedMessages.get("asdf()"); + + serviceContainer.openLink = sinon.spy(); + const wrapper = mount(Provider({store}, + EvaluationResult({message, serviceContainer}) + )); + + 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"); + let call = serviceContainer.openLink.getCall(0); + expect(call.args[0]).toEqual(message.exceptionDocURL); + }); + + it("has the expected indent", () => { + const message = stubPreparedMessages.get("new Date(0)"); + + const indent = 10; + let wrapper = render(EvaluationResult({ message, indent})); + expect(wrapper.find(".indent").prop("style").width) + .toBe(`${indent * INDENT_WIDTH}px`); + + wrapper = render(EvaluationResult({ message})); + expect(wrapper.find(".indent").prop("style").width).toBe(`0`); + }); + + it("has location information", () => { + const message = stubPreparedMessages.get("1 + @"); + const wrapper = render(EvaluationResult({ message })); + + const locationLink = wrapper.find(`.message-location`); + expect(locationLink.length).toBe(1); + expect(locationLink.text()).toBe("debugger eval code:1:4"); + }); +}); diff --git a/devtools/client/webconsole/new-console-output/test/components/filter-bar.test.js b/devtools/client/webconsole/new-console-output/test/components/filter-bar.test.js new file mode 100644 index 000000000..23f958cd9 --- /dev/null +++ b/devtools/client/webconsole/new-console-output/test/components/filter-bar.test.js @@ -0,0 +1,96 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +const expect = require("expect"); +const sinon = require("sinon"); +const { render, mount } = require("enzyme"); + +const { createFactory } = require("devtools/client/shared/vendor/react"); +const Provider = createFactory(require("react-redux").Provider); + +const FilterButton = createFactory(require("devtools/client/webconsole/new-console-output/components/filter-button")); +const FilterBar = createFactory(require("devtools/client/webconsole/new-console-output/components/filter-bar")); +const { getAllUi } = require("devtools/client/webconsole/new-console-output/selectors/ui"); +const { + MESSAGES_CLEAR, + MESSAGE_LEVEL +} = require("devtools/client/webconsole/new-console-output/constants"); + +const { setupStore } = require("devtools/client/webconsole/new-console-output/test/helpers"); +const serviceContainer = require("devtools/client/webconsole/new-console-output/test/fixtures/serviceContainer"); + +describe("FilterBar component:", () => { + it("initial render", () => { + const store = setupStore([]); + + const wrapper = render(Provider({store}, FilterBar({ serviceContainer }))); + const toolbar = wrapper.find( + ".devtools-toolbar.webconsole-filterbar-primary" + ); + + // Clear button + expect(toolbar.children().eq(0).attr("class")) + .toBe("devtools-button devtools-clear-icon"); + expect(toolbar.children().eq(0).attr("title")).toBe("Clear output"); + + // Filter bar toggle + expect(toolbar.children().eq(1).attr("class")) + .toBe("devtools-button devtools-filter-icon"); + expect(toolbar.children().eq(1).attr("title")).toBe("Toggle filter bar"); + + // Text filter + expect(toolbar.children().eq(2).attr("class")).toBe("devtools-plaininput text-filter"); + expect(toolbar.children().eq(2).attr("placeholder")).toBe("Filter output"); + expect(toolbar.children().eq(2).attr("type")).toBe("search"); + expect(toolbar.children().eq(2).attr("value")).toBe(""); + }); + + it("displays filter bar when button is clicked", () => { + const store = setupStore([]); + + expect(getAllUi(store.getState()).filterBarVisible).toBe(false); + + const wrapper = mount(Provider({store}, FilterBar({ serviceContainer }))); + wrapper.find(".devtools-filter-icon").simulate("click"); + + expect(getAllUi(store.getState()).filterBarVisible).toBe(true); + + // Buttons are displayed + const buttonProps = { + active: true, + dispatch: store.dispatch + }; + const logButton = FilterButton(Object.assign({}, buttonProps, + { label: "Logs", filterKey: MESSAGE_LEVEL.LOG })); + const debugButton = FilterButton(Object.assign({}, buttonProps, + { label: "Debug", filterKey: MESSAGE_LEVEL.DEBUG })); + const infoButton = FilterButton(Object.assign({}, buttonProps, + { label: "Info", filterKey: MESSAGE_LEVEL.INFO })); + const warnButton = FilterButton(Object.assign({}, buttonProps, + { label: "Warnings", filterKey: MESSAGE_LEVEL.WARN })); + const errorButton = FilterButton(Object.assign({}, buttonProps, + { label: "Errors", filterKey: MESSAGE_LEVEL.ERROR })); + expect(wrapper.contains([errorButton, warnButton, logButton, infoButton, debugButton])).toBe(true); + }); + + it("fires MESSAGES_CLEAR action when clear button is clicked", () => { + const store = setupStore([]); + store.dispatch = sinon.spy(); + + const wrapper = mount(Provider({store}, FilterBar({ serviceContainer }))); + wrapper.find(".devtools-clear-icon").simulate("click"); + const call = store.dispatch.getCall(0); + expect(call.args[0]).toEqual({ + type: MESSAGES_CLEAR + }); + }); + + it("sets filter text when text is typed", () => { + const store = setupStore([]); + + const wrapper = mount(Provider({store}, FilterBar({ serviceContainer }))); + wrapper.find(".devtools-plaininput").simulate("input", { target: { value: "a" } }); + expect(store.getState().filters.text).toBe("a"); + }); +}); diff --git a/devtools/client/webconsole/new-console-output/test/components/filter-button.test.js b/devtools/client/webconsole/new-console-output/test/components/filter-button.test.js new file mode 100644 index 000000000..3774da0b8 --- /dev/null +++ b/devtools/client/webconsole/new-console-output/test/components/filter-button.test.js @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +const expect = require("expect"); +const { render } = require("enzyme"); + +const { createFactory } = require("devtools/client/shared/vendor/react"); + +const FilterButton = createFactory(require("devtools/client/webconsole/new-console-output/components/filter-button")); +const { MESSAGE_LEVEL } = require("devtools/client/webconsole/new-console-output/constants"); + +describe("FilterButton component:", () => { + const props = { + active: true, + label: "Error", + filterKey: MESSAGE_LEVEL.ERROR, + }; + + it("displays as active when turned on", () => { + const wrapper = render(FilterButton(props)); + expect(wrapper.html()).toBe( + "<button class=\"menu-filter-button error checked\">Error</button>" + ); + }); + + it("displays as inactive when turned off", () => { + const inactiveProps = Object.assign({}, props, { active: false }); + const wrapper = render(FilterButton(inactiveProps)); + expect(wrapper.html()).toBe( + "<button class=\"menu-filter-button error\">Error</button>" + ); + }); +}); diff --git a/devtools/client/webconsole/new-console-output/test/components/message-container.test.js b/devtools/client/webconsole/new-console-output/test/components/message-container.test.js new file mode 100644 index 000000000..2377af906 --- /dev/null +++ b/devtools/client/webconsole/new-console-output/test/components/message-container.test.js @@ -0,0 +1,54 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +// Test utils. +const expect = require("expect"); +const { + renderComponent, + shallowRenderComponent +} = require("devtools/client/webconsole/new-console-output/test/helpers"); + +// Components under test. +const { MessageContainer } = require("devtools/client/webconsole/new-console-output/components/message-container"); +const ConsoleApiCall = require("devtools/client/webconsole/new-console-output/components/message-types/console-api-call"); +const EvaluationResult = require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result"); +const PageError = require("devtools/client/webconsole/new-console-output/components/message-types/page-error"); + +// 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("MessageContainer component:", () => { + it("pipes data to children as expected", () => { + const message = stubPreparedMessages.get("console.log('foobar', 'test')"); + const rendered = renderComponent(MessageContainer, {message, serviceContainer}); + + expect(rendered.textContent.includes("foobar")).toBe(true); + }); + it("picks correct child component", () => { + const messageTypes = [ + { + component: ConsoleApiCall, + message: stubPreparedMessages.get("console.log('foobar', 'test')") + }, + { + component: EvaluationResult, + message: stubPreparedMessages.get("new Date(0)") + }, + { + component: PageError, + message: stubPreparedMessages.get("ReferenceError: asdf is not defined") + } + ]; + + messageTypes.forEach(info => { + const { component, message } = info; + const rendered = shallowRenderComponent(MessageContainer, { + message, + serviceContainer, + }); + expect(rendered.type).toBe(component); + }); + }); +}); diff --git a/devtools/client/webconsole/new-console-output/test/components/message-icon.test.js b/devtools/client/webconsole/new-console-output/test/components/message-icon.test.js new file mode 100644 index 000000000..0244f08cf --- /dev/null +++ b/devtools/client/webconsole/new-console-output/test/components/message-icon.test.js @@ -0,0 +1,23 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +const { + MESSAGE_LEVEL, +} = require("devtools/client/webconsole/new-console-output/constants"); +const MessageIcon = require("devtools/client/webconsole/new-console-output/components/message-icon"); + +const expect = require("expect"); + +const { + renderComponent +} = require("devtools/client/webconsole/new-console-output/test/helpers"); + +describe("MessageIcon component:", () => { + it("renders icon based on level", () => { + const rendered = renderComponent(MessageIcon, { level: MESSAGE_LEVEL.ERROR }); + + expect(rendered.classList.contains("icon")).toBe(true); + expect(rendered.getAttribute("title")).toBe("Error"); + }); +}); diff --git a/devtools/client/webconsole/new-console-output/test/components/message-repeat.test.js b/devtools/client/webconsole/new-console-output/test/components/message-repeat.test.js new file mode 100644 index 000000000..0257a3aad --- /dev/null +++ b/devtools/client/webconsole/new-console-output/test/components/message-repeat.test.js @@ -0,0 +1,25 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +const MessageRepeat = require("devtools/client/webconsole/new-console-output/components/message-repeat"); + +const expect = require("expect"); + +const { + renderComponent +} = require("devtools/client/webconsole/new-console-output/test/helpers"); + +describe("MessageRepeat component:", () => { + it("renders repeated value correctly", () => { + const rendered = renderComponent(MessageRepeat, { repeat: 99 }); + expect(rendered.classList.contains("message-repeats")).toBe(true); + expect(rendered.style.visibility).toBe("visible"); + expect(rendered.textContent).toBe("99"); + }); + + it("renders an un-repeated value correctly", () => { + const rendered = renderComponent(MessageRepeat, { repeat: 1 }); + expect(rendered.style.visibility).toBe("hidden"); + }); +}); diff --git a/devtools/client/webconsole/new-console-output/test/components/network-event-message.test.js b/devtools/client/webconsole/new-console-output/test/components/network-event-message.test.js new file mode 100644 index 000000000..8d0c5307e --- /dev/null +++ b/devtools/client/webconsole/new-console-output/test/components/network-event-message.test.js @@ -0,0 +1,74 @@ +/* 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 } = require("enzyme"); + +// React +const { createFactory } = require("devtools/client/shared/vendor/react"); + +// Components under test. +const NetworkEventMessage = createFactory(require("devtools/client/webconsole/new-console-output/components/message-types/network-event-message")); +const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/message-indent"); + +// 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"); + +const EXPECTED_URL = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html"; + +describe("NetworkEventMessage component:", () => { + describe("GET request", () => { + it("renders as expected", () => { + const message = stubPreparedMessages.get("GET request"); + const wrapper = render(NetworkEventMessage({ message, serviceContainer })); + + expect(wrapper.find(".message-body .method").text()).toBe("GET"); + expect(wrapper.find(".message-body .xhr").length).toBe(0); + expect(wrapper.find(".message-body .url").length).toBe(1); + expect(wrapper.find(".message-body .url").text()).toBe(EXPECTED_URL); + expect(wrapper.find("div.message.cm-s-mozilla span.message-body.devtools-monospace").length).toBe(1); + }); + + it("has the expected indent", () => { + const message = stubPreparedMessages.get("GET request"); + + const indent = 10; + let wrapper = render(NetworkEventMessage({ message, serviceContainer, indent})); + expect(wrapper.find(".indent").prop("style").width) + .toBe(`${indent * INDENT_WIDTH}px`); + + wrapper = render(NetworkEventMessage({ message, serviceContainer })); + expect(wrapper.find(".indent").prop("style").width).toBe(`0`); + }); + }); + + describe("XHR GET request", () => { + it("renders as expected", () => { + const message = stubPreparedMessages.get("XHR GET request"); + const wrapper = render(NetworkEventMessage({ message, serviceContainer })); + + expect(wrapper.find(".message-body .method").text()).toBe("GET"); + expect(wrapper.find(".message-body .xhr").length).toBe(1); + expect(wrapper.find(".message-body .xhr").text()).toBe("XHR"); + expect(wrapper.find(".message-body .url").text()).toBe(EXPECTED_URL); + expect(wrapper.find("div.message.cm-s-mozilla span.message-body.devtools-monospace").length).toBe(1); + }); + }); + + describe("XHR POST request", () => { + it("renders as expected", () => { + const message = stubPreparedMessages.get("XHR POST request"); + const wrapper = render(NetworkEventMessage({ message, serviceContainer })); + + expect(wrapper.find(".message-body .method").text()).toBe("POST"); + expect(wrapper.find(".message-body .xhr").length).toBe(1); + expect(wrapper.find(".message-body .xhr").text()).toBe("XHR"); + expect(wrapper.find(".message-body .url").length).toBe(1); + expect(wrapper.find(".message-body .url").text()).toBe(EXPECTED_URL); + expect(wrapper.find("div.message.cm-s-mozilla span.message-body.devtools-monospace").length).toBe(1); + }); + }); +}); diff --git a/devtools/client/webconsole/new-console-output/test/components/page-error.test.js b/devtools/client/webconsole/new-console-output/test/components/page-error.test.js new file mode 100644 index 000000000..93f3a9ea5 --- /dev/null +++ b/devtools/client/webconsole/new-console-output/test/components/page-error.test.js @@ -0,0 +1,126 @@ +/* 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 PageError = require("devtools/client/webconsole/new-console-output/components/message-types/page-error"); +const { + MESSAGE_OPEN, + MESSAGE_CLOSE, +} = require("devtools/client/webconsole/new-console-output/constants"); +const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/message-indent"); + +// 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("PageError component:", () => { + it("renders", () => { + const message = stubPreparedMessages.get("ReferenceError: asdf is not defined"); + const wrapper = render(PageError({ message, serviceContainer })); + + expect(wrapper.find(".message-body").text()) + .toBe("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 https://github.com/devtools-html/gecko-dev/issues/285 + expect(locationLink.text()).toBe("test-tempfile.js:3:5"); + }); + + 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}) + )); + + // 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"); + let call = serviceContainer.openLink.getCall(0); + expect(call.args[0]).toEqual(message.exceptionDocURL); + }); + + it("has a stacktrace which can be openned", () => { + 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(".theme-twisty.open").length).toBe(1); + + // There should be three stacktrace items. + const frameLinks = wrapper.find(`.stack-trace span.frame-link`); + expect(frameLinks.length).toBe(3); + }); + + it("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(".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}, + PageError({ + 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 + }); + }); + + it("has the expected indent", () => { + const message = stubPreparedMessages.get("ReferenceError: asdf is not defined"); + const indent = 10; + let wrapper = render(PageError({ message, serviceContainer, indent})); + expect(wrapper.find(".indent").prop("style").width) + .toBe(`${indent * INDENT_WIDTH}px`); + + wrapper = render(PageError({ message, serviceContainer})); + expect(wrapper.find(".indent").prop("style").width).toBe(`0`); + }); +}); |