зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1566013 - Part 1: Process canonical manifest and hook it with the Manifest component r=Ola
Differential Revision: https://phabricator.services.mozilla.com/D43954 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
a04d027dce
Коммит
22cb75164e
|
@ -4,6 +4,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const {
|
||||
createFactory,
|
||||
PureComponent,
|
||||
|
@ -12,63 +13,38 @@ const {
|
|||
section,
|
||||
} = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const ManifestLoader = createFactory(require("../manifest/ManifestLoader"));
|
||||
|
||||
const Manifest = createFactory(require("./Manifest"));
|
||||
const ManifestEmpty = createFactory(require("./ManifestEmpty"));
|
||||
|
||||
class ManifestPage extends PureComponent {
|
||||
render() {
|
||||
// TODO: needs to be replaced with data from Redux
|
||||
const data = {
|
||||
validation: [
|
||||
{ level: "warning", message: "Icons item at index 0 is invalid." },
|
||||
{ level: "error", message: "Random JSON error" },
|
||||
{
|
||||
level: "warning",
|
||||
message:
|
||||
"Icons item at index 2 is invalid. Icons item at index 2 is invalid. Icons item at index 2 is invalid. Icons item at index 2 is invalid.",
|
||||
},
|
||||
],
|
||||
icons: [],
|
||||
identity: [
|
||||
{
|
||||
key: "name",
|
||||
value:
|
||||
"Name is a verrry long name and the name is longer tha you thinnk because it is loooooooooooooooooooooooooooooooooooooooooooooooong",
|
||||
},
|
||||
{
|
||||
key: "short_name",
|
||||
value: "Na",
|
||||
},
|
||||
],
|
||||
presentation: [
|
||||
{ key: "display", value: "browser" },
|
||||
{ key: "orientation", value: "landscape" },
|
||||
{ key: "start_url", value: "root" },
|
||||
{ key: "theme_color", value: "#345" },
|
||||
{ key: "background_color", value: "#F9D" },
|
||||
],
|
||||
// TODO: Use well-defined types
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1576881
|
||||
static get propTypes() {
|
||||
return {
|
||||
manifest: PropTypes.object,
|
||||
};
|
||||
}
|
||||
|
||||
const isManifestEmpty = !data;
|
||||
render() {
|
||||
const { manifest } = this.props;
|
||||
|
||||
return section(
|
||||
{
|
||||
className: `app-page ${isManifestEmpty ? "app-page--empty" : ""}`,
|
||||
className: `app-page ${!manifest ? "app-page--empty" : ""}`,
|
||||
},
|
||||
ManifestLoader({}),
|
||||
isManifestEmpty
|
||||
? ManifestEmpty({})
|
||||
: Manifest({
|
||||
icons: data.icons,
|
||||
identity: data.identity,
|
||||
presentation: data.presentation,
|
||||
validation: data.validation,
|
||||
})
|
||||
manifest ? Manifest({ ...manifest }) : ManifestEmpty({})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
manifest: state.manifest.manifest,
|
||||
};
|
||||
}
|
||||
// Exports
|
||||
module.exports = ManifestPage;
|
||||
module.exports = connect(mapStateToProps)(ManifestPage);
|
||||
|
|
|
@ -23,6 +23,12 @@ const PAGE_TYPES = {
|
|||
|
||||
const DEFAULT_PAGE = PAGE_TYPES.MANIFEST;
|
||||
|
||||
const MANIFEST_CATEGORIES = {
|
||||
IDENTITY: "identity",
|
||||
PRESENTATION: "presentation",
|
||||
ICONS: "icons",
|
||||
};
|
||||
|
||||
const MANIFEST_ISSUE_LEVELS = {
|
||||
ERROR: "error",
|
||||
WARNING: "warning",
|
||||
|
@ -34,6 +40,7 @@ module.exports = Object.assign(
|
|||
{
|
||||
DEFAULT_PAGE,
|
||||
PAGE_TYPES,
|
||||
MANIFEST_CATEGORIES,
|
||||
MANIFEST_ISSUE_LEVELS,
|
||||
},
|
||||
actionTypes
|
||||
|
|
|
@ -4,7 +4,83 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { UPDATE_MANIFEST } = require("../constants");
|
||||
const {
|
||||
MANIFEST_CATEGORIES,
|
||||
MANIFEST_ISSUE_LEVELS,
|
||||
UPDATE_MANIFEST,
|
||||
} = require("../constants");
|
||||
|
||||
function _processRawManifestIcons(rawIcons) {
|
||||
// TODO: we are currently ignoring the following fields present in the data
|
||||
// from the canonical manifest:
|
||||
// - purpose
|
||||
// - type
|
||||
// We should include this info so we can pass it as props to the relevant
|
||||
// component
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1577446
|
||||
return rawIcons.map(icon => {
|
||||
return {
|
||||
key: icon.sizes.join(" "),
|
||||
value: icon.src,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function _processRawManifestMembers(rawManifest) {
|
||||
function getCategoryForMember(key) {
|
||||
switch (key) {
|
||||
case "name":
|
||||
case "short_name":
|
||||
return MANIFEST_CATEGORIES.IDENTITY;
|
||||
default:
|
||||
return MANIFEST_CATEGORIES.PRESENTATION;
|
||||
}
|
||||
}
|
||||
|
||||
const res = {
|
||||
[MANIFEST_CATEGORIES.IDENTITY]: [],
|
||||
[MANIFEST_CATEGORIES.PRESENTATION]: [],
|
||||
};
|
||||
|
||||
// filter out extra metadata members (those with moz_ prefix) and icons
|
||||
const rawMembers = Object.entries(rawManifest).filter(
|
||||
([key, value]) => !key.startsWith("moz_") && !(key === "icons")
|
||||
);
|
||||
|
||||
for (const [key, value] of rawMembers) {
|
||||
const category = getCategoryForMember(key);
|
||||
res[category].push({ key, value });
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function _processRawManifestIssues(issues) {
|
||||
return issues.map(x => {
|
||||
return {
|
||||
level: x.warn
|
||||
? MANIFEST_ISSUE_LEVELS.WARNING
|
||||
: MANIFEST_ISSUE_LEVELS.ERROR,
|
||||
message: x.warn || x.error,
|
||||
type: x.type || null,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function _processRawManifest(rawManifest) {
|
||||
const res = {
|
||||
url: rawManifest.moz_manifest_url,
|
||||
};
|
||||
|
||||
// group manifest members by category
|
||||
Object.assign(res, _processRawManifestMembers(rawManifest));
|
||||
// process icons
|
||||
res.icons = _processRawManifestIcons(rawManifest.icons || []);
|
||||
// process error messages
|
||||
res.validation = _processRawManifestIssues(rawManifest.moz_validation || []);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function ManifestState() {
|
||||
return {
|
||||
|
@ -18,7 +94,7 @@ function manifestReducer(state = ManifestState(), action) {
|
|||
case UPDATE_MANIFEST:
|
||||
const { manifest, errorMessage } = action;
|
||||
return Object.assign({}, state, {
|
||||
manifest,
|
||||
manifest: manifest ? _processRawManifest(manifest) : null,
|
||||
errorMessage,
|
||||
});
|
||||
default:
|
||||
|
|
|
@ -1,45 +1,36 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ManifestPage renders the expected snapshot 1`] = `
|
||||
exports[`ManifestPage renders the expected snapshot when there is a manifest 1`] = `
|
||||
<section
|
||||
className="app-page "
|
||||
>
|
||||
<Connect(ManifestLoader) />
|
||||
<Manifest
|
||||
icons={Array []}
|
||||
icons={
|
||||
Array [
|
||||
Object {
|
||||
"key": "1x1",
|
||||
"value": "something.png",
|
||||
},
|
||||
]
|
||||
}
|
||||
identity={
|
||||
Array [
|
||||
Object {
|
||||
"key": "name",
|
||||
"value": "Name is a verrry long name and the name is longer tha you thinnk because it is loooooooooooooooooooooooooooooooooooooooooooooooong",
|
||||
},
|
||||
Object {
|
||||
"key": "short_name",
|
||||
"value": "Na",
|
||||
"value": "foo",
|
||||
},
|
||||
]
|
||||
}
|
||||
presentation={
|
||||
Array [
|
||||
Object {
|
||||
"key": "display",
|
||||
"value": "browser",
|
||||
"key": "lorem",
|
||||
"value": "ipsum",
|
||||
},
|
||||
Object {
|
||||
"key": "orientation",
|
||||
"value": "landscape",
|
||||
},
|
||||
Object {
|
||||
"key": "start_url",
|
||||
"value": "root",
|
||||
},
|
||||
Object {
|
||||
"key": "theme_color",
|
||||
"value": "#345",
|
||||
},
|
||||
Object {
|
||||
"key": "background_color",
|
||||
"value": "#F9D",
|
||||
"key": "foo",
|
||||
"value": "bar",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -47,18 +38,19 @@ exports[`ManifestPage renders the expected snapshot 1`] = `
|
|||
Array [
|
||||
Object {
|
||||
"level": "warning",
|
||||
"message": "Icons item at index 0 is invalid.",
|
||||
},
|
||||
Object {
|
||||
"level": "error",
|
||||
"message": "Random JSON error",
|
||||
},
|
||||
Object {
|
||||
"level": "warning",
|
||||
"message": "Icons item at index 2 is invalid. Icons item at index 2 is invalid. Icons item at index 2 is invalid. Icons item at index 2 is invalid.",
|
||||
"message": "This is a warning",
|
||||
},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`ManifestPage renders the expected snapshot when there is no manifest 1`] = `
|
||||
<section
|
||||
className="app-page app-page--empty"
|
||||
>
|
||||
<Connect(ManifestLoader) />
|
||||
<ManifestEmpty />
|
||||
</section>
|
||||
`;
|
||||
|
|
|
@ -7,6 +7,13 @@
|
|||
const { shallow } = require("enzyme");
|
||||
const { createFactory } = require("react");
|
||||
|
||||
const {
|
||||
setupStore,
|
||||
} = require("devtools/client/application/test/components/helpers/helpers");
|
||||
const {
|
||||
MANIFEST_SIMPLE,
|
||||
} = require("devtools/client/application/test/components/fixtures/data/constants");
|
||||
|
||||
const ManifestPage = createFactory(
|
||||
require("devtools/client/application/src/components/manifest/ManifestPage")
|
||||
);
|
||||
|
@ -16,8 +23,26 @@ const ManifestPage = createFactory(
|
|||
*/
|
||||
|
||||
describe("ManifestPage", () => {
|
||||
it("renders the expected snapshot", () => {
|
||||
const wrapper = shallow(ManifestPage({}));
|
||||
function buildStoreWithManifest(manifest) {
|
||||
return setupStore({
|
||||
preloadedState: {
|
||||
manifest: {
|
||||
manifest,
|
||||
errorMessage: "",
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
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 there is no manifest", () => {
|
||||
const store = buildStoreWithManifest(null);
|
||||
const wrapper = shallow(ManifestPage({ store })).dive();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,6 +4,6 @@ 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`] = `<ManifestPage />`;
|
||||
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) />`;
|
||||
|
|
|
@ -18,6 +18,7 @@ add_task(async function() {
|
|||
|
||||
const action = updateManifest({ name: "foo" }, "some error");
|
||||
const newState = manifestReducer(state, action);
|
||||
equal(newState.manifest.name, "foo");
|
||||
equal(newState.manifest.identity[0].key, "name");
|
||||
equal(newState.manifest.identity[0].value, "foo");
|
||||
equal(newState.errorMessage, "some error");
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче