CEC-775 Manifest details component (#114)

* CEC-775 Manifest details component

* Code smells

* Fix build warning
This commit is contained in:
John Wu
2022-01-17 08:59:55 -08:00
committed by GitHub
parent cb5035cf96
commit a858b842c6
9 changed files with 467 additions and 6 deletions

View File

@@ -4607,6 +4607,11 @@ exports[`App Route /package-status authenticated 1`] = `
<div
data-testid="mocked-carupdatesprovider"
>
<div
class="makeStyles-link-1227"
>
Show Details
</div>
<div
class="makeStyles-paper-1204 makeStyles-tableSize-1256"
>

View File

@@ -9,6 +9,21 @@ export const ManifestsProvider = ({ children }) => {
const [manifests, setManifests] = useState([]);
const [totalManifests, setTotalManifests] = useState(0);
const getManifest = async (id, token) => {
let result;
try {
setBusy(true);
result = await api.getManifest(id, token);
if (result.error)
throw new Error(`Get manifests error. ${result.message}`);
} finally {
setBusy(false);
}
return result;
};
const getManifests = async (search, token) => {
let result;
@@ -54,6 +69,7 @@ export const ManifestsProvider = ({ children }) => {
busy,
manifests,
totalManifests,
getManifest,
getManifests,
deleteManifest,
}}

View File

@@ -3,6 +3,37 @@ import React from "react";
const ManifestsContext = React.createContext();
let busy = false;
let manifest = {
id: 1,
name: "Test Deployment",
version: "1.0.100",
description: "Deployment folder test",
release_notes: "https://releasenotes.com",
ecu_list: "ICC 1000",
ecu_updates: [
{
name: "ICC",
part_number: "BBBBBB",
version: "1000",
files: [
{
file_id: "b0cda514c94080b4",
filename: "LARGE.jpg",
url: "https://upload-dev.fiskerdps.com/92bbc448-99c8-4851-91ad-f8042e4deb49/LARGE.jpg",
file_size: 14559274,
size: 14488498,
type: "ODX Data",
created: "2021-12-09T22:38:29.102813Z",
updated: "2021-12-09T22:38:29.102813Z",
},
],
created: "2021-12-09T22:38:20.408351Z",
updated: "2022-01-14T00:47:08.996451Z",
},
],
created: "2021-12-09T22:38:11.679943Z",
updated: "2022-01-14T00:47:08.996451Z",
};
let manifests = [
{
id: 1,
@@ -22,6 +53,7 @@ export const useManifestsContext = () => ({
busy,
manifests,
totalManifests,
getManifest: jest.fn(() => manifest),
getManifests: jest.fn(() => manifests),
deleteManifest: jest.fn(),
});

View File

@@ -0,0 +1,223 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Manifest Details Component Render Hidden 1`] = `
Object {
"asFragment": [Function],
"baseElement": <body>
<div>
<div
data-testid="mocked-userprovider"
>
<div
data-testid="mocked-manifestsprovider"
>
<div
class="makeStyles-link-26"
>
Show Details
</div>
</div>
</div>
</div>
</body>,
"container": <div>
<div
data-testid="mocked-userprovider"
>
<div
data-testid="mocked-manifestsprovider"
>
<div
class="makeStyles-link-26"
>
Show Details
</div>
</div>
</div>
</div>,
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
"rerender": [Function],
"unmount": [Function],
}
`;
exports[`Manifest Details Component Render Shown 1`] = `
Object {
"asFragment": [Function],
"baseElement": <body>
<div>
<div
data-testid="mocked-userprovider"
>
<div
data-testid="mocked-manifestsprovider"
>
<div
class="makeStyles-link-89"
>
Hide Details
</div>
<ul>
<li>
Test Deployment 1.0.100
</li>
<li>
Deployment folder test https://releasenotes.com
</li>
<li>
ECUs:
<ul>
<li>
ICC, Part: BBBBBB, Version: 1000
<br />
<ul>
<li>
ODX Data: LARGE.jpg
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</body>,
"container": <div>
<div
data-testid="mocked-userprovider"
>
<div
data-testid="mocked-manifestsprovider"
>
<div
class="makeStyles-link-89"
>
Hide Details
</div>
<ul>
<li>
Test Deployment 1.0.100
</li>
<li>
Deployment folder test https://releasenotes.com
</li>
<li>
ECUs:
<ul>
<li>
ICC, Part: BBBBBB, Version: 1000
<br />
<ul>
<li>
ODX Data: LARGE.jpg
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>,
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
"rerender": [Function],
"unmount": [Function],
}
`;

View File

@@ -0,0 +1,94 @@
import React, { useState, useEffect } from "react";
import { useParams } from "react-router";
import { useManifestsContext } from "../../Contexts/ManifestsContext";
import { useStatusContext } from "../../Contexts/StatusContext";
import { useUserContext } from "../../Contexts/UserContext";
import useStyles from "../../useStyles";
const ECUFileList = (files) => {
if (!files || files.length === 0) return "No files";
return (
<ul>
{files.map((file) => (
<li key={file.filename}>{`${file.type}: ${file.filename} `}</li>
))}
</ul>
);
};
const ECUList = (ecus) => {
if (!ecus || ecus.length === 0) return "None";
return (
<ul>
{ecus.map((ecu) => (
<li key={ecu.name}>
{`${ecu.name}, Part: ${ecu.part_number}, Version: ${ecu.version}`}
<br />
{ECUFileList(ecu.files)}
</li>
))}
</ul>
);
};
const ManifestDetails = ({ opened }) => {
const classes = useStyles();
const { manifest_id } = useParams();
const [manifest, setManifest] = useState(null);
const [open, setOpen] = useState(opened || false);
const { getManifest } = useManifestsContext();
const { setMessage } = useStatusContext();
const {
token: {
idToken: { jwtToken: token },
},
} = useUserContext();
const init = async () => {
try {
const result = await getManifest(manifest_id, token);
if (result.error) {
throw new Error(`Get manifest error. ${result.message}`);
} else {
setManifest(result);
}
} catch (e) {
setMessage(e.message);
}
};
const toggleOpen = (e) => {
e.preventDefault();
setOpen(!open);
};
useEffect(() => {
if (!open || manifest) return;
init();
// eslint-disable-next-line
}, [open]);
if (!open)
return (
<div className={classes.link} onClick={(e) => toggleOpen(e)}>
Show Details
</div>
);
if (manifest === null) return <div>Loading Manifest...</div>;
return (
<>
<div className={classes.link} onClick={(e) => toggleOpen(e)}>
Hide Details
</div>
<ul>
<li>{`${manifest.name} ${manifest.version}`}</li>
<li>{`${manifest.description} ${manifest.release_notes}`}</li>
<li>ECUs: {ECUList(manifest.ecu_updates)}</li>
</ul>
</>
);
};
export default ManifestDetails;

View File

@@ -0,0 +1,46 @@
jest.mock("../../Contexts/ManifestsContext");
jest.mock("../../Contexts/UserContext");
import React from "react";
import { render, waitFor } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom";
import { ManifestsProvider } from "../../Contexts/ManifestsContext";
import { UserProvider, setToken } from "../../Contexts/UserContext";
import { StatusProvider } from "../../Contexts/StatusContext";
import ManifestDetails from ".";
import { TEST_AUTH_OBJECT } from "../../../utils/testing";
const TestComponent = (opened) => (
<UserProvider>
<BrowserRouter>
<StatusProvider>
<ManifestsProvider>
<ManifestDetails opened={opened} />
</ManifestsProvider>
</StatusProvider>
</BrowserRouter>
</UserProvider>
);
describe("Manifest Details Component", () => {
beforeAll(() => {
setToken(TEST_AUTH_OBJECT);
});
it("Render Hidden", async () => {
const rendered = render(TestComponent(false));
await waitFor(() => {
// pause for render
});
expect(rendered).toMatchSnapshot();
});
it("Render Shown", async () => {
const rendered = render(TestComponent(true));
await waitFor(() => {
// pause for render
});
expect(rendered).toMatchSnapshot();
});
});

View File

@@ -26,6 +26,7 @@ import { useStatusContext } from "../../Contexts/StatusContext";
import useStyles from "../../useStyles";
import { LocalDateTimeString } from "../../../utils/dates";
import { logger } from "../../../services/monitoring";
import ManifestDetails from "../Details";
const MainForm = () => {
const { manifest_id } = useParams();
@@ -182,6 +183,7 @@ const MainForm = () => {
const ManifestStatus = () => (
<ManifestsProvider>
<CarUpdatesProvider>
<ManifestDetails />
<MainForm />
</CarUpdatesProvider>
</ManifestsProvider>

View File

@@ -1,12 +1,10 @@
const manifestsAPI = {
createCarUpdates: async (data, token) => {
if (!data.id) data.id = 0;
data.id++;
return data;
},
getPackages: async (search, token) => {
return {
data: [
@@ -30,9 +28,9 @@ const manifestsAPI = {
version: "1.2",
link: "https://cloudfront.com/download",
ecu_list: "ECU1 1.1.0,ECU2 1.1.2",
}
]
}
},
],
};
},
updatePackage: async (data, token) => {
@@ -54,6 +52,40 @@ const manifestsAPI = {
getCarUpdateProgress: async (carupdateids, token) => {
return { statuses: [] };
},
getManifest: async (id, token) => {
return {
id,
name: "Test Deployment",
version: "1.0.100",
description: "Deployment folder test",
release_notes: "https://releasenotes.com",
ecu_list: "ICC 1000",
ecu_updates: [
{
name: "ICC",
part_number: "BBBBBB",
version: "1000",
files: [
{
file_id: "b0cda514c94080b4",
filename: "LARGE.jpg",
url: "https://upload-dev.fiskerdps.com/92bbc448-99c8-4851-91ad-f8042e4deb49/LARGE.jpg",
file_size: 14559274,
size: 14488498,
type: "ODX Data",
created: "2021-12-09T22:38:29.102813Z",
updated: "2021-12-09T22:38:29.102813Z",
},
],
created: "2021-12-09T22:38:20.408351Z",
updated: "2022-01-14T00:47:08.996451Z",
},
],
created: "2021-12-09T22:38:11.679943Z",
updated: "2022-01-14T00:47:08.996451Z",
};
},
};
export default manifestsAPI;

View File

@@ -16,6 +16,17 @@ const manifestsAPI = {
),
}).then(fetchRespHandler),
getManifest: async (id, token) => {
const u = addQueryParams(`${API_ENDPOINT}/manifest`, { id });
return fetch(u, {
method: "GET",
headers: Object.assign(
{ "Content-Type": "application/json" },
getAuthHeaderOptions(token)
),
}).then(fetchRespHandler);
},
getManifests: async (search, token) => {
const u = addQueryParams(`${API_ENDPOINT}/manifests`, search);
return fetch(u, {