aa23a263fe
- 移除 react-i18next、i18next 及相关依赖
- 删除旧的 i18n/ 目录和 useLazyTranslation 工具
- 新增 utils/chromeI18n.ts 类型安全 wrapper(useI18n Hook + getMessage)
- 生成 public/_locales/{zh,en}/messages.json(298 个翻译 key)
- 批量更新 39+ 组件文件的导入和翻译调用
- 转换翻译键格式:namespace:key → namespace_key
- 修复 ErrorBoundary/PageErrorBoundary 从 withTranslation HOC 改为直接调用 getMessage
- 更新 vitest.setup.ts mock 加载实际翻译文本
- 修复 11 个测试文件的断言以匹配中文翻译
- TypeScript、ESLint、547 项测试全部通过
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
126 lines
3.6 KiB
TypeScript
126 lines
3.6 KiB
TypeScript
import { describe, expect, it, vi, beforeEach } from 'vitest';
|
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
import App from '../App';
|
|
import { storageUtil } from '@/utils/chromeStorage';
|
|
import {
|
|
getDefaultVisibleFeatureKeys,
|
|
getDefaultPageOrder,
|
|
getFeatureByKey,
|
|
} from '@/config/features';
|
|
import { getMessage } from '@/utils/chromeI18n';
|
|
|
|
// Mock storageUtil
|
|
vi.mock('@/utils/chromeStorage', () => ({
|
|
storageUtil: {
|
|
get: vi.fn(),
|
|
set: vi.fn(() => Promise.resolve()),
|
|
},
|
|
}));
|
|
|
|
describe('Options App', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
localStorage.clear();
|
|
});
|
|
|
|
it('合法数据应正常加载并显示正确的功能列表', async () => {
|
|
const defaultOrder = getDefaultPageOrder();
|
|
|
|
(storageUtil.get as any).mockImplementation((_key: string, defaultValue: any) =>
|
|
Promise.resolve(defaultValue),
|
|
);
|
|
|
|
render(<App />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
|
|
});
|
|
|
|
// 验证默认可见的功能都被渲染出来了
|
|
for (const key of defaultOrder) {
|
|
const feature = getFeatureByKey(key);
|
|
if (feature) {
|
|
expect(screen.getByText(getMessage(feature.labelKey))).toBeInTheDocument();
|
|
}
|
|
}
|
|
});
|
|
|
|
it('非法 visiblePages 数据应回退到默认值', async () => {
|
|
const defaultVisible = getDefaultVisibleFeatureKeys();
|
|
|
|
(storageUtil.get as any).mockImplementation((key: string, defaultValue: any) => {
|
|
if (key.includes('VisiblePages')) {
|
|
return Promise.resolve(['invalidPage', 'anotherInvalid']);
|
|
}
|
|
return Promise.resolve(defaultValue);
|
|
});
|
|
|
|
render(<App />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
|
|
});
|
|
|
|
// 验证默认值的功能仍然被渲染(非法数据被回退)
|
|
for (const key of defaultVisible) {
|
|
const feature = getFeatureByKey(key);
|
|
if (feature && key !== 'dashboard') {
|
|
expect(screen.getByText(getMessage(feature.labelKey))).toBeInTheDocument();
|
|
}
|
|
}
|
|
});
|
|
|
|
it('非法 pageOrder 数据应回退到默认值', async () => {
|
|
const defaultOrder = getDefaultPageOrder();
|
|
|
|
(storageUtil.get as any).mockImplementation((key: string, defaultValue: any) => {
|
|
if (key.includes('PageOrder')) {
|
|
return Promise.resolve(['notARealPage', 123, null]);
|
|
}
|
|
return Promise.resolve(defaultValue);
|
|
});
|
|
|
|
render(<App />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
|
|
});
|
|
|
|
// 验证默认顺序的功能都被渲染
|
|
for (const key of defaultOrder) {
|
|
const feature = getFeatureByKey(key);
|
|
if (feature) {
|
|
expect(screen.getByText(getMessage(feature.labelKey))).toBeInTheDocument();
|
|
}
|
|
}
|
|
});
|
|
|
|
it('非数组数据应回退到默认值', async () => {
|
|
const defaultOrder = getDefaultPageOrder();
|
|
|
|
(storageUtil.get as any).mockImplementation((key: string, defaultValue: any) => {
|
|
if (key.includes('VisiblePages')) {
|
|
return Promise.resolve('not-an-array');
|
|
}
|
|
if (key.includes('PageOrder')) {
|
|
return Promise.resolve({ foo: 'bar' });
|
|
}
|
|
return Promise.resolve(defaultValue);
|
|
});
|
|
|
|
render(<App />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
|
|
});
|
|
|
|
// 验证默认功能都被渲染
|
|
for (const key of defaultOrder) {
|
|
const feature = getFeatureByKey(key);
|
|
if (feature) {
|
|
expect(screen.getByText(getMessage(feature.labelKey))).toBeInTheDocument();
|
|
}
|
|
}
|
|
});
|
|
});
|