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() 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( {}} />) 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() }) })