01
🏗️
Page Object Model
LoginPage.ts and PimPage.ts encapsulate all UI interactions. Tests remain clean, readable, and maintainable — zero raw selectors in spec files.
02
🔌
Custom Fixtures
orangehrm.fixture.ts extends Playwright's base fixture to inject page objects and JSON test data directly into test functions — zero boilerplate setup per test.
03
⚙️
Environment Config
utils/env.ts loads BASE_URL, credentials, headless flag, and data file paths from .env. Zero hardcoded values anywhere in the test suite.
04
🔗
Hooks & Serial Execution
beforeAll logs in once and reuses the browser session. test.describe.serial guarantees TC-02 only runs after TC-01 completes.
05
📊
Data-Driven Testing
Employee records from employees.json and license data from license.json drive all test inputs. Adding test cases requires only editing JSON — no code changes.
06
✅
Assertions
Validates dashboard navigation, PIM module routing, employee detail persistence, and driving license field updates — covering the complete end-to-end business flow.
1import { test, expect } from '../fixtures/orangehrm.fixture';
2
3test.describe.serial('OrangeHRM Employee Flow', () => {
4
5 test.beforeAll(async ({ loginPage, page }) => {
6 // Single login — session reused across all tests
7 await loginPage.navigate();
8 await loginPage.login(env.USERNAME, env.PASSWORD);
9 });
10
11 test('Register multiple employees from JSON', async ({ pimPage, employees }) => {
12 for (const emp of employees) {
13 await pimPage.addEmployee(emp); // data-driven
14 }
15 });
16
17 test('Edit 4th employee driving license', async ({ pimPage, license }) => {
18 await pimPage.updateLicense(4, license.number);
19 await expect(pimPage.licenseField).toHaveValue(license.number);
20 });
21});