Skip to content

/playwright-core

Conducts rigorous authoring and review of Playwright E2E tests. Enforces accessibility-first locators, web-first assertions, strict isolation, and DAMP architecture. Use when generating, refactoring, or reviewing any Playwright test code.

shell
$ npx -y skills add hzijad/playwright-agent-skills --skill playwright-core --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/playwright-core
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

Conducts rigorous authoring and review of Playwright E2E tests. Enforces accessibility-first locators, web-first assertions, strict isolation, and DAMP architecture. Use when generating, refactoring, or reviewing any Playwright test code.

SKILL.md

playwright-core.SKILL.md
name: playwright-core
description: Conducts rigorous authoring and review of Playwright E2E tests. Enforces accessibility-first locators, web-first assertions, strict isolation, and DAMP architecture. Use when generating, refactoring, or reviewing any Playwright test code.

Playwright Core: Test Architecture and Quality Gates

Overview

Writing end-to-end tests is easy. Writing end-to-end tests that survive UI refactors and network latency without flaking requires discipline.

Use this skill when you are authoring, reviewing, or refactoring Playwright tests that should behave like a real user journey. It pairs well with `playwright-auth-state` for logged-in flows, `playwright-network-mocking` for external API control, and `playwright-debugging` when a test is already failing.

**The approval standard:** A test is only valid if it tests the application exactly how a human user interacts with it. We do not test implementation details, we do not rely on fixed sleep timers, and we do not share state between tests. If a test fails, it should indicate a true user-facing bug, not a brittle CSS selector or a race condition.

When to Use

  • Before writing new Playwright E2E tests or component tests.
  • When reviewing a PR that adds or modifies test coverage.
  • When fixing a "flaky" test that passes locally but fails in CI.
  • When refactoring existing Page Object Models (POMs) or test fixtures.

When Not to Use

  • When you need authenticated state reuse; use `playwright-auth-state` instead.
  • When you need request interception; use `playwright-network-mocking` instead.
  • When you are diagnosing a specific failure or flake; use `playwright-debugging` instead.
  • When you need CI configuration, fixture scaffolding, or a broader test framework recipe.

The Five-Axis Test Review

Every Playwright test must be evaluated across these five dimensions before execution:

1. Resiliency (Locator Strategy)

Does the test target user intent, or is it coupled to implementation?

  • Are we using `getByRole` as the absolute first choice?
  • Are we avoiding CSS classes, XPaths, and DOM hierarchy dependencies?
  • If the developer changes a `<div>` to a `<span>`, or swaps a CSS framework (e.g., Bootstrap to Tailwind), will the test survive?

2. Determinism (Web-First Assertions)

Are we relying on Playwright's actionability engine, or are we manually guessing execution speed?

  • Are there any `page.waitForTimeout()` calls? These are strictly forbidden.
  • Are we using auto-retrying assertions like `expect(locator).toBeVisible()`?
  • Are we properly awaiting asynchronous UI state changes, such as waiting for a loading spinner to detach, before interacting?

3. Isolation (Clean Slate)

Can this test run in complete isolation, in any order, and in parallel?

  • Does the test rely on data created by a previous test?
  • Is state setup and teardown handled cleanly in `test.beforeEach` and `test.afterEach`?
  • Are we bypassing the UI for data setup, using API calls to focus purely on the target behavior?

4. Readability (DAMP over DRY)

Can another engineer read the test top-to-bottom and understand the business requirement?

  • Do the test names describe the behavior and the outcome?
  • Is the test DAMP, meaning Descriptive And Meaningful Phrases? Slight repetition in setup is vastly preferred over 10 layers of abstracted, unreadable helper functions.
  • Does the test follow the Arrange-Act-Assert (AAA) pattern clearly?

5. Intent (Testing Behavior)

Does the test verify what the user cares about?

  • Are we asserting internal component state variables, or the visible DOM?
  • Are we checking for accessibility text rather than raw HTML nodes?

---

Structural Remedies

When you identify a structural problem in a test, do not just patch it. Reach for a named restructuring:

  • **Replace brittle CSS selectors** with accessible locators (`getByRole`, `getByLabel`).
  • **Replace hardcoded sleeps** with `expect().toBeVisible()` or `page.waitForResponse()`.
  • **Collapse abstracted helper logic** back into the test block if it hides the core user journey.
  • **Extract deeply nested POMs** into flat, feature-specific Page Objects.
  • **Split multi-assertion monolith tests** into separate `test()` blocks with a shared `beforeEach`.

---

Strict Locator Hierarchy

You must follow this exact order of preference when querying the DOM. Fall to the next level only if the previous is impossible.

1. `page.getByRole()` - Always the first choice. Tests accessibility and user intent simultaneously. 2. `page.getByLabel()` - The standard for form inputs. 3. `page.getByPlaceholder()` - Acceptable for inputs without labels. 4. `page.getByText()` - For generic non-interactive text elements. 5. `page.getByTestId()` - The fallback. Use only when semantic querying is impossible, such as dynamic SVG charts. 6. CSS/XPath - Forbidden unless explicitly requested for legacy integration.

When a locator could match more than one element, refine it with semantic filtering instead of switching to position-based selection. Prefer `filter()`, `and()`, or a narrower accessible name over `nth()` or DOM traversal.

---

Code Standards & Anti-Patterns

Web-First Assertions

Always use auto-retrying assertions. Never read a value and assert it synchronously.

// Bad: synchronous evaluation. Causes race conditions if the element is still rendering.
const isVisible = await page.getByRole('button').isVisible();
expect(isVisible).toBeTruthy();

// Good: Playwright handles the polling and timeout automatically.
await expect(page.getByRole('button', { name: 'Submit' })).toBeVisible();

Actionability Before Interaction

Do not force clicks on unready elements. Let Playwright wait for actionability.

// Bad: bypassing actionability checks.
await page.locator('.btn').click({ force: true });

// Good: waiting for the app to be ready.
await page.getByRole('button', { name: 'Submit' }).click();

###

Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withplaywright-agent-skills

Playwright test patterns that avoid the mistakes agents make by default. Playwright Agent Skills is a small, opinionated set of reusable prompts for writing and reviewing Playwright tests.

Get the whole plugin, auto-invoked
Stats
6
Stars
0
Views
0
Forks
Active
Maintenance
MIT
License
18d ago
Last commit
18d ago
Created

Repo: hzijad/playwright-agent-skills