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
3 changes: 0 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ jobs:
cache: true
node-version-file: '.nvmrc'

- name: Check TypeScript
run: vp exec tsc --noEmit

- name: Run tests with coverage
run: vp run test

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
"electron-builder": "26.17.0",
"final-form": "5.0.1",
"graphql": "17.0.2",
"graphql-config": "5.1.8",
"happy-dom": "20.14.6",
"husky": "9.1.7",
"playwright": "1.63.0",
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/main/handlers/storage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { EVENTS } from '../../shared/events';

import { registerStorageHandlers } from './storage';

type IpcHandler = (event: unknown, ...args: unknown[]) => unknown | Promise<unknown>;
type IpcHandler = (event: unknown, ...args: unknown[]) => unknown;

const handleMock = vi.fn();

Expand Down
2 changes: 1 addition & 1 deletion src/main/lifecycle/window.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ describe('main/lifecycle/window.ts', () => {
});

it('configureWindowEvents returns early if no window', () => {
const mbNoWindow = { ...menubar, window: null };
const mbNoWindow = Object.assign({}, menubar, { window: null });

expect(() =>
configureWindowEvents(mbNoWindow as unknown as Menubar, menuBuilder),
Expand Down
7 changes: 4 additions & 3 deletions src/main/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ describe('main/utils', () => {
describe('takeScreenshot', () => {
it('writes file and logs info', async () => {
const mb = createMb();
await takeScreenshot(mb as unknown as Menubar);
expect(writeFile).toHaveBeenCalled();
takeScreenshot(mb as unknown as Menubar);

await vi.waitFor(() => expect(writeFile).toHaveBeenCalled());
const writtenPath = (writeFile.mock.calls[0] as unknown[])[0] as string;
expect(writtenPath.startsWith(path.join('/home/test'))).toBe(true);
expect(logInfoMock).toHaveBeenCalledWith(
Expand All @@ -89,7 +90,7 @@ describe('main/utils', () => {
window: { capturePage: () => Promise.reject(new Error('capture failed')) },
};

await takeScreenshot(mb as unknown as Menubar);
takeScreenshot(mb as unknown as Menubar);

await vi.waitFor(() =>
expect(logErrorMock).toHaveBeenCalledWith(
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/__helpers__/visual.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,10 @@ beforeEach(async () => {
vi.stubGlobal(
'fetch',
vi.fn(async (input: RequestInfo | URL) => {
const target =
input instanceof URL ? input.href : typeof input === 'string' ? input : input.url;
throw new Error(
`Unexpected network request in visual test: ${String(input)}. Mock the network boundary explicitly.`,
`Unexpected network request in visual test: ${target}. Mock the network boundary explicitly.`,
);
}),
);
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/__helpers__/vitest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function getRequestTarget(input: RequestInfo | URL): string {
return input.url;
}

return String(input);
return (input as Request).url;
}

function createGitifyBridgeApi(): Window['gitify'] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export const LoginWithPersonalAccessTokenForm: FC<LoginWithPersonalAccessTokenFo
...(data.username ? { username: data.username } : {}),
forge,
});
navigate('/');
void navigate('/');
} catch (err) {
rendererLogError('loginWithPersonalAccessToken', 'Failed to login with PAT', toError(err));
setErrors({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ it.each([
[DesignLanguage.CLASSIC, Theme.DARK],
[DesignLanguage.CLASSIC, Theme.LIGHT],
])('keeps label text readable in %s %s tooltips', async (designLanguage, theme) => {
const tree = await renderRoute(
const tree = renderRoute(
<div data-testid="label-metric" style={{ padding: 60 }}>
<LabelsPill labels={[{ name: 'enhancement', color: '0e8a16' }]} />
</div>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ async function renderList(
settings: Partial<SettingsState> = {},
accounts: AccountNotifications[] = [{ account, notifications, error: null }],
) {
const tree = await renderRoute(<NotificationsRoute />, {
const tree = renderRoute(<NotificationsRoute />, {
theme: Theme.LIGHT,
designLanguage: DesignLanguage.CLASSIC,
accounts: accounts.map((entry) => entry.account),
Expand Down Expand Up @@ -225,6 +225,7 @@ describe('notification list in a browser', () => {
error: { title: 'Account failed', descriptions: ['Try again'], emojis: ['🔥'] },
},
]);
// oxlint-disable-next-line typescript/await-thenable -- Vitest types omit `expect.element`'s poll promise
await expect.element(page.getByText('Account failed')).toBeVisible();
});

Expand Down Expand Up @@ -312,6 +313,7 @@ describe('notification list in a browser', () => {
finish(true);
await pending;
});
// oxlint-disable-next-line typescript/await-thenable -- Vitest types omit `expect.element`'s poll promise
await expect.element(page.getByTestId('repository-mark-as-read')).toBeVisible();
expect(scrollContainer()).toBe(scroller);
expect(document.getElementById('new-notification')?.classList.contains('opacity-0')).toBe(
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/primitives/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const Header: FC<HeaderProps> = (props: HeaderProps) => {
data-testid="header-nav-back"
icon={ArrowLeftIcon}
onClick={() => {
navigate(-1);
void navigate(-1);
if (props.fetchOnBack) {
void fetchNotifications();
}
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/hooks/useAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const useAccounts = (): AccountsState => {
// unlocks their screen, without waiting for the next scheduled interval.
useEffect(() => {
return window.gitify.onSystemWake(() => {
refetch();
void refetch();
});
}, [refetch]);

Expand Down
9 changes: 6 additions & 3 deletions src/renderer/hooks/useLogins.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('renderer/hooks/useLogins.ts', () => {
const { result } = renderLoginsHook();

await act(async () => {
result.current.loginWithDeviceFlowStart('github');
void result.current.loginWithDeviceFlowStart('github');
});

expect(startSpy).toHaveBeenCalled();
Expand Down Expand Up @@ -104,7 +104,10 @@ describe('renderer/hooks/useLogins.ts', () => {
const { result } = renderLoginsHook();

await act(async () => {
result.current.loginWithDeviceFlowPoll('github', 'session' as unknown as DeviceFlowSession);
void result.current.loginWithDeviceFlowPoll(
'github',
'session' as unknown as DeviceFlowSession,
);
});

expect(pollSpy).toHaveBeenCalledWith('session');
Expand All @@ -131,7 +134,7 @@ describe('renderer/hooks/useLogins.ts', () => {
const { result } = renderLoginsHook();

await act(async () => {
result.current.loginWithOAuthApp('github', {
void result.current.loginWithOAuthApp('github', {
clientId: 'id' as ClientID,
clientSecret: 'secret' as ClientSecret,
hostname: Constants.GITHUB_HOSTNAME,
Expand Down
8 changes: 4 additions & 4 deletions src/renderer/hooks/useNotifications.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,14 +212,14 @@ describe('renderer/hooks/useNotifications.ts', () => {
await waitFor(() => expect(result.current.status).toBe('success'));

act(() => {
result.current.refetchNotifications();
void result.current.refetchNotifications();
});
await waitFor(() => expect(result.current.status).toBe('error'));
expect(result.current.isFetching).toBe(false);

// Trigger a retry that stays unsettled.
act(() => {
result.current.refetchNotifications();
void result.current.refetchNotifications();
});

await waitFor(() => expect(result.current.isFetching).toBe(true));
Expand Down Expand Up @@ -251,7 +251,7 @@ describe('renderer/hooks/useNotifications.ts', () => {

// Trigger a background refetch that stays unsettled.
act(() => {
result.current.refetchNotifications();
void result.current.refetchNotifications();
});

await waitFor(() => expect(result.current.isFetching).toBe(true));
Expand Down Expand Up @@ -792,7 +792,7 @@ describe('renderer/hooks/useNotifications.ts', () => {

const enterpriseCount = mockMultipleAccountNotifications[1].notifications.length;

await act(() => {
act(() => {
result.current.removeAccountNotifications(mockGitHubCloudAccount);
});

Expand Down
10 changes: 5 additions & 5 deletions src/renderer/hooks/useShortcutActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ export function useShortcutActions(): { shortcuts: ShortcutConfigs } {
isAllowed: isLoggedIn,
action: () => {
if (isOnFiltersRoute) {
navigate('/', { replace: true });
void navigate('/', { replace: true });
} else {
navigate('/filters');
void navigate('/filters');
}
},
},
Expand All @@ -95,7 +95,7 @@ export function useShortcutActions(): { shortcuts: ShortcutConfigs } {
if (isLoading) {
return;
}
navigate('/', { replace: true });
void navigate('/', { replace: true });
void fetchNotifications();
},
},
Expand All @@ -104,10 +104,10 @@ export function useShortcutActions(): { shortcuts: ShortcutConfigs } {
isAllowed: isLoggedIn,
action: () => {
if (isOnSettingsRoute) {
navigate('/', { replace: true });
void navigate('/', { replace: true });
void fetchNotifications();
} else {
navigate('/settings');
void navigate('/settings');
}
},
},
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/icons/LogoIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Size } from '../types';
interface LogoIconProps {
isDark?: boolean;
onClick?: () => void;
size: Size.SMALL | Size.MEDIUM | Size.LARGE;
size?: Size.SMALL | Size.MEDIUM | Size.LARGE;
}

const LIGHT_GRADIENT_START = '#CCCCCC';
Expand Down
8 changes: 4 additions & 4 deletions src/renderer/routes/Accounts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const AccountsRoute: FC = () => {
useAccountsStore.setState({
accounts: [account, ...accounts.filter((a) => a !== account)],
});
navigate('/accounts', { replace: true });
void navigate('/accounts', { replace: true });
};

const handleRefresh = async (account: Account) => {
Expand All @@ -109,7 +109,7 @@ export const AccountsRoute: FC = () => {
}));
}

navigate('/accounts', { replace: true });
void navigate('/accounts', { replace: true });

/**
* Typically the above refresh API call completes very quickly,
Expand Down Expand Up @@ -146,7 +146,7 @@ export const AccountsRoute: FC = () => {
return;
}

navigate(loginMethod.route, {
void navigate(loginMethod.route, {
replace: true,
state: { account },
});
Expand Down Expand Up @@ -381,7 +381,7 @@ export const AccountsRoute: FC = () => {
keepMenuOpenRef.current = true;
setSelectedForge(adapter);
} else {
navigate(adapter.loginMethods[0].route, { replace: true });
void navigate(adapter.loginMethods[0].route, { replace: true });
}
}}
>
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/routes/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const LoginRoute: FC = () => {
useEffect(() => {
if (isLoggedIn) {
showWindow();
navigate('/', { replace: true });
void navigate('/', { replace: true });
}
// oxlint-disable-next-line react/exhaustive-deps -- navigate is stable
}, [isLoggedIn]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('Gitea HTTP login', () => {
headers: { 'content-type': 'application/json' },
}),
);
await renderRoute(<GiteaLoginWithPersonalAccessTokenRoute />, {
renderRoute(<GiteaLoginWithPersonalAccessTokenRoute />, {
theme: Theme.LIGHT,
designLanguage: DesignLanguage.CLASSIC,
});
Expand Down Expand Up @@ -56,15 +56,18 @@ describe('Gitea HTTP login', () => {
});

it('shows validation and API errors', async () => {
await renderRoute(<GiteaLoginWithPersonalAccessTokenRoute />, {
renderRoute(<GiteaLoginWithPersonalAccessTokenRoute />, {
theme: Theme.LIGHT,
designLanguage: DesignLanguage.CLASSIC,
});
await page.getByTestId('login-submit').click();
// oxlint-disable-next-line typescript/await-thenable -- Vitest types omit `expect.element`'s poll promise
await expect.element(page.getByText('Hostname is required')).toBeVisible();
await page.getByTestId('login-hostname').fill('http://user:secret@git.internal/path');
// oxlint-disable-next-line typescript/await-thenable -- Vitest types omit `expect.element`'s poll promise
await expect.element(page.getByTestId('login-create-token')).toBeDisabled();
await page.getByTestId('login-submit').click();
// oxlint-disable-next-line typescript/await-thenable -- Vitest types omit `expect.element`'s poll promise
await expect.element(page.getByText('Hostname format is invalid')).toBeVisible();
expect(fetch).not.toHaveBeenCalled();

Expand Down
2 changes: 1 addition & 1 deletion src/renderer/routes/github/LoginWithDeviceFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export const GitHubLoginWithDeviceFlowRoute: FC = () => {

if (token && isActive) {
await loginWithDeviceFlowComplete(forge, token, session.hostname);
navigate('/');
void navigate('/');
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/renderer/routes/github/LoginWithGitHubCLI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const GitHubLoginWithCLIRoute: FC = () => {

try {
await loginWithCli('github', hostname);
navigate('/');
void navigate('/');
} catch (err) {
rendererLogError('loginWithCli', 'Failed to login with GitHub CLI', toError(err));
setError(summarizeLoginError(err) ?? `Failed to login with GitHub CLI against ${hostname}`);
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/routes/github/LoginWithOAuthApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const GitHubLoginWithOAuthAppRoute: FC = () => {
async (data: OAuthAppFormData) => {
try {
await loginWithOAuthApp(forge, data);
navigate('/');
void navigate('/');
} catch (err) {
rendererLogError('loginWithOAuthApp', 'Failed to login with OAuth App', toError(err));
setErrors({
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/routes/routes.visual.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ const ACCESSIBILITY_THEMES = [
];

async function captureRoute(route: RouteCase, theme: Theme, designLanguage: DesignLanguage) {
await renderRoute(route.element, { ...route.state, theme, designLanguage });
renderRoute(route.element, { ...route.state, theme, designLanguage });

await expect(page.getByTestId('visual-root')).toMatchScreenshot(
`${route.name}-${theme.toLowerCase()}-${designLanguage}`,
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/utils/forges/gitea/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ describe('renderer/utils/forges/gitea/client.ts', () => {
await patchGiteaNotificationThread(httpAccount, '42');
expect(fetchMock()).toHaveBeenCalledTimes(3);
for (const [url, init] of fetchMock().mock.calls) {
expect(String(url)).toMatch(/^http:\/\/git\.internal:3000\/api\/v1\//);
expect(url as string).toMatch(/^http:\/\/git\.internal:3000\/api\/v1\//);
expect(init?.headers).toMatchObject({ Authorization: 'token decrypted' });
}
});
Expand Down
Loading
Loading