CEC-425 Added Delete Verification Prompt (#198)

Co-authored-by: Alexander Andrews <aandrews@fiskerinc.com>
This commit is contained in:
Alexander Andrews
2022-09-20 09:40:28 -04:00
committed by GitHub
parent 9c7a2b4577
commit 618cc68196
22 changed files with 692 additions and 392 deletions

658
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3287,23 +3287,26 @@ exports[`App Route /packages authenticated 1`] = `
/> />
</svg> </svg>
</a> </a>
<a <div>
class="" <a
href="/packages" class=""
title="Delete \\"Test Manifest 1.0\\"" href="/packages"
> title="Delete \\"Test Manifest 1.0\\""
<svg
aria-hidden="true"
aria-label="Delete Test Manifest 1.0"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
> >
<path <svg
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" aria-hidden="true"
/> aria-label="Delete Test Manifest 1.0"
</svg> class="MuiSvgIcon-root"
</a> focusable="false"
viewBox="0 0 24 24"
>
<path
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
/>
</svg>
</a>
<div />
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -7024,6 +7027,7 @@ exports[`App Route /vehicle-status authenticated 1`] = `
</a> </a>
</div> </div>
</div> </div>
<div />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -28,6 +28,7 @@ exports[`VehicleDetailsTab Render 1`] = `
VIN VIN
</b> </b>
: :
TESTVIN1234567890
</p> </p>
<p> <p>
<b> <b>
@@ -84,13 +85,13 @@ exports[`VehicleDetailsTab Render 1`] = `
> >
<a <a
class="" class=""
href="/vehicle-update?vin=undefined" href="/vehicle-update?vin=TESTVIN1234567890"
style="margin: 5px;" style="margin: 5px;"
title="Update \\"undefined\\"" title="Update \\"TESTVIN1234567890\\""
> >
<svg <svg
aria-hidden="true" aria-hidden="true"
aria-label="Update \\"undefined\\"" aria-label="Update \\"TESTVIN1234567890\\""
class="MuiSvgIcon-root" class="MuiSvgIcon-root"
focusable="false" focusable="false"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -103,11 +104,11 @@ exports[`VehicleDetailsTab Render 1`] = `
<a <a
class="" class=""
href="/" href="/"
title="Delete \\"undefined\\"" title="Delete \\"TESTVIN1234567890\\""
> >
<svg <svg
aria-hidden="true" aria-hidden="true"
aria-label="Delete \\"undefined\\"" aria-label="Delete \\"TESTVIN1234567890\\""
class="MuiSvgIcon-root" class="MuiSvgIcon-root"
focusable="false" focusable="false"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -119,6 +120,7 @@ exports[`VehicleDetailsTab Render 1`] = `
</a> </a>
</div> </div>
</div> </div>
<div />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -14,12 +14,14 @@ import { useStatusContext } from "../../../Contexts/StatusContext";
import useStyles from "../../../useStyles"; import useStyles from "../../../useStyles";
import { logger } from "../../../../services/monitoring"; import { logger } from "../../../../services/monitoring";
import { useVehicleContext, VehicleProvider } from "../../../Contexts/VehicleContext"; import { useVehicleContext, VehicleProvider } from "../../../Contexts/VehicleContext";
import DeleteConfirmation from "../../../DeleteConfirmation";
const MainForm = ({ vin }) => { const MainForm = ({ vin }) => {
const classes = useStyles(); const classes = useStyles();
const { setMessage } = useStatusContext(); const { setMessage } = useStatusContext();
const { vehicle, getVehicle, deleteVehicle } = useVehicleContext(); const { vehicle, getVehicle, deleteVehicle } = useVehicleContext();
const [redirect, setRedirect] = useState(null); const [redirect, setRedirect] = useState(null);
const [showDeleteModal, setShowDeleteModal] = useState(false)
const { token: { idToken: { jwtToken: token } } } = useUserContext(); const { token: { idToken: { jwtToken: token } } } = useUserContext();
useEffect(() => { useEffect(() => {
@@ -76,12 +78,13 @@ const MainForm = ({ vin }) => {
</Link> </Link>
</Tooltip> </Tooltip>
<Tooltip key={`delete-${vin}`} title={`Delete "${vin}"`}> <Tooltip key={`delete-${vin}`} title={`Delete "${vin}"`}>
<Link to="#" onClick={onDelete}> <Link to="#" onClick={() => setShowDeleteModal(true)}>
<DeleteIcon aria-label={`Delete "${vin}"`} /> <DeleteIcon aria-label={`Delete "${vin}"`} />
</Link> </Link>
</Tooltip> </Tooltip>
</Grid> </Grid>
</Grid> </Grid>
<DeleteConfirmation message={vin} open={showDeleteModal} close={()=> setShowDeleteModal(false)} deleteFunction={onDelete}/>
</div > </div >
); );
}; };

View File

@@ -4,6 +4,7 @@ jest.mock("../../../Contexts/UserContext");
import { render, waitFor } from "@testing-library/react"; import { render, waitFor } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom";
import routeData from "react-router";
import { VehicleProvider } from "../../../Contexts/VehicleContext"; import { VehicleProvider } from "../../../Contexts/VehicleContext";
import { StatusProvider } from "../../../Contexts/StatusContext"; import { StatusProvider } from "../../../Contexts/StatusContext";
@@ -18,7 +19,7 @@ const renderVehicleDetailsTab = async () => {
<StatusProvider> <StatusProvider>
<UserProvider> <UserProvider>
<BrowserRouter> <BrowserRouter>
<MainForm /> <MainForm vin="TESTVIN1234567890"/>
</BrowserRouter> </BrowserRouter>
</UserProvider> </UserProvider>
</StatusProvider> </StatusProvider>
@@ -35,6 +36,11 @@ describe("VehicleDetailsTab", () => {
addSnapshotSerializer(expect); addSnapshotSerializer(expect);
}); });
beforeEach(() => {
// Does not work if placed in beforeAll
jest.spyOn(routeData, 'useParams').mockReturnValue({ vin: "TESTVIN1234567890" })
})
it("Render", async () => { it("Render", async () => {
setToken(TEST_AUTH_OBJECT); setToken(TEST_AUTH_OBJECT);
const container = await renderVehicleDetailsTab(); const container = await renderVehicleDetailsTab();

View File

@@ -128,6 +128,7 @@ exports[`DetailsTab Render 1`] = `
</a> </a>
</div> </div>
</div> </div>
<div />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -175,6 +175,7 @@ exports[`CarStatus Render 1`] = `
VIN VIN
</b> </b>
: :
TESTVIN1234567890
</p> </p>
</div> </div>
<div <div
@@ -182,13 +183,13 @@ exports[`CarStatus Render 1`] = `
> >
<a <a
class="" class=""
href="/vehicle-update?vin=undefined" href="/vehicle-update?vin=TESTVIN1234567890"
style="margin: 5px;" style="margin: 5px;"
title="Update \\"undefined\\"" title="Update \\"TESTVIN1234567890\\""
> >
<svg <svg
aria-hidden="true" aria-hidden="true"
aria-label="Update \\"undefined\\"" aria-label="Update \\"TESTVIN1234567890\\""
class="MuiSvgIcon-root" class="MuiSvgIcon-root"
focusable="false" focusable="false"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -201,11 +202,11 @@ exports[`CarStatus Render 1`] = `
<a <a
class="" class=""
href="/" href="/"
title="Delete \\"undefined\\"" title="Delete \\"TESTVIN1234567890\\""
> >
<svg <svg
aria-hidden="true" aria-hidden="true"
aria-label="Delete \\"undefined\\"" aria-label="Delete \\"TESTVIN1234567890\\""
class="MuiSvgIcon-root" class="MuiSvgIcon-root"
focusable="false" focusable="false"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -217,6 +218,7 @@ exports[`CarStatus Render 1`] = `
</a> </a>
</div> </div>
</div> </div>
<div />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -7,6 +7,7 @@ jest.mock("@material-ui/core/utils/unstable_useId", () =>
import { render, waitFor } from "@testing-library/react"; import { render, waitFor } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom";
import routeData from "react-router";
import { CANFiltersProvider } from "../../Contexts/CANFiltersContext"; import { CANFiltersProvider } from "../../Contexts/CANFiltersContext";
import { StatusProvider } from "../../Contexts/StatusContext"; import { StatusProvider } from "../../Contexts/StatusContext";
@@ -38,6 +39,11 @@ describe("CarStatus", () => {
addSnapshotSerializer(expect); addSnapshotSerializer(expect);
}); });
beforeEach(() => {
// Does not work if placed in beforeAll
jest.spyOn(routeData, 'useParams').mockReturnValue({ vin: "TESTVIN1234567890" })
})
it("Render", async () => { it("Render", async () => {
setToken(TEST_AUTH_OBJECT); setToken(TEST_AUTH_OBJECT);
const container = await renderCarStatus(); const container = await renderCarStatus();

View File

@@ -3,7 +3,7 @@ import { Box } from "@material-ui/core";
function TabPanel(props) { function TabPanel(props) {
const { children, value, index, ...other } = props; const { children, value, index, ...other } = props;
return ( return (
<div <div
role="tabpanel" role="tabpanel"

View File

@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Delete Confirmation Modal Should render 1`] = `
<div
aria-hidden="true"
>
<div />
</div>
`;

View File

@@ -0,0 +1,36 @@
import React from "react";
import PropTypes from "prop-types";
import {Dialog, DialogTitle, DialogContentText, Button, DialogActions, DialogContent} from '@material-ui/core';
const DeleteConfirmation = (props) => {
return (
<div>
<Dialog open={props.open}
onClose={props.close}>
<DialogTitle id="alert-dialog-title">
{"Delete Resource?"}
</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
{"Are you sure you want to delete: " + props.message}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={props.close}>Cancel</Button>
<Button variant="contained" color="secondary" onClick={() => { props.close(); props.deleteFunction()}} autoFocus>
Delete
</Button>
</DialogActions>
</Dialog>
</div>
)
}
DeleteConfirmation.propTypes={
open: PropTypes.bool.isRequired, // Boolean that determines if the modal should be open
close: PropTypes.func.isRequired, // Function that sets the open state to false i.e. () => setOpen(false)
message: PropTypes.any.isRequired, // What the user will see if being confirmed to be deleted
deleteFunction: PropTypes.func.isRequired, // Function that runs when user clicks delete
}
export default DeleteConfirmation;

View File

@@ -0,0 +1,20 @@
jest.mock("../Contexts/UserContext");
import React from "react";
import { render, cleanup } from "@testing-library/react";
import DeleteConfirmation from "./index";
import addSnapshotSerializer from "../../utils/snapshot";
describe("Delete Confirmation Modal", () => {
beforeAll(() => {
addSnapshotSerializer(expect);
});
it("Should render", () => {
const { container } = render(
<DeleteConfirmation open={true} close={()=>{}} message="Test Message" deleteFunction={()=>{}}/>
);
expect(container).toMatchSnapshot();
cleanup();
});
});

View File

@@ -28,6 +28,7 @@ exports[`FleetDetailsTab Render 1`] = `
Name Name
</b> </b>
: :
Test Fleet
</p> </p>
<p> <p>
<b> <b>
@@ -91,13 +92,13 @@ exports[`FleetDetailsTab Render 1`] = `
> >
<a <a
class="" class=""
href="/fleet-update?name=undefined" href="/fleet-update?name=Test Fleet"
style="margin: 5px;" style="margin: 5px;"
title="Update \\"undefined\\"" title="Update \\"Test Fleet\\""
> >
<svg <svg
aria-hidden="true" aria-hidden="true"
aria-label="Update \\"undefined\\"" aria-label="Update \\"Test Fleet\\""
class="MuiSvgIcon-root" class="MuiSvgIcon-root"
focusable="false" focusable="false"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -110,11 +111,11 @@ exports[`FleetDetailsTab Render 1`] = `
<a <a
class="" class=""
href="/" href="/"
title="Delete \\"undefined\\"" title="Delete \\"Test Fleet\\""
> >
<svg <svg
aria-hidden="true" aria-hidden="true"
aria-label="Delete \\"undefined\\"" aria-label="Delete \\"Test Fleet\\""
class="MuiSvgIcon-root" class="MuiSvgIcon-root"
focusable="false" focusable="false"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -126,6 +127,7 @@ exports[`FleetDetailsTab Render 1`] = `
</a> </a>
</div> </div>
</div> </div>
<div />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -14,12 +14,14 @@ import { useStatusContext } from "../../../Contexts/StatusContext";
import { FleetProvider, useFleetContext } from "../../../Contexts/FleetContext" import { FleetProvider, useFleetContext } from "../../../Contexts/FleetContext"
import useStyles from "../../../useStyles"; import useStyles from "../../../useStyles";
import { logger } from "../../../../services/monitoring"; import { logger } from "../../../../services/monitoring";
import DeleteConfirmation from "../../../DeleteConfirmation";
const MainForm = ({ name }) => { const MainForm = ({ name }) => {
const classes = useStyles(); const classes = useStyles();
const { setMessage } = useStatusContext(); const { setMessage } = useStatusContext();
const { fleet, getFleet, deleteFleet } = useFleetContext(); const { fleet, getFleet, deleteFleet } = useFleetContext();
const [redirect, setRedirect] = useState(null); const [redirect, setRedirect] = useState(null);
const [showDeleteModal, setShowDeleteModal] = useState(false)
const { token: { idToken: { jwtToken: token } } } = useUserContext(); const { token: { idToken: { jwtToken: token } } } = useUserContext();
useEffect(() => { useEffect(() => {
@@ -77,12 +79,13 @@ const MainForm = ({ name }) => {
</Link> </Link>
</Tooltip> </Tooltip>
<Tooltip key={`delete-${name}`} title={`Delete "${name}"`}> <Tooltip key={`delete-${name}`} title={`Delete "${name}"`}>
<Link to="#" onClick={onDelete}> <Link to="#" onClick={() => setShowDeleteModal(true)}>
<DeleteIcon aria-label={`Delete "${name}"`} /> <DeleteIcon aria-label={`Delete "${name}"`} />
</Link> </Link>
</Tooltip> </Tooltip>
</Grid> </Grid>
</Grid> </Grid>
<DeleteConfirmation message={name} open={showDeleteModal} close={()=> setShowDeleteModal(false)} deleteFunction={onDelete}/>
</div > </div >
); );
}; };

View File

@@ -4,6 +4,7 @@ jest.mock("../../../Contexts/UserContext");
import { render, waitFor } from "@testing-library/react"; import { render, waitFor } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom";
import routeData from "react-router";
import { FleetProvider } from "../../../Contexts/FleetContext"; import { FleetProvider } from "../../../Contexts/FleetContext";
import { StatusProvider } from "../../../Contexts/StatusContext"; import { StatusProvider } from "../../../Contexts/StatusContext";
@@ -18,7 +19,7 @@ const renderFleetDetailsTab = async () => {
<StatusProvider> <StatusProvider>
<UserProvider> <UserProvider>
<BrowserRouter> <BrowserRouter>
<MainForm /> <MainForm name="Test Fleet"/>
</BrowserRouter> </BrowserRouter>
</UserProvider> </UserProvider>
</StatusProvider> </StatusProvider>
@@ -35,6 +36,11 @@ describe("FleetDetailsTab", () => {
addSnapshotSerializer(expect); addSnapshotSerializer(expect);
}); });
beforeEach(() => {
// Does not work if placed in beforeAll
jest.spyOn(routeData, 'useParams').mockReturnValue({ name: "Test Fleet" })
})
it("Render", async () => { it("Render", async () => {
setToken(TEST_AUTH_OBJECT); setToken(TEST_AUTH_OBJECT);
const container = await renderFleetDetailsTab(); const container = await renderFleetDetailsTab();

View File

@@ -153,23 +153,26 @@ exports[`FleetVehiclesTable Render 1`] = `
<td <td
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter" class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
> >
<a <div>
class="" <a
href="/" class=""
title="Delete \\"USWESTVIN12345678\\"" href="/"
> title="Delete \\"USWESTVIN12345678\\""
<svg
aria-hidden="true"
aria-label="Delete USWESTVIN12345678"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
> >
<path <svg
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" aria-hidden="true"
/> aria-label="Delete USWESTVIN12345678"
</svg> class="MuiSvgIcon-root"
</a> focusable="false"
viewBox="0 0 24 24"
>
<path
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
/>
</svg>
</a>
<div />
</div>
</td> </td>
</tr> </tr>
<tr <tr
@@ -187,23 +190,26 @@ exports[`FleetVehiclesTable Render 1`] = `
<td <td
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter" class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
> >
<a <div>
class="" <a
href="/" class=""
title="Delete \\"USWESTVIN12345679\\"" href="/"
> title="Delete \\"USWESTVIN12345679\\""
<svg
aria-hidden="true"
aria-label="Delete USWESTVIN12345679"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
> >
<path <svg
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" aria-hidden="true"
/> aria-label="Delete USWESTVIN12345679"
</svg> class="MuiSvgIcon-root"
</a> focusable="false"
viewBox="0 0 24 24"
>
<path
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
/>
</svg>
</a>
<div />
</div>
</td> </td>
</tr> </tr>
<tr <tr
@@ -221,23 +227,26 @@ exports[`FleetVehiclesTable Render 1`] = `
<td <td
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter" class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
> >
<a <div>
class="" <a
href="/" class=""
title="Delete \\"USWESTVIN12345670\\"" href="/"
> title="Delete \\"USWESTVIN12345670\\""
<svg
aria-hidden="true"
aria-label="Delete USWESTVIN12345670"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
> >
<path <svg
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" aria-hidden="true"
/> aria-label="Delete USWESTVIN12345670"
</svg> class="MuiSvgIcon-root"
</a> focusable="false"
viewBox="0 0 24 24"
>
<path
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
/>
</svg>
</a>
<div />
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@@ -22,7 +22,8 @@ import useStyles from "../../../../useStyles";
import SearchField from "../../../../Controls/SearchField"; import SearchField from "../../../../Controls/SearchField";
import { logger } from "../../../../../services/monitoring"; import { logger } from "../../../../../services/monitoring";
import { Roles, hasRole } from "../../../../../utils/roles"; import { Roles, hasRole } from "../../../../../utils/roles";
import {useLocalStorage} from "../../../../useLocalStorage"; import { useLocalStorage } from "../../../../useLocalStorage";
import DeleteConfirmation from "../../../../DeleteConfirmation";
const tableColumns = [ const tableColumns = [
{ {
@@ -43,6 +44,7 @@ const MainForm = ({ name }) => {
const [orderBy, setOrderBy] = useState("id"); const [orderBy, setOrderBy] = useState("id");
const [order, setOrder] = useState("desc"); const [order, setOrder] = useState("desc");
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const [showDeleteModal, setShowDeleteModal] = useState(false)
const classes = useStyles(); const classes = useStyles();
const { setMessage } = useStatusContext(); const { setMessage } = useStatusContext();
const { fleetVehicles, totalFleetVehicles, getFleetVehicles, deleteFleetVehicle } = useFleetContext(); const { fleetVehicles, totalFleetVehicles, getFleetVehicles, deleteFleetVehicle } = useFleetContext();
@@ -132,11 +134,15 @@ const MainForm = ({ name }) => {
); );
} else { } else {
return ( return (
<Tooltip key={`delete-${action.id}`} title={action.tip}> <div>
<Link to="#" onClick={() => onDelete(action.id)}> <Tooltip key={`delete-${action.id}`} title={action.tip}>
{action.icon} <Link to="#" onClick={() => onDelete(action.id)}>
</Link> {action.icon}
</Tooltip> </Link>
</Tooltip>
<DeleteConfirmation message={action.id} open={showDeleteModal} close={() => setShowDeleteModal(false)} deleteFunction={() => onDelete(action.id)} />
</div>
); );
} }
}); });
@@ -151,7 +157,7 @@ const MainForm = ({ name }) => {
</Link> </Link>
</Grid> </Grid>
<Grid item md={8} align="right" className={classes.textCenterAlign}> <Grid item md={8} align="right" className={classes.textCenterAlign}>
<SearchField classes={classes} onSearch={handleSearch}/> <SearchField classes={classes} onSearch={handleSearch} />
</Grid> </Grid>
</Grid> </Grid>
<Table> <Table>

View File

@@ -135,6 +135,7 @@ exports[`DetailsTab Render 1`] = `
</a> </a>
</div> </div>
</div> </div>
<div />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -152,23 +152,26 @@ exports[`VehiclesTab Render 1`] = `
<td <td
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter" class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
> >
<a <div>
class="" <a
href="/" class=""
title="Delete \\"USWESTVIN12345678\\"" href="/"
> title="Delete \\"USWESTVIN12345678\\""
<svg
aria-hidden="true"
aria-label="Delete USWESTVIN12345678"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
> >
<path <svg
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" aria-hidden="true"
/> aria-label="Delete USWESTVIN12345678"
</svg> class="MuiSvgIcon-root"
</a> focusable="false"
viewBox="0 0 24 24"
>
<path
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
/>
</svg>
</a>
<div />
</div>
</td> </td>
</tr> </tr>
<tr <tr
@@ -186,23 +189,26 @@ exports[`VehiclesTab Render 1`] = `
<td <td
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter" class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
> >
<a <div>
class="" <a
href="/" class=""
title="Delete \\"USWESTVIN12345679\\"" href="/"
> title="Delete \\"USWESTVIN12345679\\""
<svg
aria-hidden="true"
aria-label="Delete USWESTVIN12345679"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
> >
<path <svg
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" aria-hidden="true"
/> aria-label="Delete USWESTVIN12345679"
</svg> class="MuiSvgIcon-root"
</a> focusable="false"
viewBox="0 0 24 24"
>
<path
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
/>
</svg>
</a>
<div />
</div>
</td> </td>
</tr> </tr>
<tr <tr
@@ -220,23 +226,26 @@ exports[`VehiclesTab Render 1`] = `
<td <td
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter" class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
> >
<a <div>
class="" <a
href="/" class=""
title="Delete \\"USWESTVIN12345670\\"" href="/"
> title="Delete \\"USWESTVIN12345670\\""
<svg
aria-hidden="true"
aria-label="Delete USWESTVIN12345670"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
> >
<path <svg
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" aria-hidden="true"
/> aria-label="Delete USWESTVIN12345670"
</svg> class="MuiSvgIcon-root"
</a> focusable="false"
viewBox="0 0 24 24"
>
<path
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
/>
</svg>
</a>
<div />
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@@ -124,6 +124,7 @@ exports[`FleetStatus Render 1`] = `
Name Name
</b> </b>
: :
Fleet Name
</p> </p>
<p> <p>
<b> <b>
@@ -187,13 +188,13 @@ exports[`FleetStatus Render 1`] = `
> >
<a <a
class="" class=""
href="/fleet-update?name=undefined" href="/fleet-update?name=Fleet Name"
style="margin: 5px;" style="margin: 5px;"
title="Update \\"undefined\\"" title="Update \\"Fleet Name\\""
> >
<svg <svg
aria-hidden="true" aria-hidden="true"
aria-label="Update \\"undefined\\"" aria-label="Update \\"Fleet Name\\""
class="MuiSvgIcon-root" class="MuiSvgIcon-root"
focusable="false" focusable="false"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -206,11 +207,11 @@ exports[`FleetStatus Render 1`] = `
<a <a
class="" class=""
href="/" href="/"
title="Delete \\"undefined\\"" title="Delete \\"Fleet Name\\""
> >
<svg <svg
aria-hidden="true" aria-hidden="true"
aria-label="Delete \\"undefined\\"" aria-label="Delete \\"Fleet Name\\""
class="MuiSvgIcon-root" class="MuiSvgIcon-root"
focusable="false" focusable="false"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -222,6 +223,7 @@ exports[`FleetStatus Render 1`] = `
</a> </a>
</div> </div>
</div> </div>
<div />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -7,6 +7,7 @@ jest.mock("@material-ui/core/utils/unstable_useId", () =>
import { render, waitFor } from "@testing-library/react"; import { render, waitFor } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom";
import routeData from "react-router";
import { FleetProvider } from "../../Contexts/FleetContext"; import { FleetProvider } from "../../Contexts/FleetContext";
import { StatusProvider } from "../../Contexts/StatusContext"; import { StatusProvider } from "../../Contexts/StatusContext";
@@ -38,6 +39,11 @@ describe("FleetStatus", () => {
addSnapshotSerializer(expect); addSnapshotSerializer(expect);
}); });
beforeEach(() => {
// Does not work if placed in beforeAll
jest.spyOn(routeData, 'useParams').mockReturnValue({ name: "Fleet Name" })
})
it("Render", async () => { it("Render", async () => {
setToken(TEST_AUTH_OBJECT); setToken(TEST_AUTH_OBJECT);
const container = await renderCarStatus(); const container = await renderCarStatus();

View File

@@ -30,6 +30,7 @@ import ECUList from "../../Controls/ECUList";
import { Roles, hasRole } from "../../../utils/roles"; import { Roles, hasRole } from "../../../utils/roles";
import { useLocalStorage } from "../../useLocalStorage"; import { useLocalStorage } from "../../useLocalStorage";
import { TYPE_MANIFEST_SOFTWARE } from "../../../utils/manifest_types"; import { TYPE_MANIFEST_SOFTWARE } from "../../../utils/manifest_types";
import DeleteConfirmation from "../../DeleteConfirmation";
const tableColumns = [ const tableColumns = [
{ {
@@ -67,6 +68,7 @@ const MainForm = () => {
const [orderBy, setOrderBy] = useState("id"); const [orderBy, setOrderBy] = useState("id");
const [order, setOrder] = useState("asc"); const [order, setOrder] = useState("asc");
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const [showDeleteModal, setShowDeleteModal] = useState(false)
const { getManifests, deleteManifest, manifests, totalManifests } = const { getManifests, deleteManifest, manifests, totalManifests } =
useManifestsContext(); useManifestsContext();
const { setMessage, setTitle, setSitePath } = useStatusContext(); const { setMessage, setTitle, setSitePath } = useStatusContext();
@@ -178,11 +180,14 @@ const MainForm = () => {
); );
} else { } else {
return ( return (
<div>
<Tooltip key={`delete-${action.id}`} title={action.tip}> <Tooltip key={`delete-${action.id}`} title={action.tip}>
<Link to="#" onClick={() => onDelete(action.id)}> <Link to="#" onClick={() => onDelete(action.id)}>
{action.icon} {action.icon}
</Link> </Link>
</Tooltip> </Tooltip>
<DeleteConfirmation message={action.id} open={showDeleteModal} close={() => setShowDeleteModal(false)} deleteFunction={() => onDelete(action.id)} />
</div>
); );
} }
}); });