diff --git a/frontend/tests/unit/LoginPage.validation.test.tsx b/frontend/tests/unit/LoginPage.validation.test.tsx new file mode 100644 index 0000000..53e2ab8 --- /dev/null +++ b/frontend/tests/unit/LoginPage.validation.test.tsx @@ -0,0 +1,69 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +vi.mock('../../src/api/usrApi', () => ({ + fetchCompanies: vi.fn(), + login: vi.fn(), +})); + +import { fetchCompanies, login } from '../../src/api/usrApi'; +import LoginPage from '../../src/pages/usr/Login/LoginPage'; +import { renderWithProviders } from './renderLogin'; + +const mockedFetch = fetchCompanies as unknown as ReturnType; +const mockedLogin = login as unknown as ReturnType; + +async function selectVersion(user: ReturnType, label: string) { + const combobox = screen.getByRole('combobox'); + await user.click(combobox); + const option = await screen.findByText(label); + await user.click(option); +} + +describe('LoginPage 必填校验', () => { + beforeEach(() => { + vi.clearAllMocks(); + localStorage.clear(); + mockedFetch.mockResolvedValue([ + { id: 1, sCompanyName: '甲公司', sVersion: '标准版' }, + { id: 2, sCompanyName: '乙公司', sVersion: null }, + ]); + }); + + it('blocks submit and shows required messages when empty', async () => { + renderWithProviders(); + // 等待版本加载完成 + expect(await screen.findByText('请选择版本')).toBeInTheDocument(); + const user = userEvent.setup(); + await user.click(screen.getByRole('button', { name: /登\s*录/ })); + // 校验错误文案渲染在 .ant-form-item-explain-error,逐条断言(避免与 Select placeholder 文案冲突) + await waitFor(() => { + const errors = Array.from( + document.querySelectorAll('.ant-form-item-explain-error'), + ).map((el) => el.textContent); + expect(errors).toContain('请输入用户名'); + expect(errors).toContain('请输入密码'); + expect(errors).toContain('请选择版本'); + }); + expect(mockedLogin).not.toHaveBeenCalled(); + }); + + it('submits with payload when all filled', async () => { + mockedLogin.mockReturnValue(new Promise(() => {})); // 挂起,只断言入参 + renderWithProviders(); + expect(await screen.findByText('请选择版本')).toBeInTheDocument(); + const user = userEvent.setup(); + await user.type(screen.getByPlaceholderText('请输入你的用户名'), 'admin'); + await user.type(screen.getByPlaceholderText('请输入你的密码'), 'secret'); + await selectVersion(user, '乙公司'); + await user.click(screen.getByRole('button', { name: /登\s*录/ })); + await waitFor(() => + expect(mockedLogin).toHaveBeenCalledWith({ + sUserName: 'admin', + password: 'secret', + companyId: 2, + }), + ); + }); +});