summaryrefslogtreecommitdiffstats
path: root/devtools/client/application/test/node/components
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/application/test/node/components')
-rw-r--r--devtools/client/application/test/node/components/__snapshots__/components_application_panel-App.test.js.snap12
-rw-r--r--devtools/client/application/test/node/components/components_application_panel-App.test.js26
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-Manifest.test.js.snap396
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestColorItem.test.js.snap58
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestEmpty.test.js.snap46
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIconItem.test.js.snap106
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIssue.test.js.snap49
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIssueList.test.js.snap89
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestItem.test.js.snap35
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestJsonLink.test.js.snap26
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestLoader.test.js.snap50
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestPage.test.js.snap80
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestSection.test.js.snap30
-rw-r--r--devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestUrlItem.test.js.snap21
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-Manifest.test.js73
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestColorItem.test.js48
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestEmpty.test.js23
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIconItem.test.js48
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIssue.test.js30
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIssueList.test.js59
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestItem.test.js28
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestJsonLink.test.js36
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestLoader.test.js82
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestPage.test.js59
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestSection.test.js34
-rw-r--r--devtools/client/application/test/node/components/manifest/components_application_panel-ManifestUrlItem.test.js30
-rw-r--r--devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-PageSwitcher.test.js.snap9
-rw-r--r--devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-Sidebar.test.js.snap64
-rw-r--r--devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-SidebarItem.test.js.snap141
-rw-r--r--devtools/client/application/test/node/components/routing/components_application_panel-PageSwitcher.test.js73
-rw-r--r--devtools/client/application/test/node/components/routing/components_application_panel-Sidebar.test.js51
-rw-r--r--devtools/client/application/test/node/components/routing/components_application_panel-SidebarItem.test.js82
-rw-r--r--devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-Registration.test.js.snap180
-rw-r--r--devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-RegistrationList.test.js.snap159
-rw-r--r--devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-RegistrationListEmpty.test.js.snap66
-rw-r--r--devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-Worker.test.js.snap132
-rw-r--r--devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-WorkersPage.test.js.snap143
-rw-r--r--devtools/client/application/test/node/components/service-workers/components_application_panel-Registration.test.js88
-rw-r--r--devtools/client/application/test/node/components/service-workers/components_application_panel-RegistrationList.test.js43
-rw-r--r--devtools/client/application/test/node/components/service-workers/components_application_panel-RegistrationListEmpty.test.js23
-rw-r--r--devtools/client/application/test/node/components/service-workers/components_application_panel-Worker.test.js110
-rw-r--r--devtools/client/application/test/node/components/service-workers/components_application_panel-WorkersPage.test.js82
42 files changed, 3020 insertions, 0 deletions
diff --git a/devtools/client/application/test/node/components/__snapshots__/components_application_panel-App.test.js.snap b/devtools/client/application/test/node/components/__snapshots__/components_application_panel-App.test.js.snap
new file mode 100644
index 0000000000..cef0e0a85d
--- /dev/null
+++ b/devtools/client/application/test/node/components/__snapshots__/components_application_panel-App.test.js.snap
@@ -0,0 +1,12 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`App renders the expected snapshot 1`] = `
+<LocalizationProvider>
+ <main
+ className="app"
+ >
+ <Connect(Sidebar) />
+ <Connect(PageSwitcher) />
+ </main>
+</LocalizationProvider>
+`;
diff --git a/devtools/client/application/test/node/components/components_application_panel-App.test.js b/devtools/client/application/test/node/components/components_application_panel-App.test.js
new file mode 100644
index 0000000000..fb003be26e
--- /dev/null
+++ b/devtools/client/application/test/node/components/components_application_panel-App.test.js
@@ -0,0 +1,26 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+// Import & init localization
+const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js");
+const LocalizationProvider = createFactory(FluentReact.LocalizationProvider);
+
+// Import component
+const App = createFactory(
+ require("resource://devtools/client/application/src/components/App.js")
+);
+
+describe("App", () => {
+ it("renders the expected snapshot", () => {
+ const wrapper = shallow(
+ LocalizationProvider({ bundles: [] }, App({}))
+ ).dive(); // dive to bypass the LocalizationProvider wrapper
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-Manifest.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-Manifest.test.js.snap
new file mode 100644
index 0000000000..d46eb63334
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-Manifest.test.js.snap
@@ -0,0 +1,396 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Manifest does not render the issues section when the manifest is valid 1`] = `
+<article
+ className="js-manifest"
+>
+ <Localized
+ id="manifest-view-header"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <ManifestJsonLink />
+ <ManifestSection
+ key="manifest-section-1"
+ title="manifest-item-identity"
+ >
+ <table>
+ <tbody>
+ <ManifestItem
+ key="name"
+ label="name"
+ >
+ foo
+ </ManifestItem>
+ </tbody>
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-2"
+ title="manifest-item-presentation"
+ >
+ <table>
+ <tbody>
+ <ManifestItem
+ key="lorem"
+ label="lorem"
+ >
+ ipsum
+ </ManifestItem>
+ <ManifestItem
+ key="foo"
+ label="foo"
+ >
+ bar
+ </ManifestItem>
+ </tbody>
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-3"
+ title="manifest-item-icons"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+</article>
+`;
+
+exports[`Manifest does render the issues section when the manifest is not valid 1`] = `
+<article
+ className="js-manifest"
+>
+ <Localized
+ id="manifest-view-header"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <ManifestJsonLink />
+ <ManifestSection
+ key="manifest-section-0"
+ title="manifest-item-warnings"
+ >
+ <ManifestIssueList
+ issues={
+ Array [
+ Object {
+ "level": "warning",
+ "message": "This is a warning",
+ },
+ ]
+ }
+ />
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-1"
+ title="manifest-item-identity"
+ >
+ <table>
+ <tbody>
+ <ManifestItem
+ key="name"
+ label="name"
+ >
+ foo
+ </ManifestItem>
+ </tbody>
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-2"
+ title="manifest-item-presentation"
+ >
+ <table>
+ <tbody>
+ <ManifestItem
+ key="lorem"
+ label="lorem"
+ >
+ ipsum
+ </ManifestItem>
+ <ManifestItem
+ key="foo"
+ label="foo"
+ >
+ bar
+ </ManifestItem>
+ </tbody>
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-3"
+ title="manifest-item-icons"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+</article>
+`;
+
+exports[`Manifest renders the expected snapshot for a manifest with color members 1`] = `
+<article
+ className="js-manifest"
+>
+ <Localized
+ id="manifest-view-header"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <ManifestJsonLink />
+ <ManifestSection
+ key="manifest-section-1"
+ title="manifest-item-identity"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-2"
+ title="manifest-item-presentation"
+ >
+ <table>
+ <tbody>
+ <ManifestColorItem
+ key="background_color"
+ label="background_color"
+ value="red"
+ />
+ <ManifestColorItem
+ key="theme_color"
+ label="theme_color"
+ value="rgb(0, 0, 0)"
+ />
+ </tbody>
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-3"
+ title="manifest-item-icons"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+</article>
+`;
+
+exports[`Manifest renders the expected snapshot for a manifest with icon members 1`] = `
+<article
+ className="js-manifest"
+>
+ <Localized
+ id="manifest-view-header"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <ManifestJsonLink />
+ <ManifestSection
+ key="manifest-section-1"
+ title="manifest-item-identity"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-2"
+ title="manifest-item-presentation"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-3"
+ title="manifest-item-icons"
+ >
+ <table>
+ <tbody>
+ <ManifestIconItem
+ key="0"
+ label={
+ Object {
+ "contentType": "image/png",
+ "sizes": "1x1",
+ }
+ }
+ value={
+ Object {
+ "purpose": "any",
+ "src": "something.png",
+ }
+ }
+ />
+ <ManifestIconItem
+ key="1"
+ label={
+ Object {
+ "contentType": "",
+ "sizes": "",
+ }
+ }
+ value={
+ Object {
+ "purpose": "any maskable",
+ "src": "something.svg",
+ }
+ }
+ />
+ </tbody>
+ </table>
+ </ManifestSection>
+</article>
+`;
+
+exports[`Manifest renders the expected snapshot for a manifest with string members 1`] = `
+<article
+ className="js-manifest"
+>
+ <Localized
+ id="manifest-view-header"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <ManifestJsonLink />
+ <ManifestSection
+ key="manifest-section-1"
+ title="manifest-item-identity"
+ >
+ <table>
+ <tbody>
+ <ManifestItem
+ key="name"
+ label="name"
+ >
+ foo
+ </ManifestItem>
+ </tbody>
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-2"
+ title="manifest-item-presentation"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-3"
+ title="manifest-item-icons"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+</article>
+`;
+
+exports[`Manifest renders the expected snapshot for a manifest with unknown types 1`] = `
+<article
+ className="js-manifest"
+>
+ <Localized
+ id="manifest-view-header"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <ManifestJsonLink />
+ <ManifestSection
+ key="manifest-section-1"
+ title="manifest-item-identity"
+ >
+ <table>
+ <tbody>
+ <ManifestItem
+ key="lorem"
+ label="lorem"
+ >
+ ipsum
+ </ManifestItem>
+ </tbody>
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-2"
+ title="manifest-item-presentation"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-3"
+ title="manifest-item-icons"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+</article>
+`;
+
+exports[`Manifest renders the expected snapshot for a manifest with url members 1`] = `
+<article
+ className="js-manifest"
+>
+ <Localized
+ id="manifest-view-header"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <ManifestJsonLink />
+ <ManifestSection
+ key="manifest-section-1"
+ title="manifest-item-identity"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-2"
+ title="manifest-item-presentation"
+ >
+ <table>
+ <tbody>
+ <ManifestUrlItem
+ key="start_url"
+ label="start_url"
+ value="https://example.com/"
+ />
+ <ManifestUrlItem
+ key="scope"
+ label="scope"
+ value="https://example.com/"
+ />
+ </tbody>
+ </table>
+ </ManifestSection>
+ <ManifestSection
+ key="manifest-section-3"
+ title="manifest-item-icons"
+ >
+ <table>
+ <tbody />
+ </table>
+ </ManifestSection>
+</article>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestColorItem.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestColorItem.test.js.snap
new file mode 100644
index 0000000000..4f3e485084
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestColorItem.test.js.snap
@@ -0,0 +1,58 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestColorItem does not strip translucent alpha from the displayed color 1`] = `
+<ManifestItem
+ label="foo"
+>
+ <div
+ className="manifest-item__color"
+ style={
+ Object {
+ "--color-value": "#00FF00FA",
+ }
+ }
+ >
+ #00FF00FA
+ </div>
+</ManifestItem>
+`;
+
+exports[`ManifestColorItem renders the expected snapshot for a populated color item 1`] = `
+<ManifestItem
+ label="foo"
+>
+ <div
+ className="manifest-item__color"
+ style={
+ Object {
+ "--color-value": "#ff0000",
+ }
+ }
+ >
+ #ff0000
+ </div>
+</ManifestItem>
+`;
+
+exports[`ManifestColorItem renders the expected snapshot for an empty color item 1`] = `
+<ManifestItem
+ label="foo"
+/>
+`;
+
+exports[`ManifestColorItem strips opaque alpha from the displayed color 1`] = `
+<ManifestItem
+ label="foo"
+>
+ <div
+ className="manifest-item__color"
+ style={
+ Object {
+ "--color-value": "#00FF00",
+ }
+ }
+ >
+ #00FF00
+ </div>
+</ManifestItem>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestEmpty.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestEmpty.test.js.snap
new file mode 100644
index 0000000000..bdc5e9ed60
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestEmpty.test.js.snap
@@ -0,0 +1,46 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestEmpty renders the expected snapshot 1`] = `
+<article
+ className="app-page__icon-container js-manifest-empty"
+>
+ <aside>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ }
+ }
+ id="sidebar-item-manifest"
+ >
+ <img
+ className="app-page__icon"
+ src="chrome://devtools/skin/images/application-manifest.svg"
+ />
+ </Localized>
+ </aside>
+ <div>
+ <Localized
+ id="manifest-empty-intro2"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <p>
+ <Localized
+ id="manifest-empty-intro-link"
+ >
+ <a
+ onClick={[Function]}
+ />
+ </Localized>
+ </p>
+ <Localized
+ id="manifest-non-existing"
+ >
+ <p />
+ </Localized>
+ </div>
+</article>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIconItem.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIconItem.test.js.snap
new file mode 100644
index 0000000000..200c6306de
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIconItem.test.js.snap
@@ -0,0 +1,106 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestIconItem renders the expected snapshop when a label member is missing 1`] = `
+<ManifestItem
+ label={
+ Array [
+ null,
+ null,
+ "image/png",
+ ]
+ }
+>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ }
+ }
+ id="manifest-icon-img"
+ >
+ <img
+ className="manifest-item__icon"
+ src="icon.png"
+ title="manifest-icon-img-title-no-sizes"
+ />
+ </Localized>
+ <br />
+ <Localized
+ $purpose="any"
+ code={<code />}
+ id="manifest-icon-purpose"
+ >
+ <span />
+ </Localized>
+</ManifestItem>
+`;
+
+exports[`ManifestIconItem renders the expected snapshop when all label members are missing 1`] = `
+<ManifestItem
+ label={
+ Array [
+ null,
+ null,
+ null,
+ ]
+ }
+>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ }
+ }
+ id="manifest-icon-img"
+ >
+ <img
+ className="manifest-item__icon"
+ src="icon.png"
+ title="manifest-icon-img-title-no-sizes"
+ />
+ </Localized>
+ <br />
+ <Localized
+ $purpose="any"
+ code={<code />}
+ id="manifest-icon-purpose"
+ >
+ <span />
+ </Localized>
+</ManifestItem>
+`;
+
+exports[`ManifestIconItem renders the expected snapshot for a fully populated icon item 1`] = `
+<ManifestItem
+ label={
+ Array [
+ "128x128",
+ <br />,
+ "image/png",
+ ]
+ }
+>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ }
+ }
+ id="manifest-icon-img"
+ >
+ <img
+ className="manifest-item__icon"
+ src="icon.png"
+ title="manifest-icon-img-title__{\\"sizes\\":\\"128x128\\"}"
+ />
+ </Localized>
+ <br />
+ <Localized
+ $purpose="any"
+ code={<code />}
+ id="manifest-icon-purpose"
+ >
+ <span />
+ </Localized>
+</ManifestItem>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIssue.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIssue.test.js.snap
new file mode 100644
index 0000000000..3cf46f07b1
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIssue.test.js.snap
@@ -0,0 +1,49 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestIssue renders the expected snapshot for a warning 1`] = `
+<li
+ className="js-manifest-issue "
+>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ "title": true,
+ }
+ }
+ id="icon-warning"
+ >
+ <img
+ className="manifest-issue__icon manifest-issue__icon--warning"
+ src="chrome://devtools/skin/images/alert-small.svg"
+ />
+ </Localized>
+ <span>
+ Lorem ipsum
+ </span>
+</li>
+`;
+
+exports[`ManifestIssue renders the expected snapshot for an error 1`] = `
+<li
+ className="js-manifest-issue "
+>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ "title": true,
+ }
+ }
+ id="icon-error"
+ >
+ <img
+ className="manifest-issue__icon manifest-issue__icon--error"
+ src="chrome://devtools/skin/images/error-small.svg"
+ />
+ </Localized>
+ <span>
+ Lorem ipsum
+ </span>
+</li>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIssueList.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIssueList.test.js.snap
new file mode 100644
index 0000000000..edbf2d07c9
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestIssueList.test.js.snap
@@ -0,0 +1,89 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestIssueList groups issues by level and shows errors first 1`] = `
+Array [
+ <ul
+ className="manifest-issues js-manifest-issues"
+ key="issuelist-0"
+ >
+ <ManifestIssue
+ className="manifest-issues__item"
+ key="issue-0"
+ level="error"
+ message="An error"
+ />
+ </ul>,
+ <ul
+ className="manifest-issues js-manifest-issues"
+ key="issuelist-1"
+ >
+ <ManifestIssue
+ className="manifest-issues__item"
+ key="issue-0"
+ level="warning"
+ message="A warning"
+ />
+ <ManifestIssue
+ className="manifest-issues__item"
+ key="issue-1"
+ level="warning"
+ message="Another warning"
+ />
+ </ul>,
+]
+`;
+
+exports[`ManifestIssueList renders nothing for empty issues 1`] = `null`;
+
+exports[`ManifestIssueList renders the expected snapshot for a populated list 1`] = `
+Array [
+ <ul
+ className="manifest-issues js-manifest-issues"
+ key="issuelist-0"
+ >
+ <ManifestIssue
+ className="manifest-issues__item"
+ key="issue-0"
+ level="error"
+ message="Foo"
+ />
+ </ul>,
+ <ul
+ className="manifest-issues js-manifest-issues"
+ key="issuelist-1"
+ >
+ <ManifestIssue
+ className="manifest-issues__item"
+ key="issue-0"
+ level="warning"
+ message="Foo"
+ />
+ <ManifestIssue
+ className="manifest-issues__item"
+ key="issue-1"
+ level="warning"
+ message="Bar"
+ />
+ </ul>,
+]
+`;
+
+exports[`ManifestIssueList skips rendering empty level groups 1`] = `
+<ul
+ className="manifest-issues js-manifest-issues"
+ key="issuelist-0"
+>
+ <ManifestIssue
+ className="manifest-issues__item"
+ key="issue-0"
+ level="warning"
+ message="A warning"
+ />
+ <ManifestIssue
+ className="manifest-issues__item"
+ key="issue-1"
+ level="warning"
+ message="Another warning"
+ />
+</ul>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestItem.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestItem.test.js.snap
new file mode 100644
index 0000000000..69d983d308
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestItem.test.js.snap
@@ -0,0 +1,35 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestItem renders the expected snapshot for a populated item 1`] = `
+<tr
+ className="manifest-item js-manifest-item"
+>
+ <th
+ className="manifest-item__label js-manifest-item-label"
+ scope="row"
+ >
+ foo
+ </th>
+ <td
+ className="manifest-item__value js-manifest-item-content"
+ >
+ bar
+ </td>
+</tr>
+`;
+
+exports[`ManifestItem renders the expected snapshot for an empty item 1`] = `
+<tr
+ className="manifest-item js-manifest-item"
+>
+ <th
+ className="manifest-item__label js-manifest-item-label"
+ scope="row"
+ >
+ foo
+ </th>
+ <td
+ className="manifest-item__value js-manifest-item-content"
+ />
+</tr>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestJsonLink.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestJsonLink.test.js.snap
new file mode 100644
index 0000000000..061578b846
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestJsonLink.test.js.snap
@@ -0,0 +1,26 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestJsonLink renders the expected snapshot when given a data URL 1`] = `
+<p
+ className="manifest-json-link"
+>
+ <Localized
+ id="manifest-json-link-data-url"
+ />
+</p>
+`;
+
+exports[`ManifestJsonLink renders the expected snapshot when given a regular URL 1`] = `
+<p
+ className="manifest-json-link"
+>
+ <a
+ className="js-manifest-json-link devtools-ellipsis-text"
+ href="#"
+ onClick={[Function]}
+ title="https://example.com/manifest.json"
+ >
+ https://example.com/manifest.json
+ </a>
+</p>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestLoader.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestLoader.test.js.snap
new file mode 100644
index 0000000000..16c885cf80
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestLoader.test.js.snap
@@ -0,0 +1,50 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestLoader renders a message when it is loading 1`] = `
+<aside
+ className="manifest-loader"
+>
+ <Localized
+ id="manifest-loading"
+ >
+ <p
+ className="manifest-loader__load js-manifest-loading"
+ />
+ </Localized>
+</aside>
+`;
+
+exports[`ManifestLoader renders a message when manifest has failed to load 1`] = `
+<aside
+ className="manifest-loader"
+>
+ <Localized
+ id="manifest-loaded-error"
+ key="manifest-error-label"
+ >
+ <h1
+ className="js-manifest-loaded-error app-page__title"
+ />
+ </Localized>
+ <p
+ className="technical-text"
+ key="manifest-error-message"
+ >
+ lorem ipsum
+ </p>
+</aside>
+`;
+
+exports[`ManifestLoader renders a message when manifest has loaded OK 1`] = `
+<aside
+ className="manifest-loader"
+>
+ <Localized
+ id="manifest-loaded-ok"
+ >
+ <p
+ className="js-manifest-loaded-ok"
+ />
+ </Localized>
+</aside>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestPage.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestPage.test.js.snap
new file mode 100644
index 0000000000..4700ccf935
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestPage.test.js.snap
@@ -0,0 +1,80 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestPage renders the expected snapshot when the manifest is loading 1`] = `
+<section
+ className="app-page js-manifest-page app-page--empty"
+>
+ <Connect(ManifestLoader) />
+</section>
+`;
+
+exports[`ManifestPage renders the expected snapshot when the manifest needs to load 1`] = `
+<section
+ className="app-page js-manifest-page app-page--empty"
+>
+ <Connect(ManifestLoader) />
+</section>
+`;
+
+exports[`ManifestPage renders the expected snapshot when there is a manifest 1`] = `
+<section
+ className="app-page js-manifest-page "
+>
+ <Manifest
+ icons={
+ Array [
+ Object {
+ "key": Object {
+ "contentType": "image/png",
+ "sizes": "1x1",
+ },
+ "type": "icon",
+ "value": Object {
+ "purpose": "any",
+ "src": "something.png",
+ },
+ },
+ ]
+ }
+ identity={
+ Array [
+ Object {
+ "key": "name",
+ "type": "string",
+ "value": "foo",
+ },
+ ]
+ }
+ presentation={
+ Array [
+ Object {
+ "key": "lorem",
+ "type": "string",
+ "value": "ipsum",
+ },
+ Object {
+ "key": "foo",
+ "type": "string",
+ "value": "bar",
+ },
+ ]
+ }
+ validation={
+ Array [
+ Object {
+ "level": "warning",
+ "message": "This is a warning",
+ },
+ ]
+ }
+ />
+</section>
+`;
+
+exports[`ManifestPage renders the expected snapshot when there is no manifest 1`] = `
+<section
+ className="app-page js-manifest-page app-page--empty"
+>
+ <ManifestEmpty />
+</section>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestSection.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestSection.test.js.snap
new file mode 100644
index 0000000000..e8ea10867f
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestSection.test.js.snap
@@ -0,0 +1,30 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestSection renders the expected snapshot for a populated section 1`] = `
+<section
+ className="manifest-section "
+>
+ <h2
+ className="manifest-section__title"
+ >
+ Lorem ipsum
+ </h2>
+ <tr>
+ <td>
+ foo
+ </td>
+ </tr>
+</section>
+`;
+
+exports[`ManifestSection renders the expected snapshot for a section with no children 1`] = `
+<section
+ className="manifest-section manifest-section--empty"
+>
+ <h2
+ className="manifest-section__title"
+ >
+ Lorem ipsum
+ </h2>
+</section>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestUrlItem.test.js.snap b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestUrlItem.test.js.snap
new file mode 100644
index 0000000000..62f4fdfe11
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/__snapshots__/components_application_panel-ManifestUrlItem.test.js.snap
@@ -0,0 +1,21 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestUrlItem renders the expected snapshot for a populated url 1`] = `
+<ManifestItem
+ label="foo"
+>
+ <div
+ className="manifest-item__url"
+ />
+</ManifestItem>
+`;
+
+exports[`ManifestUrlItem renders the expected snapshot for an empty url 1`] = `
+<ManifestItem
+ label="foo"
+>
+ <div
+ className="manifest-item__url"
+ />
+</ManifestItem>
+`;
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-Manifest.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-Manifest.test.js
new file mode 100644
index 0000000000..0b554fbdd2
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-Manifest.test.js
@@ -0,0 +1,73 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const Manifest = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/Manifest.js")
+);
+
+const {
+ MANIFEST_COLOR_MEMBERS,
+ MANIFEST_ICON_MEMBERS,
+ MANIFEST_STRING_MEMBERS,
+ MANIFEST_UNKNOWN_TYPE_MEMBERS,
+ MANIFEST_URL_MEMBERS,
+ MANIFEST_NO_ISSUES,
+ MANIFEST_WITH_ISSUES,
+} = require("resource://devtools/client/application/test/node/fixtures/data/constants.js");
+
+/*
+ * Test for Manifest component
+ */
+
+describe("Manifest", () => {
+ it("renders the expected snapshot for a manifest with string members", () => {
+ const wrapper = shallow(Manifest(MANIFEST_STRING_MEMBERS));
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot for a manifest with color members", () => {
+ const wrapper = shallow(Manifest(MANIFEST_COLOR_MEMBERS));
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot for a manifest with unknown types", () => {
+ const wrapper = shallow(Manifest(MANIFEST_UNKNOWN_TYPE_MEMBERS));
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot for a manifest with icon members", () => {
+ const wrapper = shallow(Manifest(MANIFEST_ICON_MEMBERS));
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot for a manifest with url members", () => {
+ const wrapper = shallow(Manifest(MANIFEST_URL_MEMBERS));
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("does render the issues section when the manifest is not valid", () => {
+ const wrapper = shallow(Manifest(MANIFEST_WITH_ISSUES));
+ expect(wrapper).toMatchSnapshot();
+
+ const sections = wrapper.find("ManifestSection");
+ expect(sections).toHaveLength(4);
+ expect(sections.get(0).props.title).toBe("manifest-item-warnings");
+ expect(sections.find("ManifestIssueList")).toHaveLength(1);
+ });
+
+ it("does not render the issues section when the manifest is valid", () => {
+ const wrapper = shallow(Manifest(MANIFEST_NO_ISSUES));
+ expect(wrapper).toMatchSnapshot();
+
+ const sections = wrapper.find("ManifestSection");
+ expect(sections).toHaveLength(3);
+ expect(sections.get(0).props.title).not.toBe("manifest-item-warnings");
+ expect(sections.find("ManifestIssueList")).toHaveLength(0);
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestColorItem.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestColorItem.test.js
new file mode 100644
index 0000000000..eac67ec195
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestColorItem.test.js
@@ -0,0 +1,48 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const ManifestColorItem = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestColorItem.js")
+);
+
+/*
+ * Unit tests for the ManifestItem component
+ */
+
+describe("ManifestColorItem", () => {
+ it("renders the expected snapshot for a populated color item", () => {
+ const wrapper = shallow(
+ ManifestColorItem({ label: "foo", value: "#ff0000" })
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot for an empty color item", () => {
+ const wrapper = shallow(ManifestColorItem({ label: "foo" }));
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("strips opaque alpha from the displayed color", () => {
+ const wrapper = shallow(
+ ManifestColorItem({ label: "foo", value: "#00FF00FF" })
+ );
+ expect(wrapper).toMatchSnapshot();
+
+ expect(wrapper.find(".manifest-item__color").text()).toBe("#00FF00");
+ });
+
+ it("does not strip translucent alpha from the displayed color", () => {
+ const wrapper = shallow(
+ ManifestColorItem({ label: "foo", value: "#00FF00FA" })
+ );
+ expect(wrapper).toMatchSnapshot();
+
+ expect(wrapper.find(".manifest-item__color").text()).toBe("#00FF00FA");
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestEmpty.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestEmpty.test.js
new file mode 100644
index 0000000000..de27a56ec5
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestEmpty.test.js
@@ -0,0 +1,23 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const ManifestEmpty = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestEmpty.js")
+);
+
+/**
+ * Test for ManifestEmpty component
+ */
+
+describe("ManifestEmpty", () => {
+ it("renders the expected snapshot", () => {
+ const wrapper = shallow(ManifestEmpty({}));
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIconItem.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIconItem.test.js
new file mode 100644
index 0000000000..e3ea293c82
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIconItem.test.js
@@ -0,0 +1,48 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const ManifestIconItem = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestIconItem.js")
+);
+
+/*
+ * Unit tests for the ManifestIconItem component
+ */
+
+describe("ManifestIconItem", () => {
+ it("renders the expected snapshot for a fully populated icon item", () => {
+ const wrapper = shallow(
+ ManifestIconItem({
+ label: { sizes: "128x128", contentType: "image/png" },
+ value: { src: "icon.png", purpose: "any" },
+ })
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshop when a label member is missing", () => {
+ const wrapper = shallow(
+ ManifestIconItem({
+ label: { sizes: undefined, contentType: "image/png" },
+ value: { src: "icon.png", purpose: "any" },
+ })
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshop when all label members are missing", () => {
+ const wrapper = shallow(
+ ManifestIconItem({
+ label: { sizes: undefined, contentType: undefined },
+ value: { src: "icon.png", purpose: "any" },
+ })
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIssue.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIssue.test.js
new file mode 100644
index 0000000000..41350557be
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIssue.test.js
@@ -0,0 +1,30 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const ManifestIssue = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestIssue.js")
+);
+
+/*
+ * Tests for the ManifestIssue component
+ */
+
+describe("ManifestIssue", () => {
+ it("renders the expected snapshot for a warning", () => {
+ const issue = { level: "warning", message: "Lorem ipsum" };
+ const wrapper = shallow(ManifestIssue(issue));
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot for an error", () => {
+ const issue = { level: "error", message: "Lorem ipsum" };
+ const wrapper = shallow(ManifestIssue(issue));
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIssueList.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIssueList.test.js
new file mode 100644
index 0000000000..71d59d3e07
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestIssueList.test.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const ManifestIssueList = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestIssueList.js")
+);
+
+/*
+ * Tests for the ManifestIssue component
+ */
+
+describe("ManifestIssueList", () => {
+ it("renders the expected snapshot for a populated list", () => {
+ const issues = [
+ { level: "error", message: "Foo" },
+ { level: "warning", message: "Foo" },
+ { level: "warning", message: "Bar" },
+ ];
+ const wrapper = shallow(ManifestIssueList({ issues }));
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("groups issues by level and shows errors first", () => {
+ const issues = [
+ { level: "warning", message: "A warning" },
+ { level: "error", message: "An error" },
+ { level: "warning", message: "Another warning" },
+ ];
+ const wrapper = shallow(ManifestIssueList({ issues }));
+ expect(wrapper).toMatchSnapshot();
+
+ expect(wrapper.find("ManifestIssue").get(0).props.level).toBe("error");
+ expect(wrapper.find("ManifestIssue").get(1).props.level).toBe("warning");
+ expect(wrapper.find("ManifestIssue").get(2).props.level).toBe("warning");
+ });
+
+ it("skips rendering empty level groups", () => {
+ const issues = [
+ { level: "warning", message: "A warning" },
+ { level: "warning", message: "Another warning" },
+ ];
+ const wrapper = shallow(ManifestIssueList({ issues }));
+ expect(wrapper).toMatchSnapshot();
+
+ const lists = wrapper.find(".js-manifest-issues");
+ expect(lists).toHaveLength(1);
+ });
+
+ it("renders nothing for empty issues", () => {
+ const wrapper = shallow(ManifestIssueList({ issues: [] }));
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestItem.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestItem.test.js
new file mode 100644
index 0000000000..ca9303aab4
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestItem.test.js
@@ -0,0 +1,28 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const ManifestItem = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestItem.js")
+);
+
+/*
+ * Unit tests for the ManifestItem component
+ */
+
+describe("ManifestItem", () => {
+ it("renders the expected snapshot for a populated item", () => {
+ const wrapper = shallow(ManifestItem({ label: "foo" }, "bar"));
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot for an empty item", () => {
+ const wrapper = shallow(ManifestItem({ label: "foo" }));
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestJsonLink.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestJsonLink.test.js
new file mode 100644
index 0000000000..fccab31b9d
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestJsonLink.test.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const ManifestJsonLink = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestJsonLink.js")
+);
+
+/*
+ * Test for the ManifestJsonLink component
+ */
+
+describe("ManifestJsonLink", () => {
+ it("renders the expected snapshot when given a regular URL", () => {
+ const wrapper = shallow(
+ ManifestJsonLink({ url: "https://example.com/manifest.json" })
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot when given a data URL", () => {
+ const wrapper = shallow(
+ ManifestJsonLink({
+ url: `data:application/manifest+json,{"name": "Foo"}`,
+ })
+ );
+ expect(wrapper).toMatchSnapshot();
+ // assert there's no link for data URLs
+ expect(wrapper.find("a").length).toBe(0);
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestLoader.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestLoader.test.js
new file mode 100644
index 0000000000..d3cc8595ce
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestLoader.test.js
@@ -0,0 +1,82 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+// Import test helpers
+const {
+ setupStore,
+} = require("resource://devtools/client/application/test/node/helpers.js");
+// Import fixtures
+const {
+ MANIFEST_NO_ISSUES,
+} = require("resource://devtools/client/application/test/node/fixtures/data/constants.js");
+
+const manifestActions = require("resource://devtools/client/application/src/actions/manifest.js");
+// NOTE: we need to spy on the action before we load the component, so it gets
+// bound to the spy, not the original implementation
+const fetchManifestActionSpy = jest.spyOn(manifestActions, "fetchManifest");
+
+const ManifestLoader = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestLoader.js")
+);
+
+describe("ManifestLoader", () => {
+ function buildStore({ manifest, errorMessage, isLoading }) {
+ const manifestState = Object.assign(
+ {
+ manifest: null,
+ errorMessage: "",
+ isLoading: false,
+ },
+ { manifest, errorMessage, isLoading }
+ );
+
+ return setupStore({ manifest: manifestState });
+ }
+
+ afterAll(() => {
+ fetchManifestActionSpy.mockRestore();
+ });
+
+ it("loads a manifest when mounted", async () => {
+ fetchManifestActionSpy.mockReturnValue({ type: "foo" });
+
+ const store = buildStore({});
+
+ shallow(ManifestLoader({ store })).dive();
+
+ expect(manifestActions.fetchManifest).toHaveBeenCalled();
+ fetchManifestActionSpy.mockReset();
+ });
+
+ it("renders a message when it is loading", async () => {
+ const store = buildStore({ isLoading: true });
+ const wrapper = shallow(ManifestLoader({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders a message when manifest has loaded OK", async () => {
+ const store = buildStore({
+ isLoading: false,
+ manifest: MANIFEST_NO_ISSUES,
+ errorMessage: "",
+ });
+ const wrapper = shallow(ManifestLoader({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders a message when manifest has failed to load", async () => {
+ const store = buildStore({
+ manifest: null,
+ isLoading: false,
+ errorMessage: "lorem ipsum",
+ });
+ const wrapper = shallow(ManifestLoader({ store })).dive();
+
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestPage.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestPage.test.js
new file mode 100644
index 0000000000..b479882924
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestPage.test.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const {
+ setupStore,
+} = require("resource://devtools/client/application/test/node/helpers.js");
+const {
+ MANIFEST_SIMPLE,
+} = require("resource://devtools/client/application/test/node/fixtures/data/constants.js");
+
+const ManifestPage = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestPage.js")
+);
+
+/**
+ * Test for ManifestPage.js component
+ */
+
+describe("ManifestPage", () => {
+ function buildStoreWithManifest(manifest, isLoading = false) {
+ return setupStore({
+ manifest: {
+ manifest,
+ errorMessage: "",
+ isLoading,
+ },
+ });
+ }
+
+ it("renders the expected snapshot when there is a manifest", () => {
+ const store = buildStoreWithManifest(MANIFEST_SIMPLE);
+ const wrapper = shallow(ManifestPage({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot when the manifest needs to load", () => {
+ const store = buildStoreWithManifest(undefined);
+ const wrapper = shallow(ManifestPage({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot when the manifest is loading", () => {
+ const store = buildStoreWithManifest(undefined, true);
+ const wrapper = shallow(ManifestPage({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot when there is no manifest", () => {
+ const store = buildStoreWithManifest(null);
+ const wrapper = shallow(ManifestPage({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestSection.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestSection.test.js
new file mode 100644
index 0000000000..c117febb57
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestSection.test.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+const {
+ td,
+ tr,
+} = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
+
+const ManifestSection = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestSection.js")
+);
+
+/*
+ * Unit tests for the ManifestSection component
+ */
+
+describe("ManifestSection", () => {
+ it("renders the expected snapshot for a populated section", () => {
+ const content = tr({}, td({}, "foo"));
+ const wrapper = shallow(ManifestSection({ title: "Lorem ipsum" }, content));
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot for a section with no children", () => {
+ const wrapper = shallow(ManifestSection({ title: "Lorem ipsum" }));
+ expect(wrapper).toMatchSnapshot();
+ expect(wrapper.find(".manifest-section--empty"));
+ });
+});
diff --git a/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestUrlItem.test.js b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestUrlItem.test.js
new file mode 100644
index 0000000000..1ef1504a3f
--- /dev/null
+++ b/devtools/client/application/test/node/components/manifest/components_application_panel-ManifestUrlItem.test.js
@@ -0,0 +1,30 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const ManifestUrlItem = createFactory(
+ require("resource://devtools/client/application/src/components/manifest/ManifestUrlItem.js")
+);
+
+/*
+ * Unit tests for the ManifestUrlItem component
+ */
+
+describe("ManifestUrlItem", () => {
+ it("renders the expected snapshot for a populated url", () => {
+ const wrapper = shallow(
+ ManifestUrlItem({ label: "foo" }, "https://example.com")
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot for an empty url", () => {
+ const wrapper = shallow(ManifestUrlItem({ label: "foo" }));
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-PageSwitcher.test.js.snap b/devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-PageSwitcher.test.js.snap
new file mode 100644
index 0000000000..4fc899a511
--- /dev/null
+++ b/devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-PageSwitcher.test.js.snap
@@ -0,0 +1,9 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PageSwitcher renders nothing when an invalid page is selected 1`] = `""`;
+
+exports[`PageSwitcher renders nothing when no page is selected 1`] = `""`;
+
+exports[`PageSwitcher renders the ManifestPage component when manifest page is selected 1`] = `<Connect(ManifestPage) />`;
+
+exports[`PageSwitcher renders the WorkersPage component when workers page is selected 1`] = `<Connect(WorkersPage) />`;
diff --git a/devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-Sidebar.test.js.snap b/devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-Sidebar.test.js.snap
new file mode 100644
index 0000000000..4348d7c5b9
--- /dev/null
+++ b/devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-Sidebar.test.js.snap
@@ -0,0 +1,64 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Sidebar renders the expected snapshot when no page is selected 1`] = `
+<aside
+ className="sidebar js-sidebar"
+>
+ <ul
+ className="sidebar__list"
+ >
+ <Connect(SidebarItem)
+ isSelected={false}
+ key="sidebar-item-service-workers"
+ page="service-workers"
+ />
+ <Connect(SidebarItem)
+ isSelected={false}
+ key="sidebar-item-manifest"
+ page="manifest"
+ />
+ </ul>
+</aside>
+`;
+
+exports[`Sidebar renders the expected snapshot when the manifest page is selected 1`] = `
+<aside
+ className="sidebar js-sidebar"
+>
+ <ul
+ className="sidebar__list"
+ >
+ <Connect(SidebarItem)
+ isSelected={false}
+ key="sidebar-item-service-workers"
+ page="service-workers"
+ />
+ <Connect(SidebarItem)
+ isSelected={true}
+ key="sidebar-item-manifest"
+ page="manifest"
+ />
+ </ul>
+</aside>
+`;
+
+exports[`Sidebar renders the expected snapshot when the service workers page is selected 1`] = `
+<aside
+ className="sidebar js-sidebar"
+>
+ <ul
+ className="sidebar__list"
+ >
+ <Connect(SidebarItem)
+ isSelected={true}
+ key="sidebar-item-service-workers"
+ page="service-workers"
+ />
+ <Connect(SidebarItem)
+ isSelected={false}
+ key="sidebar-item-manifest"
+ page="manifest"
+ />
+ </ul>
+</aside>
+`;
diff --git a/devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-SidebarItem.test.js.snap b/devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-SidebarItem.test.js.snap
new file mode 100644
index 0000000000..c5f3122e6c
--- /dev/null
+++ b/devtools/client/application/test/node/components/routing/__snapshots__/components_application_panel-SidebarItem.test.js.snap
@@ -0,0 +1,141 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`SidebarItem renders the expected snapshot when the manifest page is not selected 1`] = `
+<li
+ className="sidebar-item js-sidebar-manifest "
+ onClick={[Function]}
+ role="link"
+>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ "title": true,
+ }
+ }
+ id="sidebar-item-manifest"
+ >
+ <img
+ className="sidebar-item__icon"
+ src="chrome://devtools/skin/images/application-manifest.svg"
+ />
+ </Localized>
+ <Localized
+ attrs={
+ Object {
+ "title": true,
+ }
+ }
+ id="sidebar-item-manifest"
+ >
+ <span
+ className="devtools-ellipsis-text"
+ />
+ </Localized>
+</li>
+`;
+
+exports[`SidebarItem renders the expected snapshot when the manifest page is selected 1`] = `
+<li
+ className="sidebar-item js-sidebar-manifest sidebar-item--selected"
+ onClick={[Function]}
+ role="link"
+>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ "title": true,
+ }
+ }
+ id="sidebar-item-manifest"
+ >
+ <img
+ className="sidebar-item__icon"
+ src="chrome://devtools/skin/images/application-manifest.svg"
+ />
+ </Localized>
+ <Localized
+ attrs={
+ Object {
+ "title": true,
+ }
+ }
+ id="sidebar-item-manifest"
+ >
+ <span
+ className="devtools-ellipsis-text"
+ />
+ </Localized>
+</li>
+`;
+
+exports[`SidebarItem renders the expected snapshot when the service-workers page is not selected 1`] = `
+<li
+ className="sidebar-item js-sidebar-service-workers "
+ onClick={[Function]}
+ role="link"
+>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ "title": true,
+ }
+ }
+ id="sidebar-item-service-workers"
+ >
+ <img
+ className="sidebar-item__icon"
+ src="chrome://devtools/skin/images/debugging-workers.svg"
+ />
+ </Localized>
+ <Localized
+ attrs={
+ Object {
+ "title": true,
+ }
+ }
+ id="sidebar-item-service-workers"
+ >
+ <span
+ className="devtools-ellipsis-text"
+ />
+ </Localized>
+</li>
+`;
+
+exports[`SidebarItem renders the expected snapshot when the service-workers page is selected 1`] = `
+<li
+ className="sidebar-item js-sidebar-service-workers sidebar-item--selected"
+ onClick={[Function]}
+ role="link"
+>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ "title": true,
+ }
+ }
+ id="sidebar-item-service-workers"
+ >
+ <img
+ className="sidebar-item__icon"
+ src="chrome://devtools/skin/images/debugging-workers.svg"
+ />
+ </Localized>
+ <Localized
+ attrs={
+ Object {
+ "title": true,
+ }
+ }
+ id="sidebar-item-service-workers"
+ >
+ <span
+ className="devtools-ellipsis-text"
+ />
+ </Localized>
+</li>
+`;
diff --git a/devtools/client/application/test/node/components/routing/components_application_panel-PageSwitcher.test.js b/devtools/client/application/test/node/components/routing/components_application_panel-PageSwitcher.test.js
new file mode 100644
index 0000000000..1e69aa6869
--- /dev/null
+++ b/devtools/client/application/test/node/components/routing/components_application_panel-PageSwitcher.test.js
@@ -0,0 +1,73 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+// Import setupStore with imported & combined reducers
+const {
+ setupStore,
+} = require("resource://devtools/client/application/test/node/helpers.js");
+
+const PageSwitcher = createFactory(
+ require("resource://devtools/client/application/src/components/routing/PageSwitcher.js")
+);
+
+const {
+ PAGE_TYPES,
+} = require("resource://devtools/client/application/src/constants.js");
+
+/**
+ * Test for workerListEmpty.js component
+ */
+
+describe("PageSwitcher", () => {
+ function buildStoreWithSelectedPage(selectedPage) {
+ return setupStore({
+ ui: {
+ selectedPage,
+ },
+ });
+ }
+
+ const consoleErrorSpy = jest
+ .spyOn(console, "error")
+ .mockImplementation(() => {});
+
+ beforeEach(() => {
+ console.error.mockClear();
+ });
+
+ afterAll(() => {
+ consoleErrorSpy.mockRestore();
+ });
+
+ it("renders the ManifestPage component when manifest page is selected", () => {
+ const store = buildStoreWithSelectedPage(PAGE_TYPES.MANIFEST);
+ const wrapper = shallow(PageSwitcher({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the WorkersPage component when workers page is selected", () => {
+ const store = buildStoreWithSelectedPage(PAGE_TYPES.SERVICE_WORKERS);
+ const wrapper = shallow(PageSwitcher({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders nothing when no page is selected", () => {
+ const store = buildStoreWithSelectedPage(null);
+ const wrapper = shallow(PageSwitcher({ store })).dive();
+ expect(console.error).toHaveBeenCalledTimes(1);
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders nothing when an invalid page is selected", () => {
+ const store = buildStoreWithSelectedPage("foo");
+ const wrapper = shallow(PageSwitcher({ store })).dive();
+ expect(console.error).toHaveBeenCalledTimes(1);
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/routing/components_application_panel-Sidebar.test.js b/devtools/client/application/test/node/components/routing/components_application_panel-Sidebar.test.js
new file mode 100644
index 0000000000..4593f702bc
--- /dev/null
+++ b/devtools/client/application/test/node/components/routing/components_application_panel-Sidebar.test.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const {
+ setupStore,
+} = require("resource://devtools/client/application/test/node/helpers.js");
+
+const {
+ PAGE_TYPES,
+} = require("resource://devtools/client/application/src/constants.js");
+
+const Sidebar = createFactory(
+ require("resource://devtools/client/application/src/components/routing/Sidebar.js")
+);
+
+/**
+ * Test for Sidebar.js component
+ */
+
+describe("Sidebar", () => {
+ function buildStoreWithSelectedPage(selectedPage) {
+ return setupStore({
+ ui: {
+ selectedPage,
+ },
+ });
+ }
+ it("renders the expected snapshot when the manifest page is selected", () => {
+ const store = buildStoreWithSelectedPage(PAGE_TYPES.MANIFEST);
+ const wrapper = shallow(Sidebar({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot when the service workers page is selected", () => {
+ const store = buildStoreWithSelectedPage(PAGE_TYPES.SERVICE_WORKERS);
+ const wrapper = shallow(Sidebar({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot when no page is selected", () => {
+ const store = buildStoreWithSelectedPage();
+ const wrapper = shallow(Sidebar({ store })).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/routing/components_application_panel-SidebarItem.test.js b/devtools/client/application/test/node/components/routing/components_application_panel-SidebarItem.test.js
new file mode 100644
index 0000000000..955c97acd2
--- /dev/null
+++ b/devtools/client/application/test/node/components/routing/components_application_panel-SidebarItem.test.js
@@ -0,0 +1,82 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const {
+ setupStore,
+} = require("resource://devtools/client/application/test/node/helpers.js");
+
+const {
+ PAGE_TYPES,
+} = require("resource://devtools/client/application/src/constants.js");
+
+const SidebarItem = createFactory(
+ require("resource://devtools/client/application/src/components/routing/SidebarItem.js")
+);
+
+/**
+ * Test for SidebarItem.js component
+ */
+
+describe("SidebarItem", () => {
+ function buildStoreWithSelectedPage(selectedPage) {
+ return setupStore({
+ ui: {
+ selectedPage,
+ },
+ });
+ }
+
+ it("renders the expected snapshot when the manifest page is selected", () => {
+ const store = buildStoreWithSelectedPage(PAGE_TYPES.MANIFEST);
+ const wrapper = shallow(
+ SidebarItem({
+ store,
+ page: "manifest",
+ isSelected: true,
+ })
+ ).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot when the service-workers page is selected", () => {
+ const store = buildStoreWithSelectedPage(PAGE_TYPES.SERVICE_WORKERS);
+ const wrapper = shallow(
+ SidebarItem({
+ store,
+ isSelected: true,
+ page: "service-workers",
+ })
+ ).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot when the manifest page is not selected", () => {
+ const store = buildStoreWithSelectedPage(PAGE_TYPES.MANIFEST);
+ const wrapper = shallow(
+ SidebarItem({
+ store,
+ isSelected: false,
+ page: "manifest",
+ })
+ ).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot when the service-workers page is not selected", () => {
+ const store = buildStoreWithSelectedPage(PAGE_TYPES.SERVICE_WORKERS);
+ const wrapper = shallow(
+ SidebarItem({
+ store,
+ isSelected: false,
+ page: "service-workers",
+ })
+ ).dive();
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-Registration.test.js.snap b/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-Registration.test.js.snap
new file mode 100644
index 0000000000..f85bf8b2a1
--- /dev/null
+++ b/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-Registration.test.js.snap
@@ -0,0 +1,180 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Registration Renders the expected snapshot for a registration with a worker 1`] = `
+<li
+ className=""
+>
+ <article
+ className="registration js-sw-container"
+ >
+ <header
+ className="registration__header"
+ >
+ <h2
+ className="registration__scope js-sw-scope devtools-ellipsis-text"
+ title="SCOPE 123"
+ >
+ SCOPE 123
+ </h2>
+ </header>
+ <aside
+ className="registration__controls"
+ >
+ <Localized
+ id="serviceworker-worker-unregister"
+ >
+ <UIButton
+ className="js-unregister-button"
+ onClick={[Function]}
+ />
+ </Localized>
+ </aside>
+ <ul
+ className="registration__workers"
+ >
+ <li
+ className="registration__workers-item"
+ key="id-worker-1-example"
+ >
+ <Connect(Worker)
+ isDebugEnabled={true}
+ worker={
+ Object {
+ "id": "id-worker-1-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ }
+ }
+ />
+ </li>
+ </ul>
+ </article>
+</li>
+`;
+
+exports[`Registration Renders the expected snapshot for a registration with multiple workers 1`] = `
+<li
+ className=""
+>
+ <article
+ className="registration js-sw-container"
+ >
+ <header
+ className="registration__header"
+ >
+ <h2
+ className="registration__scope js-sw-scope devtools-ellipsis-text"
+ title="SCOPE 123"
+ >
+ SCOPE 123
+ </h2>
+ </header>
+ <aside
+ className="registration__controls"
+ >
+ <Localized
+ id="serviceworker-worker-unregister"
+ >
+ <UIButton
+ className="js-unregister-button"
+ onClick={[Function]}
+ />
+ </Localized>
+ </aside>
+ <ul
+ className="registration__workers"
+ >
+ <li
+ className="registration__workers-item"
+ key="id-worker-1-example"
+ >
+ <Connect(Worker)
+ isDebugEnabled={true}
+ worker={
+ Object {
+ "id": "id-worker-1-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ }
+ }
+ />
+ </li>
+ <li
+ className="registration__workers-item"
+ key="id-worker-2-example"
+ >
+ <Connect(Worker)
+ isDebugEnabled={true}
+ worker={
+ Object {
+ "id": "id-worker-2-example",
+ "state": 2,
+ "stateText": "installed",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ }
+ }
+ />
+ </li>
+ </ul>
+ </article>
+</li>
+`;
+
+exports[`Registration Renders the expected snapshot when sw debugging is disabled 1`] = `
+<li
+ className=""
+>
+ <article
+ className="registration js-sw-container"
+ >
+ <header
+ className="registration__header"
+ >
+ <h2
+ className="registration__scope js-sw-scope devtools-ellipsis-text"
+ title="SCOPE 123"
+ >
+ SCOPE 123
+ </h2>
+ </header>
+ <aside
+ className="registration__controls"
+ >
+ <Localized
+ id="serviceworker-worker-unregister"
+ >
+ <UIButton
+ className="js-unregister-button"
+ onClick={[Function]}
+ />
+ </Localized>
+ </aside>
+ <ul
+ className="registration__workers"
+ >
+ <li
+ className="registration__workers-item"
+ key="id-worker-1-example"
+ >
+ <Connect(Worker)
+ isDebugEnabled={false}
+ worker={
+ Object {
+ "id": "id-worker-1-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ }
+ }
+ />
+ </li>
+ </ul>
+ </article>
+</li>
+`;
diff --git a/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-RegistrationList.test.js.snap b/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-RegistrationList.test.js.snap
new file mode 100644
index 0000000000..160bff7c8c
--- /dev/null
+++ b/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-RegistrationList.test.js.snap
@@ -0,0 +1,159 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`RegistrationList renders the expected snapshot for a list with a single registration 1`] = `
+Array [
+ <article
+ className="registrations-container"
+ key="registrations-container"
+ >
+ <Localized
+ id="serviceworker-list-header"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <ul
+ className="registrations-container__list"
+ >
+ <Connect(Registration)
+ className="registrations-container__item"
+ isDebugEnabled={true}
+ key="id-reg-1-example"
+ registration={
+ Object {
+ "id": "id-reg-1-example",
+ "registrationFront": "",
+ "scope": "SCOPE 123",
+ "workers": Array [
+ Object {
+ "id": "id-worker-1-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ },
+ ],
+ }
+ }
+ />
+ </ul>
+ </article>,
+ <footer
+ className="aboutdebugging-plug"
+ >
+ <Localized
+ a={
+ <a
+ className="aboutdebugging-plug__link"
+ onClick={[Function]}
+ />
+ }
+ id="serviceworker-list-aboutdebugging"
+ key="serviceworkerlist-footer"
+ >
+ <p />
+ </Localized>
+ </footer>,
+]
+`;
+
+exports[`RegistrationList renders the expected snapshot for a multiple registration list 1`] = `
+Array [
+ <article
+ className="registrations-container"
+ key="registrations-container"
+ >
+ <Localized
+ id="serviceworker-list-header"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <ul
+ className="registrations-container__list"
+ >
+ <Connect(Registration)
+ className="registrations-container__item"
+ isDebugEnabled={true}
+ key="id-reg-1-example"
+ registration={
+ Object {
+ "id": "id-reg-1-example",
+ "registrationFront": "",
+ "scope": "SCOPE1",
+ "workers": Array [
+ Object {
+ "id": "id-worker-1-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ },
+ ],
+ }
+ }
+ />
+ <Connect(Registration)
+ className="registrations-container__item"
+ isDebugEnabled={true}
+ key="id-reg-1-example"
+ registration={
+ Object {
+ "id": "id-reg-1-example",
+ "registrationFront": "",
+ "scope": "SCOPE2",
+ "workers": Array [
+ Object {
+ "id": "id-worker-2-example",
+ "state": 2,
+ "stateText": "installed",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ },
+ ],
+ }
+ }
+ />
+ <Connect(Registration)
+ className="registrations-container__item"
+ isDebugEnabled={true}
+ key="id-reg-3-example"
+ registration={
+ Object {
+ "id": "id-reg-3-example",
+ "registrationFront": "",
+ "scope": "SCOPE3",
+ "workers": Array [
+ Object {
+ "id": "id-worker-3-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ },
+ ],
+ }
+ }
+ />
+ </ul>
+ </article>,
+ <footer
+ className="aboutdebugging-plug"
+ >
+ <Localized
+ a={
+ <a
+ className="aboutdebugging-plug__link"
+ onClick={[Function]}
+ />
+ }
+ id="serviceworker-list-aboutdebugging"
+ key="serviceworkerlist-footer"
+ >
+ <p />
+ </Localized>
+ </footer>,
+]
+`;
diff --git a/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-RegistrationListEmpty.test.js.snap b/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-RegistrationListEmpty.test.js.snap
new file mode 100644
index 0000000000..657c7164d7
--- /dev/null
+++ b/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-RegistrationListEmpty.test.js.snap
@@ -0,0 +1,66 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`RegistrationListEmpty renders the expected snapshot 1`] = `
+<article
+ className="app-page__icon-container js-registration-list-empty"
+>
+ <aside>
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ }
+ }
+ id="sidebar-item-service-workers"
+ >
+ <img
+ className="app-page__icon"
+ src="chrome://devtools/skin/images/debugging-workers.svg"
+ />
+ </Localized>
+ </aside>
+ <div>
+ <Localized
+ id="serviceworker-empty-intro2"
+ >
+ <h1
+ className="app-page__title"
+ />
+ </Localized>
+ <Localized
+ a={
+ <a
+ onClick={[Function]}
+ />
+ }
+ id="serviceworker-empty-suggestions2"
+ span={
+ <a
+ onClick={[Function]}
+ />
+ }
+ >
+ <p />
+ </Localized>
+ <p>
+ <Localized
+ id="serviceworker-empty-intro-link"
+ >
+ <a
+ onClick={[Function]}
+ />
+ </Localized>
+ </p>
+ <p>
+ <Localized
+ id="serviceworker-empty-suggestions-aboutdebugging2"
+ >
+ <a
+ className="js-trusted-link"
+ onClick={[Function]}
+ />
+ </Localized>
+ </p>
+ </div>
+</article>
+`;
diff --git a/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-Worker.test.js.snap b/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-Worker.test.js.snap
new file mode 100644
index 0000000000..7e71765e90
--- /dev/null
+++ b/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-Worker.test.js.snap
@@ -0,0 +1,132 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Worker Renders the expected snapshot for a non-active worker 1`] = `
+<section
+ className="worker js-sw-worker"
+>
+ <p
+ className="worker__icon"
+ >
+ <img
+ className="worker__icon-image"
+ src="chrome://devtools/skin/images/debugging-workers.svg"
+ />
+ </p>
+ <p
+ className="worker__source"
+ >
+ <span
+ className="js-source-url"
+ >
+ worker.js
+ </span>
+ </p>
+ <p
+ className="worker__misc"
+ >
+ <span
+ className="js-worker-status worker__status worker__status--waiting"
+ >
+ installed
+ </span>
+
+ </p>
+</section>
+`;
+
+exports[`Worker Renders the expected snapshot for a running worker 1`] = `
+<section
+ className="worker js-sw-worker"
+>
+ <p
+ className="worker__icon"
+ >
+ <img
+ className="worker__icon-image"
+ src="chrome://devtools/skin/images/debugging-workers.svg"
+ />
+ </p>
+ <p
+ className="worker__source"
+ >
+ <a
+ className="js-inspect-link"
+ href="#"
+ onClick={[Function]}
+ title="http://example.com/worker.js"
+ >
+ <span
+ className="js-source-url"
+ >
+ worker.js
+ </span>
+  
+ <Localized
+ attrs={
+ Object {
+ "alt": true,
+ }
+ }
+ id="serviceworker-worker-inspect-icon"
+ >
+ <img
+ src="chrome://devtools/skin/images/application-debug.svg"
+ />
+ </Localized>
+ </a>
+ </p>
+ <p
+ className="worker__misc"
+ >
+ <span
+ className="js-worker-status worker__status worker__status--active"
+ >
+ serviceworker-worker-status-running
+ </span>
+
+ </p>
+</section>
+`;
+
+exports[`Worker Renders the expected snapshot for a stopped worker 1`] = `
+<section
+ className="worker js-sw-worker"
+>
+ <p
+ className="worker__icon"
+ >
+ <img
+ className="worker__icon-image"
+ src="chrome://devtools/skin/images/debugging-workers.svg"
+ />
+ </p>
+ <p
+ className="worker__source"
+ >
+ <span
+ className="js-source-url"
+ >
+ worker.js
+ </span>
+ </p>
+ <p
+ className="worker__misc"
+ >
+ <span
+ className="js-worker-status worker__status worker__status--active"
+ >
+ serviceworker-worker-status-stopped
+ </span>
+
+ <Localized
+ id="serviceworker-worker-start3"
+ >
+ <UIButton
+ className="js-start-button"
+ onClick={[Function]}
+ size="micro"
+ />
+ </Localized>
+ </p>
+</section>
+`;
diff --git a/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-WorkersPage.test.js.snap b/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-WorkersPage.test.js.snap
new file mode 100644
index 0000000000..5de3e33b4e
--- /dev/null
+++ b/devtools/client/application/test/node/components/service-workers/__snapshots__/components_application_panel-WorkersPage.test.js.snap
@@ -0,0 +1,143 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`WorkersPage filters out workers from diferent domains 1`] = `
+<section
+ className="app-page js-service-workers-page "
+>
+ <RegistrationList
+ canDebugWorkers={true}
+ registrations={
+ Array [
+ Object {
+ "id": "id-reg-1-example",
+ "registrationFront": "",
+ "scope": "SCOPE1",
+ "workers": Array [
+ Object {
+ "id": "id-worker-1-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ },
+ ],
+ },
+ Object {
+ "id": "id-reg-2-example",
+ "registrationFront": "",
+ "scope": "SCOPE2",
+ "workers": Array [
+ Object {
+ "id": "id-worker-2-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ },
+ ],
+ },
+ ]
+ }
+ />
+</section>
+`;
+
+exports[`WorkersPage filters out workers from different domains and renders an empty list when there is none left 1`] = `
+<section
+ className="app-page js-service-workers-page app-page--empty"
+>
+ <RegistrationListEmpty />
+</section>
+`;
+
+exports[`WorkersPage it renders a list with a single element if there's just 1 worker 1`] = `
+<section
+ className="app-page js-service-workers-page "
+>
+ <RegistrationList
+ canDebugWorkers={true}
+ registrations={
+ Array [
+ Object {
+ "id": "id-reg-1-example",
+ "registrationFront": "",
+ "scope": "SCOPE 123",
+ "workers": Array [
+ Object {
+ "id": "id-worker-1-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ },
+ ],
+ },
+ ]
+ }
+ />
+</section>
+`;
+
+exports[`WorkersPage renders a list with multiple elements when there are multiple workers 1`] = `
+<section
+ className="app-page js-service-workers-page "
+>
+ <RegistrationList
+ canDebugWorkers={true}
+ registrations={
+ Array [
+ Object {
+ "id": "id-reg-1-example",
+ "registrationFront": "",
+ "scope": "SCOPE1",
+ "workers": Array [
+ Object {
+ "id": "id-worker-1-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ },
+ ],
+ },
+ Object {
+ "id": "id-reg-1-example",
+ "registrationFront": "",
+ "scope": "SCOPE2",
+ "workers": Array [
+ Object {
+ "id": "id-worker-2-example",
+ "state": 2,
+ "stateText": "installed",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ },
+ ],
+ },
+ Object {
+ "id": "id-reg-3-example",
+ "registrationFront": "",
+ "scope": "SCOPE3",
+ "workers": Array [
+ Object {
+ "id": "id-worker-3-example",
+ "state": 4,
+ "stateText": "activated",
+ "url": "http://example.com/worker.js",
+ "workerDescriptorFront": "",
+ },
+ ],
+ },
+ ]
+ }
+ />
+</section>
+`;
+
+exports[`WorkersPage renders an empty list if there are no workers 1`] = `
+<section
+ className="app-page js-service-workers-page app-page--empty"
+>
+ <RegistrationListEmpty />
+</section>
+`;
diff --git a/devtools/client/application/test/node/components/service-workers/components_application_panel-Registration.test.js b/devtools/client/application/test/node/components/service-workers/components_application_panel-Registration.test.js
new file mode 100644
index 0000000000..7473a61d23
--- /dev/null
+++ b/devtools/client/application/test/node/components/service-workers/components_application_panel-Registration.test.js
@@ -0,0 +1,88 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+// Import test helpers
+const {
+ setupStore,
+} = require("resource://devtools/client/application/test/node/helpers.js");
+
+const {
+ REGISTRATION_SINGLE_WORKER,
+ REGISTRATION_MULTIPLE_WORKERS,
+} = require("resource://devtools/client/application/test/node/fixtures/data/constants.js");
+
+const Registration = createFactory(
+ require("resource://devtools/client/application/src/components/service-workers/Registration.js")
+);
+
+describe("Registration", () => {
+ it("Renders the expected snapshot for a registration with a worker", () => {
+ const store = setupStore({});
+
+ const wrapper = shallow(
+ Registration({
+ isDebugEnabled: true,
+ registration: REGISTRATION_SINGLE_WORKER,
+ store,
+ })
+ ).dive();
+
+ expect(wrapper).toMatchSnapshot();
+ // ensure that we do have the proper amount of workers
+ expect(wrapper.find("Connect(Worker)")).toHaveLength(1);
+ });
+
+ it("Renders the expected snapshot for a registration with multiple workers", () => {
+ const store = setupStore({});
+
+ const wrapper = shallow(
+ Registration({
+ isDebugEnabled: true,
+ registration: REGISTRATION_MULTIPLE_WORKERS,
+ store,
+ })
+ ).dive();
+
+ expect(wrapper).toMatchSnapshot();
+ // ensure that we do have the proper amount of workers
+ expect(wrapper.find("Connect(Worker)")).toHaveLength(2);
+ });
+
+ it("Renders the expected snapshot when sw debugging is disabled", () => {
+ const store = setupStore({});
+
+ const wrapper = shallow(
+ Registration({
+ isDebugEnabled: false,
+ registration: REGISTRATION_SINGLE_WORKER,
+ store,
+ })
+ ).dive();
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("Removes the ending forward slash from the scope, when present", () => {
+ const store = setupStore({});
+
+ const registration = Object.assign({}, REGISTRATION_SINGLE_WORKER, {
+ scope: "https://example.com/something/",
+ });
+
+ const wrapper = shallow(
+ Registration({
+ isDebugEnabled: false,
+ registration,
+ store,
+ })
+ ).dive();
+
+ const scopeEl = wrapper.find(".js-sw-scope");
+ expect(scopeEl.text()).toBe("example.com/something");
+ });
+});
diff --git a/devtools/client/application/test/node/components/service-workers/components_application_panel-RegistrationList.test.js b/devtools/client/application/test/node/components/service-workers/components_application_panel-RegistrationList.test.js
new file mode 100644
index 0000000000..6bb202cd25
--- /dev/null
+++ b/devtools/client/application/test/node/components/service-workers/components_application_panel-RegistrationList.test.js
@@ -0,0 +1,43 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+// Import constants
+const {
+ SINGLE_WORKER_DEFAULT_DOMAIN_LIST,
+ MULTIPLE_WORKER_LIST,
+} = require("resource://devtools/client/application/test/node/fixtures/data/constants.js");
+
+const RegistrationList = createFactory(
+ require("resource://devtools/client/application/src/components/service-workers/RegistrationList.js")
+);
+
+/**
+ * Test for RegistrationList.js component
+ */
+describe("RegistrationList", () => {
+ it("renders the expected snapshot for a list with a single registration", () => {
+ const wrapper = shallow(
+ RegistrationList({
+ registrations: SINGLE_WORKER_DEFAULT_DOMAIN_LIST,
+ canDebugWorkers: true,
+ })
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders the expected snapshot for a multiple registration list", () => {
+ const wrapper = shallow(
+ RegistrationList({
+ registrations: MULTIPLE_WORKER_LIST,
+ canDebugWorkers: true,
+ })
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/service-workers/components_application_panel-RegistrationListEmpty.test.js b/devtools/client/application/test/node/components/service-workers/components_application_panel-RegistrationListEmpty.test.js
new file mode 100644
index 0000000000..811535facc
--- /dev/null
+++ b/devtools/client/application/test/node/components/service-workers/components_application_panel-RegistrationListEmpty.test.js
@@ -0,0 +1,23 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+const RegistrationListEmpty = createFactory(
+ require("resource://devtools/client/application/src/components/service-workers/RegistrationListEmpty.js")
+);
+
+/**
+ * Test for RegistrationListEmpty.js component
+ */
+
+describe("RegistrationListEmpty", () => {
+ it("renders the expected snapshot", () => {
+ const wrapper = shallow(RegistrationListEmpty({}));
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/service-workers/components_application_panel-Worker.test.js b/devtools/client/application/test/node/components/service-workers/components_application_panel-Worker.test.js
new file mode 100644
index 0000000000..36a6acda0c
--- /dev/null
+++ b/devtools/client/application/test/node/components/service-workers/components_application_panel-Worker.test.js
@@ -0,0 +1,110 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+// Import test helpers
+const {
+ setupStore,
+} = require("resource://devtools/client/application/test/node/helpers.js");
+
+const {
+ WORKER_RUNNING,
+ WORKER_STOPPED,
+ WORKER_WAITING,
+} = require("resource://devtools/client/application/test/node/fixtures/data/constants.js");
+
+const Worker = createFactory(
+ require("resource://devtools/client/application/src/components/service-workers/Worker.js")
+);
+
+describe("Worker", () => {
+ it("Renders the expected snapshot for a running worker", () => {
+ const store = setupStore({});
+
+ const wrapper = shallow(
+ Worker({
+ isDebugEnabled: true,
+ worker: WORKER_RUNNING,
+ store,
+ })
+ ).dive();
+
+ // ensure proper status
+ expect(wrapper.find(".js-worker-status").text()).toBe(
+ "serviceworker-worker-status-running"
+ );
+ // check that Start button is not available
+ expect(wrapper.find(".js-start-button")).toHaveLength(0);
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("Renders the expected snapshot for a stopped worker", () => {
+ const store = setupStore({});
+
+ const wrapper = shallow(
+ Worker({
+ isDebugEnabled: true,
+ worker: WORKER_STOPPED,
+ store,
+ })
+ ).dive();
+
+ // ensure proper status
+ expect(wrapper.find(".js-worker-status").text()).toBe(
+ "serviceworker-worker-status-stopped"
+ );
+ // check that Start button is available
+ expect(wrapper.find(".js-start-button")).toHaveLength(1);
+ // check that inspect link does not exist
+ expect(wrapper.find(".js-inspect-link")).toHaveLength(0);
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("Renders the start button even if debugging workers is disabled", () => {
+ const store = setupStore({});
+
+ const wrapper = shallow(
+ Worker({
+ isDebugEnabled: false,
+ worker: WORKER_STOPPED,
+ store,
+ })
+ ).dive();
+
+ // ensure proper status
+ expect(wrapper.find(".js-worker-status").text()).toBe(
+ "serviceworker-worker-status-stopped"
+ );
+ // check that Start button is available
+ expect(wrapper.find(".js-start-button")).toHaveLength(1);
+ });
+
+ it("Renders the expected snapshot for a non-active worker", () => {
+ const store = setupStore({});
+
+ const wrapper = shallow(
+ Worker({
+ isDebugEnabled: true,
+ worker: WORKER_WAITING,
+ store,
+ })
+ ).dive();
+
+ // ensure proper status
+ // NOTE: since non-active status are localized directly in the front, not
+ // in the panel, we don't expect a localization ID here
+ expect(wrapper.find(".js-worker-status").text()).toBe("installed");
+ // check that Start button is not available
+ expect(wrapper.find(".js-start-button")).toHaveLength(0);
+ // check that Debug link does not exist
+ expect(wrapper.find(".js-inspect-link")).toHaveLength(0);
+
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/application/test/node/components/service-workers/components_application_panel-WorkersPage.test.js b/devtools/client/application/test/node/components/service-workers/components_application_panel-WorkersPage.test.js
new file mode 100644
index 0000000000..be1b14f216
--- /dev/null
+++ b/devtools/client/application/test/node/components/service-workers/components_application_panel-WorkersPage.test.js
@@ -0,0 +1,82 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Import libs
+const { shallow } = require("enzyme");
+const { createFactory } = require("react");
+
+// Import fixtures
+const {
+ EMPTY_WORKER_LIST,
+ SINGLE_WORKER_DEFAULT_DOMAIN_LIST,
+ SINGLE_WORKER_DIFFERENT_DOMAIN_LIST,
+ MULTIPLE_WORKER_LIST,
+ MULTIPLE_WORKER_MIXED_DOMAINS_LIST,
+} = require("resource://devtools/client/application/test/node/fixtures/data/constants.js");
+
+// Import setupStore with imported & combined reducers
+const {
+ setupStore,
+} = require("resource://devtools/client/application/test/node/helpers.js");
+
+// Import component
+const WorkersPage = createFactory(
+ require("resource://devtools/client/application/src/components/service-workers/WorkersPage.js")
+);
+
+/**
+ * Test for App.js component
+ */
+describe("WorkersPage", () => {
+ const baseState = {
+ workers: { list: [], canDebugWorkers: true },
+ page: { domain: "example.com" },
+ };
+
+ function buildStoreWithWorkers(workerList) {
+ const workers = { list: workerList, canDebugWorkers: true };
+ const state = Object.assign({}, baseState, { workers });
+ return setupStore(state);
+ }
+
+ it("renders an empty list if there are no workers", () => {
+ const store = buildStoreWithWorkers(EMPTY_WORKER_LIST);
+ const wrapper = shallow(WorkersPage({ store })).dive();
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("it renders a list with a single element if there's just 1 worker", () => {
+ const store = buildStoreWithWorkers(SINGLE_WORKER_DEFAULT_DOMAIN_LIST);
+ const wrapper = shallow(WorkersPage({ store })).dive();
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("renders a list with multiple elements when there are multiple workers", () => {
+ const store = buildStoreWithWorkers(MULTIPLE_WORKER_LIST);
+ const wrapper = shallow(WorkersPage({ store })).dive();
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it("filters out workers from diferent domains", () => {
+ const store = buildStoreWithWorkers(MULTIPLE_WORKER_MIXED_DOMAINS_LIST);
+ const wrapper = shallow(WorkersPage({ store })).dive();
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it(
+ "filters out workers from different domains and renders an empty list when " +
+ "there is none left",
+ () => {
+ const store = buildStoreWithWorkers(SINGLE_WORKER_DIFFERENT_DOMAIN_LIST);
+ const wrapper = shallow(WorkersPage({ store })).dive();
+
+ expect(wrapper).toMatchSnapshot();
+ }
+ );
+});