Bug 1565172 Add routing support for Manifest page, r=ladybenko,fluent-reviewers,flod
authorOla Gasidlo <ogasidlo@mozilla.com>
Tue, 13 Aug 2019 13:18:23 +0000
changeset 487658 ee1d903b21e90c792457c10107b45b070d42cb24
parent 487657 fa5a02a46c5077a565aec9448be5da7cd23709d1
child 487659 5ea843b6282cf499ed798088ff06af24b97bfe4f
push id36429
push userdvarga@mozilla.com
push dateTue, 13 Aug 2019 21:52:12 +0000
treeherdermozilla-central@eff8c62bdeb7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersladybenko, fluent-reviewers, flod
bugs1565172
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1565172 Add routing support for Manifest page, r=ladybenko,fluent-reviewers,flod Add routing support for Manifest page with simple CSS and fluent string for `no manifest found` Differential Revision: https://phabricator.services.mozilla.com/D40808
devtools/client/application/application.css
devtools/client/application/src/components/layout/PageContainer.js
devtools/client/application/src/components/manifest/ManifestPage.css
devtools/client/application/src/components/manifest/ManifestPage.js
devtools/client/application/src/components/manifest/moz.build
devtools/client/application/src/components/moz.build
devtools/client/application/src/constants.js
devtools/client/application/test/browser/browser_application_panel_debug-service-worker.js
devtools/client/application/test/browser/browser_application_panel_list-domain-workers.js
devtools/client/application/test/browser/browser_application_panel_list-several-workers.js
devtools/client/application/test/browser/browser_application_panel_list-single-worker.js
devtools/client/application/test/browser/browser_application_panel_list-unicode.js
devtools/client/application/test/browser/browser_application_panel_list-workers-empty.js
devtools/client/application/test/browser/browser_application_panel_open-links.js
devtools/client/application/test/browser/browser_application_panel_start-service-worker.js
devtools/client/application/test/browser/browser_application_panel_unregister-worker.js
devtools/client/application/test/browser/head.js
devtools/client/application/test/components/layout/__snapshots__/components_application_panel-PageContainer.test.js.snap
devtools/client/application/test/components/layout/components_application_panel-PageContainer.test.js
devtools/client/application/test/components/manifest/__snapshots__/components_application_panel-ManifestPage.test.js.snap
devtools/client/application/test/components/manifest/components_application_panel-ManifestPage.test.js
devtools/client/locales/en-US/application.ftl
--- a/devtools/client/application/application.css
+++ b/devtools/client/application/application.css
@@ -6,16 +6,17 @@
 * Global styles
 */
 @import "resource://devtools/client/application/src/base.css";
 
 /*
 * Components
 */
 @import "resource://devtools/client/application/src/components/App.css";
+@import "resource://devtools/client/application/src/components/manifest/ManifestPage.css";
 @import "resource://devtools/client/application/src/components/service-workers/Worker.css";
 @import "resource://devtools/client/application/src/components/service-workers/WorkerList.css";
 @import "resource://devtools/client/application/src/components/service-workers/WorkerListEmpty.css";
 @import "resource://devtools/client/application/src/components/service-workers/WorkersPage.css";
 @import "resource://devtools/client/application/src/components/ui/UIButton.css";
 
 html,
 body,
--- a/devtools/client/application/src/components/layout/PageContainer.js
+++ b/devtools/client/application/src/components/layout/PageContainer.js
@@ -8,32 +8,39 @@ const {
   createFactory,
   PureComponent,
 } = require("devtools/client/shared/vendor/react");
 const { connect } = require("devtools/client/shared/vendor/react-redux");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 
 const { PAGE_TYPES } = require("../../constants");
 
+const ManifestPage = createFactory(require("../manifest/ManifestPage"));
 const WorkersPage = createFactory(require("../service-workers/WorkersPage"));
 
 class PageContainer extends PureComponent {
   static get propTypes() {
     return {
       page: PropTypes.oneOf(Object.values(PAGE_TYPES)),
     };
   }
 
   render() {
     let component = null;
 
     switch (this.props.page) {
+      case PAGE_TYPES.MANIFEST:
+        component = ManifestPage({});
+        break;
       case PAGE_TYPES.SERVICE_WORKERS:
         component = WorkersPage({});
         break;
+      default:
+        console.error("Unknown path. Can not direct to a page.");
+        return null;
     }
 
     return component;
   }
 }
 
 function mapStateToProps(state) {
   return {
new file mode 100644
--- /dev/null
+++ b/devtools/client/application/src/components/manifest/ManifestPage.css
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.manifest-page {
+	height: 100vh;
+  padding: 0 2rem;
+  display: grid;
+  -moz-user-select: none;
+
+  /* slipt up in components in https://bugzilla.mozilla.org/show_bug.cgi?id=1566011 */
+  align-items: center;
+  justify-content: center;
+  font-size: var(--title-10-font-size);
+  color: var(--theme-toolbar-color);
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/application/src/components/manifest/ManifestPage.js
@@ -0,0 +1,30 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {
+  createFactory,
+  PureComponent,
+} = require("devtools/client/shared/vendor/react");
+const {
+  section,
+} = require("devtools/client/shared/vendor/react-dom-factories");
+
+const FluentReact = require("devtools/client/shared/vendor/fluent-react");
+const Localized = createFactory(FluentReact.Localized);
+
+class ManifestPage extends PureComponent {
+  render() {
+    return Localized(
+      {
+        id: "manifest-empty-intro",
+      },
+      section({ className: `manifest-page` })
+    );
+  }
+}
+
+// Exports
+module.exports = ManifestPage;
new file mode 100644
--- /dev/null
+++ b/devtools/client/application/src/components/manifest/moz.build
@@ -0,0 +1,8 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DevToolsModules(
+    'ManifestPage.css',
+    'ManifestPage.js'
+)
--- a/devtools/client/application/src/components/moz.build
+++ b/devtools/client/application/src/components/moz.build
@@ -1,14 +1,15 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += [
     'layout',
+    'manifest',
     'service-workers',
     'ui',
 ]
 
 DevToolsModules(
     'App.css',
     'App.js',
 )
--- a/devtools/client/application/src/constants.js
+++ b/devtools/client/application/src/constants.js
@@ -10,15 +10,16 @@ const actionTypes = {
   // ui substate
   UPDATE_SELECTED_PAGE: "UPDATE_SELECTED_PAGE",
   // workers substate
   UPDATE_CAN_DEBUG_WORKERS: "UPDATE_CAN_DEBUG_WORKERS",
   UPDATE_WORKERS: "UPDATE_WORKERS",
 };
 
 const PAGE_TYPES = {
+  MANIFEST: "manifest",
   SERVICE_WORKERS: "service-workers",
 };
 
-const DEFAULT_PAGE = PAGE_TYPES.SERVICE_WORKERS;
+const DEFAULT_PAGE = PAGE_TYPES.MANIFEST;
 
 // flatten constants
 module.exports = Object.assign({}, { DEFAULT_PAGE, PAGE_TYPES }, actionTypes);
--- a/devtools/client/application/test/browser/browser_application_panel_debug-service-worker.js
+++ b/devtools/client/application/test/browser/browser_application_panel_debug-service-worker.js
@@ -18,16 +18,19 @@ Services.scriptloader.loadSubScript(
 const TAB_URL = URL_ROOT + "resources/service-workers/debug.html";
 
 add_task(async function() {
   await enableApplicationPanel();
 
   const { panel, tab, target } = await openNewTabAndApplicationPanel(TAB_URL);
   const doc = panel.panelWin.document;
 
+  // select service worker view
+  selectPage(panel, "service-workers");
+
   info("Wait until the service worker appears in the application panel");
   await waitUntil(() => getWorkerContainers(doc).length === 1);
 
   const container = getWorkerContainers(doc)[0];
   info("Wait until the debug button is displayed and enabled");
   await waitUntil(() => {
     const button = container.querySelector(".js-debug-button");
     return button && !button.disabled;
--- a/devtools/client/application/test/browser/browser_application_panel_list-domain-workers.js
+++ b/devtools/client/application/test/browser/browser_application_panel_list-domain-workers.js
@@ -16,16 +16,19 @@ const EMPTY_URL = (URL_ROOT + "resources
 );
 
 add_task(async function() {
   await enableApplicationPanel();
 
   const { panel, target } = await openNewTabAndApplicationPanel(SIMPLE_URL);
   const doc = panel.panelWin.document;
 
+  // select service worker view
+  selectPage(panel, "service-workers");
+
   info("Wait until the service worker appears in the application panel");
   await waitUntil(() => getWorkerContainers(doc).length === 1);
 
   let scopeEl = getWorkerContainers(doc)[0].querySelector(".js-sw-scope");
   ok(
     scopeEl.textContent.startsWith("example.com"),
     "First service worker registration is displayed for the correct domain"
   );
--- a/devtools/client/application/test/browser/browser_application_panel_list-several-workers.js
+++ b/devtools/client/application/test/browser/browser_application_panel_list-several-workers.js
@@ -12,16 +12,19 @@ const SIMPLE_URL = URL_ROOT + "resources
 const OTHER_SCOPE_URL = URL_ROOT + "resources/service-workers/scope-page.html";
 
 add_task(async function() {
   await enableApplicationPanel();
 
   const { panel, target } = await openNewTabAndApplicationPanel(SIMPLE_URL);
   const doc = panel.panelWin.document;
 
+  // select service worker view
+  selectPage(panel, "service-workers");
+
   info("Wait until the service worker appears in the application panel");
   await waitUntil(() => getWorkerContainers(doc).length === 1);
 
   info("Wait until the unregister button is displayed for the service worker");
   await waitUntil(() =>
     getWorkerContainers(doc)[0].querySelector(".js-unregister-button")
   );
 
--- a/devtools/client/application/test/browser/browser_application_panel_list-single-worker.js
+++ b/devtools/client/application/test/browser/browser_application_panel_list-single-worker.js
@@ -7,16 +7,19 @@ const TAB_URL =
   URL_ROOT + "resources/service-workers/dynamic-registration.html";
 
 add_task(async function() {
   await enableApplicationPanel();
 
   const { panel, tab } = await openNewTabAndApplicationPanel(TAB_URL);
   const doc = panel.panelWin.document;
 
+  // select service worker view
+  selectPage(panel, "service-workers");
+
   const isWorkerListEmpty = !!doc.querySelector(".worker-list-empty");
   ok(isWorkerListEmpty, "No Service Worker displayed");
 
   info("Register a service worker in the page.");
   await ContentTask.spawn(tab.linkedBrowser, {}, async function() {
     content.wrappedJSObject.registerServiceWorker();
   });
 
--- a/devtools/client/application/test/browser/browser_application_panel_list-unicode.js
+++ b/devtools/client/application/test/browser/browser_application_panel_list-unicode.js
@@ -13,16 +13,19 @@ const TAB_URL = (
  */
 
 add_task(async function() {
   await enableApplicationPanel();
 
   const { panel, target } = await openNewTabAndApplicationPanel(TAB_URL);
   const doc = panel.panelWin.document;
 
+  // select service worker view
+  selectPage(panel, "service-workers");
+
   info("Wait until the service worker appears in the application panel");
   await waitUntil(() => getWorkerContainers(doc).length === 1);
 
   const workerContainer = getWorkerContainers(doc)[0];
 
   const scopeEl = workerContainer.querySelector(".js-sw-scope");
   ok(
     scopeEl.textContent.startsWith(
--- a/devtools/client/application/test/browser/browser_application_panel_list-workers-empty.js
+++ b/devtools/client/application/test/browser/browser_application_panel_list-workers-empty.js
@@ -11,15 +11,18 @@
 const EMPTY_URL = URL_ROOT + "resources/service-workers/empty.html";
 
 add_task(async function() {
   await enableApplicationPanel();
 
   const { panel, tab } = await openNewTabAndApplicationPanel(EMPTY_URL);
   const doc = panel.panelWin.document;
 
+  // select service worker view
+  selectPage(panel, "service-workers");
+
   await waitUntil(() => doc.querySelector(".js-worker-list-empty") !== null);
   ok(true, "No service workers are shown for an empty page");
 
   // close the tab
   info("Closing the tab.");
   await BrowserTestUtils.removeTab(tab);
 });
--- a/devtools/client/application/test/browser/browser_application_panel_open-links.js
+++ b/devtools/client/application/test/browser/browser_application_panel_open-links.js
@@ -10,18 +10,20 @@ const { Toolbox } = require("devtools/cl
  */
 
 const TAB_URL = URL_ROOT + "resources/service-workers/empty.html";
 
 add_task(async function() {
   await enableApplicationPanel();
 
   const { panel, toolbox } = await openNewTabAndApplicationPanel(TAB_URL);
+  const doc = panel.panelWin.document;
 
-  const doc = panel.panelWin.document;
+  // select service worker view
+  selectPage(panel, "service-workers");
 
   // detach devtools in a separate window
   await toolbox.switchHost(Toolbox.HostType.WINDOW);
 
   // click on the link and wait for the new tab to open
   const onTabLoaded = BrowserTestUtils.waitForNewTab(
     gBrowser,
     "about:debugging#workers"
--- a/devtools/client/application/test/browser/browser_application_panel_start-service-worker.js
+++ b/devtools/client/application/test/browser/browser_application_panel_start-service-worker.js
@@ -16,16 +16,19 @@ add_task(async function() {
   // The default value is 30000 milliseconds.
   info("Set a low service worker idle timeout");
   await pushPref("dom.serviceWorkers.idle_timeout", 1000);
   await pushPref("dom.serviceWorkers.idle_extended_timeout", 1000);
 
   const { panel, tab, target } = await openNewTabAndApplicationPanel(TAB_URL);
   const doc = panel.panelWin.document;
 
+  // select service worker view
+  selectPage(panel, "service-workers");
+
   await waitForWorkerRegistration(tab);
 
   info("Wait until the service worker appears in the application panel");
   await waitUntil(() => getWorkerContainers(doc).length === 1);
 
   info("Wait until the start button is displayed and enabled");
   const container = getWorkerContainers(doc)[0];
   await waitUntil(() => {
@@ -54,16 +57,20 @@ add_task(async function() {
   await enableApplicationPanel();
 
   // disable sw debugging by increasing the # of processes and thus multi-e10s kicking in
   info("Disable service worker debugging");
   await pushPref("dom.ipc.processCount", 8);
 
   const { panel, tab, target } = await openNewTabAndApplicationPanel(TAB_URL);
   const doc = panel.panelWin.document;
+
+  // select service worker view
+  selectPage(panel, "service-workers");
+
   await waitForWorkerRegistration(tab);
 
   info("Wait until the service worker appears in the application panel");
   await waitUntil(() => getWorkerContainers(doc).length === 1);
 
   info("Wait until the start button is displayed");
   const container = getWorkerContainers(doc)[0];
   await waitUntil(() => container.querySelector(".js-start-button"));
--- a/devtools/client/application/test/browser/browser_application_panel_unregister-worker.js
+++ b/devtools/client/application/test/browser/browser_application_panel_unregister-worker.js
@@ -6,16 +6,19 @@
 const TAB_URL = URL_ROOT + "resources/service-workers/simple.html";
 
 add_task(async function() {
   await enableApplicationPanel();
 
   const { panel, tab, target } = await openNewTabAndApplicationPanel(TAB_URL);
   const doc = panel.panelWin.document;
 
+  // select service worker view
+  selectPage(panel, "service-workers");
+
   info("Wait until the service worker appears in the application panel");
   await waitUntil(() => getWorkerContainers(doc).length === 1);
 
   const workerContainer = getWorkerContainers(doc)[0];
 
   info("Wait until the unregister button is displayed for the service worker");
   await waitUntil(() => workerContainer.querySelector(".js-unregister-button"));
   info("Click the unregister button");
--- a/devtools/client/application/test/browser/head.js
+++ b/devtools/client/application/test/browser/head.js
@@ -76,8 +76,17 @@ async function waitForWorkerRegistration
   info("Wait until the registration appears on the window");
   const swBrowser = swTab.linkedBrowser;
   await asyncWaitUntil(async () =>
     ContentTask.spawn(swBrowser, {}, function() {
       return content.wrappedJSObject.getRegistration();
     })
   );
 }
+
+// TODO: update this function once the sidebar links are implemented (See bug
+// https: //bugzilla.mozilla.org/show_bug.cgi?id=1565213), and switch to to
+// click those links instead, since it's more representative of what users do
+function selectPage(panel, page) {
+  info(`Selecting application page: ${page}`);
+  const actions = panel.panelWin.Application.actions;
+  actions.updateSelectedPage(page);
+}
--- a/devtools/client/application/test/components/layout/__snapshots__/components_application_panel-PageContainer.test.js.snap
+++ b/devtools/client/application/test/components/layout/__snapshots__/components_application_panel-PageContainer.test.js.snap
@@ -1,7 +1,9 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`PageContainer renders nothing when an invalid page is selected 1`] = `""`;
 
 exports[`PageContainer renders nothing when no page is selected 1`] = `""`;
 
+exports[`PageContainer renders the ManifestPage component when manifest page is selected 1`] = `<ManifestPage />`;
+
 exports[`PageContainer renders the WorkersPage component when workers page is selected 1`] = `<Connect(WorkersPage) />`;
--- a/devtools/client/application/test/components/layout/components_application_panel-PageContainer.test.js
+++ b/devtools/client/application/test/components/layout/components_application_panel-PageContainer.test.js
@@ -2,16 +2,18 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Import libs
 const { shallow } = require("enzyme");
 const { createFactory } = require("react");
 
+console.error = jest.fn();
+
 // Import setupStore with imported & combined reducers
 const {
   setupStore,
 } = require("devtools/client/application/test/components/helpers/helpers");
 
 const PageContainer = createFactory(
   require("devtools/client/application/src/components/layout/PageContainer")
 );
@@ -28,26 +30,38 @@ describe("PageContainer", () => {
       preloadedState: {
         ui: {
           selectedPage,
         },
       },
     });
   }
 
+  beforeEach(() => {
+    console.error.mockClear();
+  });
+
+  it("renders the ManifestPage component when manifest page is selected", () => {
+    const store = buildStoreWithSelectedPage(PAGE_TYPES.MANIFEST);
+    const wrapper = shallow(PageContainer({ 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(PageContainer({ store })).dive();
     expect(wrapper).toMatchSnapshot();
   });
 
   it("renders nothing when no page is selected", () => {
     const store = buildStoreWithSelectedPage(null);
     const wrapper = shallow(PageContainer({ 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(PageContainer({ store })).dive();
+    expect(console.error).toHaveBeenCalledTimes(1);
     expect(wrapper).toMatchSnapshot();
   });
 });
new file mode 100644
--- /dev/null
+++ b/devtools/client/application/test/components/manifest/__snapshots__/components_application_panel-ManifestPage.test.js.snap
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ManifestPage renders the expected snapshot 1`] = `
+<Localized
+  id="manifest-empty-intro"
+>
+  <section
+    className="manifest-page"
+  />
+</Localized>
+`;
new file mode 100644
--- /dev/null
+++ b/devtools/client/application/test/components/manifest/components_application_panel-ManifestPage.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 ManifestPage = createFactory(
+  require("devtools/client/application/src/components/manifest/ManifestPage")
+);
+
+/**
+ * Test for ManifestPage.js component
+ */
+
+describe("ManifestPage", () => {
+  it("renders the expected snapshot", () => {
+    const wrapper = shallow(ManifestPage({}));
+    expect(wrapper).toMatchSnapshot();
+  });
+});
--- a/devtools/client/locales/en-US/application.ftl
+++ b/devtools/client/locales/en-US/application.ftl
@@ -74,8 +74,11 @@ serviceworker-empty-suggestions-console 
 
 # Suggestion to use the debugger to investigate why a service worker is not registered.
 # Clicking on the link will switch from the Application panel to the debugger.
 serviceworker-empty-suggestions-debugger = Step through your Service Worker registration and look for exceptions. <a>Open the Debugger</a>
 
 # Suggestion to go to about:debugging in order to see Service Workers for all domains.
 # Clicking on the link will open about:debugging in a new tab.
 serviceworker-empty-suggestions-aboutdebugging = Inspect Service Workers from other domains. <a>Open about:debugging</a>
+
+# Text displayed when no manifest was found for the current page.
+manifest-empty-intro = No manifest found to inspect.