From 6bd5bd1c3989a2ae2396624e095159312c9105b3 Mon Sep 17 00:00:00 2001 From: padamsen_fisker Date: Tue, 30 Jan 2024 16:57:19 -0500 Subject: [PATCH] CEC-5672 - UI for adding SUMS versions --- .../App/__snapshots__/App.test.js.snap | 384 ++++++++++++++++-- src/components/Contexts/CarUpdatesContext.jsx | 71 +++- .../Controls/CarUpdatesTable/index.jsx | 2 +- src/components/Flashpack/Details/index.jsx | 2 +- src/components/Flashpack/index.jsx | 2 +- src/components/Layouts/SideMenu.jsx | 13 +- .../__snapshots__/SideMenu.test.jsx.snap | 48 ++- src/components/Manifest/List/index.jsx | 2 +- src/components/Routes/SiteRoutes.jsx | 36 +- src/components/SUMS/Add/index.jsx | 12 +- src/components/SUMS/Add/index.test.jsx | 4 +- .../List/__snapshots__/index.test.jsx.snap | 175 ++++++++ src/components/SUMS/List/index.jsx | 243 +++++++++++ src/components/SUMS/List/index.test.jsx | 46 +++ .../New/__snapshots__/index.test.jsx.snap | 138 +++++++ src/components/SUMS/New/index.jsx | 129 ++++++ src/components/SUMS/New/index.test.jsx | 46 +++ .../SUMS/__snapshots__/index.test.jsx.snap | 25 +- src/components/SUMS/index.jsx | 15 +- src/components/SUMS/index.test.jsx | 4 +- src/services/updatesAPI.js | 29 +- 21 files changed, 1366 insertions(+), 60 deletions(-) create mode 100644 src/components/SUMS/List/__snapshots__/index.test.jsx.snap create mode 100644 src/components/SUMS/List/index.jsx create mode 100644 src/components/SUMS/List/index.test.jsx create mode 100644 src/components/SUMS/New/__snapshots__/index.test.jsx.snap create mode 100644 src/components/SUMS/New/index.jsx create mode 100644 src/components/SUMS/New/index.test.jsx diff --git a/src/components/App/__snapshots__/App.test.js.snap b/src/components/App/__snapshots__/App.test.js.snap index a7883f8..d0216d3 100644 --- a/src/components/App/__snapshots__/App.test.js.snap +++ b/src/components/App/__snapshots__/App.test.js.snap @@ -434,6 +434,28 @@ exports[`App Route / authenticated 1`] = ` /> +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -470,7 +492,7 @@ exports[`App Route / authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + SUMS + +
    + +
    +
  • @@ -1853,6 +1897,28 @@ exports[`App Route /home authenticated 1`] = ` /> +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -1889,7 +1955,7 @@ exports[`App Route /home authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -2685,7 +2773,7 @@ exports[`App Route /issue-info authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -3319,7 +3429,7 @@ exports[`App Route /issues authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -4322,7 +4454,7 @@ exports[`App Route /package-deploy authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -5448,7 +5602,7 @@ exports[`App Route /package-status authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -6529,7 +6705,7 @@ exports[`App Route /packages authenticated 1`] = ` - Flashpack + SUMS 2023.03.00.00.E @@ -7693,6 +7869,28 @@ exports[`App Route /page-not-found authenticated 1`] = ` />
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -7729,7 +7927,7 @@ exports[`App Route /page-not-found authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -8379,7 +8599,7 @@ exports[`App Route /tools/certificates/add authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + SUMS + +
    + +
    +
  • @@ -9659,6 +9901,28 @@ exports[`App Route /tools/sms/send authenticated 1`] = ` /> +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -9695,7 +9959,7 @@ exports[`App Route /tools/sms/send authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -10444,7 +10730,7 @@ exports[`App Route /vehicle-add authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -11648,7 +11956,7 @@ exports[`App Route /vehicle-status authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -12781,7 +13111,7 @@ exports[`App Route /vehicles authenticated 1`] = ` - Flashpack + SUMS { const [busy, setBusy] = useState(false); const [carUpdates, setCarUpdates] = useState([]); const [versions, setVersions] = useState([SELECT_VERSION_OBJ]); + const [totalVersions, setTotalVersions] = useState(0); const [versionRxSwins, setVersionRxSwins] = useState([]); const [totalVersionRxSwins, setTotalVersionRxSwins] = useState(0); const [totalCarUpdates, setTotalCarUpdates] = useState(0); @@ -286,7 +287,7 @@ export const CarUpdatesProvider = ({ children }) => { try { setBusy(true); - result = await api.getSUMSVersions(token); + result = await api.getSUMSVersions(null, token); if (result.error) throw new Error(`Get software versions error. ${result.message}`); @@ -299,6 +300,70 @@ export const CarUpdatesProvider = ({ children }) => { return result; }; + const getSUMSVersionsList = async (options, token) => { + let result; + + try { + setBusy(true); + + result = await api.getSUMSVersions(options, token); + if (result.error) + throw new Error(`Get software versions error. ${result.message}`); + + setVersions(result.data); + if (options && options.offset === 0 && result.total) { + setTotalVersions(result.total); + } + } finally { + setBusy(false); + } + + return result; + }; + + const addSUMSVersion = async (sums_version, os_version, token) => { + let result; + + try { + setBusy(true); + + if (!validateSoftwareVersion(sums_version)) throw new Error(`invalid version ${sums_version}`); + + const data = { + "sumsversions": [ + { + "version": sums_version, + "os_version": os_version, + } + ], + } + + result = await api.addSUMSVersion(data, token); + if (result.error) + throw new Error(`Add SUMS version error. ${result.message}`); + } finally { + setBusy(false); + } + + return result; + } + + const deleteSUMSVersion = async (version, token) => { + let result; + + try { + setBusy(true); + + result = await api.deleteSUMSVersion(version, token); + if (result.error) + throw new Error(`Delete software version error. ${result.message}`); + } finally { + setBusy(false); + } + + return result; + } + const updateSUMSVersion = async (id, version, token) => { let result; @@ -374,6 +439,7 @@ export const CarUpdatesProvider = ({ children }) => { totalCarUpdates, versionRxSwins, versions, + totalVersions, cancelUpdate, deployUpdate, deployCarUpdates, @@ -381,6 +447,9 @@ export const CarUpdatesProvider = ({ children }) => { getCarUpdates, getLog, getSUMSVersions, + getSUMSVersionsList, + addSUMSVersion, + deleteSUMSVersion, getVINUpdates, startMonitor, stopMonitor, diff --git a/src/components/Controls/CarUpdatesTable/index.jsx b/src/components/Controls/CarUpdatesTable/index.jsx index d3cc482..ae46859 100644 --- a/src/components/Controls/CarUpdatesTable/index.jsx +++ b/src/components/Controls/CarUpdatesTable/index.jsx @@ -177,7 +177,7 @@ const MainForm = ({ vin, token }) => { - + {row.updatemanifest?.sums} diff --git a/src/components/Flashpack/Details/index.jsx b/src/components/Flashpack/Details/index.jsx index 2fc8bee..b00e63a 100644 --- a/src/components/Flashpack/Details/index.jsx +++ b/src/components/Flashpack/Details/index.jsx @@ -69,7 +69,7 @@ const MainForm = () => { useEffect(() => { loadFlashpackECUMappings(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [token, token, pageIndex, pageSize, orderBy, order]); + }, [token, pageIndex, pageSize, orderBy, order]); const loadFlashpackECUMappings = async () => { try { diff --git a/src/components/Flashpack/index.jsx b/src/components/Flashpack/index.jsx index a682f39..20d83bf 100644 --- a/src/components/Flashpack/index.jsx +++ b/src/components/Flashpack/index.jsx @@ -82,7 +82,7 @@ const MainForm = () => { useEffect(() => { loadFlashpacks(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [token, token, pageIndex, pageSize]); + }, [token, pageIndex, pageSize]); const loadFlashpacks = async () => { try { diff --git a/src/components/Layouts/SideMenu.jsx b/src/components/Layouts/SideMenu.jsx index 97a89e8..ae494d4 100644 --- a/src/components/Layouts/SideMenu.jsx +++ b/src/components/Layouts/SideMenu.jsx @@ -69,6 +69,11 @@ const menuData = [ to: "/tools/certificates/add", rolesPerProvider: Permissions.FiskerMagnaCertificate, }] : [], + { + label: "Flashpack", + to: "/tools/flashpacks", + rolesPerProvider: Permissions.FiskerRead, + }, { label: "Security.dll", to: "/tools/security-dll", @@ -80,10 +85,10 @@ const menuData = [ rolesPerProvider: Permissions.FiskerCreate, }, { - label: "Flashpack", - to: "/tools/flashpacks", - rolesPerProvider: Permissions.FiskerRead, - }, + label: "SUMS", + to: "/tools/sumsversions", + rolesPerProvider: Permissions.FiskerMagnaCreate, + } ], }, ]; diff --git a/src/components/Layouts/__snapshots__/SideMenu.test.jsx.snap b/src/components/Layouts/__snapshots__/SideMenu.test.jsx.snap index 2e282bf..d02dffe 100644 --- a/src/components/Layouts/__snapshots__/SideMenu.test.jsx.snap +++ b/src/components/Layouts/__snapshots__/SideMenu.test.jsx.snap @@ -353,6 +353,28 @@ exports[`SideMenu Authenticated 1`] = ` />
  • +
  • + +
    + + Flashpack + +
    + +
    +
  • @@ -389,7 +411,7 @@ exports[`SideMenu Authenticated 1`] = ` - Flashpack + SUMS
  • +
  • + +
    + + SUMS + +
    + +
    +
  • diff --git a/src/components/Manifest/List/index.jsx b/src/components/Manifest/List/index.jsx index b8a9638..fdac965 100644 --- a/src/components/Manifest/List/index.jsx +++ b/src/components/Manifest/List/index.jsx @@ -448,7 +448,7 @@ const MainForm = () => { {formatManifestType(row.manifest_type)} - + {row.sums} diff --git a/src/components/Routes/SiteRoutes.jsx b/src/components/Routes/SiteRoutes.jsx index aac7613..52f9eae 100644 --- a/src/components/Routes/SiteRoutes.jsx +++ b/src/components/Routes/SiteRoutes.jsx @@ -17,15 +17,9 @@ const FleetsList = React.lazy(() => import("../Fleets/Table")); const FleetStatus = React.lazy(() => import("../Fleets/Status")); const FleetAddForm = React.lazy(() => import("../Fleets/Add")); const FleetUpdateForm = React.lazy(() => import("../Fleets/Update")); -const FleetAddVehicleForm = React.lazy(() => - import("../Fleets/Status/Vehicles/Add") -); -const FleetAddCANFilterForm = React.lazy(() => - import("../Fleets/Status/CANFilters/Add") -); -const FleetUpdateCANFilterForm = React.lazy(() => - import("../Fleets/Status/CANFilters/Update") -); +const FleetAddVehicleForm = React.lazy(() => import("../Fleets/Status/Vehicles/Add")); +const FleetAddCANFilterForm = React.lazy(() => import("../Fleets/Status/CANFilters/Add")); +const FleetUpdateCANFilterForm = React.lazy(() => import("../Fleets/Status/CANFilters/Update")); const Home = React.lazy(() => import("../Home")); const Manifests = React.lazy(() => import("../Manifest/List")); const ManifestDeploy = React.lazy(() => import("../Manifest/Deploy")); @@ -44,6 +38,8 @@ const Flashpacks = React.lazy(() => import("../Flashpack")); const FlashpackDetails = React.lazy(() => import("../Flashpack/Details")); const FlashpackAdd = React.lazy(() => import("../Flashpack/Add")) const Datascope = React.lazy(() => import("../Dashboard")); +const Sums = React.lazy(() => import("../SUMS/List")) +const SumsNew = React.lazy(() => import("../SUMS/New")) const SumsRxSwin = React.lazy(() => import("../SUMS")); const SumsRxSwinAdd = React.lazy(() => import("../SUMS/Add")); const DashboardCustom = React.lazy(() => import("../DashboardCustom")); @@ -338,7 +334,25 @@ const SiteRoutes = () => { providers={providers} /> } + type={TYPES.PROTECTED} + token={token} + groups={groups} + rolesPerGroup={Permissions.FiskerMagnaRead} + providers={providers} + /> + } + type={TYPES.PROTECTED} + token={token} + groups={groups} + rolesPerGroup={Permissions.FiskerMagnaCreate} + providers={providers} + /> + } type={TYPES.PROTECTED} token={token} @@ -347,7 +361,7 @@ const SiteRoutes = () => { providers={providers} /> } type={TYPES.PROTECTED} token={token} diff --git a/src/components/SUMS/Add/index.jsx b/src/components/SUMS/Add/index.jsx index 4ef751b..ba5a355 100644 --- a/src/components/SUMS/Add/index.jsx +++ b/src/components/SUMS/Add/index.jsx @@ -30,9 +30,17 @@ const MainForm = () => { useEffect(() => { setTitle(`Add RXSWIN to SUMS Version ${sums_version}`); setSitePath([ + { + label: "Tools", + link: "/tools/sumsversions", + }, + { + label: "SUMS Versions", + link: "/tools/sumsversions", + }, { label: `SUMS Version ${sums_version}`, - link: `/sums/${sums_version}`, + link: `/tools/sums/${sums_version}`, }, { label: `Add RXSWIN`, @@ -62,7 +70,7 @@ const MainForm = () => { if (!result || result.error) return; setMessage(`Added ${rxswin}`); - setRedirect(`/sums/${sums_version}`); + setRedirect(`/tools/sums/${sums_version}`); } catch (e) { setMessage(e.message); logger.warn(e.stack); diff --git a/src/components/SUMS/Add/index.test.jsx b/src/components/SUMS/Add/index.test.jsx index f44513f..ef24c28 100644 --- a/src/components/SUMS/Add/index.test.jsx +++ b/src/components/SUMS/Add/index.test.jsx @@ -18,8 +18,8 @@ const renderSUMSAdd = async () => { - - + + diff --git a/src/components/SUMS/List/__snapshots__/index.test.jsx.snap b/src/components/SUMS/List/__snapshots__/index.test.jsx.snap new file mode 100644 index 0000000..a593331 --- /dev/null +++ b/src/components/SUMS/List/__snapshots__/index.test.jsx.snap @@ -0,0 +1,175 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SUMSList Render 1`] = ` +
    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + +
    + + SUMS Version + + + + + OS Version + + + + + Created + + sorted descending + + + + + + Delete + + +
    +
    +
    +
    +
    +
    +
    +
    +`; diff --git a/src/components/SUMS/List/index.jsx b/src/components/SUMS/List/index.jsx new file mode 100644 index 0000000..a848f74 --- /dev/null +++ b/src/components/SUMS/List/index.jsx @@ -0,0 +1,243 @@ +import { + Grid, + IconButton, + Table, + TableBody, + TableCell, + TableFooter, + TablePagination, + TableRow, +} from "@material-ui/core"; +import AddCircleIcon from "@material-ui/icons/AddCircle"; +import DeleteIcon from "@material-ui/icons/Delete"; +import { LocalDateTimeString } from "../../../utils/dates"; +import clsx from "clsx"; +import { Link } from "react-router-dom"; +import { logger } from "../../../services/monitoring"; +import React, { useEffect, useState } from "react"; +import { useCarUpdatesContext, CarUpdatesProvider } from "../../Contexts/CarUpdatesContext"; +import { useStatusContext } from "../../Contexts/StatusContext"; +import { useUserContext } from "../../Contexts/UserContext"; +import TableHeaderSortable from "../../Table/HeaderSortable"; +import { useLocalStorage } from "../../useLocalStorage"; +import DeleteConfirmation from "../../DeleteConfirmation"; +import useStyles from "../../useStyles"; +import { Permissions } from "../../../utils/roles"; +import { RoleWrap } from "../../Controls/RoleWrap"; + +const tableColumns = [ + { + id: "version", + label: "SUMS Version", + }, + { + id: "os_version", + label: "OS Version", + }, + { + id: "created_at", + label: "Created", + }, + { + id: "delete", + label: "Delete", + }, +]; + +const PAGE_SIZE = "SUMS_VERSIONS_TABLE_PAGE_SIZE"; + +const MainForm = () => { + const classes = useStyles(); + const { setMessage, setTitle, setSitePath } = useStatusContext(); + const [orderBy, setOrderBy] = useState("created_at"); + const [order, setOrder] = useState("desc"); + const [showDeleteModal, setShowDeleteModal] = useState(false); + const [rowToDelete, setRowToDelete] = useState({}); + const [pageSize, setPageSize] = useLocalStorage(PAGE_SIZE, 10); + const [pageIndex, setPageIndex] = useState(0); + const { + getSUMSVersionsList, + deleteSUMSVersion, + versions, + totalVersions, + stopMonitor, + } = useCarUpdatesContext(); + const { + token: { + idToken: { jwtToken: token }, + }, + groups, + providers, + } = useUserContext(); + + useEffect(() => { + setTitle("SUMS Versions"); + setSitePath([ + { + label: "Tools", + link: "/tools/sumsversions", + }, + { + label: "SUMS Versions", + }, + ]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + loadSUMSVersions(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [token, pageIndex, pageSize, orderBy, order]); + + const loadSUMSVersions = async () => { + try { + if (!token) return; + stopMonitor(); + await getSUMSVersionsList( + { + limit: pageSize, + offset: pageSize * pageIndex, + order: `${orderBy} ${order}`, + }, + token + ); + } catch (e) { + setMessage(e.message); + logger.warn(e.stack); + } + }; + + const handleChangePageIndex = (event, newIndex) => { + setPageIndex(newIndex); + }; + + const handleChangePageSize = (event) => { + setPageSize(parseInt(event.target.value, 10)); + setPageIndex(0); + }; + + const handleSort = (event, property) => { + try { + if (property === orderBy) { + if (order === "asc") { + setOrder("desc"); + } else { + setOrder("asc"); + } + } else { + setOrderBy(property); + setOrder("asc"); + } + } catch (e) { + logger.warn(e.stack); + } + }; + + const onDeleteClick = (row) => { + setRowToDelete(row); + setShowDeleteModal(true); + } + + const sendDelete = async () => { + if (rowToDelete) { + try { + const result = await deleteSUMSVersion(rowToDelete.version, token); + if (!result || result.error) return; + + setMessage(`Deleted ${rowToDelete.version}`); + loadSUMSVersions(); + } catch (e) { + setMessage(e.message); + logger.warn(e.stack); + } + } + }; + + return ( +
    + + + + + + + + + + + {versions && versions.map((row, index) => ( + + + + {row.version} + + + + {row.os_version} + + + {LocalDateTimeString(row.created)} + + + + onDeleteClick(row)} + aria-label={`Send delete for ${row.version}`} + size="small" + color="primary" + > + + + + + + ))} + + + + {!versions || versions.length === 0 ? ( + No SUMS Versions + ) : ( + )} + + +
    + setShowDeleteModal(false)} + deleteFunction={sendDelete} + /> +
    + ); +}; + +const SUMS = () => ( + + + +); + +export default SUMS; \ No newline at end of file diff --git a/src/components/SUMS/List/index.test.jsx b/src/components/SUMS/List/index.test.jsx new file mode 100644 index 0000000..3a21ab2 --- /dev/null +++ b/src/components/SUMS/List/index.test.jsx @@ -0,0 +1,46 @@ +jest.mock("../../Contexts/CarUpdatesContext"); +jest.mock("../../Contexts/StatusContext"); +jest.mock("../../Contexts/UserContext"); +jest.mock("@material-ui/core/utils/unstable_useId", () => + jest.fn().mockReturnValue("mui-test-id") +); +import { render, waitFor } from "@testing-library/react"; +import { MemoryRouter, Route } from "react-router-dom"; +import { CarUpdatesProvider } from "../../Contexts/CarUpdatesContext"; +import { StatusProvider } from "../../Contexts/StatusContext"; +import { UserProvider, setToken } from "../../Contexts/UserContext"; +import { TEST_AUTH_OBJECT_FISKER } from "../../../utils/testing"; +import MainForm from "./index"; +import addSnapshotSerializer from "../../../utils/snapshot"; + +const renderSUMSList = async () => { + const { container } = render( + + + + + + + + + + + + ); + await waitFor(() => { + /* render */ + }); + return container; +}; + +describe("SUMSList", () => { + beforeAll(() => { + addSnapshotSerializer(expect); + }); + + it("Render", async () => { + setToken(TEST_AUTH_OBJECT_FISKER); + const container = await renderSUMSList(); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/src/components/SUMS/New/__snapshots__/index.test.jsx.snap b/src/components/SUMS/New/__snapshots__/index.test.jsx.snap new file mode 100644 index 0000000..6801e02 --- /dev/null +++ b/src/components/SUMS/New/__snapshots__/index.test.jsx.snap @@ -0,0 +1,138 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SUMSNew Render 1`] = ` +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + +
    +
    +
    + +
    + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +`; diff --git a/src/components/SUMS/New/index.jsx b/src/components/SUMS/New/index.jsx new file mode 100644 index 0000000..cd3c832 --- /dev/null +++ b/src/components/SUMS/New/index.jsx @@ -0,0 +1,129 @@ +import { + Button, + TextField +} from "@material-ui/core"; +import React, { useEffect, useState } from "react"; +import { Redirect } from "react-router"; +import { logger } from "../../../services/monitoring"; +import { useStatusContext } from "../../Contexts/StatusContext"; +import { + CarUpdatesProvider, + useCarUpdatesContext +} from "../../Contexts/CarUpdatesContext"; +import { useUserContext } from "../../Contexts/UserContext"; +import useStyles from "../../useStyles"; + +const MainForm = () => { + const { addSUMSVersion, busy } = useCarUpdatesContext(); + const { + token: { + idToken: { jwtToken: token }, + }, + } = useUserContext(); + const classes = useStyles(); + const [redirect, setRedirect] = useState(null); + const { setMessage, setTitle, setSitePath } = useStatusContext(); + const [sumsVersion, setSumsVersion] = useState(""); + const [osVersion, setOsVersion] = useState(""); + + useEffect(() => { + setTitle(`New SUMS Version`); + setSitePath([ + { + label: "Tools", + link: "/tools/sumsversions", + }, + { + label: "SUMS Versions", + link: "/tools/sumsversions", + }, + { + label: `New SUMS Version`, + }, + ]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const onSUMSVersionChange = (event) => { + setSumsVersion(event.target.value); + } + + const onOSVersionChange = (event) => { + setOsVersion(event.target.value); + } + + const onSubmit = async (event) => { + try { + event.preventDefault(); + + const result = await addSUMSVersion(sumsVersion, osVersion, token); + if (!result || result.error) return; + + setMessage(`Added ${sumsVersion}`); + setRedirect(`/tools/sumsversions`); + } catch (e) { + setMessage(e.message); + logger.warn(e.stack); + } + }; + + if (redirect && redirect.length > 0) { + return ; + } + + return ( +
    +
    + + + + +
    + ); +}; + +const SumsNew = () => ( + + + +); + +export default SumsNew; \ No newline at end of file diff --git a/src/components/SUMS/New/index.test.jsx b/src/components/SUMS/New/index.test.jsx new file mode 100644 index 0000000..08d3dff --- /dev/null +++ b/src/components/SUMS/New/index.test.jsx @@ -0,0 +1,46 @@ +jest.mock("../../Contexts/CarUpdatesContext"); +jest.mock("../../Contexts/StatusContext"); +jest.mock("../../Contexts/UserContext"); +jest.mock("@material-ui/core/utils/unstable_useId", () => + jest.fn().mockReturnValue("mui-test-id") +); +import { render, waitFor } from "@testing-library/react"; +import { MemoryRouter, Route } from "react-router-dom"; +import { CarUpdatesProvider } from "../../Contexts/CarUpdatesContext"; +import { StatusProvider } from "../../Contexts/StatusContext"; +import { UserProvider, setToken } from "../../Contexts/UserContext"; +import { TEST_AUTH_OBJECT_FISKER } from "../../../utils/testing"; +import MainForm from "./index"; +import addSnapshotSerializer from "../../../utils/snapshot"; + +const renderSUMSNew = async () => { + const { container } = render( + + + + + + + + + + + + ); + await waitFor(() => { + /* render */ + }); + return container; +}; + +describe("SUMSNew", () => { + beforeAll(() => { + addSnapshotSerializer(expect); + }); + + it("Render", async () => { + setToken(TEST_AUTH_OBJECT_FISKER); + const container = await renderSUMSNew(); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/src/components/SUMS/__snapshots__/index.test.jsx.snap b/src/components/SUMS/__snapshots__/index.test.jsx.snap index ee5e68c..d966fbe 100644 --- a/src/components/SUMS/__snapshots__/index.test.jsx.snap +++ b/src/components/SUMS/__snapshots__/index.test.jsx.snap @@ -23,7 +23,7 @@ exports[`SUMS Render 1`] = ` > + Delete + + + { useEffect(() => { setTitle(`SUMS Version ${sums_version}`); setSitePath([ + { + label: "Tools", + link: "/tools/sumsversions", + }, + { + label: "SUMS Versions", + link: "/tools/sumsversions", + }, { label: `SUMS Version ${sums_version}`, - link: `/sums/${sums_version}`, }, ]); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -152,7 +163,7 @@ const MainForm = () => {
    - + diff --git a/src/components/SUMS/index.test.jsx b/src/components/SUMS/index.test.jsx index cfd5390..57ea849 100644 --- a/src/components/SUMS/index.test.jsx +++ b/src/components/SUMS/index.test.jsx @@ -18,8 +18,8 @@ const renderSUMS = async () => { - - + + diff --git a/src/services/updatesAPI.js b/src/services/updatesAPI.js index adce177..305f595 100644 --- a/src/services/updatesAPI.js +++ b/src/services/updatesAPI.js @@ -99,8 +99,8 @@ const updatesAPI = { .catch(errorHandler); }, - getSUMSVersions: async (token) => { - return fetch(`${API_ENDPOINT}/manifest/sums`, { + getSUMSVersions: async (options, token) => { + return fetch(addQueryParams(`${API_ENDPOINT}/manifest/sums`, options), { method: "GET", headers: Object.assign( { "Content-Type": "application/json" }, @@ -111,6 +111,31 @@ const updatesAPI = { .catch(errorHandler); }, + addSUMSVersion: async (data, token) => { + return fetch(`${API_ENDPOINT}/manifest/sums`, { + method: "POST", + headers: Object.assign( + { "Content-Type": "application/json" }, + getAuthHeaderOptions(token) + ), + body: JSON.stringify(data), + }) + .then(fetchRespHandler) + .catch(errorHandler); + }, + + deleteSUMSVersion: async (version, token) => { + return fetch(`${API_ENDPOINT}/manifest/sums/${version}`, { + method: "DELETE", + headers: Object.assign( + { "Content-Type": "application/json" }, + getAuthHeaderOptions(token) + ), + }) + .then(fetchRespHandler) + .catch(errorHandler); + }, + updateSUMSVersion: async (id, version, token) => { return fetch(`${API_ENDPOINT}/manifests/${id}/sums`, { method: "PUT",