test(worker): Account — fill gaps + lifecycle test

This commit is contained in:
Bas van Rossem
2026-07-23 14:07:14 +02:00
parent 13cbc50c4f
commit 32bdaa3e31
2 changed files with 50 additions and 0 deletions

View File

@@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import Account from './Account'; import Account from './Account';
import App from '../App';
import { AuthProvider } from '../auth/AuthContext'; import { AuthProvider } from '../auth/AuthContext';
import { apiFetch } from '../lib/api'; import { apiFetch } from '../lib/api';
import { clearToken, getToken, setToken } from '../lib/auth-storage'; import { clearToken, getToken, setToken } from '../lib/auth-storage';
@@ -25,6 +26,15 @@ function renderAccount() {
); );
} }
function renderApp() {
const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
return render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>,
);
}
describe('Account', () => { describe('Account', () => {
beforeEach(() => { beforeEach(() => {
mockedApiFetch.mockReset(); mockedApiFetch.mockReset();
@@ -44,6 +54,13 @@ describe('Account', () => {
expect(screen.getByText('worker@solelog.local')).toBeInTheDocument(); expect(screen.getByText('worker@solelog.local')).toBeInTheDocument();
}); });
it('shows the fallback message when the account cannot be loaded', async () => {
mockedApiFetch.mockResolvedValue({});
renderAccount();
expect(await screen.findByText('Kon accountgegevens niet laden.')).toBeInTheDocument();
expect(screen.queryByText('Test Werker')).not.toBeInTheDocument();
});
it('logs out: clicking Uitloggen clears the token', async () => { it('logs out: clicking Uitloggen clears the token', async () => {
setToken('tok'); setToken('tok');
const user = userEvent.setup(); const user = userEvent.setup();
@@ -51,4 +68,21 @@ describe('Account', () => {
await user.click(screen.getByRole('button', { name: 'Uitloggen' })); await user.click(screen.getByRole('button', { name: 'Uitloggen' }));
expect(getToken()).toBeNull(); expect(getToken()).toBeNull();
}); });
it('lifecycle: logging out returns to the login screen', async () => {
setToken('tok');
window.history.replaceState(null, '', '/account');
const user = userEvent.setup();
renderApp();
// On the Account screen while authenticated.
expect(await screen.findByRole('button', { name: 'Uitloggen' })).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: 'Uitloggen' }));
// Context flips to unauthenticated → the login form renders.
expect(await screen.findByText('E-mailadres')).toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'Uitloggen' })).not.toBeInTheDocument();
expect(getToken()).toBeNull();
});
}); });

View File

@@ -311,3 +311,19 @@ Guaranteed behaviors:
`"Kan de export niet openen"` when the response is not ok. `"Kan de export niet openen"` when the response is not ok.
- Lifecycle (`src/screens/History.test.tsx`): the list renders a completed session showing both its - Lifecycle (`src/screens/History.test.tsx`): the list renders a completed session showing both its
worked duration and its `Pauze` line, then the export action invokes the download path. worked duration and its `Pauze` line, then the export action invokes the download path.
## Account — worker client
Src covered (worker `apps/worker`): `src/screens/Account.tsx` — 100% stmts/branch/funcs/lines.
No `c8 ignore`s needed.
Guaranteed behaviors:
- Account renders the Dutch header (`Account`) and, once `GET /api/me` resolves, shows the signed-in
user's name and email from `useMe()`.
- The fallback message `Kon accountgegevens niet laden.` shows when the query resolves without a
`user` (and the name/email are then absent).
- Clicking `Uitloggen` calls `signOut`, which clears the stored bearer token.
- Lifecycle (`src/screens/Account.test.tsx`): from the authenticated app on the Account screen,
clicking `Uitloggen` flips the auth context to unauthenticated so the login form
(`E-mailadres`) renders and the `Uitloggen` button is gone (token cleared).