# Playwright Utils Overview ## Principle Use production-ready, fixture-based utilities from `@seontechnologies/playwright-utils` for common Playwright testing patterns. Build test helpers as pure functions first, then wrap in framework-specific fixtures for composability and reuse. ## Rationale Writing Playwright utilities from scratch for every project leads to: - Duplicated code across test suites - Inconsistent patterns and quality - Maintenance burden when Playwright APIs change - Missing advanced features (schema validation, HAR recording, auth persistence) `@seontechnologies/playwright-utils` provides: - **Production-tested utilities**: Used at SEON Technologies in production - **Functional-first design**: Core logic as pure functions, fixtures for convenience - **Composable fixtures**: Use `mergeTests` to combine utilities - **TypeScript support**: Full type safety with generic types - **Comprehensive coverage**: API requests, auth, network, logging, file handling, burn-in ## Installation ```bash npm install -D @seontechnologies/playwright-utils ``` **Peer Dependencies:** - `@playwright/test` >= 1.54.1 (required) - `ajv` >= 8.0.0 (optional - for JSON Schema validation) - `js-yaml` >= 4.0.0 (optional - for YAML schema support) - `zod` >= 3.0.0 (optional - for Zod schema validation) ## Available Utilities ### Core Testing Utilities | Utility | Purpose | Test Context | | -------------------------- | ------------------------------------------ | ------------- | | **api-request** | Typed HTTP client with schema validation | API tests | | **network-recorder** | HAR record/playback for offline testing | UI tests | | **auth-session** | Token persistence, multi-user auth | Both UI & API | | **recurse** | Cypress-style polling for async conditions | Both UI & API | | **intercept-network-call** | Network spy/stub with auto JSON parsing | UI tests | | **log** | Playwright report-integrated logging | Both UI & API | | **file-utils** | CSV/XLSX/PDF/ZIP reading & validation | Both UI & API | | **burn-in** | Smart test selection with git diff | CI/CD | | **network-error-monitor** | Automatic HTTP 4xx/5xx detection | UI tests | ## Design Patterns ### Pattern 1: Functional Core, Fixture Shell **Context**: All utilities follow the same architectural pattern - pure function as core, fixture as wrapper. **Implementation**: ```typescript // Direct import (pass Playwright context explicitly) import { apiRequest } from '@seontechnologies/playwright-utils'; test('direct usage', async ({ request }) => { const { status, body } = await apiRequest({ request, // Must pass request context method: 'GET', path: '/api/users', }); }); // Fixture import (context injected automatically) import { test } from '@seontechnologies/playwright-utils/fixtures'; test('fixture usage', async ({ apiRequest }) => { const { status, body } = await apiRequest({ // No need to pass request context method: 'GET', path: '/api/users', }); }); ``` **Key Points**: - Pure functions testable without Playwright running - Fixtures inject framework dependencies automatically - Choose direct import (more control) or fixture (convenience) ### Pattern 2: Subpath Imports for Tree-Shaking **Context**: Import only what you need to keep bundle sizes small. **Implementation**: ```typescript // Import specific utility import { apiRequest } from '@seontechnologies/playwright-utils/api-request'; // Import specific fixture import { test } from '@seontechnologies/playwright-utils/api-request/fixtures'; // Import everything (use sparingly) import { apiRequest, recurse, log } from '@seontechnologies/playwright-utils'; ``` **Key Points**: - Subpath imports enable tree-shaking - Keep bundle sizes minimal - Import from specific paths for production builds ### Pattern 3: Fixture Composition with mergeTests **Context**: Combine multiple playwright-utils fixtures with your own custom fixtures. **Implementation**: ```typescript // playwright/support/merged-fixtures.ts import { mergeTests } from '@playwright/test'; import { test as apiRequestFixture } from '@seontechnologies/playwright-utils/api-request/fixtures'; import { test as authFixture } from '@seontechnologies/playwright-utils/auth-session/fixtures'; import { test as recurseFixture } from '@seontechnologies/playwright-utils/recurse/fixtures'; import { test as logFixture } from '@seontechnologies/playwright-utils/log/fixtures'; // Merge all fixtures into one test object export const test = mergeTests(apiRequestFixture, authFixture, recurseFixture, logFixture); export { expect } from '@playwright/test'; ``` ```typescript // In your tests import { test, expect } from '../support/merged-fixtures'; test('all utilities available', async ({ apiRequest, authToken, recurse, log }) => { await log.step('Making authenticated API request'); const { body } = await apiRequest({ method: 'GET', path: '/api/protected', headers: { Authorization: `Bearer ${authToken}` }, }); await recurse( () => apiRequest({ method: 'GET', path: `/status/${body.id}` }), (res) => res.body.ready === true, ); }); ``` **Key Points**: - `mergeTests` combines multiple fixtures without conflicts - Create one merged-fixtures.ts file per project - Import test object from your merged fixtures in all tests - All utilities available in single test signature ## Integration with Existing Tests ### Gradual Adoption Strategy **1. Start with logging** (zero breaking changes): ```typescript import { log } from '@seontechnologies/playwright-utils'; test('existing test', async ({ page }) => { await log.step('Navigate to page'); // Just add logging await page.goto('/dashboard'); // Rest of test unchanged }); ``` **2. Add API utilities** (for API tests): ```typescript import { test } from '@seontechnologies/playwright-utils/api-request/fixtures'; test('API test', async ({ apiRequest }) => { const { status, body } = await apiRequest({ method: 'GET', path: '/api/users', }); expect(status).toBe(200); }); ``` **3. Expand to network utilities** (for UI tests): ```typescript import { test } from '@seontechnologies/playwright-utils/fixtures'; test('UI with network control', async ({ page, interceptNetworkCall }) => { const usersCall = interceptNetworkCall({ url: '**/api/users', }); await page.goto('/dashboard'); const { responseJson } = await usersCall; expect(responseJson).toHaveLength(10); }); ``` **4. Full integration** (merged fixtures): Create merged-fixtures.ts and use across all tests. ## Related Fragments - `api-request.md` - HTTP client with schema validation - `network-recorder.md` - HAR-based offline testing - `auth-session.md` - Token management - `intercept-network-call.md` - Network interception - `recurse.md` - Polling patterns - `log.md` - Logging utility - `file-utils.md` - File operations - `fixtures-composition.md` - Advanced mergeTests patterns ## Anti-Patterns **❌ Don't mix direct and fixture imports in same test:** ```typescript import { apiRequest } from '@seontechnologies/playwright-utils'; import { test } from '@seontechnologies/playwright-utils/auth-session/fixtures'; test('bad', async ({ request, authToken }) => { // Confusing - mixing direct (needs request) and fixture (has authToken) await apiRequest({ request, method: 'GET', path: '/api/users' }); }); ``` **✅ Use consistent import style:** ```typescript import { test } from '../support/merged-fixtures'; test('good', async ({ apiRequest, authToken }) => { // Clean - all from fixtures await apiRequest({ method: 'GET', path: '/api/users' }); }); ``` **❌ Don't import everything when you need one utility:** ```typescript import * as utils from '@seontechnologies/playwright-utils'; // Large bundle ``` **✅ Use subpath imports:** ```typescript import { apiRequest } from '@seontechnologies/playwright-utils/api-request'; // Small bundle ``` ## Reference Implementation The official `@seontechnologies/playwright-utils` repository provides working examples of all patterns described in these fragments. **Repository:** https://github.com/seontechnologies/playwright-utils **Key resources:** - **Test examples:** `playwright/tests` - All utilities in action - **Framework setup:** `playwright.config.ts`, `playwright/support/merged-fixtures.ts` - **CI patterns:** `.github/workflows/` - GitHub Actions with sharding, parallelization **Quick start:** ```bash git clone https://github.com/seontechnologies/playwright-utils.git cd playwright-utils nvm use npm install npm run test:pw-ui # Explore tests with Playwright UI npm run test:pw ``` All patterns in TEA fragments are production-tested in this repository.