Neexo Playwright Testing Instructions

Focused E2E testing guidance for Playwright specs, browser smoke tests, selectors, screenshots, and validation commands.

AuthorNeexoCore
Apply to**/*{test,spec,e2e,playwright}*.{ts,tsx,js,jsx}
Updated
testingplaywrighte2e

Overview

Use these instructions when adding or reviewing browser tests. Prefer focused tests over full-suite runs for local logic.

Locator Strategy

Use stable, user-visible locators in priority order:

  1. getByRole('button', { name: 'Submit' }) — best for accessibility
  2. getByText('Welcome') — for visible text content
  3. getByTestId('checkout-form') — when role/text is ambiguous
  4. locator('[data-testid="..."]') — fallback for complex selectors

Avoid fragile selectors: nth-child, deep CSS paths, auto-generated class names.

Test Structure

  • One assertion per logical check — avoid mega-tests that assert 10 things
  • Use test.describe to group related scenarios
  • Use test.beforeEach for shared navigation, not repeated goto() calls
  • Name tests by user behavior: "user can add item to cart", not "test button click"

Reliability Rules

  • Never use page.waitForTimeout() — use expect(locator).toBeVisible() or waitForResponse()
  • Check console errors for UI changes: page.on('console', ...)
  • Use expect(page).toHaveURL() instead of checking raw URL strings
  • Run the smallest relevant test first — npx playwright test path/to/file.spec.ts

Screenshots and Visual Testing

  • Use await expect(page).toHaveScreenshot() for visual regression
  • Avoid whileInView animations and lazy-loaded images in screenshot tests — they produce flaky baselines
  • Use page.setViewportSize() for consistent screenshot dimensions

Patterns to Avoid

  • Timing-based waits (setTimeout, waitForTimeout)
  • Selectors coupled to CSS framework class names (.css-1a2b3c)
  • Tests that depend on external API state without mocking
  • Full test suite runs for single-file logic changes

Raw content

Copy this into your project — e.g. .instructions.md, .agent.md, or SKILL.md

## Overview

Use these instructions when adding or reviewing browser tests. Prefer focused tests over full-suite runs for local logic.

## Locator Strategy

Use stable, user-visible locators in priority order:

1. `getByRole('button', { name: 'Submit' })` — best for accessibility
2. `getByText('Welcome')` — for visible text content
3. `getByTestId('checkout-form')` — when role/text is ambiguous
4. `locator('[data-testid="..."]')` — fallback for complex selectors

Avoid fragile selectors: `nth-child`, deep CSS paths, auto-generated class names.

## Test Structure

- One assertion per logical check — avoid mega-tests that assert 10 things
- Use `test.describe` to group related scenarios
- Use `test.beforeEach` for shared navigation, not repeated `goto()` calls
- Name tests by user behavior: `"user can add item to cart"`, not `"test button click"`

## Reliability Rules

- Never use `page.waitForTimeout()` — use `expect(locator).toBeVisible()` or `waitForResponse()`
- Check console errors for UI changes: `page.on('console', ...)`
- Use `expect(page).toHaveURL()` instead of checking raw URL strings
- Run the smallest relevant test first — `npx playwright test path/to/file.spec.ts`

## Screenshots and Visual Testing

- Use `await expect(page).toHaveScreenshot()` for visual regression
- Avoid `whileInView` animations and lazy-loaded images in screenshot tests — they produce flaky baselines
- Use `page.setViewportSize()` for consistent screenshot dimensions

## Patterns to Avoid

- Timing-based waits (`setTimeout`, `waitForTimeout`)
- Selectors coupled to CSS framework class names (`.css-1a2b3c`)
- Tests that depend on external API state without mocking
- Full test suite runs for single-file logic changes