Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 35 additions & 13 deletions src/renderer/__helpers__/test-utils.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,46 @@
import { render } from '@testing-library/react';
import { type ReactElement, type ReactNode, useMemo } from 'react';
import { MemoryRouter } from 'react-router-dom';

import { BaseStyles, ThemeProvider } from '@primer/react';

import { mockAuth, mockSettings } from '../__mocks__/state-mocks';

import { AppContext, type AppContextState } from '../context/App';

export { navigateMock } from './vitest.setup';
export type DeepPartial<T> = { [K in keyof T]?: DeepPartial<T[K]> };

const EMPTY_APP_CONTEXT: TestAppContext = {};

interface RenderOptions extends Partial<AppContextState> {
initialEntries?: string[];
}

/**
* Test context
*/
type TestAppContext = Partial<AppContextState>;

/**
* Props for the AppContextProvider wrapper
*/
interface AppContextProviderProps {
readonly children: ReactNode;
readonly value?: Partial<AppContextState>;
readonly value?: TestAppContext;
readonly initialEntries?: string[];
}

/**
* Wrapper component that provides ThemeProvider, BaseStyles, and AppContext
* with sensible defaults for testing.
*/
function AppContextProvider({ children, value = {} }: AppContextProviderProps) {
const defaultValue: AppContextState = useMemo(() => {
function AppContextProvider({
children,
value = EMPTY_APP_CONTEXT,
initialEntries,
}: AppContextProviderProps) {
const defaultValue: TestAppContext = useMemo(() => {
return {
auth: mockAuth,
settings: mockSettings,
Expand Down Expand Up @@ -58,17 +76,19 @@ function AppContextProvider({ children, value = {} }: AppContextProviderProps) {
updateFilter: vi.fn(),

...value,
} as AppContextState;
} as TestAppContext;
}, [value]);

return (
<ThemeProvider>
<BaseStyles>
<AppContext.Provider value={defaultValue}>
{children}
</AppContext.Provider>
</BaseStyles>
</ThemeProvider>
<MemoryRouter initialEntries={initialEntries}>
<ThemeProvider>
<BaseStyles>
<AppContext.Provider value={defaultValue}>
{children}
</AppContext.Provider>
</BaseStyles>
</ThemeProvider>
</MemoryRouter>
);
}

Expand All @@ -80,11 +100,13 @@ function AppContextProvider({ children, value = {} }: AppContextProviderProps) {
*/
export function renderWithAppContext(
ui: ReactElement,
context: Partial<AppContextState> = {},
{ initialEntries, ...context }: RenderOptions = {},
) {
return render(ui, {
wrapper: ({ children }) => (
<AppContextProvider value={context}>{children}</AppContextProvider>
<AppContextProvider initialEntries={initialEntries} value={context}>
{children}
</AppContextProvider>
),
});
}
Expand Down
10 changes: 10 additions & 0 deletions src/renderer/__helpers__/vitest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import '@testing-library/jest-dom/vitest';

import { useFiltersStore } from '../stores';

/**
* Shared navigate mock — import from test-utils in any test that needs to assert on navigation
*/
export const navigateMock = vi.fn();
vi.mock('react-router-dom', async () => ({
...(await vi.importActual('react-router-dom')),
useNavigate: () => navigateMock,
}));

// Sets timezone to UTC for consistent date/time in tests and snapshots
process.env.TZ = 'UTC';

Expand All @@ -10,6 +19,7 @@ process.env.TZ = 'UTC';
*/
beforeEach(() => {
useFiltersStore.getState().reset();
navigateMock.mockReset();
});

/**
Expand Down
Loading