# 系统初始化向导集成测试用例

**创建日期**: 2026-02-15  
**版本**: v1.0  
**优先级**: P0  
**测试类型**: E2E 集成测试

---

## 一、测试概述

### 1.1 测试目标

验证系统初始化向导功能的完整流程，包括：
- 超级管理员首次登录自动进入向导模式
- 项目创建流程（手动创建/从集团同步）
- 用户选择器功能（搜索、创建用户）
- 角色模板配置
- 向导完成后正确进入系统

### 1.2 测试范围

| 模块 | 功能点 | 测试类型 |
|------|--------|----------|
| 认证 | 登录、权限获取 | API + UI |
| 向导 | 项目创建、角色配置 | UI |
| 用户 | 创建用户、用户选择 | API + UI |
| 项目 | 项目编号生成 | API |
| 权限 | 菜单动态加载 | UI |

### 1.3 前置条件

1. 数据库已清理到初始状态（仅保留 admin 用户和系统项目数据）
2. 后端服务全部启动（Gateway、Auth、MDM、OPS）
3. 前端服务启动
4. 浏览器清除 LocalStorage

---

## 二、测试用例

### TC-WIZARD-001: 超级管理员首次登录进入向导模式

**测试权限**: 超级管理员 (admin)

**前置条件**:
- 数据库中无业务项目
- admin 用户仅有 SUPER_ADMIN 角色，关联系统项目

**测试步骤**:

| 步骤 | 操作 | 期望结果 |
|------|------|----------|
| 1 | 访问 http://localhost:5175/ | 显示登录页面 |
| 2 | 输入用户名 `admin`，密码 `admin123`，点击登录 | 登录成功，自动跳转到 `/setup-wizard` |
| 3 | 检查页面标题 | 显示"欢迎使用 Ether 智慧物业管理平台" |
| 4 | 检查步骤条 | 显示3个步骤：创建项目、角色配置、完成设置 |

**验证方法**:
```javascript
// API 验证
const response = await fetch('/api/v1/auth/user-permissions', {
  headers: { 'Authorization': `Bearer ${token}` }
});
const data = await response.json();
// 验证 isSystemAdmin
assert(data.projects.some(p => p.isSystem === true));
// 验证 needSetupWizard
assert(data.projects.filter(p => !p.isSystem).length === 0);
```

**API 测试**:
```bash
# 登录获取 token
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin123"}' \
  | jq -r '.data.accessToken')

# 验证权限响应
curl -s http://localhost:8080/api/v1/auth/user-permissions \
  -H "Authorization: Bearer $TOKEN" | jq '{
    projects: .data.projects,
    isSystem: [.data.projects[].isSystem]
  }'
```

---

### TC-WIZARD-002: 创建方式切换

**测试权限**: 超级管理员

**前置条件**: 已进入向导页面

**测试步骤**:

| 步骤 | 操作 | 期望结果 |
|------|------|----------|
| 1 | 检查默认选中 | 默认选中"手动创建" |
| 2 | 点击"从集团同步" | 显示"功能开发中，敬请期待"提示 |
| 3 | "下一步"按钮状态 | 按钮禁用 |
| 4 | 切换回"手动创建" | 表单正常显示，"下一步"按钮可用 |

---

### TC-WIZARD-003: 省市区下拉选择

**测试权限**: 超级管理员

**前置条件**: 已进入向导页面，选择"手动创建"

**测试步骤**:

| 步骤 | 操作 | 期望结果 |
|------|------|----------|
| 1 | 检查省份字段 | 显示"上海市"，禁用状态 |
| 2 | 检查城市字段 | 显示"上海市"，禁用状态 |
| 3 | 点击区县下拉框 | 显示上海16个区选项 |
| 4 | 选择"浦东新区" | 区县字段显示"浦东新区" |

**验证数据**:
```javascript
const SHANGHAI_DISTRICTS = [
  '黄浦区', '徐汇区', '长宁区', '静安区', '普陀区',
  '虹口区', '杨浦区', '闵行区', '宝山区', '嘉定区',
  '浦东新区', '金山区', '松江区', '青浦区', '奉贤区', '崇明区'
];
// 验证下拉选项数量
assert(dropdownOptions.length === 16);
```

---

### TC-WIZARD-004: 用户选择器 - 创建用户

**测试权限**: 超级管理员

**前置条件**: 已进入向导页面，选择"手动创建"

**测试步骤**:

| 步骤 | 操作 | 期望结果 |
|------|------|----------|
| 1 | 点击"项目负责人"输入框 | 弹出"选择负责人"对话框 |
| 2 | 检查对话框按钮 | "确定"和"取消"按钮显示中文 |
| 3 | 点击"创建用户"按钮 | 弹出"创建用户"对话框 |
| 4 | 输入用户名 `test_manager` | - |
| 5 | 输入姓名 `测试负责人` | - |
| 6 | 输入手机号 `13800138001` | - |
| 7 | 密码留空 | 显示"留空将自动生成随机密码"提示 |
| 8 | 点击"确定" | 显示"用户创建成功"弹窗，显示生成的密码 |
| 9 | 点击"我已保存" | 用户自动选中，输入框显示"测试负责人 (13800138001)" |

**API 验证**:
```bash
# 创建用户 API 测试
curl -s -X POST http://localhost:8080/api/v1/auth/users \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "username": "test_manager",
    "realName": "测试负责人",
    "phone": "13800138001",
    "userType": "ENTERPRISE"
  }' | jq '{
    id: .data.id,
    username: .data.username,
    generatedPassword: .data.generatedPassword
  }'
```

**验证点**:
- 用户类型为 `ENTERPRISE`（非 PROJECT）
- 返回 `generatedPassword` 字段
- 密码为12位随机字符

---

### TC-WIZARD-005: 用户选择器 - 搜索用户

**测试权限**: 超级管理员

**前置条件**: 系统中已有用户

**测试步骤**:

| 步骤 | 操作 | 期望结果 |
|------|------|----------|
| 1 | 点击"项目负责人"输入框 | 弹出"选择负责人"对话框 |
| 2 | 在搜索框输入"测试" | 显示匹配的用户列表 |
| 3 | 检查用户列表项 | 显示头像、姓名、手机号 |
| 4 | 点击"选择"按钮 | 用户选中，对话框关闭 |

---

### TC-WIZARD-006: 角色配置 - 查看权限详情

**测试权限**: 超级管理员

**前置条件**: 已完成项目信息填写，进入步骤2

**测试步骤**:

| 步骤 | 操作 | 期望结果 |
|------|------|----------|
| 1 | 检查角色模板列表 | 显示6个角色模板 |
| 2 | 检查角色说明 | 项目负责人显示"负责项目整体管理，拥有最高权限..." |
| 3 | 点击权限数量链接 | 弹出权限详情对话框 |
| 4 | 检查权限分组 | 权限按模块分组显示（用户管理、角色管理等） |
| 5 | 检查滚动区域 | 权限列表固定高度，超出部分滚动 |

**角色模板验证**:
```javascript
const expectedTemplates = [
  { code: 'PROJECT_MANAGER', name: '项目负责人' },
  { code: 'PROPERTY_MANAGER', name: '物业经理' },
  { code: 'CUSTOMER_SERVICE', name: '客服人员' },
  { code: 'MAINTENANCE', name: '维修人员' },
  { code: 'SECURITY', name: '安保人员' },
  { code: 'OWNER', name: '业主' }
];
```

---

### TC-WIZARD-007: 完成向导 - 项目编号自动生成

**测试权限**: 超级管理员

**前置条件**: 已完成项目信息和角色配置

**测试步骤**:

| 步骤 | 操作 | 期望结果 |
|------|------|----------|
| 1 | 点击"完成初始化"按钮 | 显示加载状态 |
| 2 | 等待完成 | 显示"初始化完成！"成功页面 |
| 3 | 检查项目编号 | 显示格式为 `PRJ{YYYYMM}{序号}`，如 `PRJ202602001` |
| 4 | 检查创建的角色 | 显示已创建的角色列表 |

**项目编号验证**:
```javascript
// 验证编号格式
const codePattern = /^PRJ\d{6}\d{3}$/;
assert(codePattern.test(projectCode));
// 验证编号递增
// 第二个项目应为 PRJ202602002
```

**API 验证**:
```bash
# 验证项目创建
curl -s http://localhost:8080/api/v1/mdm/projects \
  -H "Authorization: Bearer $TOKEN" | jq '.data[0] | {
    name, code, managerName
  }'
```

---

### TC-WIZARD-008: 完成向导 - 进入系统

**测试权限**: 超级管理员

**前置条件**: 向导已完成，显示成功页面

**测试步骤**:

| 步骤 | 操作 | 期望结果 |
|------|------|----------|
| 1 | 点击"进入系统"按钮 | 页面跳转到首页 |
| 2 | 检查 URL | 不再是 `/setup-wizard` 或 `/no-project` |
| 3 | 检查侧边菜单 | 显示项目相关的菜单项 |
| 4 | 检查项目选择器 | 显示刚创建的项目 |

**验证方法**:
```javascript
// 验证权限已刷新
const permissionStore = usePermissionStore();
assert(permissionStore.hasProjects === true);
assert(permissionStore.needSetupWizard === false);
assert(permissionStore.menus.length > 0);
```

---

## 三、数据清理脚本

### 3.1 清理到初始状态

```sql
-- MDM 数据库
DELETE FROM mdm_project WHERE id != '00000000-0000-0000-0000-000000000000';

-- Auth 数据库
DELETE FROM auth_user_role WHERE project_id != '00000000-0000-0000-0000-000000000000';
DELETE FROM auth_role_permission WHERE role_id IN (
  SELECT id FROM auth_role WHERE project_id != '00000000-0000-0000-0000-000000000000'
);
DELETE FROM auth_role WHERE project_id != '00000000-0000-0000-0000-000000000000';
DELETE FROM auth_permission WHERE project_id != '00000000-0000-0000-0000-000000000000';
DELETE FROM auth_user WHERE username != 'admin';
```

### 3.2 Shell 脚本

```bash
#!/bin/bash
# reset-test-data.sh - 重置测试数据到初始状态

PGPASSWORD=ether123 psql -h localhost -U ether -d ether_mdm -c \
  "DELETE FROM mdm_project WHERE id != '00000000-0000-0000-0000-000000000000';"

PGPASSWORD=ether123 psql -h localhost -U ether -d ether_auth -c \
  "DELETE FROM auth_user_role WHERE project_id != '00000000-0000-0000-0000-000000000000';
   DELETE FROM auth_role_permission WHERE role_id IN (SELECT id FROM auth_role WHERE project_id != '00000000-0000-0000-0000-000000000000');
   DELETE FROM auth_role WHERE project_id != '00000000-0000-0000-0000-000000000000';
   DELETE FROM auth_permission WHERE project_id != '00000000-0000-0000-0000-000000000000';
   DELETE FROM auth_user WHERE username != 'admin';"

echo "Test data reset complete!"
```

---

## 四、E2E 自动化测试脚本

### 4.1 Puppeteer 测试脚本

```typescript
// e2e/setup-wizard.test.ts
import puppeteer from 'puppeteer';

describe('Setup Wizard E2E Tests', () => {
  let browser: puppeteer.Browser;
  let page: puppeteer.Page;

  beforeAll(async () => {
    browser = await puppeteer.launch({ headless: false });
    page = await browser.newPage();
  });

  afterAll(async () => {
    await browser.close();
  });

  beforeEach(async () => {
    // 清除 localStorage
    await page.goto('http://localhost:5175/');
    await page.evaluate(() => localStorage.clear());
  });

  test('TC-WIZARD-001: 超级管理员首次登录进入向导模式', async () => {
    // 登录
    await page.goto('http://localhost:5175/login');
    await page.type('input[placeholder="请输入用户名"]', 'admin');
    await page.type('input[placeholder="请输入密码"]', 'admin123');
    await page.click('button[type="submit"]');

    // 等待跳转
    await page.waitForNavigation();

    // 验证 URL
    expect(page.url()).toContain('/setup-wizard');

    // 验证页面标题
    const title = await page.$eval('.wizard-header h1', el => el.textContent);
    expect(title).toContain('欢迎使用 Ether 智慧物业管理平台');
  });

  test('TC-WIZARD-004: 用户选择器 - 创建用户', async () => {
    // 假设已在向导页面
    await page.click('.user-selector input');
    await page.waitForSelector('.ant-modal');

    // 点击创建用户
    await page.click('button:has-text("创建用户")');

    // 填写表单
    await page.type('#username', 'e2e_test_user');
    await page.type('#realName', 'E2E测试用户');
    await page.type('#phone', '13900139000');

    // 提交
    await page.click('.ant-modal button[type="submit"]');

    // 验证密码弹窗
    await page.waitForSelector('.ant-modal-content:has-text("用户创建成功")');
    const password = await page.$eval('.generated-password', el => el.textContent);
    expect(password).toHaveLength(12);
  });

  test('TC-WIZARD-007: 完成向导 - 项目编号自动生成', async () => {
    // 完成向导流程...

    // 验证项目编号
    const projectCode = await page.$eval('.project-code-display .code', el => el.textContent);
    expect(projectCode).toMatch(/^PRJ\d{6}\d{3}$/);
  });
});
```

---

## 五、已知问题与修复记录

### 5.1 已修复问题

| 问题编号 | 描述 | 修复方案 | 修复日期 |
|----------|------|----------|----------|
| BUG-001 | 超级管理员登录后显示"暂无项目权限" | 修复 `isSystem` 字段序列化问题 | 2026-02-15 |
| BUG-002 | 创建用户时 userType 使用 PROJECT | 改为 ENTERPRISE | 2026-02-15 |
| BUG-003 | 对话框按钮显示英文 | 添加 ok-text/cancel-text | 2026-02-15 |
| BUG-004 | 自动生成密码未显示 | 添加密码显示弹窗 | 2026-02-15 |
| BUG-005 | 项目编号显示"-" | 从 MDM 响应获取生成的编号 | 2026-02-15 |
| BUG-006 | 向导完成后跳转到无项目页面 | 修复 hasProjects 计算逻辑 | 2026-02-15 |

---

## 六、执行记录

| 执行日期 | 执行人 | 结果 | 备注 |
|----------|--------|------|------|
| 2026-02-15 | AI Assistant | 通过 | 首次完整测试 |
| | | | |

---

## 七、版本历史

| 版本 | 日期 | 修改内容 | 修改人 |
|------|------|----------|--------|
| v1.0 | 2026-02-15 | 初始版本 | AI Assistant |
