Skip to content
This repository has been archived by the owner on Sep 18, 2024. It is now read-only.

Commit

Permalink
Update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
acouch committed Jul 5, 2024
1 parent a26633b commit b4954ae
Show file tree
Hide file tree
Showing 12 changed files with 142 additions and 183 deletions.
14 changes: 1 addition & 13 deletions frontend/src/components/search/SearchOpportunityStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { Checkbox } from "@trussworks/react-uswds";
import { QueryContext } from "../../app/[locale]/search/QueryProvider";
import { useContext } from "react";
import { useDebouncedCallback } from "use-debounce";
import { useSearchParamUpdater } from "src/hooks/useSearchParamUpdater";

interface StatusOption {
Expand All @@ -22,27 +21,16 @@ const statusOptions: StatusOption[] = [
{ id: "status-archived", label: "Archived", value: "archived" },
];

// Wait 50 miliseconds before updating query params
// and submitting the form
const SEARCH_OPPORTUNITY_STATUS_DEBOUNCE_TIME = 50;

export default function SearchOpportunityStatus({
query,
}: SearchOpportunityStatusProps) {
const { queryTerm } = useContext(QueryContext);
const { updateQueryParams } = useSearchParamUpdater();

const debouncedUpdate = useDebouncedCallback(
(selectedStatuses: Set<string>) => {
updateQueryParams(selectedStatuses, "status", queryTerm);
},
SEARCH_OPPORTUNITY_STATUS_DEBOUNCE_TIME,
);

const handleCheck = (value: string, isChecked: boolean) => {
const updated = new Set(query);
isChecked ? updated.add(value) : updated.delete(value);
debouncedUpdate(updated);
updateQueryParams(updated, "status", queryTerm);
};

return (
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/search/SearchPagination.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";
import { Pagination } from "@trussworks/react-uswds";
import { QueryContext } from "src/app/[locale]/search/QueryProvider";
import { useSearchParamUpdater } from "src/hooks/useSearchParamUpdater";
import { useContext } from "react";
import { useSearchParamUpdater } from "src/hooks/useSearchParamUpdater";

export enum PaginationPosition {
Top = "topPagination",
Expand Down
4 changes: 2 additions & 2 deletions frontend/tests/api/OpportunityListingApi.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApiResponse } from "../../src/types/opportunity/opportunityResponseTypes";
import OpportunityListingAPI from "../../src/app/api/OpportunityListingAPI";

jest.mock("../../src/app/api/BaseApi");
jest.mock("src/app/api/BaseApi");

describe("OpportunityListingAPI", () => {
const mockedRequest = jest.fn();
Expand All @@ -21,7 +21,7 @@ describe("OpportunityListingAPI", () => {
mockedRequest.mockResolvedValue(mockResponse);

const result = await opportunityListingAPI.getOpportunityById(12345);
console.log("results => ", result);

expect(mockedRequest).toHaveBeenCalledWith(
"GET",
opportunityListingAPI.basePath,
Expand Down
26 changes: 22 additions & 4 deletions frontend/tests/components/search/SearchBar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { fireEvent, render, screen } from "@testing-library/react";
import React from "react";
import SearchBar from "src/components/search/SearchBar";
import { axe } from "jest-axe";
import QueryProvider from "src/app/[locale]/search/QueryProvider";

// Mock the hook since it's used in the component
const mockUpdateQueryParams = jest.fn();
Expand All @@ -19,13 +20,21 @@ describe("SearchBar", () => {
const initialQueryParams = "initial query";

it("should not have basic accessibility issues", async () => {
const { container } = render(<SearchBar query={initialQueryParams} />);
const { container } = render(
<QueryProvider>
<SearchBar query={initialQueryParams} />
</QueryProvider>,
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});

it("updates the input value when typing in the search field", () => {
render(<SearchBar query={initialQueryParams} />);
render(
<QueryProvider>
<SearchBar query={initialQueryParams} />
</QueryProvider>,
);

const input = screen.getByRole("searchbox");
fireEvent.change(input, { target: { value: "new query" } });
Expand All @@ -34,14 +43,23 @@ describe("SearchBar", () => {
});

it("calls updateQueryParams with the correct argument when submitting the form", () => {
render(<SearchBar query={initialQueryParams} />);
render(
<QueryProvider>
<SearchBar query={initialQueryParams} />
</QueryProvider>,
);

const input = screen.getByRole("searchbox");
fireEvent.change(input, { target: { value: "new query" } });

const searchButton = screen.getByRole("button", { name: /search/i });
fireEvent.click(searchButton);

expect(mockUpdateQueryParams).toHaveBeenCalledWith("new query", "query");
expect(mockUpdateQueryParams).toHaveBeenCalledWith(
"",
"query",
"new query",
false,
);
});
});
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import "@testing-library/jest-dom/extend-expect";

import { axe } from "jest-axe";
import { fireEvent, render, screen } from "@testing-library/react";
import React from "react";
import SearchFilterAccordion, {
FilterOption,
} from "src/components/search/SearchFilterAccordion/SearchFilterAccordion";
import { fireEvent, render, screen } from "@testing-library/react";

import React from "react";
import { axe } from "jest-axe";

const initialFilterOptions: FilterOption[] = [
{
Expand All @@ -31,9 +29,17 @@ const initialFilterOptions: FilterOption[] = [
},
];

const mockUpdateQueryParams = jest.fn();

jest.mock("src/hooks/useSearchParamUpdater", () => ({
useSearchParamUpdater: () => ({
updateQueryParams: mockUpdateQueryParams,
}),
}));

describe("SearchFilterAccordion", () => {
const title = "Test Accordion";
const queryParamKey = "status";
const queryParamKey = "fundingInstrument";

it("should not have basic accessibility issues", async () => {
const { container } = render(
Expand Down Expand Up @@ -65,7 +71,7 @@ describe("SearchFilterAccordion", () => {
});

it("displays select all and clear all correctly", () => {
render(
const { rerender } = render(
<SearchFilterAccordion
options={initialFilterOptions}
title={title}
Expand All @@ -86,8 +92,18 @@ describe("SearchFilterAccordion", () => {
"Cooperative Agreement",
);

// after clicking one of the boxes, both select all and clear all should be enabled
fireEvent.click(cooperativeAgreementCheckbox);
const updatedQuery = new Set("");
updatedQuery.add("Cooperative Agreement");
// after clicking one of the boxes, the page should rerender
// both select all and clear all should be enabled
rerender(
<SearchFilterAccordion
options={initialFilterOptions}
title={title}
queryParamKey={queryParamKey}
query={updatedQuery}
/>,
);
expect(selectAllButton).toBeEnabled();
expect(clearAllButton).toBeEnabled();
});
Expand All @@ -97,7 +113,7 @@ describe("SearchFilterAccordion", () => {
<SearchFilterAccordion
options={initialFilterOptions}
title={title}
queryParamKey={queryParamKey}
queryParamKey={"status"}
query={new Set()}
/>,
);
Expand All @@ -116,31 +132,38 @@ describe("SearchFilterAccordion", () => {
});

it("checks boxes correctly and updates count", () => {
render(
const { rerender } = render(
<SearchFilterAccordion
options={initialFilterOptions}
title={title}
queryParamKey={queryParamKey}
query={new Set()}
query={new Set("")}
/>,
);

const updatedQuery = new Set("");
updatedQuery.add("Cooperative Agreement");
updatedQuery.add("Grant");
// after clicking one of the boxes, the page should rerender
// both select all and clear all should be enabled
rerender(
<SearchFilterAccordion
options={initialFilterOptions}
title={title}
queryParamKey={queryParamKey}
query={updatedQuery}
/>,
);

const cooperativeAgreementCheckbox = screen.getByLabelText(
"Cooperative Agreement",
);
fireEvent.click(cooperativeAgreementCheckbox);

const grantCheckbox = screen.getByLabelText("Grant");
fireEvent.click(grantCheckbox);

// Verify the count updates to 2
const countSpan = screen.getByText("2", {
selector: ".usa-tag.usa-tag--big.radius-pill.margin-left-1",
});
expect(countSpan).toBeInTheDocument();

// Verify the checkboxes are checked
expect(cooperativeAgreementCheckbox).toBeChecked();
expect(grantCheckbox).toBeChecked();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,9 @@ describe("SearchFilterCheckbox", () => {
const checkbox = screen.getByLabelText(option.label);
fireEvent.click(checkbox);

// Wait for the increment function to be called
await waitFor(() => {
expect(mockIncrement).toHaveBeenCalledTimes(1);
});

// Wait for the updateCheckedOption function to be called with the checkbox being checked
await waitFor(() => {
expect(mockUpdateCheckedOption).toHaveBeenCalledWith(option.id, true);
expect(mockUpdateCheckedOption).toHaveBeenCalledWith(option.value, true);
});

// Simulate user clicking the checkbox again to uncheck it
fireEvent.click(checkbox);

// TODO (Issue #1618): Resolve issues with unchecking

// await waitFor(() => {
// expect(mockDecrement).toHaveBeenCalledTimes(1);
// });

// // Wait for the updateCheckedOption function to be called with the checkbox being unchecked
// await waitFor(() => {
// expect(mockUpdateCheckedOption).toHaveBeenCalledWith(option.id, false);
// });
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -80,29 +80,6 @@ describe("SearchFilterSection", () => {
).toBeInTheDocument();
});

it("correctly updates the section count", async () => {
// Render the component with default props
render(<SearchFilterSection {...defaultProps} />);

// Just 1 is checked initially, so count should be 1
const countSpanAsOne = screen.getByText("1", { selector: ".usa-tag" });
expect(countSpanAsOne).toBeInTheDocument();

// uncollapse section
fireEvent.click(screen.getByRole("button"));

// Check the 1st box in the section
const checkboxForChild1 = screen.getByLabelText("Child 1");
fireEvent.click(checkboxForChild1);

await waitFor(() => {
// count should now be 2
expect(
screen.getByText("2", { selector: ".usa-tag" }),
).toBeInTheDocument();
});
});

it("renders hidden inputs for checked children when collapsed", () => {
// checkbox "1-2" is checked, but when the section is collapsed we still need to send the value
// to the form to submit, so we use a hidden input. It must be present.
Expand Down
49 changes: 18 additions & 31 deletions frontend/tests/components/search/SearchOpportunityStatus.test.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import "@testing-library/jest-dom/extend-expect";

import { render, screen } from "@testing-library/react";

import { axe } from "jest-axe";
import { fireEvent, render, screen } from "@testing-library/react";
import React from "react";
import SearchOpportunityStatus from "src/components/search/SearchOpportunityStatus";
import { axe } from "jest-axe";

jest.mock("use-debounce", () => ({
useDebouncedCallback: (fn: (...args: unknown[]) => unknown) => {
return [fn, jest.fn()];
},
}));

const mockUpdateQueryParams = jest.fn();

Expand All @@ -37,28 +29,23 @@ describe("SearchOpportunityStatus", () => {
expect(screen.getByText("Archived")).toBeEnabled();
});

/* eslint-disable jest/no-commented-out-tests */

// TODO: Fix additional tests

// it("checking a checkbox calls updateQueryParams and requestSubmit", async () => {
// render(<SearchOpportunityStatus formRef={formRef} />);
it("checking a checkbox calls updateQueryParams and requestSubmit", async () => {
const query = new Set("");
query.add("test");
const combined = new Set("");
combined.add("test").add("forecasted");
render(<SearchOpportunityStatus query={query} />);

// // No need to wait for component to mount since we're not testing that here
// const forecastedCheckbox = screen.getByRole("checkbox", {
// name: "Forecasted",
// });
const forecastedCheckbox = screen.getByRole("checkbox", {
name: "Forecasted",
});

// fireEvent.click(forecastedCheckbox);
fireEvent.click(forecastedCheckbox);

// // Since we mocked useDebouncedCallback, we expect the function to be called immediately
// // Make sure to check for both updateQueryParams and requestSubmit
// // expect(formRef.current.requestSubmit).toHaveBeenCalled();
// expect(mockUpdateQueryParams).toHaveBeenCalledWith(
// new Set(["forecasted"]),
// "status",
// );
// });

// TODO: Add more tests as needed to cover other interactions and edge cases
expect(mockUpdateQueryParams).toHaveBeenCalledWith(
combined,
"status",
undefined,
);
});
});
Loading

0 comments on commit b4954ae

Please sign in to comment.