test(worker): Account — fill gaps + lifecycle test
This commit is contained in:
@@ -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();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
Reference in New Issue
Block a user