Skip to content

Commit

Permalink
unit test updates
Browse files Browse the repository at this point in the history
  • Loading branch information
karla-vm committed Nov 14, 2023
1 parent 31d270e commit c522b7f
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 60 deletions.
80 changes: 48 additions & 32 deletions services/ui-src/src/components/pages/Admin/AdminPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,19 @@ import { AdminPage, AdminBannerContext } from "components";
import {
RouterWrappedComponent,
mockBannerData,
mockBannerStore,
} from "utils/testing/setupJest";
import { useStore } from "utils";
import { bannerErrors } from "verbiage/errors";

const mockBannerMethods = {
fetchAdminBanner: jest.fn(() => {}),
writeAdminBanner: jest.fn(() => {}),
deleteAdminBanner: jest.fn(() => {}),
};

const mockContextWithoutBanner = {
...mockBannerMethods,
bannerData: undefined,
isLoading: false,
errorData: null,
};

const mockContextWithBanner = {
...mockBannerMethods,
bannerData: mockBannerData,
isLoading: false,
errorData: null,
};
jest.mock("utils/state/useStore");
const mockedUseStore = useStore as jest.MockedFunction<typeof useStore>;

const adminView = (context: any) => (
<RouterWrappedComponent>
Expand All @@ -41,20 +33,25 @@ const adminView = (context: any) => (
describe("Test AdminPage banner manipulation functionality", () => {
it("Deletes current banner on delete button click", async () => {
await act(async () => {
await render(adminView(mockContextWithBanner));
mockedUseStore.mockReturnValue(mockBannerStore);
await render(adminView(mockBannerMethods));
});
const deleteButton = screen.getByText("Delete Current Banner");
await userEvent.click(deleteButton);
await waitFor(() =>
expect(mockContextWithBanner.deleteAdminBanner).toHaveBeenCalled()
expect(mockBannerMethods.deleteAdminBanner).toHaveBeenCalled()
);
});
});

describe("Test AdminPage without banner", () => {
beforeEach(async () => {
await act(async () => {
await render(adminView(mockContextWithoutBanner));
mockedUseStore.mockReturnValue({
...mockBannerStore,
bannerData: undefined,
});
await render(adminView(mockBannerMethods));
});
});

Expand All @@ -75,7 +72,8 @@ describe("Test AdminPage without banner", () => {
describe("Test AdminPage with banner", () => {
beforeEach(async () => {
await act(async () => {
await render(adminView(mockContextWithBanner));
mockedUseStore.mockReturnValue(mockBannerStore);
await render(adminView(mockBannerMethods));
});
});

Expand All @@ -101,38 +99,56 @@ describe("Test AdminPage with banner", () => {
describe("Test AdminPage with active/inactive banner", () => {
const currentTime = Date.now(); // 'current' time in ms since unix epoch
const oneDay = 1000 * 60 * 60 * 24; // 1000ms * 60s * 60m * 24h = 86,400,000ms
const context = mockContextWithBanner;
const context = mockBannerMethods;
mockedUseStore.mockReturnValue(mockBannerStore);

test("Active banner shows 'active' status", async () => {
context.bannerData.startDate = currentTime - oneDay;
context.bannerData.endDate = currentTime + oneDay;
const activeBannerData = {
...mockBannerData,
startDate: currentTime - oneDay,
endDate: currentTime + oneDay,
};
await act(async () => {
mockedUseStore.mockReturnValue({
...mockBannerStore,
bannerData: activeBannerData,
bannerActive: true,
});
await render(adminView(context));
});
const currentBannerStatus = screen.getByText("Status:");
expect(currentBannerStatus.textContent).toEqual("Status: Active");
});

test("Inactive banner shows 'inactive' status", async () => {
context.bannerData.startDate = currentTime + oneDay;
context.bannerData.endDate = currentTime + oneDay + oneDay;
const inactiveBannerData = {
...mockBannerData,
startDate: currentTime + oneDay,
endDate: currentTime + oneDay + oneDay,
};
await act(async () => {
await render(adminView(context));
mockedUseStore.mockReturnValue({
...mockBannerStore,
bannerData: inactiveBannerData,
});
await act(async () => {
await render(adminView(context));
});
const currentBannerStatus = screen.getByText("Status:");
expect(currentBannerStatus.textContent).toEqual("Status: Inactive");
});
const currentBannerStatus = screen.getByText("Status:");
expect(currentBannerStatus.textContent).toEqual("Status: Inactive");
});
});

describe("Test AdminPage delete banner error handling", () => {
it("Displays error if deleteBanner throws error", async () => {
window.HTMLElement.prototype.scrollIntoView = jest.fn();
const context = mockContextWithBanner;
context.deleteAdminBanner = jest.fn(() => {
throw new Error();
mockedUseStore.mockReturnValue({
...mockBannerStore,
bannerErrorMessage: bannerErrors.DELETE_BANNER_FAILED,
});

await act(async () => {
await render(adminView(context));
await render(adminView(mockBannerMethods));
});
const deleteButton = screen.getByText("Delete Current Banner");
await userEvent.click(deleteButton);
Expand All @@ -142,14 +158,14 @@ describe("Test AdminPage delete banner error handling", () => {

describe("Test AdminPage accessibility", () => {
it("Should not have basic accessibility issues without banner", async () => {
const { container } = render(adminView(mockContextWithoutBanner));
const { container } = render(adminView(mockBannerMethods));
await act(async () => {
expect(await axe(container)).toHaveNoViolations();
});
});

it("Should not have basic accessibility issues with banner", async () => {
const { container } = render(adminView(mockContextWithBanner));
const { container } = render(adminView(mockBannerMethods));
await act(async () => {
expect(await axe(container)).toHaveNoViolations();
});
Expand Down
50 changes: 29 additions & 21 deletions services/ui-src/src/components/pages/Admin/AdminPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useContext, useEffect } from "react";
import { useContext, useEffect } from "react";
// components
import {
Box,
Expand All @@ -17,21 +17,29 @@ import {
PageTemplate,
} from "components";
// utils
import { checkDateRangeStatus, convertDateUtcToEt } from "utils";
import { checkDateRangeStatus, convertDateUtcToEt, useStore } from "utils";
import { bannerErrors } from "verbiage/errors";
import verbiage from "verbiage/pages/admin";

export const AdminPage = () => {
const { deleteAdminBanner, writeAdminBanner } =
useContext(AdminBannerContext);

// state management
const {
bannerData,
deleteAdminBanner,
writeAdminBanner,
isLoading,
errorMessage,
} = useContext(AdminBannerContext);
const [error, setError] = useState<string | undefined>(errorMessage);
const [deleting, setDeleting] = useState<boolean>(false);
const [isBannerActive, setIsBannerActive] = useState<boolean>(false);
bannerActive,
setBannerActive,
bannerLoading,
bannerErrorMessage,
setBannerErrorMessage,
bannerDeleting,
setBannerDeleting,
} = useStore();

useEffect(() => {
setBannerErrorMessage("");
}, []);

useEffect(() => {
let bannerActivity = false;
Expand All @@ -41,26 +49,26 @@ export const AdminPage = () => {
bannerData.endDate
);
}
setIsBannerActive(bannerActivity);
setBannerActive(bannerActivity);
}, [bannerData]);

useEffect(() => {
setError(errorMessage);
}, [errorMessage]);
setBannerErrorMessage(bannerErrorMessage);
}, [bannerErrorMessage]);

const deleteBanner = async () => {
setDeleting(true);
setBannerDeleting(true);
try {
await deleteAdminBanner();
} catch (error: any) {
setError(bannerErrors.DELETE_BANNER_FAILED);
setBannerErrorMessage(bannerErrors.DELETE_BANNER_FAILED);
}
setDeleting(false);
setBannerDeleting(false);
};

return (
<PageTemplate sxOverride={sx.layout} data-testid="admin-view">
<ErrorAlert error={error} sxOverride={sx.errorAlert} />
<ErrorAlert error={bannerErrorMessage} sxOverride={sx.errorAlert} />
<Box sx={sx.introTextBox}>
<Heading as="h1" id="AdminHeader" tabIndex={-1} sx={sx.headerText}>
{verbiage.intro.header}
Expand All @@ -69,7 +77,7 @@ export const AdminPage = () => {
</Box>
<Box sx={sx.currentBannerSectionBox}>
<Text sx={sx.sectionHeader}>Current Banner</Text>
{isLoading ? (
{bannerLoading ? (
<Flex sx={sx.spinnerContainer}>
<Spinner size="md" />
</Flex>
Expand All @@ -81,8 +89,8 @@ export const AdminPage = () => {
<Flex sx={sx.currentBannerInfo}>
<Text sx={sx.currentBannerStatus}>
Status:{" "}
<span className={isBannerActive ? "active" : "inactive"}>
{isBannerActive ? "Active" : "Inactive"}
<span className={bannerActive ? "active" : "inactive"}>
{bannerActive ? "Active" : "Inactive"}
</span>
</Text>
<Text sx={sx.currentBannerDate}>
Expand All @@ -101,7 +109,7 @@ export const AdminPage = () => {
sx={sx.deleteBannerButton}
onClick={deleteBanner}
>
{deleting ? (
{bannerDeleting ? (
<Spinner size="md" />
) : (
"Delete Current Banner"
Expand Down
13 changes: 6 additions & 7 deletions services/ui-src/src/components/pages/Home/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import { useContext, useState, useEffect } from "react";
import { useEffect } from "react";
// components
import { Box, Collapse, Heading, Link, Text } from "@chakra-ui/react";
import {
AdminBannerContext,
AdminDashSelector,
Banner,
PageTemplate,
TemplateCard,
} from "components";
// utils
import { checkDateRangeStatus, useUser } from "utils";
import { checkDateRangeStatus, useStore, useUser } from "utils";
// verbiage
import verbiage from "verbiage/pages/home";

export const HomePage = () => {
const { bannerData } = useContext(AdminBannerContext);
// state management
const { bannerData, bannerActive, setBannerActive } = useStore();
const { userIsEndUser, userReports } = useUser().user ?? {};
const [isBannerActive, setIsBannerActive] = useState(false);

useEffect(() => {
let bannerActivity = false;
Expand All @@ -26,10 +25,10 @@ export const HomePage = () => {
bannerData.endDate
);
}
setIsBannerActive(bannerActivity);
setBannerActive(bannerActivity);
}, [bannerData]);

const showBanner = !!bannerData?.key && isBannerActive;
const showBanner = !!bannerData?.key && bannerActive;
const { intro, cards } = verbiage;

return (
Expand Down

0 comments on commit c522b7f

Please sign in to comment.