agentsclimarketplace

Playwright core

Skill hzijad/playwright-agent-skills/skills/playwright-core

Playwright skills for writing, reviewing, and debugging reliable end-to-end tests.

Install
npx -y skills add hzijad/playwright-agent-skills --skill playwright-core

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 21 days oldThe repository was created 21 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

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

10.4 KB, as published. Nobody here has run it

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();

Provable Assertions (Mutation Check)

An assertion that has never been observed to fail provides no evidence. Both LLM- and human-authored tests drift toward assertions that pass regardless of the underlying behavior — sophisticated-looking checks that are, in spirit, no different from expect(true).toBeTruthy().

Before treating a new assertion as finished, prove it can go red:

  • Temporarily invert the expected condition, or break the state the assertion depends on — drop or alter the response with page.route(), remove a required fixture, or comment out the relevant application behavior — run the test once, and confirm it fails for the expected reason.
  • Revert the break and confirm the test passes again.
  • This is a one-time proof done during authoring, not a permanent step. Do not ship a test that deliberately breaks its own app.

This matters most for negative assertions. expect(locator).not.toBeVisible() passes just as happily when the locator itself is wrong — a typo'd role or name — as it does when the element is genuinely absent. A negative assertion is only trustworthy once you've confirmed, at least once, that the same locator resolves correctly when the element is present. Otherwise a broken selector and a correct negative assertion are indistinguishable.

The Anti-Rationalization Table

When tempted to take shortcuts to generate code faster, refer to this table:

RationalizationThe Reality & Required Action
"I'll use page.waitForTimeout(3000) because the transition animation is slow."REJECTED. Sleep timers guarantee flaky CI suites. Action: Assert the expected end-state, for example await expect(modal).toBeVisible().
"Using .submit-btn-active (CSS) is faster than looking up the ARIA role."REJECTED. Implementation details change often. Action: Locate by user intent: await page.getByRole('button', { name: 'Submit' }).
"I'll combine 5 different user flows into one giant test block so it runs faster."REJECTED. Tests must be isolated. If it fails on step 4, steps 1-3 provide no value. Action: Break them into separate test() blocks.
"I'll use page.evaluate() to click the element via JavaScript."REJECTED. Users cannot fire synthetic JS events; they use a mouse. Action: Ensure the element is not obscured and use a standard .click().
"The test passes locally, so I don't need to check the trace."REJECTED. Local execution does not mimic CI resource constraints. Action: Verify with tracing or multiple repeats to ensure determinism.
"The test passes, so the assertion must be correct."REJECTED. A pass alone proves nothing. Action: break the condition once during authoring and confirm the test goes red before trusting it.
"I'll assert the element is not visible to confirm it was removed."RISKY. This passes identically whether the element was removed or the locator is simply wrong. Action: confirm the same locator resolves when the element is present, at least once.

Red Flags in Code Review

If you see any of the following in existing code, flag them as Required Changes:

  • Use of .locator('.class-name') instead of semantic queries.
  • Use of nth() or index-based selection when a semantic locator can disambiguate the target.
  • Tests relying on the execution outcome of the test immediately above them.
  • Any instance of waitForTimeout.
  • Complex if/else logic inside a test file. Tests should be linear paths.
  • Unhandled promises, such as missing await on actions or assertions.
  • Testing external dependencies, for example hitting the real Stripe API instead of mocking it.
  • Negative assertions (.not.toBeVisible(), .not.toContainText(), etc.) with no evidence the same locator resolves correctly when the element is present.
  • Assertions that read as boilerplate and show no sign of ever having been proven capable of failing.

Verification & Handoff Checklist

Before concluding your task, output this checklist and verify each point:

  • All locators are user-facing (getByRole, getByLabel, etc.).
  • No hardcoded sleeps or waitForTimeout calls exist.
  • Assertions use expect().to... for auto-retrying.
  • The test is strictly isolated and can run in any order.
  • External dependencies are mocked or intercepted.
  • The test reads like a human user journey, not an implementation walkthrough.
  • New assertions have been proven to fail under a deliberate break, then confirmed to pass again.
  • Any negative assertion has been checked against a false-locator false positive.

If any box is unchecked, treat the test as incomplete.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.