Add package updates, car updates, and vehicle screens (#25)

This commit is contained in:
John Wu
2021-03-31 17:42:31 -07:00
committed by GitHub
parent 2d1faa8fb7
commit 17f81822c0
33 changed files with 2409 additions and 699 deletions

View File

@@ -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,

View File

@@ -33,7 +33,6 @@ describe("FileUploadContext", () => {
linkURL,
upload,
cancel,
setFiles,
} = useFileUploadContext();
const { message, setMessage } = useStatusContext();
const TEST_FILE = [{ name: "test.jpg", size: 0 }];

View 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],
});
});
});
});

View 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");
}
};

View File

@@ -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);

View File

@@ -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,
}}

View File

@@ -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 })
}
/>
</>
);