373fc0496c
统一简化多个页面里的CopyButton调用,删除不再需要的空回调参数 * feat: 添加clearCookies函数的单元测试并修复cookie域名处理逻辑 * feat: 增强 data URI 处理,支持带参数的前缀并更新相关测试 * fix: 修正 AGENTS.md 中 TypeScript 类型检查命令的描述 * feat: 添加 settings.local.json 文件以配置 Bash 权限 * perf: 预设背景色避免 Popup 弹窗白屏闪烁 * perf: 避免图标过早实例化,传递组件引用而非 JSX 节点 * feat: 添加 useLazyTranslation 和 preloadNamespaces 函数以支持动态加载 i18n 命名空间 * feat: 使用 useLazyTranslation 替换 useTranslation 以支持懒加载翻译 * feat: 添加 PageSkeleton 组件及其测试用例以支持页面加载骨架屏 * feat: 使用骨架屏替换加载状态指示器,优化用户体验 * feat: 优化 CopyButton 组件的复制功能,添加定时器管理复制状态 * feat: 调整 chunk 大小警告阈值以优化构建性能
100 lines
3.3 KiB
TypeScript
100 lines
3.3 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { render } from '@testing-library/react';
|
|
import RouterContainer from '@/components/RouterContainer';
|
|
import { RouterProvider } from '@/providers/RouterProvider';
|
|
import { SnackbarProvider } from '@/components/GlobalSnackbar';
|
|
import type { PageType } from '@/types/storage';
|
|
import React from 'react';
|
|
|
|
const mockRouterValue = {
|
|
currentPage: 'dashboard' as PageType,
|
|
visiblePages: ['dashboard', 'timestamp'] as PageType[],
|
|
pageOrder: ['timestamp'] as PageType[],
|
|
isLoaded: true,
|
|
navigateTo: vi.fn(),
|
|
syncNavigation: vi.fn(),
|
|
goBack: vi.fn(),
|
|
setVisiblePages: vi.fn(),
|
|
setPageOrder: vi.fn(),
|
|
};
|
|
|
|
vi.mock('@/providers/RouterProvider', () => ({
|
|
useRouter: () => mockRouterValue,
|
|
RouterProvider: ({ children }: { children: React.ReactNode }) => children,
|
|
}));
|
|
|
|
describe('RouterContainer 组件', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
const renderWithProvider = (ui: React.ReactElement) => {
|
|
return render(
|
|
<SnackbarProvider>
|
|
<RouterProvider>{ui}</RouterProvider>
|
|
</SnackbarProvider>,
|
|
);
|
|
};
|
|
|
|
describe('渲染测试', () => {
|
|
it('isLoaded 为 false 时应渲染骨架屏', () => {
|
|
mockRouterValue.isLoaded = false;
|
|
const { container } = renderWithProvider(<RouterContainer />);
|
|
// 骨架屏使用 Skeleton 组件
|
|
const skeletons = container.querySelectorAll('.MuiSkeleton-root');
|
|
expect(skeletons.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('isLoaded 为 true 时应渲染页面内容', () => {
|
|
mockRouterValue.isLoaded = true;
|
|
mockRouterValue.currentPage = 'dashboard';
|
|
const { container } = renderWithProvider(<RouterContainer />);
|
|
expect(container.querySelector('.page-transition-dashboard')).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('动画类测试', () => {
|
|
it('在 dashboard 页面应应用 dashboard 动画类', () => {
|
|
mockRouterValue.currentPage = 'dashboard';
|
|
renderWithProvider(<RouterContainer />);
|
|
const box = document.querySelector('.page-transition-dashboard');
|
|
expect(box).toBeInTheDocument();
|
|
});
|
|
|
|
it('在非 dashboard 页面应应用 enter 动画类', () => {
|
|
mockRouterValue.currentPage = 'timestamp';
|
|
renderWithProvider(<RouterContainer />);
|
|
const box = document.querySelector('.page-transition-enter');
|
|
expect(box).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('路由处理测试', () => {
|
|
it('currentPage 变化时应更新', () => {
|
|
const { rerender } = renderWithProvider(<RouterContainer />);
|
|
|
|
mockRouterValue.currentPage = 'timestamp';
|
|
rerender(
|
|
<SnackbarProvider>
|
|
<RouterProvider>{<RouterContainer />}</RouterProvider>
|
|
</SnackbarProvider>,
|
|
);
|
|
|
|
const box = document.querySelector('.page-transition-enter');
|
|
expect(box).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('页面级错误隔离', () => {
|
|
it('PageErrorBoundary 应包裹在 Suspense 内层', () => {
|
|
mockRouterValue.isLoaded = true;
|
|
mockRouterValue.currentPage = 'dashboard';
|
|
const { container } = renderWithProvider(<RouterContainer />);
|
|
|
|
// 验证 RouterContainer 的 Box 结构存在
|
|
const routerBox = container.querySelector('.page-transition-dashboard');
|
|
expect(routerBox).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|