I have a component that shows data in a grid if the API returns data, and if no data is returned, it shows a message:
export default async function Operations({
searchParams,
}: {
searchParams: OperationsSearchParams;
}) {
const session = await getServerSession(authOptions);
// Fetch operations data
const operations: {
rows: OperationRow[];
row_count: number;
} = await fetchOperationsPageData(searchParams);
if (!operations) {
return <div>No operations data in database.</div>;
}
// Show the operator column if the user is CAS internal
const isOperatorColumn =
session?.user.app_role?.includes("cas") &&
!session?.user.app_role?.includes("pending");
// Render the DataGrid component
return (
<div className="mt-5">
<OperationDataGrid
initialData={operations}
isOperatorColumn={isOperatorColumn}
/>
</div>
);
}
Within fetchOperationsPageData
is a function called `actionHandler:
export const fetchOperationsPageData = async (
searchParams: OperationsSearchParams,
) => {
try {
const queryParams = buildQueryParams(searchParams);
// fetch data from server
const pageData = await actionHandler(
`registration/operations${queryParams}`,
"GET",
"",
);
return {
rows: formatOperationRows(pageData.data),
row_count: pageData.row_count,
};
} catch (error) {
throw error;
}
};
In the test for my Operations
component, I need to mock both the fetchOperationsPageData
or actionHandler
. However, only the action handler is being mocked, so my first test keeps failing:
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import {
actionHandler,
useRouter,
useSearchParams,
} from "@bciers/testConfig/mocks";
import Operations from "apps/registration/app/components/operations/Operations";
import { FrontEndRoles } from "@/app/utils/enums";
useRouter.mockReturnValue({
query: {},
replace: vi.fn(),
});
useSearchParams.mockReturnValue({
get: vi.fn(),
});
const mockResponse = {
data: [
{
id: 1,
operator: "FakeOperator",
name: "Operation 1",
bcghg_id: "1-211113-0001",
type: "Single Facility Operation",
},
{
id: 2,
operator: "FakeOperator",
name: "Operation 2",
bcghg_id: "2",
type: "Linear Facility Operation",
},
],
row_count: 2,
};
describe("Operations component", () => {
beforeEach(async () => {
vi.clearAllMocks();
});
it("renders a message when there are no operations in the database", async () => {
actionHandler.mockReturnValueOnce(mockResponse);
vi.doMock(
"apps/registration/app/components/operations/fetchOperationsPageData",
() => ({
default: vi.fn(),
}),
);
const fetchOperationsPageData = vi.fn();
fetchOperationsPageData.mockReturnValueOnce(undefined);
render(
await Operations({ searchParams: {}, role: FrontEndRoles.CAS_ADMIN }),
);
expect(screen.queryByRole("grid")).not.toBeInTheDocument();
expect(screen.getByText(/No operations data in database./i)).toBeVisible();
vi.doUnmock(
"apps/registration/app/components/operations/fetchOperationsPageData",
);
});
it("renders the OperationDataGrid component when there are operations in the database", async () => {
actionHandler.mockReturnValueOnce(mockResponse);
render(
await Operations({ searchParams: {}, role: FrontEndRoles.CAS_ADMIN }),
);
expect(screen.getByRole("grid")).toBeVisible();
expect(
screen.queryByText(/No operations data in database./i),
).not.toBeInTheDocument();
});
});
I’ve tried various combinations of vi.mock, vi.doMock, etc. If I successfully mock fetchOperationsPageData
, then the second tests fails because the actionHandler
mock doesn’t work anymore.