80 lines
2.5 KiB
TypeScript
80 lines
2.5 KiB
TypeScript
import { act, render, screen, waitFor } from '@testing-library/react';
|
|
import { AuthProvider, useAuth } from './auth-context';
|
|
|
|
function Probe() {
|
|
const { admin, loading, error, logout } = useAuth();
|
|
return (
|
|
<div>
|
|
<div data-testid="loading">{String(loading)}</div>
|
|
<div data-testid="admin">{admin?.email ?? 'null'}</div>
|
|
<div data-testid="error">{error ?? 'null'}</div>
|
|
<button type="button" onClick={() => void logout()}>logout</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
let fetchSpy: jest.SpyInstance;
|
|
|
|
beforeEach(() => {
|
|
fetchSpy = jest.spyOn(global, 'fetch');
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.restoreAllMocks();
|
|
});
|
|
|
|
describe('AuthProvider', () => {
|
|
it('exposes a loading state then sets admin from /api/auth/me', async () => {
|
|
fetchSpy.mockResolvedValue(
|
|
new Response(JSON.stringify({ admin: { id: 'a-1', email: 'me@x.com', role: 'OWNER', tenantId: 't1', tenantSlug: 'default', tenantName: 'Default' } }), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
}),
|
|
);
|
|
render(
|
|
<AuthProvider>
|
|
<Probe />
|
|
</AuthProvider>,
|
|
);
|
|
await waitFor(() => expect(screen.getByTestId('admin')).toHaveTextContent('me@x.com'));
|
|
expect(screen.getByTestId('loading')).toHaveTextContent('false');
|
|
});
|
|
|
|
it('sets admin to null on 401', async () => {
|
|
fetchSpy.mockResolvedValue(
|
|
new Response(JSON.stringify({ message: 'Unauthorized' }), {
|
|
status: 401,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
}),
|
|
);
|
|
render(
|
|
<AuthProvider>
|
|
<Probe />
|
|
</AuthProvider>,
|
|
);
|
|
await waitFor(() => expect(screen.getByTestId('admin')).toHaveTextContent('null'));
|
|
});
|
|
|
|
it('calls POST /api/auth/logout when logout is invoked', async () => {
|
|
fetchSpy
|
|
.mockResolvedValueOnce(
|
|
new Response(JSON.stringify({ admin: { id: 'a-1', email: 'me@x.com' } }), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
}),
|
|
)
|
|
.mockResolvedValueOnce(new Response(null, { status: 204 }));
|
|
render(
|
|
<AuthProvider>
|
|
<Probe />
|
|
</AuthProvider>,
|
|
);
|
|
await waitFor(() => expect(screen.getByTestId('admin')).toHaveTextContent('me@x.com'));
|
|
await act(async () => {
|
|
screen.getByText('logout').click();
|
|
});
|
|
await waitFor(() => expect(fetchSpy).toHaveBeenCalledWith('/api/auth/logout', expect.objectContaining({ method: 'POST' })));
|
|
expect(screen.getByTestId('admin')).toHaveTextContent('null');
|
|
});
|
|
});
|