CEC-2920 Aftersales certificates (#225)

* CEC-2920 aftersales certificates

* smells

* smells
This commit is contained in:
John Wu
2022-10-25 11:00:50 -07:00
committed by GitHub
parent 58890ea40e
commit aaf47f4cc7
7 changed files with 231 additions and 31 deletions

View File

@@ -4532,6 +4532,57 @@ exports[`App Route /tools/certificates/add authenticated 1`] = `
ICC
</span>
</label>
<label
class="MuiFormControlLabel-root"
>
<span
aria-disabled="false"
class="MuiButtonBase-root MuiIconButton-root PrivateSwitchBase-root-0 MuiRadio-root MuiRadio-colorSecondary MuiIconButton-colorSecondary"
>
<span
class="MuiIconButton-label"
>
<input
class="PrivateSwitchBase-input-0"
name="cert-type"
type="radio"
value="Aftersales"
/>
<div
class="PrivateRadioButtonIcon-root-0"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
/>
</svg>
<svg
aria-hidden="true"
class="MuiSvgIcon-root PrivateRadioButtonIcon-layer-0"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M8.465 8.465C9.37 7.56 10.62 7 12 7C14.76 7 17 9.24 17 12C17 13.38 16.44 14.63 15.535 15.535C14.63 16.44 13.38 17 12 17C9.24 17 7 14.76 7 12C7 10.62 7.56 9.37 8.465 8.465Z"
/>
</svg>
</div>
</span>
<span
class="MuiTouchRipple-root"
/>
</span>
<span
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
>
Aftersales
</span>
</label>
<label
class="MuiFormControlLabel-root"
>

View File

@@ -1,4 +1,3 @@
import React, { useRef, useState } from "react";
import {
Button,
FormControlLabel,
@@ -7,13 +6,15 @@ import {
RadioGroup,
TextField,
} from "@material-ui/core";
import React, { useRef, useState } from "react";
import { CertTypeData, CertTypes } from "../../../utils/certificates";
import useStyles from "../../useStyles";
import { CertTypes } from "../../Contexts/CertificateContext";
const getCertTypeLabel = (certtype) => {
if (certtype === CertTypes.Aftersales) return "Service Tool ID";
return "VIN";
const item = CertTypeData.find((item) => certtype === item.value);
if (item !== null) return item.inputlabel;
return "ID";
};
const CreateForm = ({ onCreate, busy }) => {
@@ -60,21 +61,16 @@ const CreateForm = ({ onCreate, busy }) => {
onChange={onCertTypeChange}
margin="normal"
>
<FormControlLabel
value={CertTypes.TBOX}
control={<Radio />}
label="TBOX"
/>
<FormControlLabel
value={CertTypes.ICC}
control={<Radio />}
label="ICC"
/>
<FormControlLabel
value={CertTypes.Charging}
control={<Radio />}
label="Charging"
/>
{CertTypeData.map((item, i) => {
return (
<FormControlLabel
key={i}
value={item.value}
label={item.label}
control={<Radio />}
/>
);
})}
</RadioGroup>
<Button
type="submit"

View File

@@ -1,12 +1,12 @@
import React, { useEffect, useState } from "react";
import { logger } from "../../../services/monitoring";
import {
useCertificateContext,
CertificateProvider,
useCertificateContext,
} from "../../Contexts/CertificateContext";
import { useStatusContext } from "../../Contexts/StatusContext";
import { useUserContext } from "../../Contexts/UserContext";
import { logger } from "../../../services/monitoring";
import CreateForm from "./CreateForm";
import DownloadCerts from "./DownloadCerts";
@@ -43,11 +43,12 @@ const MainForm = () => {
const onCreate = async (data) => {
try {
const result = await createCert(data, token);
const name = data.common_name || data.tool_id;
setCommonName(name);
setPubCert(result.public_key);
setPrivCert(result.private_key);
setCommonName(data.common_name);
setMessage(`Created ${data.common_name} certificate`);
setMessage(`Created ${name} certificate`);
setView(VIEW_DOWNLOAD);
} catch (e) {
setMessage(e.message);

View File

@@ -1,21 +1,25 @@
import React, { useContext, useState } from "react";
import api from "../../services/certificatesAPI";
import { CertTypes } from "../../utils/certificates";
const CertificateContext = React.createContext();
export const CertTypes = {
TBOX: "TBOX",
ICC: "ICC",
Charging: "Charging",
Aftersales: "Aftersales",
};
const validateCreate = (data) => {
if (!data.type) throw new Error("type is required");
if (!data.common_name) throw new Error("common name is required");
};
const callCreateCert = (data, token) => {
if (data.type === CertTypes.Aftersales) {
data.tool_id = data.common_name;
delete data.common_name;
return api.createAftersales(data, token);
}
return api.create(data, token);
};
export const CertificateProvider = ({ children }) => {
const [busy, setBusy] = useState(false);
@@ -25,7 +29,8 @@ export const CertificateProvider = ({ children }) => {
validateCreate(data);
const result = await api.create(data, token);
const result = await callCreateCert(data, token);
if (result.error) {
throw new Error(`Create certificate error. ${result.message}`);
}

View File

@@ -0,0 +1,105 @@
jest.mock("../../services/certificatesAPI");
import {
act,
cleanup,
fireEvent,
render,
screen,
waitFor,
} from "@testing-library/react";
import { useState } from "react";
import {
CertificateProvider,
useCertificateContext,
} from "./CertificateContext";
describe("CertificateContext", () => {
beforeEach(() => {
const TestComp = () => {
const { createCert } = useCertificateContext();
const [result, setResult] = useState(null);
const testCreate = async (data) => {
const x = await createCert(data);
setResult(JSON.stringify(x));
};
return (
<>
<div data-testid="output">{result}</div>
<button
data-testid="createCertTBOX"
onClick={async () => {
await testCreate({
common_name: "11111111111111111",
type: "TBOX",
});
}}
/>
<button
data-testid="createCertICC"
onClick={async () => {
await testCreate({
common_name: "11111111111111111",
type: "ICC",
});
}}
/>
<button
data-testid="createCertAftersales"
onClick={async () => {
await testCreate({
common_name: "11111111111111112",
type: "Aftersales",
});
}}
/>
</>
);
};
render(
<CertificateProvider>
<TestComp />
</CertificateProvider>
);
});
afterEach(() => {
cleanup();
});
it("TBOX certificate", async () => {
await act(async () => {
fireEvent.click(screen.getByTestId("createCertTBOX"));
await waitFor(() =>
expect(screen.getByTestId("output").innerHTML).toBe(
'{"private_key":"-----BEGIN RSA PRIVATE KEY-----DATA-----END RSA PRIVATE KEY-----","public_key":"-----BEGIN CERTIFICATE-----DATA-----END CERTIFICATE-----","serial_number":"00:76:d2:ca:86:35:8c:88:52:fd:94:8e:55:d3:b6:a8:2e:73:68:00","type":"TBOX"}'
)
);
});
});
it("ICC certificate", async () => {
await act(async () => {
fireEvent.click(screen.getByTestId("createCertICC"));
await waitFor(() =>
expect(screen.getByTestId("output").innerHTML).toBe(
'{"private_key":"-----BEGIN RSA PRIVATE KEY-----DATA-----END RSA PRIVATE KEY-----","public_key":"-----BEGIN CERTIFICATE-----DATA-----END CERTIFICATE-----","serial_number":"00:76:d2:ca:86:35:8c:88:52:fd:94:8e:55:d3:b6:a8:2e:73:68:00","type":"ICC"}'
)
);
});
});
it("Aftersales certificate", async () => {
await act(async () => {
fireEvent.click(screen.getByTestId("createCertAftersales"));
await waitFor(() =>
expect(screen.getByTestId("output").innerHTML).toBe(
'{"private_key":"-----BEGIN RSA PRIVATE KEY-----DATA-----END RSA PRIVATE KEY-----","public_key":"-----BEGIN CERTIFICATE-----DATA-----END CERTIFICATE-----","serial_number":"00:76:d2:ca:86:35:8c:88:52:fd:94:8e:55:d3:b6:a8:2e:73:68:00","type":"Aftersales"}'
)
);
});
});
});