75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { useContext } from 'react';
|
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { http, HttpResponse } from 'msw';
|
|
import { server } from '@/shared/lib/test/server';
|
|
import { SessionContext } from '@/entities/session';
|
|
import { SessionProvider } from './SessionProvider';
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
|
|
const API = '/api/v1';
|
|
|
|
function renderWithProviders(ui: React.ReactElement) {
|
|
const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
|
return render(
|
|
<QueryClientProvider client={queryClient}>
|
|
<SessionProvider>{ui}</SessionProvider>
|
|
</QueryClientProvider>,
|
|
);
|
|
}
|
|
|
|
function TestConsumer() {
|
|
const ctx = useContext(SessionContext);
|
|
if (!ctx) return <div>no context</div>;
|
|
return (
|
|
<div>
|
|
<span data-testid="session">{ctx.isAuthenticated ? 'authenticated' : 'anonymous'}</span>
|
|
<span data-testid="email">{ctx.user?.email ?? ''}</span>
|
|
<button onClick={() => ctx.login('a@b.com', 'p')}>login</button>
|
|
<button onClick={() => ctx.register('a@b.com', 'p')}>register</button>
|
|
<button onClick={() => ctx.logout()}>logout</button>
|
|
<button onClick={() => ctx.updateProfile({ name: 'New' })}>updateProfile</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
describe('SessionProvider', () => {
|
|
it('starts unauthenticated when refresh fails', async () => {
|
|
server.use(http.post(`${API}/auth/refresh`, () => new HttpResponse(null, { status: 401 })));
|
|
renderWithProviders(<TestConsumer />);
|
|
await waitFor(() => {
|
|
expect(screen.getByTestId('session')).toHaveTextContent('anonymous');
|
|
});
|
|
});
|
|
|
|
it('restores session on mount when refresh succeeds', async () => {
|
|
renderWithProviders(<TestConsumer />);
|
|
await waitFor(() => {
|
|
expect(screen.getByTestId('session')).toHaveTextContent('authenticated');
|
|
expect(screen.getByTestId('email')).toHaveTextContent('user@test.com');
|
|
});
|
|
});
|
|
|
|
it('updates state after login', async () => {
|
|
server.use(http.post(`${API}/auth/refresh`, () => new HttpResponse(null, { status: 401 })));
|
|
const user = userEvent.setup();
|
|
renderWithProviders(<TestConsumer />);
|
|
await waitFor(() => expect(screen.getByTestId('session')).toHaveTextContent('anonymous'));
|
|
await user.click(screen.getByRole('button', { name: 'login' }));
|
|
await waitFor(() => {
|
|
expect(screen.getByTestId('session')).toHaveTextContent('authenticated');
|
|
});
|
|
});
|
|
|
|
it('updates state after logout', async () => {
|
|
const user = userEvent.setup();
|
|
renderWithProviders(<TestConsumer />);
|
|
await waitFor(() => expect(screen.getByTestId('session')).toHaveTextContent('authenticated'));
|
|
await user.click(screen.getByRole('button', { name: 'logout' }));
|
|
await waitFor(() => {
|
|
expect(screen.getByTestId('session')).toHaveTextContent('anonymous');
|
|
});
|
|
});
|
|
});
|