Skip to content

Commit c758145

Browse files
authored
refactor: further test suite changes (#2398)
* refactor: continued refactoring of test suite Signed-off-by: Adam Setch <[email protected]> * refactor: continued refactoring of test suite Signed-off-by: Adam Setch <[email protected]> * refactor: continued refactoring of test suite Signed-off-by: Adam Setch <[email protected]> --------- Signed-off-by: Adam Setch <[email protected]>
1 parent 34f0ca6 commit c758145

29 files changed

+697
-515
lines changed

src/main/events.test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,41 +22,41 @@ describe('main/events', () => {
2222
});
2323

2424
it('onMainEvent registers ipcMain.on listener', () => {
25-
const listener = jest.fn();
25+
const listenerMock = jest.fn();
2626
onMainEvent(
2727
EVENTS.WINDOW_SHOW,
28-
listener as unknown as (e: Electron.IpcMainEvent, d: unknown) => void,
28+
listenerMock as unknown as (e: Electron.IpcMainEvent, d: unknown) => void,
2929
);
30-
expect(onMock).toHaveBeenCalledWith(EVENTS.WINDOW_SHOW, listener);
30+
expect(onMock).toHaveBeenCalledWith(EVENTS.WINDOW_SHOW, listenerMock);
3131
});
3232

3333
it('handleMainEvent registers ipcMain.handle listener', () => {
34-
const listener = jest.fn();
34+
const listenerMock = jest.fn();
3535
handleMainEvent(
3636
EVENTS.VERSION,
37-
listener as unknown as (
37+
listenerMock as unknown as (
3838
e: Electron.IpcMainInvokeEvent,
3939
d: unknown,
4040
) => void,
4141
);
42-
expect(handleMock).toHaveBeenCalledWith(EVENTS.VERSION, listener);
42+
expect(handleMock).toHaveBeenCalledWith(EVENTS.VERSION, listenerMock);
4343
});
4444

4545
it('sendRendererEvent forwards event to webContents with data', () => {
46-
const send = jest.fn();
47-
const mb: MockMenubar = { window: { webContents: { send } } };
46+
const sendMock = jest.fn();
47+
const mb: MockMenubar = { window: { webContents: { send: sendMock } } };
4848
sendRendererEvent(
4949
mb as unknown as Menubar,
5050
EVENTS.UPDATE_ICON_TITLE,
5151
'title',
5252
);
53-
expect(send).toHaveBeenCalledWith(EVENTS.UPDATE_ICON_TITLE, 'title');
53+
expect(sendMock).toHaveBeenCalledWith(EVENTS.UPDATE_ICON_TITLE, 'title');
5454
});
5555

5656
it('sendRendererEvent forwards event without data', () => {
57-
const send = jest.fn();
58-
const mb: MockMenubar = { window: { webContents: { send } } };
57+
const sendMock = jest.fn();
58+
const mb: MockMenubar = { window: { webContents: { send: sendMock } } };
5959
sendRendererEvent(mb as unknown as Menubar, EVENTS.RESET_APP);
60-
expect(send).toHaveBeenCalledWith(EVENTS.RESET_APP, undefined);
60+
expect(sendMock).toHaveBeenCalledWith(EVENTS.RESET_APP, undefined);
6161
});
6262
});

src/main/first-run.test.ts

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,39 @@
11
import path from 'node:path';
22

3-
// Mocks
4-
const existsSync = jest.fn();
5-
const mkdirSync = jest.fn();
6-
const writeFileSync = jest.fn();
3+
const existsSyncMock = jest.fn();
4+
const mkdirSyncMock = jest.fn();
5+
const writeFileSyncMock = jest.fn();
6+
77
jest.mock('node:fs', () => ({
88
__esModule: true,
99
default: {
10-
existsSync: (...a: unknown[]) => existsSync(...a),
11-
mkdirSync: (...a: unknown[]) => mkdirSync(...a),
12-
writeFileSync: (...a: unknown[]) => writeFileSync(...a),
10+
existsSync: (...a: unknown[]) => existsSyncMock(...a),
11+
mkdirSync: (...a: unknown[]) => mkdirSyncMock(...a),
12+
writeFileSync: (...a: unknown[]) => writeFileSyncMock(...a),
1313
},
14-
existsSync: (...a: unknown[]) => existsSync(...a),
15-
mkdirSync: (...a: unknown[]) => mkdirSync(...a),
16-
writeFileSync: (...a: unknown[]) => writeFileSync(...a),
14+
existsSync: (...a: unknown[]) => existsSyncMock(...a),
15+
mkdirSync: (...a: unknown[]) => mkdirSyncMock(...a),
16+
writeFileSync: (...a: unknown[]) => writeFileSyncMock(...a),
1717
}));
1818

19-
const moveToApplicationsFolder = jest.fn();
20-
const isInApplicationsFolder = jest.fn(() => false);
21-
const getPath = jest.fn(() => '/User/Data');
19+
const moveToApplicationsFolderMock = jest.fn();
20+
const isInApplicationsFolderMock = jest.fn(() => false);
21+
const getPathMock = jest.fn(() => '/User/Data');
2222

23-
const showMessageBox = jest.fn(async () => ({ response: 0 }));
23+
const showMessageBoxMock = jest.fn(async () => ({ response: 0 }));
2424

2525
jest.mock('electron', () => ({
2626
app: {
27-
getPath: () => getPath(),
28-
isInApplicationsFolder: () => isInApplicationsFolder(),
29-
moveToApplicationsFolder: () => moveToApplicationsFolder(),
27+
getPath: () => getPathMock(),
28+
isInApplicationsFolder: () => isInApplicationsFolderMock(),
29+
moveToApplicationsFolder: () => moveToApplicationsFolderMock(),
3030
},
31-
dialog: { showMessageBox: () => showMessageBox() },
31+
dialog: { showMessageBox: () => showMessageBoxMock() },
3232
}));
3333

34-
const logError = jest.fn();
34+
const logErrorMock = jest.fn();
3535
jest.mock('../shared/logger', () => ({
36-
logError: (...a: unknown[]) => logError(...a),
36+
logError: (...a: unknown[]) => logErrorMock(...a),
3737
}));
3838

3939
let mac = true;
@@ -54,55 +54,55 @@ describe('main/first-run', () => {
5454
});
5555

5656
it('creates first-run marker when not existing and returns true', async () => {
57-
existsSync.mockReturnValueOnce(false); // marker absent
58-
existsSync.mockReturnValueOnce(false); // folder absent
57+
existsSyncMock.mockReturnValueOnce(false); // marker absent
58+
existsSyncMock.mockReturnValueOnce(false); // folder absent
5959
await onFirstRunMaybe();
60-
expect(mkdirSync).toHaveBeenCalledWith(path.dirname(configPath()));
61-
expect(writeFileSync).toHaveBeenCalledWith(configPath(), '');
60+
expect(mkdirSyncMock).toHaveBeenCalledWith(path.dirname(configPath()));
61+
expect(writeFileSyncMock).toHaveBeenCalledWith(configPath(), '');
6262
});
6363

6464
it('skips writing when marker exists', async () => {
65-
existsSync.mockReturnValueOnce(true); // marker present
65+
existsSyncMock.mockReturnValueOnce(true); // marker present
6666
await onFirstRunMaybe();
67-
expect(writeFileSync).not.toHaveBeenCalled();
68-
expect(mkdirSync).not.toHaveBeenCalled();
67+
expect(writeFileSyncMock).not.toHaveBeenCalled();
68+
expect(mkdirSyncMock).not.toHaveBeenCalled();
6969
});
7070

7171
it('handles fs write error gracefully', async () => {
72-
existsSync.mockReturnValueOnce(false); // marker absent
73-
existsSync.mockReturnValueOnce(true); // folder exists
74-
writeFileSync.mockImplementation(() => {
72+
existsSyncMock.mockReturnValueOnce(false); // marker absent
73+
existsSyncMock.mockReturnValueOnce(true); // folder exists
74+
writeFileSyncMock.mockImplementation(() => {
7575
throw new Error('fail');
7676
});
7777
await onFirstRunMaybe();
78-
expect(logError).toHaveBeenCalledWith(
78+
expect(logErrorMock).toHaveBeenCalledWith(
7979
'isFirstRun',
8080
'Unable to write firstRun file',
8181
expect.any(Error),
8282
);
8383
});
8484

8585
it('prompts and moves app on macOS when user accepts', async () => {
86-
existsSync.mockReturnValueOnce(false); // marker
87-
existsSync.mockReturnValueOnce(false); // folder
88-
showMessageBox.mockResolvedValueOnce({ response: 0 });
86+
existsSyncMock.mockReturnValueOnce(false); // marker
87+
existsSyncMock.mockReturnValueOnce(false); // folder
88+
showMessageBoxMock.mockResolvedValueOnce({ response: 0 });
8989
await onFirstRunMaybe();
90-
expect(moveToApplicationsFolder).toHaveBeenCalled();
90+
expect(moveToApplicationsFolderMock).toHaveBeenCalled();
9191
});
9292

9393
it('does not move when user declines', async () => {
94-
existsSync.mockReturnValueOnce(false);
95-
existsSync.mockReturnValueOnce(false);
96-
showMessageBox.mockResolvedValueOnce({ response: 1 });
94+
existsSyncMock.mockReturnValueOnce(false);
95+
existsSyncMock.mockReturnValueOnce(false);
96+
showMessageBoxMock.mockResolvedValueOnce({ response: 1 });
9797
await onFirstRunMaybe();
98-
expect(moveToApplicationsFolder).not.toHaveBeenCalled();
98+
expect(moveToApplicationsFolderMock).not.toHaveBeenCalled();
9999
});
100100

101101
it('skips prompt on non-macOS', async () => {
102102
mac = false;
103-
existsSync.mockReturnValueOnce(false);
104-
existsSync.mockReturnValueOnce(false);
103+
existsSyncMock.mockReturnValueOnce(false);
104+
existsSyncMock.mockReturnValueOnce(false);
105105
await onFirstRunMaybe();
106-
expect(showMessageBox).not.toHaveBeenCalled();
106+
expect(showMessageBoxMock).not.toHaveBeenCalled();
107107
});
108108
});

src/preload/index.test.ts

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
import { EVENTS } from '../shared/events';
22

33
// Mocks shared modules used inside preload
4-
const sendMainEvent = jest.fn();
5-
const invokeMainEvent = jest.fn();
6-
const onRendererEvent = jest.fn();
7-
const logError = jest.fn();
4+
const sendMainEventMock = jest.fn();
5+
const invokeMainEventMock = jest.fn();
6+
const onRendererEventMock = jest.fn();
7+
const logErrorMock = jest.fn();
88

99
jest.mock('./utils', () => ({
10-
sendMainEvent: (...args: unknown[]) => sendMainEvent(...args),
11-
invokeMainEvent: (...args: unknown[]) => invokeMainEvent(...args),
12-
onRendererEvent: (...args: unknown[]) => onRendererEvent(...args),
10+
sendMainEvent: (...args: unknown[]) => sendMainEventMock(...args),
11+
invokeMainEvent: (...args: unknown[]) => invokeMainEventMock(...args),
12+
onRendererEvent: (...args: unknown[]) => onRendererEventMock(...args),
1313
}));
1414

1515
jest.mock('../shared/logger', () => ({
16-
logError: (...args: unknown[]) => logError(...args),
16+
logError: (...args: unknown[]) => logErrorMock(...args),
1717
}));
1818

1919
// We'll reconfigure the electron mock per context isolation scenario.
20-
const exposeInMainWorld = jest.fn();
21-
const getZoomLevel = jest.fn(() => 1);
22-
const setZoomLevel = jest.fn((_level: number) => undefined);
20+
const exposeInMainWorldMock = jest.fn();
21+
const getZoomLevelMock = jest.fn(() => 1);
22+
const setZoomLevelMock = jest.fn((_level: number) => undefined);
2323

2424
jest.mock('electron', () => ({
2525
contextBridge: {
2626
exposeInMainWorld: (key: string, value: unknown) =>
27-
exposeInMainWorld(key, value),
27+
exposeInMainWorldMock(key, value),
2828
},
2929
webFrame: {
30-
getZoomLevel: () => getZoomLevel(),
31-
setZoomLevel: (level: number) => setZoomLevel(level),
30+
getZoomLevel: () => getZoomLevelMock(),
31+
setZoomLevel: (level: number) => setZoomLevelMock(level),
3232
},
3333
}));
3434

@@ -79,17 +79,17 @@ describe('preload/index', () => {
7979
const w = window as unknown as { gitify: Record<string, unknown> };
8080

8181
expect(w.gitify).toBeDefined();
82-
expect(exposeInMainWorld).not.toHaveBeenCalled();
82+
expect(exposeInMainWorldMock).not.toHaveBeenCalled();
8383
});
8484

8585
it('exposes api via contextBridge when context isolation enabled', async () => {
8686
(process as unknown as { contextIsolated?: boolean }).contextIsolated =
8787
true;
8888
await importPreload();
8989

90-
expect(exposeInMainWorld).toHaveBeenCalledTimes(1);
90+
expect(exposeInMainWorldMock).toHaveBeenCalledTimes(1);
9191

92-
const [key, api] = exposeInMainWorld.mock.calls[0];
92+
const [key, api] = exposeInMainWorldMock.mock.calls[0];
9393
expect(key).toBe('gitify');
9494
expect(api).toHaveProperty('openExternalLink');
9595
});
@@ -100,7 +100,7 @@ describe('preload/index', () => {
100100
const api = (window as unknown as { gitify: TestApi }).gitify; // casting only in test boundary
101101
api.tray.updateColor(-1);
102102

103-
expect(sendMainEvent).toHaveBeenNthCalledWith(
103+
expect(sendMainEventMock).toHaveBeenNthCalledWith(
104104
1,
105105
EVENTS.UPDATE_ICON_COLOR,
106106
-1,
@@ -113,7 +113,7 @@ describe('preload/index', () => {
113113
const api = (window as unknown as { gitify: TestApi }).gitify;
114114
api.openExternalLink('https://example.com', true);
115115

116-
expect(sendMainEvent).toHaveBeenCalledWith(EVENTS.OPEN_EXTERNAL, {
116+
expect(sendMainEventMock).toHaveBeenCalledWith(EVENTS.OPEN_EXTERNAL, {
117117
url: 'https://example.com',
118118
activate: true,
119119
});
@@ -135,7 +135,7 @@ describe('preload/index', () => {
135135
const originalEnv = process.env.NODE_ENV;
136136
process.env.NODE_ENV = 'production';
137137

138-
invokeMainEvent.mockResolvedValueOnce('1.2.3');
138+
invokeMainEventMock.mockResolvedValueOnce('1.2.3');
139139

140140
await importPreload();
141141

@@ -149,19 +149,19 @@ describe('preload/index', () => {
149149
await importPreload();
150150

151151
const api = (window as unknown as { gitify: TestApi }).gitify;
152-
const callback = jest.fn();
153-
api.onSystemThemeUpdate(callback);
152+
const callbackMock = jest.fn();
153+
api.onSystemThemeUpdate(callbackMock);
154154

155-
expect(onRendererEvent).toHaveBeenCalledWith(
155+
expect(onRendererEventMock).toHaveBeenCalledWith(
156156
EVENTS.UPDATE_THEME,
157157
expect.any(Function),
158158
);
159159

160160
// Simulate event
161-
const listener = onRendererEvent.mock.calls[0][1];
161+
const listener = onRendererEventMock.mock.calls[0][1];
162162
listener({}, 'dark');
163163

164-
expect(callback).toHaveBeenCalledWith('dark');
164+
expect(callbackMock).toHaveBeenCalledWith('dark');
165165
});
166166

167167
it('raiseNativeNotification without url calls app.show', async () => {

src/preload/utils.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ describe('preload/utils', () => {
5050
});
5151

5252
it('onRendererEvent registers listener and receives emitted data', () => {
53-
const handler = jest.fn();
53+
const handlerMock = jest.fn();
5454
onRendererEvent(
5555
EVENTS.UPDATE_ICON_TITLE,
56-
handler as unknown as (
56+
handlerMock as unknown as (
5757
e: Electron.IpcRendererEvent,
5858
args: string,
5959
) => void,
@@ -65,8 +65,8 @@ describe('preload/utils', () => {
6565
).__emit(EVENTS.UPDATE_ICON_TITLE, 'payload');
6666
expect(ipcRenderer.on).toHaveBeenCalledWith(
6767
EVENTS.UPDATE_ICON_TITLE,
68-
handler,
68+
handlerMock,
6969
);
70-
expect(handler).toHaveBeenCalledWith({}, 'payload');
70+
expect(handlerMock).toHaveBeenCalledWith({}, 'payload');
7171
});
7272
});

src/renderer/__helpers__/test-utils.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export function AppContextProvider({
2626
return {
2727
auth: mockAuth,
2828
settings: mockSettings,
29+
isLoggedIn: true,
2930

3031
notifications: [],
3132

0 commit comments

Comments
 (0)