-
Notifications
You must be signed in to change notification settings - Fork 285
Expand file tree
/
Copy pathtest-utils.tsx
More file actions
116 lines (97 loc) · 3.03 KB
/
test-utils.tsx
File metadata and controls
116 lines (97 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import { render } from '@testing-library/react';
import { type ReactElement, type ReactNode, useMemo } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { mockAuth, mockSettings } from '../__mocks__/state-mocks';
import { AppContext, type AppContextState } from '../context/App';
import { type FiltersStore, useFiltersStore } from '../stores';
export { navigateMock } from './vitest.setup';
export type DeepPartial<T> = { [K in keyof T]?: DeepPartial<T[K]> };
const EMPTY_APP_CONTEXT: TestAppContext = {};
/**
* Test context
*/
type TestAppContext = Partial<AppContextState>;
interface RenderOptions extends TestAppContext {
initialEntries?: string[];
filters?: Partial<FiltersStore>;
}
/**
* Props for the AppContextProvider wrapper
*/
interface AppContextProviderProps {
readonly children: ReactNode;
readonly value?: TestAppContext;
readonly initialEntries?: string[];
}
/**
* Wrapper component that provides ThemeProvider, BaseStyles, and AppContext
* with sensible defaults for testing.
*/
function AppContextProvider({
children,
value = EMPTY_APP_CONTEXT,
initialEntries,
}: AppContextProviderProps) {
const defaultValue: TestAppContext = useMemo(() => {
return {
auth: mockAuth,
settings: mockSettings,
isLoggedIn: true,
notifications: [],
notificationCount: 0,
unreadNotificationCount: 0,
hasNotifications: false,
hasUnreadNotifications: false,
status: 'success',
globalError: null,
// Default mock implementations for all required methods
loginWithDeviceFlowStart: vi.fn(),
loginWithDeviceFlowPoll: vi.fn(),
loginWithDeviceFlowComplete: vi.fn(),
loginWithOAuthApp: vi.fn(),
loginWithPersonalAccessToken: vi.fn(),
logoutFromAccount: vi.fn(),
fetchNotifications: vi.fn(),
removeAccountNotifications: vi.fn(),
markNotificationsAsRead: vi.fn(),
markNotificationsAsDone: vi.fn(),
unsubscribeNotification: vi.fn(),
clearFilters: vi.fn(),
resetSettings: vi.fn(),
updateSetting: vi.fn(),
updateFilter: vi.fn(),
shortcutRegistrationError: null,
clearShortcutRegistrationError: vi.fn(),
...value,
} as TestAppContext;
}, [value]);
return (
<MemoryRouter initialEntries={initialEntries}>
<AppContext.Provider value={defaultValue as AppContextState}>
{children}
</AppContext.Provider>
</MemoryRouter>
);
}
/**
* Custom render that wraps components with all providers needed for testing:
* MemoryRouter, AppContext, and Zustand stores.
*
* Usage:
* renderWithProviders(<MyComponent />, { notifications, accounts, settings, filters, ... })
*/
export function renderWithProviders(
ui: ReactElement,
{ initialEntries, filters, ...context }: RenderOptions = {},
) {
if (filters) {
useFiltersStore.setState(filters);
}
return render(ui, {
wrapper: ({ children }) => (
<AppContextProvider initialEntries={initialEntries} value={context}>
{children}
</AppContextProvider>
),
});
}