Works with the AI Agents you already use

    Claude CodeClaude CodeCursorCursorCodex CLICodex CLIMuseMuseDotsDots+22 more

    Playwright E2E Production Pack

    1

    Eight agent skills and two scripts so your AI agent writes Playwright suites that stay green: locators, auth, fixtures, mocking, flakes, CI, visual, a11y.

    $24

    Secure checkout via Stripe

    Money-back guarantee

    Converts to your local currency at checkout

    Security scanned
    Playwright E2E Production Pack

    Playwright E2E Production Pack

    Example session with this skill installed

    Our orders spec fails a couple of times a week in CI and nobody trusts it. Here it is. Fix it.

    import { test, expect } from '@playwright/test';
    
    test.beforeEach(async ({ page }) => {
      await page.goto('/login');
      await page.fill('#email', 'user@example.test');
      await page.fill('#password', 'local-only');
      await page.click('button[type=submit]');
      await page.waitForTimeout(1000);
    });
    
    test('lists three orders', async ({ page }) => {
      expect(await page.locator('tbody tr').count()).toBe(3);
    });
    
    test('cancels the pending order', async ({ page }) => {
      await page.getByRole('button', { name: 'Cancel' }).first().click();
      expect(page.locator('tbody tr:nth-child(1) td:nth-child(2)')).toHaveText('cancelled');
    });
    
    test('saves the dark theme', async ({ page }) => {
      await page.getByRole('button', { name: 'Settings' }).click();
      await page.selectOption('#theme', 'dark');
      await page.getByRole('button', { name: 'Save' }).click();
      await expect(page.getByRole('status')).toHaveText('Settings saved');
    });
    
    • Read your context and instructions
    • Compiled the playwright e2e production

    The agent loads playwright-e2e-production, then playwright-locators, and runs the linter:

    $ node lint-playwright-specs.mjs orders.spec.ts
    WARN  page-selector-action orders.spec.ts:5 Selector-based page method. Playwright marks these discouraged; use a locator: page.getByRole(...).click().
    WARN  page-selector-action orders.spec.ts:6 Selector-based page method. Playwright marks these discouraged; use a locator: page.getByRole(...).click().
    WARN  page-selector-action orders.spec.ts:7 Selector-based page method. Playwright marks these discouraged; use a locator: page.getByRole(...).click().
    ERROR wait-for-timeout orders.spec.ts:8 Fixed sleep. Wait for the condition instead: a web-first assertion, page.waitForResponse() or page.waitForURL().
    ERROR one-shot-assertion orders.spec.ts:12 Value read once, then asserted. Use the retrying matcher (toBeVisible, toHaveText, toHaveCount, toHaveValue, toHaveAttribute) or expect.poll().
    WARN  positional-action orders.spec.ts:16 Acting on first(), last() or nth() usually silences a strict mode violation and clicks whichever match renders first. Filter by text, a child locator or within().
    ERROR unawaited-assertion orders.spec.ts:17 Async assertion without await. It never fails the test. Add await.
    WARN  structural-css orders.spec.ts:17 Structural CSS (nth-child or deep > chains). Breaks on layout changes; filter by content instead.
    WARN  page-selector-action orders.spec.ts:22 Selector-based page method. Playwright marks these discouraged; use a locator: page.getByRole(...).click().
    3 error(s), 6 warning(s), 0 note(s)
    

    Then it loads playwright-flake-triage, reproduces CI conditions (retries: 2, trace: 'on-first-retry', an orders API whose latency varies up to 1.5 s like the shared staging backend) with --repeat-each=10, and triages the JSON report:

    $ node triage-report.mjs results.json
    1 report(s), 3 test(s): 2 passed, 1 flaky, 0 failed, 0 skipped
    
    FLAKY  [chromium] orders.spec.ts:11 lists three orders
           attempts: failed>failed>passed | passed | passed | passed | failed>passed | passed | failed>failed>passed | passed | failed>passed | passed
           cause: value-assertion (Error: expect(received).toBe(expected) // Object.is equality)
           fix: A plain value assertion. If it is flaky, the value was read once while the UI was still changing: use a web-first matcher or expect.poll().
           trace: npx playwright show-trace test-results\orders-lists-three-orders-chromium-retry1\trace.zip
    
    By cause: value-assertion 1
    

    It explains the three problems. The count is read once, one second after login, from a table that renders when the API answers; a slow answer fails the test. The cancel test never asserts anything: the expect is not awaited. Worse, .first() clicks the Cancel button of order A-1001, which is paid, not pending; even with await added the test passes, because it checks the first row too. And the theme test changes a setting on the shared account that other tests read.

    It moves the login into a setup project (from playwright-auth-state) and rewrites the spec:

    import { test, expect } from '@playwright/test';
    
    test.beforeEach(async ({ page }) => {
      await page.goto('/dashboard');
    });
    
    test('lists three orders', async ({ page }) => {
      const orders = page.getByRole('table', { name: 'Orders' });
      await expect(orders.getByRole('row').filter({ has: page.getByRole('cell') })).toHaveCount(3);
    });
    
    test('cancels the pending order', async ({ page }) => {
      const row = page.getByRole('row').filter({ has: page.getByRole('cell', { name: 'A-1002', exact: true }) });
      await expect(row.getByRole('cell').nth(1)).toHaveText('pending');
      await row.getByRole('button', { name: 'Cancel' }).click();
      await expect(row.getByRole('cell').nth(1)).toHaveText('cancelled');
    });
    
    test('saves the dark theme', { lock: 'user-settings' }, async ({ page }) => {
      await page.getByRole('button', { name: 'Settings' }).click();
      const dialog = page.getByRole('dialog', { name: 'Settings' });
      await dialog.getByLabel('Theme').selectOption('dark');
      await dialog.getByRole('button', { name: 'Save' }).click();
      await expect(page.getByRole('status')).toHaveText('Settings saved');
    });
    

    The row is found by its order id, not its status: filtering on 'pending' would stop matching the moment the status changes, and the final assertion would look for a row that no longer exists. The header row has column headers, not cells, so the count filter skips it. The lock (Playwright 1.63+) keeps every test that touches the theme from running at the same time.

    $ node lint-playwright-specs.mjs orders.spec.ts
    0 error(s), 0 warning(s), 0 note(s)
    
    $ npx playwright test --repeat-each=20
      62 passed (16.3s)
    
    $ node triage-report.mjs results.json --fail-on-flaky
    1 report(s), 5 test(s): 5 passed, 0 flaky, 0 failed, 0 skipped
    

    Both specs, the outputs above (trimmed of the echoed source lines and extra trace paths) and the 20x rerun under the same latency are real runs on @playwright/test 1.64.0 with Chromium. Finally it adds the linter and the triage step to the CI workflow from playwright-ci-sharding.

    Connects securely to your tools. The creator never sees your data.

    About this skill

    Agents write Playwright tests that pass once. They get production wrong: waitForTimeout(1000) after a login click, expect(await locator.count()).toBe(3) that reads the table before it renders, an expect(...).toHaveText() without await that can never fail, .first().click() to silence a strict mode violation (and cancel the wrong order), a UI login in every beforeEach, parallel tests fighting over one account, page.route('**/api/orders') that silently misses /api/orders?page=2, HAR files committed with a live session cookie inside, retries that hide the same flaky tests for months, four shards with four separate reports, screenshot baselines from a laptop that fail on every CI run, and axe scans of a page whose dialog was never opened.

    This pack gives the agent current rules, checked against the @playwright/test 1.64 type definitions, CLI help and docs source, and run in a real Playwright 1.64 suite:

    • playwright-e2e-production: routing, pre-flight checklist, current versions, what changed from 1.57 to 1.64.
    • playwright-locators: role, label and test-id locators, filter, within(), visible(), frames, shadow DOM, retrying assertions, expect.poll, toPass, aria snapshots.
    • playwright-auth-state: setup projects, storageState, API login, roles, one account per worker, IndexedDB and sessionStorage tokens, passkeys, test locks.
    • playwright-fixtures: test and worker fixtures, auto fixtures as global hooks, per-project options and the array-option trap, page objects, data fixtures that clean up, custom matchers that handle .not.
    • playwright-network-mocking: fulfill, fetch-and-patch, error states, URL matching rules, handler order, HAR record and replay, WebSocket mocks, service workers, the clock API.
    • playwright-flake-triage: trace modes and the trace CLI, retries, retryStrategy: 'isolated', failOnFlakyTests, --repeat-each, --shuffle, a root-cause catalogue with the real error texts.
    • playwright-ci-sharding: CI config, shard balancing, blob reports merged into HTML, JSON and annotations, GitHub Actions with current action versions, Docker image, GitLab.
    • playwright-visual-a11y: screenshot baselines in the CI image, masks, thresholds, WebP, update modes; axe with WCAG 2.2 tags, fingerprinted known issues, keyboard and aria assertions, forced-colors emulation.

    Two zero-dependency Node scripts: lint-playwright-specs.mjs flags sleeps, one-shot and unawaited assertions, unawaited actions, ElementHandles, selector-based page methods, networkidle, force and positional clicks, XPath and structural CSS; triage-report.mjs reads JSON reports from one or many runs (including merged shards and --repeat-each), groups attempts per test, labels each failure with a likely cause and fix, and lists the traces to open.

    Works with Claude Code (skills folder or plugin), Codex, Gemini CLI and Cursor. Plain Agent Skills format.

    Versions: @playwright/test 1.64 (Node 20+), Docker image v1.64.0-noble, @axe-core/playwright 4.13, GitHub Actions checkout@v7 / setup-node@v7 / upload-artifact@v7 / download-artifact@v8. Reviewed after every Playwright minor release.

    How to use

    Skills on Agensi run inside your AI agent. Copy the prompt, paste it into your agent, and it connects to Agensi and installs this skill for you. If a payment is needed, your agent shows it to you first.

    Reviews

    No reviews yet

    Be one of the first to try it. Every listed skill passes our trust checks below.

    Security scanned

    Passed our 8-point scan before listing

    Fresh listing

    Recently published to Agensi

    Money-back guarantee

    Doesn't do what its page promises? You get your money back.

    Trust & safety

    Security scanned

    Verified clean 6 days ago

    • Passed all security checks, Safe to install

    Requires

    playwright
    Node.js
    tsc

    Listed6 days ago

    What's inside

    Frequently Asked Questions