### Project Setup and Testing Commands Source: https://github.com/seontechnologies/playwright-utils/blob/main/CONTRIBUTING.md Commands to clone the repository, install dependencies, start the sample app, and run Playwright tests. Includes commands for UI mode and verification. ```bash git clone https://github.com/seontechnologies/playwright-utils.git cd playwright-utils nvm use npm install # Start the sample app (required for integration testing) npm run start:sample-app # In a new terminal, run tests to verify setup npm run test:pw npm run test:pw-ui # Run with UI mode ``` -------------------------------- ### Clone and Install Playwright Utils Project Source: https://github.com/seontechnologies/playwright-utils/blob/main/README.md Clones the Playwright Utils repository, installs dependencies, and sets up the development environment. Includes commands for starting a sample app and running Playwright tests. ```bash git clone https://github.com/seontechnologies/playwright-utils.git cd playwright-utils nvm use npm install # start docker # running the app initially may require docker to download things for a few minutes npm run start:sample-app # open a new tab, and run a test # run with UI, with headless, and if you want also the IDE npm run test:pw-ui npm run test:pw ``` -------------------------------- ### Playwright Network Recorder Direct Import Example (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/network-recorder.md Illustrates using the network recorder by directly importing its functions. This method requires manual setup and cleanup of the recorder, providing more granular control. It's useful when the fixture approach is not suitable for your test setup. ```typescript import { createNetworkRecorder } from '@seontechnologies/playwright-utils/network-recorder' import { test } from '@playwright/test' test('Direct usage example', async ({ page, context }, testInfo) => { const recorder = createNetworkRecorder(testInfo) await recorder.setup(context) // Your test code await page.goto('/') await recorder.cleanup() }) ``` -------------------------------- ### Package and Install Locally (Bash) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/features/opensource-plan/plan.md This sequence of commands allows you to package the project into a tarball and then install it globally on your local machine. This is useful for testing the installation process and verifying the package functionality before publishing to a registry. ```bash npm pack npm install -g ./seontechnologies-playwright-utils-*.tgz ``` -------------------------------- ### Global Setup Function for Authentication (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/auth-session.md This TypeScript file defines a global setup function that launches a browser, navigates to a login page, authenticates, and saves the session state. This function runs once before all tests in the project. ```typescript // global-setup.ts import { chromium, FullConfig } from '@playwright/test' import path from 'path' async function globalSetup(config: FullConfig) { // Create browser, context, and page const browser = await chromium.launch() const page = await browser.newPage() // Navigate to login page and authenticate await page.goto('https://example.com/login') await page.getByLabel('Username').fill('user') await page.getByLabel('Password').fill('password') await page.getByRole('button', { name: 'Sign in' }).click() // Wait for login to complete await page.waitForURL('https://example.com/dashboard') // Save storage state to a file for reuse await page.context().storageState({ path: path.join(process.cwd(), 'playwright/.auth/user.json') }) await browser.close() } export default globalSetup ``` -------------------------------- ### Playwright Configuration with Setup Project (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/auth-session.md This TypeScript configuration file sets up Playwright projects, defining a 'setup' project that runs the authentication setup and subsequent projects that depend on the saved authentication state. It specifies the use of the storageState for 'chromium' and 'firefox' projects. ```typescript // playwright.config.ts import { defineConfig, devices } from '@playwright/test' export default defineConfig({ projects: [ // Setup project that runs first { name: 'setup', testMatch: /.*\.setup\.ts/ }, // Test projects that use the authenticated state { name: 'chromium', use: { ...devices['Desktop Chrome'], // Use prepared auth state storageState: 'playwright/.auth/user.json' }, dependencies: ['setup'] // This project depends on setup project }, { name: 'firefox', use: { ...devices['Desktop Firefox'], storageState: 'playwright/.auth/user.json' }, dependencies: ['setup'] } ] }) ``` -------------------------------- ### Authentication Setup File (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/auth-session.md This TypeScript file demonstrates how to set up authentication by navigating to a login page, filling credentials, and saving the resulting session state to a JSON file. It's designed to be run as a Playwright setup project. ```typescript // tests/auth.setup.ts - Authentication setup file import { test as setup } from '@playwright/test' const authFile = 'playwright/.auth/user.json' setup('authenticate', async ({ page }) => { // Navigate to login page and authenticate via UI await page.goto('https://example.com/login') await page.getByLabel('Username').fill('user') await page.getByLabel('Password').fill('password') await page.getByRole('button', { name: 'Sign in' }).click() // Wait until the page receives the cookies await page.waitForURL('https://example.com/dashboard') // Save storage state to a file await page.context().storageState({ path: authFile }) }) ``` -------------------------------- ### Test External Installation (Bash) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/features/opensource-plan/plan.md This script tests the installation of the Playwright Utils package in a clean, separate directory. It simulates an external user installing the package from the npm registry and then runs a small Node.js script to verify successful installation and basic functionality, including subpath imports. ```bash # In a clean test directory mkdir /tmp/test-playwright-utils-install cd /tmp/test-playwright-utils-install npm init -y # Install and test (no authentication needed for public npm packages!) npm install @seontechnologies/playwright-utils node -e "const { log } = require('@seontechnologies/playwright-utils/log'); console.log('✅ Installation successful');" ``` -------------------------------- ### Environment-Based Network Recording (Bash) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/features/network-traffic-record-playback/examples.md Illustrates how to control the network recorder's mode using the `PW_NET_MODE` environment variable. Examples cover 'record', 'playback', and 'disabled' modes, along with the default behavior. ```bash # Record network traffic for later playback PW_NET_MODE=record npm run test:pw # HAR files will be created in har-files/ directory # Playback from recorded HAR files (tests run in isolation) PW_NET_MODE=playback npm run test:pw # Tests use recorded network responses # Disabled mode - normal test execution PW_NET_MODE=disabled npm run test:pw # or just npm run test:pw ``` -------------------------------- ### Playwright Configuration with Global Setup (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/auth-session.md This TypeScript configuration file references a global setup file to handle authentication and configures all tests to use the saved storage state. It defines projects for 'chromium' and 'firefox' browsers. ```typescript // playwright.config.ts import { defineConfig, devices } from '@playwright/test' export default defineConfig({ // Reference the global setup file globalSetup: './global-setup.ts', use: { // Use the saved state for all tests storageState: 'playwright/.auth/user.json' }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, { name: 'firefox', use: { ...devices['Desktop Firefox'] } } ] }) ``` -------------------------------- ### Direct Network Recorder Usage without Fixtures (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/features/network-traffic-record-playback/examples.md Shows how to use the network recorder directly without Playwright's built-in fixtures. This involves importing `createNetworkRecorder` and manually managing setup and cleanup. It also allows for custom HAR file organization. ```typescript import { test } from '@playwright/test' import { createNetworkRecorder } from '@seontechnologies/playwright-utils/network-recorder' test('Direct network recorder usage', async ({ page, context }, testInfo) => { const recorder = createNetworkRecorder(testInfo, { harFile: { harDir: 'custom-har-files', organizeByTestFile: true } }) try { await recorder.setup(context) // Your test code await page.goto('/') // Check recorder status console.log(recorder.getStatusMessage()) } finally { await recorder.cleanup() } }) ``` -------------------------------- ### Full CRUD Example with Network Recorder Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/network-recorder.md Demonstrates a complete end-to-end test for movie CRUD operations using the network recorder in 'playback' mode. It includes setup, adding, editing, and deleting a movie, relying on recorded network traffic for all interactions. This example highlights the utility's ability to support stateful mocking for realistic scenarios. ```typescript import { expect, test } from '@playwright/support/merged-fixtures' import { addMovie } from '@playwright/support/ui-helpers/add-movie' import { editMovie } from '@playwright/support/ui-helpers/edit-movie' import { log } from 'src/log' // Control mode via environment variable in the test file process.env.PW_NET_MODE = 'playback' // or 'record' when capturing test.describe('movie crud e2e - browser only (network recorder)', () => { test.beforeEach(async ({ page, networkRecorder, context }) => { // Setup network recorder based on PW_NET_MODE await networkRecorder.setup(context) await page.goto('/') }) test('should add, edit and delete a movie using only browser interactions', async ({ page, interceptNetworkCall }) => { const { name, year, rating, director } = { name: 'Inception', year: 2010, rating: 8.8, director: 'Christopher Nolan' } await log.step('add a movie using the UI') await addMovie(page, name, year, rating, director) await page.getByTestId('add-movie-button').click() await log.step('click on movie to edit') await page.getByText(name).click() await log.step('Edit the movie') const { editedName, editedYear, editedRating, editedDirector } = { editedName: "Inception (Director's Cut)", editedYear: 2011, editedRating: 9.0, editedDirector: 'Christopher Nolan' } const loadUpdateMovie = interceptNetworkCall({ method: 'PUT', url: '/movies/*' }) await log.step('edit movie using the UI') await editMovie(page, editedName, editedYear, editedRating, editedDirector) await loadUpdateMovie // Go back and verify edit await page.getByTestId('back').click() await expect(page).toHaveURL('/movies') await page.getByText(editedName).waitFor() await log.step('delete movie from list') await page.getByTestId(`delete-movie-${editedName}`).click() await expect( page.getByTestId(`delete-movie-${editedName}`) ).not.toBeVisible() }) }) ``` -------------------------------- ### Example Command Line Execution for Burn-in Source: https://context7.com/seontechnologies/playwright-utils/llms.txt This bash snippet shows how to execute the burn-in script from the command line using `npx tsx`. Ensure you have `tsx` installed globally or as a dev dependency. ```bash # Run from command line # npx tsx burn-in-script.ts ``` -------------------------------- ### Complete Custom Auth Provider Example in TypeScript Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/auth-session.md This comprehensive TypeScript example shows a full implementation of a custom `AuthProvider`. It includes methods for managing authentication tokens, extracting data, checking token validity, and defining environment-specific configurations. It relies on several imported utility functions. ```typescript // playwright/support/auth/custom-auth-provider.ts import type { APIRequestContext } from '@playwright/test' import { type AuthOptions, type AuthProvider, AuthSessionManager, authStorageInit, getStorageDir, getTokenFilePath, saveStorageState } from '../../../src/auth-session' import { log } from '../../../src/log' import { acquireToken } from './token/acquire' import { checkTokenValidity } from './token/check-validity' import { isTokenExpired } from './token/is-expired' import { extractToken, extractCookies } from './token/extract' import { getEnvironment } from './get-environment' import { getUserIdentifier } from './get-user-identifier' import { getBaseUrl } from './get-base-url' const myCustomProvider: AuthProvider = { // Get the current base URL to use getBaseUrl, // Get the current environment to use getEnvironment, // Get the current user identifier to use getUserIdentifier, // Extract token from storage state extractToken, // Extract cookies from token data extractCookies, // Check if token is expired isTokenExpired, // Main token management method async manageAuthToken(request: APIRequestContext, options: AuthOptions = {}) { const environment = this.getEnvironment(options) const userIdentifier = this.getUserIdentifier(options) // Get the path for storing the token const tokenPath = getTokenFilePath({ environment, userIdentifier, tokenFileName: 'storage-state.json' }) // Check if we already have a valid token const validToken = await checkTokenValidity(tokenPath) if (validToken) { return validToken } // No valid token found, initialize storage and get a new one authStorageInit({ environment, userIdentifier }) const storageState = await acquireToken( request, environment, userIdentifier, options ) // Save the token for future use saveStorageState(tokenPath, storageState) return storageState }, // Clear token when needed clearToken(options: AuthOptions = {}) { const environment = this.getEnvironment(options) const userIdentifier = this.getUserIdentifier(options) const storageDir = getStorageDir({ environment, userIdentifier }) const authManager = AuthSessionManager.getInstance({ storageDir }) authManager.clearToken() return true } } export default myCustomProvider ``` -------------------------------- ### Use Fixtures for Network Recorder Consistency Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/features/network-traffic-record-playback/examples.md This TypeScript code snippet illustrates the best practice of using fixtures provided by Playwright utilities for network recording. Using fixtures ensures automatic cleanup and consistency, contrasting with manual setup which requires explicit cleanup code. ```typescript // ✅ Good - use fixtures for automatic cleanup import { test } from '@seontechnologies/playwright-utils/network-recorder/fixtures' // ❌ Manual - requires explicit cleanup import { createNetworkRecorder } from '@seontechnologies/playwright-utils/network-recorder' ``` -------------------------------- ### Test Example with Authenticated State and Token Reuse (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/auth-session.md This TypeScript test file demonstrates how to write tests that utilize an authenticated state, assuming an `authToken` fixture is available. It includes examples of checking for the token's existence and using it to make authenticated API requests. ```typescript // From playwright/tests/auth-session/auth-session-sanity.spec.ts (actual working test) import { log } from '../../../src/log' import { test, expect } from '../../support/merged-fixtures' /** * Create a preview of a token that's safe for logging */ const createTokenPreview = (token: string): string => token.substring(0, 10) + '...' + token.substring(token.length - 5) // Configure tests to run in serial mode for proper token reuse testing test.describe.configure({ mode: 'serial' }) test.describe('Auth Session Example', () => { test('should have auth token available', async ({ authToken }) => { // Token is already obtained via the fixture expect(authToken).toBeDefined() expect(typeof authToken).toBe('string') expect(authToken.length).toBeGreaterThan(0) // Log token for debugging (shortened for security) const tokenPreview = createTokenPreview(authToken) await log.info(`Token available without explicit fetching: ${tokenPreview}`) }) test('should reuse the same auth token', async ({ authToken, apiRequest }) => { // The token is already available without making a new request expect(authToken).toBeDefined() // We can use the token for API requests const { status } = await apiRequest({ method: 'GET', path: '/movies', headers: { Authorization: authToken // Use the token directly } }) expect(status).toBe(200) }) }) ``` -------------------------------- ### Playback Configuration with Fallback (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/features/network-traffic-record-playback/examples.md Configures the network recorder for 'playback' mode. This example includes options for fallback behavior (using live requests if HAR entries are missing) and filtering which requests to playback. ```typescript // Playback mode configuration const recorderContext = await networkRecorder.setup(context, { playback: { fallback: true, // Fall back to live requests if HAR entry missing urlFilter: /api\/v1/ // Only playback API calls } }) ``` -------------------------------- ### Update Playwright Config with Global Setup Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/auth-session.md This TypeScript code snippet demonstrates how to configure your Playwright configuration file. It sets the `globalSetup` option to point to your global setup file and defines the `baseURL` for Playwright's requests. This ensures consistent base URLs across your tests. ```typescript // playwright.config.ts import { defineConfig } from '@playwright/test' const BASE_URL = 'http://localhost:3000' export default defineConfig({ // Other config options... // Point to your global setup file globalSetup: './playwright/support/global-setup.ts', use: { baseURL: BASE_URL } // Other config options... }) ``` -------------------------------- ### Pre-fetch Tokens in Global Setup (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/auth-session.md This TypeScript snippet shows how to pre-fetch authentication tokens during the global setup phase of a testing framework. This is crucial for improving test performance by ensuring tokens are readily available. It initializes storage, configures the authentication session, sets the auth provider, and then initiates a global pre-fetch of all necessary tokens. ```typescript // global-setup.ts import { authStorageInit, configureAuthSession, setAuthProvider, authGlobalInit } from './auth' import myCustomProvider from './custom-auth-provider' async function globalSetup() { // Initialize storage authStorageInit() // Configure basic settings configureAuthSession({ environment: process.env.TEST_ENV || 'local', userIdentifier: 'default', debug: true }) // Set the auth provider setAuthProvider(myCustomProvider) // Pre-fetch tokens for all configured environments and users // This happens once before all tests run await authGlobalInit() } export default globalSetup ``` -------------------------------- ### Custom HAR Directory Configuration (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/features/network-traffic-record-playback/examples.md Configures the network recorder to save HAR files in a custom directory. It demonstrates setting `harDir`, `baseName`, and `organizeByTestFile` options during the setup process. ```typescript const recorderContext = await networkRecorder.setup(context, { harFile: { harDir: 'my-har-files', baseName: 'api-calls', organizeByTestFile: false // All HAR files in same directory } }) ``` -------------------------------- ### Project Build and Utility Commands Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/project-architecture.md Essential npm scripts for managing the project's build process, cleaning the distribution directory, and performing validation checks. These commands ensure the project is correctly built, tested, and ready for deployment. ```bash npm run start:sample-app npm run build npm run clean npm run typecheck npm run lint npm run fix:format npm run validate npm run publish:local ``` -------------------------------- ### Use Synchronous Logging Methods Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/log.md Provides synchronous methods for logging in contexts where asynchronous operations like `async/await` are not available, such as global setup or utility functions. Examples include `log.infoSync`, `log.successSync`, and `log.errorSync`. ```typescript // Use sync methods when async/await isn't available log.infoSync('Initializing configuration') log.successSync('Environment configured') log.errorSync('Setup failed') ``` -------------------------------- ### Using API Request in Non-Test Contexts - TypeScript Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/api-request.md Provides an example of using the `apiRequest` utility outside of Playwright's test context, such as in global setup or helper functions. It shows how to create a separate request context and disable test step wrapping. ```typescript import { apiRequest } from '@seontechnologies/playwright-utils' import { request } from '@playwright/test' // For use in global setup or outside of test.step() contexts async function fetchToken() { const requestContext = await request.newContext() const { body } = await apiRequest({ request: requestContext, method: 'GET', path: '/auth/token', baseUrl: 'https://api.example.com', testStep: false // Disable test.step wrapping for non-test contexts }) await requestContext.dispose() return body.token } ``` -------------------------------- ### Configure Global Authentication Setup for Playwright Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/auth-session.md Sets up the global authentication configuration for Playwright tests. This involves initializing storage, configuring session settings, and setting the authentication provider. The order of function calls is critical for correct initialization. Dependencies include '@seontechnologies/playwright-utils/auth-session' and a custom auth provider. ```typescript // playwright/support/global-setup.ts import { authStorageInit, setAuthProvider, configureAuthSession, authGlobalInit } from '@seontechnologies/playwright-utils/auth-session' import myCustomProvider from './auth/custom-auth-provider' async function globalSetup() { // Initialize storage, config and provider in the correct order authStorageInit() configureAuthSession({ // Auth sessions stored in .auth at repo root (.gitignore this) debug: true }) setAuthProvider(myCustomProvider) // Optional: pre-fetch all tokens for better test startup performance await authGlobalInit() } export default globalSetup ``` -------------------------------- ### Basic Network Recording with Fixtures (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/features/network-traffic-record-playback/examples.md Demonstrates basic network traffic recording using Playwright fixtures. It sets up the network recorder, logs its mode and HAR file path, and then executes test actions. Cleanup is handled automatically by the fixture. ```typescript import { test } from '@seontechnologies/playwright-utils/network-recorder/fixtures' test('Record network traffic during test', async ({ page, context, networkRecorder }) => { // Setup network recording const recorderContext = await networkRecorder.setup(context) console.log(`Mode: ${recorderContext.mode}`) console.log(`HAR file: ${recorderContext.harFilePath}`) // Your test code - network traffic will be recorded/played back based on PW_NET_MODE await page.goto('/') await page.locator('button').click() // Cleanup happens automatically }) ``` -------------------------------- ### Make GET Request with Playwright's apiRequest Fixture Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/api-request.md Shows how to use the apiRequest utility as a Playwright fixture. This integrates seamlessly into Playwright tests, allowing typed responses and direct assertion on the response body. It simplifies request setup within test files. ```typescript // Import the fixture import { test } from '@seontechnologies/playwright-utils/fixtures' // Use the fixture in your tests test('should fetch user data', async ({ apiRequest }) => { const { status, body } = await apiRequest({ method: 'GET', path: '/api/users/123', headers: { Authorization: 'Bearer token' } }) // Assertions expect(status).toBe(200) expect(body.name).toBe('John Doe') }) ``` -------------------------------- ### Advanced Logging Scenarios in Playwright Tests (TypeScript) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/log.md Illustrates various advanced logging scenarios within Playwright tests, including logging object payloads, conditional logging based on environment variables, and logging sensitive information like authentication tokens. These examples show how to integrate logging with test setup, assertions, and data handling. ```typescript // From playwright/tests/external/todo-with-logs.spec.ts test.beforeEach(async ({ page }) => { await log.step('Navigate to TodoMVC app') await page.goto('https://demo.playwright.dev/todomvc') }) test('Log demo', async () => { await log.info('Starting TodoMVC test suite with enhanced logging') // Object logging with debug level await log.debug({ timestamp: new Date(), recordCount: 42 }) // Success logging await log.success('success!') // Step logging (shows in Playwright UI) await log.step( 'You should not log an object here, steps only display strings' ) // Objects work but show empty in test steps await log.info({ someText: 'objects will show empty in test steps' }) }) ``` ```typescript // From playwright/tests/sample-app/backend/crud-movie-event.spec.ts test('should crud', async ({ authToken, addMovie, getAllMovies }) => { await log.info(authToken) // Log the auth token // Add movie with logging const { body: createResponse } = await addMovie(authToken, movie) const movieId = createResponse.data.id await log.step('isKafkaWorking: ' + isKafkaWorking) // Conditional logging based on environment if (isKafkaWorking) { await log.warning('Kafka is not working, skipping Kafka event checks') } }) ``` ```typescript // From playwright/tests/auth-session/auth-session-sanity.spec.ts test('should have auth token available', async ({ authToken }) => { // Create safe token preview for logging const tokenPreview = createTokenPreview(authToken) await log.info(`Token available without explicit fetching: ${tokenPreview}`) }) test('should reuse the same auth token', async ({ authToken }) => { const tokenPreview = createTokenPreview(authToken) await log.step( `Second test reuses the token without fetching again: ${tokenPreview}` ) }) ``` -------------------------------- ### Complex URL Mapping for Multi-Environment Setup Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/network-recorder.md Configure comprehensive URL mapping for complex enterprise applications with multiple environments. This example combines static hostname mapping and pattern-based matching to ensure HAR files function correctly across various staging, production, and preview environments by consistently mapping them to a base development URL. ```typescript // Real-world configuration for multiple environments await networkRecorder.setup(context, { playback: { urlMapping: { // Static mapping for known environments hostMapping: { // Local development 'localhost:3000': 'admin.seondev.space', // Staging environments 'admin-staging.seon.io': 'admin.seondev.space', 'admin-staging.us-east-1-main.seon.io': 'admin.seondev.space', // Production environments 'admin.seon.io': 'admin.seondev.space', 'admin.us-east-1-main.seon.io': 'admin.seondev.space', 'admin.ap-southeast-1-main.seon.io': 'admin.seondev.space' }, // Pattern matching for dynamic environments patterns: [ // PR preview environments (admin-1234.seondev.space) { match: /admin-\d+\.seondev\.space/, replace: 'admin.seondev.space' }, // Staging PR previews { match: /admin-staging-pr-\w+-\d\.seon\.io/, replace: 'admin.seondev.space' } ] } } }) ``` -------------------------------- ### Authenticated Network Recording Example Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/network-recorder.md Demonstrates how to perform network recording after authenticating a user. It shows the sequence of logging in, setting up the network recorder with the authenticated context, and then testing authenticated flows. ```typescript test('Authenticated recording', async ({ page, context, authSession, networkRecorder }) => { // First authenticate await authSession.login('testuser', 'password') // Then setup network recording with authenticated context await networkRecorder.setup(context) // Test authenticated flows await page.goto('/dashboard') }) ``` -------------------------------- ### Demonstrate Different HTTP Error Patterns on Same Endpoint Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/network-error-monitor.md This TypeScript example showcases how the Network Error Monitor distinguishes between different error patterns, such as GET 404 vs. POST 500 on the same endpoint. It uses a fixture with `maxTestsPerError` to illustrate how repeated errors are handled. The expected outcome is that the first occurrence of each unique pattern fails the test, while subsequent occurrences of the same pattern pass if the limit is reached. ```typescript import { test, expect } from '@seontechnologies/playwright-utils/network-error-monitor/fixtures' // Configure with maxTestsPerError to limit domino effect const testWithLimit = test.extend( createNetworkErrorMonitorFixture({ excludePatterns: [], maxTestsPerError: 1 }) ) test.describe('Complex error patterns', () => { testWithLimit.fail('GET 404 on user endpoint', async ({ page }) => { // Pattern: GET:404:/api/users // First test with this pattern - will fail await page.goto('/users/search') await page.getByRole('button', { name: 'Search' }).click() // GET 404 /api/users/999 (user not found) expect(true).toBe(true) }) testWithLimit.fail('POST 500 on user endpoint', async ({ page }) => { // Pattern: POST:500:/api/users (DIFFERENT from above) // Also first test with this pattern - will fail await page.goto('/users/create') await page.getByRole('button', { name: 'Submit' }).click() // POST 500 /api/users/create (server error) expect(true).toBe(true) }) testWithLimit('GET 404 on same endpoint again', async ({ page }) => { // Pattern: GET:404:/api/users (same as first test) // Second test with this pattern - will PASS (limit reached) await page.goto('/users/search') await page.getByRole('button', { name: 'Search' }).click() // This test passes because GET:404:/api/users already failed once expect(true).toBe(true) }) }) ``` -------------------------------- ### Install Dependencies for Schema Validation (Bash) Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/api-request.md Provides the npm commands to install peer dependencies required for different schema validation types. It includes installing AJV for JSON Schema, Zod for Zod schema validation, and js-yaml for OpenAPI YAML files. ```bash # For JSON Schema validation (using AJV) npm install ajv # For Zod schema validation npm install zod # For YAML OpenAPI schema files (required for .yaml/.yml files) npm install js-yaml @types/js-yaml # Install all dependencies for complete schema support npm install ajv zod js-yaml @types/js-yaml ``` -------------------------------- ### Use Environment Variables for Network Recording Modes Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/features/network-traffic-record-playback/examples.md This bash snippet illustrates how to control the network recording mode using environment variables. It shows setting the `PW_NET_MODE` to 'record' for development and 'playback' for CI/CD environments to ensure consistent and fast test execution. ```bash # Development - record new tests PW_NET_MODE=record npm run test:pw # CI/CD - use playback mode for consistent, fast tests PW_NET_MODE=playback npm run test:pw ``` -------------------------------- ### POST /movies Source: https://github.com/seontechnologies/playwright-utils/blob/main/sample-app/backend/docs/api-docs.html Create a new movie in the system. ```APIDOC ## POST /movies ### Description Create a new movie in the system. ### Method POST ### Endpoint /movies ### Parameters #### Request Body - **name** (string) - Required - Movie name. - **year** (number) - Required - Release year. - **rating** (number) - Required - Rating. - **director** (string) - Required - Director. ### Request Example ```json { "name": "The Matrix", "year": 1999, "rating": 8.7, "director": "Lana Wachowski, Lilly Wachowski" } ``` ### Response #### Success Response (200) - **status** (integer) - Response status code (e.g., 200). - **data** (object) - Contains the details of the created movie. - **id** (number) - Movie ID. - **name** (string) - Movie name. - **year** (number) - Release year. - **rating** (number) - Rating. - **director** (string) - Director. - **error** (string) - Error message, if any. #### Response Example (Success) ```json { "status": 200, "data": { "id": 2, "name": "The Matrix", "year": 1999, "rating": 8.7, "director": "Lana Wachowski, Lilly Wachowski" }, "error": null } ``` #### Error Response (400) Invalid request body or validation error. #### Error Response (409) - **status** (integer) - Conflict status code (e.g., 409). - **error** (string) - Error message (e.g., "Movie already exists"). #### Response Example (409) ```json { "status": 409, "error": "Movie already exists" } ``` ``` -------------------------------- ### Install Playwright Utils Package Source: https://github.com/seontechnologies/playwright-utils/blob/main/README.md Installs the Playwright Utils package as a development dependency using npm or pnpm. Requires `@playwright/test` as a peer dependency. ```bash npm i -D @seontechnologies/playwright-utils pnpm i -D @seontechnologies/playwright-utils ``` -------------------------------- ### Get Movie by ID (GET /movies/{id}) Source: https://github.com/seontechnologies/playwright-utils/blob/main/sample-app/backend/docs/api-docs.html Retrieves a single movie by its ID. Returns a 200 if the movie is found, and 404 if the movie is not found. This endpoint is available on local development and production servers. ```HTTP GET /movies/{id} ``` -------------------------------- ### Building and Packaging Playwright Utils Locally Source: https://github.com/seontechnologies/playwright-utils/blob/main/README.md Instructions for building the Playwright Utils package and creating a tarball for local installation. This is useful for testing changes or integrating the package into a project without publishing it. ```bash # Build the package npm run build # Create a tarball package npm pack # Install in a target repository (change the version according to the file name) # For npm projects: npm install ../playwright-utils/seontechnologies-playwright-utils-1.0.1.tgz # For pnpm projects: pnpm add file:/path/to/playwright-utils-1.0.1.tgz ``` -------------------------------- ### Organize HAR Files by Test File Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/bmad-method/features/network-traffic-record-playback/examples.md This TypeScript configuration example shows how to organize HAR files for better maintainability. By setting `organizeByTestFile` to true within the `harFile` configuration, subdirectories are automatically created for each test file, grouping related HAR files. ```typescript // Group by feature/test file for maintainability { harFile: { harDir: 'har-files', organizeByTestFile: true // Creates subdirectories per test file } } ``` -------------------------------- ### GitHub Actions Workflow for Smart Burn-in Tests Source: https://github.com/seontechnologies/playwright-utils/blob/main/docs/burn-in.md A GitHub Actions workflow file (`.github/workflows/burn-in.yml`) demonstrating how to set up and run Playwright's smart burn-in tests. It includes steps for checking out code, setting up Node.js, installing dependencies, and running the burn-in script with sharding. ```yaml name: Smart Burn-in Tests on: pull_request: types: [opened, synchronize, reopened] jobs: burn-in: runs-on: ubuntu-latest # Key: Use matrix for parallel sharding strategy: fail-fast: false matrix: shardIndex: [1, 2] shardTotal: [2] permissions: contents: read packages: read # Add if you need private packages outputs: runE2E: ${{ steps.burn-in-result.outputs.runE2E }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # Important: Need full history for git diff - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' - name: Install dependencies run: npm ci # or yarn/pnpm install - name: Run Smart Burn-in id: burn-in-step working-directory: playwright/ # Adjust to your test directory env: CI: 'true' PW_BURN_IN: true # Add any other environment variables your tests need run: | # Key: Ensure base branch is available for git diff git branch -f main origin/main # Key: Use your burn-in script with sharding npm run test:pw:burn-in-changed -- --base-branch=main --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - name: Set burn-in result id: burn-in-result run: | # Set output based on your needs - this determines if E2E tests run echo "runE2E=true" >> $GITHUB_OUTPUT ```