Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZEVA-1737: Unit test for utils #2379

Merged
merged 1 commit into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import constructReassessmentReductions from "../constructReassessmentReductions";
import Big from "big.js";

describe("constructReassessmentReductions", () => {
it("should return empty reductions when both inputs are empty", () => {
const result = constructReassessmentReductions([], []);
expect(result).toEqual({ reductionsToUpdate: [], reductionsToAdd: [] });
});

it("should add new reductions when no previous reductions exist", () => {
const reductions = [
{
type: "Type1",
modelYear: 2023,
creditA: new Big(10),
creditB: new Big(20),
},
];

const result = constructReassessmentReductions(reductions, []);

expect(result).toEqual({
reductionsToUpdate: [],
reductionsToAdd: [
{ creditClass: "A", modelYear: 2023, value: 10 },
{ creditClass: "B", modelYear: 2023, value: 20 },
],
});
});

it("should be able to make changes in existing reductions", () => {
const reductions = [
{
type: "Type1",
modelYear: 2023,
creditA: new Big(15),
creditB: new Big(20),
},
];
const prevReductions = [
{
type: "Type1",
modelYear: 2023,
creditA: new Big(10),
creditB: new Big(20),
},
];

const result = constructReassessmentReductions(reductions, prevReductions);

expect(result).toEqual({
reductionsToUpdate: [
{
creditClass: "A",
modelYear: 2023,
oldValue: 10,
newValue: 15,
},
],
reductionsToAdd: [],
});
});

it("should add reductions for new types or years not in previous reductions", () => {
const reductions = [
{
type: "Type1",
modelYear: 2023,
creditA: new Big(10),
creditB: new Big(20),
},
{
type: "Type2",
modelYear: 2024,
creditA: new Big(5),
creditB: new Big(0),
},
];
const prevReductions = [
{
type: "Type1",
modelYear: 2023,
creditA: new Big(10),
creditB: new Big(20),
},
];

const result = constructReassessmentReductions(reductions, prevReductions);

expect(result).toEqual({
reductionsToUpdate: [],
reductionsToAdd: [{ creditClass: "A", modelYear: 2024, value: 5 }],
});
});

it("should return empty updates and additions when reductions match previous reductions", () => {
const reductions = [
{
type: "Type1",
modelYear: 2023,
creditA: new Big(10),
creditB: new Big(20),
},
];
const prevReductions = [
{
type: "Type1",
modelYear: 2023,
creditA: new Big(10),
creditB: new Big(20),
},
];

const result = constructReassessmentReductions(reductions, prevReductions);

expect(result).toEqual({ reductionsToUpdate: [], reductionsToAdd: [] });
});

it("should handle reductions with no corresponding previous reductions", () => {
const reductions = [
{
type: "Type1",
modelYear: 2023,
creditA: new Big(0),
creditB: new Big(30),
},
];

const prevReductions = [];

const result = constructReassessmentReductions(reductions, prevReductions);

expect(result).toEqual({
reductionsToUpdate: [],
reductionsToAdd: [{ creditClass: "B", modelYear: 2023, value: 30 }],
});
});
});
79 changes: 79 additions & 0 deletions frontend/src/app/utilities/__tests__/download.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import download from "../download";
import axios from "axios";

jest.mock("axios");

describe("download", () => {
const mockBlob = new Blob(["file content"], { type: "text/plain" });
const mockSetAttribute = jest.fn();
const mockClick = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
URL.createObjectURL = jest.fn();

document.createElement = jest.fn().mockImplementation((tagName) => {
if (tagName === "a") {
return {
setAttribute: mockSetAttribute,
click: mockClick,
href: "",
};
}
return {};
});
document.body.appendChild = jest.fn();
});

it("should download a file with the filename from content-disposition header", async () => {
const mockResponse = {
data: mockBlob,
headers: { "content-disposition": 'attachment; filename="testfile.txt"' },
};
axios.get.mockResolvedValue(mockResponse);

await download("https://example.com/file", {}, null);

expect(axios.get).toHaveBeenCalledWith("https://example.com/file", {
responseType: "blob",
});
expect(URL.createObjectURL).toHaveBeenCalledWith(mockBlob);
expect(mockSetAttribute).toHaveBeenCalledWith("download", "testfile.txt");
expect(mockClick).toHaveBeenCalledTimes(1);
});

it("should use the filename override if provided", async () => {
const mockResponse = {
data: mockBlob,
headers: {},
};
axios.get.mockResolvedValue(mockResponse);

await download("https://example.com/file", {}, "customname.txt");

expect(axios.get).toHaveBeenCalledWith("https://example.com/file", {
responseType: "blob",
});
expect(URL.createObjectURL).toHaveBeenCalledWith(mockBlob);
expect(mockSetAttribute).toHaveBeenCalledWith("download", "customname.txt");
expect(mockClick).toHaveBeenCalledTimes(1);
});

it("should include additional params in the request", async () => {
const mockResponse = {
data: mockBlob,
headers: { "content-disposition": 'attachment; filename="testfile.txt"' },
};

axios.get.mockResolvedValue(mockResponse);

const params = { headers: { Authorization: "Bearer token" } };
await download("https://example.com/file", params);

expect(axios.get).toHaveBeenCalledWith("https://example.com/file", {
responseType: "blob",
...params,
});
expect(URL.createObjectURL).toHaveBeenCalledWith(mockBlob);
});
});
55 changes: 55 additions & 0 deletions frontend/src/app/utilities/__tests__/formatAddress.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import formatAddress from "../formatAddress";

describe("formatAddress", () => {
it("should return an empty string when no address is provided", () => {
expect(formatAddress(null)).toBe("");
expect(formatAddress(undefined)).toBe("");
});

it("should return the representative name when only representativeName is provided", () => {
const address = { representativeName: "John Doe" };
expect(formatAddress(address)).toBe("John Doe");
});

it("should only return address line when it is the only thing provided", () => {
const address = { addressLine1: "123 Main St" };
expect(formatAddress(address)).toBe("123 Main St");
});

it("should only return address line 2 when it is the only thing provided", () => {
const address = { addressLine2: "1233 Fake St" };
expect(formatAddress(address)).toBe("1233 Fake St");
});

it("should only return city when it is the only thing provided", () => {
const address = { city: "Vancouver" };
expect(formatAddress(address)).toBe("Vancouver");
});

it("should return a formatted address with multiple elements", () => {
const address = {
representativeName: "John Doe",
addressLine1: "123 Main St",
addressLine2: "Apt 4B",
city: "Victoria",
state: "BC",
country: "Canada",
postalCode: "V8V 3V3",
};
const expected =
"John Doe, 123 Main St, Apt 4B, Victoria, BC, Canada, V8V 3V3";
expect(formatAddress(address)).toBe(expected);
});

it("can handle missing elements", () => {
const address = {
representativeName: "John Doe",
addressLine1: "123 Main St",
city: "Victoria",
country: "Canada",
postalCode: "V8V 3V3",
};
const expected = "John Doe, 123 Main St, Victoria, Canada, V8V 3V3";
expect(formatAddress(address)).toBe(expected);
});
});
101 changes: 101 additions & 0 deletions frontend/src/app/utilities/__tests__/upload.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { upload, chunkUpload, getFileUploadPromises } from "../upload";
import axios from "axios";

jest.mock("axios");

const mockFiles = [new File(["file content"], "testfile.txt")];
const mockMultipleFiles = [
new File(["file content"], "testfile.txt"),
new File(["file content"], "testfile2.txt"),
];
const mockResponse = {
data: { success: true },
};
const mockUrl = "https://example.com/upload";
const additionalData = { key1: "value1", key2: "value2" };

describe("upload", () => {
afterEach(() => {
jest.clearAllMocks();
});

it("should upload a file", async () => {
axios.post.mockResolvedValue(mockResponse);

const result = await upload(mockUrl, mockFiles);

expect(axios.post).toHaveBeenCalledWith(mockUrl, expect.any(FormData), {
headers: { "Content-Type": "multipart/form-data" },
});
expect(result).toEqual({
data: expect.objectContaining({ success: true }),
});
});

it("should upload multiple files", async () => {
axios.post.mockResolvedValue(mockResponse);
await upload(mockUrl, mockMultipleFiles);
expect(axios.post).toHaveBeenCalledWith(mockUrl, expect.any(FormData), {
headers: { "Content-Type": "multipart/form-data" },
});
const formData = axios.post.mock.calls[0][1];
expect(formData.getAll("files").length).toBe(2);
});

it("should add additional data to the request", async () => {
axios.post.mockResolvedValue({ data: "success" });

const response = await upload(mockUrl, mockFiles, additionalData);

expect(axios.post).toHaveBeenCalledWith(
mockUrl,
expect.any(FormData),
expect.objectContaining({
headers: { "Content-Type": "multipart/form-data" },
}),
);

const formData = axios.post.mock.calls[0][1];
expect(formData.getAll("files").length).toBe(1);
expect(formData.getAll("files")[0]).toEqual(mockFiles[0]);
expect(formData.get("key1")).toBe("value1");
expect(formData.get("key2")).toBe("value2");

expect(response).toEqual({ data: "success" });
});
});

describe("getFileUploadPromises", () => {
const mockPresignedUrlResponse = {
data: {
url: "http://example.com/upload",
minioObjectName: "mockObjectName",
},
};

beforeEach(() => {
jest.clearAllMocks();

jest.spyOn(global, "FileReader").mockImplementation(function () {
this.readAsArrayBuffer = jest.fn(() => {
this.onload({ target: { result: "mocked-file-content" } });
});
});

axios.get.mockResolvedValue(mockPresignedUrlResponse);
axios.put.mockResolvedValue({});
});

afterEach(() => {
jest.restoreAllMocks();
});

it("should return an array of promises", () => {
const promises = getFileUploadPromises(mockUrl, mockMultipleFiles);

expect(promises).toHaveLength(mockMultipleFiles.length);
promises.forEach((promise) => {
expect(promise).toBeInstanceOf(Promise);
});
});
});
Loading