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
8 changes: 4 additions & 4 deletions src/main/first-run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ import { APPLICATION } from '../shared/constants';

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

function configPath() {
return path.join('/User/Data', 'FirstRun', APPLICATION.FIRST_RUN_FOLDER);
}

describe('main/first-run', () => {
beforeEach(() => {
jest.clearAllMocks();
mac = true;
});

function configPath() {
return path.join('/User/Data', 'FirstRun', APPLICATION.FIRST_RUN_FOLDER);
}

it('creates first-run marker when not existing and returns true', async () => {
existsSync.mockReturnValueOnce(false); // marker absent
existsSync.mockReturnValueOnce(false); // folder absent
Expand Down
24 changes: 8 additions & 16 deletions src/main/menu.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ describe('main/menu.ts', () => {
/** Helper: build menu & return template (first arg passed to buildFromTemplate) */
const buildAndGetTemplate = () => {
menuBuilder.buildMenu();
return (Menu.buildFromTemplate as jest.Mock).mock.calls.slice(
return (Menu.buildFromTemplate as jest.Mock).mock.calls.at(
-1,
)[0][0] as TemplateItem[];
)[0] as TemplateItem[];
};

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

it('developer submenu click actions execute expected functions', () => {
const template = buildAndGetTemplate();
const devEntry = template.find(
(item) => item?.label === 'Developer',
) as TemplateItem;
const devEntry = template.find((item) => item?.label === 'Developer');
expect(devEntry).toBeDefined();
const submenu = devEntry.submenu;
const clickByLabel = (label: string) =>
Expand Down Expand Up @@ -218,9 +216,7 @@ describe('main/menu.ts', () => {

it('developer submenu includes expected static accelerators', () => {
const template = buildAndGetTemplate();
const devEntry = template.find(
(item) => item?.label === 'Developer',
) as TemplateItem;
const devEntry = template.find((item) => item?.label === 'Developer');
const reloadItem = devEntry.submenu.find((i) => i.role === 'reload');
expect(reloadItem?.accelerator).toBe('CommandOrControl+R');
});
Expand All @@ -239,16 +235,14 @@ describe('main/menu.ts', () => {
mb.buildMenu();
});
// Return the newest template captured
return (Menu.buildFromTemplate as jest.Mock).mock.calls.slice(
return (Menu.buildFromTemplate as jest.Mock).mock.calls.at(
-1,
)[0][0] as TemplateItem[];
)[0] as TemplateItem[];
};

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

it('uses non-mac accelerator for toggleDevTools otherwise', () => {
const template = buildTemplateWithPlatform(false);
const devEntry = template.find(
(i) => i?.label === 'Developer',
) as TemplateItem;
const devEntry = template.find((item) => item?.label === 'Developer');
const toggleItem = devEntry.submenu.find(
(i) => i.role === 'toggleDevTools',
);
Expand Down
4 changes: 2 additions & 2 deletions src/main/updater.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ jest.mock('electron', () => {

// Utility to emit mocked autoUpdater events
const emit = (event: string, arg?: ListenerArgs) => {
(listeners[event] || []).forEach((cb) => {
for (const cb of listeners[event] || []) {
cb(arg);
});
}
};

// Re-import autoUpdater after mocking
Expand Down
27 changes: 27 additions & 0 deletions src/preload/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ describe('preload/index', () => {

it('exposes api on window when context isolation disabled', async () => {
await importPreload();

const w = window as unknown as { gitify: Record<string, unknown> };

expect(w.gitify).toBeDefined();
expect(exposeInMainWorld).not.toHaveBeenCalled();
});
Expand All @@ -84,16 +86,20 @@ describe('preload/index', () => {
(process as unknown as { contextIsolated?: boolean }).contextIsolated =
true;
await importPreload();

expect(exposeInMainWorld).toHaveBeenCalledTimes(1);

const [key, api] = exposeInMainWorld.mock.calls[0];
expect(key).toBe('gitify');
expect(api).toHaveProperty('openExternalLink');
});

it('tray.updateColor sends correct events', async () => {
await importPreload();

const api = (window as unknown as { gitify: TestApi }).gitify; // casting only in test boundary
api.tray.updateColor(-1);

expect(sendMainEvent).toHaveBeenNthCalledWith(
1,
EVENTS.UPDATE_ICON_COLOR,
Expand All @@ -103,8 +109,10 @@ describe('preload/index', () => {

it('openExternalLink sends event with payload', async () => {
await importPreload();

const api = (window as unknown as { gitify: TestApi }).gitify;
api.openExternalLink('https://example.com', true);

expect(sendMainEvent).toHaveBeenCalledWith(EVENTS.OPEN_EXTERNAL, {
url: 'https://example.com',
activate: true,
Expand All @@ -114,60 +122,79 @@ describe('preload/index', () => {
it('app.version returns dev in development', async () => {
const originalEnv = process.env.NODE_ENV;
process.env.NODE_ENV = 'development';

await importPreload();

const api = (window as unknown as { gitify: TestApi }).gitify;

await expect(api.app.version()).resolves.toBe('dev');
process.env.NODE_ENV = originalEnv;
});

it('app.version prefixes production version', async () => {
const originalEnv = process.env.NODE_ENV;
process.env.NODE_ENV = 'production';

invokeMainEvent.mockResolvedValueOnce('1.2.3');

await importPreload();

const api = (window as unknown as { gitify: TestApi }).gitify;

await expect(api.app.version()).resolves.toBe('v1.2.3');
process.env.NODE_ENV = originalEnv;
});

it('onSystemThemeUpdate registers listener', async () => {
await importPreload();

const api = (window as unknown as { gitify: TestApi }).gitify;
const callback = jest.fn();
api.onSystemThemeUpdate(callback);

expect(onRendererEvent).toHaveBeenCalledWith(
EVENTS.UPDATE_THEME,
expect.any(Function),
);

// Simulate event
const listener = onRendererEvent.mock.calls[0][1];
listener({}, 'dark');

expect(callback).toHaveBeenCalledWith('dark');
});

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

const api = (window as unknown as { gitify: TestApi }).gitify;
api.app.show = jest.fn();

const notification = api.raiseNativeNotification(
'Title',
'Body',
) as MockNotification;

notification.triggerClick();

expect(api.app.show).toHaveBeenCalled();
});

it('raiseNativeNotification with url hides app then opens link', async () => {
await importPreload();

const api = (window as unknown as { gitify: TestApi }).gitify;
api.app.hide = jest.fn();
api.openExternalLink = jest.fn();

const notification = api.raiseNativeNotification(
'Title',
'Body',
'https://x',
) as MockNotification;

notification.triggerClick();

expect(api.app.hide).toHaveBeenCalled();
expect(api.openExternalLink).toHaveBeenCalledWith('https://x', true);
});
Expand Down
33 changes: 19 additions & 14 deletions src/renderer/components/Sidebar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jest.mock('react-router-dom', () => ({

describe('renderer/components/Sidebar.tsx', () => {
const mockFetchNotifications = jest.fn();
const mockOpenExternalLink = jest
const openExternalLinkSpy = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

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

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

expect(mockNavigate).toHaveBeenNthCalledWith(1, '/', { replace: true });
expect(mockNavigate).toHaveBeenCalledTimes(1);
expect(mockNavigate).toHaveBeenCalledWith('/', { replace: true });
});

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

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

expect(mockOpenExternalLink).toHaveBeenCalledTimes(1);
expect(mockOpenExternalLink).toHaveBeenCalledWith(
expect(openExternalLinkSpy).toHaveBeenCalledTimes(1);
expect(openExternalLinkSpy).toHaveBeenCalledWith(
'https://github.com/notifications',
);
});
Expand Down Expand Up @@ -125,7 +126,8 @@ describe('renderer/components/Sidebar.tsx', () => {

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

expect(mockNavigate).toHaveBeenNthCalledWith(1, '/filters');
expect(mockNavigate).toHaveBeenCalledTimes(1);
expect(mockNavigate).toHaveBeenCalledWith('/filters');
});

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

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

expect(mockNavigate).toHaveBeenNthCalledWith(1, '/', { replace: true });
expect(mockNavigate).toHaveBeenCalledTimes(1);
expect(mockNavigate).toHaveBeenCalledWith('/', { replace: true });
});
});

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

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

expect(mockOpenExternalLink).toHaveBeenCalledTimes(1);
expect(mockOpenExternalLink).toHaveBeenCalledWith(
expect(openExternalLinkSpy).toHaveBeenCalledTimes(1);
expect(openExternalLinkSpy).toHaveBeenCalledWith(
'https://github.com/issues',
);
});
Expand All @@ -177,8 +180,8 @@ describe('renderer/components/Sidebar.tsx', () => {

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

expect(mockOpenExternalLink).toHaveBeenCalledTimes(1);
expect(mockOpenExternalLink).toHaveBeenCalledWith(
expect(openExternalLinkSpy).toHaveBeenCalledTimes(1);
expect(openExternalLinkSpy).toHaveBeenCalledWith(
'https://github.com/pulls',
);
});
Expand Down Expand Up @@ -235,7 +238,8 @@ describe('renderer/components/Sidebar.tsx', () => {

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

expect(mockNavigate).toHaveBeenNthCalledWith(1, '/settings');
expect(mockNavigate).toHaveBeenCalledTimes(1);
expect(mockNavigate).toHaveBeenCalledWith('/settings');
});

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

expect(mockFetchNotifications).toHaveBeenCalledTimes(1);
expect(mockNavigate).toHaveBeenNthCalledWith(1, '/', { replace: true });
expect(mockNavigate).toHaveBeenCalledTimes(1);
expect(mockNavigate).toHaveBeenCalledWith('/', { replace: true });
});
});

it('should quit the app', async () => {
const mockQuitApp = jest.spyOn(comms, 'quitApp');
const quitAppSpy = jest.spyOn(comms, 'quitApp').mockImplementation();

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

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

expect(mockQuitApp).toHaveBeenCalledTimes(1);
expect(quitAppSpy).toHaveBeenCalledTimes(1);
});
});
4 changes: 2 additions & 2 deletions src/renderer/components/avatars/AvatarWithFallback.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('renderer/components/avatars/AvatarWithFallback.tsx', () => {
renderWithAppContext(<AvatarWithFallback {...props} />);

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

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

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

// Simulate image load error (wrapped in act via fireEvent)
fireEvent.error(avatar);
Expand Down
Loading
Loading