Skip to content

Commit

Permalink
User Zustandification™️ (#11527)
Browse files Browse the repository at this point in the history
  • Loading branch information
karla-vm authored Dec 7, 2023
1 parent beed7ce commit 9cb5713
Show file tree
Hide file tree
Showing 62 changed files with 583 additions and 516 deletions.
14 changes: 7 additions & 7 deletions services/ui-src/src/components/app/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ import { act } from "react-dom/test-utils";
import { axe } from "jest-axe";
// utils
import {
mockStateUser,
mockNoUser,
mockNoUserStore,
RouterWrappedComponent,
mockUseStore,
} from "utils/testing/setupJest";
import { useUser, UserProvider } from "utils";
import { UserProvider, useStore } from "utils";
//components
import { App } from "components";

jest.mock("utils/auth/useUser");
const mockedUseUser = useUser as jest.MockedFunction<typeof useUser>;
jest.mock("utils/state/useStore");
const mockedUseStore = useStore as jest.MockedFunction<typeof useStore>;
mockedUseStore.mockReturnValue(mockUseStore);

const appComponent = (
<RouterWrappedComponent>
Expand All @@ -24,15 +25,14 @@ const appComponent = (

describe("Test App", () => {
test("App is visible", async () => {
mockedUseUser.mockReturnValue(mockStateUser);
await act(async () => {
await render(appComponent);
});
expect(screen.getByTestId("app-container")).toBeVisible();
});

test("App renders local logins if there is no user", async () => {
mockedUseUser.mockReturnValue(mockNoUser);
mockedUseStore.mockReturnValue(mockNoUserStore);
await act(async () => {
await render(appComponent);
});
Expand Down
12 changes: 9 additions & 3 deletions services/ui-src/src/components/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from "react";
import { useContext, useEffect } from "react";
import { useLocation, Route, Routes } from "react-router-dom";
import { ErrorBoundary } from "react-error-boundary";
// components
Expand All @@ -21,12 +21,18 @@ import {
fireTealiumPageView,
isApparentReportPage,
makeMediaQueryClasses,
useUser,
UserContext,
useStore,
} from "utils";

export const App = () => {
const mqClasses = makeMediaQueryClasses();
const { logout, user, showLocalLogins } = useUser();

// state management
const context = useContext(UserContext);
const { logout } = context;
const { user, showLocalLogins } = useStore();

const { pathname, key } = useLocation();
const isExportPage = pathname.includes("/export");

Expand Down
43 changes: 31 additions & 12 deletions services/ui-src/src/components/app/AppRoutes.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ import { createMemoryHistory } from "history";
// components
import { AppRoutes } from "components";
// utils
import { useUser, UserProvider } from "utils";
import { UserProvider, useStore } from "utils";
import {
mockAdminUser,
mockAdminUserStore,
mockBannerStore,
mockLDFlags,
mockStateUser,
mockStateUserNoReports,
mockStateUserStore,
mockStateUserStoreNoReports,
} from "utils/testing/setupJest";
// verbiage
import notFoundVerbiage from "verbiage/pages/not-found";

jest.mock("utils/auth/useUser");
const mockedUseUser = useUser as jest.MockedFunction<typeof useUser>;
jest.mock("utils/state/useStore");
const mockedUseStore = useStore as jest.MockedFunction<typeof useStore>;

mockLDFlags.setDefault({ mlrReport: true });

Expand All @@ -34,7 +35,10 @@ const tempScroll = window.HTMLElement.prototype.scrollIntoView;
describe("Test AppRoutes for admin-specific routes", () => {
beforeEach(async () => {
window.HTMLElement.prototype.scrollIntoView = function () {};
mockedUseUser.mockReturnValue(mockAdminUser);
mockedUseStore.mockReturnValue({
...mockAdminUserStore,
...mockBannerStore,
});
history = createMemoryHistory();
history.push("/admin");
await act(async () => {
Expand All @@ -52,7 +56,10 @@ describe("Test AppRoutes for admin-specific routes", () => {

describe("Test AppRoutes for non-admin-specific routes", () => {
beforeEach(async () => {
mockedUseUser.mockReturnValue(mockStateUser);
mockedUseStore.mockReturnValue({
...mockStateUserStore,
...mockBannerStore,
});
history = createMemoryHistory();
history.push("/admin");
await act(async () => {
Expand All @@ -68,7 +75,10 @@ describe("Test AppRoutes for non-admin-specific routes", () => {

describe("Test AppRoutes for non-admin-specific routes", () => {
beforeEach(async () => {
mockedUseUser.mockReturnValue(mockStateUser);
mockedUseStore.mockReturnValue({
...mockStateUserStore,
...mockBannerStore,
});
history = createMemoryHistory();
history.push("/admin");
await act(async () => {
Expand All @@ -84,7 +94,10 @@ describe("Test AppRoutes for non-admin-specific routes", () => {

describe("Test AppRoutes 404 handling", () => {
beforeEach(async () => {
mockedUseUser.mockReturnValue(mockStateUser);
mockedUseStore.mockReturnValue({
...mockStateUserStore,
...mockBannerStore,
});
history = createMemoryHistory();
history.push("/obviously-fake-route");
await act(async () => {
Expand All @@ -100,7 +113,10 @@ describe("Test AppRoutes 404 handling", () => {
describe("Test AppRoutes for MCPAR report-specific routes", () => {
beforeEach(async () => {
window.HTMLElement.prototype.scrollIntoView = function () {};
mockedUseUser.mockReturnValue(mockStateUser);
mockedUseStore.mockReturnValue({
...mockStateUserStore,
...mockBannerStore,
});
history = createMemoryHistory();
history.push("/mcpar");
await act(async () => {
Expand All @@ -119,7 +135,10 @@ describe("Test AppRoutes for MCPAR report-specific routes", () => {
describe("Test AppRoutes for state users without report-specific access", () => {
beforeEach(async () => {
window.HTMLElement.prototype.scrollIntoView = function () {};
mockedUseUser.mockReturnValue(mockStateUserNoReports);
mockedUseStore.mockReturnValue({
...mockStateUserStoreNoReports,
...mockBannerStore,
});
history = createMemoryHistory();
history.push("/mlr");
await act(async () => {
Expand Down
9 changes: 6 additions & 3 deletions services/ui-src/src/components/app/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ import {
} from "components";
// utils
import { ReportRoute, ReportType } from "types";
import { ScrollToTopComponent, useUser } from "utils";
import { ScrollToTopComponent, useStore } from "utils";
import { Fragment, useContext } from "react";
import { Flex, Spinner } from "@chakra-ui/react";

export const AppRoutes = () => {
const { userIsAdmin, userReports } = useUser().user ?? {};
const mlrReport = useFlags()?.mlrReport;
const { userIsAdmin, userReports } = useStore().user ?? {};
const { report, contextIsLoaded } = useContext(ReportContext);

// LaunchDarkly
const mlrReport = useFlags()?.mlrReport;

// determine if the user has access to specific reports
const userReportAccess = {
MCPAR: userReports?.includes("MCPAR") || userIsAdmin,
Expand Down
14 changes: 7 additions & 7 deletions services/ui-src/src/components/cards/TemplateCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { TemplateCard } from "components";
// utils
import {
mockLDFlags,
mockStateUser,
mockStateUserNoReports,
mockStateUserStore,
mockStateUserStoreNoReports,
RouterWrappedComponent,
} from "utils/testing/setupJest";
import { useUser } from "utils";
import { useStore } from "utils";
// verbiage
import verbiage from "verbiage/pages/home";

Expand All @@ -23,8 +23,8 @@ jest.mock("utils/other/useBreakpoint", () => ({
})),
}));

jest.mock("utils/auth/useUser");
const mockedUseUser = useUser as jest.MockedFunction<typeof useUser>;
jest.mock("utils/state/useStore");
const mockedUseStore = useStore as jest.MockedFunction<typeof useStore>;

const mockUseNavigate = jest.fn();

Expand Down Expand Up @@ -79,15 +79,15 @@ describe("Test MCPAR TemplateCard", () => {
});

test("MCPAR TemplateCard navigates to next route on link click", async () => {
mockedUseUser.mockReturnValue(mockStateUser);
mockedUseStore.mockReturnValue(mockStateUserStore);
const templateCardLink = screen.getByText(mcparTemplateVerbiage.link.text)!;
await userEvent.click(templateCardLink);
const expectedRoute = mcparTemplateVerbiage.link.route;
await expect(mockUseNavigate).toHaveBeenCalledWith(expectedRoute);
});

test("'Enter MCPAR' button is disabled for user with no access to this report", async () => {
mockedUseUser.mockReturnValue(mockStateUserNoReports);
mockedUseStore.mockReturnValue(mockStateUserStoreNoReports);
const templateCardLink = screen.getByText(mcparTemplateVerbiage.link.text)!;
expect(templateCardLink).toBeDisabled;
});
Expand Down
20 changes: 10 additions & 10 deletions services/ui-src/src/components/drawers/ReportDrawer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import { axe } from "jest-axe";
//components
import { ReportDrawer } from "components";
import {
mockAdminUser,
mockAdminUserStore,
mockCompletedQualityMeasuresEntity,
mockDrawerForm,
mockEmptyDrawerForm,
mockModalDrawerReportPageVerbiage,
mockStateUser,
mockStateUserStore,
RouterWrappedComponent,
} from "utils/testing/setupJest";
// utils
import { useUser } from "utils";
import { useStore } from "utils";
// constants
import { closeText, saveAndCloseText } from "../../constants";

Expand All @@ -25,8 +25,8 @@ const mockDrawerDisclosure = {
onClose: mockOnClose,
};

jest.mock("utils/auth/useUser");
const mockedUseUser = useUser as jest.MockedFunction<typeof useUser>;
jest.mock("utils/state/useStore");
const mockedUseStore = useStore as jest.MockedFunction<typeof useStore>;

const drawerComponent = (
<RouterWrappedComponent>
Expand All @@ -45,13 +45,13 @@ describe("Test ReportDrawer rendering", () => {
jest.clearAllMocks();
});
it("Should render save text for state user", async () => {
mockedUseUser.mockReturnValue(mockStateUser);
mockedUseStore.mockReturnValue(mockStateUserStore);
render(drawerComponent);
expect(screen.getByText(saveAndCloseText)).toBeVisible();
});

it("Should not render save text for admin user", async () => {
mockedUseUser.mockReturnValue(mockAdminUser);
mockedUseStore.mockReturnValue(mockAdminUserStore);
render(drawerComponent);
expect(screen.queryByText(saveAndCloseText)).not.toBeInTheDocument();
});
Expand All @@ -72,7 +72,7 @@ describe("Test ReportDrawerWithoutFormFields rendering", () => {
jest.clearAllMocks();
});
it("Should render save text for state user", async () => {
mockedUseUser.mockReturnValue(mockStateUser);
mockedUseStore.mockReturnValue(mockStateUserStore);
render(drawerComponentWithoutFormFields);
expect(
screen.getByText(mockModalDrawerReportPageVerbiage.drawerNoFormMessage)
Expand All @@ -82,7 +82,7 @@ describe("Test ReportDrawerWithoutFormFields rendering", () => {

describe("Test ReportDrawer fill form and close", () => {
beforeEach(() => {
mockedUseUser.mockReturnValue(mockStateUser);
mockedUseStore.mockReturnValue(mockStateUserStore);
render(drawerComponent);
});
afterEach(() => {
Expand Down Expand Up @@ -116,7 +116,7 @@ describe("Test ReportDrawer fill form and close", () => {

describe("Test ReportDrawer accessibility", () => {
it("Should not have basic accessibility issues", async () => {
mockedUseUser.mockReturnValue(mockStateUser);
mockedUseStore.mockReturnValue(mockStateUserStore);
const { container } = render(drawerComponent);
const results = await axe(container);
expect(results).toHaveNoViolations();
Expand Down
4 changes: 2 additions & 2 deletions services/ui-src/src/components/drawers/ReportDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MouseEventHandler } from "react";
import { Box, Button, Flex, Text, Spinner } from "@chakra-ui/react";
import { Drawer, Form } from "components";
// utils
import { useUser } from "utils";
import { useStore } from "utils";
// types
import {
AnyObject,
Expand All @@ -27,7 +27,7 @@ export const ReportDrawer = ({
...props
}: Props) => {
// determine if fields should be disabled (based on admin and read-only roles)
const { userIsAdmin, userIsReadOnly } = useUser().user ?? {};
const { userIsAdmin, userIsReadOnly } = useStore().user ?? {};
const buttonText =
userIsAdmin || userIsReadOnly ? closeText : saveAndCloseText;
const formFieldsExist = form.fields.length;
Expand Down
4 changes: 2 additions & 2 deletions services/ui-src/src/components/fields/ChoiceListField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
getAutosaveFields,
labelTextWithOptional,
parseCustomHtml,
useUser,
useStore,
} from "utils";
import {
AnyObject,
Expand Down Expand Up @@ -45,7 +45,7 @@ export const ChoiceListField = ({
const { entities, entityType, updateEntities, selectedEntity } =
useContext(EntityContext);
const { full_name, state, userIsAdmin, userIsReadOnly } =
useUser().user ?? {};
useStore().user ?? {};
// get form context and register field
const form = useFormContext();
const fieldIsRegistered = name in form.getValues();
Expand Down
Loading

0 comments on commit 9cb5713

Please sign in to comment.