diff --git a/__tests__/pages/utilities/har-file-viewer.test.tsx b/__tests__/pages/utilities/har-file-viewer.test.tsx new file mode 100644 index 0000000..86f4456 --- /dev/null +++ b/__tests__/pages/utilities/har-file-viewer.test.tsx @@ -0,0 +1,101 @@ +import { render, screen, within } from "@testing-library/react"; +import { userEvent } from "@testing-library/user-event"; +import HARFileViewer from "../../../pages/utilities/har-file-viewer"; + +// Mock HAR file data +const mockHarData = { + log: { + entries: [ + { + request: { + url: "https://example.com/api/test", + method: "GET", + headers: [ + { name: "User-Agent", value: "Mozilla/50" }, + { name: "Accept", value: "application/json" }, + ], + }, + response: { + status: 200, + content: { + size: 124, + mimeType: "application/json", + text: '{"message": "success"}', + }, + headers: [{ name: "Content-Type", value: "application/json" }], + }, + time: 150, + startedDateTime: "2023-01-01T00:00:00", + }, + { + request: { + url: "https://example.com/css/style.css", + method: "GET", + headers: [{ name: "User-Agent", value: "Mozilla/50" }], + }, + response: { + status: 404, + content: { + size: 248, + mimeType: "text/css", + text: "body { color: red; }", + }, + headers: [{ name: "Content-Type", value: "text/css" }], + }, + time: 75, + startedDateTime: "2023-01-01T00:00:01.000Z", + }, + ], + }, +}; + +describe("HARFileViewer", () => { + test("should render the component and display the drop zone text", () => { + render(); + + expect(screen.getByText("Drop your .har file here")).toBeInTheDocument(); + }); + + test("should list all requests after uploading a har file", async () => { + const user = userEvent.setup(); + render(); + + // Create a mock file + const file = new File([JSON.stringify(mockHarData)], "test.har", { + type: "application/json", + }); + + // Find the file input and upload the file + const fileInput = screen.getByTestId("input"); + await user.upload(fileInput, file); + + // Wait for the requests to be displayed + await screen.findByText("https://example.com/api/test"); + await screen.findByText("https://example.com/css/style.css"); + }); + + test("should list the status code for every request", async () => { + const user = userEvent.setup(); + render(); + + // Create a mock file + const file = new File([JSON.stringify(mockHarData)], "test.har", { + type: "application/json", + }); + + // Find the file input and upload the file + const fileInput = screen.getByTestId("input"); + await user.upload(fileInput, file); + + // Get all rows + const rows = await screen.findAllByTestId("table-row"); + + // For the 1st row, get status code column and verify if its 200 + const row1 = within(rows[0]).getByTestId("column-status-code"); + expect(row1).toHaveTextContent("200"); + + // For the 2nd row, get status code column and verify if its 404 + const row2 = within(rows[1]).getByTestId("column-status-code"); + expect(row2).toHaveTextContent("404"); + }); +}); diff --git a/jest.setup.ts b/jest.setup.ts index d0de870..148b93a 100644 --- a/jest.setup.ts +++ b/jest.setup.ts @@ -1 +1,13 @@ import "@testing-library/jest-dom"; + +// There's no official way to mock next/navigation. +// We just make it no-op for all tests. +jest.mock("next/navigation", () => ({ + useRouter: () => ({ + push: jest.fn(), + replace: jest.fn(), + back: jest.fn(), + forward: jest.fn(), + refresh: jest.fn(), + }), +})); diff --git a/package-lock.json b/package-lock.json index 41b631d..79df55e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "devDependencies": { "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", + "@testing-library/user-event": "^14.6.1", "@types/jest": "^29.5.12", "@types/js-yaml": "^4.0.9", "@types/node": "^20", @@ -2890,6 +2891,19 @@ } } }, + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", diff --git a/package.json b/package.json index a7759ea..c9d8345 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "devDependencies": { "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", + "@testing-library/user-event": "^14.6.1", "@types/jest": "^29.5.12", "@types/js-yaml": "^4.0.9", "@types/node": "^20", diff --git a/pages/utilities/har-file-viewer.tsx b/pages/utilities/har-file-viewer.tsx index 1d99bb0..ee8f2a4 100644 --- a/pages/utilities/har-file-viewer.tsx +++ b/pages/utilities/har-file-viewer.tsx @@ -105,6 +105,7 @@ export default function HARFileViewer() { > handleFileUpload(event.target.files?.[0])} className="absolute inset-0 w-full h-full opacity-0 cursor-pointer" @@ -287,6 +288,7 @@ const HarTable = ({ entries, activeFilter }: HarTableComponentProps) => { {filteredAndSortedEntries.map((entry, index) => ( { > {entry.request.url} - + {entry.response.status}