From 7589602955d24f7e39be2bd589283d53b306f846 Mon Sep 17 00:00:00 2001 From: Caleb Cox Date: Fri, 6 Sep 2024 12:01:28 -0500 Subject: [PATCH] Add TestSetupProvider for mocking SetupProvider more effectively --- .../Primary/LogoLink/LogoLink.test.tsx | 24 +++++++-------- .../Layouts/Primary/NavBar/NavBar.test.tsx | 22 +++++--------- .../Primary/NavBar/NavTools/NavTools.test.tsx | 24 +++++++-------- .../ProfileMenuPanel.test.tsx | 26 +++++++--------- .../Items/ProfileMenu/ProfileMenu.test.tsx | 27 +++++++---------- .../Layouts/Primary/TopBar/TopBar.test.tsx | 30 ++++++++----------- src/components/Setup/SetupProvider.tsx | 17 +++++++++-- 7 files changed, 77 insertions(+), 93 deletions(-) diff --git a/src/components/Layouts/Primary/LogoLink/LogoLink.test.tsx b/src/components/Layouts/Primary/LogoLink/LogoLink.test.tsx index 1390c09eb..042a26366 100644 --- a/src/components/Layouts/Primary/LogoLink/LogoLink.test.tsx +++ b/src/components/Layouts/Primary/LogoLink/LogoLink.test.tsx @@ -1,25 +1,23 @@ import { render } from '@testing-library/react'; -import { useSetupContext } from 'src/components/Setup/SetupProvider'; +import { TestSetupProvider } from 'src/components/Setup/SetupProvider'; import { LogoLink } from './LogoLink'; -jest.mock('src/components/Setup/SetupProvider'); - describe('LogoLink', () => { it('renders a link when not on the setup tour', () => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: false, - }); - - const { getByRole } = render(); + const { getByRole } = render( + + + , + ); expect(getByRole('link')).toBeInTheDocument(); }); it('does not render a link when on the setup tour', () => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: true, - }); - - const { queryByRole } = render(); + const { queryByRole } = render( + + + , + ); expect(queryByRole('link')).not.toBeInTheDocument(); }); }); diff --git a/src/components/Layouts/Primary/NavBar/NavBar.test.tsx b/src/components/Layouts/Primary/NavBar/NavBar.test.tsx index 36008b938..8c012870d 100644 --- a/src/components/Layouts/Primary/NavBar/NavBar.test.tsx +++ b/src/components/Layouts/Primary/NavBar/NavBar.test.tsx @@ -3,13 +3,11 @@ import { MockedProvider } from '@apollo/client/testing'; import { ThemeProvider } from '@mui/material/styles'; import { render } from '@testing-library/react'; import TestRouter from '__tests__/util/TestRouter'; -import { useSetupContext } from 'src/components/Setup/SetupProvider'; +import { TestSetupProvider } from 'src/components/Setup/SetupProvider'; import theme from 'src/theme'; import { getTopBarMultipleMock } from '../TopBar/TopBar.mock'; import { NavBar } from './NavBar'; -jest.mock('src/components/Setup/SetupProvider'); - const router = { query: { accountListId: 'abc' }, isReady: true, @@ -18,15 +16,19 @@ const router = { interface TestComponentProps { openMobile?: boolean; + onSetupTour?: boolean; } const TestComponent: React.FC = ({ openMobile = false, + onSetupTour, }) => ( - + + + @@ -36,12 +38,6 @@ const onMobileClose = jest.fn(); const mocks = [getTopBarMultipleMock()]; describe('NavBar', () => { - beforeEach(() => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: false, - }); - }); - it('default', () => { const { queryByTestId } = render(); @@ -60,11 +56,7 @@ describe('NavBar', () => { }); it('hides links during the setup tour', () => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: true, - }); - - const { queryByRole } = render(); + const { queryByRole } = render(); expect( queryByRole('button', { name: 'Dashboard' }), diff --git a/src/components/Layouts/Primary/NavBar/NavTools/NavTools.test.tsx b/src/components/Layouts/Primary/NavBar/NavTools/NavTools.test.tsx index e42ef7c2e..6343ad7e2 100644 --- a/src/components/Layouts/Primary/NavBar/NavTools/NavTools.test.tsx +++ b/src/components/Layouts/Primary/NavBar/NavTools/NavTools.test.tsx @@ -3,24 +3,28 @@ import { MockedProvider } from '@apollo/client/testing'; import { ThemeProvider } from '@mui/material/styles'; import { render, waitFor } from '@testing-library/react'; import TestRouter from '__tests__/util/TestRouter'; -import { useSetupContext } from 'src/components/Setup/SetupProvider'; +import { TestSetupProvider } from 'src/components/Setup/SetupProvider'; import theme from 'src/theme'; import { getTopBarMultipleMock } from '../../TopBar/TopBar.mock'; import { NavTools } from './NavTools'; -jest.mock('src/components/Setup/SetupProvider'); - const router = { query: { accountListId: 'abc' }, isReady: true, push: jest.fn(), }; -const TestComponent = () => ( +interface TestComponentProps { + onSetupTour?: boolean; +} + +const TestComponent: React.FC = ({ onSetupTour }) => ( - + + + @@ -28,10 +32,6 @@ const TestComponent = () => ( describe('NavTools', () => { it('default', async () => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: false, - }); - const { findByText, getByTestId, getByText } = render(); expect(getByTestId('NavTools')).toBeInTheDocument(); @@ -40,11 +40,7 @@ describe('NavTools', () => { }); it('hides links during the setup tour', async () => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: true, - }); - - const { queryByText, getByTestId } = render(); + const { queryByText, getByTestId } = render(); expect(getByTestId('NavTools')).toBeInTheDocument(); expect(queryByText('Add')).not.toBeInTheDocument(); diff --git a/src/components/Layouts/Primary/NavBar/NavTools/ProfileMenuPanel/ProfileMenuPanel.test.tsx b/src/components/Layouts/Primary/NavBar/NavTools/ProfileMenuPanel/ProfileMenuPanel.test.tsx index 2ae1bf3d2..fd389df5c 100644 --- a/src/components/Layouts/Primary/NavBar/NavTools/ProfileMenuPanel/ProfileMenuPanel.test.tsx +++ b/src/components/Layouts/Primary/NavBar/NavTools/ProfileMenuPanel/ProfileMenuPanel.test.tsx @@ -5,36 +5,34 @@ import userEvent from '@testing-library/user-event'; import { signOut } from 'next-auth/react'; import TestRouter from '__tests__/util/TestRouter'; import TestWrapper from '__tests__/util/TestWrapper'; -import { useSetupContext } from 'src/components/Setup/SetupProvider'; +import { TestSetupProvider } from 'src/components/Setup/SetupProvider'; import theme from '../../../../../../theme'; import { getTopBarMock } from '../../../TopBar/TopBar.mock'; import { ProfileMenuPanel } from './ProfileMenuPanel'; -jest.mock('src/components/Setup/SetupProvider'); - const router = { pathname: '/accountLists/[accountListId]/test', query: { accountListId: '1' }, push: jest.fn(), }; -const TestComponent = () => ( +interface TestComponentProps { + onSetupTour?: boolean; +} + +const TestComponent: React.FC = ({ onSetupTour }) => ( - + + + ); describe('ProfileMenuPanelForNavBar', () => { - beforeEach(() => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: false, - }); - }); - it('default', () => { const { getByTestId } = render(); @@ -86,12 +84,8 @@ describe('ProfileMenuPanelForNavBar', () => { }); it('hides links during the setup tour', async () => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: true, - }); - const { findByTestId, getByRole, getByTestId, queryByText } = render( - , + , ); userEvent.click(await findByTestId('accountListSelectorButton')); diff --git a/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.test.tsx b/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.test.tsx index ffaf2ad59..d4abc718c 100644 --- a/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.test.tsx +++ b/src/components/Layouts/Primary/TopBar/Items/ProfileMenu/ProfileMenu.test.tsx @@ -9,7 +9,7 @@ import { session } from '__tests__/fixtures/session'; import TestRouter from '__tests__/util/TestRouter'; import TestWrapper from '__tests__/util/TestWrapper'; import { render, waitFor } from '__tests__/util/testingLibraryReactMock'; -import { useSetupContext } from 'src/components/Setup/SetupProvider'; +import { TestSetupProvider } from 'src/components/Setup/SetupProvider'; import theme from '../../../../../../theme'; import { getTopBarMock, @@ -17,8 +17,6 @@ import { } from '../../TopBar.mock'; import ProfileMenu from './ProfileMenu'; -jest.mock('src/components/Setup/SetupProvider'); - const mockEnqueue = jest.fn(); jest.mock('notistack', () => ({ @@ -48,25 +46,26 @@ const routerNoAccountListId = { interface TestComponentProps { router?: Partial; mocks?: MockedResponse[]; + onSetupTour?: boolean; } -const TestComponent: React.FC = ({ router, mocks }) => ( +const TestComponent: React.FC = ({ + router, + mocks, + onSetupTour, +}) => ( - + + + ); describe('ProfileMenu', () => { - beforeEach(() => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: false, - }); - }); - it('default', async () => { const { getByTestId, getByRole, getByText, findByText } = render( , @@ -175,12 +174,8 @@ describe('ProfileMenu', () => { }); it('hides links during the setup tour', async () => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: true, - }); - const { findByText, getByRole, getByTestId, queryByText } = render( - , + , ); expect(await findByText('John Smith')).toBeInTheDocument(); diff --git a/src/components/Layouts/Primary/TopBar/TopBar.test.tsx b/src/components/Layouts/Primary/TopBar/TopBar.test.tsx index c6d6453a8..d2abb26ac 100644 --- a/src/components/Layouts/Primary/TopBar/TopBar.test.tsx +++ b/src/components/Layouts/Primary/TopBar/TopBar.test.tsx @@ -4,14 +4,12 @@ import { ThemeProvider } from '@mui/material/styles'; import { render } from '@testing-library/react'; import { SnackbarProvider } from 'notistack'; import TestRouter from '__tests__/util/TestRouter'; -import { useSetupContext } from 'src/components/Setup/SetupProvider'; +import { TestSetupProvider } from 'src/components/Setup/SetupProvider'; import theme from '../../../../theme'; import { getNotificationsMocks } from './Items/NotificationMenu/NotificationMenu.mock'; import TopBar from './TopBar'; import { getTopBarMultipleMock } from './TopBar.mock'; -jest.mock('src/components/Setup/SetupProvider'); - const accountListId = 'accountListId'; const onMobileNavOpen = jest.fn(); @@ -33,7 +31,11 @@ jest.mock('notistack', () => ({ }, })); -const TestComponent = () => ( +interface TestComponentProps { + onSetupTour?: boolean; +} + +const TestComponent: React.FC = ({ onSetupTour }) => ( @@ -41,10 +43,12 @@ const TestComponent = () => ( mocks={[getTopBarMultipleMock(), ...getNotificationsMocks()]} addTypename={false} > - + + + @@ -53,10 +57,6 @@ const TestComponent = () => ( describe('TopBar', () => { it('default', () => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: false, - }); - const { getByTestId, getByText } = render(); expect(getByTestId('TopBar')).toBeInTheDocument(); @@ -64,11 +64,7 @@ describe('TopBar', () => { }); it('hides links during the setup tour', () => { - (useSetupContext as jest.MockedFn).mockReturnValue({ - onSetupTour: true, - }); - - const { queryByText } = render(); + const { queryByText } = render(); expect(queryByText('Dashboard')).not.toBeInTheDocument(); }); diff --git a/src/components/Setup/SetupProvider.tsx b/src/components/Setup/SetupProvider.tsx index 6ba6f9d16..b3f2ab7da 100644 --- a/src/components/Setup/SetupProvider.tsx +++ b/src/components/Setup/SetupProvider.tsx @@ -1,5 +1,6 @@ import { useRouter } from 'next/router'; import React, { + PropsWithChildren, ReactNode, createContext, useContext, @@ -43,13 +44,13 @@ const setupPages = new Set([ '/accountLists/[accountListId]/setup/finish', ]); -interface Props { +interface SetupProviderProps { children: ReactNode; } // This context component ensures that users have gone through the setup process // and provides the setup state to the rest of the application -export const SetupProvider: React.FC = ({ children }) => { +export const SetupProvider: React.FC = ({ children }) => { const { data } = useSetupStageQuery(); const { push, pathname } = useRouter(); @@ -99,3 +100,15 @@ export const SetupProvider: React.FC = ({ children }) => { ); }; + +// This provider is meant for use in tests. It lets tests easily override the +// onSetupTour without needing to mock useSetupProvider or the pathname and +// SetupStage GraphQL query. +export const TestSetupProvider: React.FC> = ({ + children, + onSetupTour, +}) => ( + + {children} + +);