agentsclimarketplace

Test frontend

Skill talgacapri/pm-os/.claude/skills/test-frontend

AI operating system for product managers. 65 Claude Code skills, 7 multi-perspective review agents, a memory system. Battle-tested in real PM work.

Install
npx -y skills add talgacapri/pm-os --skill test-frontend

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

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 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

Write, review, and audit frontend tests for a React + Vitest + Playwright codebase. Applies ISTQB CTFL v4.0 standards (black-box techniques, test pyramid, risk-based prioritization, defect taxonomy) combined with E2E-first philosophy and AAA structure. Triggers on "write tests", "test this component", "test coverage", "Playwright", "Vitest", "RTL", "E2E for", or any request to write or review React/frontend tests.

SKILL.md

12.9 KB, as published. Nobody here has run it

Frontend Testing Skill

Stack: React · Vitest · React Testing Library · Playwright Standard: ISTQB CTFL v4.0.1 (ISO/IEC/IEEE 29119 aligned)


ISTQB Foundation: The Seven Testing Principles

Apply these every time. They are not optional ceremony — they shape every decision below.

  1. Testing shows presence, not absence of defects. Tests reduce risk; they don't prove correctness.
  2. Exhaustive testing is impossible. Use risk-based prioritization (see §Risk) to focus effort.
  3. Early testing saves time and money. Write tests before or alongside code, not after.
  4. Defects cluster together. When one bug appears in a component, look for siblings. Retest the cluster.
  5. Tests wear out. Rotate and extend tests each sprint. The same suite repeated blindly misses new defects.
  6. Testing is context dependent. Alpha-stage product? Risk tolerance is different from a financial product in production.
  7. Absence-of-defects fallacy. Passing tests don't mean users are happy. Validate behavior, not just spec conformance.

Test Levels (ISTQB) Mapped to This Stack

ISTQB LevelOur ImplementationTooling
Component (Unit)Pure functions, utilities, custom hooksVitest
Component IntegrationComponents with children, context, storesVitest + RTL
SystemFull user flows end-to-endPlaywright
AcceptanceUAT scenarios / acceptance criteria from user storiesPlaywright (ATDD)

The Test Pyramid: Where to Spend Effort

         /  E2E (Playwright)  \       ← few, slow, high confidence
        /  Integration Tests   \      ← moderate, medium speed
       /  Unit Tests (Vitest)   \     ← many, fast, isolated
      /__________________________\

Rules:

  • Unit tests: pure functions and custom hooks ONLY. No React components.
  • Integration tests: components with real children, real context, minimal mocking (≤2 mocks per test).
  • E2E tests: full user flows. If you need 3+ mocks to write a unit or integration test, write E2E instead.

Test Types (ISTQB §2.2.2)

TypeFrontend Application
FunctionalDoes the component do what the user story says?
Non-functionalAccessibility (axe-core), performance (Core Web Vitals), usability
Black-boxTest via user-visible behavior — roles, labels, text — never internal state
White-boxBranch coverage in business logic utilities (Vitest coverage report)
RegressionEvery bug fix gets a new test. Run full suite in CI on every PR.
ConfirmationAfter a fix: re-run the failing test and verify it passes.

Testing Techniques (ISTQB §4)

Black-Box Techniques (apply to all component tests)

Equivalence Partitioning (EP) Group inputs that the component treats identically. Test one value per partition.

// Button disabled prop — three partitions: true, false, undefined (defaults to false)
it('should be clickable when enabled', ...)      // valid partition
it('should be inert when disabled', ...)          // invalid partition
it('should default to enabled when prop absent', ...) // default partition

Boundary Value Analysis (BVA) Apply to numeric inputs, string lengths, list sizes. Use 3-value BVA: boundary - 1, boundary, boundary + 1.

// Pagination showing max 10 items
it('renders 9 items', ...)   // below boundary
it('renders 10 items', ...)  // at boundary
it('renders 11 items — truncates or paginates', ...) // above boundary

Decision Table Testing Use when a component has multiple conditions producing different outcomes (e.g. form validation).

| isLoggedIn | hasPermission | isExpired | Result        |
|------------|---------------|-----------|---------------|
| true       | true          | false     | Show content  |
| true       | true          | true      | Show refresh  |
| true       | false         | -         | Show 403      |
| false      | -             | -         | Redirect login|

Write one test per column.

State Transition Testing For components with finite states (modals, stepper flows, auth states):

// All States coverage minimum: test every state is reachable
// Valid Transitions coverage preferred: test every allowed transition
// e.g. idle → loading → success / error → idle

White-Box Techniques (utilities and hooks)

Statement Coverage: Every line of a utility executes under test. Target: 100%. Branch Coverage: Every conditional branch (if/else, ternary, switch) is exercised. Target: ≥95%. Run pnpm test:coverage to verify. Branch coverage subsumes statement coverage.

Experience-Based Techniques

Error Guessing: Before writing a test, list: what would a developer likely get wrong here? Null inputs, empty arrays, missing locale, timezone edge cases, race conditions on async.

Exploratory Testing: After writing scripted tests, spend 10 minutes clicking through the component freely. Log anomalies as new test cases.

Checklist-Based Testing: For each PR touching UI, run through:

  • Renders without crash
  • Keyboard navigable
  • Screen reader roles correct
  • Loading state shown
  • Error state shown
  • Empty state shown
  • Responsive at 375px and 1280px

Core Philosophy

E2E tests are the default for user-facing behavior. Unit tests are for pure functions only. Component unit tests are an anti-pattern — they test the wrong thing (implementation) and break on every refactor.

Test behavior, not implementation. Never instance.setState(), never component.props, never internal variable names.

Minimal mocking. Real code > fake code. If you need to mock more than 2 things, that's a signal to write E2E instead.

Selector priority (from strongest to weakest semantic signal): getByRole > getByLabelText > getByPlaceholderText > getByText > getByTestId > CSS selectors (never).


File Structure

src/
  components/
    MyComponent/
      index.tsx
      index.test.tsx       ← co-located unit/integration test (Vitest)
  utils/
    format.ts
    format.test.ts         ← unit test for pure function

e2e/
  tests/
    checkout.spec.ts       ← E2E user flow (Playwright)
    auth.spec.ts
  utils/
    test-helpers.ts        ← shared E2E setup helpers

Test Structure: AAA Pattern (ISTQB)

Every test follows Arrange → Act → Assert. No exceptions.

it('should disable submit when form is invalid', () => {
  // Arrange
  render(<ContactForm />)
  const submitButton = screen.getByRole('button', { name: /submit/i })

  // Act
  await userEvent.type(screen.getByLabelText(/email/i), 'not-an-email')
  await userEvent.tab() // trigger blur/validation

  // Assert
  expect(submitButton).toBeDisabled()
})

Test Naming

Format: should [expected outcome] when [condition]

it('should show error message when email format is invalid')
it('should call onSubmit when form fields are valid')
it('should disable input when isReadOnly is true')
it('should render empty state when no items are provided')

Required Test Scenarios (Minimum)

Every component test file must include:

ScenarioAlways Required
Renders without crashing
Required props render correctly
Optional props with defaults
null / undefined / empty inputs
Boundary values (if numeric or list input)

Conditional (include when the feature is present):

FeatureAdd these tests
onClick / onSubmitTriggers once, passes correct args
Async / API callLoading state, success state, error state
useEffectRuns on mount, runs on dep change, cleanup
RoutingNavigation happens, params passed
FormValidates, submits, shows field errors
PaginationAt boundary, below, above

Incremental Workflow

When testing a directory or feature, never generate all tests at once.

For each file (ordered: utilities → hooks → simple components → complex → integration):
  1. Write test
  2. Run: pnpm test path/to/file.test.tsx
  3. PASS → mark done, proceed to next
  4. FAIL → fix first, do not continue until green

Complexity > 50 lines of logic? Extract to a hook or utility, then test that in isolation first.


Coverage Targets

MetricTarget
Statement coverage100%
Branch coverage≥95%
Function coverage100%
Line coverage≥95%

Run: pnpm test:coverage and review the HTML report in coverage/. Fix uncovered branches before marking a story done.


E2E Test Structure (Playwright)

// e2e/tests/checkout.spec.ts
import { test, expect } from '@playwright/test'
import { createTestAccount, addFunds } from '../utils/test-helpers'

test.describe('Checkout', () => {
  test.beforeEach(async ({ page, context }) => {
    await createTestAccount(page, { status: 'active' })
    const cookies = await context.cookies()
    const accountId = cookies.find(c => c.name === 'account_id')?.value
    await addFunds({ accountId, amount: 10000 })
  })

  test('user can complete checkout with default payment method', async ({ page }) => {
    // Arrange
    await page.goto('/catalog')

    // Act
    await page.getByRole('heading', { name: 'Product Name' }).click()
    await page.getByRole('button', { name: /buy now/i }).click()
    await page.getByRole('button', { name: /confirm/i }).click()

    // Assert
    await expect(page.getByRole('heading', { name: /order confirmed/i })).toBeVisible()
  })
})

E2E Selector Rules:

  1. getByRole — always first choice
  2. getByLabel — for form inputs
  3. getByText — for static content
  4. getByTestId — last resort when no accessible selector exists
  5. CSS selectors — never

Risk-Based Test Prioritization (ISTQB §5.1.5 + §5.2)

Before writing tests, classify each area by:

  • Risk likelihood (how often does this area change?)
  • Risk impact (what fails if this is broken? payments > UI polish)

Execute in this order:

  1. High likelihood + High impact → full coverage, E2E + integration
  2. Low likelihood + High impact → integration + boundary tests
  3. High likelihood + Low impact → smoke tests
  4. Low likelihood + Low impact → minimal, if time allows

Example for fintech: payment flows, auth, KYC steps = highest risk. Animations, empty states = lowest risk. Tune this for your domain.


Defect Reporting (ISTQB §5.5)

When a test fails and you're logging a bug, include:

Title: [Component] [Behavior] when [condition]
Severity: Critical / Major / Minor / Cosmetic
Steps to Reproduce:
  1. Navigate to /page
  2. Click X
  3. Enter Y
Expected: Z
Actual: W
Test that catches it: [link to spec file + test name]
Root Cause (if known): Error / Defect / Environmental

The distinction matters (ISTQB §1.2.3):

  • Error = developer mistake (e.g., wrong logic)
  • Defect = the bug in the code (e.g., off-by-one)
  • Failure = what the user sees (e.g., wrong total shown)

Static Testing Checklist (ISTQB §3) — PR Review

Before merging any frontend PR, confirm:

  • No unused variables or imports (ESLint clean)
  • No hardcoded strings that should be i18n keys
  • Accessibility attributes present (aria-label, role)
  • No console.log left in production code
  • Component props typed (no any)
  • Error boundaries in place for async data sections

Key Commands

# Run all unit/integration tests
pnpm test

# Watch mode during development
pnpm test:watch

# Run a specific test file
pnpm test src/components/Button/index.test.tsx

# Coverage report
pnpm test:coverage

# Run E2E tests
pnpm playwright test

# Run specific E2E spec
pnpm playwright test e2e/tests/checkout.spec.ts

# Run E2E in headed mode (debugging)
pnpm playwright test --headed

Collaboration-Based Testing (ISTQB §4.5)

When working with designers and engineers on user stories:

ATDD approach: Before any code is written, define acceptance criteria in Given/When/Then format. These become your Playwright tests.

Given a logged-in user with sufficient balance
When they tap "Send Money" and complete the flow
Then the transaction appears in history with correct amount and status

INVEST check for stories before testing:

  • Independent: test can run without other test state
  • Negotiable: acceptance criteria written collaboratively
  • Valuable: tests a real user need, not an implementation detail
  • Estimable: you can estimate testing effort
  • Small: one user story = one focused test scenario
  • Testable: acceptance criteria exist and are unambiguous

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.