import { describe, it, expect, vi, beforeEach } from 'vitest'; import { screen, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; vi.mock('../../src/api/usrApi', () => ({ fetchCompanies: vi.fn(), login: vi.fn(), })); import { fetchCompanies } from '../../src/api/usrApi'; import LoginPage from '../../src/pages/usr/Login/LoginPage'; import { renderWithProviders } from './renderLogin'; const mockedFetch = fetchCompanies as unknown as ReturnType; describe('LoginPage 版本下拉状态机', () => { beforeEach(() => { vi.clearAllMocks(); localStorage.clear(); }); it('shows loading placeholder and disabled select while fetching', async () => { // 永不 resolve 的 promise → 保持 companiesLoading mockedFetch.mockReturnValue(new Promise(() => {})); renderWithProviders(); // loading 占位文案 expect(await screen.findByText(/加载版本中/)).toBeInTheDocument(); // Select 处禁用态 const combobox = screen.getByRole('combobox'); expect(combobox).toBeDisabled(); }); it('renders options with label rule on resolve (idle)', async () => { mockedFetch.mockResolvedValue([ { id: 1, sCompanyName: '甲公司', sVersion: '标准版' }, { id: 2, sCompanyName: '乙公司', sVersion: null }, ]); renderWithProviders(); // 加载完成后 placeholder 切到「请选择版本」 expect(await screen.findByText('请选择版本')).toBeInTheDocument(); const combobox = screen.getByRole('combobox'); await waitFor(() => expect(combobox).not.toBeDisabled()); const user = userEvent.setup(); await user.click(combobox); // 下拉项 label 规则(D8) const listbox = await screen.findByRole('listbox'); expect(within(listbox.parentElement as HTMLElement).getByText('甲公司(标准版)')).toBeInTheDocument(); expect(within(listbox.parentElement as HTMLElement).getByText('乙公司')).toBeInTheDocument(); }); it('auto-selects when single option', async () => { mockedFetch.mockResolvedValue([{ id: 7, sCompanyName: '独苗公司', sVersion: '专业版' }]); renderWithProviders(); // 单项自动选中 → 选中项 label 出现在选择框中 expect(await screen.findByText('独苗公司(专业版)')).toBeInTheDocument(); }); it('empty state when companies is empty', async () => { mockedFetch.mockResolvedValue([]); renderWithProviders(); // 轻量提示 expect(await screen.findByText('未获取到可登录版本,请联系管理员')).toBeInTheDocument(); }); it('shows error with retry when fetch fails and retry re-calls', async () => { mockedFetch.mockRejectedValueOnce(new Error('boom')); renderWithProviders(); expect(await screen.findByText('版本加载失败')).toBeInTheDocument(); const retry = screen.getByRole('button', { name: /点击重试/ }); // 重试时返回正常数据 mockedFetch.mockResolvedValueOnce([{ id: 1, sCompanyName: '甲公司', sVersion: '标准版' }]); const user = userEvent.setup(); await user.click(retry); await waitFor(() => expect(mockedFetch).toHaveBeenCalledTimes(2)); }); });