Merge branch 'release/0.0.3'
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import React, { useContext, useState, useEffect } from "react";
|
||||
import React, {useContext, useState} from "react";
|
||||
|
||||
import api from "../../services/vehiclesAPI";
|
||||
import { useUserContext } from "./UserContext";
|
||||
import { LocalDateTimeString } from "../../utils/dates";
|
||||
import {useInterval} from "usehooks-ts";
|
||||
|
||||
const CANSignalContext = React.createContext();
|
||||
|
||||
@@ -15,41 +15,26 @@ const BlankSignal = (msg) => ({
|
||||
const transformSignals = (signals) =>
|
||||
signals
|
||||
.map((signal) => {
|
||||
const { Timestamp, ...Settings } = signal;
|
||||
const keys = Object.keys(Settings);
|
||||
const { timestamp, value, name } = signal;
|
||||
|
||||
return keys.map((key) => ({
|
||||
timestamp: LocalDateTimeString(Timestamp),
|
||||
signal: key,
|
||||
value: Settings[key],
|
||||
}));
|
||||
return {
|
||||
timestamp: LocalDateTimeString(timestamp),
|
||||
signal: name,
|
||||
value: value,
|
||||
};
|
||||
})
|
||||
.flat();
|
||||
|
||||
export const CANSignalProvider = ({ children }) => {
|
||||
const {
|
||||
token: {
|
||||
idToken: { jwtToken: token },
|
||||
},
|
||||
} = useUserContext();
|
||||
export const CANSignalProvider = ({ token, children }) => {
|
||||
const [vin, setVIN] = useState(null);
|
||||
const [signals, setSignals] = useState([]);
|
||||
let delay = 500;
|
||||
const [delay, setDelay] = useState(500);
|
||||
|
||||
useEffect(() => {
|
||||
getCANSignals();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [vin]);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
getCANSignals();
|
||||
}, delay);
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [signals]);
|
||||
useInterval(
|
||||
() => {
|
||||
getCANSignals()
|
||||
}, vin?delay:null
|
||||
)
|
||||
|
||||
const getCANSignals = async () => {
|
||||
try {
|
||||
@@ -62,10 +47,10 @@ export const CANSignalProvider = ({ children }) => {
|
||||
const items = transformSignals(result.data);
|
||||
|
||||
if (items.length > 0) {
|
||||
delay = 500;
|
||||
setDelay(500);
|
||||
setSignals(items);
|
||||
} else {
|
||||
delay = 1000;
|
||||
setDelay(1000);
|
||||
setSignals([BlankSignal("No signals")]);
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
75
src/components/Contexts/CANSignalsContext.test.jsx
Normal file
75
src/components/Contexts/CANSignalsContext.test.jsx
Normal file
@@ -0,0 +1,75 @@
|
||||
jest.mock("../../services/vehiclesAPI");
|
||||
|
||||
import {
|
||||
render,
|
||||
cleanup,
|
||||
screen,
|
||||
fireEvent,
|
||||
waitFor,
|
||||
act,
|
||||
} from "@testing-library/react";
|
||||
import {CANSignalProvider, useCANSignalContext} from "./CANSignalsContext";
|
||||
|
||||
const checkSignalsResults = (filters) => {
|
||||
expect(screen.getByTestId("signals").innerHTML).toEqual(filters);
|
||||
};
|
||||
|
||||
describe("CANSignalsContext", () => {
|
||||
describe("getSignals", () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers("setInterval");
|
||||
const TestComp = () => {
|
||||
const { signals, setVIN } = useCANSignalContext();
|
||||
|
||||
return (
|
||||
<>
|
||||
<div data-testid="signals">{JSON.stringify(signals)}</div>
|
||||
<button
|
||||
data-testid="getSignals"
|
||||
onClick={()=>{setVIN("TESTVIN1234567890")}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
render(
|
||||
<CANSignalProvider>
|
||||
<TestComp />
|
||||
</CANSignalProvider>
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
cleanup();
|
||||
});
|
||||
|
||||
it("initial state", () => {
|
||||
checkSignalsResults("[]");
|
||||
});
|
||||
|
||||
it("getSignals", async () => {
|
||||
// eslint-disable-next-line testing-library/no-unnecessary-act
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByTestId("getSignals"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("signals").innerHTML).toBe("[]")
|
||||
);
|
||||
jest.advanceTimersByTime(501);
|
||||
})
|
||||
|
||||
await waitFor(() => {
|
||||
return expect(screen.getByTestId("signals").innerHTML).not.toBe("[]");
|
||||
} );
|
||||
|
||||
checkSignalsResults(JSON.stringify(expectedSignalsData));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const expectedSignalsData = [
|
||||
{
|
||||
timestamp: "7/14/2021 8:09:40 PM",
|
||||
signal: "signal",
|
||||
value: 123
|
||||
},
|
||||
];
|
||||
@@ -139,7 +139,7 @@ describe("FleetContext", () => {
|
||||
onClick={() =>
|
||||
add({
|
||||
name: "EU-WEST",
|
||||
log_level: "warn",
|
||||
log_level: "warning",
|
||||
canbus: { enabled: false },
|
||||
})
|
||||
}
|
||||
@@ -219,7 +219,7 @@ describe("FleetContext", () => {
|
||||
onClick={() =>
|
||||
update({
|
||||
name: "EU-WEST",
|
||||
log_level: "warn",
|
||||
log_level: "warning",
|
||||
canbus: { enabled: false },
|
||||
})
|
||||
}
|
||||
@@ -782,7 +782,7 @@ const expectedFleetsData = [
|
||||
},
|
||||
{
|
||||
name: "US-CENTRAL",
|
||||
log_level: "warn",
|
||||
log_level: "warning",
|
||||
canbus: {
|
||||
enabled: false,
|
||||
data_logger_enabled: false,
|
||||
|
||||
@@ -31,6 +31,8 @@ export const VehicleProvider = ({ children }) => {
|
||||
const [vehicle, setVehicle] = useState({});
|
||||
const [vehicles, setVehicles] = useState([]);
|
||||
const [totalVehicles, setTotalVehicles] = useState(0);
|
||||
const [fleets, setFleets] = useState([]);
|
||||
const [totalFleets, setTotalFleets] = useState(0);
|
||||
const [models, setModels] = useState([]);
|
||||
const [years, setYears] = useState([]);
|
||||
|
||||
@@ -45,6 +47,7 @@ export const VehicleProvider = ({ children }) => {
|
||||
}
|
||||
cars.forEach((car) => {
|
||||
car.connected = result[car.vin] || false;
|
||||
car.connectedHMI = result[`2:${car.vin}`] || false;
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error(e.stack);
|
||||
@@ -219,6 +222,25 @@ export const VehicleProvider = ({ children }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const getFleets = async (vin, search, token) => {
|
||||
try {
|
||||
setBusy(true);
|
||||
validateVIN(vin);
|
||||
|
||||
const result = await api.getFleets(vin, search, token);
|
||||
if (result.error) {
|
||||
setFleets([]);
|
||||
throw new Error(`Get Fleets of vehicle`)
|
||||
}
|
||||
setFleets(result.data ?? []);
|
||||
if (result.total) {
|
||||
setTotalFleets(result.total);
|
||||
}
|
||||
} finally {
|
||||
setBusy(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<VehicleContext.Provider
|
||||
value={{
|
||||
@@ -228,6 +250,8 @@ export const VehicleProvider = ({ children }) => {
|
||||
vehicle,
|
||||
vehicles,
|
||||
years,
|
||||
fleets,
|
||||
totalFleets,
|
||||
addVehicle,
|
||||
deleteVehicle,
|
||||
getConnections,
|
||||
@@ -241,6 +265,7 @@ export const VehicleProvider = ({ children }) => {
|
||||
getVehicles,
|
||||
sendCommand,
|
||||
updateVehicle,
|
||||
getFleets,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -13,19 +13,64 @@ import { StatusProvider, useStatusContext } from "./StatusContext";
|
||||
const checkVehicleResult = (error, busy, vehicle) => {
|
||||
checkBaseResults(error, busy);
|
||||
expect(screen.getByTestId("vehicle").innerHTML).toEqual(vehicle);
|
||||
}
|
||||
};
|
||||
|
||||
const checkVehiclesResult = (error, busy, vehicles) => {
|
||||
checkBaseResults(error, busy);
|
||||
expect(screen.getByTestId("vehicles").innerHTML).toEqual(vehicles);
|
||||
};
|
||||
|
||||
const checkFleetsResult = (error, busy, fleets) => {
|
||||
checkBaseResults(error, busy);
|
||||
expect(screen.getByTestId("fleets").innerHTML).toEqual(fleets);
|
||||
};
|
||||
|
||||
const checkBaseResults = (error, busy) => {
|
||||
expect(screen.getByTestId("error").innerHTML).toEqual(error);
|
||||
expect(screen.getByTestId("busy").innerHTML).toEqual(busy);
|
||||
};
|
||||
|
||||
describe("VehicleContext", () => {
|
||||
describe("getFleets", () => {
|
||||
beforeEach(() => {
|
||||
const TestComp = () => {
|
||||
const { busy, error, fleets, getFleets } = useVehicleContext();
|
||||
|
||||
return (
|
||||
<>
|
||||
<div data-testid="error">{error}</div>
|
||||
<div data-testid="busy">{busy.toString()}</div>
|
||||
<div data-testid="fleets">{JSON.stringify(fleets)}</div>
|
||||
<button
|
||||
data-testid="getFleets"
|
||||
onClick={() => getFleets("3C4PDCBG0ET127145")}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
render(
|
||||
<VehicleProvider>
|
||||
<TestComp />
|
||||
</VehicleProvider>
|
||||
);
|
||||
});
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
it("Initial state", () => {
|
||||
checkFleetsResult("", "false", "[]");
|
||||
});
|
||||
|
||||
it("getFleets", async () => {
|
||||
fireEvent.click(screen.getByTestId("getFleets"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("fleets").innerHTML).not.toBe("[]")
|
||||
);
|
||||
checkFleetsResult("", "false", JSON.stringify(["fleet1", "fleet2"]));
|
||||
});
|
||||
});
|
||||
|
||||
describe("getVehicles", () => {
|
||||
beforeEach(() => {
|
||||
const TestComp = () => {
|
||||
@@ -195,12 +240,22 @@ describe("VehicleContext", () => {
|
||||
<>
|
||||
<div data-testid="error">{message}</div>
|
||||
<div data-testid="busy">{busy.toString()}</div>
|
||||
<button data-testid="updateVehicleNull" onClick={() => update(null)} />
|
||||
<button data-testid="updateVehicleNoVIN" onClick={() => update({})} />
|
||||
<button
|
||||
data-testid="updateVehicleNull"
|
||||
onClick={() => update(null)}
|
||||
/>
|
||||
<button
|
||||
data-testid="updateVehicleNoVIN"
|
||||
onClick={() => update({})}
|
||||
/>
|
||||
<button
|
||||
data-testid="updateVehicle"
|
||||
onClick={() =>
|
||||
update({ vin: "3C4PDCBG0ET127145", log_level: "warn", canbus: { enabled: false } })
|
||||
update({
|
||||
vin: "3C4PDCBG0ET127145",
|
||||
log_level: "warning",
|
||||
canbus: { enabled: false },
|
||||
})
|
||||
}
|
||||
/>
|
||||
</>
|
||||
@@ -265,13 +320,17 @@ describe("VehicleContext", () => {
|
||||
<>
|
||||
<div data-testid="error">{message}</div>
|
||||
<div data-testid="busy">{busy.toString()}</div>
|
||||
<button data-testid="deleteVehicleNull" onClick={() => deleteV(null)} />
|
||||
<button data-testid="deleteVehicleNonexistent" onClick={() => deleteV("11111111111111111")} />
|
||||
<button
|
||||
data-testid="deleteVehicleNull"
|
||||
onClick={() => deleteV(null)}
|
||||
/>
|
||||
<button
|
||||
data-testid="deleteVehicleNonexistent"
|
||||
onClick={() => deleteV("11111111111111111")}
|
||||
/>
|
||||
<button
|
||||
data-testid="deleteVehicle"
|
||||
onClick={() =>
|
||||
deleteV("3C4PDCBG0ET127145")
|
||||
}
|
||||
onClick={() => deleteV("3C4PDCBG0ET127145")}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
@@ -321,7 +380,7 @@ describe("VehicleContext", () => {
|
||||
describe("sendCommand", () => {
|
||||
beforeEach(async () => {
|
||||
const TestComp = () => {
|
||||
const {busy, sendCommand} = useVehicleContext();
|
||||
const { busy, sendCommand } = useVehicleContext();
|
||||
const { message, setMessage } = useStatusContext();
|
||||
|
||||
const sendC = async (vin, command) => {
|
||||
@@ -336,25 +395,38 @@ describe("VehicleContext", () => {
|
||||
<>
|
||||
<div data-testid="error">{message}</div>
|
||||
<div data-testid="busy">{busy.toString()}</div>
|
||||
<button data-testid="sendCommandNullVin" onClick={() => sendC(null, {command:"doors_lock"})} />
|
||||
<button data-testid="sendCommandNonexistentVin" onClick={() => sendC(["11111111111111111"], {command:"doors_lock"})} />
|
||||
<button
|
||||
data-testid="sendCommandNullVin"
|
||||
onClick={() => sendC(null, { command: "doors_lock" })}
|
||||
/>
|
||||
<button
|
||||
data-testid="sendCommandNonexistentVin"
|
||||
onClick={() =>
|
||||
sendC(["11111111111111111"], { command: "doors_lock" })
|
||||
}
|
||||
/>
|
||||
<button
|
||||
data-testid="sendCommandVin"
|
||||
onClick={() => sendC("3C4PDCBG0ET127145", {command:"doors_lock"})}
|
||||
onClick={() =>
|
||||
sendC("3C4PDCBG0ET127145", { command: "doors_lock" })
|
||||
}
|
||||
/>
|
||||
<button
|
||||
data-testid="sendCommandWrongCommand"
|
||||
onClick={() => sendC("3C4PDCBG0ET127145", {command:"noSuchCommand"})}
|
||||
onClick={() =>
|
||||
sendC("3C4PDCBG0ET127145", { command: "noSuchCommand" })
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);}
|
||||
render(
|
||||
<StatusProvider>
|
||||
<VehicleProvider>
|
||||
<TestComp />
|
||||
</VehicleProvider>
|
||||
</StatusProvider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
render(
|
||||
<StatusProvider>
|
||||
<VehicleProvider>
|
||||
<TestComp />
|
||||
</VehicleProvider>
|
||||
</StatusProvider>
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -364,24 +436,23 @@ describe("VehicleContext", () => {
|
||||
it("initial state", () => {
|
||||
checkBaseResults("", "false");
|
||||
});
|
||||
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
const expectedFilters = [
|
||||
{
|
||||
can_id: "123-456",
|
||||
interval: 789
|
||||
interval: 789,
|
||||
},
|
||||
{
|
||||
can_id: "1",
|
||||
interval: 1000
|
||||
interval: 1000,
|
||||
},
|
||||
{
|
||||
can_id: "1000",
|
||||
interval: 1
|
||||
}
|
||||
]
|
||||
interval: 1,
|
||||
},
|
||||
];
|
||||
|
||||
const expectedVehicleData = {
|
||||
vin: "3C4PDCBG0ET127145",
|
||||
@@ -390,9 +461,16 @@ const expectedVehicleData = {
|
||||
trim: "Basic",
|
||||
ecu_list: "ECUA 2.0.0, ECUB 2.1.1",
|
||||
log_level: "info",
|
||||
canbus: { enabled: true, data_logger_enabled: true, max_mem_buffer_size: 1, max_disk_buffer_size: 2, filters: expectedFilters },
|
||||
canbus: {
|
||||
enabled: true,
|
||||
data_logger_enabled: true,
|
||||
max_mem_buffer_size: 1,
|
||||
max_disk_buffer_size: 2,
|
||||
filters: expectedFilters,
|
||||
},
|
||||
connected: true,
|
||||
}
|
||||
connectedHMI: false,
|
||||
};
|
||||
|
||||
const expectedVehiclesData = [
|
||||
{
|
||||
@@ -402,19 +480,44 @@ const expectedVehiclesData = [
|
||||
trim: "Basic",
|
||||
ecu_list: "ECUA 2.0.0, ECUB 2.1.1",
|
||||
log_level: "info",
|
||||
canbus: { enabled: true, data_logger_enabled: true, max_mem_buffer_size: 1, max_disk_buffer_size: 2, filters: expectedFilters },
|
||||
canbus: {
|
||||
enabled: true,
|
||||
data_logger_enabled: true,
|
||||
max_mem_buffer_size: 1,
|
||||
max_disk_buffer_size: 2,
|
||||
filters: expectedFilters,
|
||||
},
|
||||
connected: true,
|
||||
connectedHMI: false,
|
||||
},
|
||||
{ vin: "1G1FP87S3GN100062", connected: true, connectedHMI: false },
|
||||
{
|
||||
vin: "1HGCG325XYA062256",
|
||||
year: 2021,
|
||||
connected: true,
|
||||
connectedHMI: false,
|
||||
},
|
||||
{
|
||||
vin: "1J4GZ78YXWC160024",
|
||||
year: 2021,
|
||||
model: "Ocean",
|
||||
connected: true,
|
||||
connectedHMI: false,
|
||||
},
|
||||
{
|
||||
vin: "2C3CCAAG8CH222800",
|
||||
model: "Ocean",
|
||||
trim: "Basic",
|
||||
connected: true,
|
||||
connectedHMI: false,
|
||||
},
|
||||
{ vin: "1G1FP87S3GN100062", connected: true },
|
||||
{ vin: "1HGCG325XYA062256", year: 2021, connected: true },
|
||||
{ vin: "1J4GZ78YXWC160024", year: 2021, model: "Ocean", connected: true },
|
||||
{ vin: "2C3CCAAG8CH222800", model: "Ocean", trim: "Basic", connected: true },
|
||||
{
|
||||
vin: "KNADM4A39C6028108",
|
||||
year: 2021,
|
||||
model: "Ocean",
|
||||
trim: "Basic",
|
||||
connected: true,
|
||||
connectedHMI: false,
|
||||
},
|
||||
{
|
||||
vin: "1G11C5SL9FF153507",
|
||||
@@ -422,5 +525,6 @@ const expectedVehiclesData = [
|
||||
model: "Ocean",
|
||||
trim: "Basic",
|
||||
connected: true,
|
||||
connectedHMI: false,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -28,7 +28,7 @@ let fleets = [
|
||||
},
|
||||
{
|
||||
name: "US-CENTRAL",
|
||||
log_level: "warn",
|
||||
log_level: "warning",
|
||||
canbus: { enabled: false, data_logger_enabled: false, max_mem_buffer_size: 0, max_disk_buffer_size: 0 },
|
||||
vehicles: ["USCENTVIN12345678", "USCENTVIN12345679", "USCENTVIN12345670"]
|
||||
},
|
||||
|
||||
@@ -35,6 +35,7 @@ let vehicle = {
|
||||
let vehicleState = {
|
||||
data: {
|
||||
online: false,
|
||||
online_hmi: true,
|
||||
battery: {
|
||||
percent: 95,
|
||||
},
|
||||
@@ -77,6 +78,8 @@ let vehicles = [];
|
||||
let models = ["Ocean", "PEAR"];
|
||||
let years = [2023, 2024];
|
||||
let totalVehicles = 0;
|
||||
let fleets = ["fleet1", "fleet2"];
|
||||
let totalFleets = 2;
|
||||
let error = null;
|
||||
|
||||
export const VehicleProvider = ({ children }) => {
|
||||
@@ -86,6 +89,8 @@ export const VehicleProvider = ({ children }) => {
|
||||
export const useVehicleContext = () => ({
|
||||
busy,
|
||||
models,
|
||||
fleets,
|
||||
totalFleets,
|
||||
totalVehicles,
|
||||
vehicle,
|
||||
vehicles,
|
||||
@@ -141,6 +146,10 @@ export const useVehicleContext = () => ({
|
||||
command,
|
||||
parameters,
|
||||
})),
|
||||
getFleets: jest.fn((vin, search,_token) => {return {
|
||||
data: ["fleet1", "fleet2"],
|
||||
total: 2,
|
||||
}}),
|
||||
});
|
||||
|
||||
export const setBusy = (val) => {
|
||||
|
||||
Reference in New Issue
Block a user