feat(admin): 添加用户管理相关文件

添加用户管理视图、API和状态管理文件
This commit is contained in:
张翔
2026-03-28 14:37:29 +08:00
commit 08ea5fbe98
1643 changed files with 255646 additions and 0 deletions
@@ -0,0 +1,180 @@
# UAT 测试文档
## 概述
UAT (User Acceptance Testing) 测试是用户验收测试,用于验证系统是否满足业务需求和用户期望。UAT测试从最终用户的角度出发,模拟真实用户的使用场景。
## 测试框架
UAT测试基于 Playwright 框架,采用 BDD (Behavior-Driven Development) 风格,使用 Given-When-Then 结构描述测试步骤。
### 核心文件
- `uat-base.ts`: UAT测试基础框架,包含测试夹具、测试步骤和断言工具
- `uat-001-auth.spec.ts`: 用户认证相关测试
- `uat-002-user-management.spec.ts`: 用户管理功能测试
- `uat-003-almanac.spec.ts`: 黄历查询功能测试
- `uat-004-fortune.spec.ts`: 运势分析功能测试
- `uat-005-ziwei.spec.ts`: 紫微斗数功能测试
## 运行UAT测试
### 前置条件
1. 确保后端服务已启动
2. 确保前端开发服务器已启动
3. 确保数据库已初始化测试数据
### 运行所有UAT测试
```bash
npm run test:e2e
```
### 运行特定UAT测试套件
```bash
# 运行认证测试
npx playwright test e2e/uat/uat-001-auth.spec.ts
# 运行用户管理测试
npx playwright test e2e/uat/uat-002-user-management.spec.ts
# 运行黄历查询测试
npx playwright test e2e/uat/uat-003-almanac.spec.ts
# 运行运势分析测试
npx playwright test e2e/uat/uat-004-fortune.spec.ts
# 运行紫微斗数测试
npx playwright test e2e/uat/uat-005-ziwei.spec.ts
```
### 运行UAT测试(UI模式)
```bash
npx playwright test e2e/uat --ui
```
### 调试UAT测试
```bash
npx playwright test e2e/uat --debug
```
## 测试用例说明
### UAT-001: 用户注册和登录流程
| 用例ID | 用例名称 | 描述 |
|---------|---------|------|
| UAT-001-01 | 用户成功登录系统 | 验证用户使用正确的凭据登录系统 |
| UAT-001-02 | 用户登录失败 - 错误密码 | 验证使用错误密码登录时显示错误消息 |
| UAT-001-03 | 用户登出系统 | 验证用户成功登出系统 |
### UAT-002: 用户管理功能
| 用例ID | 用例名称 | 描述 |
|---------|---------|------|
| UAT-002-01 | 查看用户列表 | 验证用户可以查看用户列表 |
| UAT-002-02 | 创建新用户 | 验证用户可以创建新用户 |
| UAT-002-03 | 编辑用户信息 | 验证用户可以编辑用户信息 |
| UAT-002-04 | 删除用户 | 验证用户可以删除用户 |
| UAT-002-05 | 搜索用户 | 验证用户可以搜索用户 |
### UAT-003: 黄历查询功能
| 用例ID | 用例名称 | 描述 |
|---------|---------|------|
| UAT-003-01 | 查询单日黄历 | 验证用户可以查询指定日期的黄历 |
| UAT-003-02 | 查看宜忌事项 | 验证黄历显示正确的宜忌事项 |
| UAT-003-03 | 查看吉凶方位 | 验证黄历显示正确的吉凶方位 |
| UAT-003-04 | 查看冲煞信息 | 验证黄历显示正确的冲煞信息 |
| UAT-003-05 | 查看建除十二神 | 验证黄历显示正确的建除十二神 |
### UAT-004: 运势分析功能
| 用例ID | 用例名称 | 描述 |
|---------|---------|------|
| UAT-004-01 | 查看每日运势 | 验证用户可以查看每日运势 |
| UAT-004-02 | 查看每月运势 | 验证用户可以查看每月运势 |
| UAT-004-03 | 查看每年运势 | 验证用户可以查看每年运势 |
| UAT-004-04 | 查看宫位运势 | 验证运势显示正确的宫位信息 |
| UAT-004-05 | 查看幸运信息 | 验证运势显示正确的幸运色、数字、方位 |
### UAT-005: 紫微斗数功能
| 用例ID | 用例名称 | 描述 |
|---------|---------|------|
| UAT-005-01 | 生成紫微斗数命盘 | 验证用户可以生成紫微斗数命盘 |
| UAT-005-02 | 查看十二宫位 | 验证命盘显示正确的十二宫位 |
| UAT-005-03 | 查看主星排列 | 验证命盘显示正确的主星排列 |
| UAT-005-04 | 查看四化飞星 | 验证命盘显示正确的四化飞星 |
| UAT-005-05 | 查看命盘分析 | 验证命盘显示正确的分析结果 |
| UAT-005-06 | 保存命盘 | 验证用户可以保存命盘 |
## 测试数据
UAT测试使用以下测试数据:
### 用户认证
- 用户名: `admin`
- 密码: `admin123`
### 测试用户创建
- 用户名: `testuser_${timestamp}`
- 邮箱: `testuser_${timestamp}@example.com`
- 密码: `Test@123456`
- 角色: `USER``ADMIN`
- 状态: `ACTIVE`
### 黄历查询
- 测试日期: `2024-01-01`
### 运势分析
- 测试日期: `2024-01-15`
### 紫微斗数
- 出生日期: `1990-05-15`
- 出生时间: `08:30`
- 性别: `MALE`
## 测试报告
UAT测试执行后会生成以下报告:
1. **HTML报告**: `playwright-report/index.html`
2. **JSON报告**: `test-results/results.json`
3. **截图**: 失败测试的截图保存在 `test-results/` 目录
4. **视频**: 失败测试的视频保存在 `test-results/` 目录
## 最佳实践
1. **测试独立性**: 每个测试用例应该独立运行,不依赖其他测试用例
2. **测试清理**: 每个测试用例执行后应该清理测试数据
3. **测试覆盖**: UAT测试应该覆盖所有关键业务流程
4. **测试文档**: 每个测试用例应该有清晰的描述和预期结果
5. **测试维护**: 定期更新UAT测试以反映业务需求的变化
## 故障排查
### 常见问题
1. **测试超时**
- 检查网络连接
- 检查后端服务是否正常运行
- 增加测试超时时间
2. **元素定位失败**
- 检查页面是否完全加载
- 检查元素选择器是否正确
- 使用 Playwright 的等待机制
3. **测试数据问题**
- 检查数据库是否有正确的测试数据
- 检查测试数据是否被其他测试修改
- 使用唯一的测试数据标识符
## 联系方式
如有问题,请联系测试团队或查看项目文档。
@@ -0,0 +1,63 @@
import { test, expect } from '@playwright/test';
import { test as uatTest } from './uat-base';
import { LoginPage } from '../pages/login-page';
import { DashboardPage } from '../pages/dashboard-page';
import { UserManagementPage } from '../pages/user-management-page';
import { testConfig } from '../core/test-config';
uatTest.describe('UAT-001: 用户注册和登录流程', () => {
let loginPage: LoginPage;
let dashboardPage: DashboardPage;
test.beforeEach(async ({ page, uatLogin, uatDashboard }) => {
loginPage = uatLogin;
dashboardPage = uatDashboard;
});
uatTest('UAT-001-01: 用户成功登录系统', async ({ page }) => {
await test.step('Given 用户打开登录页面', async () => {
await page.goto(testConfig.getBaseURL());
await expect(page).toHaveTitle(/登录/);
});
await test.step('When 用户输入有效的用户名和密码', async () => {
await loginPage.login('admin', 'admin123');
});
await test.step('Then 用户应成功登录并跳转到仪表盘', async () => {
await expect(page).toHaveURL(/.*dashboard/);
await expect(page.locator('[data-testid="page-title"]')).toContainText('仪表盘');
});
});
uatTest('UAT-001-02: 用户登录失败 - 错误密码', async ({ page }) => {
await test.step('Given 用户打开登录页面', async () => {
await page.goto(testConfig.getBaseURL());
});
await test.step('When 用户输入错误的密码', async () => {
await loginPage.login('admin', 'wrongpassword');
});
await test.step('Then 系统应显示错误消息', async () => {
await expect(page.locator('.ant-message-error')).toBeVisible();
await expect(page.locator('.ant-message-error')).toContainText('用户名或密码错误');
});
});
uatTest('UAT-001-03: 用户登出系统', async ({ page }) => {
await test.step('Given 用户已登录系统', async () => {
await page.goto(testConfig.getBaseURL());
await loginPage.login('admin', 'admin123');
await expect(page).toHaveURL(/.*dashboard/);
});
await test.step('When 用户点击登出按钮', async () => {
await page.click('[data-testid="logout-button"]');
});
await test.step('Then 用户应被重定向到登录页面', async () => {
await expect(page).toHaveURL(/.*login/);
});
});
});
@@ -0,0 +1,116 @@
import { test } from '@playwright/test';
import { test as uatTest } from './uat-base';
import { LoginPage } from '../pages/login-page';
import { DashboardPage } from '../pages/dashboard-page';
import { UserManagementPage } from '../pages/user-management-page';
import { testConfig } from '../core/test-config';
uatTest.describe('UAT-002: 用户管理功能', () => {
let loginPage: LoginPage;
let dashboardPage: DashboardPage;
let userManagementPage: UserManagementPage;
test.beforeEach(async ({ page, uatLogin, uatDashboard, uatUserManagement }) => {
loginPage = uatLogin;
dashboardPage = uatDashboard;
userManagementPage = uatUserManagement;
await page.goto(testConfig.getBaseURL());
await loginPage.login('admin', 'admin123');
await expect(page).toHaveURL(/.*dashboard/);
});
uatTest('UAT-002-01: 查看用户列表', async ({ page }) => {
await test.step('Given 用户已登录系统', async () => {
await expect(page).toHaveURL(/.*dashboard/);
});
await test.step('When 用户导航到用户管理页面', async () => {
await dashboardPage.navigateToUserManagement();
});
await test.step('Then 用户应看到用户列表', async () => {
await expect(page.locator('[data-testid="user-table"]')).toBeVisible();
await expect(page.locator('[data-testid="page-title"]')).toContainText('用户管理');
});
});
uatTest('UAT-002-02: 创建新用户', async ({ page }) => {
const testUsername = `testuser_${Date.now()}`;
const testEmail = `testuser_${Date.now()}@example.com`;
await test.step('Given 用户在用户管理页面', async () => {
await dashboardPage.navigateToUserManagement();
await expect(page.locator('[data-testid="user-table"]')).toBeVisible();
});
await test.step('When 用户点击新增用户按钮并填写信息', async () => {
await userManagementPage.clickAddUser();
await userManagementPage.fillUserForm({
username: testUsername,
email: testEmail,
password: 'Test@123456',
confirmPassword: 'Test@123456',
role: 'USER',
status: 'ACTIVE'
});
await userManagementPage.submitUserForm();
});
await test.step('Then 新用户应创建成功', async () => {
await expect(page.locator('.ant-message-success')).toBeVisible();
await expect(page.locator('.ant-message-success')).toContainText('用户创建成功');
});
});
uatTest('UAT-002-03: 编辑用户信息', async ({ page }) => {
await test.step('Given 用户在用户管理页面', async () => {
await dashboardPage.navigateToUserManagement();
await expect(page.locator('[data-testid="user-table"]')).toBeVisible();
});
await test.step('When 用户点击编辑按钮并修改信息', async () => {
await page.click('button:has-text("编辑")');
await page.fill('[data-testid="email-input"]', 'updated@example.com');
await page.click('[data-testid="submit-button"]');
});
await test.step('Then 用户信息应更新成功', async () => {
await expect(page.locator('.ant-message-success')).toBeVisible();
await expect(page.locator('.ant-message-success')).toContainText('用户更新成功');
});
});
uatTest('UAT-002-04: 删除用户', async ({ page }) => {
await test.step('Given 用户在用户管理页面', async () => {
await dashboardPage.navigateToUserManagement();
await expect(page.locator('[data-testid="user-table"]')).toBeVisible();
});
await test.step('When 用户点击删除按钮并确认', async () => {
await page.click('button:has-text("删除")');
await page.click('.ant-modal-confirm-btn');
});
await test.step('Then 用户应删除成功', async () => {
await expect(page.locator('.ant-message-success')).toBeVisible();
await expect(page.locator('.ant-message-success')).toContainText('用户删除成功');
});
});
uatTest('UAT-002-05: 搜索用户', async ({ page }) => {
await test.step('Given 用户在用户管理页面', async () => {
await dashboardPage.navigateToUserManagement();
await expect(page.locator('[data-testid="user-table"]')).toBeVisible();
});
await test.step('When 用户输入用户名进行搜索', async () => {
await page.fill('[data-testid="username-search-input"]', 'admin');
await page.click('[data-testid="search-button"]');
});
await test.step('Then 系统应显示匹配的用户', async () => {
await expect(page.locator('[data-testid="user-table"]')).toBeVisible();
});
});
});
@@ -0,0 +1,135 @@
import { test } from '@playwright/test';
import { test as uatTest } from './uat-base';
import { LoginPage } from '../pages/login-page';
import { DashboardPage } from '../pages/dashboard-page';
import { testConfig } from '../core/test-config';
uatTest.describe('UAT-003: 黄历查询功能', () => {
let loginPage: LoginPage;
let dashboardPage: DashboardPage;
test.beforeEach(async ({ page, uatLogin, uatDashboard }) => {
loginPage = uatLogin;
dashboardPage = uatDashboard;
await page.goto(testConfig.getBaseURL());
await loginPage.login('admin', 'admin123');
await expect(page).toHaveURL(/.*dashboard/);
});
uatTest('UAT-003-01: 查询单日黄历', async ({ page }) => {
const testDate = '2024-01-01';
await test.step('Given 用户已登录系统', async () => {
await expect(page).toHaveURL(/.*dashboard/);
});
await test.step('When 用户导航到黄历页面并选择日期', async () => {
await page.goto(`${testConfig.getBaseURL()}/almanac`);
await page.fill('[data-testid="date-picker"]', testDate);
await page.click('[data-testid="query-button"]');
});
await test.step('Then 系统应显示黄历信息', async () => {
await expect(page.locator('[data-testid="almanac-result"]')).toBeVisible();
await expect(page.locator('[data-testid="suitable-activities"]')).toBeVisible();
await expect(page.locator('[data-testid="unsuitable-activities"]')).toBeVisible();
await expect(page.locator('[data-testid="god-direction"]')).toBeVisible();
await expect(page.locator('[data-testid="fortune-direction"]')).toBeVisible();
});
});
uatTest('UAT-003-02: 查看宜忌事项', async ({ page }) => {
await test.step('Given 用户已查询黄历', async () => {
await page.goto(`${testConfig.getBaseURL()}/almanac`);
await page.fill('[data-testid="date-picker"]', '2024-01-01');
await page.click('[data-testid="query-button"]');
await expect(page.locator('[data-testid="almanac-result"]')).toBeVisible();
});
await test.step('When 用户查看宜忌事项', async () => {
await expect(page.locator('[data-testid="suitable-activities"]')).toBeVisible();
await expect(page.locator('[data-testid="unsuitable-activities"]')).toBeVisible();
});
await test.step('Then 宜忌事项应正确显示', async () => {
const suitableText = await page.locator('[data-testid="suitable-activities"]').textContent();
const unsuitableText = await page.locator('[data-testid="unsuitable-activities"]').textContent();
expect(suitableText).toBeTruthy();
expect(suitableText!.length).toBeGreaterThan(0);
expect(unsuitableText).toBeTruthy();
expect(unsuitableText!.length).toBeGreaterThan(0);
});
});
uatTest('UAT-003-03: 查看吉凶方位', async ({ page }) => {
await test.step('Given 用户已查询黄历', async () => {
await page.goto(`${testConfig.getBaseURL()}/almanac`);
await page.fill('[data-testid="date-picker"]', '2024-01-01');
await page.click('[data-testid="query-button"]');
await expect(page.locator('[data-testid="almanac-result"]')).toBeVisible();
});
await test.step('When 用户查看吉凶方位', async () => {
await expect(page.locator('[data-testid="god-direction"]')).toBeVisible();
await expect(page.locator('[data-testid="joy-direction"]')).toBeVisible();
await expect(page.locator('[data-testid="fortune-direction"]')).toBeVisible();
await expect(page.locator('[data-testid="noble-direction"]')).toBeVisible();
});
await test.step('Then 方位信息应正确显示', async () => {
const godDirection = await page.locator('[data-testid="god-direction"]').textContent();
const fortuneDirection = await page.locator('[data-testid="fortune-direction"]').textContent();
expect(godDirection).toBeTruthy();
expect(godDirection!.length).toBeGreaterThan(0);
expect(fortuneDirection).toBeTruthy();
expect(fortuneDirection!.length).toBeGreaterThan(0);
});
});
uatTest('UAT-003-04: 查看冲煞信息', async ({ page }) => {
await test.step('Given 用户已查询黄历', async () => {
await page.goto(`${testConfig.getBaseURL()}/almanac`);
await page.fill('[data-testid="date-picker"]', '2024-01-01');
await page.click('[data-testid="query-button"]');
await expect(page.locator('[data-testid="almanac-result"]')).toBeVisible();
});
await test.step('When 用户查看冲煞信息', async () => {
await expect(page.locator('[data-testid="clash-info"]')).toBeVisible();
await expect(page.locator('[data-testid="evil-direction"]')).toBeVisible();
});
await test.step('Then 冲煞信息应正确显示', async () => {
const clashInfo = await page.locator('[data-testid="clash-info"]').textContent();
const evilDirection = await page.locator('[data-testid="evil-direction"]').textContent();
expect(clashInfo).toBeTruthy();
expect(clashInfo!.length).toBeGreaterThan(0);
expect(evilDirection).toBeTruthy();
expect(evilDirection!.length).toBeGreaterThan(0);
});
});
uatTest('UAT-003-05: 查看建除十二神', async ({ page }) => {
await test.step('Given 用户已查询黄历', async () => {
await page.goto(`${testConfig.getBaseURL()}/almanac`);
await page.fill('[data-testid="date-picker"]', '2024-01-01');
await page.click('[data-testid="query-button"]');
await expect(page.locator('[data-testid="almanac-result"]')).toBeVisible();
});
await test.step('When 用户查看建除十二神', async () => {
await expect(page.locator('[data-testid="jian-chu"]')).toBeVisible();
});
await test.step('Then 建除十二神应正确显示', async () => {
const jianChu = await page.locator('[data-testid="jian-chu"]').textContent();
expect(jianChu).toBeTruthy();
expect(jianChu!.length).toBeGreaterThan(0);
});
});
});
@@ -0,0 +1,125 @@
import { test } from '@playwright/test';
import { test as uatTest } from './uat-base';
import { LoginPage } from '../pages/login-page';
import { DashboardPage } from '../pages/dashboard-page';
import { testConfig } from '../core/test-config';
uatTest.describe('UAT-004: 运势分析功能', () => {
let loginPage: LoginPage;
let dashboardPage: DashboardPage;
test.beforeEach(async ({ page, uatLogin, uatDashboard }) => {
loginPage = uatLogin;
dashboardPage = uatDashboard;
await page.goto(testConfig.getBaseURL());
await loginPage.login('admin', 'admin123');
await expect(page).toHaveURL(/.*dashboard/);
});
uatTest('UAT-004-01: 查看每日运势', async ({ page }) => {
const testDate = '2024-01-15';
await test.step('Given 用户已登录系统', async () => {
await expect(page).toHaveURL(/.*dashboard/);
});
await test.step('When 用户导航到运势页面并选择日期', async () => {
await page.goto(`${testConfig.getBaseURL()}/fortune`);
await page.fill('[data-testid="fortune-date"]', testDate);
await page.click('[data-testid="query-fortune-button"]');
});
await test.step('Then 系统应显示每日运势', async () => {
await expect(page.locator('[data-testid="daily-fortune"]')).toBeVisible();
await expect(page.locator('[data-testid="overall-luck"]')).toBeVisible();
await expect(page.locator('[data-testid="career-advice"]')).toBeVisible();
await expect(page.locator('[data-testid="wealth-advice"]')).toBeVisible();
await expect(page.locator('[data-testid="relationship-advice"]')).toBeVisible();
await expect(page.locator('[data-testid="health-advice"]')).toBeVisible();
});
});
uatTest('UAT-004-02: 查看每月运势', async ({ page }) => {
await test.step('Given 用户已登录系统', async () => {
await expect(page).toHaveURL(/.*dashboard/);
});
await test.step('When 用户导航到运势页面并切换到每月运势', async () => {
await page.goto(`${testConfig.getBaseURL()}/fortune`);
await page.click('[data-testid="monthly-fortune-tab"]');
});
await test.step('Then 系统应显示每月运势', async () => {
await expect(page.locator('[data-testid="monthly-fortune"]')).toBeVisible();
await expect(page.locator('[data-testid="monthly-overall-luck"]')).toBeVisible();
await expect(page.locator('[data-testid="monthly-key-focus"]')).toBeVisible();
await expect(page.locator('[data-testid="monthly-caution-advice"]')).toBeVisible();
});
});
uatTest('UAT-004-03: 查看每年运势', async ({ page }) => {
await test.step('Given 用户已登录系统', async () => {
await expect(page).toHaveURL(/.*dashboard/);
});
await test.step('When 用户导航到运势页面并切换到每年运势', async () => {
await page.goto(`${testConfig.getBaseURL()}/fortune`);
await page.click('[data-testid="yearly-fortune-tab"]');
});
await test.step('Then 系统应显示每年运势', async () => {
await expect(page.locator('[data-testid="yearly-fortune"]')).toBeVisible();
await expect(page.locator('[data-testid="yearly-overall-luck"]')).toBeVisible();
await expect(page.locator('[data-testid="yearly-theme"]')).toBeVisible();
await expect(page.locator('[data-testid="yearly-major-opportunity"]')).toBeVisible();
await expect(page.locator('[data-testid="yearly-major-challenge"]')).toBeVisible();
});
});
uatTest('UAT-004-04: 查看宫位运势', async ({ page }) => {
await test.step('Given 用户已查看每日运势', async () => {
await page.goto(`${testConfig.getBaseURL()}/fortune`);
await page.fill('[data-testid="fortune-date"]', '2024-01-15');
await page.click('[data-testid="query-fortune-button"]');
await expect(page.locator('[data-testid="daily-fortune"]')).toBeVisible();
});
await test.step('When 用户查看宫位运势', async () => {
await expect(page.locator('[data-testid="palace-fortunes"]')).toBeVisible();
});
await test.step('Then 宫位运势应正确显示', async () => {
const palaceCount = await page.locator('[data-testid^="palace-"]').count();
expect(palaceCount).toBeGreaterThan(0);
});
});
uatTest('UAT-004-05: 查看幸运信息', async ({ page }) => {
await test.step('Given 用户已查看每日运势', async () => {
await page.goto(`${testConfig.getBaseURL()}/fortune`);
await page.fill('[data-testid="fortune-date"]', '2024-01-15');
await page.click('[data-testid="query-fortune-button"]');
await expect(page.locator('[data-testid="daily-fortune"]')).toBeVisible();
});
await test.step('When 用户查看幸运信息', async () => {
await expect(page.locator('[data-testid="lucky-color"]')).toBeVisible();
await expect(page.locator('[data-testid="lucky-number"]')).toBeVisible();
await expect(page.locator('[data-testid="lucky-direction"]')).toBeVisible();
});
await test.step('Then 幸运信息应正确显示', async () => {
const luckyColor = await page.locator('[data-testid="lucky-color"]').textContent();
const luckyNumber = await page.locator('[data-testid="lucky-number"]').textContent();
const luckyDirection = await page.locator('[data-testid="lucky-direction"]').textContent();
expect(luckyColor).toBeTruthy();
expect(luckyColor!.length).toBeGreaterThan(0);
expect(luckyNumber).toBeTruthy();
expect(luckyNumber!.length).toBeGreaterThan(0);
expect(luckyDirection).toBeTruthy();
expect(luckyDirection!.length).toBeGreaterThan(0);
});
});
});
@@ -0,0 +1,146 @@
import { test } from '@playwright/test';
import { test as uatTest } from './uat-base';
import { LoginPage } from '../pages/login-page';
import { DashboardPage } from '../pages/dashboard-page';
import { testConfig } from '../core/test-config';
uatTest.describe('UAT-005: 紫微斗数功能', () => {
let loginPage: LoginPage;
let dashboardPage: DashboardPage;
test.beforeEach(async ({ page, uatLogin, uatDashboard }) => {
loginPage = uatLogin;
dashboardPage = uatDashboard;
await page.goto(testConfig.getBaseURL());
await loginPage.login('admin', 'admin123');
await expect(page).toHaveURL(/.*dashboard/);
});
uatTest('UAT-005-01: 生成紫微斗数命盘', async ({ page }) => {
const birthDate = '1990-05-15';
const birthTime = '08:30';
await test.step('Given 用户已登录系统', async () => {
await expect(page).toHaveURL(/.*dashboard/);
});
await test.step('When 用户导航到紫微斗数页面并输入出生信息', async () => {
await page.goto(`${testConfig.getBaseURL()}/ziwei`);
await page.fill('[data-testid="birth-date"]', birthDate);
await page.fill('[data-testid="birth-time"]', birthTime);
await page.click('[data-testid="gender-male"]');
await page.click('[data-testid="generate-chart-button"]');
});
await test.step('Then 系统应生成紫微斗数命盘', async () => {
await expect(page.locator('[data-testid="ziwei-chart"]')).toBeVisible();
await expect(page.locator('[data-testid="palace-grid"]')).toBeVisible();
await expect(page.locator('[data-testid="ming-gong"]')).toBeVisible();
await expect(page.locator('[data-testid="shen-gong"]')).toBeVisible();
});
});
uatTest('UAT-005-02: 查看十二宫位', async ({ page }) => {
await test.step('Given 用户已生成紫微斗数命盘', async () => {
await page.goto(`${testConfig.getBaseURL()}/ziwei`);
await page.fill('[data-testid="birth-date"]', '1990-05-15');
await page.fill('[data-testid="birth-time"]', '08:30');
await page.click('[data-testid="gender-male"]');
await page.click('[data-testid="generate-chart-button"]');
await expect(page.locator('[data-testid="ziwei-chart"]')).toBeVisible();
});
await test.step('When 用户查看十二宫位', async () => {
await expect(page.locator('[data-testid="palace-grid"]')).toBeVisible();
});
await test.step('Then 十二宫位应正确显示', async () => {
const palaceCount = await page.locator('[data-testid^="palace-"]').count();
expect(palaceCount).toBe(12);
});
});
uatTest('UAT-005-03: 查看主星排列', async ({ page }) => {
await test.step('Given 用户已生成紫微斗数命盘', async () => {
await page.goto(`${testConfig.getBaseURL()}/ziwei`);
await page.fill('[data-testid="birth-date"]', '1990-05-15');
await page.fill('[data-testid="birth-time"]', '08:30');
await page.click('[data-testid="gender-male"]');
await page.click('[data-testid="generate-chart-button"]');
await expect(page.locator('[data-testid="ziwei-chart"]')).toBeVisible();
});
await test.step('When 用户查看主星排列', async () => {
await expect(page.locator('[data-testid="major-stars"]')).toBeVisible();
});
await test.step('Then 主星应正确显示', async () => {
const majorStars = await page.locator('[data-testid^="major-star-"]').count();
expect(majorStars).toBeGreaterThan(0);
});
});
uatTest('UAT-005-04: 查看四化飞星', async ({ page }) => {
await test.step('Given 用户已生成紫微斗数命盘', async () => {
await page.goto(`${testConfig.getBaseURL()}/ziwei`);
await page.fill('[data-testid="birth-date"]', '1990-05-15');
await page.fill('[data-testid="birth-time"]', '08:30');
await page.click('[data-testid="gender-male"]');
await page.click('[data-testid="generate-chart-button"]');
await expect(page.locator('[data-testid="ziwei-chart"]')).toBeVisible();
});
await test.step('When 用户查看四化飞星', async () => {
await expect(page.locator('[data-testid="transformations"]')).toBeVisible();
});
await test.step('Then 四化飞星应正确显示', async () => {
await expect(page.locator('[data-testid="hua-lu"]')).toBeVisible();
await expect(page.locator('[data-testid="hua-quan"]')).toBeVisible();
await expect(page.locator('[data-testid="hua-ke"]')).toBeVisible();
await expect(page.locator('[data-testid="hua-ji"]')).toBeVisible();
});
});
uatTest('UAT-005-05: 查看命盘分析', async ({ page }) => {
await test.step('Given 用户已生成紫微斗数命盘', async () => {
await page.goto(`${testConfig.getBaseURL()}/ziwei`);
await page.fill('[data-testid="birth-date"]', '1990-05-15');
await page.fill('[data-testid="birth-time"]', '08:30');
await page.click('[data-testid="gender-male"]');
await page.click('[data-testid="generate-chart-button"]');
await expect(page.locator('[data-testid="ziwei-chart"]')).toBeVisible();
});
await test.step('When 用户查看命盘分析', async () => {
await expect(page.locator('[data-testid="chart-analysis"]')).toBeVisible();
});
await test.step('Then 命盘分析应正确显示', async () => {
const analysisText = await page.locator('[data-testid="chart-analysis"]').textContent();
expect(analysisText).toBeTruthy();
expect(analysisText!.length).toBeGreaterThan(0);
});
});
uatTest('UAT-005-06: 保存命盘', async ({ page }) => {
await test.step('Given 用户已生成紫微斗数命盘', async () => {
await page.goto(`${testConfig.getBaseURL()}/ziwei`);
await page.fill('[data-testid="birth-date"]', '1990-05-15');
await page.fill('[data-testid="birth-time"]', '08:30');
await page.click('[data-testid="gender-male"]');
await page.click('[data-testid="generate-chart-button"]');
await expect(page.locator('[data-testid="ziwei-chart"]')).toBeVisible();
});
await test.step('When 用户点击保存命盘按钮', async () => {
await page.click('[data-testid="save-chart-button"]');
});
await test.step('Then 命盘应保存成功', async () => {
await expect(page.locator('.ant-message-success')).toBeVisible();
await expect(page.locator('.ant-message-success')).toContainText('命盘保存成功');
});
});
});
@@ -0,0 +1,169 @@
import { test as base, expect, Page } from '@playwright/test';
import { LoginPage } from '../pages/login-page';
import { DashboardPage } from '../pages/dashboard-page';
import { UserManagementPage } from '../pages/user-management-page';
import { testConfig } from '../core/test-config';
export type UATFixtures = {
uatLogin: LoginPage;
uatDashboard: DashboardPage;
uatUserManagement: UserManagementPage;
};
export const test = base.extend<UATFixtures>({
uatLogin: async ({ page }, use) => {
const loginPage = new LoginPage(page);
await use(loginPage);
},
uatDashboard: async ({ page }, use) => {
const dashboardPage = new DashboardPage(page);
await use(dashboardPage);
},
uatUserManagement: async ({ page }, use) => {
const userManagementPage = new UserManagementPage(page);
await use(userManagementPage);
}
});
test.describe.configure({
mode: 'serial',
timeout: 60000
});
export const UATTestSteps = {
async completeUserRegistrationFlow(page: Page, username: string, password: string) {
const loginPage = new LoginPage(page);
await test.step('用户打开登录页面', async () => {
await page.goto(testConfig.getBaseURL());
await expect(page).toHaveTitle(/登录/);
});
await test.step('用户输入用户名和密码', async () => {
await loginPage.login(username, password);
});
await test.step('验证用户成功登录并跳转到仪表盘', async () => {
await expect(page).toHaveURL(/.*dashboard/);
});
},
async completeUserManagementFlow(page: Page, username: string, email: string, role: string) {
const dashboardPage = new DashboardPage(page);
const userManagementPage = new UserManagementPage(page);
await test.step('用户导航到用户管理页面', async () => {
await dashboardPage.navigateToUserManagement();
await expect(page).toHaveURL(/.*users/);
});
await test.step('用户点击新增用户按钮', async () => {
await userManagementPage.clickAddUser();
});
await test.step('用户填写用户信息', async () => {
await userManagementPage.fillUserForm({
username,
email,
password: 'Test@123456',
confirmPassword: 'Test@123456',
role,
status: 'ACTIVE'
});
});
await test.step('用户提交表单', async () => {
await userManagementPage.submitUserForm();
});
await test.step('验证用户创建成功', async () => {
await expect(page.locator('.ant-message-success')).toBeVisible();
});
},
async completeAlmanacQueryFlow(page: Page, date: string) {
await test.step('用户打开黄历查询页面', async () => {
await page.goto(`${testConfig.getBaseURL()}/almanac`);
});
await test.step('用户选择日期', async () => {
await page.fill('[data-testid="date-picker"]', date);
});
await test.step('用户点击查询按钮', async () => {
await page.click('[data-testid="query-button"]');
});
await test.step('验证黄历信息显示', async () => {
await expect(page.locator('[data-testid="almanac-result"]')).toBeVisible();
await expect(page.locator('[data-testid="suitable-activities"]')).toBeVisible();
await expect(page.locator('[data-testid="unsuitable-activities"]')).toBeVisible();
});
},
async completeFortuneAnalysisFlow(page: Page) {
await test.step('用户打开运势分析页面', async () => {
await page.goto(`${testConfig.getBaseURL()}/fortune`);
});
await test.step('用户查看每日运势', async () => {
await expect(page.locator('[data-testid="daily-fortune"]')).toBeVisible();
});
await test.step('用户查看每月运势', async () => {
await page.click('[data-testid="monthly-fortune-tab"]');
await expect(page.locator('[data-testid="monthly-fortune"]')).toBeVisible();
});
await test.step('用户查看每年运势', async () => {
await page.click('[data-testid="yearly-fortune-tab"]');
await expect(page.locator('[data-testid="yearly-fortune"]')).toBeVisible();
});
},
async completeZiweiChartGenerationFlow(page: Page, birthDate: string, birthTime: string) {
await test.step('用户打开紫微斗数页面', async () => {
await page.goto(`${testConfig.getBaseURL()}/ziwei`);
});
await test.step('用户输入出生日期和时间', async () => {
await page.fill('[data-testid="birth-date"]', birthDate);
await page.fill('[data-testid="birth-time"]', birthTime);
});
await test.step('用户选择性别', async () => {
await page.click('[data-testid="gender-male"]');
});
await test.step('用户点击生成命盘按钮', async () => {
await page.click('[data-testid="generate-chart-button"]');
});
await test.step('验证命盘生成成功', async () => {
await expect(page.locator('[data-testid="ziwei-chart"]')).toBeVisible();
await expect(page.locator('[data-testid="palace-grid"]')).toBeVisible();
});
}
};
export const UATAssertions = {
assertPageTitle(page: Page, expectedTitle: string) {
return expect(page).toHaveTitle(new RegExp(expectedTitle));
},
assertElementVisible(page: Page, selector: string) {
return expect(page.locator(selector)).toBeVisible();
},
assertElementText(page: Page, selector: string, expectedText: string) {
return expect(page.locator(selector)).toHaveText(expectedText);
},
assertSuccessMessage(page: Page, message: string) {
return expect(page.locator('.ant-message-success')).toContainText(message);
},
assertErrorMessage(page: Page, message: string) {
return expect(page.locator('.ant-message-error')).toContainText(message);
}
};