From 9cfa3e68f67aaaf44c64860b9152173a5c12e4f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Wed, 25 Mar 2026 09:44:57 +0800 Subject: [PATCH] feat: add UAT helper utilities and test data --- uat-tests/data/roles.json | 14 ++++++++++ uat-tests/data/scenarios.json | 14 ++++++++++ uat-tests/data/users.json | 20 +++++++++++++ uat-tests/utils/data-loader.ts | 43 ++++++++++++++++++++++++++++ uat-tests/utils/scenario-runner.ts | 45 ++++++++++++++++++++++++++++++ uat-tests/utils/uat-helper.ts | 43 ++++++++++++++++++++++++++++ 6 files changed, 179 insertions(+) create mode 100644 uat-tests/data/roles.json create mode 100644 uat-tests/data/scenarios.json create mode 100644 uat-tests/data/users.json create mode 100644 uat-tests/utils/data-loader.ts create mode 100644 uat-tests/utils/scenario-runner.ts create mode 100644 uat-tests/utils/uat-helper.ts diff --git a/uat-tests/data/roles.json b/uat-tests/data/roles.json new file mode 100644 index 0000000..4d42057 --- /dev/null +++ b/uat-tests/data/roles.json @@ -0,0 +1,14 @@ +{ + "admin": { + "name": "管理员", + "permissions": ["all"] + }, + "manager": { + "name": "经理", + "permissions": ["user:read", "user:write", "role:read"] + }, + "user": { + "name": "普通用户", + "permissions": ["user:read"] + } +} diff --git a/uat-tests/data/scenarios.json b/uat-tests/data/scenarios.json new file mode 100644 index 0000000..6077fae --- /dev/null +++ b/uat-tests/data/scenarios.json @@ -0,0 +1,14 @@ +{ + "user-lifecycle": { + "description": "用户生命周期测试场景", + "users": ["admin", "manager", "user"] + }, + "role-management": { + "description": "角色管理测试场景", + "users": ["admin"] + }, + "collaboration": { + "description": "多角色协作测试场景", + "users": ["admin", "manager", "user"] + } +} diff --git a/uat-tests/data/users.json b/uat-tests/data/users.json new file mode 100644 index 0000000..fbaec6b --- /dev/null +++ b/uat-tests/data/users.json @@ -0,0 +1,20 @@ +{ + "admin": { + "username": "admin", + "password": "admin123", + "role": "admin", + "email": "admin@novalon.com" + }, + "manager": { + "username": "manager", + "password": "manager123", + "role": "manager", + "email": "manager@novalon.com" + }, + "user": { + "username": "testuser", + "password": "testuser123", + "role": "user", + "email": "user@novalon.com" + } +} diff --git a/uat-tests/utils/data-loader.ts b/uat-tests/utils/data-loader.ts new file mode 100644 index 0000000..725cd8e --- /dev/null +++ b/uat-tests/utils/data-loader.ts @@ -0,0 +1,43 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { uatConfig } from '../config/uat-config'; + +export interface TestData { + users: any[]; + roles: any[]; + scenarios: any; +} + +export class DataLoader { + private static data: TestData | null = null; + + static load(): TestData { + if (!this.data) { + const usersPath = path.join(uatConfig.testDataPath, 'users.json'); + const rolesPath = path.join(uatConfig.testDataPath, 'roles.json'); + const scenariosPath = path.join(uatConfig.testDataPath, 'scenarios.json'); + + this.data = { + users: JSON.parse(fs.readFileSync(usersPath, 'utf-8')), + roles: JSON.parse(fs.readFileSync(rolesPath, 'utf-8')), + scenarios: JSON.parse(fs.readFileSync(scenariosPath, 'utf-8')) + }; + } + return this.data; + } + + static getUserByRole(role: string): any { + const data = this.load(); + return data.users.find(user => user.role === role); + } + + static getUsersByScenario(scenarioName: string): any[] { + const data = this.load(); + const scenario = data.scenarios[scenarioName]; + return scenario?.users || []; + } + + static reset() { + this.data = null; + } +} diff --git a/uat-tests/utils/scenario-runner.ts b/uat-tests/utils/scenario-runner.ts new file mode 100644 index 0000000..640f071 --- /dev/null +++ b/uat-tests/utils/scenario-runner.ts @@ -0,0 +1,45 @@ +import { test, Page } from '@playwright/test'; +import { UATHelper } from './uat-helper'; + +export interface ScenarioConfig { + name: string; + description: string; + priority: 'P0' | 'P1' | 'P2'; + setup?: (page: Page) => Promise; + execute: (page: Page, helper: UATHelper) => Promise; + verify?: (page: Page, helper: UATHelper) => Promise; + cleanup?: (page: Page) => Promise; +} + +export class ScenarioRunner { + static async runScenario(config: ScenarioConfig) { + test.describe(`${config.name} (${config.priority})`, () => { + test.beforeEach(async ({ page }) => { + if (config.setup) { + await config.setup(page); + } + }); + + test(config.description, async ({ page }) => { + const helper = new UATHelper(page); + await config.execute(page, helper); + + if (config.verify) { + await config.verify(page, helper); + } + }); + + test.afterEach(async ({ page }) => { + if (config.cleanup) { + await config.cleanup(page); + } + }); + }); + } + + static async runMultipleScenarios(scenarios: ScenarioConfig[]) { + for (const scenario of scenarios) { + await this.runScenario(scenario); + } + } +} diff --git a/uat-tests/utils/uat-helper.ts b/uat-tests/utils/uat-helper.ts new file mode 100644 index 0000000..6098f85 --- /dev/null +++ b/uat-tests/utils/uat-helper.ts @@ -0,0 +1,43 @@ +import { Page, expect } from '@playwright/test'; +import { uatConfig } from '../config/uat-config'; + +export class UATHelper { + constructor(private page: Page) {} + + async waitForElement(selector: string, options?: { timeout?: number }) { + await this.page.waitForSelector(selector, { + timeout: options?.timeout || uatConfig.timeout, + state: 'visible' + }); + } + + async waitForAPIResponse(urlPattern: string) { + return this.page.waitForResponse(response => + response.url().includes(urlPattern) + ); + } + + async waitForPageLoad() { + await this.page.waitForLoadState('networkidle'); + await this.page.waitForFunction(() => + document.readyState === 'complete' + ); + } + + async takeScreenshot(name: string) { + await this.page.screenshot({ + path: `uat-tests/screenshots/${name}.png`, + fullPage: true + }); + } + + async verifySuccessMessage(expectedMessage: string) { + const message = await this.page.textContent('.el-message--success'); + expect(message).toContain(expectedMessage); + } + + async verifyErrorMessage(expectedMessage: string) { + const message = await this.page.textContent('.el-message--error'); + expect(message).toContain(expectedMessage); + } +}