lexxit-automation-framework
v3.0.30
Published
Playwright test execution framework with Express API
Readme
Playwright Test Execution Framework
A Node.js + TypeScript framework that executes Playwright-based test sets defined entirely in JSON, exposed through a REST API, with a live polling dashboard to monitor execution in real time.
Tech Stack
- Node.js 22, TypeScript
- Express.js (REST API)
- Playwright (Chromium, Firefox, Edge)
- In-memory execution store (no database)
Setup
npm install
npx playwright install
npm run devThe server starts on port 5501. On startup, the console prints the API URL and a list of available endpoints.
Project Structure
new_Framework/
├── src/
│ ├── api/
│ │ └── server.ts # Express server, all routes
│ ├── runner/
│ │ └── testRunner.ts # Orchestrates a full test set (sequential/parallel)
│ ├── executor/
│ │ ├── scriptExecutor.ts # Runs one test script (all its steps)
│ │ ├── stepExecutor.ts # Runs one step, routes to the correct handler
│ │ ├── mapping.ts # Parses step_script strings into function + args
│ │ └── functionMap.ts # Maps step_script function names to handler methods
│ ├── actions/
│ │ ├── browserManager.ts # openBrowser, closeBrowser, navigation, video
│ │ ├── textHandler.ts # enterText, getText, verifyText, etc.
│ │ ├── clickHandler.ts # click, doubleClick, rightClick, hover, etc.
│ │ ├── checkboxHandler.ts # check, uncheck, toggle, verifyChecked, etc.
│ │ ├── radiobuttonHandler.ts# select, selectByValue, selectByLabel, etc.
│ │ └── dropdownHandler.ts # native/combobox/multiselect dropdown actions
│ ├── utils/
│ │ ├── locatorService.ts # Resolves an element from a list of xpath locators
│ │ └── waitConditions.ts # waitForVisible, waitForTextChange, etc.
│ ├── validator/
│ │ └── validator.ts # Validates testset/testscript/step payload shapes
│ ├── store/
│ │ └── executionStore.ts # In-memory live execution state, keyed by execution_id
│ └── types/
│ └── types.ts # All shared TypeScript interfaces
├── public/
│ └── dashboard.html # Live polling dashboard UI
├── videos/ # Saved test recordings (when video_enabled)
├── tsconfig.json
└── package.jsonHow a Request Flows
POST /executereceives the full test set JSON.- The payload is validated in three layers: testset, testscript, and step.
- If valid, an
execution_id(UUID) is generated and the response is returned immediately — the test set runs in the background. - If
open_dashboard: true, the dashboard auto-opens in your default browser (only once per server session). - The dashboard polls the server and shows live step-by-step progress.
- Once finished, the full result (same shape as a traditional synchronous response) becomes available under
final_result.
API Endpoints
| Method | Path | Description |
|--------|------|-------------|
| GET | / | Lists all available endpoints |
| POST | /execute | Submit a test set for execution |
| GET | /status/:execution_id | Live status + final result of one execution |
| GET | /executions | List all executions, latest first |
| GET | /dashboard | Live dashboard UI |
POST /execute
Request body is the full test set JSON (see Request Format below).
Response (returned immediately, before execution finishes):
{
"status": "started",
"execution_id": "a1b2c3d4-...",
"dashboard_url": "http://localhost:5501/dashboard?execution_id=a1b2c3d4-...",
"result_url": "http://localhost:5501/status/a1b2c3d4-..."
}If validation fails, responds with 400 and an errors array describing every problem found, tagged by level (testset, testscript, or step).
GET /status/:execution_id
Returns the live execution state. While running, scripts[].steps[] update in real time (pending → running → pass/fail/skip). Once finished, final_result is populated with the complete original-style response (status, full step results, summary).
{
"execution_id": "a1b2c3d4-...",
"test_set_name": "E2E Smoke Suite",
"status": "pass",
"start_time": "2026-06-17 10:00:00",
"end_time": "2026-06-17 10:00:42",
"scripts": [
{
"test_script_uid": "d42bbbd5-...",
"test_case_name": "asdfasdf444",
"status": "pass",
"steps": [
{
"step_name": "Enter 'sdf' into 'First name'",
"status": "pass",
"expected_result": "'sdf' entered into 'First name' successfully",
"comments": "'sdf' entered into 'First name' successfully",
"duration": "0 seconds"
}
]
}
],
"final_result": {
"status": "pass",
"results": [ /* ... full TestScriptResult objects ... */ ],
"summary": {
"test_set_name": "E2E Smoke Suite",
"total_scripts": 1,
"passed": 1,
"failed": 0,
"duration": "12 seconds",
"start_time": "2026-06-17 10:00:00",
"end_time": "2026-06-17 10:00:12"
}
}
}Request Format
A test set request has three nested levels: testset, testscript, and step.
{
"test_set_name": "E2E Smoke Suite",
"open_dashboard": true,
"parallel": false,
"stop_on_failure": true,
"video_enabled": true,
"exec_mode": { "mode": "medium", "delay_ms": 1000 },
"scripts": [
{
"test_script_uid": "d42bbbd5-f50f-4b71-a119-ef7294eab861",
"test_case_name": "asdfasdf444",
"voice_enabled": false,
"app_id": "1b040097-495d-4428-84d1-bd31ecc97e93",
"browser": "edge",
"headless": false,
"screenshot_mode": "on_failure",
"stop_on_failure": true,
"steps": [
{
"step_name": "Open edge",
"step_script": "tSetup.openBrowser('edge')",
"label": ""
},
{
"step_name": "Navigate to URL",
"step_script": "tSetup.navigateToURL('https://example.com')",
"label": ""
},
{
"label": "First name",
"locators": [
"//input[@id='fname']",
"//input[@id='fname' and @name='fname']"
],
"obj_uid": "066d39cd-b378-40c0-aa7f-e80e6c55a530",
"page_uid": null,
"step_name": "Enter 'sdf' into 'First name'",
"step_script": "tSetup.enterText('xpath', '//input[@id=\"fname\"]', 'sdf')",
"value": "sdf"
},
{
"step_name": "Close Browser",
"step_script": "tSetup.closeBrowser()",
"label": ""
}
]
}
]
}Testset-level fields
| Field | Type | Description |
|-------|------|--------------|
| test_set_name | string | Display name for the test set |
| open_dashboard | boolean | Auto-opens the dashboard in your browser when execution starts |
| parallel | boolean | Run scripts in parallel (max 10 concurrent) instead of sequentially |
| stop_on_failure | boolean | Reserved for testset-level stop behavior |
| video_enabled | boolean | Records a .webm video per script (forced false in fast exec mode) |
| exec_mode | object, optional | { mode: 'fast' \| 'medium' \| 'slow', delay_ms?: number }. Defaults to fast if omitted |
| scripts | array | One or more test scripts |
Testscript-level fields
| Field | Type | Description |
|-------|------|--------------|
| test_script_uid | string | Unique ID for this script |
| test_case_name | string | Display name |
| app_id | string | Application identifier |
| browser | chromium | firefox | edge | Browser to launch |
| headless | boolean | Run headless or headed |
| screenshot_mode | on_failure | always | never | Reserved for screenshot behavior |
| stop_on_failure | boolean | Skip remaining steps in this script once one fails |
| steps | array | Ordered list of steps to execute |
Step-level fields
| Field | Type | Description |
|-------|------|--------------|
| step_name | string | Display name for the step |
| step_script | string | The action to run, e.g. tSetup.enterText('id','fname','mahesh') |
| label | string | Human-readable name of the target element, used in result messages |
| locators | string[] | List of xpath locators tried together (first visible match wins) |
| obj_uid, page_uid | string | null | Optional metadata passed through to results |
Execution Modes
| Mode | Behavior |
|------|----------|
| fast (default) | No delay between steps. video_enabled is forced to false regardless of the request value |
| medium | Waits delay_ms (default 1000ms if not provided) between steps. Respects video_enabled |
| slow | Waits delay_ms (default 3000ms if not provided) between steps. Respects video_enabled |
delay_ms can be passed explicitly inside exec_mode to override the defaults for medium/slow.
Step Script Reference
Steps are written as tSetup.<functionName>(args...). The framework parses this string and routes it to the matching handler. Currently mapped functions:
| Function | Handler |
|----------|---------|
| openBrowser, closeBrowser, navigateToURL, navigateBack, navigateForward, refreshPage, getTitle, getCurrentURL | Browser Manager |
| enterText, typeText, clearText, getInputValue, appendText, setInputValue, verifyText, verifyValue, getText | Text Handler |
| clickElement, doubleClick, rightClick, hover | Click Handler |
| check_checkbox, uncheck_checkbox, verifyChecked, verifyUnchecked, verifyEnabled, verifyDisabled, verifyVisible, verifyHidden | Checkbox Handler |
| selectRadioButton | Radiobutton Handler |
| selectDropdown | Dropdown Handler |
Functions not yet mapped (e.g. dragAndDrop, file_upload, enterTextInFrame, verifyElementCount, verifyAttribute, acceptAlert, dismissAlert, getAlertText, verifyTitle, verifyURL, clickByJS) are documented as comments in functionMap.ts for future implementation.
Locator Resolution
Each step can provide multiple xpath locators as fallbacks. They're combined into a single OR-expression and the first visible, attached match is used. If the first locator in the list wasn't the one that matched, the step's comments field notes which position and xpath actually resolved — useful for cleaning up brittle locators over time.
Live Dashboard
Visit http://localhost:5501/dashboard (or let it auto-open via open_dashboard: true).
- Left navigation lists all executions, most recent at the top.
- Selecting an execution shows each script and its steps.
- Steps show a spinner while running, then a pass/fail/skip badge.
- Click any step row to expand and see its expected result and comments.
- The dashboard polls
/executionsevery 3 seconds and/status/:execution_idevery 2 seconds — no manual refresh needed.
Step Statuses
| Status | Meaning |
|--------|---------|
| pending | Not yet started (dashboard-only state) |
| running | Currently executing (dashboard-only state) |
| pass | Completed successfully |
| fail | Failed |
| skip | Skipped because an earlier step in the same script failed (when stop_on_failure: true) |
Notes
- Videos are saved to the
videos/folder, named<test_script_uid>_<timestamp>.webm. - Parallel execution runs scripts in batches of up to 10 concurrently; batches are processed one after another.
- The execution store is in-memory only — restarting the server clears all execution history.
