基于项目需求文档(PRD.md, FeatureSummary.md, DevelopmentPlan.md, UIDesign.md, User_Role_Interfaces.md)编写的 TDD 测试用例。 后端测试 (Python/pytest): - 单元测试: rule_engine, brief_parser, timestamp_alignment, video_auditor, validators - 集成测试: API Brief, Video, Review 端点 - AI 模块测试: ASR, OCR, Logo 检测服务 - 全局 fixtures 和 pytest 配置 前端测试 (TypeScript/Vitest): - 工具函数测试: utils.test.ts - 组件测试: Button, VideoPlayer, ViolationList - Hooks 测试: useVideoAudit, useVideoPlayer, useAppeal - MSW mock handlers 配置 E2E 测试 (Playwright): - 认证流程测试 - 视频上传流程测试 - 视频审核流程测试 - 申诉流程测试 所有测试当前使用 pytest.skip() / it.skip() 作为占位符, 遵循 TDD 红灯阶段 - 等待实现代码后运行。 验收标准覆盖: - ASR WER ≤ 10% - OCR 准确率 ≥ 95% - Logo F1 ≥ 0.85 - 时间戳误差 ≤ 0.5s - 频次统计准确率 ≥ 95% Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
218 lines
8.2 KiB
TypeScript
218 lines
8.2 KiB
TypeScript
/**
|
||
* 视频审核流程 E2E 测试
|
||
*
|
||
* TDD 测试用例 - 测试完整的视频审核用户流程
|
||
*
|
||
* 用户流程参考:User_Role_Interfaces.md
|
||
*/
|
||
|
||
import { test, expect } from '@playwright/test'
|
||
|
||
test.describe('Video Review Flow', () => {
|
||
test.beforeEach(async ({ page }) => {
|
||
// 以 Agency 审核员身份登录
|
||
// await page.goto('/login')
|
||
// await page.getByPlaceholder('邮箱').fill('agency@example.com')
|
||
// await page.getByPlaceholder('密码').fill('password123')
|
||
// await page.getByRole('button', { name: '登录' }).click()
|
||
// await page.waitForURL('/dashboard')
|
||
})
|
||
|
||
test.skip('should display pending review list', async ({ page }) => {
|
||
// await page.goto('/reviews/pending')
|
||
//
|
||
// // 验证列表显示
|
||
// await expect(page.getByRole('heading', { name: '待审核视频' })).toBeVisible()
|
||
// await expect(page.getByTestId('video-list')).toBeVisible()
|
||
//
|
||
// // 验证列表项
|
||
// const videos = page.getByTestId('video-item')
|
||
// await expect(videos).toHaveCount.greaterThan(0)
|
||
})
|
||
|
||
test.skip('should open video review page', async ({ page }) => {
|
||
// await page.goto('/reviews/pending')
|
||
//
|
||
// // 点击第一个视频
|
||
// await page.getByTestId('video-item').first().click()
|
||
//
|
||
// // 验证审核页面
|
||
// await expect(page.getByTestId('video-player')).toBeVisible()
|
||
// await expect(page.getByTestId('violation-list')).toBeVisible()
|
||
// await expect(page.getByTestId('brief-compliance')).toBeVisible()
|
||
})
|
||
|
||
test.skip('should play video and seek to violation', async ({ page }) => {
|
||
// await page.goto('/reviews/video_001')
|
||
//
|
||
// // 找到违规项
|
||
// const violation = page.getByTestId('violation-item').first()
|
||
// await expect(violation).toBeVisible()
|
||
//
|
||
// // 点击时间戳跳转
|
||
// await violation.getByTestId('timestamp-link').click()
|
||
//
|
||
// // 验证视频跳转到对应时间
|
||
// const currentTime = page.getByTestId('current-time')
|
||
// await expect(currentTime).toContainText('00:05')
|
||
})
|
||
|
||
test.skip('should show violation evidence screenshot', async ({ page }) => {
|
||
// await page.goto('/reviews/video_001')
|
||
//
|
||
// // 找到 Logo 违规项
|
||
// const logoViolation = page.getByText('竞品 Logo').locator('..')
|
||
//
|
||
// // 点击查看证据
|
||
// await logoViolation.getByRole('button', { name: '查看证据' }).click()
|
||
//
|
||
// // 验证截图显示
|
||
// await expect(page.getByTestId('evidence-modal')).toBeVisible()
|
||
// await expect(page.getByRole('img', { name: '违规截图' })).toBeVisible()
|
||
})
|
||
|
||
test.skip('should pass video review', async ({ page }) => {
|
||
// await page.goto('/reviews/video_001')
|
||
//
|
||
// // 点击通过按钮
|
||
// await page.getByRole('button', { name: '通过' }).click()
|
||
//
|
||
// // 填写评语(可选)
|
||
// await page.getByPlaceholder('审核评语').fill('内容符合要求')
|
||
//
|
||
// // 确认提交
|
||
// await page.getByRole('button', { name: '确认通过' }).click()
|
||
//
|
||
// // 验证成功提示
|
||
// await expect(page.getByText('审核完成')).toBeVisible()
|
||
//
|
||
// // 验证跳转到下一个待审核视频或列表
|
||
// await expect(page).toHaveURL(/\/reviews/)
|
||
})
|
||
|
||
test.skip('should reject video with selected violations', async ({ page }) => {
|
||
// await page.goto('/reviews/video_001')
|
||
//
|
||
// // 选择违规项
|
||
// await page.getByTestId('violation-checkbox').first().click()
|
||
// await page.getByTestId('violation-checkbox').nth(1).click()
|
||
//
|
||
// // 点击驳回按钮
|
||
// await page.getByRole('button', { name: '驳回' }).click()
|
||
//
|
||
// // 验证显示已选违规项
|
||
// const modal = page.getByTestId('reject-modal')
|
||
// await expect(modal).toBeVisible()
|
||
// await expect(modal.getByText('已选择 2 项违规')).toBeVisible()
|
||
//
|
||
// // 填写评语
|
||
// await modal.getByPlaceholder('审核评语').fill('存在违规内容,请修改')
|
||
//
|
||
// // 确认驳回
|
||
// await modal.getByRole('button', { name: '确认驳回' }).click()
|
||
//
|
||
// // 验证成功提示
|
||
// await expect(page.getByText('已驳回')).toBeVisible()
|
||
})
|
||
|
||
test.skip('should force pass with reason', async ({ page }) => {
|
||
// await page.goto('/reviews/video_001')
|
||
//
|
||
// // 点击强制通过
|
||
// await page.getByRole('button', { name: '强制通过' }).click()
|
||
//
|
||
// // 验证需要填写原因
|
||
// const modal = page.getByTestId('force-pass-modal')
|
||
// await expect(modal).toBeVisible()
|
||
//
|
||
// // 尝试不填原因提交
|
||
// await modal.getByRole('button', { name: '确认' }).click()
|
||
// await expect(modal.getByText('请填写强制通过原因')).toBeVisible()
|
||
//
|
||
// // 填写原因
|
||
// await modal.getByPlaceholder('请填写原因').fill('达人玩的新梗,品牌方认可')
|
||
// await modal.getByRole('button', { name: '确认' }).click()
|
||
//
|
||
// // 验证成功
|
||
// await expect(page.getByText('强制通过成功')).toBeVisible()
|
||
})
|
||
|
||
test.skip('should add manual violation', async ({ page }) => {
|
||
// await page.goto('/reviews/video_001')
|
||
//
|
||
// // 点击添加违规
|
||
// await page.getByRole('button', { name: '添加违规项' }).click()
|
||
//
|
||
// // 填写违规信息
|
||
// const modal = page.getByTestId('add-violation-modal')
|
||
// await modal.getByLabel('违规类型').selectOption('other')
|
||
// await modal.getByPlaceholder('违规内容').fill('发现额外问题')
|
||
// await modal.getByLabel('开始时间').fill('00:10')
|
||
// await modal.getByLabel('结束时间').fill('00:15')
|
||
// await modal.getByLabel('严重程度').selectOption('medium')
|
||
//
|
||
// // 提交
|
||
// await modal.getByRole('button', { name: '添加' }).click()
|
||
//
|
||
// // 验证违规项已添加
|
||
// await expect(page.getByText('发现额外问题')).toBeVisible()
|
||
// await expect(page.getByTestId('violation-item').filter({ hasText: '手动添加' })).toBeVisible()
|
||
})
|
||
|
||
test.skip('should delete AI violation', async ({ page }) => {
|
||
// await page.goto('/reviews/video_001')
|
||
//
|
||
// // 找到 AI 检测的违规项
|
||
// const aiViolation = page.getByTestId('violation-item').filter({ hasText: 'AI 检测' }).first()
|
||
//
|
||
// // 点击删除
|
||
// await aiViolation.getByRole('button', { name: '删除' }).click()
|
||
//
|
||
// // 确认删除
|
||
// const confirmModal = page.getByTestId('confirm-modal')
|
||
// await confirmModal.getByPlaceholder('删除原因').fill('误检')
|
||
// await confirmModal.getByRole('button', { name: '确认删除' }).click()
|
||
//
|
||
// // 验证违规项已删除
|
||
// await expect(aiViolation).not.toBeVisible()
|
||
})
|
||
})
|
||
|
||
test.describe('Brief Compliance Check', () => {
|
||
test.skip('should display brief compliance status', async ({ page }) => {
|
||
// await page.goto('/reviews/video_001')
|
||
//
|
||
// // 验证 Brief 合规面板
|
||
// const compliancePanel = page.getByTestId('brief-compliance')
|
||
// await expect(compliancePanel).toBeVisible()
|
||
//
|
||
// // 验证卖点覆盖
|
||
// await expect(compliancePanel.getByText('卖点覆盖')).toBeVisible()
|
||
// await expect(compliancePanel.getByText('2/3')).toBeVisible()
|
||
//
|
||
// // 验证时长要求
|
||
// await expect(compliancePanel.getByText('产品同框')).toBeVisible()
|
||
})
|
||
|
||
test.skip('should show uncovered selling points', async ({ page }) => {
|
||
// await page.goto('/reviews/video_001')
|
||
//
|
||
// // 点击查看详情
|
||
// await page.getByTestId('brief-compliance').getByRole('button', { name: '查看详情' }).click()
|
||
//
|
||
// // 验证显示未覆盖的卖点
|
||
// const detailModal = page.getByTestId('compliance-detail-modal')
|
||
// await expect(detailModal.getByText('未覆盖')).toBeVisible()
|
||
// await expect(detailModal.getByText('敏感肌适用')).toBeVisible()
|
||
})
|
||
|
||
test.skip('should highlight timing requirement failures', async ({ page }) => {
|
||
// await page.goto('/reviews/video_001')
|
||
//
|
||
// // 验证不合规的时长要求显示为红色
|
||
// const timingRequirement = page.getByTestId('timing-requirement').filter({ hasText: '品牌名提及' })
|
||
// await expect(timingRequirement).toHaveClass(/text-red/)
|
||
// await expect(timingRequirement.getByText('2/3')).toBeVisible() // 未达标
|
||
})
|
||
})
|