Skip to content

Commit

Permalink
update testing process
Browse files Browse the repository at this point in the history
  • Loading branch information
mairisb committed Dec 24, 2023
1 parent 02ffd5f commit 29b2bcc
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 45 deletions.
69 changes: 40 additions & 29 deletions packages/client/src/pages/page.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
import { Page } from './page';
import { screen } from '@testing-library/react';
import { useNavigate } from 'react-router-dom';
import { useSelector } from 'react-redux';

jest.mock('../core/config', () => ({
config: {
TSPARK_APP_APP_NAME: 'MockAppName',
},
}));

jest.mock('react-redux', () => ({
useSelector: jest.fn(),
}));
import { RootStore } from '../core/root.store';
import { renderWithProviders } from '../utils/test.utils';
import { Page } from './page';

jest.mock('react-router-dom', () => ({
useNavigate: jest.fn(),
}));
jest.mock('react-router-dom', () => {
const originalModule = jest.requireActual('react-router-dom');
return {
...originalModule,
useNavigate: jest.fn(),
};
});

describe('Page', () => {
let navigate: jest.Mock;
Expand All @@ -27,46 +22,62 @@ describe('Page', () => {
});

it('should render page title', () => {
render(<Page title="Test title" />);
renderWithProviders(<Page title="Test title" />);

const pageTitle = screen.getByTestId('page-title');
expect(pageTitle.textContent).toEqual('Test title');
});

it('should set document title on mount and reset on unmount', () => {
const { unmount } = render(<Page title="Test title" />);
expect(document.title).toEqual('MockAppName - Test title');
const { unmount } = renderWithProviders(<Page title="Test title" />);

expect(document.title).toEqual('TSpark - Test title');

unmount();
expect(document.title).toEqual('MockAppName');
expect(document.title).toEqual('TSpark');
});

it('should render children', () => {
render(
renderWithProviders(
<Page title="Test title">
<span>Test child</span>
</Page>,
);

expect(screen.getByText('Test child')).toBeInTheDocument();
});

it('should redirect to /login if the page is auth protected and user is not logged in', () => {
(useSelector as jest.Mock).mockReturnValue(false);
render(<Page title="Test title" isAuthProtected />);
const rootStore = new RootStore();
rootStore.authStore.isAuthenticated = false;

renderWithProviders(<Page title="Test title" isAuthProtected />, {
rootStore,
});

expect(navigate).toHaveBeenCalledWith('/login');
});

it('should not redirect if the page is auth protected and user is logged in', () => {
(useSelector as jest.Mock).mockReturnValue(true);
render(<Page title="Test title" isAuthProtected />);
const rootStore = new RootStore();
rootStore.authStore.isAuthenticated = true;

renderWithProviders(<Page title="Test title" isAuthProtected />, {
rootStore,
});

expect(navigate).not.toHaveBeenCalled();
});

it("should not redirect if the page is not auth protected, irrespective of user's authentication status", () => {
(useSelector as jest.Mock).mockReturnValue(false);
render(<Page title="Test title" />);
const rootStore = new RootStore();

rootStore.authStore.isAuthenticated = false;
renderWithProviders(<Page title="Test title" />, { rootStore });
expect(navigate).not.toHaveBeenCalled();

(useSelector as jest.Mock).mockReturnValue(true);
render(<Page title="Test title" />);
rootStore.authStore.isAuthenticated = true;
renderWithProviders(<Page title="Test title" />, { rootStore });
expect(navigate).not.toHaveBeenCalled();
});
});
26 changes: 10 additions & 16 deletions packages/client/src/utils/test.utils.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
import type { PreloadedState } from '@reduxjs/toolkit';
import type { RenderOptions } from '@testing-library/react';
import { render } from '@testing-library/react';
import React, { PropsWithChildren } from 'react';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
import { AppStore, RootState, setupStore } from '../core/store';
import { RootStore, StoreContext } from '../core/root.store';

// https://redux.js.org/usage/writing-tests#setting-up-a-reusable-test-render-function

interface ExtendedRenderOptions extends Omit<RenderOptions, 'queries'> {
preloadedState?: PreloadedState<RootState>;
store?: AppStore;
interface ExtendedRenderOptions extends RenderOptions {
rootStore?: RootStore;
}

export const renderWithProviders = (
ui: React.ReactElement,
{
preloadedState = {},
store = setupStore(preloadedState),
...renderOptions
}: ExtendedRenderOptions = {},
{ rootStore = new RootStore(), ...renderOptions }: ExtendedRenderOptions = {},
) => {
const Wrapper = ({ children }: PropsWithChildren<{}>): JSX.Element => {
return (
<Provider store={store}>
<StoreContext.Provider value={rootStore}>
<MemoryRouter>{children}</MemoryRouter>
</Provider>
</StoreContext.Provider>
);
};

return { store, ...render(ui, { wrapper: Wrapper, ...renderOptions }) };
return {
store: rootStore,
...render(ui, { wrapper: Wrapper, ...renderOptions }),
};
};

0 comments on commit 29b2bcc

Please sign in to comment.