feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -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);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user