Bug 1565213 - Add routing for sidebar component, r=ladybenko

Add routing for sidebar component

Differential Revision: https://phabricator.services.mozilla.com/D43726

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ola Gasidlo 2019-09-12 12:55:46 +00:00
Родитель 8bc66c201a
Коммит caf9aff884
28 изменённых файлов: 367 добавлений и 51 удалений

Просмотреть файл

@ -1,3 +1,7 @@
/* 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-issues {
list-style-type: none;
padding-inline-start: 0;

Просмотреть файл

@ -8,8 +8,8 @@
.manifest-item__label {
color: var(--theme-text-color-alt);
font-weight: var(--title-30-font-weight);
width: calc(var(--base-unit) * 28);
font-weight: var(--title-10-font-weight);
text-align: right;
}

Просмотреть файл

@ -48,7 +48,9 @@ class ManifestPage extends PureComponent {
return section(
{
className: `app-page ${!manifest ? "app-page--empty" : ""}`,
className: `app-page js-manifest-page ${
!manifest ? "app-page--empty" : ""
}`,
},
this.shouldShowLoader ? ManifestLoader({}) : this.renderManifest()
);

Просмотреть файл

@ -6,6 +6,8 @@
padding-block: calc(var(--base-unit) * 2);
width: 100%;
border-spacing: calc(var(--base-unit) * 2) 0;
font-size: var(--body-10-font-size);
font-weight: var(--body-10-font-weight);
}
.manifest-section--empty {

Просмотреть файл

@ -12,18 +12,32 @@ const {
aside,
ul,
} = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const SidebarItem = createFactory(require("./SidebarItem"));
const { PAGE_TYPES } = require("../../constants");
class Sidebar extends PureComponent {
static get propTypes() {
return {
// this prop is automatically injected via connect
selectedPage: PropTypes.oneOf(Object.values(PAGE_TYPES)),
};
}
render() {
const navItems = Object.values(PAGE_TYPES);
const isSelected = page => {
return page === this.props.selectedPage;
};
return aside(
{
className: "sidebar",
className: "sidebar js-sidebar",
},
ul(
{
@ -33,6 +47,7 @@ class Sidebar extends PureComponent {
return SidebarItem({
page: page,
key: `sidebar-item-${page}`,
isSelected: isSelected(page),
});
})
)
@ -40,5 +55,10 @@ class Sidebar extends PureComponent {
}
}
// Exports
module.exports = Sidebar;
function mapStateToProps(state) {
return {
selectedPage: state.ui.selectedPage,
};
}
module.exports = connect(mapStateToProps)(Sidebar);

Просмотреть файл

@ -12,9 +12,16 @@
grid-template-columns: auto 1fr;
grid-gap: var(--base-unit);
padding: calc(var(--base-unit)) calc(var(--base-unit) * 6);
user-select: none;
cursor: pointer;
}
.sidebar-item:hover {
.sidebar-item--selected {
background-color: var(--theme-selection-background);
color: var(--theme-selection-color);
}
.sidebar-item:not(.sidebar-item--selected):hover {
background-color: var(--highlight-color);
}
@ -23,5 +30,4 @@
width: calc(var(--base-unit) * 4);
-moz-context-properties: fill;
fill: currentColor;
}

Просмотреть файл

@ -16,6 +16,9 @@ const {
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const Actions = require("./../../actions/index");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const FluentReact = require("devtools/client/shared/vendor/fluent-react");
const Localized = createFactory(FluentReact.Localized);
@ -37,12 +40,26 @@ class SidebarItem extends PureComponent {
static get propTypes() {
return {
page: PropTypes.oneOf(Object.values(PAGE_TYPES)),
isSelected: PropTypes.bool.isRequired,
// this prop is automatically injected via connect
dispatch: PropTypes.func.isRequired,
};
}
render() {
const { page } = this.props;
const { isSelected, page } = this.props;
return li(
{ className: "sidebar-item" },
{
className: `sidebar-item js-sidebar-${page} ${
isSelected ? "sidebar-item--selected" : ""
}`,
onClick: () => {
const { dispatch } = this.props;
dispatch(Actions.updateSelectedPage(page));
},
role: "link",
},
Localized(
{
id: LOCALIZATION_IDS[page],
@ -69,5 +86,5 @@ class SidebarItem extends PureComponent {
}
}
// Exports
module.exports = SidebarItem;
const mapDispatchToProps = dispatch => ({ dispatch });
module.exports = connect(mapDispatchToProps)(SidebarItem);

Просмотреть файл

@ -38,7 +38,9 @@ class WorkersPage extends PureComponent {
return section(
{
className: `app-page ${isWorkerListEmpty ? "app-page--empty" : ""}`,
className: `app-page js-service-workers-page ${
isWorkerListEmpty ? "app-page--empty" : ""
}`,
},
isWorkerListEmpty
? WorkerListEmpty({})

Просмотреть файл

@ -19,6 +19,7 @@ const actionTypes = {
UPDATE_WORKERS: "UPDATE_WORKERS",
};
// NOTE: these const values are used as part of CSS selectors - be mindful of the characters used
const PAGE_TYPES = {
MANIFEST: "manifest",
SERVICE_WORKERS: "service-workers",

Просмотреть файл

@ -23,6 +23,7 @@ support-files =
!/devtools/client/shared/test/shared-head.js
!/devtools/client/shared/test/telemetry-test-helpers.js
[browser_application_panel_sidebar.js]
[browser_application_panel_debug-service-worker.js]
skip-if = debug # Bug 1559591
[browser_application_panel_list-domain-workers.js]

Просмотреть файл

@ -23,7 +23,6 @@ add_task(async function() {
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");

Просмотреть файл

@ -21,7 +21,6 @@ add_task(async function() {
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");

Просмотреть файл

@ -17,7 +17,6 @@ add_task(async function() {
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");

Просмотреть файл

@ -12,9 +12,9 @@ add_task(async function() {
const { panel, tab } = await openNewTabAndApplicationPanel(TAB_URL);
const doc = panel.panelWin.document;
// select service worker view
selectPage(panel, "service-workers");
info("Check for non-existing service worker");
const isWorkerListEmpty = !!doc.querySelector(".worker-list-empty");
ok(isWorkerListEmpty, "No Service Worker displayed");

Просмотреть файл

@ -18,7 +18,6 @@ add_task(async function() {
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");

Просмотреть файл

@ -16,7 +16,6 @@ add_task(async function() {
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);

Просмотреть файл

@ -17,7 +17,6 @@ add_task(async function() {
const { panel, toolbox } = await openNewTabAndApplicationPanel(TAB_URL);
const doc = panel.panelWin.document;
// select service worker view
selectPage(panel, "service-workers");
// detach devtools in a separate window

Просмотреть файл

@ -0,0 +1,80 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Check that the manifest is being properly shown
*/
add_task(async function() {
info("Test that we are displaying correctly the sidebar");
await enableApplicationPanel();
const { panel, tab } = await openNewTabAndApplicationPanel();
const doc = panel.panelWin.document;
info("Waiting for the sidebar to be displayed");
await waitUntil(() => doc.querySelector(".js-sidebar") !== null);
ok(true, "Sidebar is being displayed");
await waitUntil(() => doc.querySelector(".js-manifest-page") !== null);
ok(true, "Manifest page was loaded per default.");
// close the tab
info("Closing the tab.");
await BrowserTestUtils.removeTab(tab);
});
add_task(async function() {
info("Test that we are displaying correctly the selected page - manifest");
await enableApplicationPanel();
const { panel, tab, target } = await openNewTabAndApplicationPanel();
const doc = panel.panelWin.document;
info("Select service worker page");
selectPage(panel, "service-workers");
await waitUntil(() => doc.querySelector(".js-service-workers-page") !== null);
info("Select manifest page in the sidebar");
const link = doc.querySelector(".js-sidebar-manifest");
link.click();
await waitUntil(() => doc.querySelector(".js-manifest-page") !== null);
ok(true, "Manifest page was selected.");
await unregisterAllWorkers(target.client);
// close the tab
info("Closing the tab.");
await BrowserTestUtils.removeTab(tab);
});
add_task(async function() {
info(
"Test that we are displaying correctly the selected page - service workers"
);
const url = URL_ROOT + "resources/manifest/load-ok.html";
await enableApplicationPanel();
const { panel, tab } = await openNewTabAndApplicationPanel(url);
const doc = panel.panelWin.document;
selectPage(panel, "manifest");
info("Waiting for the manifest to load");
await waitUntil(() => doc.querySelector(".js-manifest-page") !== null);
ok(true, "Manifest page was selected.");
info("Select service worker page in the sidebar");
const link = doc.querySelector(".js-sidebar-service-workers");
link.click();
await waitUntil(() => doc.querySelector(".js-service-workers-page") !== null);
ok(true, "Service workers page was selected.");
// close the tab
info("Closing the tab.");
await BrowserTestUtils.removeTab(tab);
});

Просмотреть файл

@ -21,7 +21,6 @@ add_task(async function() {
const { panel, tab, target } = await openNewTabAndApplicationPanel(TAB_URL);
const doc = panel.panelWin.document;
// select service worker view
selectPage(panel, "service-workers");
await waitForWorkerRegistration(tab);
@ -63,7 +62,6 @@ add_task(async function() {
const { panel, tab, target } = await openNewTabAndApplicationPanel(TAB_URL);
const doc = panel.panelWin.document;
// select service worker view
selectPage(panel, "service-workers");
await waitForWorkerRegistration(tab);

Просмотреть файл

@ -11,7 +11,6 @@ add_task(async function() {
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");

Просмотреть файл

@ -82,11 +82,13 @@ async function waitForWorkerRegistration(swTab) {
);
}
// 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) {
/**
* Select a page by simulating a user click in the sidebar.
* @param {string} page The page we want to select (see `PAGE_TYPES`)
**/
info(`Selecting application page: ${page}`);
const actions = panel.panelWin.Application.actions;
actions.updateSelectedPage(page);
const doc = panel.panelWin.document;
const navItem = doc.querySelector(`.js-sidebar-${page}`);
navItem.click();
}

Просмотреть файл

@ -5,7 +5,7 @@ exports[`App renders the expected snapshot 1`] = `
<main
className="app"
>
<Sidebar />
<Connect(Sidebar) />
<Connect(PageSwitcher) />
</main>
</LocalizationProvider>

Просмотреть файл

@ -2,7 +2,7 @@
exports[`ManifestPage renders the expected snapshot when the manifest is loading 1`] = `
<section
className="app-page app-page--empty"
className="app-page js-manifest-page app-page--empty"
>
<Connect(ManifestLoader) />
</section>
@ -10,7 +10,7 @@ exports[`ManifestPage renders the expected snapshot when the manifest is loading
exports[`ManifestPage renders the expected snapshot when the manifest needs to load 1`] = `
<section
className="app-page app-page--empty"
className="app-page js-manifest-page app-page--empty"
>
<Connect(ManifestLoader) />
</section>
@ -18,7 +18,7 @@ exports[`ManifestPage renders the expected snapshot when the manifest needs to l
exports[`ManifestPage renders the expected snapshot when there is a manifest 1`] = `
<section
className="app-page "
className="app-page js-manifest-page "
>
<Manifest
icons={
@ -63,7 +63,7 @@ exports[`ManifestPage renders the expected snapshot when there is a manifest 1`]
exports[`ManifestPage renders the expected snapshot when there is no manifest 1`] = `
<section
className="app-page app-page--empty"
className="app-page js-manifest-page app-page--empty"
>
<ManifestEmpty />
</section>

Просмотреть файл

@ -1,17 +1,61 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Sidebar renders the expected snapshot 1`] = `
exports[`Sidebar renders the expected snapshot when no page is selected 1`] = `
<aside
className="sidebar"
className="sidebar js-sidebar"
>
<ul
className="sidebar__list"
>
<SidebarItem
<Connect(SidebarItem)
isSelected={false}
key="sidebar-item-manifest"
page="manifest"
/>
<SidebarItem
<Connect(SidebarItem)
isSelected={false}
key="sidebar-item-service-workers"
page="service-workers"
/>
</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={true}
key="sidebar-item-manifest"
page="manifest"
/>
<Connect(SidebarItem)
isSelected={false}
key="sidebar-item-service-workers"
page="service-workers"
/>
</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={false}
key="sidebar-item-manifest"
page="manifest"
/>
<Connect(SidebarItem)
isSelected={true}
key="sidebar-item-service-workers"
page="service-workers"
/>

Просмотреть файл

@ -1,8 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SidebarItem renders the expected snapshot with manifest page 1`] = `
exports[`SidebarItem renders the expected snapshot when the manifest page is not selected 1`] = `
<li
className="sidebar-item"
className="sidebar-item js-sidebar-manifest "
onClick={[Function]}
role="link"
>
<Localized
attrs={
@ -33,9 +35,81 @@ exports[`SidebarItem renders the expected snapshot with manifest page 1`] = `
</li>
`;
exports[`SidebarItem renders the expected snapshot with service-workers page 1`] = `
exports[`SidebarItem renders the expected snapshot when the manifest page is selected 1`] = `
<li
className="sidebar-item"
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={

Просмотреть файл

@ -7,6 +7,12 @@
const { shallow } = require("enzyme");
const { createFactory } = require("react");
const {
setupStore,
} = require("devtools/client/application/test/components/helpers/helpers");
const { PAGE_TYPES } = require("devtools/client/application/src/constants");
const Sidebar = createFactory(
require("devtools/client/application/src/components/routing/Sidebar")
);
@ -16,8 +22,28 @@ const Sidebar = createFactory(
*/
describe("Sidebar", () => {
it("renders the expected snapshot", () => {
const wrapper = shallow(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();
});
});

Просмотреть файл

@ -7,6 +7,12 @@
const { shallow } = require("enzyme");
const { createFactory } = require("react");
const {
setupStore,
} = require("devtools/client/application/test/components/helpers/helpers");
const { PAGE_TYPES } = require("devtools/client/application/src/constants");
const SidebarItem = createFactory(
require("devtools/client/application/src/components/routing/SidebarItem")
);
@ -16,21 +22,59 @@ const SidebarItem = createFactory(
*/
describe("SidebarItem", () => {
it("renders the expected snapshot with manifest page", () => {
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 with service-workers page", () => {
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();
});
});

Просмотреть файл

@ -2,7 +2,7 @@
exports[`WorkersPage filters out workers from diferent domains 1`] = `
<section
className="app-page "
className="app-page js-service-workers-page "
>
<WorkerList
canDebugWorkers={true}
@ -32,7 +32,7 @@ exports[`WorkersPage filters out workers from diferent domains 1`] = `
exports[`WorkersPage filters out workers from different domains and renders an empty list when there is none left 1`] = `
<section
className="app-page app-page--empty"
className="app-page js-service-workers-page app-page--empty"
>
<WorkerListEmpty />
</section>
@ -40,7 +40,7 @@ exports[`WorkersPage filters out workers from different domains and renders an e
exports[`WorkersPage it renders a list with a single element if there's just 1 worker 1`] = `
<section
className="app-page "
className="app-page js-service-workers-page "
>
<WorkerList
canDebugWorkers={true}
@ -62,7 +62,7 @@ exports[`WorkersPage it renders a list with a single element if there's just 1 w
exports[`WorkersPage renders a list with multiple elements when there are multiple workers 1`] = `
<section
className="app-page "
className="app-page js-service-workers-page "
>
<WorkerList
canDebugWorkers={true}
@ -100,7 +100,7 @@ exports[`WorkersPage renders a list with multiple elements when there are multip
exports[`WorkersPage renders an empty list if there are no workers 1`] = `
<section
className="app-page app-page--empty"
className="app-page js-service-workers-page app-page--empty"
>
<WorkerListEmpty />
</section>