Add package updates, car updates, and vehicle screens (#25)
This commit is contained in:
@@ -38,10 +38,6 @@ export const FileUploadProvider = ({ children }) => {
|
||||
throw new Error("Package update version required");
|
||||
}
|
||||
|
||||
if (!formData.vehicles || formData.vehicles.length === 0) {
|
||||
throw new Error("Vehicles required");
|
||||
}
|
||||
|
||||
if (!uploadFiles || uploadFiles.length === 0) {
|
||||
throw new Error("File required");
|
||||
}
|
||||
@@ -64,7 +60,7 @@ export const FileUploadProvider = ({ children }) => {
|
||||
setStatus(`Uploading ${filename}`);
|
||||
setCancelUpload(getCancelToken());
|
||||
|
||||
const { data } = await uploadFile(
|
||||
const data = await uploadFile(
|
||||
file,
|
||||
formData,
|
||||
accessToken,
|
||||
|
||||
@@ -33,7 +33,6 @@ describe("FileUploadContext", () => {
|
||||
linkURL,
|
||||
upload,
|
||||
cancel,
|
||||
setFiles,
|
||||
} = useFileUploadContext();
|
||||
const { message, setMessage } = useStatusContext();
|
||||
const TEST_FILE = [{ name: "test.jpg", size: 0 }];
|
||||
|
||||
291
src/components/Contexts/UpdateContext.test.jsx
Normal file
291
src/components/Contexts/UpdateContext.test.jsx
Normal file
@@ -0,0 +1,291 @@
|
||||
jest.mock("../../services/updates");
|
||||
|
||||
import {
|
||||
render,
|
||||
cleanup,
|
||||
screen,
|
||||
fireEvent,
|
||||
waitFor,
|
||||
} from "@testing-library/react";
|
||||
import { UpdatesProvider, useUpdatesContext } from "../Contexts/UpdatesContext";
|
||||
import { StatusProvider, useStatusContext } from "../Contexts/StatusContext";
|
||||
import { TEST_AUTH_OBJECT } from "../../utils/testing";
|
||||
|
||||
describe("UpdatesContext", () => {
|
||||
describe("getPackages", () => {
|
||||
const expectedData = `[{"id":1,"package_name":"Test","version":"1.0","link":"http://cloudfront.com/download"},{"id":2,"package_name":"Test","version":"1.1","link":"http://cloudfront.com/download"},{"id":3,"package_name":"Test","version":"1.2","link":"http://cloudfront.com/download"}]`;
|
||||
const checkState = (busy, packages, message) => {
|
||||
expect(screen.getByTestId("busy").innerHTML).toEqual(busy);
|
||||
expect(screen.getByTestId("packages").innerHTML).toEqual(packages);
|
||||
expect(screen.getByTestId("message").innerHTML).toEqual(message);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
const TestComp = () => {
|
||||
const { busy, packages, getPackages } = useUpdatesContext();
|
||||
const { message, setMessage } = useStatusContext();
|
||||
const exec = async (data, token) => {
|
||||
try {
|
||||
await getPackages(data, token);
|
||||
} catch (e) {
|
||||
setMessage(e.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div data-testid="busy">{busy.toString()}</div>
|
||||
<div data-testid="packages">{JSON.stringify(packages)}</div>
|
||||
<div data-testid="message">{message}</div>
|
||||
<button
|
||||
data-testid="no-filter"
|
||||
onClick={() => {
|
||||
exec(null, TEST_AUTH_OBJECT);
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
data-testid="with-filter"
|
||||
onClick={() => {
|
||||
exec({ package_name: "Test" }, TEST_AUTH_OBJECT);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
render(
|
||||
<StatusProvider>
|
||||
<UpdatesProvider>
|
||||
<TestComp />
|
||||
</UpdatesProvider>
|
||||
</StatusProvider>
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
it("Initial state", async () => {
|
||||
checkState("false", "[]", "");
|
||||
});
|
||||
|
||||
it("getPackages no filter", async () => {
|
||||
fireEvent.click(screen.getByTestId("no-filter"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("busy").innerHTML).toBe("false")
|
||||
);
|
||||
checkState("false", expectedData, "");
|
||||
});
|
||||
|
||||
it("getPackages with filter", async () => {
|
||||
fireEvent.click(screen.getByTestId("with-filter"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("busy").innerHTML).toBe("false")
|
||||
);
|
||||
checkState("false", expectedData, "");
|
||||
});
|
||||
});
|
||||
|
||||
describe("updatePackage", () => {
|
||||
let result = null;
|
||||
const checkState = (busy, message, data) => {
|
||||
expect(screen.getByTestId("busy").innerHTML).toEqual(busy);
|
||||
expect(screen.getByTestId("message").innerHTML).toEqual(message);
|
||||
expect(result).toEqual(data);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
const TestComp = () => {
|
||||
const { busy, updatePackage } = useUpdatesContext();
|
||||
const { message, setMessage } = useStatusContext();
|
||||
const exec = async (data, token) => {
|
||||
var r = null;
|
||||
|
||||
try {
|
||||
r = await updatePackage(data, token);
|
||||
} catch (e) {
|
||||
setMessage(e.message);
|
||||
}
|
||||
|
||||
return r;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div data-testid="busy">{busy.toString()}</div>
|
||||
<div data-testid="message">{message}</div>
|
||||
<button
|
||||
data-testid="no-data"
|
||||
onClick={async () => {
|
||||
result = await exec(null, TEST_AUTH_OBJECT);
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
data-testid="with-bad-data"
|
||||
onClick={async () => {
|
||||
result = await exec({ package_name: "Test" }, TEST_AUTH_OBJECT);
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
data-testid="with-good-data"
|
||||
onClick={async () => {
|
||||
result = await exec(
|
||||
{
|
||||
package_name: "Test",
|
||||
version: "1.0",
|
||||
},
|
||||
TEST_AUTH_OBJECT
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
render(
|
||||
<StatusProvider>
|
||||
<UpdatesProvider>
|
||||
<TestComp />
|
||||
</UpdatesProvider>
|
||||
</StatusProvider>
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
result = null;
|
||||
});
|
||||
|
||||
it("Initial state", () => {
|
||||
checkState("false", "", null);
|
||||
});
|
||||
|
||||
it("no-data", async () => {
|
||||
fireEvent.click(screen.getByTestId("no-data"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("busy").innerHTML).toBe("false")
|
||||
);
|
||||
checkState("false", "No update data", null);
|
||||
});
|
||||
|
||||
it("with-bad-data", async () => {
|
||||
fireEvent.click(screen.getByTestId("with-bad-data"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("busy").innerHTML).toBe("false")
|
||||
);
|
||||
checkState("false", "Version required", null);
|
||||
});
|
||||
|
||||
it("with-good-data", async () => {
|
||||
fireEvent.click(screen.getByTestId("with-good-data"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("busy").innerHTML).toBe("false")
|
||||
);
|
||||
checkState("false", "", { package_name: "Test", version: "1.0" });
|
||||
});
|
||||
});
|
||||
|
||||
describe("createCarUpdates", () => {
|
||||
let result = null;
|
||||
const checkState = (busy, message, data) => {
|
||||
expect(screen.getByTestId("busy").innerHTML).toEqual(busy);
|
||||
expect(screen.getByTestId("message").innerHTML).toEqual(message);
|
||||
expect(result).toEqual(data);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
const TestComp = () => {
|
||||
const { busy, createCarUpdates } = useUpdatesContext();
|
||||
const { message, setMessage } = useStatusContext();
|
||||
const exec = async (data, token) => {
|
||||
var r = null;
|
||||
|
||||
try {
|
||||
r = await createCarUpdates(data, token);
|
||||
} catch (e) {
|
||||
setMessage(e.message);
|
||||
}
|
||||
|
||||
return r;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div data-testid="busy">{busy.toString()}</div>
|
||||
<div data-testid="message">{message}</div>
|
||||
<button
|
||||
data-testid="no-data"
|
||||
onClick={async () => {
|
||||
result = await exec(null, TEST_AUTH_OBJECT);
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
data-testid="with-bad-data"
|
||||
onClick={async () => {
|
||||
result = await exec(
|
||||
{ package_id: 1, car_ids: [] },
|
||||
TEST_AUTH_OBJECT
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
data-testid="with-good-data"
|
||||
onClick={async () => {
|
||||
result = await exec(
|
||||
{
|
||||
package_id: 1,
|
||||
car_ids: [1, 2, 3],
|
||||
},
|
||||
TEST_AUTH_OBJECT
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
render(
|
||||
<StatusProvider>
|
||||
<UpdatesProvider>
|
||||
<TestComp />
|
||||
</UpdatesProvider>
|
||||
</StatusProvider>
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
result = null;
|
||||
});
|
||||
|
||||
it("Initial state", () => {
|
||||
checkState("false", "", null);
|
||||
});
|
||||
|
||||
it("no-data", async () => {
|
||||
fireEvent.click(screen.getByTestId("no-data"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("busy").innerHTML).toBe("false")
|
||||
);
|
||||
checkState("false", "No car update data", null);
|
||||
});
|
||||
|
||||
it("with-bad-data", async () => {
|
||||
fireEvent.click(screen.getByTestId("with-bad-data"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("busy").innerHTML).toBe("false")
|
||||
);
|
||||
checkState("false", "Car ids required", null);
|
||||
});
|
||||
|
||||
it("with-good-data", async () => {
|
||||
fireEvent.click(screen.getByTestId("with-good-data"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("busy").innerHTML).toBe("false")
|
||||
);
|
||||
checkState("false", "", {
|
||||
id: 1,
|
||||
package_id: 1,
|
||||
car_ids: [1, 2, 3],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
131
src/components/Contexts/UpdatesContext.jsx
Normal file
131
src/components/Contexts/UpdatesContext.jsx
Normal file
@@ -0,0 +1,131 @@
|
||||
import React, { useContext, useState } from "react";
|
||||
|
||||
import api from "../../services/updates";
|
||||
|
||||
const UpdatesContext = React.createContext();
|
||||
|
||||
export const UpdatesProvider = ({ children }) => {
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [packages, setPackages] = useState([]);
|
||||
const [carUpdates, setCarUpdates] = useState([]);
|
||||
const [totalPackages, setTotalPackages] = useState(0);
|
||||
const [totalCarUpdates, setTotalCarUpdates] = useState(0);
|
||||
|
||||
const getPackages = async (search, token) => {
|
||||
let result;
|
||||
|
||||
try {
|
||||
setBusy(true);
|
||||
result = await api.getPackages(search, token);
|
||||
if (result.error)
|
||||
throw new Error(`Get packages error. ${result.message}`);
|
||||
setPackages(result.data);
|
||||
if (search && search.offset === 0 && result.total) {
|
||||
setTotalPackages(result.total);
|
||||
}
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const updatePackage = async (data, token) => {
|
||||
let result = null;
|
||||
|
||||
try {
|
||||
setBusy(true);
|
||||
validateUpdatePackage(data);
|
||||
result = await api.updatePackage(data, token);
|
||||
if (result.error)
|
||||
throw new Error(`Update package error. ${result.message}`);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const createCarUpdates = async (data, token) => {
|
||||
let result;
|
||||
|
||||
try {
|
||||
setBusy(true);
|
||||
validateCreateCarUpdates(data);
|
||||
result = await api.createCarUpdates(data, token);
|
||||
if (result.error)
|
||||
throw new Error(`Create car updates error. ${result.message}`);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const getCarUpdates = async (search, token) => {
|
||||
let result;
|
||||
|
||||
try {
|
||||
setBusy(true);
|
||||
result = await api.getCarUpdates(search, token);
|
||||
if (result.error)
|
||||
throw new Error(`Get packages error. ${result.message}`);
|
||||
setCarUpdates(result.data);
|
||||
if (search && search.offset === 0 && result.total) {
|
||||
setTotalCarUpdates(result.total);
|
||||
}
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
return (
|
||||
<UpdatesContext.Provider
|
||||
value={{
|
||||
busy,
|
||||
packages,
|
||||
totalPackages,
|
||||
carUpdates,
|
||||
totalCarUpdates,
|
||||
getPackages,
|
||||
updatePackage,
|
||||
createCarUpdates,
|
||||
getCarUpdates,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</UpdatesContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useUpdatesContext = () => useContext(UpdatesContext);
|
||||
|
||||
const validateUpdatePackage = (data) => {
|
||||
if (data === null) {
|
||||
throw new Error("No update data");
|
||||
}
|
||||
|
||||
if (!data.package_name) {
|
||||
throw new Error("Package name required");
|
||||
}
|
||||
|
||||
if (!data.version) {
|
||||
throw new Error("Version required");
|
||||
}
|
||||
};
|
||||
|
||||
const validateCreateCarUpdates = (data) => {
|
||||
if (data === null) {
|
||||
throw new Error("No car update data");
|
||||
}
|
||||
|
||||
if (!data.package_id || data.package_id === 0) {
|
||||
throw new Error("Package id required");
|
||||
}
|
||||
|
||||
if (!data.car_ids || data.car_ids.length === 0) {
|
||||
throw new Error("Car ids required");
|
||||
}
|
||||
};
|
||||
@@ -79,8 +79,6 @@ export const UserProvider = ({ children }) => {
|
||||
setError(`Verify error. ${e.message}`);
|
||||
document.location = signOut();
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const signIn = async (code) => {
|
||||
@@ -89,13 +87,6 @@ export const UserProvider = ({ children }) => {
|
||||
try {
|
||||
if (!code) return;
|
||||
|
||||
const refresh = async (value) => {
|
||||
let result = null;
|
||||
|
||||
try {
|
||||
if (!value) {
|
||||
throw new Error("Token required");
|
||||
}
|
||||
setFetching(true);
|
||||
setError(null);
|
||||
|
||||
|
||||
@@ -15,11 +15,20 @@ const validateAdd = (vehicle) => {
|
||||
if (vehicle.vin.length > 17) {
|
||||
throw new Error("VIN cannot be larger than 17 characters");
|
||||
}
|
||||
|
||||
if (!vehicle.model || vehicle.model.length === 0) {
|
||||
throw new Error("model required");
|
||||
}
|
||||
|
||||
if (!vehicle.year || vehicle.year < 2000 || vehicle.year > 9999) {
|
||||
throw new Error("year required");
|
||||
}
|
||||
};
|
||||
|
||||
export const VehicleProvider = ({ children }) => {
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [vehicles, setVehicles] = useState([]);
|
||||
const [totalVehicles, setTotalVehicles] = useState(0);
|
||||
|
||||
const getVehicles = async (search, token) => {
|
||||
try {
|
||||
@@ -30,6 +39,9 @@ export const VehicleProvider = ({ children }) => {
|
||||
throw new Error(`Get vehicles error. ${result.message}`);
|
||||
} else {
|
||||
setVehicles(result.data);
|
||||
if (result.total) {
|
||||
setTotalVehicles(result.total);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
setBusy(false);
|
||||
@@ -53,6 +65,7 @@ export const VehicleProvider = ({ children }) => {
|
||||
value={{
|
||||
busy,
|
||||
vehicles,
|
||||
totalVehicles,
|
||||
getVehicles,
|
||||
addVehicle,
|
||||
}}
|
||||
|
||||
@@ -83,7 +83,9 @@ describe("VehicleContext", () => {
|
||||
<button data-testid="addVehiclesNoVIN" onClick={() => add({})} />
|
||||
<button
|
||||
data-testid="addVehicles"
|
||||
onClick={() => add({ vin: "XXXXXXXXXXX" })}
|
||||
onClick={() =>
|
||||
add({ vin: "XXXXXXXXXXX", model: "Ocean", year: 3000 })
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user