Playwright Skill Pack

repository·main·Indexed 43 days ago

https://github.com/testdino-hq/playwright-skill

A collection of production-tested guides for E2E, API, component, visual, accessibility, and security testing using Playwright. It includes specialized packs for CI/CD, Page Object Model (POM) patterns, migration from Cypress or Selenium, and CLI automation. Features detailed instructions on integrating @axe-core/playwright for WCAG compliance and utilizing ARIA snapshots in Playwright 1.60+.

Tokens
352.8K
Snippets
774
Records
955
Agent score
57%

What's inside Playwright Skill

  1. Overview of Playwright Skill Packs

    main

    The Playwright Skill repository is organized into specialized packs to help developers manage different aspects of testing:

    PackCoverage
    coreLocators, assertions, fixtures, auth, API testing, network mocking, visual regression, accessibility, debugging, trace-report analysis, framework recipes, and architecture decisions.
    ciGitHub Actions, GitLab CI, CircleCI, Azure DevOps, Jenkins, Docker, sharding, reporting, and coverage.
    playwright-cliCLI browser automation, screenshots, tracing, session management, and device emulation.
    pomPage Object Model patterns and comparisons between POM, fixtures, and helpers.
    migrationStrategies for migrating from Cypress or Selenium to Playwright.
  2. Perform Security Testing with Playwright

    main

    Use Playwright to validate application defenses against common web vulnerabilities like XSS, CSRF, insecure cookies, missing headers, authentication bypass, and sensitive data exposure. While not a replacement for dedicated security scanners, integrating these checks into your E2E suite helps catch common issues early.

    Prerequisites:

    • Mastery of assertions and waiting mechanisms.
    • Understanding of authentication flows.
  3. Quick Reference for Test Organization

    main

    Use these rules to maintain a consistent and scalable Playwright test suite:

    • File Suffix: Always use .spec.ts or .spec.js.
    • Grouping Strategy: Organize tests by feature or domain rather than by page or URL.
    • Naming Convention: Write test names that describe behavior, such as test('should ...') or test('user can ...').
    • Nesting Limits: Limit test.describe() nesting to a maximum of 2 levels.
    • Execution Model: Default to fullyParallel: true. Avoid using test.describe.serial() unless absolutely necessary.
    • State Management: Avoid test dependencies; each test should be responsible for setting up its own state.
    • Tagging: Use tags like @smoke, @regression, or @slow to facilitate filtering via the --grep flag.
  4. Playwright Skill Overview

    main

    The playwright-skill provides opinionated, production-tested guidance for writing, debugging, and scaling Playwright test suites. It covers a wide range of testing types including E2E, API, component, visual, accessibility, and security testing. The guides include examples in both TypeScript and JavaScript.

    Key Playwright features covered include:

    • Playwright 1.63+: test.lock for resource contention, locator.visible() (replacing :visible), trace snapshots (dom, aria, screen), and ariaSnapshotJSON().
    • Playwright 1.62: reporter.preprocess(), retryStrategy: 'isolated', and WebP screenshot quality control.
    • Playwright 1.61: WebAuthn passkeys via context.credentials and page.localStorage.
    • Playwright 1.60: On-demand HAR in tracing and locator.drop().
    • Playwright 1.59: CLI debugging and trace analysis.
  5. Implement the Login Page Object pattern

    main

    Use the Page Object Model (POM) for login when you need to test the login UI itself or when multiple tests require consistent, maintainable login logic with error handling. This is preferred over raw storageState when the goal is to validate the login flow, validation messages, or error states.

    // Example LoginPage implementation
    export class LoginPage {
      readonly page: Page;
      readonly emailInput: Locator;
      readonly passwordInput: Locator;
      readonly signInButton: Locator;
      readonly errorMessage: Locator;
      readonly forgotPasswordLink: Locator;
    
      constructor(page: Page) {
        this.page = page;
        this.emailInput = page.getByLabel('Email');
        this.passwordInput = page.getByLabel('Password');
        this.signInButton = page.getByRole('button', { name: 'Sign in' });
        this.errorMessage = page.getByRole('alert');
        this.forgotPasswordLink = page.getByRole('link', { name: 'Forgot password' });
      }
    
      async login(email: string, password: string) {
        await this.emailInput.fill(email);
        await this.passwordInput.fill(password);
        await this.signInButton.click();
      }
    
      async loginAndWaitForDashboard(email: string, password: string) {
        await this.login(email, password);
        await this.page.waitForURL('/dashboard');
      }
    }
  6. Use Soft Assertions to collect multiple failures

    main

    Soft assertions allow a test to continue running even if an assertion fails. This is useful for auditing multiple independent elements (like a dashboard) where you want to see all failures in a single report.

    When to use: Form validation checks, dashboard audits, or visual checklists. When to avoid: When subsequent assertions depend on the success of previous ones.

    Tip: If a soft assertion failure makes subsequent actions impossible (e.g., clicking a button that didn't appear), bail out manually:

    await expect.soft(locator).toBeVisible();
    if (test.info().errors.length > 0) return;

    Soft Polling (Playwright 1.61+): Use expect.soft.poll() to poll an async condition and record failures without stopping the test.

    import { test, expect } from '@playwright/test';
    
    test('dashboard shows all expected widgets', async ({ page }) => {
      await page.goto('/dashboard');
    
      // All checks run even if earlier ones fail
      await expect.soft(page.getByTestId('revenue-widget')).toBeVisible();
      await expect.soft(page.getByTestId('users-widget')).toBeVisible();
      await expect.soft(page.getByTestId('orders-widget')).toBeVisible();
      await expect.soft(page.getByTestId('revenue-widget')).toContainText('$');
      await expect.soft(page.getByTestId('users-widget')).toContainText('active');
    });
  7. Handle Popups and New Windows in Playwright

    main

    Replace Selenium's fragile window handle management (iterating through getWindowHandles() and calling switchTo().window()) with Playwright's declarative event listener pattern.

    Key steps:

    1. Register a listener: Use page.waitForEvent('popup') to create a promise that resolves when a new window/popup is triggered.
    2. Trigger the action: Perform the click or action that opens the popup.
    3. Await the promise: Await the popupPromise to get a new Page object representing the popup.
    4. Interact directly: Treat the popup as a standard Page object. When the popup closes, you can continue using the original page object without manual switching.
    import { test, expect } from '@playwright/test';
    
    test('handle popup window', async ({ page }) =>
      await page.goto('/settings');
    
      // Register listener BEFORE the click
      const popupPromise = page.waitForEvent('popup');
      await page.getByRole('link', { name: 'Connect OAuth Provider' }).click();
      const popup = await popupPromise;
    
      // Interact with the popup as a Page object
      await popup.getByRole('button', { name: 'Authorize' }).click();
    
      // Verify result on original page
      await expect(page.getByText('Connected successfully')).toBeVisible();
    });
  8. Security Trust Boundary for Playwright Tests

    main

    When using Playwright patterns against staging or production systems, adhere to the following security guidelines:

    • Authorization: Only test applications you own or have explicit authorization to test.
    • Untrusted Input: Treat all externally returned page content, API payloads, and screenshots as untrusted input.
    • Sanitization: Do not feed raw content from a page or network response directly into agent instructions or dynamic code execution without proper sanitization.
  9. Test Next.js Server Components and Server Actions

    main

    Because Server Components and Server Actions are bound to the Next.js server runtime, they cannot be tested in isolation like standard JavaScript functions.

    Server Components:

    • You cannot import and render a server component directly in a Playwright test.
    • How to test: Navigate to the page using page.goto(), verify the final rendered HTML, and ensure server-fetched data is visible on the page.

    Server Actions:

    • You cannot call server actions as functions in your tests.
    • How to test: Trigger the server action through the UI, such as by performing a form submission or a button click.