|
|
@@ -2,146 +2,171 @@
|
|
|
* ================================================================
|
|
|
* 场景:能量规则配置全流程 E2E 测试
|
|
|
* ================================================================
|
|
|
- * 用户故事:管理员配置五维能量发放规则
|
|
|
+ * 目标:管理员通过 cfc-web Element UI 管理后台配置五维能量发放规则
|
|
|
+ * 部署地址:http://cfc.iwintrue.com/admin
|
|
|
*
|
|
|
* 流程步骤:
|
|
|
- * 1. 查看能量规则列表
|
|
|
- * 2. 创建新规则
|
|
|
- * 3. 启用/禁用规则
|
|
|
+ * 1. 查看能量规则列表(el-table 展示)
|
|
|
+ * 2. 创建新规则(el-dialog 表单)
|
|
|
+ * 3. 启用/禁用规则(el-switch 切换)
|
|
|
* 4. 编辑/删除规则
|
|
|
*
|
|
|
- * 关键里程碑:
|
|
|
- * - [Milestone-1] 返回规则列表
|
|
|
- * - [Milestone-2] 规则管理成功
|
|
|
+ * 前置条件:已登录管理员账号
|
|
|
* ================================================================
|
|
|
- *
|
|
|
- * 运行:npx playwright test tests/e2e/energy-rules-config.spec.js
|
|
|
*/
|
|
|
|
|
|
const { test, expect } = require('@playwright/test');
|
|
|
|
|
|
-test.describe('【场景流程】能量规则配置全流程', () => {
|
|
|
+// 共享登录逻辑 — 在每个测试前确保已登录
|
|
|
+async function ensureLoggedIn(page) {
|
|
|
+ // 检查是否已在管理后台(有侧边栏即为已登录)
|
|
|
+ const sidebar = page.locator('.sidebar-container, .el-menu-vertical-demo, .el-aside');
|
|
|
+ if (await sidebar.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 未登录则跳转登录页
|
|
|
+ await page.goto('/login');
|
|
|
+ await page.waitForSelector('.el-input__inner', { timeout: 15000 });
|
|
|
+
|
|
|
+ // 填写用户名和密码
|
|
|
+ await page.fill('.el-input__inner', 'admin', { timeout: 5000 });
|
|
|
+
|
|
|
+ // 查找密码输入框(第二个)
|
|
|
+ const passwordInputs = page.locator('.el-input__inner').filter({ hasPlaceholder: /密码/ });
|
|
|
+ if (await passwordInputs.count() > 0) {
|
|
|
+ await passwordInputs.first().fill('admin123');
|
|
|
+ } else {
|
|
|
+ // fallback: 填第二个输入框
|
|
|
+ const inputs = page.locator('.el-input__inner');
|
|
|
+ const count = await inputs.count();
|
|
|
+ if (count >= 2) {
|
|
|
+ await inputs.nth(1).fill('admin123');
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // ===== 场景1:查看能量规则列表 =====
|
|
|
+ // 点击登录按钮
|
|
|
+ await page.click('.el-button--primary.login-btn, .el-button[type="primary"]:not(.skip)');
|
|
|
+
|
|
|
+ // 等待登录成功(跳转到 dashboard)
|
|
|
+ await page.waitForURL(/\/dashboard|\/admin\/dashboard/, { timeout: 15000 });
|
|
|
+}
|
|
|
+
|
|
|
+test.describe('【场景流程】能量规则配置全流程', () => {
|
|
|
|
|
|
test('[场景1] 查看能量规则列表 - 期望返回规则列表', async ({ page }) => {
|
|
|
- // ========== Given:管理员进入能量规则页 ==========
|
|
|
- await page.goto('/#/pages/admin/energy-rules');
|
|
|
+ await ensureLoggedIn(page);
|
|
|
+ await page.goto('/energy-rule');
|
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
|
|
- // ========== When:查看规则列表 ==========
|
|
|
- await page.waitForSelector('.rule-list, .energy-rule-list', { timeout: 10000 });
|
|
|
-
|
|
|
- // ========== Then:Milestone-1 - 返回规则列表 ========
|
|
|
- const ruleItems = page.locator('.rule-item, .energy-rule');
|
|
|
- const count = await ruleItems.count();
|
|
|
+ // Element UI table
|
|
|
+ await expect(page.locator('.el-table')).toBeVisible({ timeout: 10000 });
|
|
|
|
|
|
+ // 检查表格有数据行
|
|
|
+ const rows = page.locator('.el-table__body tr');
|
|
|
+ const count = await rows.count();
|
|
|
expect(count).toBeGreaterThan(0);
|
|
|
|
|
|
- // 验证规则包含维度信息
|
|
|
- const firstRule = ruleItems.first();
|
|
|
- const dimensionTag = firstRule.locator('.dimension-tag, .rule-type');
|
|
|
- if (await dimensionTag.isVisible()) {
|
|
|
- const tagText = await dimensionTag.textContent();
|
|
|
- expect(tagText).toBeTruthy();
|
|
|
+ // 检查维度列
|
|
|
+ const dimensionCell = page.locator('.el-table__body td').filter({ hasText: /^身$|^智$|^行$|^心$|^富$/ }).first();
|
|
|
+ if (await dimensionCell.isVisible().catch(() => false)) {
|
|
|
+ const text = await dimensionCell.textContent();
|
|
|
+ expect(text).toBeTruthy();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- // ===== 场景2:创建能量规则 =====
|
|
|
-
|
|
|
test('[场景2] 创建能量规则 - 期望规则创建成功', async ({ page }) => {
|
|
|
- // ========== Given:管理员进入创建规则页 ==========
|
|
|
- await page.goto('/#/pages/admin/energy-rule-create');
|
|
|
+ await ensureLoggedIn(page);
|
|
|
+ await page.goto('/energy-rule');
|
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
|
|
- // ========== When:创建规则 ==========
|
|
|
- await page.waitForSelector('.rule-form', { timeout: 5000 });
|
|
|
+ // 点击"新增规则"按钮
|
|
|
+ await page.click('el-button:has-text("新增规则"), .el-button:has-text("新增规则")');
|
|
|
|
|
|
- // 选择维度
|
|
|
- const dimensionSelect = page.locator('.dimension-picker, select[name="dimension"]');
|
|
|
- if (await dimensionSelect.isVisible()) {
|
|
|
- await dimensionSelect.selectOption('body');
|
|
|
- }
|
|
|
+ // 等待 dialog 弹出
|
|
|
+ await page.waitForSelector('.el-dialog', { timeout: 10000 });
|
|
|
+
|
|
|
+ // 填写规则编码
|
|
|
+ await page.fill('input[placeholder="唯一编码,如 DAILY_CHECKIN"]', 'E2E_TEST_RULE');
|
|
|
|
|
|
- // 选择事件类型
|
|
|
- const eventSelect = page.locator('.event-picker, select[name="eventType"]');
|
|
|
- if (await eventSelect.isVisible()) {
|
|
|
- await eventSelect.selectOption('checkin');
|
|
|
+ // 填写规则名称
|
|
|
+ await page.fill('input[placeholder="规则名称"]', 'E2E Test Rule');
|
|
|
+
|
|
|
+ // 选择维度
|
|
|
+ const dimSelect = page.locator('.el-select').filter({ has: page.locator('.el-input[placeholder*="维度"]') });
|
|
|
+ if (await dimSelect.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
|
+ await dimSelect.click();
|
|
|
+ await page.click('.el-select-dropdown__item:has-text("身")');
|
|
|
}
|
|
|
|
|
|
- // 输入能量值
|
|
|
- const valueInput = page.locator('input[name="energyValue"], .value-input');
|
|
|
- if (await valueInput.isVisible()) {
|
|
|
- await valueInput.fill('5');
|
|
|
+ // 填写能量值
|
|
|
+ const numInput = page.locator('.el-input-number input');
|
|
|
+ if (await numInput.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
|
+ await numInput.fill('5');
|
|
|
}
|
|
|
|
|
|
- // 提交
|
|
|
- await page.click('.submit-btn, .save-btn');
|
|
|
+ // 点击保存
|
|
|
+ await page.click('.el-dialog .el-button--primary:has-text("保存")');
|
|
|
|
|
|
- // ========== Then:Milestone-2 - 创建成功 ========
|
|
|
- await page.waitForSelector('.success-tip, .rule-created', { timeout: 10000 });
|
|
|
- expect(await page.locator('.success-tip, .rule-created').isVisible()).toBeTruthy();
|
|
|
+ // 等待成功提示
|
|
|
+ await expect(page.locator('.el-message--success')).toBeVisible({ timeout: 10000 });
|
|
|
});
|
|
|
|
|
|
- // ===== 场景3:启用/禁用规则 =====
|
|
|
-
|
|
|
test('[场景3] 启用/禁用规则 - 期望状态切换成功', async ({ page }) => {
|
|
|
- // ========== Given:管理员进入规则页 ==========
|
|
|
- await page.goto('/#/pages/admin/energy-rules');
|
|
|
+ await ensureLoggedIn(page);
|
|
|
+ await page.goto('/energy-rule');
|
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
|
|
- // ========== When:切换规则状态 ==========
|
|
|
- await page.waitForSelector('.rule-item', { timeout: 10000 });
|
|
|
-
|
|
|
- const toggleBtn = page.locator('.toggle-btn, .rule-toggle').first();
|
|
|
- if (await toggleBtn.isVisible()) {
|
|
|
- await toggleBtn.click();
|
|
|
- }
|
|
|
+ // 等待表格加载
|
|
|
+ await expect(page.locator('.el-table')).toBeVisible({ timeout: 10000 });
|
|
|
|
|
|
- // ========== Then:状态切换成功 ========
|
|
|
- await page.waitForTimeout(500);
|
|
|
+ // 点击第一行的开关
|
|
|
+ const firstSwitch = page.locator('.el-table__body .el-switch').first();
|
|
|
+ if (await firstSwitch.isVisible({ timeout: 5000 }).catch(() => false)) {
|
|
|
+ await firstSwitch.click();
|
|
|
+ await page.waitForTimeout(1000);
|
|
|
|
|
|
- // 验证状态变化
|
|
|
- const statusTag = page.locator('.status-tag, .rule-status').first();
|
|
|
- if (await statusTag.isVisible()) {
|
|
|
- const statusText = await statusTag.textContent();
|
|
|
- expect(statusText).toBeTruthy();
|
|
|
+ // 等待成功消息
|
|
|
+ const successMsg = page.locator('.el-message--success');
|
|
|
+ if (await successMsg.isVisible({ timeout: 5000 }).catch(() => false)) {
|
|
|
+ await expect(successMsg).toContainText(/状态已更新/);
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- // ===== 场景4:编辑/删除规则 =====
|
|
|
-
|
|
|
test('[场景4] 编辑/删除规则 - 期望操作成功', async ({ page }) => {
|
|
|
- // ========== Given:管理员进入规则页 ==========
|
|
|
- await page.goto('/#/pages/admin/energy-rules');
|
|
|
+ await ensureLoggedIn(page);
|
|
|
+ await page.goto('/energy-rule');
|
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
|
|
- // ========== When:编辑规则 ==========
|
|
|
- await page.waitForSelector('.rule-item', { timeout: 10000 });
|
|
|
+ // 等待表格加载
|
|
|
+ await expect(page.locator('.el-table')).toBeVisible({ timeout: 10000 });
|
|
|
|
|
|
- const firstRule = page.locator('.rule-item').first();
|
|
|
- const editBtn = firstRule.locator('.edit-btn');
|
|
|
+ // 点击第一行的编辑按钮
|
|
|
+ const firstRow = page.locator('.el-table__body tr').first();
|
|
|
+ const editBtn = firstRow.locator('.el-button--primary.el-button--small:has-text("编辑")');
|
|
|
|
|
|
- if (await editBtn.isVisible()) {
|
|
|
+ if (await editBtn.isVisible({ timeout: 5000 }).catch(() => false)) {
|
|
|
await editBtn.click();
|
|
|
} else {
|
|
|
- await firstRule.click();
|
|
|
+ // fallback: 点击第一行任意可交互元素
|
|
|
+ await firstRow.click();
|
|
|
}
|
|
|
|
|
|
- await page.waitForSelector('.edit-form, .rule-form', { timeout: 5000 });
|
|
|
+ // 等待 dialog 弹出
|
|
|
+ await page.waitForSelector('.el-dialog', { timeout: 5000 });
|
|
|
|
|
|
- // 修改能量值
|
|
|
- const valueInput = page.locator('input[name="energyValue"], .value-input');
|
|
|
- if (await valueInput.isVisible()) {
|
|
|
- await valueInput.fill('10');
|
|
|
+ // 修改能量值为 10
|
|
|
+ const numInput = page.locator('.el-dialog .el-input-number input');
|
|
|
+ if (await numInput.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
|
+ await numInput.fill('10');
|
|
|
}
|
|
|
|
|
|
- // 保存
|
|
|
- await page.click('.save-btn, .submit-btn');
|
|
|
+ // 点击保存
|
|
|
+ await page.click('.el-dialog .el-button--primary:has-text("保存")');
|
|
|
|
|
|
- // ========== Then:操作成功 ========
|
|
|
- await page.waitForSelector('.success-tip, .update-success', { timeout: 10000 });
|
|
|
- expect(await page.locator('.success-tip, .update-success').isVisible()).toBeTruthy();
|
|
|
+ // 等待成功提示
|
|
|
+ await expect(page.locator('.el-message--success')).toBeVisible({ timeout: 10000 });
|
|
|
});
|
|
|
|
|
|
-});
|
|
|
+});
|