### Quick Start Example Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/README.md Demonstrates a basic setup using @playwright-labs/decorators for a class-based test suite with lifecycle hooks. ```APIDOC ## Quick Start Example ### Description This example shows how to use the `@describe`, `@beforeEach`, `@test`, and `@afterEach` decorators to create a class-based test suite with Playwright. ### Method N/A (Decorator Usage) ### Endpoint N/A (Decorator Usage) ### Request Body N/A ### Response N/A ### Code Example ```typescript import { describe, test, beforeEach, afterEach } from '@playwright-labs/decorators'; @describe('Login Tests') class LoginTests { @beforeEach() async setup() { await this.page.goto('https://example.com/login'); } @test('should login successfully') async testLogin() { await this.page.fill('#username', 'user@example.com'); await this.page.fill('#password', 'password123'); await this.page.click('#login-button'); await expect(this.page).toHaveURL('/dashboard'); } @afterEach() async cleanup() { await this.page.context().clearCookies(); } } ``` ``` -------------------------------- ### Start Docker Compose Stack Source: https://github.com/vitalics/playwright-labs/blob/main/packages/reporter-otel/README.md Navigate to the example directory and start the Docker Compose stack for the E2E example. The `--wait` flag ensures services are ready before proceeding. ```bash cd packages/reporter-otel/example docker compose up -d --wait ``` -------------------------------- ### E2E Example Setup Source: https://github.com/vitalics/playwright-labs/blob/main/packages/reporter-otel/README.md Instructions and commands to set up and run the end-to-end example for the Playwright OTel reporter, including Docker Compose. ```APIDOC ## E2E Example (`example/`) The package includes a fully wired example under `packages/reporter-otel/example/` with a Docker Compose stack. ### Start the stack ```bash cd packages/reporter-otel/example docker compose up -d --wait ``` ### Run the example ```bash pnpm test:e2e ``` ### Tear down ```bash docker compose down --remove-orphans ``` ``` -------------------------------- ### Quick start commands Source: https://github.com/vitalics/playwright-labs/blob/main/examples/otel-stack/README.md Install dependencies and execute the end-to-end test suite. ```sh # From this directory: pnpm install pnpm test:e2e ``` -------------------------------- ### Quick Start: MySQL Example Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-sql/README.md Example demonstrating how to configure and use the MySQL adapter in Playwright tests. ```APIDOC ### 3. MySQL ```ts import { test, expect } from '@playwright-labs/fixture-sql'; import { mysqlAdapter } from '@playwright-labs/fixture-sql/mysql'; test.use({ sqlAdapter: mysqlAdapter('mysql://user:pass@localhost:3306/testdb'), }); test('products exist', async ({ sql: db }) => { const { rows } = await db.query('SELECT id FROM products LIMIT 1'); expect(rows.length).toBeGreaterThan(0); }); ``` ``` -------------------------------- ### Quick Start: PostgreSQL Example Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-sql/README.md Example demonstrating how to configure and use the PostgreSQL adapter in Playwright tests. ```APIDOC ### 2. PostgreSQL ```ts import { test, expect } from '@playwright-labs/fixture-sql'; import { pgAdapter } from '@playwright-labs/fixture-sql/pg'; test.use({ sqlAdapter: pgAdapter('postgresql://user:pass@localhost:5432/testdb'), }); test('users table exists', async ({ sql: db }) => { const { rows } = await db.query<{ count: string }>( 'SELECT COUNT(*) AS count FROM users', ); expect(Number(rows[0]!.count)).toBeGreaterThanOrEqual(0); }); ``` ``` -------------------------------- ### Implement Complete Test Class Example Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/getting-started.md A comprehensive example demonstrating suite-level setup, test-level setup, specific timeouts, and cleanup hooks. ```typescript import { describe, test, beforeAll, beforeEach, afterEach, afterAll, timeout } from '@playwright-labs/decorators'; import { expect } from '@playwright/test'; @describe('Complete Example') @timeout(30000) // 30 seconds for all tests class CompleteExample { static testData: any; @beforeAll() static async setupSuite() { // Runs once before all tests this.testData = await loadTestData(); } @beforeEach() async setupTest() { // Runs before each test await this.page.goto('https://example.com'); } @test('basic test') async testBasic() { await expect(this.page).toHaveTitle(/Example/); } @test('with specific timeout') @timeout(5000) // Override class timeout async testFast() { const heading = this.page.locator('h1'); await expect(heading).toBeVisible(); } @afterEach() async cleanupTest() { // Runs after each test await this.page.context().clearCookies(); } @afterAll() static async cleanupSuite() { // Runs once after all tests await cleanup(this.testData); } } ``` -------------------------------- ### Start Email Preview Server Source: https://github.com/vitalics/playwright-labs/blob/main/examples/reporter-email/README.md Start the preview server from the examples directory or the monorepo root. The server will open at http://localhost:3000 and hot-reloads on file changes. ```bash cd packages/reporter-email/examples pnpm email:preview ``` ```bash pnpm --filter reporter-email-example email:preview ``` -------------------------------- ### Quick Start: SQLite Example Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-sql/README.md A basic example demonstrating how to set up the SQLite adapter and perform basic SQL operations (CREATE, INSERT, SELECT) within a Playwright test. ```APIDOC ## Quick start ### 1. Replace the base `test` import ```ts // tests/my.spec.ts import { test, expect } from '@playwright-labs/fixture-sql'; import { sqliteAdapter } from '@playwright-labs/fixture-sql/sqlite'; import { sql } from '@playwright-labs/fixture-sql'; // re-exported from sql-core test.use({ sqlAdapter: sqliteAdapter(':memory:') }); test('inserts and reads a row', async ({ sql: db }) => { await db.execute(sql`CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)`); await db.execute(sql`INSERT INTO users VALUES (1, 'Alice')`); const { rows } = await db.query<{ name: string }>( sql("SELECT name FROM users WHERE id = ?"), [1], ); expect(rows[0]!.name).toBe('Alice'); }); ``` ``` -------------------------------- ### Install @playwright-labs/sql-core and Database Drivers Source: https://github.com/vitalics/playwright-labs/blob/main/packages/sql-core/README.md Install the core package and the specific database driver you intend to use. For example, install `better-sqlite3` for SQLite, `pg` for PostgreSQL, or `mysql2` for MySQL/MariaDB. ```bash pnpm add @playwright-labs/sql-core # install the driver you actually use pnpm add -D better-sqlite3 # SQLite pnpm add -D pg # PostgreSQL pnpm add -D mysql2 # MySQL / MariaDB ``` -------------------------------- ### Basic Test Setup with Allure Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-allure/README.md Example of using the useAllure fixture to add metadata, steps, and attachments to a test. ```typescript import { test, expect } from "@playwright-labs/fixture-allure"; test("my test", async ({ page, useAllure }) => { const allure = useAllure({ id: 123456, description: "This is a test description", layer: "API", severity: "critical", owner: "John Doe", epic: "User Management", feature: "Login", story: "User can log in", suite: "Authentication", labels: { custom_label: "my_value", }, tags: ["ui", "regression"], issues: [{ url: "https://example.com/issue1", name: "Issue 1" }], links: [{ url: "https://example.com/doc1", name: "documentation 1" }], }); await page.goto("https://example.com"); await allure.step("Login step", async () => { await page.fill("#username", "user"); await page.fill("#password", "pass"); await page.click("#submit"); }); await allure.attachment("screenshot", await page.screenshot(), "image/png"); }); ``` -------------------------------- ### Install @playwright-labs/slack-buildkit Source: https://github.com/vitalics/playwright-labs/blob/main/packages/slack-buildkit/README.md Install the core package and optionally React support. ```bash pnpm add @playwright-labs/slack-buildkit # React support (optional) pnpm add react ``` -------------------------------- ### Install fixture-otel and reporter-otel Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-otel/README.md Install the necessary packages for OTel fixtures and reporting. ```bash npm install @playwright-labs/fixture-otel # also install the reporter if you haven't already npm install @playwright-labs/reporter-otel ``` -------------------------------- ### Install reporter-slack and slack-buildkit Source: https://github.com/vitalics/playwright-labs/blob/main/packages/reporter-slack/README.md Install the Slack reporter and the Slack Block Kit builder. React templates are optional. ```bash pnpm add @playwright-labs/reporter-slack @playwright-labs/slack-buildkit # React templates (optional) pnpm add react ``` -------------------------------- ### Install Reporter Package Source: https://github.com/vitalics/playwright-labs/blob/main/packages/reporter-otel/README.md Install the reporter package for traces and built-in metrics. For custom fixture support, also install `@playwright-labs/fixture-otel`. ```bash # Reporter only (traces + built-in metrics) npm install @playwright-labs/reporter-otel # Reporter + custom fixture support npm install @playwright-labs/reporter-otel @playwright-labs/fixture-otel ``` -------------------------------- ### Install @playwright-labs/fixture-allure Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-allure/README.md Install the Playwright Allure fixture package. ```sh npm i @playwright-labs/fixture-allure pnpm add @playwright-labs/fixture-allure yarn add @playwright-labs/fixture-allure ``` -------------------------------- ### Install and Import Decorators Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/troubleshooting.md Install the required packages and verify the import path. ```bash npm install @playwright-labs/decorators @playwright/test ``` ```typescript import { describe, test } from '@playwright-labs/decorators'; ``` -------------------------------- ### Install package Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-abort/README.md Commands to install the library using various package managers. ```sh npm install @playwright/test @playwright-labs/fixture-abort # npm pnpm add @playwright/test @playwright-labs/fixture-abort # pnpm yarn add @playwright/test @playwright-labs/fixture-abort # yarn ``` -------------------------------- ### Install fixture-ghost-cursor Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-ghost-cursor/README.md Install the necessary packages for fixture-ghost-cursor and ghost-cursor. Ensure @playwright/test is installed as a peer dependency. ```bash npm install @playwright-labs/fixture-ghost-cursor @playwright-labs/ghost-cursor # or pnpm add @playwright-labs/fixture-ghost-cursor @playplaywright-labs/ghost-cursor ``` -------------------------------- ### Installation Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-sql/README.md Instructions for installing the Playwright SQL fixture and the necessary database drivers. ```APIDOC ## Installation ```bash pnpm add -D @playwright-labs/fixture-sql # install the driver you actually use pnpm add -D pg # PostgreSQL pnpm add -D mysql2 # MySQL / MariaDB pnpm add -D better-sqlite3 # SQLite ``` ``` -------------------------------- ### GitHub Actions Basic CI Setup Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/cicd-integration.md This YAML configuration sets up a basic GitHub Actions workflow to run Playwright tests. It checks out code, sets up Node.js, installs dependencies, installs Playwright browsers, runs tests, and uploads test reports as artifacts. ```yaml # .github/workflows/playwright.yml name: Playwright Tests on: push: branches: [main] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - name: Install dependencies run: npm ci - name: Install Playwright browsers run: npx playwright install --with-deps - name: Run tests run: npx playwright test - uses: actions/upload-artifact@v4 if: ${{ !cancelled() }} with: name: playwright-report path: playwright-report/ retention-days: 30 ``` -------------------------------- ### Install dependencies Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-sql/README.md Install the core fixture package and the specific database driver required for your project. ```bash pnpm add -D @playwright-labs/fixture-sql # install the driver you actually use pnpm add -D pg # PostgreSQL pnpm add -D mysql2 # MySQL / MariaDB pnpm add -D better-sqlite3 # SQLite ``` -------------------------------- ### Use API for Setup When Possible Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/best-practices.md Perform setup tasks via API requests to speed up test execution compared to UI-based interactions. ```typescript // ✅ Good: API setup is faster than UI @beforeEach() async setup() { // Create test data via API (fast) const response = await this.request.post('/api/users', { data: { name: 'Test User', email: 'test@test.com' }, }); this.userId = (await response.json()).id; // Only navigate for the actual test await this.page.goto(`/users/${this.userId}`); } // ❌ Slower: Create data through UI @beforeEach() async setup() { await this.page.goto('/admin/users/new'); await this.page.fill('#name', 'Test User'); await this.page.fill('#email', 'test@test.com'); await this.page.click('#save'); // ... wait for navigation, read ID from URL... } ``` -------------------------------- ### Install @playwright-labs/selectors-core Source: https://github.com/vitalics/playwright-labs/blob/main/packages/selectors-core/README.md Commands to install the package using npm or pnpm. ```bash npm install -D @playwright-labs/selectors-core # or pnpm add -D @playwright-labs/selectors-core ``` -------------------------------- ### Quick Start: Class-Based Playwright Tests Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/README.md Demonstrates a basic setup for Playwright tests using TypeScript decorators for describe, test, beforeEach, and afterEach. ```typescript import { describe, test, beforeEach, afterEach } from '@playwright-labs/decorators'; @describe('Login Tests') class LoginTests { @beforeEach() async setup() { await this.page.goto('https://example.com/login'); } @test('should login successfully') async testLogin() { await this.page.fill('#username', 'user@example.com'); await this.page.fill('#password', 'password123'); await this.page.click('#login-button'); await expect(this.page).toHaveURL('/dashboard'); } @afterEach() async cleanup() { await this.page.context().clearCookies(); } } ``` -------------------------------- ### Manage Shared Setup Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/migration-guide.md Use static methods and decorators to handle setup and teardown logic across tests. ```typescript test.describe('API Tests', () => { let apiClient: ApiClient; test.beforeAll(async () => { apiClient = new ApiClient(); await apiClient.authenticate(); }); test('get users', async () => { const users = await apiClient.getUsers(); expect(users.length).toBeGreaterThan(0); }); test.afterAll(async () => { await apiClient.cleanup(); }); }); ``` ```typescript @describe('API Tests') class ApiTests { static apiClient: ApiClient; @beforeAll() static async setup() { this.apiClient = new ApiClient(); await this.apiClient.authenticate(); } @test('get users') async testGetUsers() { const users = ApiTests.apiClient.getUsers(); expect(users.length).toBeGreaterThan(0); } @afterAll() static async cleanup() { await this.apiClient.cleanup(); } } ``` -------------------------------- ### Install allure-js-commons Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-allure/README.md Install the core Allure JS commons package. ```sh npm i allure-js-commons pnpm add allure-js-commons yarn add allure-js-commons ``` -------------------------------- ### Install Ghost Cursor Source: https://github.com/vitalics/playwright-labs/blob/main/packages/ghost-cursor/README.md Install the ghost-cursor package using npm or pnpm. Ensure @playwright/test is installed separately as it is a peer dependency. ```bash npm install @playwright-labs/ghost-cursor # or pnpm add @playwright-labs/ghost-cursor ``` -------------------------------- ### Install Dependencies for Contributing Source: https://github.com/vitalics/playwright-labs/blob/main/packages/playwright-best-practices-build/README.md Run this command to install all necessary dependencies when contributing to the Playwright Best Practices project. ```bash pnpm install ``` -------------------------------- ### Install Playwright Fixture Timers Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-timers/README.md Install the package using npm, pnpm, or yarn. ```sh npm install @playwright/test @playwright-labs/fixture-timers # npm pnpm add @playwright/test @playwright-labs/fixture-timers # pnpm yarn add @playwright/test @playwright-labs/fixture-timers # yarn ``` -------------------------------- ### Project structure overview Source: https://github.com/vitalics/playwright-labs/blob/main/examples/otel-stack/README.md The directory layout for the example project. ```text example/ ├── tests/ │ ├── sample.spec.ts # generates OTel data (counters, histograms, spans) │ └── verify.spec.ts # asserts data arrived in Jaeger + Prometheus ├── playwright.config.ts # two-project setup: generate → verify ├── global-setup.ts # starts the Docker Compose stack ├── global-teardown.ts # stops the Docker Compose stack ├── docker-compose.yml # OTel Collector + Jaeger + Prometheus + Grafana ├── otel-collector-config.yaml ├── prometheus.yml └── grafana/ └── provisioning/ └── datasources/ └── datasources.yaml # Prometheus + Jaeger datasources ``` -------------------------------- ### Install @playwright-labs/fixture-env Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-env/README.md Install the package using npm, pnpm, or yarn. ```sh npm install @playwright/test @playwright-labs/fixture-env # npm pnpm add @playwright/test @playwright-labs/fixture-env # pnpm yarn add @playwright/test @playwright-labs/fixture-env # yarn ``` -------------------------------- ### Installing Angular Selectors Source: https://github.com/vitalics/playwright-labs/blob/main/packages/selectors-angular/README.md Install the package using your preferred package manager. ```bash npm install -D @playwright-labs/selectors-angular # or yarn add -D @playwright-labs/selectors-angular # or pnpm add -D @playwright-labs/selectors-angular ``` -------------------------------- ### Implement Suite-Level Setup with @beforeAll Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/lifecycle-hooks.md Use static methods for shared setup tasks like database connections. Playwright fixtures are not available in these hooks. ```typescript @describe('Database Tests') class DatabaseTests { static connection: DBConnection; static testData: any[]; @beforeAll() static async setupDatabase() { DatabaseTests.connection = await Database.connect(); DatabaseTests.testData = await DatabaseTests.connection.seed(); } @test('query users') async testQuery() { const users = await DatabaseTests.connection.query('SELECT * FROM users'); expect(users.length).toBeGreaterThan(0); } @test('insert record') async testInsert() { await DatabaseTests.connection.insert('users', { name: 'Test' }); } } ``` -------------------------------- ### Implement Test-Level Setup with @beforeEach Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/lifecycle-hooks.md Use instance methods to perform setup before every test. Playwright fixtures like this.page are fully accessible here. ```typescript @describe('Login Tests') class LoginTests { private loginPage: LoginPage; @beforeEach() async navigateToLogin() { await this.page.goto('/login'); this.loginPage = new LoginPage(this.page); } @test('valid login') async testValidLogin() { await this.loginPage.login('user@test.com', 'password'); await expect(this.page).toHaveURL('/dashboard'); } @test('invalid login') async testInvalidLogin() { await this.loginPage.login('bad@test.com', 'wrong'); await expect(this.page.locator('.error')).toBeVisible(); } } ``` -------------------------------- ### Share Setup Logic via Inheritance Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/best-practices.md Use base classes to encapsulate common setup logic like authentication, promoting reusability across multiple test suites. ```typescript // ✅ Good: Shared setup in base class class AuthenticatedTests extends BaseTest { @beforeEach() async authenticate() { await this.page.goto('/login'); await this.page.fill('#email', 'admin@test.com'); await this.page.fill('#password', 'password'); await this.page.click('#submit'); } } @describe('Dashboard') class DashboardTests extends AuthenticatedTests {} @describe('Settings') class SettingsTests extends AuthenticatedTests {} @describe('Profile') class ProfileTests extends AuthenticatedTests {} ``` -------------------------------- ### Installation: Playwright Decorators Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/README.md Install the @playwright-labs/decorators package along with @playwright/test using npm. ```bash npm install @playwright-labs/decorators @playwright/test ``` -------------------------------- ### Install `@playwright-labs/fixture-otel` Source: https://github.com/vitalics/playwright-labs/blob/main/packages/reporter-otel/README.md Install the necessary package for OpenTelemetry fixtures in your Playwright project using npm or yarn. ```bash npm install @playwright-labs/fixture-otel ``` -------------------------------- ### Setup with Selector Engine Only Source: https://github.com/vitalics/playwright-labs/blob/main/packages/selectors-react/README.md Manually register the 'react' selector engine using `selectors.register` in a setup file, typically imported in `playwright.config.ts`. ```typescript // tests/setup.ts import { selectors } from '@playwright/test'; import { ReactEngine } from '@playwright-labs/selectors-react'; selectors.register('react', ReactEngine); ``` ```typescript // playwright.config.ts import './tests/setup'; // executed once per worker ``` -------------------------------- ### Rule Example Placeholder Source: https://github.com/vitalics/playwright-labs/blob/main/packages/playwright-best-practices/README.md Placeholder for providing correct implementation examples in rule documentation. ```typescript // Good code example ``` -------------------------------- ### Install zod for schema definition Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-env/README.md Install zod if you plan to define your environment schema using it. ```sh npm install zod # npm pnpm add zod # pnpm yarn add zod # yarn ``` -------------------------------- ### Install @playwright-labs/decorators Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/getting-started.md Commands to install the package and Playwright test dependencies using various package managers. ```bash npm install @playwright-labs/decorators @playwright/test ``` ```bash yarn add @playwright-labs/decorators @playwright/test ``` ```bash pnpm add @playwright-labs/decorators @playwright/test ``` -------------------------------- ### useContainerFromDockerFile Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-testcontainers/README.md Builds a Docker image from a local Dockerfile and starts a container from it. ```APIDOC ## useContainerFromDockerFile(context, dockerfilePath?, opts?) ### Description Builds a Docker image from a local Dockerfile, then starts a container from it. Accepts the same ContainerOpts as useContainer. ### Parameters #### Path Parameters - **context** (string) - Required - Path to the Docker build context directory - **dockerfilePath** (string) - Optional - Path to the Dockerfile within the context (default: "Dockerfile") - **opts** (ContainerOpts) - Optional - Container configuration ### Returns - **Promise** - A promise that resolves to the started container instance. ### Request Example ```typescript test("custom image", async ({ useContainerFromDockerFile }) => { const container = await useContainerFromDockerFile( "./docker", "Dockerfile.test", { ports: 8080, waitStrategy: Wait.forHttp("/health", 8080), }, ); }); ``` ``` -------------------------------- ### E-Commerce Price Testing Example Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/data-driven-tests.md A real-world example demonstrating price calculation testing with multiple data scenarios. ```typescript @describe('Product Pricing') class ProductPricingTests { @test.each([ [100, 0, 100], // No discount [100, 10, 90], // 10% off [100, 50, 50], // 50% off [99.99, 20, 79.99], // Decimal price ], 'price $1 with $2% discount = $3') @param('originalPrice', 'Product original price') @param('discountPercent', 'Discount percentage to apply') @param('expectedPrice', 'Final price after discount') @timeout(5000) async testPriceCalculation( originalPrice: number, discountPercent: number, expectedPrice: number ) { await this.page.goto('/product/123'); await this.page.fill('#original-price', originalPrice.toString()); await this.page.fill('#discount', discountPercent.toString()); await this.page.click('#calculate'); const finalPrice = await this.page.textContent('.final-price'); expect(parseFloat(finalPrice)).toBe(expectedPrice); } } ``` -------------------------------- ### Assert Vue setup state equality Source: https://github.com/vitalics/playwright-labs/blob/main/packages/selectors-vue/README.md Use toBeVueSetup to verify that the Composition API setup state matches an expected value. ```ts await counter.locator('button').last().click(); await expect(page.locator('vue=Counter').first()).toBeVueSetup('count', 1); ``` -------------------------------- ### React Selector Source Examples Source: https://github.com/vitalics/playwright-labs/blob/main/packages/selectors-react/README.md Examples of specifying data sources for React selectors, including props, state, and context. ```plaintext [props.disabled=false] [state.0=5], [state.count=0] [context.theme="dark"] ``` -------------------------------- ### Install ajv-ts and Playwright Dependencies Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-ajv-ts/README.md Install the necessary packages using pnpm. Ensure Playwright, ajv-ts, and the ajv-ts fixture are all included. ```sh pnpm i @playwright/test pnpm i ajv-ts pnpm i @playwright-labs/fixture-ajv-ts ``` -------------------------------- ### Basic Test Setup Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-faker/README.md Example of using the faker fixture directly within a Playwright test. ```typescript import { test, expect } from "@playwright-labs/fixture-faker"; test("my test", async ({ page, faker }) => { await page.goto("https://example.com"); await page.fill("#username", faker.internet.email()); await page.fill("#password", faker.internet.password()); await page.click("#submit"); }); ``` -------------------------------- ### Full integration example Source: https://github.com/vitalics/playwright-labs/blob/main/packages/ts-plugin-sql/README.md Demonstrates using the fixture-sql adapter with the plugin for typed queries in tests. ```ts import { test, expect } from '@playwright-labs/fixture-sql'; import { pgAdapter } from '@playwright-labs/fixture-sql/pg'; import { sql } from '@playwright-labs/ts-plugin-sql'; import type { UsersRow } from './db-types.js'; test.use({ sqlAdapter: pgAdapter(process.env.DATABASE_URL!) }); test('typed query with IDE support', async ({ sql: client }) => { // Plugin provides completions and diagnostics here: const { rows } = await client.query( sql("SELECT id, name FROM users WHERE id = $1"), [1], ); expect(rows[0]!.name).toBe('Alice'); }); ``` -------------------------------- ### Quick Start with SQLite Source: https://github.com/vitalics/playwright-labs/blob/main/packages/sql-core/README.md Demonstrates creating an in-memory SQLite database, executing DDL and DML statements, querying data, and closing the client connection. ```typescript import { sql } from '@playwright-labs/sql-core'; import { sqliteAdapter } from '@playwright-labs/sql-core/sqlite'; const client = await sqliteAdapter(':memory:').create(); await client.execute(sql`CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)`); await client.execute(sql`INSERT INTO users VALUES (?, ?)`, [1, 'Alice']); const { rows } = await client.query<{ name: string }> ( sql`SELECT name FROM users WHERE id = ?`, [1], ); console.log(rows[0]!.name); // 'Alice' await client.close(); ``` -------------------------------- ### Find Buttons by Label Regex Source: https://github.com/vitalics/playwright-labs/blob/main/packages/selectors-angular/README.md Finds Angular buttons whose 'label' attribute matches a regular expression. This example specifically targets labels starting with 'S'. ```typescript test('finds buttons whose label starts with S', async ({ page }) => { await expect(page.locator('angular=app-button[label=/^S/]')).toHaveCount(1); }); ``` -------------------------------- ### Grouped Tests with test.describe Source: https://github.com/vitalics/playwright-labs/blob/main/packages/playwright-best-practices/rules/fixture-describe-blocks.md This example demonstrates using `test.describe` to group related tests, such as authentication and user profile management. It utilizes `test.beforeEach` for shared setup within groups. ```typescript import { test, expect } from '@playwright/test'; test.describe('Authentication', () => { test.describe('Login', () => { test.beforeEach(async ({ page }) => { // Shared setup for all login tests await page.goto('/login'); }); test('succeeds with valid credentials', async ({ page }) => { await page.fill('[name="username"]', 'user@example.com'); await page.fill('[name="password"]', 'password123'); await page.click('button[type="submit"]'); await expect(page).toHaveURL('/dashboard'); }); test('fails with invalid password', async ({ page }) => { await page.fill('[name="username"]', 'user@example.com'); await page.fill('[name="password"]', 'wrongpassword'); await page.click('button[type="submit"]'); await expect(page.locator('.error')).toBeVisible(); }); test('shows validation for empty fields', async ({ page }) => { await page.click('button[type="submit"]'); await expect(page.locator('.validation-error')).toHaveCount(2); }); }); test.describe('Logout', () => { test.beforeEach(async ({ page }) => { // Authenticate before each logout test await page.goto('/login'); await page.fill('[name="username"]', 'user@example.com'); await page.fill('[name="password"]', 'password123'); await page.click('button[type="submit"]'); await expect(page).toHaveURL('/dashboard'); }); test('redirects to home page', async ({ page }) => { await page.click('[data-testid="logout"]'); await expect(page).toHaveURL('/'); }); test('clears session data', async ({ page, context }) => { await page.click('[data-testid="logout"]'); const cookies = await context.cookies(); expect(cookies.find(c => c.name === 'sessionId')).toBeUndefined(); }); }); }); test.describe('User Profile', () => { test.beforeEach(async ({ page }) => { // Authenticate and navigate to profile for all profile tests await page.goto('/login'); await page.fill('[name="username"]', 'user@example.com'); await page.fill('[name="password"]', 'password123'); await page.click('button[type="submit"]'); await page.goto('/profile'); }); test('updates name successfully', async ({ page }) => { await page.fill('[name="name"]', 'New Name'); await page.click('button[type="submit"]'); await expect(page.locator('.success')).toBeVisible(); }); test('validates email format', async ({ page }) => { await page.fill('[name="email"]', 'invalid-email'); await page.click('button[type="submit"]'); await expect(page.locator('.error')).toContainText('valid email'); }); }); // You can also configure describe blocks test.describe('Mobile view', () => { test.use({ viewport: { width: 375, height: 667 } }); test('shows mobile navigation', async ({ page }) => { await page.goto('/'); await expect(page.locator('.mobile-menu')).toBeVisible(); }); }); ``` -------------------------------- ### Incorrect Test Setup with Duplicated Login Logic Source: https://github.com/vitalics/playwright-labs/blob/main/packages/playwright-best-practices/rules/fixture-custom-merge-reuse.md This example shows multiple tests that duplicate the same login logic. This leads to code duplication and makes maintenance difficult. Use fixtures to avoid this. ```typescript import { test, expect } from '@playwright/test'; test('user can view profile', async ({ page }) => { // ❌ Duplicated login logic in every test await page.goto('https://example.com/login'); await page.fill('[name="email"]', 'user@example.com'); await page.fill('[name="password"]', 'password123'); await page.click('button[type="submit"]'); await page.waitForURL('**/dashboard'); await page.goto('/profile'); await expect(page.locator('.profile-name')).toBeVisible(); }); test('user can update settings', async ({ page }) => { // ❌ Same login logic duplicated await page.goto('https://example.com/login'); await page.fill('[name="email"]', 'user@example.com'); await page.fill('[name="password"]', 'password123'); await page.click('button[type="submit"]'); await page.waitForURL('**/dashboard'); await page.goto('/settings'); await page.click('[data-testid="edit-profile"]'); }); test('admin can access admin panel', async ({ page }) => { // ❌ Similar but slightly different for admin await page.goto('https://example.com/login'); await page.fill('[name="email"]', 'admin@example.com'); await page.fill('[name="password"]', 'admin123'); await page.click('button[type="submit"]'); await page.waitForURL('**/dashboard'); await page.goto('/admin'); await expect(page.locator('.admin-panel')).toBeVisible(); }); ``` -------------------------------- ### GitLab CI Basic Setup Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/cicd-integration.md This GitLab CI configuration defines a stage for running Playwright tests using a specified Docker image. It installs dependencies, runs tests, and configures artifacts to be saved. ```yaml # .gitlab-ci.yml stages: - test playwright-tests: stage: test image: mcr.microsoft.com/playwright:v1.57.0-jammy script: - npm ci - npx playwright test artifacts: when: always paths: - playwright-report/ expire_in: 7 days ``` -------------------------------- ### User Administration Test Suite Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/page-object-model.md Extend the `AuthenticatedTest` base class to create a user administration test suite. This example demonstrates how to add specific setup for navigating to the users page and testing user listing. ```typescript // tests/admin/users.spec.ts import { describe, test, beforeEach } from '@playwright-labs/decorators'; import { expect } from '@playwright/test'; import { AuthenticatedTest } from '../base/AuthenticatedTest'; import { UsersPage } from '../../pages/UsersPage'; @describe('User Administration') class UserAdminTests extends AuthenticatedTest { private usersPage: UsersPage; @beforeEach() async navigateToUsers() { this.usersPage = new UsersPage(this.page); await this.usersPage.goto(); } @test('should list all users') async testListUsers() { const count = await this.usersPage.table.getRowCount(); expect(count).toBeGreaterThan(0); } } ``` -------------------------------- ### Run SQL tests Source: https://github.com/vitalics/playwright-labs/blob/main/examples/sql/README.md Commands to execute the SQL example tests from the monorepo root or the local directory. ```bash # From the monorepo root: pnpm --filter sql-example test # Or from this directory: pnpm test ``` -------------------------------- ### Start Worker SDK for Automatic Trace Propagation Source: https://github.com/vitalics/playwright-labs/blob/main/packages/reporter-otel/README.md Configure the OpenTelemetry SDK once per worker to enable automatic trace propagation for instrumented libraries. This setup reads the OTLP endpoint from the environment variable set by the reporter. ```typescript import { test as baseTest } from "@playwright-labs/fixture-otel"; import { startWorkerSdk } from "@playwright-labs/fixture-otel"; import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node"; export const test = baseTest.extend<{}, { otelWorker: void }>({ otelWorker: [ async ({}, use) => { startWorkerSdk({ instrumentations: [getNodeAutoInstrumentations()] }); await use(); }, { scope: "worker" }, ], }); ``` -------------------------------- ### Complex Fixture Composition Example Source: https://github.com/vitalics/playwright-labs/blob/main/packages/playwright-best-practices/rules/fixture-custom-merge-reuse.md Demonstrates a multi-level fixture composition where fixtures depend on each other in a chain: 'database' → 'testUser' → 'authToken' → 'apiClient'. This setup allows for complex test environments with shared resources and authentication. ```typescript // fixtures/complete.fixture.ts import { test as base, Page } from '@playwright/test'; import { connectDB, Database } from './db'; import { ApiClient } from './api-client'; // ✅ Define all fixture types type CompleteFixtures = { // Database database: Database; testUser: User; // API apiClient: ApiClient; // Authentication authToken: string; authenticatedPage: Page; // Page Objects loginPage: LoginPage; dashboardPage: DashboardPage; }; export const test = base.extend({ // ✅ Level 1: Database connection database: async ({}, use) => { const db = await connectDB(); await use(db); await db.disconnect(); }, // ✅ Level 2: Test user (depends on database) testUser: async ({ database }, use) => { const user = await database.users.create({ email: `test-${Date.now()}@example.com`, password: 'password123', role: 'user', }); await use(user); await database.users.delete(user.id); }, // ✅ Level 3: Auth token (depends on testUser) authToken: async ({ testUser }, use) => { const response = await fetch('https://api.example.com/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: testUser.email, password: 'password123', }), }); const { token } = await response.json(); await use(token); }, // ✅ Level 4: API client (depends on authToken) ``` -------------------------------- ### Custom Authentication Fixtures for Playwright Source: https://github.com/vitalics/playwright-labs/blob/main/packages/playwright-best-practices/rules/fixture-custom-merge-reuse.md This example defines custom fixtures for authenticated users and admin users, abstracting the login process. This reduces duplication and improves test readability. The fixtures handle setup and rely on Playwright's automatic teardown for cleanup. ```typescript // fixtures/auth.fixture.ts import { test as base, expect, Page } from '@playwright/test'; type AuthFixtures = { authenticatedPage: Page; adminPage: Page; }; // ✅ Extend base test with custom fixtures export const test = base.extend({ // ✅ Regular user authentication fixture authenticatedPage: async ({ page }, use) => { // Setup: Login as regular user await page.goto('https://example.com/login'); await page.fill('[name="email"]', 'user@example.com'); await page.fill('[name="password"]', 'password123'); await page.click('button[type="submit"]'); await page.waitForURL('**/dashboard'); // Provide authenticated page to test await use(page); // Teardown: Logout happens automatically (page context is disposed) }, // ✅ Admin authentication fixture adminPage: async ({ page }, use) => { // Setup: Login as admin await page.goto('https://example.com/login'); await page.fill('[name="email"]', 'admin@example.com'); await page.fill('[name="password"]', 'admin123'); await page.click('button[type="submit"]'); await page.waitForURL('**/dashboard'); // Provide admin page to test await use(page); // Teardown: Automatic cleanup }, }); export { expect }; // tests/profile.spec.ts import { test, expect } from '../fixtures/auth.fixture'; test('user can view profile', async ({ authenticatedPage }) => { // ✅ No login code needed - already authenticated await authenticatedPage.goto('/profile'); await expect(authenticatedPage.locator('.profile-name')).toBeVisible(); }); test('user can update settings', async ({ authenticatedPage }) => { // ✅ Reuse authentication fixture await authenticatedPage.goto('/settings'); await authenticatedPage.click('[data-testid="edit-profile"]'); }); test('admin can access admin panel', async ({ adminPage }) => { // ✅ Use admin-specific fixture await adminPage.goto('/admin'); await expect(adminPage.locator('.admin-panel')).toBeVisible(); }); ``` -------------------------------- ### Install Faker fixture Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-faker/README.md Commands to install the @playwright-labs/fixture-faker package. ```sh npm i @playwright-labs/fixture-faker pnpm add @playwright-labs/fixture-faker yarn add @playwright-labs/fixture-faker ``` -------------------------------- ### Start Container from Image Name with Options Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-testcontainers/README.md Use `useContainer` with an image name and configuration options like ports, environment variables, and wait strategies. ```typescript // from image name with options const container = await useContainer("postgres:16", { ports: 5432, environment: { POSTGRES_PASSWORD: "secret" }, waitStrategy: Wait.forLogMessage("ready to accept connections"), }); ``` -------------------------------- ### Start Multiple Containers with `useContainer` Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-testcontainers/README.md The `useContainer` fixture can start multiple containers within a single test. All containers started this way are automatically stopped in parallel after the test completes. ```typescript test("multiple containers", async ({ useContainer }) => { const redis = await useContainer("redis:8", { ports: 6379 }); const postgres = await useContainer("postgres:16", { ports: 5432, environment: { POSTGRES_PASSWORD: "secret" }, }); }); ``` -------------------------------- ### Install @playwright-labs/selectors-react Source: https://github.com/vitalics/playwright-labs/blob/main/packages/selectors-react/README.md Install the package as a development dependency using npm or pnpm. ```bash npm install -D @playwright-labs/selectors-react # or pnpm add -D @playwright-labs/selectors-react ``` -------------------------------- ### PostgreSQL Adapter Initialization Source: https://github.com/vitalics/playwright-labs/blob/main/packages/sql-core/README.md Shows how to initialize the PostgreSQL adapter using a connection string or an options object. Requires 'pg' peer dependency. ```typescript import { pgAdapter } from '@playwright-labs/sql-core/pg'; const client = await pgAdapter('postgresql://user:pass@localhost:5432/mydb').create(); const client2 = await pgAdapter({ host: 'localhost', database: 'mydb' }).create(); ``` -------------------------------- ### Install @playwright-labs/selectors-vue Source: https://github.com/vitalics/playwright-labs/blob/main/packages/selectors-vue/README.md Install the necessary packages for using Vue selectors in Playwright. ```bash npm install --save-dev @playwright-labs/selectors-vue @playwright/test ``` -------------------------------- ### Install Skill via Package Manager Source: https://github.com/vitalics/playwright-labs/blob/main/packages/playwright-best-practices/README.md Use these commands to add the skill to your project using either pnpm or npm. ```bash pnpx add-skill https://github.com/vitalics/playwright-labs/tree/main/packages/playwright-best-practices # pnpm npx add-skill https://github.com/vitalics/playwright-labs/tree/main/packages/playwright-best-practices # npm ``` -------------------------------- ### Configure @use settings Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/fixtures.md Examples of common @use configurations for geolocation, locale, credentials, storage state, and base URLs. ```typescript // Geolocation @use({ geolocation: { longitude: -122.4194, latitude: 37.7749 }, permissions: ['geolocation'], }) // Custom locale @use({ locale: 'fr-FR', timezoneId: 'Europe/Paris', }) // HTTP credentials @use({ httpCredentials: { username: 'user', password: 'pass', }, }) // Storage state (for auth) @use({ storageState: './auth-state.json', }) // Base URL @use({ baseURL: 'https://staging.example.com', }) ``` -------------------------------- ### Install Testcontainers Fixture Source: https://github.com/vitalics/playwright-labs/blob/main/packages/fixture-testcontainers/README.md Install the necessary packages for Playwright Testcontainers integration. ```bash npm install -D @playwright-labs/fixture-testcontainers testcontainers ``` -------------------------------- ### Preview template in browser Source: https://github.com/vitalics/playwright-labs/blob/main/packages/reporter-email/README.md Commands to start the React Email dev server for visual template inspection. ```bash cd examples pnpm install pnpm email:preview # starts http://localhost:3000 ``` -------------------------------- ### Use @beforeAll and @afterAll for Expensive Setup/Teardown Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/best-practices.md Use `@beforeAll` and `@afterAll` for expensive setup and teardown operations that only need to run once per test suite or worker. This ensures resources like database connections are created and closed efficiently. ```typescript // ✅ Good: Expensive setup once, cheap setup per test @describe('Database Tests') class DatabaseTests { static pool: ConnectionPool; @beforeAll() static async createPool() { // Expensive: create once DatabaseTests.pool = await createPool(); } @beforeEach() async resetData() { // Cheap: reset per test await DatabaseTests.pool.query('DELETE FROM test_data'); } @afterAll() static async closePool() { await DatabaseTests.pool.close(); } } ``` -------------------------------- ### Run suite-level setup with @beforeAll Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/api-reference.md Executes once before all tests in a suite. Must be applied to a static method. ```typescript @beforeAll() static async setupSuite() { this.database = await connectToDatabase(); } ``` -------------------------------- ### Implement Authentication Setup Source: https://github.com/vitalics/playwright-labs/blob/main/packages/decorators/docs/lifecycle-hooks.md Uses a base class with a @beforeEach hook to handle login for all inheriting test classes. ```typescript class AuthenticatedTests extends BaseTest { @beforeEach() async login() { await this.page.goto('/login'); await this.page.fill('#email', 'admin@test.com'); await this.page.fill('#password', 'password'); await this.page.click('#submit'); await this.page.waitForURL('/dashboard'); } } @describe('Admin Panel') class AdminTests extends AuthenticatedTests { @test('should see admin menu') async testAdminMenu() { await expect(this.page.locator('#admin-menu')).toBeVisible(); } } ``` -------------------------------- ### MySQL/MariaDB Adapter Initialization Source: https://github.com/vitalics/playwright-labs/blob/main/packages/sql-core/README.md Illustrates initializing the MySQL/MariaDB adapter with a connection string or configuration object. Requires 'mysql2' peer dependency. ```typescript import { mysqlAdapter } from '@playwright-labs/sql-core/mysql'; const client = await mysqlAdapter('mysql://user:pass@localhost:3306/mydb').create(); const client2 = await mysqlAdapter({ host: 'localhost', database: 'mydb' }).create(); ``` -------------------------------- ### Install TypeScript dependency Source: https://github.com/vitalics/playwright-labs/blob/main/packages/ts-plugin-sql/README.md Ensure TypeScript version 5.0.0 or higher is installed as a peer dependency. ```bash pnpm add -D typescript ``` -------------------------------- ### Setup with $r Fixture Source: https://github.com/vitalics/playwright-labs/blob/main/packages/selectors-react/README.md Import the 'test' export from '@playwright-labs/selectors-react' to automatically register the selector engine and provide the '$r' fixture. ```typescript // my-test.spec.ts import { test } from '@playwright-labs/selectors-react'; import { expect } from '@playwright/test'; test('reads component props', async ({ $r }) => { const btn = $r('react=Button[props.label="Submit"]'); await btn.click(); expect(await btn.prop('label')).toBe('Submit'); }); ```