剧作家测试自动化框架(OrangeHRM)
Playwright+TypeScript测试自动化框架 OrangeHRM演示.它结合了UI测试(页面对象模型和可重用元素包装器)和API测试(fluent RequestHandler +Zod验证了有效载荷和响应),并公开了用于AI辅助测试开发的Playwright MCP服务器。
特性
- 具有共享的页面对象模型
BasePage(isOnPage()通过waitFor/try catch)和aPageManager入口点 - 可重用的UI元素包装器(
Button,Textbox,DropdownList,Checkbox,Table,Datepicker,Dialog,Menu,Tab,Toggle,Slider,FileUpload,Link,Label,RadioButton) - API层
RequestHandler(路径/参数/头文件/正文/表单→GET/POST/PUT/DELETE)以及每次通话记录选项 - Zod模式 对于请求DTO和响应实体,有效载荷在进出过程中都会被解析/验证
- 基于Faker的测试数据工厂(
prepareNewEmployeePayload,prepareNewUserPayload,prepareContactDetailsPayload)部分覆盖 - 环境感知配置(
TEST_ENV=QA|PROD|dev)viaproperties.config.ts+.env - Pino结构化日志记录(
src/utils/logger.ts)以及内存中APILogger将最近的请求/响应上下文附加到失败断言的环形缓冲区 - 诱惑和HTML记者;保留故障视频/痕迹;上的完整页面截图
- 用于AI辅助创作的剧作家MCP服务器集成
先决条件
- Node.js 18+和npm
- Git
安装
git clone https://github.com/chuongnguyen291088/pw-mcp-server.git
cd pw-mcp-server
npm ci
npx playwright install --with-deps环境配置
集 TEST_ENV 到 QA, PROD,或保持未设置(默认为 dev). properties.config.ts 将所选环境映射到从中读取的基本URL和凭据 .env:
QA_ADMIN_USERNAME=
QA_ADMIN_PASSWORD=
PROD_ADMIN_USERNAME=
PROD_ADMIN_PASSWORD=
DEV_ADMIN_USERNAME=
DEV_ADMIN_PASSWORD=目前,所有三个环境都指向 https://opensource-demo.orangehrmlive.com 对两者 base_url 和 api_host.
项目结构
├── page-objects/ (legacy — active page objects live under src/ui/page-objects)
├── src/
│ ├── api/ # VERB_resource.ts API classes (GET_users, POST_new_employee, ...)
│ ├── baseEntities.ts # Base class injecting RequestHandler
│ ├── controllers/ # Higher-level orchestrators (UserManagementController)
│ ├── entities/
│ │ ├── factories/ # Faker + Zod payload builders
│ │ │ ├── ContactDetails.factory.ts
│ │ │ ├── NewEmployee.factory.ts
│ │ │ └── NewUser.factory.ts
│ │ └── schemas/
│ │ ├── requests/ # Zod request schemas
│ │ └── responses/ # Zod response schemas (NewEmployee, NewUser, UserList)
│ ├── helpers/ # TestDataFactory scaffolding
│ ├── requestDto/ # Legacy DTO interfaces (being replaced by Zod schemas)
│ ├── ui/
│ │ ├── page-elements/ # Reusable element wrappers + BaseElement
│ │ └── page-objects/ # BasePage, PageManager, and per-screen classes
│ └── utils/ # logger.ts, apiLogger.ts, requestHandler.ts
├── tests/
│ ├── 01_authorization.spec.ts # API flow using UserManagementController + Zod-validated responses
│ ├── 01_navigation.spec.ts # UI navigation coverage via PageManager
│ ├── orangeHrm.spec.ts # Standalone browser tests (no auth dependency)
│ ├── seed.spec.ts # Scratch file for MCP/exploratory work
│ └── setup/
│ ├── authentication.setup.ts # CSRF-aware login → .auth/auth.json
│ └── talk_first_authentication.setup.ts
├── playwright.config.ts
├── properties.config.ts
├── test-options.ts # Custom fixtures: api, pageManager, pre-navigated page
├── tsconfig.json # Path aliases: @api/*, @controller/*, @schemas/*, @factories/*, ...
└── package.json可用脚本
# Runs the three main spec files against the QA env
npm test
# Standalone Talk First scenario
npm run talk-first-test这 npm test 脚本定义为:
npx cross-env TEST_ENV=qa playwright test tests/01_authorization.spec.ts tests/01_navigation.spec.ts tests/orangeHrm.spec.ts有用的一次性命令
# Run a specific spec
npx cross-env TEST_ENV=QA npx playwright test tests/01_authorization.spec.ts
# Run a specific Playwright project
npx cross-env TEST_ENV=QA npx playwright test --project="Orange HRM Execution"
# Run headed
npx cross-env TEST_ENV=QA npx playwright test --headed
# Open the last HTML report
npx playwright show-report
# Allure (results are written to ./allure-results)
npx allure generate allure-results --clean -o allure-report
npx allure open allure-report
# Start the Playwright MCP server for AI-assisted authoring
npx playwright run-test-mcp-server剧作家项目(playwright.config.ts)
Orange HRM Setup--跑步tests/setup/authentication.setup.ts,执行CSRF感知登录,并将会话保存到.auth/auth.jsonOrange HRM Execution--取决于设置项目;火柴**/01_**.spec.ts并重用存储的身份验证状态orangeHrm--独立浏览器测试**/orangeHrm.spec.ts;无身份验证依赖关系Talk Fist Setup/Talk First Execution--Talk First场景的并行设置+执行对,将状态存储在.auth/talkFirstAuth.json
全球 use 选项: baseURL 从 properties.config.ts,默认无头,1920×1080视口,打开全页截图,失败时保留视频,失败时保持跟踪,90秒测试超时。
定制夹具(test-options.ts)
始终从以下位置导入 @test-options (不是 @playwright/test)因此,测试会选择自定义夹具:
import { test, expect } from '@test-options';外露固定装置:
api--预制RequestHandler由A支持APILogger环形缓冲区pageManager—PageManager实例,已导航到仪表板page--覆盖以导航到仪表板,并在每次测试前等待仪表板标题
API层
堆栈分为四个关注点:
- Zod请求模式 (
src/entities/schemas/requests/)--定义出站有效载荷的形状/约束 - 工厂 (
src/entities/factories/)--使用Faker默认值构建有效载荷Partial重写,在返回之前通过模式验证 - API类 (
src/api/VERB_resource.ts)--延伸BaseEntities;每个暴露一个send()驱动方法this.api(theRequestHandler) - 控制器 (
src/controllers/)-将多个API类编排成更高级别的流。UserManagementController组建创建员工→ 创建用户→ 更新联系人详细信息并通过以下方式解析用户列表UserListResponseSchema
RequestHandler (src/utils/requestHandler.ts)
周围有流利的建设者 APIRequestContext:
await api
.path('/web/index.php/api/v2/pim/employees')
.body(payload)
.POST(200, { logRequestBody: true, logResponseBody: true });
await api
.path('/web/index.php/api/v2/admin/users')
.params({ limit: '50' })
.GET(200);- 链式方法:
.url(),.path(),.params(),.headers(),.body(),.form() - 终端方式:
.GET(expectedStatus),.POST(expectedStatus),.PUT(expectedStatus),.DELETE(expectedStatus) - 每种终端方法都接受
RequestOptions:logRequestHeaders,logRequestBody,logResponseBody - 如果状态代码不匹配,处理程序将抛出来自的最后50个日志条目
APILogger为了上下文 - 内部状态重置(
cleanUp())每一个请求之后,只有一个api夹具可以在通话中重复使用 POST/PUT/PATCH自动切换multipart(FormData),form(application/x-www-form-urlencoded),以及JSONdata
响应验证
响应通过Zod模式解析 src/entities/schemas/responses/ (NewEmployee, NewUser, UserList). z.infer 提供类型化访问,而无需维护并行手写接口——这是遗留问题 src/entities/*.ts 为了支持这一点,接口已被删除。
添加新的API终结点
- 在中添加Zod模式
src/entities/schemas/requests/YourRequest.schema.ts - 在中添加Zod模式
src/entities/schemas/responses/YourResponse.schema.ts - 在中添加工厂
src/entities/factories/YourThing.factory.ts使用Faker+Schema.parse({ ...defaults, ...overrides }) - 创建
src/api/VERB_resource.ts延伸BaseEntities带着一个send()方法 - 将操作暴露在
UserManagementController(或新的控制器)并通过响应模式解析响应
页面对象模型
BasePage(src/ui/page-objects/BasePage.ts)--抽象基础暴露isOnPage()(共享waitFor/try catch针对受保护的pageHeading定位器),expandMenu()对于折叠的侧边栏,以及 `navigateTo
Page()` 每个OrangeHRM区域的助手
- 每屏类扩展
BasePage仅添加特定于屏幕的定位器/操作 BasePageIndexes.ts重新导出每个页面类——始终从桶中导入,而不是单个文件PageManager将所有页面连接在一起;测试通过以下方式访问它们pm.onDashboardPage(),pm.onPIMPage(),pm.onAdminPage()等等。- 元素交互建立在中的包装器上
src/ui/page-elements/,所有这些都延伸BaseElement(使用Pino记录器进行结构化错误输出)
日志记录
src/utils/logger.ts--Pino(印刷精美,彩色)用于一般控制台输出src/utils/apiLogger.ts—APILogger维护请求/响应数据的环形缓冲区(最多50个条目)。默认情况下,标头和正文会被编辑,只有在每次调用时明确启用时才会被记录RequestOptions当断言失败时,缓冲区会出现在错误消息中。
测试数据
使用 @faker-js/faker 通过工厂 src/entities/factories/示例:
import { prepareNewEmployeePayload } from '@entities/factories/NewEmployee.factory';
const employee = prepareNewEmployeePayload({ firstName: 'Alice' });工厂填充Faker中的剩余字段,并通过匹配的Zod请求模式解析结果,因此无效的覆盖很快就会失败。
报告
- 诱惑结果→
allure-results/,生成报告→allure-report/ - 剧作家HTML报告→
playwright-report/(打开npx playwright show-report) - 故障时保留痕迹和视频
test-results/
贡献
- 创建要素分支
- 对于任何新的API工作,请遵循现有的Zod-schema-first模式
- 重用
BasePage/元素包装器,而不是滚动新的定位器 - 打开拉取请求
许可证
国际学生中心
