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(
{ui}
,
);
}
function TestConsumer() {
const ctx = useContext(SessionContext);
if (!ctx) return
no context
;
return (
{ctx.isAuthenticated ? 'authenticated' : 'anonymous'}
{ctx.user?.email ?? ''}
);
}
describe('SessionProvider', () => {
it('starts unauthenticated when refresh fails', async () => {
server.use(http.post(`${API}/auth/refresh`, () => new HttpResponse(null, { status: 401 })));
renderWithProviders();
await waitFor(() => {
expect(screen.getByTestId('session')).toHaveTextContent('anonymous');
});
});
it('restores session on mount when refresh succeeds', async () => {
renderWithProviders();
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();
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();
await waitFor(() => expect(screen.getByTestId('session')).toHaveTextContent('authenticated'));
await user.click(screen.getByRole('button', { name: 'logout' }));
await waitFor(() => {
expect(screen.getByTestId('session')).toHaveTextContent('anonymous');
});
});
});