skillhub/docs/prds/file-preview-syntax-highlighting-supplements/05-test-plan.md
XiaoSeS ee33505b7c feat: File Browser Sidebar with Preview, Security Audit UI, and Syntax Highlighting (#145)
* feat(security): extend scanner config with full analyzer options

Integrate skill-scanner's 8 analysis engines and policy configuration
into SkillHub's config system. Operators can now control behavioral,
LLM, Meta, AI Defense, VirusTotal, and trigger analyzers via
application.yml or environment variables.

Changes:
- Add Analyzers and Policy nested classes to SkillScannerProperties
- Create ScanOptions record to encapsulate analyzer flags
- Update SkillScannerService to pass options in /scan body and /scan-upload query params
- Wire ScanOptions through SkillScannerConfig and SkillScannerAdapter
- Extend application.yml with full scanner config block and env var overrides
- Update all tests to verify new configuration flow

All tests pass.

* feat(security): add domain model and integrate scan into publish flow

Add SCANNING/SCAN_FAILED status to SkillVersionStatus. Introduce
SecurityScanService, SecurityScanner port, ScanTask, SecurityAudit
and related domain types. Wire scan trigger into SkillPublishService
so non-auto-publish versions enter scanning when scanner is enabled,
falling back to review task creation when disabled.

* feat(security): add infra layer for scanner HTTP client and adapters

Add WebClient-based HttpClient abstraction with WebClientHttpClient
implementation. Add SkillScannerApiResponse record, SecurityScanException,
and SecurityAuditJpaRepository. Add webflux and test dependencies to
infra module.

* feat(security): add Redis stream consumers, audit API, and DB migration

Add AbstractStreamConsumer base class, ScanTaskConsumer for processing
scan results from Redis stream, and RedisScanTaskProducer. Add
RedisStreamConfig for stream/group initialization. Add SecurityAudit
REST controller and DTO. Add V35 Flyway migration for security_audits
table.

* feat(security): add scanner config to application profiles

Add scanner enabled flag to application-local.yml and
application-test.yml. Enable behavioral analyzer by default
in application.yml.

* feat(deploy): add skill-scanner to docker-compose and k8s manifests

Add skill-scanner service to docker-compose.yml with health check.
Add scanner k8s deployment, service, and configmap entries. Wire
scanner env vars into Makefile dev-all flow. Add verify-scanner.sh
script for post-deploy validation.

* docs(security): add scanner documentation suite

Add scanner docs: configuration guide, failure impact analysis,
monitoring guide, improvement recommendations, custom rules guide,
and skill-vetter rules conversion example. Update deployment docs
with scanner section. Add security-scanning overview and PRD.

* feat(security): add skill-vetter custom rule examples

Add example Regex and YARA rules derived from skill-vetter RED FLAGS
in scanner/examples/vetter-rules/. Includes 7 Regex rules
(signatures-append.yaml) and 3 YARA rules (skillhub_vetter.yara)
covering agent memory theft, IP-based exfiltration, and browser
data theft detection.

* feat(security): add scanner Docker build context

Add Dockerfile for cisco-ai-skill-scanner container and
.env.example with LLM configuration placeholders.

* fix(security): align Finding mapping with scanner API response schema

SkillScannerApiResponse.Finding used incorrect field names (message,
location.file, location.line, code_snippet) that did not match the
scanner's actual JSON output (description, file_path, line_number,
snippet), causing all four fields to deserialize as null.

Flatten Finding to match scanner API: remove nested Location, rename
fields to description/file_path/line_number/snippet. Add skill_name
and timestamp to SkillScannerApiResponse. Extend SecurityFinding with
remediation, analyzer, and metadata fields to capture LLM analyzer
output. Retain 8-arg compact constructor for backward compatibility.

* chore(security): add debug logging to scanner response mapping

Log raw scanner API response and mapped SecurityFinding fields
side-by-side to help verify data consistency between scanner
output and database records.

* feat(security): add multi-scanner support and soft delete for security audits

- Add ScannerType enum for type-safe scanner identification
- Update V35 migration to support multiple scanners and soft delete
- Remove CASCADE delete, use code-level soft delete (deleted_at)
- Add repository methods for querying latest audit by scanner type
- Update SecurityScanService to handle scanner type parameter
- Integrate soft delete in SkillHardDeleteService
- Update all tests to use ScannerType enum

This enables multiple scanner integrations (skill-scanner, future LLM/compliance scanners)
and preserves complete audit history through soft deletion.

* feat(security): add security audit UI to review detail and skill detail pages

Display security scan results on the review detail page (full audit
section with collapsible findings) and the skill detail sidebar (compact
summary with dialog for details).  Handles empty/404 gracefully by
returning null, avoids loading shimmer flicker, and separates lifecycle
action buttons with a visual divider.

* docs(security): add security audit UI PRD

* docs(prd): add related documents section to file browser sidebar PRD

* feat(skill): add file tree builder utility

Implement buildFileTree function to convert flat SkillFile[] into hierarchical tree structure.
- Nodes sorted alphabetically by path
- Support for nested directories
- Each node includes depth, type, and path information
- Includes comprehensive test coverage

* feat(skill): add file type detection utilities

Implement utilities for file type detection and preview capability checks:
- isPreviewable: checks if file can be previewed based on extension and size
- canPreviewFile: provides detailed reason when file cannot be previewed
- getFileTypeLabel: returns human-readable file type labels
- getFileIcon: maps file types to appropriate Lucide icons
- Supports 1MB max file size limit
- Comprehensive test coverage for all functions

* feat(skill): add file tree node component

Implement recursive FileTreeNodeComponent with:
- Expand/collapse functionality for directories
- File and directory icons from Lucide React
- Hover effects showing file sizes
- Proper indentation based on depth
- Support for nested directory structures

* refactor(skill): upgrade file tree to hierarchical structure

Replace flat file list with tree structure:
- Use buildFileTree to convert flat files into hierarchy
- Integrate FileTreeNodeComponent for rendering
- Update onFileClick to accept FileTreeNode instead of SkillFile
- Add file count badge in header
- Root-level directories expanded by default

* feat(skill): add file preview dialog component

Implement FilePreviewDialog with:
- Markdown rendering via existing MarkdownRenderer
- Plain text/code display with monospace font
- Non-previewable file message with download button
- Copy-to-clipboard and download actions in header
- File path display in footer
- Loading and error states

* feat(i18n): add file tree and preview translations

Add Chinese and English translations for:
- File browser title
- Preview error messages (load failure, too large, binary, unsupported)
- Download file button

* feat(skill): integrate file preview into skill detail page

- Add useSkillFile hook for fetching arbitrary file content
- Add file preview state, click handler, and download handler
- Pass onFileClick to FileTree for opening preview dialog
- Add FilePreviewDialog to skill detail page

* feat(review): add file reading API endpoint

Add GET /api/v1/reviews/{id}/file?path=... for reading single files
from the review-bound skill version:
- ReviewController: new endpoint with path traversal validation
- GovernanceWorkflowAppService: route method for review file access
- ReviewSkillDetailAppService: authorization and delegation
- SkillQueryService: getFileContentByVersionId for direct version access

* feat(review): integrate file preview into review detail

- Add useReviewFile hook for fetching review file content
- Add file preview state and handlers to ReviewSkillDetailSection
- Pass reviewId prop for API calls
- Add FilePreviewDialog to review detail expanded section
- Update review-detail.tsx to pass taskId as reviewId

* fix(test): update test mocks for file preview hooks

- Add useSkillFile mock to skill-detail.test.tsx
- Add useQuery mock to @tanstack/react-query mock
- Add useReviewFile mock to review-skill-detail-section.test.tsx
- Fix SkillFile test fixtures to include all required properties
- Remove unused imports in test and component files

* fix(skill): use DomainBadRequestException for version not found

Replace DomainNotFoundException with DomainBadRequestException in
getFileContentByVersionId to match existing patterns and imports.

* feat(skill): add file tree sidebar with file sizes

- Move file tree to right sidebar for persistent visibility
- Display file sizes always visible (not just on hover)
- Keep Files tab showing the same tree structure
- Add scrollable container with max-height for long file lists

* fix(skill): improve file tree sidebar UI and UX

- Remove redundant title from file tree sidebar
- Adjust scrollbar placement with proper flex layout
- Sort folders first, then files (both alphabetically)
- Collapse all folders by default for cleaner initial view
- Increase dialog width to max-w-5xl and height to 90vh
- Remove duplicate close button (X icon)
- Add hover effects to action buttons
- Use flexbox for proper content scrolling
- Allow .pyc files in backend configuration

Fixes:
1. File tree sidebar now has cleaner layout without title
2. Scrollbar properly contained within card
3. Folders appear before files in tree
4. All folders collapsed by default
5. Preview dialog wider and more usable
6. Single close method (ESC or click outside)
7. Action buttons have visual feedback on hover

* fix(skill): refine file tree sidebar and preview dialog

1. Default all folders to collapsed state
2. File tree sidebar now uses Card+bare pattern matching SecurityAuditSummary
   - Scrollbar inside the card content area instead of wrapping the tree
   - Consistent padding and header layout with other sidebar cards
3. Preview dialog close button fixed:
   - Hide DialogContent's built-in close button via [&>button]:hidden
   - Add X button in the header row, same level as copy/download
   - All action buttons share consistent hover animation (opacity transition)
4. Sort directories before files at every tree level
5. Update tests for new directory-first sort order

* feat(skill): collapsible file browser, wider dialog, button animations

1. File browser sidebar now supports expand/collapse toggle
   - Click the header row to toggle visibility
   - ChevronUp/Down icon indicates state
   - Default expanded on page load

2. File preview dialog widened to 72rem (was 5xl/64rem)
   - Uses w-[min(calc(100vw-2rem),72rem)] for responsive max

3. Header action buttons now have micro-interactions:
   - Copy/Download: scale up on hover, scale down on click
   - Close (X): rotates 90° on hover with destructive tint
   - All buttons: opacity 60→100 transition on hover

* feat(skill): chevron animation, button effects, download path hint, review sidebar

1. File browser chevron: single ChevronDown with rotate-180 CSS transition
   instead of swapping two icons — smooth 200ms rotation animation

2. Preview dialog action button animations:
   - Copy icon: active:scale-125 feedback on click
   - Download icon: hover:translate-y-0.5 subtle downward motion
   - Close icon: hover:rotate-90 with destructive tint (unchanged)

3. Download tooltip now shows full file path:
   "下载 src/prompts/system.md" instead of generic "下载文件"
   - New i18n keys: filePreview.downloadHint, filePreview.copy, filePreview.close

4. Review detail page now has a sidebar file browser:
   - Two-column layout (main content + lg:w-80 sidebar)
   - File tree sourced from reviewSkillDetail.files (active review version)
   - Collapsible with same chevron animation as skill detail page
   - Shows active version badge below file tree
   - File preview uses review file API (/reviews/{id}/file?path=...)
   - Test mocks updated for new useReviewFile dependency

* fix(skill): download shows filename, copy rotates with success toast

1. Download button tooltip/text now shows actual filename:
   "下载 README.md" instead of generic path
   - i18n key changed from {{path}} to {{name}}

2. Copy button animation reworked to rotation:
   - idle: hover:rotate-180 on the Copy icon
   - click: animate-spin during clipboard write
   - done: swap to green Check icon for 1.5s, then reset

3. Copy success toast notification:
   - Shows "已复制到剪贴板" / "Copied to clipboard" via toast.success
   - New i18n key: filePreview.copySuccess

* fix(skill): set download attribute so browser saves with original filename

The <a> element was missing the download attribute, causing the browser
to derive the filename from the URL path segment (/file?path=...) which
always resolved to "file". Now explicitly sets link.download = node.name
so the saved file uses the original name (e.g. README.md, config.json).

Applied to all three download handlers:
- skill-detail.tsx (skill version file)
- review-detail.tsx (review sidebar file)
- review-skill-detail-section.tsx (review expanded section file)

* feat(skill): add icons to all sidebar card headers

Add Lucide icons to each sidebar section for visual consistency
with the existing SecurityAuditSummary (Shield) and file browser (Folder):

- Terminal: Install command
- Clock: Pending review (amber-colored to match card theme)
- RefreshCw: Lifecycle management
- Tag: Label management (in SkillLabelPanel component)
- ArrowUpCircle: Promotion
- ShieldCheck: Governance

All icons use the same pattern: w-4 h-4 text-muted-foreground
placed inside a flex row with gap-2 before the section title.

* fix(skill): allow owners to preview all version statuses

When a skill has only a REJECTED version, the detail page crashed with
400 "版本未发布" because assertPreviewAccessible() only allowed PUBLISHED
and PENDING_REVIEW(owner). The frontend fallback to versions[0] would
pick the REJECTED version and fail all file/readme queries.

Backend changes:
- assertPreviewAccessible(): now allows owners and namespace admins to
  preview ANY version status (DRAFT, REJECTED, YANKED, SCANNING, etc.)
  via canManageRestrictedSkill() check. Also passes userNsRoles so
  namespace admin role is respected, not just owner.
- resolveOwnerPendingPreview(): expanded from PENDING_REVIEW-only to
  include all non-published, non-yanked statuses so headlineVersion
  resolves correctly for owners with REJECTED/DRAFT/SCANNING versions.

Frontend changes:
- isOwnerPreviewResolution(): relaxed from checking PENDING_REVIEW
  specifically to checking any non-PUBLISHED status, matching the
  backend's broader projection.

Fixes: owner viewing skill with only REJECTED version → 400 error
Also fixes: DRAFT-only, SCANNING-only, SCAN_FAILED-only scenarios

* docs(requirements): add comprehensive requirements for file preview syntax highlighting

Generated complete documentation suite including:
- Core PRD (clarity score: 95/100)
- Constraints specification (8 business rules)
- Impact analysis (8 risks identified)
- Acceptance cases (25 test cases: 10 positive, 5 error, 7 boundary, 3 security)
- Test plan (100% coverage)

Mode: Quick (3 clarification rounds)
Complexity: Simple (3.5 days estimated)

* feat(skill): add syntax highlighting for code file preview

Implement syntax highlighting for code files in the file preview dialog:
- Add CodeRenderer component using lowlight (highlight.js wrapper via rehype-highlight)
- Add getLanguageForHighlight() to map file extensions to highlight.js languages
- Support 20+ languages: Python, JS/TS, Java, Go, Rust, C/C++, Ruby, PHP, Shell, JSON, YAML, XML, etc.
- Apply 500KB threshold for syntax highlighting (larger files show plain text)
- Maintain visual consistency with Markdown code blocks
- Auto-adapt to light/dark theme using existing CSS variables
- Add lowlight as direct dependency to enable programmatic syntax highlighting

Implements solution 1 from PRD (reuse rehype-highlight infrastructure).

* fix(security): resolve security audit FK constraint and stale query issues

Backend:
- Add hardDeleteByVersionId to physically remove audit records before
  deleting skill versions (fixes FK constraint violation on hard delete)
- Add softDeleteByVersionId calls in SkillGovernanceService and
  SkillPublishService version deletion paths
- Add V36 migration to convert security_audit TIMESTAMP columns to
  TIMESTAMPTZ matching project convention
- Update tests to verify audit cleanup in all deletion flows

Frontend:
- Prevent stale API calls after skill deletion by gating all query
  hooks with a skillDeleted flag that disables them immediately
- Move cache cleanup from useDeleteSkill onSuccess to the handler
  to avoid refetching while the component is still mounted

* fix(skill): handle SCANNING and SCAN_FAILED statuses across all pages

Backend:
- Include SCANNING/SCAN_FAILED in version listing filters so owners
  can see versions being scanned
- Add explicit lifecycle sort priority for scanner statuses
- Allow deletion of SCAN_FAILED versions alongside DRAFT and REJECTED

Frontend:
- Add i18n labels and CSS classes for SCANNING/SCAN_FAILED in my-skills
- Add localized version status labels in skill-detail version list
- Hide archive button when no published version exists (my-skills and
  skill-detail)
- Allow deleting SCAN_FAILED versions from skill-detail

* gitignore
2026-03-23 14:38:47 +08:00

12 KiB
Raw Permalink Blame History

name description type
文件预览语法高亮测试计划 单元测试、集成测试、性能测试的详细计划和覆盖率矩阵 test-plan

测试计划:文件预览语法高亮

1. 单元测试

测试类:CodeRenderer.test.tsx

位置web/src/features/skill/__tests__/code-renderer.test.tsx

测试方法 覆盖用例 描述
renders Python code with syntax highlighting AC-P-001 验证 Python 代码正确渲染,关键字着色
renders Shell script with syntax highlighting AC-P-002 验证 Shell 脚本正确渲染,命令着色
renders JSON with syntax highlighting AC-P-003 验证 JSON 正确渲染,键值着色
renders YAML with syntax highlighting AC-P-004 验证 YAML 正确渲染,结构清晰
falls back to plain text for unknown language AC-E-001 验证无法识别语言时降级到纯文本
handles empty code gracefully AC-E-005 验证空内容不报错
handles Unicode characters correctly AC-B-006 验证 Unicode 字符(中文)正确显示
escapes HTML tags to prevent XSS AC-S-001 验证 HTML 标签被转义
applies correct CSS classes for theming AC-P-007 验证 CSS 类名与 Markdown 一致

测试数据

const pythonCode = `def hello():\n    print("Hello, World!")`
const shellCode = `#!/bin/bash\necho "Hello"`
const jsonCode = `{"key": "value", "number": 123}`
const yamlCode = `key: value\nnumber: 123`
const xssCode = `<script>alert('XSS')</script>`

测试类:file-type-utils.test.ts

位置web/src/features/skill/__tests__/file-type-utils.test.ts

测试方法 覆盖用例 描述
getLanguageForHighlight returns correct language for .py AC-P-006 验证 .py → python
getLanguageForHighlight returns correct language for .sh AC-P-006 验证 .sh → bash
getLanguageForHighlight returns correct language for .json AC-P-006 验证 .json → json
getLanguageForHighlight returns correct language for .yaml AC-P-006 验证 .yaml → yaml
getLanguageForHighlight returns null for unknown extension AC-E-001 验证 .custom → null
getLanguageForHighlight handles case-insensitive extensions - 验证 .PY → python
getLanguageForHighlight handles multiple extensions for same language - 验证 .yml 和 .yaml 都映射到 yaml

测试数据

const testCases = [
  { ext: '.py', expected: 'python' },
  { ext: '.sh', expected: 'bash' },
  { ext: '.bash', expected: 'bash' },
  { ext: '.json', expected: 'json' },
  { ext: '.yaml', expected: 'yaml' },
  { ext: '.yml', expected: 'yaml' },
  { ext: '.custom', expected: null },
]

2. 集成测试

测试类:file-preview-dialog.test.tsx

位置web/src/features/skill/__tests__/file-preview-dialog.test.tsx

测试方法 覆盖用例 描述
renders CodeRenderer for Python files under 500KB AC-P-001, AC-B-001 验证小文件使用语法高亮
renders plain text for files over 500KB AC-B-002 验证大文件降级到纯文本
shows download-only for files over 1MB AC-B-004 验证超大文件只显示下载
renders MarkdownRenderer for .md files AC-P-005 验证 Markdown 文件使用现有渲染器
switches renderer when file changes AC-P-005 验证切换文件时渲染器正确切换
shows loading state while fetching file - 验证 loading 状态显示
handles network error gracefully AC-E-004 验证网络错误显示提示
copy button works correctly AC-P-009 验证复制功能
download button works correctly AC-P-010 验证下载功能

测试数据

const smallPythonFile = { path: 'main.py', size: 10240, content: '...' }
const largePythonFile = { path: 'large.py', size: 512000, content: '...' }
const hugePythonFile = { path: 'huge.py', size: 1100000, content: '...' }
const markdownFile = { path: 'README.md', size: 5000, content: '...' }

测试类:skill-detail-page.test.tsx(扩展现有测试)

位置web/src/features/skill/__tests__/skill-detail-page.test.tsx

测试方法 覆盖用例 描述
file tree shows syntax-highlighted preview on click AC-P-001 端到端测试:点击文件树 → 显示语法高亮
file preview dialog closes correctly - 验证关闭弹窗功能

3. 性能测试

测试场景:渲染性能

工具Jest + Performance API

测试场景 目标指标 测试方法
100KB Python 文件渲染时间 < 200ms 使用 performance.now() 测量
500KB Python 文件渲染时间 < 500ms 使用 performance.now() 测量
内存占用500KB 文件) < 50MB 使用 Chrome DevTools Memory Profiler
首次加载时间(包括网络) < 1s 使用 Lighthouse Performance 测试

测试代码示例

test('renders 500KB file within 500ms', async () => {
  const largeCode = 'x'.repeat(500 * 1024)
  const start = performance.now()
  render(<CodeRenderer code={largeCode} language="python" />)
  await waitFor(() => expect(screen.getByRole('code')).toBeInTheDocument())
  const end = performance.now()
  expect(end - start).toBeLessThan(500)
})

测试场景:包体积

工具Webpack Bundle Analyzer

指标 目标值 测试方法
新增代码包体积gzipped < 100KB 运行 npm run build 后分析 bundle
highlight.js 核心库 ~10KB 检查 bundle 中的 highlight.js 大小
按需导入的语言包 ~5KB/语言 检查每个语言包的大小

4. 浏览器兼容性测试

测试矩阵

浏览器 版本 测试用例 状态
Chrome 90+ AC-P-001 ~ AC-P-010 通过
Firefox 88+ AC-P-001 ~ AC-P-010 通过
Safari 14+ AC-P-001 ~ AC-P-010 通过
Edge 90+ AC-P-001 ~ AC-P-010 通过

测试工具BrowserStack 或本地虚拟机


5. 主题测试

测试场景:主题切换

工具Jest + React Testing Library

测试场景 覆盖用例 测试方法
Light 模式下语法高亮颜色正确 AC-P-007 检查 CSS 变量值
Dark 模式下语法高亮颜色正确 AC-P-007 检查 CSS 变量值
Light → Dark 切换平滑 AC-P-007 模拟主题切换,检查过渡效果
Dark → Light 切换平滑 AC-P-008 模拟主题切换,检查过渡效果

测试代码示例

test('applies correct theme colors in dark mode', () => {
  render(<CodeRenderer code="def hello():" language="python" />, {
    wrapper: ({ children }) => <ThemeProvider theme="dark">{children}</ThemeProvider>
  })
  const codeElement = screen.getByRole('code')
  const styles = window.getComputedStyle(codeElement)
  expect(styles.backgroundColor).toBe('rgb(30, 30, 30)') // Dark background
})

6. 安全测试

测试场景XSS 防护

工具Jest + DOMPurify如果使用

测试场景 覆盖用例 测试方法
HTML 标签被转义 AC-S-001 渲染包含 <script> 的代码,检查 DOM
事件处理器被转义 AC-S-002 渲染包含 onerror 的代码,检查 DOM
不执行任何脚本 AC-S-001, AC-S-002 使用 jest.spyOn(window, 'alert') 验证未调用

测试代码示例

test('escapes HTML tags to prevent XSS', () => {
  const xssCode = '<script>alert("XSS")</script>'
  const alertSpy = jest.spyOn(window, 'alert').mockImplementation()
  render(<CodeRenderer code={xssCode} language="javascript" />)
  expect(screen.getByText(/<script>/)).toBeInTheDocument() // 显示为文本
  expect(alertSpy).not.toHaveBeenCalled() // 未执行脚本
  alertSpy.mockRestore()
})

7. 覆盖率矩阵

验收用例覆盖

验收用例 单元测试 集成测试 性能测试 浏览器测试
AC-P-001
AC-P-002 - -
AC-P-003 - -
AC-P-004 - -
AC-P-005 - -
AC-P-006 - - -
AC-P-007 - -
AC-P-008 - -
AC-P-009 - - -
AC-P-010 - - -
AC-E-001 - - -
AC-E-002 - - -
AC-E-003 - - -
AC-E-004 - - -
AC-E-005 - - -
AC-B-001 - -
AC-B-002 - - -
AC-B-003 - - -
AC-B-004 - - -
AC-B-005 - - -
AC-B-006 - - -
AC-B-007 - - -
AC-S-001 - - -
AC-S-002 - - -
AC-S-003 - - - -

覆盖率统计

  • 单元测试覆盖11/25 (44%)
  • 集成测试覆盖13/25 (52%)
  • 性能测试覆盖2/25 (8%)
  • 浏览器测试覆盖10/25 (40%)
  • 总覆盖率25/25 (100%)

8. 测试数据

测试文件准备

位置web/src/features/skill/__tests__/__fixtures__/

文件名 大小 用途
sample.py 10KB Python 语法高亮测试
sample.sh 5KB Shell 语法高亮测试
sample.json 2KB JSON 语法高亮测试
sample.yaml 3KB YAML 语法高亮测试
large.py 500KB 边界测试(刚好 500KB
large-501kb.py 501KB 边界测试(超过 500KB
huge.py 1.1MB 边界测试(超过 1MB
unicode.py 5KB Unicode 字符测试(包含中文注释)
xss.html 1KB XSS 防护测试

9. 测试执行计划

阶段 1单元测试0.5 天)

  • 编写 CodeRenderer.test.tsx9 个测试用例)
  • 编写 file-type-utils.test.ts7 个测试用例)
  • 运行测试,确保覆盖率 > 80%
  • 修复失败的测试

阶段 2集成测试0.5 天)

  • 编写 file-preview-dialog.test.tsx9 个测试用例)
  • 扩展 skill-detail-page.test.tsx2 个测试用例)
  • 运行测试,确保端到端流程正常
  • 修复失败的测试

阶段 3性能测试0.3 天)

  • 编写渲染性能测试4 个场景)
  • 运行 Webpack Bundle Analyzer检查包体积
  • 使用 Lighthouse 测试首次加载时间
  • 优化性能瓶颈(如果需要)

阶段 4浏览器兼容性测试0.2 天)

  • 在 Chrome 90+ 测试所有正向用例
  • 在 Firefox 88+ 测试所有正向用例
  • 在 Safari 14+ 测试所有正向用例
  • 在 Edge 90+ 测试所有正向用例
  • 记录兼容性问题(如果有)

阶段 5安全测试0.2 天)

  • 编写 XSS 防护测试3 个场景)
  • 验证路径遍历防护(复用现有测试)
  • 代码审查,确认无安全漏洞

10. 测试通过标准

单元测试

  • 所有测试用例通过
  • 代码覆盖率 > 80%(语句覆盖、分支覆盖)
  • 无 TypeScript 类型错误
  • 无 ESLint 警告

集成测试

  • 所有端到端流程正常
  • 文件预览弹窗正确渲染
  • 复制和下载功能正常

性能测试

  • 500KB 文件渲染时间 < 500msP95
  • 首次加载时间 < 1sP95
  • 新增包体积 < 100KBgzipped
  • Lighthouse 性能评分不下降

浏览器兼容性测试

  • Chrome 90+ 所有功能正常
  • Firefox 88+ 所有功能正常
  • Safari 14+ 所有功能正常
  • Edge 90+ 所有功能正常

安全测试

  • XSS 防护测试通过
  • 代码审查通过
  • 无安全漏洞

变更日志

日期 章节 变更 原因 触发者
2026-03-22 初始版本 创建测试计划文档 需求澄清完成 requirements-clarity