CEC-464 can filters forms (#118)

* can filters forms and lists

* unit tests

* updating warnings and tests

* merge develop

* fixed snapshots

* update jest mocks

* updating tests
This commit is contained in:
Drew Taylor
2022-03-03 11:33:07 -08:00
committed by GitHub
parent 3b9252097a
commit b7223b8bc6
37 changed files with 6673 additions and 944 deletions

View File

@@ -0,0 +1,127 @@
import React, { useContext, useState } from "react";
import api from "../../services/CANFiltersAPI";
const CANFiltersContext = React.createContext();
export const CANFiltersProvider = ({ children }) => {
const [busy, setBusy] = useState(false);
const [filters, setFilters] = useState([]);
const [totalFilters, setTotalFilters] = useState(0);
const addFilter = async (vin, filter, token) => {
try {
setBusy(true);
validateVIN(vin);
validateFilter(filter);
const result = await api.addFilter(vin, filter, token);
if (result.error) throw new Error(`Add filter error. ${result.message}`);
return result;
} finally {
setBusy(false);
}
};
const getFilters = async (vin, search, token) => {
try {
setBusy(true);
validateVIN(vin);
const result = await api.getFilters(vin, search, token);
if (result.error) {
setFilters([])
throw new Error(`Get filters error. ${result.message}`);
}
setFilters(result.data)
if (result.total) {
setTotalFilters(result.total);
}
return result;
} finally {
setBusy(false);
}
};
const updateFilter = async (vin, canID, filter, token) => {
try {
setBusy(true);
validateVIN(vin);
validateID(canID);
validateFilter(filter);
const result = await api.updateFilter(vin, canID, filter, token);
if (result.error) {
throw new Error(`Update filters error. ${result.message}`);
}
return result;
} finally {
setBusy(false);
}
}
const deleteFilter = async (vin, canID, token) => {
try {
setBusy(true);
validateVIN(vin);
validateID(canID);
const result = await api.deleteFilter(vin, canID, token);
if (result.error) {
throw new Error(`Delete filter error. ${result.message}`);
}
const index = filters.findIndex(element => element.can_id === canID);
if (index >= 0) filters.splice(index, 1);
return result;
} finally {
setBusy(false);
}
}
return (
<CANFiltersContext.Provider
value={{
busy,
filters,
totalFilters,
addFilter,
getFilters,
updateFilter,
deleteFilter
}}
>
{children}
</CANFiltersContext.Provider>
);
};
const validateVIN = (vin) => {
if (vin == null || vin.length !== 17) {
throw new Error("Invalid VIN");
}
}
const validateID = (can_id) => {
if (can_id == null || can_id === "") {
throw new Error("CAN ID required");
}
}
const validateFilter = (filter) => {
if (filter == null) {
throw new Error("No filter data");
}
validateID(filter.can_id)
if (filter.interval == null) {
throw new Error("Interval required");
}
};
export const useCANFiltersContext = () => useContext(CANFiltersContext);

View File

@@ -0,0 +1,149 @@
jest.mock("../../services/CANFiltersAPI")
import {
render,
cleanup,
screen,
fireEvent,
waitFor,
} from "@testing-library/react";
import { CANFiltersProvider, useCANFiltersContext } from "./CANFiltersContext";
import { StatusProvider, useStatusContext } from "./StatusContext";
const checkFiltersResults = (error, busy, filters) => {
checkBaseResults(error, busy);
expect(screen.getByTestId("filters").innerHTML).toEqual(filters);
};
const checkBaseResults = (error, busy) => {
expect(screen.getByTestId("error").innerHTML).toEqual(error);
expect(screen.getByTestId("busy").innerHTML).toEqual(busy);
};
describe("CANFiltersContext", () => {
describe("getFilters", () => {
beforeEach(() => {
const TestComp = () => {
const { busy, error, filters, getFilters } = useCANFiltersContext();
return (
<>
<div data-testid="error">{error}</div>
<div data-testid="busy">{busy.toString()}</div>
<div data-testid="filters">{JSON.stringify(filters)}</div>
<button
data-testid="getFilters"
onClick={() => getFilters("TESTVIN1234567890")}
/>
</>
);
};
render(
<CANFiltersProvider>
<TestComp />
</CANFiltersProvider>
);
});
afterEach(() => {
cleanup();
});
it("initial state", () => {
checkFiltersResults("", "false", "[]");
});
it("getFilters", async () => {
fireEvent.click(screen.getByTestId("getFilters"));
await waitFor(() =>
expect(screen.getByTestId("filters").innerHTML).not.toBe("[]")
);
checkFiltersResults("", "false", JSON.stringify(expectedFiltersData));
});
});
describe("addFilter", () => {
beforeEach(async () => {
const TestComp = () => {
const { busy, addFilter } = useCANFiltersContext();
const { message, setMessage } = useStatusContext();
const add = async (data) => {
try {
await addFilter("TESTVIN1234567890", data);
} catch (e) {
setMessage(e.message);
}
};
return (
<>
<div data-testid="error">{message}</div>
<div data-testid="busy">{busy.toString()}</div>
<button data-testid="addFilterNull" onClick={() => add(null)} />
<button data-testid="addFilterNoCANID" onClick={() => add({})} />
<button
data-testid="addFilter"
onClick={() =>
add({ can_id: "123", interval: 1000 })
}
/>
</>
);
};
render(
<StatusProvider>
<CANFiltersProvider>
<TestComp />
</CANFiltersProvider>
</StatusProvider>
);
});
afterEach(() => {
cleanup();
});
it("initial state", () => {
checkBaseResults("", "false");
});
it("addFilterNull", async () => {
fireEvent.click(screen.getByTestId("addFilterNull"));
await waitFor(() =>
expect(screen.getByTestId("busy").innerHTML).toEqual("false")
);
checkBaseResults("No filter data", "false");
});
it("addFilterNoCANID", async () => {
fireEvent.click(screen.getByTestId("addFilterNoCANID"));
await waitFor(() =>
expect(screen.getByTestId("busy").innerHTML).toEqual("false")
);
checkBaseResults("CAN ID required", "false");
});
it("addFilter", async () => {
fireEvent.click(screen.getByTestId("addFilter"));
await waitFor(() =>
expect(screen.getByTestId("busy").innerHTML).toEqual("false")
);
checkBaseResults("", "false");
});
});
});
const expectedFiltersData = [
{
can_id: "123",
interval: 1000
},
{
can_id: "456",
interval: 0
},
{
can_id: "789-1000",
interval: 5
},
];

View File

@@ -5,7 +5,7 @@ import api from "../../services/vehiclesAPI";
const VehicleContext = React.createContext();
const validateAdd = (vehicle) => {
if (vehicle === null) {
if (vehicle == null) {
throw new Error("No vehicle data");
}
@@ -175,7 +175,7 @@ export const VehicleProvider = ({ children }) => {
getState,
getYears,
getVehicles,
sendCommand,
sendCommand
}}
>
{children}

View File

@@ -0,0 +1,30 @@
let busy = false;
let filters = [
{
can_id: "123",
interval: 1000
},
{
can_id: "456-789",
interval: 2000
},
{
can_id: "1",
interval: 0
},
];
let totalFilters = 3;
export const CANFiltersProvider = ({ children }) => {
return <div data-testid="mocked-canfiltersprovider">{children}</div>;
};
export const useCANFiltersContext = () => ({
busy,
filters,
totalFilters,
addFilter: jest.fn(),
getFilters: jest.fn(),
updateFilter: jest.fn(),
deleteFilter: jest.fn(),
});

View File

@@ -0,0 +1,16 @@
let message = ""
let title = ""
let sitePath = {}
export const StatusProvider = ({ children }) => {
return <div data-testid="mocked-statusprovider">{children}</div>;
};
export const useStatusContext = () => ({
message,
title,
sitePath,
setMessage: jest.fn(m => message = m),
setTitle: jest.fn(t => title = t),
setSitePath: jest.fn(s => sitePath = s),
});