Skip to content
87 changes: 50 additions & 37 deletions __tests__/pages/utilities/har-file-viewer.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render, screen, within } from "@testing-library/react";
import { act, render, screen, within } from "@testing-library/react";
import { userEvent } from "@testing-library/user-event";
import HARFileViewer from "../../../pages/utilities/har-file-viewer";

Expand Down Expand Up @@ -50,6 +50,38 @@ const mockHarData = {
};

describe("HARFileViewer", () => {
beforeEach(() => {
jest.useFakeTimers();
});

afterEach(() => {
act(() => {
jest.runOnlyPendingTimers();
});
jest.useRealTimers();
});

const uploadHarFile = async (user: ReturnType<typeof userEvent.setup>) => {
const file = new File([JSON.stringify(mockHarData)], "test.har", {
type: "application/json",
});
const fileInput = screen.getByTestId("input");
await user.upload(fileInput, file);
};

const flushDebounce = async () => {
await act(async () => {
jest.advanceTimersByTime(350);
});
};

const switchToTableView = async (
user: ReturnType<typeof userEvent.setup>
) => {
const tableTab = await screen.findByRole("tab", { name: /table view/i });
await user.click(tableTab);
};

test("should render the component and display the drop zone text", () => {
render(<HARFileViewer />);

Expand All @@ -59,35 +91,23 @@ describe("HARFileViewer", () => {
});

test("should list all requests after uploading a har file", async () => {
const user = userEvent.setup();
const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
render(<HARFileViewer />);

// 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);
await uploadHarFile(user);
await switchToTableView(user);

// 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();
const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
render(<HARFileViewer />);

// 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);
await uploadHarFile(user);
await switchToTableView(user);

// Get all rows
const rows = await screen.findAllByTestId("table-row");
Expand All @@ -102,17 +122,15 @@ describe("HARFileViewer", () => {
});

test("should accept and process .json file extension", async () => {
const user = userEvent.setup();
const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
render(<HARFileViewer />);

// Create a mock file with .json extension
const file = new File([JSON.stringify(mockHarData)], "test.json", {
type: "application/json",
});

// Find the file input and upload the file
const fileInput = screen.getByTestId("input");
await user.upload(fileInput, file);
await switchToTableView(user);

// Wait for the requests to be displayed - this verifies the file was accepted
await screen.findByText("https://example.com/api/test");
Expand All @@ -125,15 +143,12 @@ describe("HARFileViewer", () => {
});

test("should filter requests based on search query", async () => {
const user = userEvent.setup();
const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
render(<HARFileViewer />);

// Upload a HAR file
const file = new File([JSON.stringify(mockHarData)], "test.har", {
type: "application/json",
});
const fileInput = screen.getByTestId("input");
await user.upload(fileInput, file);
await uploadHarFile(user);
await switchToTableView(user);

// Wait for all requests to be displayed
await screen.findByText("https://example.com/api/test");
Expand All @@ -148,7 +163,7 @@ describe("HARFileViewer", () => {
await user.type(searchInput, "api");

// Wait for debounce (300ms) + rendering time
await new Promise((resolve) => setTimeout(resolve, 500));
await flushDebounce();

// Should still see the api request
const rows = screen.queryAllByTestId("table-row");
Expand All @@ -157,15 +172,12 @@ describe("HARFileViewer", () => {
});

test("should clear search query when clear button is clicked", async () => {
const user = userEvent.setup();
const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
render(<HARFileViewer />);

// Upload a HAR file
const file = new File([JSON.stringify(mockHarData)], "test.har", {
type: "application/json",
});
const fileInput = screen.getByTestId("input");
await user.upload(fileInput, file);
await uploadHarFile(user);
await switchToTableView(user);

// Wait for requests to be displayed
await screen.findByText("https://example.com/api/test");
Expand All @@ -177,11 +189,12 @@ describe("HARFileViewer", () => {
await user.type(searchInput, "api");

// Wait for debounce
await new Promise((resolve) => setTimeout(resolve, 400));
await flushDebounce();

// Find the clear button (it should appear when there's text)
const clearButton = screen.getByTitle("Clear search");
await user.click(clearButton);
await flushDebounce();

// Search input should be empty
expect(searchInput).toHaveValue("");
Expand Down
Loading