Files
tower/apps/web/app/_lib/auth-context.test.tsx
2026-06-09 02:02:40 +05:30

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');
});
});