# 全模块测试覆盖实施计划 > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** 补充所有未覆盖模块的测试,将测试覆盖率从42.57%提升到70% **Architecture:** 采用TDD方法,优先补充核心业务模块测试,确保所有页面和API功能正常 **Tech Stack:** Jest + React Testing Library + TypeScript --- ## 📊 当前状态 **当前覆盖率:** 42.57% **未覆盖模块(0%):** - 页面详情页:cases/[id], news/[slug], products/[id], services/[id], solutions - 管理后台:admin主页, content/[id], logs - 管理后台API:config, content/[id], logs, upload, users/[id] - 其他页面:privacy, terms, preview/effects - 组件:admin, analytics, effects, examples, seo --- ## 🎯 目标 **覆盖率目标:** 70% **任务总数:** 25个 **预计时间:** 2-3周 --- ## Phase 1: 页面详情页测试(提升到55%) ### Task 1: 案例详情页测试 **Files:** - Create: `src/app/(marketing)/cases/[id]/page.test.tsx` - Test: `src/app/(marketing)/cases/[id]/page.tsx` **Step 1: 查看案例详情页源码** Run: ```bash cat src/app/\(marketing\)/cases/\[id\]/page.tsx | head -100 ``` Expected: 显示案例详情页结构和功能 **Step 2: 编写案例详情页测试** Create: `src/app/(marketing)/cases/[id]/page.test.tsx` ```typescript import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; import CaseDetailPage from './page'; describe('CaseDetailPage', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('Rendering', () => { it('should render case detail page', () => { render(); const main = screen.getByRole('main'); expect(main).toBeInTheDocument(); }); it('should render case title', () => { render(); const title = screen.getByRole('heading', { level: 1 }); expect(title).toBeInTheDocument(); }); it('should render case content', () => { render(); const content = screen.getByText(/案例详情/i); expect(content).toBeInTheDocument(); }); it('should render case images', () => { render(); const images = screen.getAllByRole('img'); expect(images.length).toBeGreaterThan(0); }); it('should render related cases', () => { render(); const relatedCases = screen.getByText(/相关案例/i); expect(relatedCases).toBeInTheDocument(); }); }); describe('Navigation', () => { it('should have back to cases link', () => { render(); const backLink = screen.getByRole('link', { name: /返回/i }); expect(backLink).toBeInTheDocument(); }); }); describe('Accessibility', () => { it('should have main landmark', () => { render(); const main = screen.getByRole('main'); expect(main).toBeInTheDocument(); }); it('should have proper heading hierarchy', () => { render(); const h1 = screen.getByRole('heading', { level: 1 }); expect(h1).toBeInTheDocument(); }); }); }); ``` **Step 3: 运行测试验证通过** Run: ```bash npm run test:unit -- src/app/\(marketing\)/cases/\[id\]/page.test.tsx ``` Expected: 所有测试通过 **Step 4: 提交代码** ```bash git add src/app/\(marketing\)/cases/\[id\]/page.test.tsx git commit -m "test: add case detail page tests" ``` --- ### Task 2: 新闻详情页测试 **Files:** - Create: `src/app/(marketing)/news/[slug]/page.test.tsx` - Test: `src/app/(marketing)/news/[slug]/page.tsx` **Step 1: 查看新闻详情页源码** Run: ```bash cat src/app/\(marketing\)/news/\[slug\]/page.tsx | head -100 ``` Expected: 显示新闻详情页结构和功能 **Step 2: 编写新闻详情页测试** Create: `src/app/(marketing)/news/[slug]/page.test.tsx` ```typescript import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; import NewsDetailPage from './page'; describe('NewsDetailPage', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('Rendering', () => { it('should render news detail page', () => { render(); const main = screen.getByRole('main'); expect(main).toBeInTheDocument(); }); it('should render news title', () => { render(); const title = screen.getByRole('heading', { level: 1 }); expect(title).toBeInTheDocument(); }); it('should render news content', () => { render(); const content = screen.getByText(/新闻详情/i); expect(content).toBeInTheDocument(); }); it('should render news date', () => { render(); const date = screen.getByText(/\d{4}-\d{2}-\d{2}/); expect(date).toBeInTheDocument(); }); it('should render news category', () => { render(); const category = screen.getByText(/分类/i); expect(category).toBeInTheDocument(); }); it('should render related news', () => { render(); const relatedNews = screen.getByText(/相关新闻/i); expect(relatedNews).toBeInTheDocument(); }); }); describe('Navigation', () => { it('should have back to news link', () => { render(); const backLink = screen.getByRole('link', { name: /返回/i }); expect(backLink).toBeInTheDocument(); }); }); describe('Accessibility', () => { it('should have main landmark', () => { render(); const main = screen.getByRole('main'); expect(main).toBeInTheDocument(); }); it('should have proper heading hierarchy', () => { render(); const h1 = screen.getByRole('heading', { level: 1 }); expect(h1).toBeInTheDocument(); }); }); }); ``` **Step 3: 运行测试验证通过** Run: ```bash npm run test:unit -- src/app/\(marketing\)/news/\[slug\]/page.test.tsx ``` Expected: 所有测试通过 **Step 4: 提交代码** ```bash git add src/app/\(marketing\)/news/\[slug\]/page.test.tsx git commit -m "test: add news detail page tests" ``` --- ### Task 3-5: 产品详情页、服务详情页、解决方案页测试 (类似Task 1-2,为产品详情页、服务详情页、解决方案页添加测试) --- ## Phase 2: 管理后台页面测试(提升到60%) ### Task 6: 管理后台主页测试 **Files:** - Create: `src/app/admin/page.test.tsx` - Test: `src/app/admin/page.tsx` **Step 1: 查看管理后台主页源码** Run: ```bash cat src/app/admin/page.tsx | head -100 ``` Expected: 显示管理后台主页结构和功能 **Step 2: 编写管理后台主页测试** Create: `src/app/admin/page.test.tsx` ```typescript import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; import AdminPage from './page'; describe('AdminPage', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('Rendering', () => { it('should render admin page', () => { render(); const main = screen.getByRole('main'); expect(main).toBeInTheDocument(); }); it('should render dashboard', () => { render(); const dashboard = screen.getByText(/仪表盘/i); expect(dashboard).toBeInTheDocument(); }); it('should render statistics', () => { render(); const stats = screen.getByText(/统计/i); expect(stats).toBeInTheDocument(); }); it('should render quick actions', () => { render(); const quickActions = screen.getByText(/快捷操作/i); expect(quickActions).toBeInTheDocument(); }); }); describe('Navigation', () => { it('should have navigation menu', () => { render(); const nav = screen.getByRole('navigation'); expect(nav).toBeInTheDocument(); }); it('should have content management link', () => { render(); const contentLink = screen.getByRole('link', { name: /内容管理/i }); expect(contentLink).toBeInTheDocument(); }); it('should have user management link', () => { render(); const userLink = screen.getByRole('link', { name: /用户管理/i }); expect(userLink).toBeInTheDocument(); }); }); describe('Accessibility', () => { it('should have main landmark', () => { render(); const main = screen.getByRole('main'); expect(main).toBeInTheDocument(); }); it('should have proper heading hierarchy', () => { render(); const h1 = screen.getByRole('heading', { level: 1 }); expect(h1).toBeInTheDocument(); }); }); }); ``` **Step 3: 运行测试验证通过** Run: ```bash npm run test:unit -- src/app/admin/page.test.tsx ``` Expected: 所有测试通过 **Step 4: 提交代码** ```bash git add src/app/admin/page.test.tsx git commit -m "test: add admin main page tests" ``` --- ### Task 7-8: 内容编辑页、审计日志页测试 (类似Task 6,为内容编辑页、审计日志页添加测试) --- ## Phase 3: 管理后台API测试(提升到65%) ### Task 9: 配置管理API测试 **Files:** - Create: `src/app/api/admin/config/route.test.ts` - Test: `src/app/api/admin/config/route.ts` **Step 1: 查看配置管理API源码** Run: ```bash cat src/app/api/admin/config/route.ts | head -100 ``` Expected: 显示配置管理API结构和功能 **Step 2: 编写配置管理API测试** Create: `src/app/api/admin/config/route.test.ts` ```typescript import { GET, POST, PUT, DELETE } from './route'; import { NextRequest } from 'next/server'; describe('/api/admin/config', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('GET', () => { it('should return config list', async () => { const request = new NextRequest('http://localhost/api/admin/config'); const response = await GET(request); const data = await response.json(); expect(response.status).toBe(200); expect(data.success).toBe(true); expect(Array.isArray(data.data)).toBe(true); }); it('should return config by key', async () => { const request = new NextRequest('http://localhost/api/admin/config?key=site_name'); const response = await GET(request); const data = await response.json(); expect(response.status).toBe(200); expect(data.success).toBe(true); expect(data.data).toBeDefined(); }); }); describe('POST', () => { it('should create new config', async () => { const request = new NextRequest('http://localhost/api/admin/config', { method: 'POST', body: JSON.stringify({ key: 'test_key', value: 'test_value', category: 'test', }), }); const response = await POST(request); const data = await response.json(); expect(response.status).toBe(201); expect(data.success).toBe(true); expect(data.data.key).toBe('test_key'); }); it('should reject invalid config', async () => { const request = new NextRequest('http://localhost/api/admin/config', { method: 'POST', body: JSON.stringify({}), }); const response = await POST(request); const data = await response.json(); expect(response.status).toBe(400); expect(data.success).toBe(false); }); }); describe('PUT', () => { it('should update config', async () => { const request = new NextRequest('http://localhost/api/admin/config', { method: 'PUT', body: JSON.stringify({ key: 'test_key', value: 'updated_value', }), }); const response = await PUT(request); const data = await response.json(); expect(response.status).toBe(200); expect(data.success).toBe(true); }); }); describe('DELETE', () => { it('should delete config', async () => { const request = new NextRequest('http://localhost/api/admin/config?key=test_key', { method: 'DELETE', }); const response = await DELETE(request); const data = await response.json(); expect(response.status).toBe(200); expect(data.success).toBe(true); }); }); }); ``` **Step 3: 运行测试验证通过** Run: ```bash npm run test:unit -- src/app/api/admin/config/route.test.ts ``` Expected: 所有测试通过 **Step 4: 提交代码** ```bash git add src/app/api/admin/config/route.test.ts git commit -m "test: add config management API tests" ``` --- ### Task 10-13: 内容API、日志API、上传API、用户API测试 (类似Task 9,为其他管理后台API添加测试) --- ## Phase 4: 其他页面测试(提升到68%) ### Task 14: 隐私政策页测试 **Files:** - Create: `src/app/privacy/page.test.tsx` - Test: `src/app/privacy/page.tsx` **Step 1: 查看隐私政策页源码** Run: ```bash cat src/app/privacy/page.tsx | head -50 ``` Expected: 显示隐私政策页结构和功能 **Step 2: 编写隐私政策页测试** Create: `src/app/privacy/page.test.tsx` ```typescript import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; import PrivacyPage from './page'; describe('PrivacyPage', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('Rendering', () => { it('should render privacy page', () => { render(); const main = screen.getByRole('main'); expect(main).toBeInTheDocument(); }); it('should render privacy title', () => { render(); const title = screen.getByRole('heading', { level: 1 }); expect(title).toBeInTheDocument(); expect(title).toHaveTextContent(/隐私政策/i); }); it('should render privacy content', () => { render(); const content = screen.getByText(/隐私/i); expect(content).toBeInTheDocument(); }); }); describe('Accessibility', () => { it('should have main landmark', () => { render(); const main = screen.getByRole('main'); expect(main).toBeInTheDocument(); }); it('should have proper heading hierarchy', () => { render(); const h1 = screen.getByRole('heading', { level: 1 }); expect(h1).toBeInTheDocument(); }); }); }); ``` **Step 3: 运行测试验证通过** Run: ```bash npm run test:unit -- src/app/privacy/page.test.tsx ``` Expected: 所有测试通过 **Step 4: 提交代码** ```bash git add src/app/privacy/page.test.tsx git commit -m "test: add privacy page tests" ``` --- ### Task 15: 服务条款页测试 (类似Task 14,为服务条款页添加测试) --- ### Task 16: 特效预览页测试 **Files:** - Create: `src/app/preview/effects/page.test.tsx` - Test: `src/app/preview/effects/page.tsx` **Step 1: 查看特效预览页源码** Run: ```bash cat src/app/preview/effects/page.tsx | head -100 ``` Expected: 显示特效预览页结构和功能 **Step 2: 编写特效预览页测试** Create: `src/app/preview/effects/page.test.tsx` ```typescript import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; import EffectsPreviewPage from './page'; describe('EffectsPreviewPage', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('Rendering', () => { it('should render effects preview page', () => { render(); const main = screen.getByRole('main'); expect(main).toBeInTheDocument(); }); it('should render effects list', () => { render(); const effectsList = screen.getByRole('list'); expect(effectsList).toBeInTheDocument(); }); it('should render effect cards', () => { render(); const effectCards = screen.getAllByRole('listitem'); expect(effectCards.length).toBeGreaterThan(0); }); }); describe('Accessibility', () => { it('should have main landmark', () => { render(); const main = screen.getByRole('main'); expect(main).toBeInTheDocument(); }); }); }); ``` **Step 3: 运行测试验证通过** Run: ```bash npm run test:unit -- src/app/preview/effects/page.test.tsx ``` Expected: 所有测试通过 **Step 4: 提交代码** ```bash git add src/app/preview/effects/page.test.tsx git commit -m "test: add effects preview page tests" ``` --- ## Phase 5: 组件测试(提升到70%) ### Task 17: 管理后台组件测试 **Files:** - Create: `src/components/admin/RichTextEditor.test.tsx` - Test: `src/components/admin/RichTextEditor.tsx` **Step 1: 查看富文本编辑器组件源码** Run: ```bash cat src/components/admin/RichTextEditor.tsx | head -100 ``` Expected: 显示富文本编辑器组件结构和功能 **Step 2: 编写富文本编辑器组件测试** Create: `src/components/admin/RichTextEditor.test.tsx` ```typescript import { render, screen, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom'; import RichTextEditor from './RichTextEditor'; describe('RichTextEditor', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('Rendering', () => { it('should render editor', () => { render( {}} />); const editor = screen.getByRole('textbox'); expect(editor).toBeInTheDocument(); }); it('should render toolbar', () => { render( {}} />); const toolbar = screen.getByRole('toolbar'); expect(toolbar).toBeInTheDocument(); }); it('should render formatting buttons', () => { render( {}} />); const boldButton = screen.getByRole('button', { name: /粗体/i }); const italicButton = screen.getByRole('button', { name: /斜体/i }); expect(boldButton).toBeInTheDocument(); expect(italicButton).toBeInTheDocument(); }); }); describe('Functionality', () => { it('should call onChange when content changes', () => { const handleChange = jest.fn(); render(); const editor = screen.getByRole('textbox'); fireEvent.change(editor, { target: { value: 'test content' } }); expect(handleChange).toHaveBeenCalledWith('test content'); }); it('should display initial value', () => { render( {}} />); const editor = screen.getByRole('textbox'); expect(editor).toHaveValue('initial content'); }); }); describe('Accessibility', () => { it('should have accessible label', () => { render( {}} aria-label="Content editor" />); const editor = screen.getByLabelText('Content editor'); expect(editor).toBeInTheDocument(); }); }); }); ``` **Step 3: 运行测试验证通过** Run: ```bash npm run test:unit -- src/components/admin/RichTextEditor.test.tsx ``` Expected: 所有测试通过 **Step 4: 提交代码** ```bash git add src/components/admin/RichTextEditor.test.tsx git commit -m "test: add rich text editor component tests" ``` --- ### Task 18-21: 其他组件测试 (类似Task 17,为analytics、effects、examples、seo组件添加测试) --- ## Phase 6: 最终验证 ### Task 22: 验证覆盖率达到70% **Step 1: 运行测试覆盖率检查** Run: ```bash npm run test:unit -- --coverage --coverageReporters=text-summary ``` Expected: 覆盖率达到70%以上 **Step 2: 如果未达标,补充缺失测试** 根据覆盖率报告,补充缺失的测试用例。 --- ### Task 23: 更新覆盖率门禁 **Files:** - Modify: `jest.config.js` - Modify: `.woodpecker/quality-gate.yml` **Step 1: 更新Jest覆盖率门禁** Modify: `jest.config.js` ```javascript coverageThreshold: { global: { branches: 70, functions: 70, lines: 70, statements: 70 } } ``` **Step 2: 更新CI/CD质量门禁** Modify: `.woodpecker/quality-gate.yml` ```yaml unit-tests: image: node:18-alpine commands: - echo "=== Running unit tests with coverage ===" - npm run test:unit -- --coverage --coverageReporters=json - | COVERAGE=$(cat coverage/coverage-summary.json | grep -o '"lines":{"pct":[0-9.]*' | grep -o '[0-9.]*$') echo "Current coverage: $COVERAGE%" if [ $(echo "$COVERAGE < 70" | bc -l) -eq 1 ]; then echo "❌ Coverage $COVERAGE% is below threshold 70%" exit 1 fi echo "✅ Coverage $COVERAGE% meets threshold 70%" ``` **Step 3: 提交配置** ```bash git add jest.config.js .woodpecker/quality-gate.yml git commit -m "feat: update coverage threshold gate to 70%" ``` --- ### Task 24: 创建测试规范文档 **Files:** - Create: `docs/TESTING_GUIDELINES.md` **Step 1: 创建测试规范文档** (参考之前的测试规范文档内容) **Step 2: 提交文档** ```bash git add docs/TESTING_GUIDELINES.md git commit -m "docs: add testing guidelines" ``` --- ### Task 25: 最终验收 **Step 1: 运行完整测试套件** Run: ```bash npm run test:unit -- --coverage ``` Expected: 覆盖率达到70%以上,所有测试通过 **Step 2: 运行CI/CD流水线** Run: ```bash npm run lint && npm run typecheck && npm run test:unit ``` Expected: 所有检查通过 **Step 3: 生成最终报告** Run: ```bash npm run test:unit -- --coverage --coverageReporters=html ``` Expected: 生成HTML覆盖率报告 **Step 4: 提交最终完成标记** ```bash git add . git commit -m "feat: complete full module test coverage to 70%" git tag v1.0.0-test-coverage-70-full ``` --- ## 📊 预期成果 **Phase 1完成后:** - 测试覆盖率:≥55% - 页面详情页测试:100%覆盖 **Phase 2完成后:** - 测试覆盖率:≥60% - 管理后台页面测试:100%覆盖 **Phase 3完成后:** - 测试覆盖率:≥65% - 管理后台API测试:100%覆盖 **Phase 4完成后:** - 测试覆盖率:≥68% - 其他页面测试:100%覆盖 **Phase 5完成后:** - 测试覆盖率:≥70% - 组件测试:100%覆盖 --- ## 🎯 成功标准 1. ✅ 测试覆盖率达到70%以上 2. ✅ 所有测试通过率100% 3. ✅ 所有未覆盖模块测试完成 4. ✅ CI/CD质量门禁更新到70% 5. ✅ 测试规范文档完整 --- **计划创建完成!**