import { MemoryRouter } from 'react-router-dom' import { render, screen, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { beforeEach, describe, expect, it, vi } from 'vitest' import { AuthContext, type AuthContextValue } from '@/app/providers/auth-context' import type { AuthCapabilities, TokenBundle } from '@/types' import { BootstrapAdminPage } from './BootstrapAdminPage' const getAuthCapabilitiesMock = vi.fn<() => Promise>() const bootstrapAdminMock = vi.fn<(payload: unknown, bootstrapSecret: string) => Promise>() const onLoginSuccessMock = vi.fn<(tokenBundle: TokenBundle) => Promise>() vi.mock('@/services/auth', () => ({ getAuthCapabilities: () => getAuthCapabilitiesMock(), bootstrapAdmin: (payload: unknown, bootstrapSecret: string) => bootstrapAdminMock(payload, bootstrapSecret), })) const authContextValue: AuthContextValue = { user: null, roles: [], isAdmin: false, isAuthenticated: false, isLoading: false, onLoginSuccess: (tokenBundle) => onLoginSuccessMock(tokenBundle), logout: vi.fn(async () => {}), refreshUser: vi.fn(async () => {}), } function renderBootstrapAdminPage() { return render( , ) } describe('BootstrapAdminPage', () => { beforeEach(() => { getAuthCapabilitiesMock.mockReset() bootstrapAdminMock.mockReset() onLoginSuccessMock.mockReset() getAuthCapabilitiesMock.mockResolvedValue({ password: true, email_activation: false, email_code: false, sms_code: false, password_reset: false, admin_bootstrap_required: true, oauth_providers: [], }) bootstrapAdminMock.mockResolvedValue({ access_token: 'access-token', refresh_token: 'refresh-token', expires_in: 7200, user: { id: 1, username: 'bootstrap_admin', email: 'bootstrap_admin@example.com', phone: '', nickname: 'Bootstrap Admin', avatar: '', status: 1, }, }) onLoginSuccessMock.mockResolvedValue(undefined) }) it('renders the first-admin bootstrap form when the system has no active admin', async () => { renderBootstrapAdminPage() await waitFor(() => expect(getAuthCapabilitiesMock).toHaveBeenCalledTimes(1)) expect(screen.getByRole('heading', { name: '初始化首个管理员账号' })).toBeInTheDocument() expect(screen.getByPlaceholderText('管理员用户名')).toBeInTheDocument() expect(screen.getByPlaceholderText('引导密钥')).toBeInTheDocument() expect(screen.getByPlaceholderText('管理员密码')).toBeInTheDocument() expect(screen.getByRole('button', { name: '完成初始化并进入系统' })).toBeInTheDocument() }) it('submits the bootstrap request and hands the created session to the auth provider', async () => { const user = userEvent.setup() renderBootstrapAdminPage() await waitFor(() => expect(screen.getByPlaceholderText('管理员用户名')).toBeInTheDocument()) await user.type(screen.getByPlaceholderText('管理员用户名'), 'bootstrap_admin') await user.type(screen.getByPlaceholderText('管理员昵称(选填)'), 'Bootstrap Admin') await user.type(screen.getByPlaceholderText('管理员邮箱(选填)'), 'bootstrap_admin@example.com') await user.type(screen.getByPlaceholderText('引导密钥'), 'bootstrap-secret') await user.type(screen.getByPlaceholderText('管理员密码'), 'Bootstrap123!@#') await user.type(screen.getByPlaceholderText('确认管理员密码'), 'Bootstrap123!@#') await user.click(screen.getByRole('button', { name: '完成初始化并进入系统' })) await waitFor(() => expect(bootstrapAdminMock).toHaveBeenCalledWith( { username: 'bootstrap_admin', nickname: 'Bootstrap Admin', email: 'bootstrap_admin@example.com', password: 'Bootstrap123!@#', }, 'bootstrap-secret', ), ) await waitFor(() => expect(onLoginSuccessMock).toHaveBeenCalledWith(expect.objectContaining({ access_token: 'access-token', refresh_token: 'refresh-token', })), ) }) it('shows an informational state when admin bootstrap is already closed', async () => { getAuthCapabilitiesMock.mockResolvedValue({ password: true, email_activation: false, email_code: false, sms_code: false, password_reset: false, admin_bootstrap_required: false, oauth_providers: [], }) renderBootstrapAdminPage() expect(await screen.findByText('管理员已完成初始化')).toBeInTheDocument() expect(screen.getByRole('link', { name: '返回登录' })).toBeInTheDocument() }) })