gongxiangp2/app/admin/page.test.tsx

73 lines
4.4 KiB
TypeScript

import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { useSession } from 'next-auth/react'
import AdminPage from './page'
const push = jest.fn()
const router = { push }
const confirmAction = jest.fn()
jest.mock('next-auth/react', () => ({ useSession: jest.fn() }))
jest.mock('next/navigation', () => ({ useRouter: () => router }))
jest.mock('@/components/ConfirmActionDialog', () => ({ useConfirmActionDialog: () => ({ confirmAction, confirmActionDialog: null }) }))
jest.mock('@/components/board/MaterialsHeader', () => () => null)
jest.mock('@/components/DepartmentPermissionsTab', () => () => null)
jest.mock('@/components/admin/MaterialManagement', () => () => null)
jest.mock('@/components/admin/CategoryManagement', () => () => null)
jest.mock('@/components/admin/PublicTrafficTab', () => () => null)
jest.mock('@/components/admin/DataStatisticsTab', () => function TestDataStatisticsTab() { return <div>统计内容</div> })
jest.mock('@/components/SuperAdminsTab', () => function TestSuperAdminsTab({ onStateChange }: { onStateChange: (state: { dirty: boolean; busy: boolean }) => void }) { return <div><span>配置内容</span><button onClick={() => onStateChange({ dirty: true, busy: false })}>模拟配置草稿</button><button onClick={() => onStateChange({ dirty: true, busy: true })}>模拟保存中</button></div> })
beforeEach(() => { jest.clearAllMocks(); confirmAction.mockResolvedValue({ confirmed: false }) })
function session(role: string, isSuperAdmin: boolean) { (useSession as jest.Mock).mockReturnValue({ status: 'authenticated', data: { user: { id: 'user', role, isSuperAdmin } } }) }
test('super-admin flag grants the management entry independently of the ordinary role', async () => {
session('USER', true); render(<AdminPage />)
fireEvent.click(await screen.findByRole('button', { name: '超级管理员' }))
await screen.findByText('配置内容')
expect(push).not.toHaveBeenCalled()
})
test('ordinary administrators do not see the super-admin configuration entry', async () => {
session('ADMIN', false); render(<AdminPage />)
await screen.findByText('统计内容')
expect(screen.queryByRole('button', { name: '超级管理员' })).not.toBeInTheDocument()
})
test('ordinary users remain outside the admin page', async () => {
session('USER', false); render(<AdminPage />)
await waitFor(() => expect(push).toHaveBeenCalledWith('/'))
expect(screen.queryByRole('button', { name: '超级管理员' })).not.toBeInTheDocument()
})
test('changing top-level tabs cannot discard a configuration draft without the user choosing to leave', async () => {
session('ADMIN', true); render(<AdminPage />)
fireEvent.click(await screen.findByRole('button', { name: '超级管理员' }))
fireEvent.click(await screen.findByRole('button', { name: '模拟配置草稿' }))
fireEvent.click(screen.getByRole('button', { name: '数据统计' }))
await waitFor(() => expect(confirmAction).toHaveBeenCalledTimes(1))
expect(screen.getByText('配置内容')).toBeInTheDocument()
fireEvent.click(screen.getByRole('button', { name: '模拟保存中' }))
expect(screen.getByRole('button', { name: '数据统计' })).toBeDisabled()
})
test.each([false, true])('appearance navigation respects the unsaved configuration decision: confirmed=%s', async (confirmed) => {
session('ADMIN', true); render(<AdminPage />)
fireEvent.click(await screen.findByRole('button', { name: '超级管理员' }))
fireEvent.click(await screen.findByRole('button', { name: '模拟配置草稿' }))
confirmAction.mockResolvedValueOnce({ confirmed })
fireEvent.click(screen.getByRole('button', { name: '外观设置' }))
await waitFor(() => expect(confirmAction).toHaveBeenCalledTimes(1))
if (confirmed) {
await waitFor(() => expect(push).toHaveBeenCalledWith('/admin/settings'))
} else {
expect(push).not.toHaveBeenCalled()
expect(screen.getByText('配置内容')).toBeInTheDocument()
}
})
test('appearance navigation is blocked while a configuration save is running', async () => {
session('ADMIN', true); render(<AdminPage />)
fireEvent.click(await screen.findByRole('button', { name: '超级管理员' }))
fireEvent.click(await screen.findByRole('button', { name: '模拟保存中' }))
const appearance = screen.getByRole('button', { name: '外观设置' })
expect(appearance).toBeDisabled()
fireEvent.click(appearance)
expect(push).not.toHaveBeenCalled()
expect(confirmAction).not.toHaveBeenCalled()
})