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:
127
src/components/Contexts/CANFiltersContext.jsx
Normal file
127
src/components/Contexts/CANFiltersContext.jsx
Normal 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);
|
||||
149
src/components/Contexts/CANFiltersContext.test.jsx
Normal file
149
src/components/Contexts/CANFiltersContext.test.jsx
Normal 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
|
||||
},
|
||||
];
|
||||
@@ -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}
|
||||
|
||||
30
src/components/Contexts/__mocks__/CANFiltersContext.jsx
Normal file
30
src/components/Contexts/__mocks__/CANFiltersContext.jsx
Normal 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(),
|
||||
});
|
||||
16
src/components/Contexts/__mocks__/StatusContext.jsx
Normal file
16
src/components/Contexts/__mocks__/StatusContext.jsx
Normal 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),
|
||||
});
|
||||
Reference in New Issue
Block a user