A production-ready hybrid test automation framework built with Playwright and TypeScript, supporting both REST API and Web UI testing with advanced features like database validation, Prometheus monitoring, and Allure reporting.
- Features
- Architecture
- Project Structure
- Quick Start
- Documentation
- Test Execution
- Reporting & Monitoring
- Configuration
- Tech Stack
- Dual API client modes - Structured (with baseURL) + Direct (full URL) calls
- Standardized API fixtures -
baseURLandextraHTTPHeadersdrive request context setup - Response validation - JSON Schema (AJV) + Zod with TypeScript integration
- Database verification - PostgreSQL & MySQL with SSH tunnel support
- Polling utilities - Reusable waits for response status and field values
- Dynamic data generation - Faker.js integration for realistic test data
- Request/response logging - Winston logger with file rotation
- Fixture-based architecture - Clean dependency injection
- Page Object Model (POM) - Maintainable, scalable test structure
- Fixture-based setup - Automatic browser lifecycle management
- Auth state management - Pre-configured authentication for faster tests
- Network interception - Mock APIs, modify responses, track requests
- Screenshot capture - Automatic failure screenshots
- TypeScript - Full type safety and IntelliSense support
- Playwright fixtures - Test isolation and parallel execution
- Winston logging - Separate logs per test run + master log
- Allure reports - HTML reports with historical trends
- Prometheus + Grafana - Test metrics visualization and monitoring
- Consul integration - Centralized configuration management (optional)
- Multi-environment - Stage, production via .env files
- Makefile automation - Simple commands for all operations
- Docker support - Containerized monitoring stack
┌─────────────────────────────────────────────────────────────────┐
│ Test Cases │
│ (/tests/*.spec.ts) │
└────────────────────────────┬────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────────┐
│ Playwright Fixtures │
│ (apiContext, apiClient, dbClient, polling, sample services) │
└────────────────────────────┬────────────────────────────────────┘
│
┌────────────┴────────────┐
│ │
↓ ↓
┌───────────────────────────┐ ┌──────────────────────┐
│ BaseTest (API) │ │ BasePage (UI) │
│ Static Utilities: │ │ Common Actions: │
│ • logger │ │ • click, fill │
│ • validator │ │ • waitFor, hover │
│ • generator │ │ • screenshot │
│ • dbClient │ │ • network helpers │
└────────────┬──────────────┘ └──────────┬───────────┘
│ │
↓ ↓
┌───────────────────────────┐ ┌──────────────────────┐
│ Service Layer (API) │ │ Page Objects (UI) │
│ • realWorldService │ │ • CreateQuestPage │
│ • baseService │ │ • UpdateQuestPage │
└────────────┬──────────────┘ └──────────────────────┘
│
↓
┌───────────────────────────┐
│ API Client │
│ • callApi() - baseURL │
│ • callDirectApi() - full │
└────────────┬──────────────┘
│
↓
┌───────────────────────────┐
│ Playwright API Context │
│ • HTTP Request/Response │
│ • Cookie/Auth State │
└───────────────────────────┘
Test Execution + Reporting Flow (Allure Included with historical data)
+─────────────────────────────+
| Playwright Runner |
+─────────────┬───────────────+
|
v
+─────────────────────────────+
| Test Execution |
| (test specs & services) |
+─────────────┬───────────────+
|
v
+─────────────────────────────+
| Allure Results |
| /allure-results/*.json |
+─────────────┬───────────────+
|
v
+─────────────────────────────+
| Allure Report Build |
| npx allure generate |
| (Retains history folder) |
+─────────────┬───────────────+
|
v
+─────────────────────────────+
| Allure HTML Report |
| /allure-report/index.html |
+─────────────────────────────+
Metrics & Observability (Prometheus + Grafana)
PLAYWRIGHT TEST RUN
|
v
+──────────────+
| Metrics Server|
| (9464 /metrics|
| Prom-client) |
+──────────────+
|
Prometheus scrapes metrics
|
v
+───────────────────+
| Prometheus |
| (stores metrics) |
+─────────┬─────────+
|
v
+───────────────────+
| Grafana |
| (Dashboards & UI) |
+───────────────────+
playtype-hybrid-framework/
├── 📂 src/
│ ├── 📂 api/
│ │ ├── client.ts # API client (callApi, callDirectApi)
│ │ ├── validator.ts # AJV & Zod validators
│ │ ├── 📂 apiUtils/
│ │ │ └── payloadGenerator.ts # Test data generators
│ │ └── 📂 services/
│ │ ├── baseService.ts # Base service with validations
│ │ └── 📂 realWorld/
│ │ └── realWorldEndpoints.ts # Service endpoint methods
│ ├── 📂 ui/
│ │ ├── 📂 pages/
│ │ │ ├── basePage.ts # Base page actions
│ │ │ ├── createQuestPage.ts # Example page object
│ │ │ └── updateQuestPage.ts
│ │ ├── 📂 actions/
│ │ │ └── helperActions.ts # Network interception, uploads
│ │ ├── 📂 uiUtils/
│ │ │ └── authUtils.ts # Auth state setup
│ │ └── poManager.ts # Page Object Manager
│ └── 📂 sharedUtils/
│ ├── config.ts # Central configuration
│ ├── consulConfig.ts # Consul integration
│ ├── dataGenerator.ts # Faker.js wrapper
│ ├── dbClient.ts # PostgreSQL/MySQL client
│ ├── logger.ts # Winston logger
│ └── reportGeneratorAllure.ts # Allure report with trends
├── 📂 tests/
│ ├── 📂 api/
│ │ ├── 📂 testRealWorldApi/
│ │ │ └── user.spec.ts # API test examples
│ │ └── schemas.ts # Zod/JSON schemas
│ ├── 📂 ui/
│ │ └── createQuestPage.spec.ts # UI test examples
│ ├── BaseApiTest.ts # API fixtures & BaseTest
│ └── baseUiTest.ts # UI fixtures
├── 📂 metrics/
│ ├── generate-metrics.ts # Prometheus metrics generator
│ ├── playwright-metrics.prom # Generated metrics file
│ └── server.ts # Metrics HTTP server
├── 📂 docs/ # Documentation
│ ├── API_TESTING.md
│ ├── UI_TESTING.md
│ ├── FIXTURES.md
│ ├── DATABASE.md
│ ├── POLLING.md
│ └── EXAMPLES.md
├── 📄 .env.stage # Stage environment config
├── 📄 .env.prod # Production environment config
├── 📄 playwright.config.ts # Playwright configuration
├── 📄 docker-compose.yml # Prometheus + Grafana
├── 📄 Makefile # Build automation
├── 📄 package.json # Dependencies
└── 📄 README.md # This file
- Node.js >= 20
- npm or yarn
- Make (pre-installed on macOS/Linux, install via Chocolatey on Windows)
# 1. Clone repository
git clone
cd playtype-hybrid-framework
# 2. Install Node.js (if not installed)
make node
# 3. Install all dependencies + Playwright browsers
make setup
# 4. Verify setup
make build# Run all tests
make test
# Run specific test file
make test-file FILE=tests/api/testRealWorldApi/user.spec.ts
# Run tests with tag
make test-tag TAG="smoke"
# View HTML report
make reportComprehensive guides available in /docs:
| Document | Description |
|---|---|
| API Testing Guide | API client usage, fixtures, validation strategies |
| UI Testing Guide | Page objects, auth setup, UI fixtures |
| Fixtures Guide | Fixture usage, test.use() overrides, examples |
| Database Testing | DB queries, SSH tunneling, validation |
| Polling Guide | Reusable polling helper, status checks, field checks |
| Configuration Guide | Environment setup, Consul, multi-env |
| Utilities Reference | Logger, data generator, validators |
| Examples | Common testing patterns and recipes |
| Makefile Commands | Complete Makefile reference |
# Run all tests (default: stage environment)
make test
# Run with specific environment
make test-env ENV=prod
# Run specific test file
make test-file FILE=tests/api/testRealWorldApi/user.spec.ts
# Run with custom environment for specific file
make test-file FILE=tests/ui/createQuestPage.spec.ts ENV=prod
# Run tests with tag
make test-tag TAG="regression"
make test-tag TAG="smoke and api"
make test-tag TAG="TC_001 or TC_002"
# Run tests multiple times (lead generation)
make test RCOUNT=5
make test-tag TAG="smoke" RCOUNT=10# Run all tests
npm test
# Run specific test
npx playwright test tests/api/user.spec.ts
# Run with grep pattern
npx playwright test --grep @smoke
# Run in headed mode
npx playwright test --headed
# Run with specific browser
npx playwright test --project=chromium# By tag
make test-tag TAG="api" # Single tag
make test-tag TAG="api and smoke" # AND logic
make test-tag TAG="api or ui" # OR logic
# By test ID
make test-tag TAG="TC_001"
make test-tag TAG="TC_001 or TC_002 or TC_003"
# By describe block
npx playwright test --grep "User Registration"
# Exclude tests
npx playwright test --grep-invert @skip# Run with 4 workers
npx playwright test --workers=4
# Fully parallel mode
npx playwright test --fully-parallel
# Serial mode (one by one)
npx playwright test --workers=1# View latest report
make report
# Generate fresh report
npx playwright show-reportAllure provides beautiful HTML reports with:
- Test execution trends over time
- Duration statistics
- Failure categorization
- Screenshots on failures
- Request/response logs
# Generate and open Allure report (with historical trends)
make allure-report
# Or step by step:
make allure-generate # Generate report
make allure-open # Open in browserAllure Features:
- Historical trends (passes/failures over time)
- Categorized failures
- Timeline visualization
- Detailed test logs
- Screenshot attachments
Monitor test metrics in real-time:
# 1. Run tests to generate metrics
make test
# 2. Generate Prometheus metrics
make test-metrics
# 3. Start monitoring stack (Prometheus + Grafana)
make monitoring-upAccess Dashboards:
- 🔵 Grafana: http://localhost:3000 (admin/admin)
- 🟠 Prometheus: http://localhost:9090
- 🟢 Metrics Server: http://localhost:9464/metrics
Stop Monitoring:
make monitoring-downAvailable Metrics:
playwright_tests_total- Total test countplaywright_tests_passed- Passed testsplaywright_tests_failed- Failed testsplaywright_tests_skipped- Skipped testsplaywright_test_duration_seconds- Test duration
Winston logger creates structured logs:
logs/
├── test-run-<timestamp>.log # Current run (debug level)
└── master.log # All runs (append mode)
Log Levels:
info- Important events (console + file)debug- Detailed debugging (file only)warn- Warningserror- Errors with stack traces
Usage in tests:
BaseTest.logger.info("Test starting...");
BaseTest.logger.debug("Detailed debug info");
BaseTest.logger.error("Test failed:", error);Create .env.stage or .env.prod:
# API Configuration
api_base_url=https://api.realworld.io
api_base_path=/api
API_BEARER_TOKEN=your-gateway-bearer-token
# UI Configuration
dashboard_url=https://app.example.com
domain=.example.com
# Named databases use DB_CONNECTIONS_JSON. Keep the JSON on one line in .env files.
DB_ENABLED=true
DB_CONNECTIONS_JSON={"orders-read":{"type":"postgres","useSsh":true,"connection":{"host":"orders-db.internal","port":5432,"user":"orders_user","password":"secret","name":"orders"},"ssh":{"host":"bastion.example.com","port":22,"username":"ubuntu","privateKeyPath":"~/.ssh/id_rsa"}},"audit-local":{"type":"mysql","useSsh":false,"connection":{"host":"127.0.0.1","port":3306,"user":"audit_user","password":"secret","name":"audit"}}}
# Auth (UI Tests)
AUTH_KEY=authState
AUTH_TOKEN=your-token-here
AUTH_USER_EMAIL=test@example.com
AUTH_USER_NAME=Test UserWhen API_BEARER_TOKEN is set, tests/BaseApiTest.ts adds Authorization: Bearer <token> to every API request context automatically. If the token is missing, the header is omitted and requests run without it.
Enable centralized config management:
// src/sharedUtils/config.ts
const config = {
useConsul: true,
consulHost: "127.0.0.1",
consulPort: 8500,
consulPrefix: "ParcelQuest",
// ...
};Consul allows dynamic configuration updates without redeploying tests.
| Category | Technology | Purpose |
|---|---|---|
| Language | TypeScript 5.0 | Type safety, IntelliSense |
| Test Runner | Playwright Test | API & UI testing |
| Assertions | Playwright expect | Built-in assertions |
| Data Generation | Faker.js | Realistic test data |
| Validation | AJV + Zod | Schema validation |
| Logging | Winston | Structured logging |
| Reporting | Allure, Playwright HTML | Test reports |
| Monitoring | Prometheus + Grafana | Metrics & dashboards |
| Config | dotenv + Consul | Environment management |
| Database | pg + mysql2 | PostgreSQL & MySQL |
| Build | TypeScript compiler | Compilation |
| Automation | Makefile | Build automation |
| Containers | Docker + Docker Compose | Monitoring stack |
make all # Full setup (deps + playwright + build)
make node # Install Node.js via nvm
make deps # Install npm dependencies
make playwright # Install Playwright browsers
make setup # Install deps + playwright
make build # TypeScript type-checkmake test # Run all tests (stage env)
make test-env ENV=prod # Run with specific env
make test-file FILE= # Run specific file
make test-file FILE= ENV=prod # Run file with env
make test-tag TAG="smoke" # Run by tag
make test-tag TAG="api and smoke" # AND condition
make test-tag TAG="api or ui" # OR condition
make test RCOUNT=5 # Repeat tests 5 times
make test-tag TAG="smoke" RCOUNT=10 # Repeat tag testsmake report # View Playwright HTML report
make allure-generate # Generate Allure report
make allure-open # Open Allure report
make allure-report # Generate + open with trendsmake test-metrics # Generate Prometheus metrics
make monitoring-up # Start Prometheus + Grafana
make monitoring-down # Stop monitoring stackmake clean-logs # Delete and recreate logs directory
make help # Show all available commandsOverride baseURL for specific tests:
// File-level override
test.use({
apiContext: async ({}, use) => {
const context = await request.newContext({
baseURL: "https://api.github.com"
});
await use(context);
await context.dispose();
}
});
test("GitHub API test", async ({ apiClient }) => {
// Uses GitHub base URL
});See Fixtures Guide for complete examples.
All service assertion helpers now support an optional mode parameter:
mode: "hard"is the default and throws immediately on failuremode: "soft"logs the failure, attaches report details, and lets the test continue
Example:
test("Soft validation example", async ({ foodApi }) => {
const response = await foodApi.getRestaurantDetails();
await foodApi.assertStatus(response, 200, { mode: "hard" });
await foodApi.validateField(response, "accepting_orders", true, { mode: "soft" });
await foodApi.validateSchema(response, someSchema, { mode: "soft" });
await foodApi.assertNoSoftAssertionFailures("Food flow soft checks failed");
});Use soft assertions for secondary checks that should not stop the flow. Use hard assertions for blockers like auth, core response status, and setup steps.
Named databases are configured through DB_CONNECTIONS_JSON. Each entry needs its own key, database type, and either a direct connection block or SSH block depending on useSsh.
Example object shape:
{
"orders-read": {
"type": "postgres",
"useSsh": true,
"connection": {
"host": "orders-db.internal",
"port": 5432,
"user": "orders_user",
"password": "secret",
"name": "orders"
},
"ssh": {
"host": "bastion.example.com",
"port": 22,
"username": "ubuntu",
"privateKeyPath": "/home/me/.ssh/id_rsa"
}
},
"audit-local": {
"type": "mysql",
"useSsh": false,
"connection": {
"host": "127.0.0.1",
"port": 3306,
"user": "audit_user",
"password": "secret",
"name": "audit"
}
}
}test("Verify DB record", async ({ rwService, dbClient }) => {
// Create via API
const response = await rwService.registerUser(payload);
const { email } = (await response.json()).user;
// Verify in a named database using the worker-scoped pool
const dbResults = await dbClient.query(
'orders-read',
'SELECT * FROM users WHERE email = $1',
[email]
);
expect(dbResults.length).toBe(1);
expect(dbResults[0].email).toBe(email);
});The dbClient fixture is worker-scoped, so each named database pool is created once per Playwright worker, reused across tests in that worker, and closed automatically during worker teardown.
Pools are opened lazily on first use for a database key. If a suite wants specific databases ready earlier, it can call dbClient.prewarm(["orders-read", "audit-local"]).
test("Mock API response", async ({ poManager }) => {
const page = poManager.getCreateQuestPage().page;
// Intercept and mock response
await page.route('**/api/quests', route => {
route.fulfill({
status: 200,
body: JSON.stringify({ success: true })
});
});
// Continue test with mocked response
});- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open Pull Request
- Use TypeScript strict mode
- Follow existing code style
- Add JSDoc comments for public methods
- Write tests for new features
- Update documentation
- Run
make buildbefore committing
This project is licensed under the MIT License.
- Issues: GitHub Issues
- Documentation: Wiki
- Discussions: GitHub Discussions
- Playwright team for the amazing testing framework
- Community contributors
- Open source libraries used in this project
Built with ❤️ using Playwright, TypeScript & Makefile
⭐ Star this repo if you find it useful!
- API Testing Guide
- UI Testing Guide
- Fixtures Reference
- Database Guide
- Polling Guide
- Examples
- Makefile Commands