11-6-company-list-test.md 11 KB

Story 11.6: 验证公司列表显示

Status: done

Story

作为测试开发者, 我想要编写公司列表查看的 E2E 测试, 以便验证公司列表的基本功能和数据展示。

Acceptance Criteria

Given Epic 11.4 (Company 管理 Page Object) 已完成 When 编写公司列表查看测试用例 Then 验证以下场景:

  1. 公司列表按预期加载

    • 页面成功导航到 /admin/companies
    • 页面标题"公司管理"显示正确
    • 表格组件加载并可见
    • 表格数据成功渲染
  2. 公司数据的正确展示

    • 公司名称显示正确(第0列)
    • 关联平台显示正确(第1列)
    • 联系人显示正确(第2列)
    • 联系电话显示正确(第3列)
    • 状态徽章显示正确(第4列:启用/禁用)
    • 创建时间显示正确(第5列)
    • 操作按钮显示正确(第6列:编辑、删除)
  3. 列表功能验证

    • 创建公司按钮存在且可点击
    • 搜索输入框存在
    • 搜索按钮存在
    • 当无数据时显示正确提示
    • 表格分页功能正常(如适用)
  4. 测试在真实浏览器中通过

    • 使用 Playwright Chromium 运行
    • 所有断言通过
    • 无超时失败

Tasks / Subtasks

  • [x] Task 1: 创建测试文件基础结构 (AC: #1)

    • Subtask 1.1: 创建 web/tests/e2e/specs/admin/company-list.spec.ts
    • Subtask 1.2: 导入必要的依赖和 Page Object
    • Subtask 1.3: 配置测试 fixture
  • [x] Task 2: 实现页面加载和基础验证测试 (AC: #1)

    • Subtask 2.1: 测试 - 应该成功导航到公司管理页面
    • Subtask 2.2: 测试 - 应该显示正确的页面标题
    • Subtask 2.3: 测试 - 应该加载公司列表表格
  • [x] Task 3: 实现数据显示验证测试 (AC: #2)

    • Subtask 3.1: 测试 - 应该正确显示公司名称
    • Subtask 3.2: 测试 - 应该正确显示关联平台
    • Subtask 3.3: 测试 - 应该正确显示联系人信息
    • Subtask 3.4: 测试 - 应该正确显示状态徽章
    • Subtask 3.5: 测试 - 应该正确显示创建时间
  • [x] Task 4: 实现列表功能测试 (AC: #3, #4)

    • Subtask 4.1: 测试 - 应该显示创建公司按钮
    • Subtask 4.2: 测试 - 应该显示搜索输入框
    • Subtask 4.3: 测试 - 无数据时显示正确提示
    • Subtask 4.4: 运行所有测试并验证通过

Code Review Follow-ups (AI)

本代码审查由 AI 对抗性代码审查工作流执行,于 2026-01-12 完成。

发现并修复的问题

HIGH 问题(已修复):

  1. 测试数据隔离问题 - 添加了 beforeEach/afterEach 钩子

    • 每个测试运行前创建唯一的测试数据
    • 测试完成后自动清理数据
    • 修复了测试依赖外部数据导致的假通过问题
  2. 空数据提示测试虚假 - 重写了无数据提示测试

    • 原测试只验证表格存在,不验证空状态
    • 新测试搜索不存在的公司,验证空数据行为
  3. 测试静默通过 - 移除了 if (count > 0) 模式

    • 原代码数据为空时测试通过但不验证任何内容
    • 新代码使用 filter({ hasText }) 精确匹配,数据不存在会抛出清晰错误

MEDIUM 问题(已修复):

  1. 冗余 count() 调用 - 简化了测试代码

    • 移除了 first().count() 冗余检查
    • 直接使用 expect().toBeVisible() 验证
  2. 搜索功能未测试 - 添加了实际搜索测试

    • 原测试只验证搜索框存在
    • 新测试实际执行搜索并验证结果
  3. 分页功能未测试 - 添加了分页控件检查

    • 检测分页控件是否存在
    • 如不存在,验证至少有数据在表格中
  4. 代码质量改进 - 添加了常量定义

    • 定义 TABLE_COLUMNS 常量避免魔法数字
    • 定义 generateTestName() 函数生成唯一测试数据

LOW 问题(已修复):

  1. 测试描述优化 - 合并了搜索相关测试

测试结果

  • 初始测试: 12 passed (原始实现)
  • 代码审查后: 14 passed (包含新增的搜索和空数据测试)
  • 所有 HIGH 和 MEDIUM 问题已修复

遗留建议

  1. Page Object 选择器改进建议: 建议在 UI 组件上添加 data-testid="company-page-title" 而非依赖 data-slot="card-title",以提高选择器稳定性

Dev Notes

Epic 上下文

Epic 11: 基础配置管理测试 (Epic F)

目标: 为平台、公司、渠道配置管理编写 E2E 测试,为后续用户管理和跨端测试提供必要的测试数据。

实体关系链:

Platform (平台)
  ↓ 1:N
Company (公司) - 必须 platformId
  ↓ 1:N
Order (订单) - 必须 companyId

当前进度:

  • 11.1: Platform 管理 Page Object ✅ done
  • 11.2: 创建测试平台 ✅ done
  • 11.3: 验证平台列表显示 ✅ done
  • 11.4: Company 管理 Page Object ✅ done
  • 11.5: 创建测试公司 backlog
  • 11.6: 验证公司列表显示 ← 当前故事
  • 11.7-11.9: 后续故事

前序故事学习 (Story 11.4)

Story 11.4 (Company Page Object) 已完成:

  • Page Object 文件: web/tests/e2e/pages/admin/company-management.page.ts
  • 完整的选择器定义和 CRUD 方法
  • 使用 @d8d/e2e-test-utilsselectRadixOptionAsync
  • 支持创建、编辑、删除、搜索功能
  • 包含完整的 TypeScript 类型定义

关键 API:

// 导航到页面
await companyPage.goto();

// 验证页面可见
await companyPage.expectToBeVisible();

// 检查公司是否存在
const exists = await companyPage.companyExists('公司名称');

// 创建公司
const result = await companyPage.createCompany({
  companyName: '测试公司',
  contactPerson: '张三',
  contactPhone: '13800138000'
}, '平台名称');

表格列顺序(重要):

  • 第0列: 公司名称
  • 第1列: 平台
  • 第2列: 联系人
  • 第3列: 联系电话
  • 第4列: 状态(启用/禁用)
  • 第5列: 创建时间
  • 第6列: 操作(编辑、删除)

参考测试模式 (Epic 8 区域管理)

参考 web/tests/e2e/specs/admin/region-list.spec.ts 的测试模式:

  1. 测试文件结构:

    import { test, expect } from '@playwright/test';
    import { CompanyManagementPage } from '@/pages/admin/company-management.page';
    
    test.describe('公司列表管理', () => {
    let companyPage: CompanyManagementPage;
    
    test.beforeEach(async ({ adminLoginPage, page }) => {
    // 登录
    await adminLoginPage.goto();
    await adminLoginPage.login('admin', 'admin123');
    
    companyPage = new CompanyManagementPage(page);
    });
    
    test.afterEach(async ({ companyPage }) => {
    // 清理测试数据
    });
    
    test('应该成功加载公司列表页面', async () => {
    await companyPage.goto();
    // 验证...
    });
    });
    
  2. 数据验证模式:

  3. 使用 page.locator() 定位表格元素

  4. 使用 filter({ hasText }) 精确匹配行

  5. 使用 nth(index) 定位列

  6. 使用 expect().toBeVisible() 验证可见性

  7. 使用 expect().toHaveText() 验证文本内容

  8. 测试隔离:

  9. 每个测试使用唯一数据(时间戳)

  10. 测试后清理数据

  11. 避免测试间相互影响

技术约束和最佳实践

选择器策略(来自 Architecture 文档):

  1. 优先使用 data-testid
  2. 使用 role + name 组合
  3. 避免使用不稳定的 CSS 类
  4. 文本匹配使用 :text-is() 精确匹配

等待策略:

  • 使用 Playwright 的 auto-waiting 机制
  • 不使用 waitForTimeout(除非必要)
  • 使用 waitForLoadState('domcontentloaded') 等待页面加载
  • 使用 waitFor({ state: 'visible' }) 等待元素可见

错误处理:

  • 捕获并记录有用的错误信息
  • 使用 console.debug() 调试(Vitest 支持)
  • 失败时自动截图(Playwright 默认)

测试数据管理

测试平台创建(前置条件): 如果测试需要关联平台,需要先确保测试平台存在:

  • 可以通过 API 直接创建
  • 或使用 Story 11.2 创建的测试平台

测试数据清理:

test.afterEach(async ({ companyPage }) => {
  // 清理测试创建的公司
  const testCompanies = ['测试公司1', '测试公司2'];
  for (const name of testCompanies) {
    await companyPage.deleteCompany(name);
  }
});

Project Structure Notes

测试文件位置:

web/tests/e2e/
├── pages/admin/
│   └── company-management.page.ts  ← 已存在
├── specs/admin/
│   └── company-list.spec.ts        ← 需要创建
└── fixtures/
    └── (测试数据文件)

导入路径:

// Page Object 导入
import { CompanyManagementPage } from '@/pages/admin/company-management.page';

// 测试工具导入
import { selectRadixOptionAsync } from '@d8d/e2e-test-utils';

References

Epic 文档:

  • [Source: _bmad-output/planning-artifacts/epics.md#Epic-11]

架构文档:

  • [Source: _bmad-output/planning-artifacts/architecture.md] - TypeScript + Playwright 陷阱部分
  • [Source: docs/standards/e2e-radix-testing.md] - Radix UI E2E 测试标准

前序故事:

  • [Source: _bmad-output/implementation-artifacts/11-4-company-page-object.md] - Company Page Object

参考测试实现:

  • [Source: web/tests/e2e/specs/admin/region-list.spec.ts] - 区域列表测试参考

项目上下文:

  • [Source: _bmad-output/project-context.md] - 技术栈和规则

Dev Agent Record

Agent Model Used

Claude Opus 4.5 (claude-opus-4-5-20251101)

Debug Log References

Completion Notes List

  1. 创建日期: 2026-01-12
  2. Epic 状态: in-progress
  3. 前置依赖: Story 11.4 (Company Page Object) 已完成
  4. 后续故事: Story 11.7 (Channel Page Object - 可选)
  5. 初始实施完成:
    • 创建了完整的公司列表 E2E 测试文件 web/tests/e2e/specs/admin/company-list.spec.ts
    • 12 个测试全部通过
    • 修复了 CompanyManagement Page Object 中的 pageTitle 选择器(从 getByRole('heading') 改为使用 data-slot="card-title"
    • 修复了操作按钮测试(编辑和删除按钮使用图标,没有文本)
  6. 代码审查完成 (2026-01-12):
    • 修复了 3 个 HIGH 问题(测试数据隔离、空数据测试、静默通过)
    • 修复了 4 个 MEDIUM 问题(冗余代码、搜索测试、分页测试、代码质量)
    • 测试数量从 12 个增加到 14 个
    • 所有测试通过 (14/14)
    • Story 状态更新为 "done"

File List

已创建/修改的文件:

  • web/tests/e2e/specs/admin/company-list.spec.ts (新建) - 公司列表 E2E 测试,包含 14 个测试用例
  • web/tests/e2e/pages/admin/company-management.page.ts (修改) - 修复 pageTitle 选择器
  • _bmad-output/implementation-artifacts/11-6-company-list-test.md (修改) - 添加代码审查记录

依赖文件:

  • web/tests/e2e/fixtures/admin-login.fixture.ts
  • packages/e2e-test-utils/src/index.ts

配置文件:

  • web/tests/e2e/playwright.config.ts