Playwright Reference
Playwright BDR Template (TypeScript Reference Implementation)
Section titled “Playwright BDR Template (TypeScript Reference Implementation)”“Minimum Magic, Maximum Control” — The engineering standard for scaling test automation to 1000+ tests without Gherkin.
This repository is the Reference Implementation of the BDR Methodology using Playwright and TypeScript.
It demonstrates how to implement Behavior-Driven Living Requirements in code, generating beautiful reports without maintaining .feature files.
Key Resources
Section titled “Key Resources”- BDR Methodology Manifesto: The full theory, 4-layer architecture, anti-flakiness principles, and guides for other languages.
- Live Allure Report: See how the code below translates into “Living Documentation”.
Quick Start
Section titled “Quick Start”1. Install dependencies
Section titled “1. Install dependencies”npm cinpx playwright install2. Run demonstration
Section titled “2. Run demonstration”# Run the unified BDR cycle (Test + Report)npm run tests
# Or run individual demo testsnpx playwright test tests/demonstration/demo.spec.ts3. View Report
Section titled “3. View Report”# Use the unified command for a complete cyclenpm run tests
# Or manually generate and open the reportnpm run reportProject Structure
Section titled “Project Structure”This template strictly follows the BDR responsibility layers:
| Directory | Layer | Description |
|---|---|---|
tests/demonstration/ | Level 3 (Spec) | The entry point. Pure business intent. Reads like a story. |
tests/features/ | Level 3 (Spec) | BDR feature demonstrations (Data-driven, inline flows, API). |
src/flows/ | Level 2 (Domain) | Business Logic. Creating users, adding items to cart. Reusable components. |
src/pom/ | Level 1 (Page) | Page Objects. Selectors and raw Playwright interactions. |
src/bdr/ | Core | Utilities for Reporting, Tables, and Decorators. |
docs/contracts/ | Metadata | Examples of Consumer-Driven Contracts (CDC) for Rule #7. |
Architectural Highlights (For Engineering Reviews)
Section titled “Architectural Highlights (For Engineering Reviews)”If you are reviewing this repository for its technical depth, here are the core pieces that solve real-world enterprise automation challenges:
- BDR Decorators: src/bdr/decorators.ts - A clean implementation of TypeScript Method Decorators for zero-boilerplate reporting.
- Lazy PO Model: src/pom/LoginPage.ts - Implementation of “Lazy Getters” for Locators to prevent “Stale Element” exceptions.
- Infrastructure Health Check (Rule #0): tests/setup/health.setup.ts - Automated environment availability check that runs before all tests to prevent false-positives.
- Dependency Injection Fixtures: src/fixtures/index.ts - Level 3 fixture architecture where Business Flows receive Page Objects as dependencies.
- Deterministic Data Seeding (Rule #3): src/fixtures/index.ts - Seeded Faker implementation that ensures test data is unique across runs but stable during retries.
- Automatic Idempotency (Rule #6): src/api/Idempotency.ts - Automatically protects against duplicate data operations during network retries.
- Contract Testing Reference (Rule #7): docs/contracts/user-profile.json - Example schema for Consumer-Driven Contracts (CDC).
- Data Cleanup Strategy (Rule #8): Factories in src/factories/ now include
_cleanup: truemetadata for infrastructure-level data hygiene.
Architecture Guidelines
Section titled “Architecture Guidelines”To get the most out of BDR’s deterministic architecture, follow these rules:
BDR Step Options
Section titled “BDR Step Options”Every BDR step (Given, When, Then) accepts optional execution settings as the second argument:
await BDR.When('User buys product', { stepId: 'purchase-flow' }, async () => { await cartPage.checkout();});stepId(string):- Stabilizes history tracking. By default, BDR uses the step name as a key. If you rename a step, its history resets. Providing a
stepIdensures that analytics persist even after major refactoring.
- Stabilizes history tracking. By default, BDR uses the step name as a key. If you rename a step, its history resets. Providing a
The BDR Symbiosis: ESLint + Static Analysis
Section titled “The BDR Symbiosis: ESLint + Static Analysis”BDR focuses on runtime reporting and intent. However, for full Enterprise-grade protection, BDR works in strict symbiosis with ESLint:
- Static Anti-Patterns (ESLint): Catches
waitForTimeout,page.$, and forgottenawaitstatements right in your IDE before code is committed. - Runtime Awareness: BDR wraps your actions in semantic blocks, ensuring the report always reflects the business goal even if the tech stack underneath shifts.
Required ESLint Setup:
npm install -D eslint eslint-plugin-playwright @typescript-eslint/parser @typescript-eslint/eslint-pluginCreate eslint.config.mjs in your root directory:
import playwright from 'eslint-plugin-playwright';import tsParser from '@typescript-eslint/parser';
export default [ playwright.configs['flat/recommended'], { files: ['tests/**/*.ts', 'src/**/*.ts'], languageOptions: { parser: tsParser }, rules: { 'playwright/expect-expect': 'off', 'no-restricted-imports': [ 'error', { paths: [ { name: '@faker-js/faker', message: "Use the seeded 'faker' fixture from src/fixtures/index.ts to ensure deterministic tests.", }, ], }, ], }, }, { files: ['src/pom/**/*.ts'], rules: { // Rule #9: Stateless POM Enforcement 'no-restricted-syntax': [ 'error', { selector: "PropertyDefinition:not([key.name='page'])", message: "POM must be stateless. Don't store data in properties. Use method arguments instead.", }, ], }, }, { files: ['src/flows/**/*.ts'], rules: { // Rule #10: BDR Flow Enforcement 'no-restricted-syntax': [ 'error', { selector: "MethodDefinition[kind='method'][accessibility!='private']:not(:has(Decorator[expression.callee.name='Step']))", message: 'All public Flow methods must be decorated with @Step for BDR reporting.', }, ], }, },];Stabilizing Hooks (beforeEach)
Section titled “Stabilizing Hooks (beforeEach)”You can wrap setup code inside BDR steps within Playwright hooks to ensure consistent reporting even for background preparation:
test.beforeEach(async ({ page }) => { await BDR.Given('Setup: Login via API', async () => { await api.login(); await page.goto('/'); });});Advanced BDR Placeholders
Section titled “Advanced BDR Placeholders”The @Step decorator supports smart interpolation:
{0}: Replaces with the first argument (index-based).{}: Sequential replacement.{0.username}: Deep-property access for objects (Lead Standard).
Open for Opportunities
Section titled “Open for Opportunities”I’m currently open to QA Automation roles — remote, contract, or full-time.
Telegram: @DmitryMeAQA
Contributing
Section titled “Contributing”This repository is for the TypeScript implementation.
If you are looking for Python, Java, or C# examples, please check the Community Implementations section in the main methodology repository.