109 lines
3.9 KiB
TypeScript
109 lines
3.9 KiB
TypeScript
import { server } from '@mocks/server'
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
import {
|
|
createMemoryHistory,
|
|
createRootRoute,
|
|
createRoute,
|
|
createRouter,
|
|
RouterProvider,
|
|
} from '@tanstack/react-router'
|
|
import { render, screen, waitFor } from '@testing-library/react'
|
|
import userEvent from '@testing-library/user-event'
|
|
import { HttpResponse, http } from 'msw'
|
|
import { describe, expect, it } from 'vitest'
|
|
import { TestSessionProvider } from '@/shared/lib/test/TestSessionProvider'
|
|
import { LoginPage } from './ui/LoginPage'
|
|
|
|
const API = '/api/v1'
|
|
|
|
function loginTestRouter(initialPath: string) {
|
|
const rootRoute = createRootRoute()
|
|
const loginRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/login',
|
|
component: LoginPage,
|
|
})
|
|
const homeRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/',
|
|
component: () => <div>Home Page</div>,
|
|
})
|
|
const routeTree = rootRoute.addChildren([loginRoute, homeRoute])
|
|
const history = createMemoryHistory({ initialEntries: [initialPath] })
|
|
return createRouter({ routeTree, history })
|
|
}
|
|
|
|
function renderLoginPage(router: ReturnType<typeof loginTestRouter>) {
|
|
const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } })
|
|
return render(
|
|
<QueryClientProvider client={queryClient}>
|
|
<TestSessionProvider>
|
|
<RouterProvider router={router} />
|
|
</TestSessionProvider>
|
|
</QueryClientProvider>,
|
|
)
|
|
}
|
|
|
|
describe('LoginPage', () => {
|
|
it('renders login form', async () => {
|
|
server.use(http.post(`${API}/auth/refresh`, () => new HttpResponse(null, { status: 401 })))
|
|
renderLoginPage(loginTestRouter('/login'))
|
|
expect(await screen.findByText('Вход')).toBeInTheDocument()
|
|
expect(screen.getByPlaceholderText('email@example.com')).toBeInTheDocument()
|
|
expect(screen.getByPlaceholderText('••••••••')).toBeInTheDocument()
|
|
})
|
|
|
|
it('redirects on successful login', async () => {
|
|
server.use(http.post(`${API}/auth/refresh`, () => new HttpResponse(null, { status: 401 })))
|
|
const user = userEvent.setup()
|
|
renderLoginPage(loginTestRouter('/login'))
|
|
|
|
await screen.findByText('Вход')
|
|
|
|
await user.type(screen.getByPlaceholderText('email@example.com'), 'test@test.com')
|
|
await user.type(screen.getByPlaceholderText('••••••••'), 'password')
|
|
await user.click(screen.getByRole('button', { name: 'Войти' }))
|
|
|
|
await screen.findByText('Home Page')
|
|
})
|
|
|
|
it('shows error on failed login', async () => {
|
|
server.use(
|
|
http.post(`${API}/auth/refresh`, () => new HttpResponse(null, { status: 401 })),
|
|
http.post(
|
|
`${API}/auth/login`,
|
|
() => new HttpResponse(null, { status: 401, statusText: 'Unauthorized' }),
|
|
),
|
|
)
|
|
const user = userEvent.setup()
|
|
renderLoginPage(loginTestRouter('/login'))
|
|
|
|
await screen.findByText('Вход')
|
|
|
|
await user.type(screen.getByPlaceholderText('email@example.com'), 'bad@test.com')
|
|
await user.type(screen.getByPlaceholderText('••••••••'), 'wrong')
|
|
await user.click(screen.getByRole('button', { name: 'Войти' }))
|
|
|
|
expect(await screen.findByText(/Ошибка API/)).toBeInTheDocument()
|
|
})
|
|
|
|
it('shows loading state while submitting', async () => {
|
|
server.use(
|
|
http.post(`${API}/auth/refresh`, () => new HttpResponse(null, { status: 401 })),
|
|
http.post(`${API}/auth/login`, () => new Promise(() => {})),
|
|
)
|
|
const user = userEvent.setup()
|
|
renderLoginPage(loginTestRouter('/login'))
|
|
|
|
await screen.findByText('Вход')
|
|
|
|
await user.type(screen.getByPlaceholderText('email@example.com'), 'test@test.com')
|
|
await user.type(screen.getByPlaceholderText('••••••••'), 'password')
|
|
await user.click(screen.getByRole('button', { name: 'Войти' }))
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByRole('button', { name: 'Войти' })).toBeDisabled()
|
|
})
|
|
})
|
|
})
|