feat(TestDataGenerator): 更新规则编辑提示和警告显示逻辑

- 修改规则编辑时的 toast 提示,确保显示正确的规则名称。
- 更新 ResultPanel 组件,优化警告数量的显示逻辑,确保超过 5 条警告时正确显示剩余警告数量。
- 新增 TestDataGeneratorPage 和 ResultPanel 组件的单元测试,验证功能的正确性。
This commit is contained in:
雨霖铃
2026-06-19 20:31:59 +08:00
parent e372fc6855
commit e1b3a26a2c
5 changed files with 140 additions and 2 deletions
@@ -0,0 +1,82 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
vi.mock('../hooks/useGenerator', () => ({
useGenerator: () => ({
isGenerating: false,
progress: null,
result: null,
error: null,
generate: vi.fn(),
cancel: vi.fn(),
clearResult: vi.fn(),
}),
}));
vi.mock('@/utils/ruleStorage', () => ({
MAX_RULES: 20,
getAll: vi.fn(() => []),
save: vi.fn(),
deleteRule: vi.fn(),
duplicate: vi.fn(),
recordUse: vi.fn(),
search: vi.fn(() => []),
exportRules: vi.fn(() => '[]'),
importRules: vi.fn(() => ({ success: 0, failed: 0, errors: [] })),
}));
vi.mock('sonner', () => ({
toast: {
success: vi.fn(),
error: vi.fn(),
},
}));
import TestDataGeneratorPage from '../index';
import * as ruleStorage from '@/utils/ruleStorage';
import { toast } from 'sonner';
import type { DataRule, FieldConfig } from '@/types/testDataGenerator';
const mockedRuleStorage = vi.mocked(ruleStorage);
const mockedToast = vi.mocked(toast);
const mockFields: FieldConfig[] = [
{
id: 'field-1',
name: 'name',
generatorId: 'string',
params: {},
required: true,
nullRate: 0,
unique: false,
},
];
const mockRule: DataRule = {
id: 'rule-1',
name: '用户数据规则',
description: '测试规则',
fields: mockFields,
createdAt: Date.now(),
updatedAt: Date.now(),
useCount: 0,
};
describe('TestDataGeneratorPage', () => {
beforeEach(() => {
vi.clearAllMocks();
mockedRuleStorage.getAll.mockReturnValue([mockRule]);
});
it('编辑规则时应显示包含规则名的 toast', async () => {
const user = userEvent.setup();
render(<TestDataGeneratorPage />);
await user.click(screen.getByText('规则管理'));
await user.click(screen.getByTitle('编辑'));
expect(mockedToast.success).toHaveBeenCalledWith('正在编辑规则「用户数据规则」');
expect(mockedToast.success).not.toHaveBeenCalledWith(expect.stringContaining('{{name}}'));
});
});
@@ -84,7 +84,9 @@ export default function ResultPanel({ result }: ResultPanelProps) {
</li>
))}
{result.warnings.length > 5 && (
<li className="text-xs text-yellow-500/80">... {'还有 {{count}} 条警告'}</li>
<li className="text-xs text-yellow-500/80">
{`... 还有 ${result.warnings.length - 5} 条警告`}
</li>
)}
</ul>
</div>
@@ -0,0 +1,42 @@
import { describe, expect, it } from 'vitest';
import { render, screen } from '@testing-library/react';
import ResultPanel from '../ResultPanel';
import type { GenerateResult } from '@/types/testDataGenerator';
function createResult(overrides: Partial<GenerateResult> = {}): GenerateResult {
return {
success: true,
warnings: [],
stats: {
total: 100,
success: 100,
failed: 0,
duration: 1200,
},
...overrides,
};
}
describe('ResultPanel', () => {
it('警告超过 5 条时应显示剩余警告数量', () => {
const warnings = Array.from({ length: 8 }, (_, index) => `警告 ${index + 1}`);
render(<ResultPanel result={createResult({ warnings })} />);
expect(screen.getByText('警告 1')).toBeInTheDocument();
expect(screen.getByText('警告 5')).toBeInTheDocument();
expect(screen.queryByText('警告 6')).not.toBeInTheDocument();
expect(screen.getByText('... 还有 3 条警告')).toBeInTheDocument();
expect(screen.queryByText(/\{\{count\}\}/)).not.toBeInTheDocument();
});
it('警告不超过 5 条时不应显示剩余提示', () => {
const warnings = ['警告 1', '警告 2', '警告 3'];
render(<ResultPanel result={createResult({ warnings })} />);
expect(screen.getByText('警告 1')).toBeInTheDocument();
expect(screen.getByText('警告 3')).toBeInTheDocument();
expect(screen.queryByText(/还有 \d+ 条警告/)).not.toBeInTheDocument();
});
});
@@ -178,6 +178,18 @@ describe('RuleManager', () => {
vi.restoreAllMocks();
});
it('should call onEdit when edit button clicked', async () => {
const user = userEvent.setup();
const onEdit = vi.fn();
mockedRuleStorage.getAll.mockReturnValue([mockRule]);
render(<RuleManager {...defaultProps} onEdit={onEdit} />);
await user.click(screen.getByTitle('编辑'));
expect(onEdit).toHaveBeenCalledWith(mockRule);
});
it('should show saved rule count', () => {
mockedRuleStorage.getAll.mockReturnValue([mockRule]);
+1 -1
View File
@@ -130,7 +130,7 @@ export default function TestDataGeneratorPage() {
setEditingRule(rule);
setActiveTab('fields');
clearResult();
toast.success('正在编辑规则「{{name}}」');
toast.success(`正在编辑规则「${rule.name}`);
},
[clearResult],
);