Skip to content

Commit 8e67ab4

Browse files
authored
refactor: test suites (#2397)
* refactor: test suites Signed-off-by: Adam Setch <[email protected]> * refactor: test suites Signed-off-by: Adam Setch <[email protected]> * refactor: test suites Signed-off-by: Adam Setch <[email protected]> * refactor: test suites Signed-off-by: Adam Setch <[email protected]> * refactor: test suites Signed-off-by: Adam Setch <[email protected]> * refactor: test suites Signed-off-by: Adam Setch <[email protected]> * refactor: test suites Signed-off-by: Adam Setch <[email protected]> --------- Signed-off-by: Adam Setch <[email protected]>
1 parent 206f571 commit 8e67ab4

34 files changed

+485
-423
lines changed

src/main/first-run.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,16 @@ import { APPLICATION } from '../shared/constants';
4343

4444
import { onFirstRunMaybe } from './first-run';
4545

46+
function configPath() {
47+
return path.join('/User/Data', 'FirstRun', APPLICATION.FIRST_RUN_FOLDER);
48+
}
49+
4650
describe('main/first-run', () => {
4751
beforeEach(() => {
4852
jest.clearAllMocks();
4953
mac = true;
5054
});
5155

52-
function configPath() {
53-
return path.join('/User/Data', 'FirstRun', APPLICATION.FIRST_RUN_FOLDER);
54-
}
55-
5656
it('creates first-run marker when not existing and returns true', async () => {
5757
existsSync.mockReturnValueOnce(false); // marker absent
5858
existsSync.mockReturnValueOnce(false); // folder absent

src/main/menu.test.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ describe('main/menu.ts', () => {
6262
/** Helper: build menu & return template (first arg passed to buildFromTemplate) */
6363
const buildAndGetTemplate = () => {
6464
menuBuilder.buildMenu();
65-
return (Menu.buildFromTemplate as jest.Mock).mock.calls.slice(
65+
return (Menu.buildFromTemplate as jest.Mock).mock.calls.at(
6666
-1,
67-
)[0][0] as TemplateItem[];
67+
)[0] as TemplateItem[];
6868
};
6969

7070
beforeEach(() => {
@@ -179,9 +179,7 @@ describe('main/menu.ts', () => {
179179

180180
it('developer submenu click actions execute expected functions', () => {
181181
const template = buildAndGetTemplate();
182-
const devEntry = template.find(
183-
(item) => item?.label === 'Developer',
184-
) as TemplateItem;
182+
const devEntry = template.find((item) => item?.label === 'Developer');
185183
expect(devEntry).toBeDefined();
186184
const submenu = devEntry.submenu;
187185
const clickByLabel = (label: string) =>
@@ -218,9 +216,7 @@ describe('main/menu.ts', () => {
218216

219217
it('developer submenu includes expected static accelerators', () => {
220218
const template = buildAndGetTemplate();
221-
const devEntry = template.find(
222-
(item) => item?.label === 'Developer',
223-
) as TemplateItem;
219+
const devEntry = template.find((item) => item?.label === 'Developer');
224220
const reloadItem = devEntry.submenu.find((i) => i.role === 'reload');
225221
expect(reloadItem?.accelerator).toBe('CommandOrControl+R');
226222
});
@@ -239,16 +235,14 @@ describe('main/menu.ts', () => {
239235
mb.buildMenu();
240236
});
241237
// Return the newest template captured
242-
return (Menu.buildFromTemplate as jest.Mock).mock.calls.slice(
238+
return (Menu.buildFromTemplate as jest.Mock).mock.calls.at(
243239
-1,
244-
)[0][0] as TemplateItem[];
240+
)[0] as TemplateItem[];
245241
};
246242

247243
it('uses mac accelerator for toggleDevTools when on macOS', () => {
248244
const template = buildTemplateWithPlatform(true);
249-
const devEntry = template.find(
250-
(i) => i?.label === 'Developer',
251-
) as TemplateItem;
245+
const devEntry = template.find((item) => item?.label === 'Developer');
252246
const toggleItem = devEntry.submenu.find(
253247
(i) => i.role === 'toggleDevTools',
254248
);
@@ -257,9 +251,7 @@ describe('main/menu.ts', () => {
257251

258252
it('uses non-mac accelerator for toggleDevTools otherwise', () => {
259253
const template = buildTemplateWithPlatform(false);
260-
const devEntry = template.find(
261-
(i) => i?.label === 'Developer',
262-
) as TemplateItem;
254+
const devEntry = template.find((item) => item?.label === 'Developer');
263255
const toggleItem = devEntry.submenu.find(
264256
(i) => i.role === 'toggleDevTools',
265257
);

src/main/updater.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ jest.mock('electron', () => {
4646

4747
// Utility to emit mocked autoUpdater events
4848
const emit = (event: string, arg?: ListenerArgs) => {
49-
(listeners[event] || []).forEach((cb) => {
49+
for (const cb of listeners[event] || []) {
5050
cb(arg);
51-
});
51+
}
5252
};
5353

5454
// Re-import autoUpdater after mocking

src/preload/index.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ describe('preload/index', () => {
7575

7676
it('exposes api on window when context isolation disabled', async () => {
7777
await importPreload();
78+
7879
const w = window as unknown as { gitify: Record<string, unknown> };
80+
7981
expect(w.gitify).toBeDefined();
8082
expect(exposeInMainWorld).not.toHaveBeenCalled();
8183
});
@@ -84,16 +86,20 @@ describe('preload/index', () => {
8486
(process as unknown as { contextIsolated?: boolean }).contextIsolated =
8587
true;
8688
await importPreload();
89+
8790
expect(exposeInMainWorld).toHaveBeenCalledTimes(1);
91+
8892
const [key, api] = exposeInMainWorld.mock.calls[0];
8993
expect(key).toBe('gitify');
9094
expect(api).toHaveProperty('openExternalLink');
9195
});
9296

9397
it('tray.updateColor sends correct events', async () => {
9498
await importPreload();
99+
95100
const api = (window as unknown as { gitify: TestApi }).gitify; // casting only in test boundary
96101
api.tray.updateColor(-1);
102+
97103
expect(sendMainEvent).toHaveBeenNthCalledWith(
98104
1,
99105
EVENTS.UPDATE_ICON_COLOR,
@@ -103,8 +109,10 @@ describe('preload/index', () => {
103109

104110
it('openExternalLink sends event with payload', async () => {
105111
await importPreload();
112+
106113
const api = (window as unknown as { gitify: TestApi }).gitify;
107114
api.openExternalLink('https://example.com', true);
115+
108116
expect(sendMainEvent).toHaveBeenCalledWith(EVENTS.OPEN_EXTERNAL, {
109117
url: 'https://example.com',
110118
activate: true,
@@ -114,60 +122,79 @@ describe('preload/index', () => {
114122
it('app.version returns dev in development', async () => {
115123
const originalEnv = process.env.NODE_ENV;
116124
process.env.NODE_ENV = 'development';
125+
117126
await importPreload();
127+
118128
const api = (window as unknown as { gitify: TestApi }).gitify;
129+
119130
await expect(api.app.version()).resolves.toBe('dev');
120131
process.env.NODE_ENV = originalEnv;
121132
});
122133

123134
it('app.version prefixes production version', async () => {
124135
const originalEnv = process.env.NODE_ENV;
125136
process.env.NODE_ENV = 'production';
137+
126138
invokeMainEvent.mockResolvedValueOnce('1.2.3');
139+
127140
await importPreload();
141+
128142
const api = (window as unknown as { gitify: TestApi }).gitify;
143+
129144
await expect(api.app.version()).resolves.toBe('v1.2.3');
130145
process.env.NODE_ENV = originalEnv;
131146
});
132147

133148
it('onSystemThemeUpdate registers listener', async () => {
134149
await importPreload();
150+
135151
const api = (window as unknown as { gitify: TestApi }).gitify;
136152
const callback = jest.fn();
137153
api.onSystemThemeUpdate(callback);
154+
138155
expect(onRendererEvent).toHaveBeenCalledWith(
139156
EVENTS.UPDATE_THEME,
140157
expect.any(Function),
141158
);
159+
142160
// Simulate event
143161
const listener = onRendererEvent.mock.calls[0][1];
144162
listener({}, 'dark');
163+
145164
expect(callback).toHaveBeenCalledWith('dark');
146165
});
147166

148167
it('raiseNativeNotification without url calls app.show', async () => {
149168
await importPreload();
169+
150170
const api = (window as unknown as { gitify: TestApi }).gitify;
151171
api.app.show = jest.fn();
172+
152173
const notification = api.raiseNativeNotification(
153174
'Title',
154175
'Body',
155176
) as MockNotification;
177+
156178
notification.triggerClick();
179+
157180
expect(api.app.show).toHaveBeenCalled();
158181
});
159182

160183
it('raiseNativeNotification with url hides app then opens link', async () => {
161184
await importPreload();
185+
162186
const api = (window as unknown as { gitify: TestApi }).gitify;
163187
api.app.hide = jest.fn();
164188
api.openExternalLink = jest.fn();
189+
165190
const notification = api.raiseNativeNotification(
166191
'Title',
167192
'Body',
168193
'https://x',
169194
) as MockNotification;
195+
170196
notification.triggerClick();
197+
171198
expect(api.app.hide).toHaveBeenCalled();
172199
expect(api.openExternalLink).toHaveBeenCalledWith('https://x', true);
173200
});

src/renderer/components/Sidebar.test.tsx

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jest.mock('react-router-dom', () => ({
1515

1616
describe('renderer/components/Sidebar.tsx', () => {
1717
const mockFetchNotifications = jest.fn();
18-
const mockOpenExternalLink = jest
18+
const openExternalLinkSpy = jest
1919
.spyOn(comms, 'openExternalLink')
2020
.mockImplementation();
2121

@@ -61,7 +61,8 @@ describe('renderer/components/Sidebar.tsx', () => {
6161

6262
await userEvent.click(screen.getByTestId('sidebar-home'));
6363

64-
expect(mockNavigate).toHaveBeenNthCalledWith(1, '/', { replace: true });
64+
expect(mockNavigate).toHaveBeenCalledTimes(1);
65+
expect(mockNavigate).toHaveBeenCalledWith('/', { replace: true });
6566
});
6667

6768
describe('notifications icon', () => {
@@ -77,8 +78,8 @@ describe('renderer/components/Sidebar.tsx', () => {
7778

7879
await userEvent.click(screen.getByTestId('sidebar-notifications'));
7980

80-
expect(mockOpenExternalLink).toHaveBeenCalledTimes(1);
81-
expect(mockOpenExternalLink).toHaveBeenCalledWith(
81+
expect(openExternalLinkSpy).toHaveBeenCalledTimes(1);
82+
expect(openExternalLinkSpy).toHaveBeenCalledWith(
8283
'https://github.com/notifications',
8384
);
8485
});
@@ -125,7 +126,8 @@ describe('renderer/components/Sidebar.tsx', () => {
125126

126127
await userEvent.click(screen.getByTestId('sidebar-filter-notifications'));
127128

128-
expect(mockNavigate).toHaveBeenNthCalledWith(1, '/filters');
129+
expect(mockNavigate).toHaveBeenCalledTimes(1);
130+
expect(mockNavigate).toHaveBeenCalledWith('/filters');
129131
});
130132

131133
it('go to the home if filters path already shown', async () => {
@@ -140,7 +142,8 @@ describe('renderer/components/Sidebar.tsx', () => {
140142

141143
await userEvent.click(screen.getByTestId('sidebar-filter-notifications'));
142144

143-
expect(mockNavigate).toHaveBeenNthCalledWith(1, '/', { replace: true });
145+
expect(mockNavigate).toHaveBeenCalledTimes(1);
146+
expect(mockNavigate).toHaveBeenCalledWith('/', { replace: true });
144147
});
145148
});
146149

@@ -158,8 +161,8 @@ describe('renderer/components/Sidebar.tsx', () => {
158161

159162
await userEvent.click(screen.getByTestId('sidebar-my-issues'));
160163

161-
expect(mockOpenExternalLink).toHaveBeenCalledTimes(1);
162-
expect(mockOpenExternalLink).toHaveBeenCalledWith(
164+
expect(openExternalLinkSpy).toHaveBeenCalledTimes(1);
165+
expect(openExternalLinkSpy).toHaveBeenCalledWith(
163166
'https://github.com/issues',
164167
);
165168
});
@@ -177,8 +180,8 @@ describe('renderer/components/Sidebar.tsx', () => {
177180

178181
await userEvent.click(screen.getByTestId('sidebar-my-pull-requests'));
179182

180-
expect(mockOpenExternalLink).toHaveBeenCalledTimes(1);
181-
expect(mockOpenExternalLink).toHaveBeenCalledWith(
183+
expect(openExternalLinkSpy).toHaveBeenCalledTimes(1);
184+
expect(openExternalLinkSpy).toHaveBeenCalledWith(
182185
'https://github.com/pulls',
183186
);
184187
});
@@ -235,7 +238,8 @@ describe('renderer/components/Sidebar.tsx', () => {
235238

236239
await userEvent.click(screen.getByTestId('sidebar-settings'));
237240

238-
expect(mockNavigate).toHaveBeenNthCalledWith(1, '/settings');
241+
expect(mockNavigate).toHaveBeenCalledTimes(1);
242+
expect(mockNavigate).toHaveBeenCalledWith('/settings');
239243
});
240244

241245
it('go to the home if settings path already shown', async () => {
@@ -252,12 +256,13 @@ describe('renderer/components/Sidebar.tsx', () => {
252256
await userEvent.click(screen.getByTestId('sidebar-settings'));
253257

254258
expect(mockFetchNotifications).toHaveBeenCalledTimes(1);
255-
expect(mockNavigate).toHaveBeenNthCalledWith(1, '/', { replace: true });
259+
expect(mockNavigate).toHaveBeenCalledTimes(1);
260+
expect(mockNavigate).toHaveBeenCalledWith('/', { replace: true });
256261
});
257262
});
258263

259264
it('should quit the app', async () => {
260-
const mockQuitApp = jest.spyOn(comms, 'quitApp');
265+
const quitAppSpy = jest.spyOn(comms, 'quitApp').mockImplementation();
261266

262267
renderWithAppContext(
263268
<MemoryRouter>
@@ -270,6 +275,6 @@ describe('renderer/components/Sidebar.tsx', () => {
270275

271276
await userEvent.click(screen.getByTestId('sidebar-quit'));
272277

273-
expect(mockQuitApp).toHaveBeenCalledTimes(1);
278+
expect(quitAppSpy).toHaveBeenCalledTimes(1);
274279
});
275280
});

src/renderer/components/avatars/AvatarWithFallback.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe('renderer/components/avatars/AvatarWithFallback.tsx', () => {
4848
renderWithAppContext(<AvatarWithFallback {...props} />);
4949

5050
// Find the avatar element by its alt text
51-
const avatar = screen.getByAltText('gitify-app') as HTMLImageElement;
51+
const avatar = screen.getByAltText('gitify-app');
5252

5353
// Simulate image load error (wrapped in act via fireEvent)
5454
fireEvent.error(avatar);
@@ -60,7 +60,7 @@ describe('renderer/components/avatars/AvatarWithFallback.tsx', () => {
6060
renderWithAppContext(<AvatarWithFallback {...props} userType={'Bot'} />);
6161

6262
// Find the avatar element by its alt text
63-
const avatar = screen.getByAltText('gitify-app') as HTMLImageElement;
63+
const avatar = screen.getByAltText('gitify-app');
6464

6565
// Simulate image load error (wrapped in act via fireEvent)
6666
fireEvent.error(avatar);

0 commit comments

Comments
 (0)