import { describe, it, expect, vi } from 'vitest' import { render, screen, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { Provider } from 'react-redux' import { MemoryRouter, Routes, Route } from 'react-router-dom' import { configureStore } from '@reduxjs/toolkit' import authReducer from '../store/slices/authSlice' import tabsReducer, { openTab } from '../store/slices/tabsSlice' import AppShell from '../components/AppShell' vi.mock('../components/NavOverlay', () => ({ default: ({ onClose }: { onClose: () => void }) => (
NavOverlay
), })) function makeStore(extraTabs = false) { const store = configureStore({ reducer: { auth: authReducer, tabs: tabsReducer } }) store.dispatch({ type: 'auth/setCredentials', payload: { accessToken: 'tok', refreshToken: 'ref', userInfo: { userId: 'u0', username: 'admin', userType: '超级管理员', language: '中文', brandId: 'b1' } }, }) if (extraTabs) { store.dispatch(openTab({ id: 'userlist', title: '用户列表', path: '/usr/users', closable: true })) } return store } function renderShell(path = '/', extraTabs = false) { const store = makeStore(extraTabs) return { store, ...render( }> MainPage} /> UserListPage} /> ), } } describe('AppShell', () => { it('renders_mainTabAndUserInfo', () => { renderShell() expect(screen.getByText('主页')).toBeInTheDocument() expect(screen.getByText(/admin/)).toBeInTheDocument() }) it('renders_openTabs', () => { renderShell('/', true) expect(screen.getByText('用户列表')).toBeInTheDocument() }) it('clickTab_navigatesToTabPath', async () => { renderShell('/', true) await userEvent.click(screen.getByText('用户列表')) await waitFor(() => expect(screen.getByText('UserListPage')).toBeInTheDocument()) }) it('closeTab_removesTabAndNavigates', async () => { renderShell('/usr/users', true) await userEvent.click(screen.getByRole('button', { name: '关闭 用户列表' })) await waitFor(() => expect(screen.queryByText('用户列表')).not.toBeInTheDocument()) expect(screen.getByText('MainPage')).toBeInTheDocument() }) it('navToggle_showsNavOverlay', async () => { renderShell() await userEvent.click(screen.getByRole('button', { name: /全部导航/ })) expect(screen.getByTestId('nav-overlay')).toBeInTheDocument() }) it('navToggle_secondClick_hidesOverlay', async () => { renderShell() await userEvent.click(screen.getByRole('button', { name: /全部导航/ })) await userEvent.click(screen.getByRole('button', { name: /全部导航/ })) expect(screen.queryByTestId('nav-overlay')).not.toBeInTheDocument() }) })