generated from bcgov/quickstart-openshift
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(SILVA-539): adding test to autocomplete
- Loading branch information
1 parent
499d120
commit 4ae3f22
Showing
2 changed files
with
202 additions
and
6 deletions.
There are no files selected for viewing
200 changes: 200 additions & 0 deletions
200
frontend/src/__test__/contexts/AutocompleteProvider.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
import React from "react"; | ||
import { render, screen, waitFor, act } from "@testing-library/react"; | ||
import userEvent from "@testing-library/user-event"; | ||
import { describe, it, vi, expect, beforeEach, afterEach } from "vitest"; | ||
import { AutocompleteProvider, useAutocomplete } from "../../contexts/AutocompleteProvider"; | ||
|
||
// Mock lodash debounce to run instantly in tests | ||
vi.mock("lodash", () => ({ | ||
debounce: (fn: any) => { | ||
fn.cancel = vi.fn(); | ||
return fn; | ||
}, | ||
})); | ||
|
||
// Mock component to consume the context | ||
const MockAutocompleteConsumer = () => { | ||
const { options, loading, error, fetchOptions } = useAutocomplete(); | ||
return ( | ||
<div> | ||
<button onClick={() => fetchOptions("test-query", "key1")}>Fetch Options</button> | ||
{loading && <div data-testid="loading">Loading...</div>} | ||
{error && <div data-testid="error">{error}</div>} | ||
<div data-testid="options">{JSON.stringify(options)}</div> | ||
</div> | ||
); | ||
}; | ||
|
||
describe("AutocompleteProvider", () => { | ||
let fetchOptionsMock: vi.Mock; | ||
|
||
beforeEach(() => { | ||
fetchOptionsMock = vi.fn((query: string, key: string) => []); | ||
}); | ||
|
||
afterEach(() => { | ||
vi.useRealTimers(); | ||
vi.restoreAllMocks(); | ||
}); | ||
|
||
it("renders children correctly", () => { | ||
render( | ||
<AutocompleteProvider fetchOptions={fetchOptionsMock}> | ||
<div>Child Component</div> | ||
</AutocompleteProvider> | ||
); | ||
expect(screen.getByText("Child Component")).toBeInTheDocument(); | ||
}); | ||
|
||
it("calls fetchOptions and updates state correctly", async () => { | ||
fetchOptionsMock.mockResolvedValueOnce(["option1", "option2"]); | ||
|
||
await act(async () =>render( | ||
<AutocompleteProvider fetchOptions={fetchOptionsMock}> | ||
<MockAutocompleteConsumer /> | ||
</AutocompleteProvider> | ||
)); | ||
|
||
await act(async () => userEvent.click(screen.getByText("Fetch Options"))); | ||
|
||
expect(fetchOptionsMock).toHaveBeenCalledWith("test-query", "key1"); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByTestId("options")).toHaveTextContent( | ||
JSON.stringify({ key1: ["option1", "option2"] }) | ||
); | ||
}); | ||
}); | ||
|
||
it("handles skip conditions", async () => { | ||
const skipConditions = { key1: (query: string) => query === "skip" }; | ||
fetchOptionsMock.mockResolvedValueOnce(["option1", "option2"]); | ||
|
||
await act(async () =>render( | ||
<AutocompleteProvider fetchOptions={fetchOptionsMock} skipConditions={skipConditions}> | ||
<MockAutocompleteConsumer /> | ||
</AutocompleteProvider> | ||
)); | ||
|
||
await act(async () =>userEvent.click(screen.getByText("Fetch Options"))); | ||
|
||
// Should fetch for "test-query" | ||
expect(fetchOptionsMock).toHaveBeenCalledWith("test-query", "key1"); | ||
|
||
userEvent.click(screen.getByText("Fetch Options")); // Attempt to fetch for "skip" | ||
fetchOptionsMock.mockClear(); | ||
|
||
await waitFor(() => { | ||
expect(fetchOptionsMock).not.toHaveBeenCalled(); // Skip condition met | ||
}); | ||
}); | ||
|
||
it("handles errors during fetching", async () => { | ||
fetchOptionsMock.mockRejectedValueOnce(new Error("Fetch error")); | ||
|
||
render( | ||
<AutocompleteProvider fetchOptions={fetchOptionsMock}> | ||
<MockAutocompleteConsumer /> | ||
</AutocompleteProvider> | ||
); | ||
|
||
userEvent.click(screen.getByText("Fetch Options")); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByTestId("error")).toHaveTextContent("Error fetching options"); | ||
}); | ||
}); | ||
|
||
it("sets options correctly", () => { | ||
render( | ||
<AutocompleteProvider fetchOptions={fetchOptionsMock}> | ||
<MockAutocompleteConsumer /> | ||
</AutocompleteProvider> | ||
); | ||
|
||
userEvent.click(screen.getByText("Fetch Options")); | ||
|
||
waitFor(() => { | ||
expect(screen.getByTestId("options")).toHaveTextContent( | ||
JSON.stringify({ key1: ["option1", "option2"] }) | ||
); | ||
}); | ||
}); | ||
|
||
it("handles multiple keys correctly", async () => { | ||
fetchOptionsMock.mockResolvedValueOnce(["option1", "option2"]); | ||
fetchOptionsMock.mockResolvedValueOnce(["option3", "option4"]); | ||
|
||
await act(async () =>render( | ||
<AutocompleteProvider fetchOptions={fetchOptionsMock}> | ||
<MockAutocompleteConsumer /> | ||
</AutocompleteProvider> | ||
)); | ||
|
||
await act(async () =>userEvent.click(screen.getByText("Fetch Options"))); | ||
expect(fetchOptionsMock).toHaveBeenCalledWith("test-query", "key1"); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByTestId("options")).toHaveTextContent( | ||
JSON.stringify({ key1: ["option1", "option2"] }) | ||
); | ||
}); | ||
|
||
await act(async () =>userEvent.click(screen.getByText("Fetch Options"))); | ||
expect(fetchOptionsMock).toHaveBeenCalledWith("test-query", "key1"); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByTestId("options")).toHaveTextContent( | ||
JSON.stringify({ key1: ["option3", "option4"] }) | ||
); | ||
}); | ||
}); | ||
|
||
it("updates loading state correctly", async () => { | ||
fetchOptionsMock.mockImplementation( | ||
() => new Promise((resolve) => setTimeout(() => resolve(["option1", "option2"]), 2500)) | ||
); | ||
|
||
await act(async () =>render( | ||
<AutocompleteProvider fetchOptions={fetchOptionsMock}> | ||
<MockAutocompleteConsumer /> | ||
</AutocompleteProvider> | ||
)); | ||
expect(screen.queryByTestId("loading")).not.toBeInTheDocument(); | ||
await act(async () =>userEvent.click(screen.getByText("Fetch Options"))); | ||
expect(screen.getByTestId("loading")).toBeInTheDocument(); | ||
await waitFor(() => expect(screen.queryByTestId("loading")).not.toBeInTheDocument(), { timeout: 3000 }); | ||
vi.clearAllTimers(); | ||
vi.useRealTimers(); | ||
}); | ||
|
||
it("updates error state correctly", async () => { | ||
fetchOptionsMock.mockRejectedValueOnce(new Error("Fetch error")); | ||
|
||
render( | ||
<AutocompleteProvider fetchOptions={fetchOptionsMock}> | ||
<MockAutocompleteConsumer /> | ||
</AutocompleteProvider> | ||
); | ||
|
||
userEvent.click(screen.getByText("Fetch Options")); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByTestId("error")).toHaveTextContent("Error fetching options"); | ||
}); | ||
}); | ||
|
||
it("does not fetch options if key or query is missing", async () => { | ||
render( | ||
<AutocompleteProvider fetchOptions={fetchOptionsMock}> | ||
<MockAutocompleteConsumer /> | ||
</AutocompleteProvider> | ||
); | ||
|
||
userEvent.click(screen.getByText("Fetch Options")); | ||
|
||
await waitFor(() => { | ||
expect(fetchOptionsMock).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters