Skip to content

Commit 3fa3eac

Browse files
authored
refactor: test renderWithProviders for store initialization (#2728)
* refactor: test renderWithProviders for store initialization Signed-off-by: Adam Setch <adam.setch@outlook.com> * refactor: test renderWithProviders for store initialization Signed-off-by: Adam Setch <adam.setch@outlook.com> * refactor: test renderWithProviders for store initialization Signed-off-by: Adam Setch <adam.setch@outlook.com> --------- Signed-off-by: Adam Setch <adam.setch@outlook.com>
1 parent af48f5c commit 3fa3eac

62 files changed

Lines changed: 396 additions & 393 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/renderer/__helpers__/test-utils.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,23 @@ import { mockAuth, mockSettings } from '../__mocks__/state-mocks';
88

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

11+
import { type FiltersStore, useFiltersStore } from '../stores';
12+
1113
export { navigateMock } from './vitest.setup';
1214
export type DeepPartial<T> = { [K in keyof T]?: DeepPartial<T[K]> };
1315

1416
const EMPTY_APP_CONTEXT: TestAppContext = {};
1517

16-
interface RenderOptions extends Partial<AppContextState> {
17-
initialEntries?: string[];
18-
}
19-
2018
/**
2119
* Test context
2220
*/
2321
type TestAppContext = Partial<AppContextState>;
2422

23+
interface RenderOptions extends TestAppContext {
24+
initialEntries?: string[];
25+
filters?: Partial<FiltersStore>;
26+
}
27+
2528
/**
2629
* Props for the AppContextProvider wrapper
2730
*/
@@ -83,7 +86,7 @@ function AppContextProvider({
8386
<MemoryRouter initialEntries={initialEntries}>
8487
<ThemeProvider>
8588
<BaseStyles>
86-
<AppContext.Provider value={defaultValue}>
89+
<AppContext.Provider value={defaultValue as AppContextState}>
8790
{children}
8891
</AppContext.Provider>
8992
</BaseStyles>
@@ -93,15 +96,20 @@ function AppContextProvider({
9396
}
9497

9598
/**
96-
* Custom render that wraps components with AppContextProvider by default.
99+
* Custom render that wraps components with all providers needed for testing:
100+
* MemoryRouter, AppContext, and Zustand stores.
97101
*
98102
* Usage:
99-
* renderWithAppContext(<MyComponent />, { auth, settings, ... })
103+
* renderWithProviders(<MyComponent />, { notifications, accounts, settings, filters, ... })
100104
*/
101-
export function renderWithAppContext(
105+
export function renderWithProviders(
102106
ui: ReactElement,
103-
{ initialEntries, ...context }: RenderOptions = {},
107+
{ initialEntries, filters, ...context }: RenderOptions = {},
104108
) {
109+
if (filters) {
110+
useFiltersStore.setState(filters);
111+
}
112+
105113
return render(ui, {
106114
wrapper: ({ children }) => (
107115
<AppContextProvider initialEntries={initialEntries} value={context}>

src/renderer/components/AllRead.test.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
import { act } from '@testing-library/react';
22

3-
import { renderWithAppContext } from '../__helpers__/test-utils';
3+
import { renderWithProviders } from '../__helpers__/test-utils';
44
import { mockSettings } from '../__mocks__/state-mocks';
55

6-
import { useFiltersStore } from '../stores';
76
import { AllRead } from './AllRead';
87

98
describe('renderer/components/AllRead.tsx', () => {
109
it('should render itself & its children - no filters', async () => {
11-
let tree: ReturnType<typeof renderWithAppContext> | null = null;
10+
let tree: ReturnType<typeof renderWithProviders> | null = null;
1211

1312
await act(async () => {
14-
tree = renderWithAppContext(<AllRead />, {
13+
tree = renderWithProviders(<AllRead />, {
1514
settings: {
1615
...mockSettings,
1716
},
@@ -22,15 +21,16 @@ describe('renderer/components/AllRead.tsx', () => {
2221
});
2322

2423
it('should render itself & its children - with filters', async () => {
25-
useFiltersStore.setState({ reasons: ['author'] });
26-
27-
let tree: ReturnType<typeof renderWithAppContext> | null = null;
24+
let tree: ReturnType<typeof renderWithProviders> | null = null;
2825

2926
await act(async () => {
30-
tree = renderWithAppContext(<AllRead />, {
27+
tree = renderWithProviders(<AllRead />, {
3128
settings: {
3229
...mockSettings,
3330
},
31+
filters: {
32+
reasons: ['author'],
33+
},
3434
});
3535
});
3636

src/renderer/components/GlobalShortcuts.test.tsx

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import userEvent from '@testing-library/user-event';
22

3-
import { navigateMock, renderWithAppContext } from '../__helpers__/test-utils';
3+
import { navigateMock, renderWithProviders } from '../__helpers__/test-utils';
44

55
import * as comms from '../utils/system/comms';
66
import * as links from '../utils/system/links';
@@ -14,7 +14,7 @@ describe('components/GlobalShortcuts.tsx', () => {
1414
describe('key bindings', () => {
1515
describe('ignores keys that are not valid', () => {
1616
it('ignores B key', async () => {
17-
renderWithAppContext(<GlobalShortcuts />);
17+
renderWithProviders(<GlobalShortcuts />);
1818

1919
await userEvent.keyboard('b');
2020

@@ -24,7 +24,7 @@ describe('components/GlobalShortcuts.tsx', () => {
2424

2525
describe('home', () => {
2626
it('navigates home when pressing H key', async () => {
27-
renderWithAppContext(<GlobalShortcuts />);
27+
renderWithProviders(<GlobalShortcuts />);
2828

2929
await userEvent.keyboard('h');
3030

@@ -38,7 +38,7 @@ describe('components/GlobalShortcuts.tsx', () => {
3838
.mockImplementation(vi.fn());
3939

4040
it('opens primary account GitHub notifications webpage when pressing N while logged in', async () => {
41-
renderWithAppContext(<GlobalShortcuts />, {
41+
renderWithProviders(<GlobalShortcuts />, {
4242
isLoggedIn: true,
4343
});
4444

@@ -48,7 +48,7 @@ describe('components/GlobalShortcuts.tsx', () => {
4848
});
4949

5050
it('does not open primary account GitHub notifications webpage when logged out', async () => {
51-
renderWithAppContext(<GlobalShortcuts />, {
51+
renderWithProviders(<GlobalShortcuts />, {
5252
isLoggedIn: false,
5353
});
5454

@@ -60,7 +60,7 @@ describe('components/GlobalShortcuts.tsx', () => {
6060

6161
describe('focus mode', () => {
6262
it('toggles focus when pressing W while logged in', async () => {
63-
renderWithAppContext(<GlobalShortcuts />, {
63+
renderWithProviders(<GlobalShortcuts />, {
6464
updateSetting: updateSettingMock,
6565
isLoggedIn: true,
6666
});
@@ -71,7 +71,7 @@ describe('components/GlobalShortcuts.tsx', () => {
7171
});
7272

7373
it('does not toggle focus mode when loading', async () => {
74-
renderWithAppContext(<GlobalShortcuts />, {
74+
renderWithProviders(<GlobalShortcuts />, {
7575
updateSetting: updateSettingMock,
7676
status: 'loading',
7777
isLoggedIn: true,
@@ -83,7 +83,7 @@ describe('components/GlobalShortcuts.tsx', () => {
8383
});
8484

8585
it('does not toggle focus mode when logged out', async () => {
86-
renderWithAppContext(<GlobalShortcuts />, {
86+
renderWithProviders(<GlobalShortcuts />, {
8787
updateSetting: updateSettingMock,
8888
isLoggedIn: false,
8989
});
@@ -96,7 +96,7 @@ describe('components/GlobalShortcuts.tsx', () => {
9696

9797
describe('filters', () => {
9898
it('toggles filters when pressing F while logged in', async () => {
99-
renderWithAppContext(<GlobalShortcuts />, {
99+
renderWithProviders(<GlobalShortcuts />, {
100100
isLoggedIn: true,
101101
});
102102

@@ -106,7 +106,7 @@ describe('components/GlobalShortcuts.tsx', () => {
106106
});
107107

108108
it('does not toggle filters when logged out', async () => {
109-
renderWithAppContext(<GlobalShortcuts />, {
109+
renderWithProviders(<GlobalShortcuts />, {
110110
isLoggedIn: false,
111111
});
112112

@@ -122,7 +122,7 @@ describe('components/GlobalShortcuts.tsx', () => {
122122
.mockImplementation(vi.fn());
123123

124124
it('opens primary account GitHub issues webpage when pressing I while logged in', async () => {
125-
renderWithAppContext(<GlobalShortcuts />, {
125+
renderWithProviders(<GlobalShortcuts />, {
126126
isLoggedIn: true,
127127
});
128128

@@ -132,7 +132,7 @@ describe('components/GlobalShortcuts.tsx', () => {
132132
});
133133

134134
it('does not open primary account GitHub issues webpage when logged out', async () => {
135-
renderWithAppContext(<GlobalShortcuts />, {
135+
renderWithProviders(<GlobalShortcuts />, {
136136
isLoggedIn: false,
137137
});
138138

@@ -148,7 +148,7 @@ describe('components/GlobalShortcuts.tsx', () => {
148148
.mockImplementation(vi.fn());
149149

150150
it('opens primary account GitHub pull requests webpage when pressing N while logged in', async () => {
151-
renderWithAppContext(<GlobalShortcuts />, {
151+
renderWithProviders(<GlobalShortcuts />, {
152152
isLoggedIn: true,
153153
});
154154

@@ -158,7 +158,7 @@ describe('components/GlobalShortcuts.tsx', () => {
158158
});
159159

160160
it('does not open primary account GitHub pull requests webpage when logged out', async () => {
161-
renderWithAppContext(<GlobalShortcuts />, {
161+
renderWithProviders(<GlobalShortcuts />, {
162162
isLoggedIn: false,
163163
});
164164

@@ -170,7 +170,7 @@ describe('components/GlobalShortcuts.tsx', () => {
170170

171171
describe('refresh', () => {
172172
it('refreshes notifications when pressing R key', async () => {
173-
renderWithAppContext(<GlobalShortcuts />, {
173+
renderWithProviders(<GlobalShortcuts />, {
174174
fetchNotifications: fetchNotificationsMock,
175175
});
176176

@@ -181,7 +181,7 @@ describe('components/GlobalShortcuts.tsx', () => {
181181
});
182182

183183
it('does not refresh when status is loading', async () => {
184-
renderWithAppContext(<GlobalShortcuts />, {
184+
renderWithProviders(<GlobalShortcuts />, {
185185
status: 'loading',
186186
});
187187

@@ -193,7 +193,7 @@ describe('components/GlobalShortcuts.tsx', () => {
193193

194194
describe('settings', () => {
195195
it('toggles settings when pressing S while logged in', async () => {
196-
renderWithAppContext(<GlobalShortcuts />, {
196+
renderWithProviders(<GlobalShortcuts />, {
197197
isLoggedIn: true,
198198
});
199199

@@ -203,7 +203,7 @@ describe('components/GlobalShortcuts.tsx', () => {
203203
});
204204

205205
it('does not toggle settings when logged out', async () => {
206-
renderWithAppContext(<GlobalShortcuts />, {
206+
renderWithProviders(<GlobalShortcuts />, {
207207
isLoggedIn: false,
208208
});
209209

@@ -215,7 +215,7 @@ describe('components/GlobalShortcuts.tsx', () => {
215215

216216
describe('accounts', () => {
217217
it('navigates to accounts when pressing A on settings route', async () => {
218-
renderWithAppContext(<GlobalShortcuts />, {
218+
renderWithProviders(<GlobalShortcuts />, {
219219
initialEntries: ['/settings'],
220220
isLoggedIn: true,
221221
});
@@ -226,7 +226,7 @@ describe('components/GlobalShortcuts.tsx', () => {
226226
});
227227

228228
it('does not trigger accounts when not on settings route', async () => {
229-
renderWithAppContext(<GlobalShortcuts />, {
229+
renderWithProviders(<GlobalShortcuts />, {
230230
isLoggedIn: true,
231231
});
232232

@@ -238,7 +238,7 @@ describe('components/GlobalShortcuts.tsx', () => {
238238

239239
describe('quit app', () => {
240240
it('quits the app when pressing Q on settings route', async () => {
241-
renderWithAppContext(<GlobalShortcuts />, {
241+
renderWithProviders(<GlobalShortcuts />, {
242242
initialEntries: ['/settings'],
243243
isLoggedIn: true,
244244
});
@@ -249,7 +249,7 @@ describe('components/GlobalShortcuts.tsx', () => {
249249
});
250250

251251
it('does not quit the app when not on settings route', async () => {
252-
renderWithAppContext(<GlobalShortcuts />, {
252+
renderWithProviders(<GlobalShortcuts />, {
253253
isLoggedIn: true,
254254
});
255255

@@ -261,7 +261,7 @@ describe('components/GlobalShortcuts.tsx', () => {
261261

262262
describe('modifiers', () => {
263263
it('ignores shortcuts when typing in an input', async () => {
264-
renderWithAppContext(
264+
renderWithProviders(
265265
<>
266266
<GlobalShortcuts />
267267
<input id="test-input" />
@@ -281,7 +281,7 @@ describe('components/GlobalShortcuts.tsx', () => {
281281
});
282282

283283
it('ignores shortcuts when typing in a textarea', async () => {
284-
renderWithAppContext(
284+
renderWithProviders(
285285
<>
286286
<GlobalShortcuts />
287287
<textarea id="test-textarea" />
@@ -301,7 +301,7 @@ describe('components/GlobalShortcuts.tsx', () => {
301301
});
302302

303303
it('ignores shortcuts when modifier keys are pressed', async () => {
304-
renderWithAppContext(<GlobalShortcuts />, {
304+
renderWithProviders(<GlobalShortcuts />, {
305305
isLoggedIn: true,
306306
});
307307

src/renderer/components/Oops.test.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event';
33

44
import { PersonIcon } from '@primer/octicons-react';
55

6-
import { navigateMock, renderWithAppContext } from '../__helpers__/test-utils';
6+
import { navigateMock, renderWithProviders } from '../__helpers__/test-utils';
77

88
import { Oops } from './Oops';
99

@@ -15,20 +15,20 @@ describe('renderer/components/Oops.tsx', () => {
1515
emojis: ['🔥'],
1616
};
1717

18-
let tree: ReturnType<typeof renderWithAppContext> | null = null;
18+
let tree: ReturnType<typeof renderWithProviders> | null = null;
1919

2020
await act(async () => {
21-
tree = renderWithAppContext(<Oops error={mockError} />);
21+
tree = renderWithProviders(<Oops error={mockError} />);
2222
});
2323

2424
expect(tree.container).toMatchSnapshot();
2525
});
2626

2727
it('should render itself & its children - fallback to unknown error', async () => {
28-
let tree: ReturnType<typeof renderWithAppContext> | null = null;
28+
let tree: ReturnType<typeof renderWithProviders> | null = null;
2929

3030
await act(async () => {
31-
tree = renderWithAppContext(<Oops error={null} />);
31+
tree = renderWithProviders(<Oops error={null} />);
3232
});
3333

3434
expect(tree.container).toMatchSnapshot();
@@ -49,7 +49,7 @@ describe('renderer/components/Oops.tsx', () => {
4949
],
5050
};
5151

52-
renderWithAppContext(<Oops error={mockError} />);
52+
renderWithProviders(<Oops error={mockError} />);
5353

5454
await userEvent.click(screen.getByText('Go somewhere'));
5555

0 commit comments

Comments
 (0)