pegasus/frontend/src/Login.test.tsx

47 lines
1.5 KiB
TypeScript

import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import Login from './Login'
import { api } from './api'
vi.mock('./api', () => ({
api: vi.fn(),
}))
describe('Login', () => {
it('submits credentials and calls onLogin', async () => {
const apiMock = vi.mocked(api)
apiMock.mockResolvedValue({ ok: true })
const onLogin = vi.fn()
render(<Login onLogin={onLogin} />)
fireEvent.change(screen.getByPlaceholderText('username'), { target: { value: 'brad' } })
fireEvent.change(screen.getByPlaceholderText('password'), { target: { value: 'pass' } })
fireEvent.click(screen.getByRole('button', { name: 'Login' }))
await waitFor(() => {
expect(onLogin).toHaveBeenCalledTimes(1)
})
expect(apiMock).toHaveBeenCalledWith('/api/login', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ username: 'brad', password: 'pass' }),
})
})
it('shows server error when login fails', async () => {
const apiMock = vi.mocked(api)
apiMock.mockRejectedValue(new Error('invalid credentials'))
render(<Login onLogin={() => {}} />)
fireEvent.change(screen.getByPlaceholderText('username'), { target: { value: 'brad' } })
fireEvent.change(screen.getByPlaceholderText('password'), { target: { value: 'bad' } })
fireEvent.click(screen.getByRole('button', { name: 'Login' }))
expect(await screen.findByText('invalid credentials')).toBeInTheDocument()
})
})