Source profileQuality 86/100Review permissions

payloadcms/payload/.claude/skills/ui4-convert-tests/SKILL.md

ui4-convert-tests

Use when UI changes are complete and e2e tests need updating. Analyzes what changed in UI components and systematically finds/fixes affected tests.

Source repository stars
44,005
Declared platforms
0
Static risk flags
1
Last source update
2026-08-06
Source checked
2026-08-06

Decision brief

What it does—and where it fits

Analyzes what changed in UI components and systematically finds/fixes affected tests.

Best for

  • UI changes are finalized and ready for test fixes
  • CI is failing on tests due to your UI changes
  • Before opening a PR to ensure tests pass

Not for

  • Dev server not running or wrong port: Tests read PORT env var (default 3000). Two approaches:
  • Option A: Use isolated port (preferred for parallel test suites)

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/payloadcms/payload --skill ".claude/skills/ui4-convert-tests"
Safe inspection promptEditorial

Inspect the Agent Skill "ui4-convert-tests" from https://github.com/payloadcms/payload/blob/8b2f2484a7556adeaab679538374228f9c395213/.claude/skills/ui4-convert-tests/SKILL.md at commit 8b2f2484a7556adeaab679538374228f9c395213. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    Process

    Goal: Understand the nature of your changes to predict test impact.

    Goal: Understand the nature of your changes to predict test impact.
  2. 02

    Step 1: Analyze What Changed

    Goal: Understand the nature of your changes to predict test impact.

    Goal: Understand the nature of your changes to predict test impact.
  3. 03

    Step 2: Find Affected Tests

    Search strategy: Cast a wide net, then narrow down.

    Search strategy: Cast a wide net, then narrow down.
  4. 04

    Search for specific selectors from Step 1

    grep -rn "\.list-header\|Create New\|create-new" test//.ts typescript // test//helpers/togglePreset.ts export async function openCreatePreset(page: Page) { await page.click('select-preset') // Open popup first await page.click('create-new-preset') } bash

    grep -rn "\.list-header\|Create New\|create-new" test//.ts typescript // test//helpers/togglePreset.ts export async function openCreatePreset(page: Page) { await page.click('select-preset') // Open popup first await pag…
  5. 05

    Step 3: Analyze Test Dependencies

    Before fixing, understand the test:

    Read the full test - Understand what it's actually testingCheck for helpers - Is there a shared helper that handles this selector?Look for patterns - Are multiple tests doing the same thing?

Permission review

Static risk signals and limitations

Runs scripts

medium · line 22

The documentation asks the agent to run terminal commands or scripts.

git diff main --name-only -- 'packages/ui/src/**/*.tsx' 'packages/ui/src/**/*.css'

Runs scripts

medium · line 30

The documentation asks the agent to run terminal commands or scripts.

git diff main -- <file> | grep -E '^\-.*className|^\-.*id=|^\+.*className|^\+.*id='

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score86/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars44,005SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
payloadcms/payload
Skill path
.claude/skills/ui4-convert-tests/SKILL.md
Commit
8b2f2484a7556adeaab679538374228f9c395213
License
MIT
Collected
2026-08-06
Default branch
main
View the original SKILL.md

UI4 Convert Tests

Overview

After completing UI changes, this skill systematically identifies and fixes affected e2e tests. It analyzes the diff to understand what kind of changes were made (not just which files), then finds tests that need updates.

When to Use

  • UI changes are finalized and ready for test fixes
  • CI is failing on tests due to your UI changes
  • Before opening a PR to ensure tests pass

Process

Step 1: Analyze What Changed

Goal: Understand the nature of your changes to predict test impact.

# Get changed UI files
git diff main --name-only -- 'packages/ui/src/**/*.tsx' 'packages/ui/src/**/*.css'

For each changed file, categorize the changes:

A. Selector Changes (IDs, classes)

git diff main -- <file> | grep -E '^\-.*className|^\-.*id=|^\+.*className|^\+.*id='

B. Structural Changes (elements moved)

Look for components being:

  • Moved INTO a popup, drawer, or dropdown
  • Wrapped in new parent elements
  • Made conditional
git diff main -- <file> | grep -E 'Popup|PopupList|Drawer|Dropdown'

C. Text/Label Changes

# Translation keys
git diff main -- <file> | grep -E "t\('|i18n\.t\("

# Hardcoded text
git diff main -- <file> | grep -E 'placeholder=|aria-label='

Build a change summary:

Change TypeWhat ChangedTest Impact
Selector.btn:has-text("Create")#create-new-docUpdate locators
StructureButton moved into popupAdd popup open step
Text"Search by ID" → "Search"Update assertions

Step 2: Find Affected Tests

Search strategy: Cast a wide net, then narrow down.

# Search for component name references (not just selectors)
grep -rn "QueryPreset\|query-preset\|preset" test/**/*.ts --include="*.spec.ts" --include="*.ts"

# Search for specific selectors from Step 1
grep -rn "\.list-header\|Create New\|#create-new" test/**/*.ts

Key test locations:

PatternWhere to Look
Component-specifictest/<feature>/e2e.spec.ts
Shared helperstest/<feature>/helpers/*.ts
Cross-cuttingtest/__helpers/e2e/*.ts
Multiple features using same componentSearch ALL test dirs

Don't just search for exact selectors! Also search for:

  • Component names (e.g., QueryPreset, ListHeader)
  • Feature names (e.g., preset, filter, search)
  • Text content that changed (e.g., "Create New", "Search by")

Step 3: Analyze Test Dependencies

Before fixing, understand the test:

  1. Read the full test - Understand what it's actually testing
  2. Check for helpers - Is there a shared helper that handles this selector?
  3. Look for patterns - Are multiple tests doing the same thing?

If multiple tests use the same selector, create/update a helper:

// test/<feature>/helpers/togglePreset.ts
export async function openCreatePreset(page: Page) {
  await page.click('#select-preset') // Open popup first
  await page.click('#create-new-preset')
}

This centralizes the fix and prevents future duplication.

Step 4: Categorize Fixes Needed

Change TypeFix Strategy
Selector renamedDirect string replacement
Element moved to popupAdd click to open popup before clicking element
Element moved to drawerAdd drawer open/close handling
Text simplifiedUpdate assertion to match new text
Element removedRework test logic or delete test
Props changedUpdate attribute assertions
Conditional renderingMay need to set up state before element appears

Step 5: Run Affected Tests

Run tests BEFORE making fixes to confirm they actually fail:

# Use isolated port to avoid conflicts
PORT=3150 pnpm test:e2e <suite> --max-failures=1

# Run specific test by name
PORT=3150 pnpm test:e2e <suite> -g "test name" --max-failures=1

Document failure patterns:

  • Timeout waiting for locator('.old-selector') → Selector changed
  • locator resolved to 0 elements → Element moved or removed
  • expected "New Text" received "Old Text" → Text content changed

Step 6: Apply Fixes

Priority: Fix helpers first, then individual tests.

Pattern 1: Selector Renamed

// Before
await page.click('.list-header .btn:has-text("Create")')

// After - prefer IDs when available
await page.click('#create-new-doc')

Pattern 2: Element Moved Into Popup

// Before - direct click
await page.click('#edit-preset')

// After - open popup first
await page.click('#select-preset') // Opens the popup
await page.click('#edit-preset') // Now visible in popup

Pattern 3: Text Content Simplified

// Before - specific placeholder text
await expect(input).toHaveAttribute('placeholder', /(Search by ID)/)

// After - simplified text
await expect(input).toHaveAttribute('placeholder', 'Search')

Pattern 4: Create Reusable Helper

When the same interaction is needed in multiple tests:

// test/<feature>/helpers/interactions.ts
export async function openEditPreset(page: Page) {
  await page.click('#select-preset')
  await page.click('#edit-preset')
}

// In tests - import and use
import { openEditPreset } from './helpers/interactions.js'
await openEditPreset(page)

Step 7: Verify Fixes

# Run same tests that failed
PORT=3150 pnpm test:e2e <suite> --max-failures=1

Only commit after tests pass.

Common Patterns (Real Examples)

Pattern: Buttons Moved Into Popup Menu

Symptom: Test times out waiting for button that used to be directly visible.

Detection: Check if buttons were wrapped in <Popup> or <PopupList>:

git diff main -- <file> | grep -E 'PopupList|Popup'

Fix: Add popup trigger click before clicking the button:

// Before: Button was directly in toolbar
await page.click('#edit-preset')

// After: Button is now inside a popup
await page.click('#select-preset') // Opens popup
await page.click('#edit-preset') // Now visible

Bonus: If multiple tests need this, create a helper function.

Pattern: Class-Based Selector → ID Selector

Symptom: .some-class or :has-text("Button Text") no longer finds element.

Detection: Component added id= attribute:

git diff main -- <file> | grep -E '^\+.*id='

Fix: Use the more stable ID:

// Before: Fragile class + text selector
await page.click('.list-header .btn:has-text("Create New")')

// After: Stable ID selector
await page.click('#create-new-doc')

Pattern: Placeholder/Label Text Simplified

Symptom: Assertion fails with expected "New Text" received "Old Text".

Detection: Translation key or hardcoded text changed:

git diff main -- <file> | grep -E 'placeholder=|t\('

Fix: Update assertion to match new text:

// Before: Verbose placeholder
await expect(input).toHaveAttribute('placeholder', /(Search by ID, Title)/)

// After: Simplified
await expect(input).toHaveAttribute('placeholder', 'Search')

Pattern: Same Fix Needed Across Multiple Tests

Symptom: Several tests in different suites fail with similar selector issues.

Detection:

# Find all tests using the old selector
grep -rn "old-selector\|.old-class" test/**/*.ts

Fix:

  1. Check if a helper already exists in test/<feature>/helpers/
  2. If yes, fix the helper (fixes all tests at once)
  3. If no, create one and refactor tests to use it

Pattern: Tests in Different Suites Share Components

When you change a shared component (like ListControls, QueryPresetBar), multiple test suites may be affected.

Detection:

# Find component name references across all tests
grep -rn "QueryPreset\|ListControl" test/**/*.ts | cut -d: -f1 | sort -u

Common cross-suite components:

  • ListControls → affects any list view tests
  • QueryPresetBar → query-presets, group-by, admin tests
  • Search → i18n, admin, most collection tests
  • Button → nearly everything

Quick Reference: Common Payload Test Selectors

ComponentCommon Selectors
Search.search-filter__input, #search-filter-input
List View.collection-list, tbody tr, .table-row
Popup.popup__content, .popup-button-list__button
Modaldialog, [id^=doc-drawer_], [id^=list-drawer_]
Buttons.btn, button[type="button"]
Query Presets#select-preset, .query-preset-bar__*

Test Commands Reference

# Run all e2e tests for a test suite (auto-starts dev server)
PORT=3150 pnpm test:e2e <suite-name>

# Run specific test file
PORT=3150 pnpm test:e2e test/<suite>/e2e.spec.ts

# Run with headed browser (see what's happening)
PORT=3150 pnpm test:e2e:headed test/<suite>/e2e.spec.ts

# Run in debug mode (step through)
PORT=3150 pnpm test:e2e:debug test/<suite>/e2e.spec.ts

# Run specific test by name pattern
PORT=3150 pnpm test:e2e test/<suite>/e2e.spec.ts -g "test name pattern"

# Stop on first failure (useful during debugging)
PORT=3150 pnpm test:e2e test/<suite>/e2e.spec.ts --max-failures=1

Note: The pnpm test:e2e command automatically:

  1. Starts a dev server if the port is free
  2. Reuses an existing dev server if the port is in use
  3. Runs playwright tests against that port

Running Tests with Isolation

Quick Start: Isolated Test Run

Pick a unique port in the 3100-3199 range:

# Run tests on an isolated port (MongoDB auto-starts its own in-memory server)
PORT=3150 pnpm test:e2e query-presets --max-failures=1

That's it for MongoDB (default). Each test run starts its own in-memory MongoDB server, so no database conflicts occur.

Postgres Isolation

For Postgres tests, use a unique database per worktree/repo:

# Create a unique database for this worktree
PGPASSWORD=payload psql -h localhost -p 5433 -U payload -c "CREATE DATABASE payload_worktree1;"

# Run tests against that database
POSTGRES_URL="postgres://payload:payload@localhost:5433/payload_worktree1" \
  PORT=3150 pnpm test:e2e query-presets --max-failures=1

Or use the custom schema approach (no separate DB needed):

# Tests will use a separate schema within the same database
PAYLOAD_DATABASE=postgres-custom-schema PORT=3150 pnpm test:e2e query-presets

Why Isolation Matters

ScenarioPort Conflict?DB Conflict?
MongoDB in-memoryYes (same port)No (each run has own server)
PostgresYes (same port)Yes (same tables)
Multiple worktreesYesYes (Postgres only)

Solution: Always set PORT to avoid port conflicts. For Postgres, also isolate the database.

Common Mistakes

Dev server not running or wrong port: Tests read PORT env var (default 3000). Two approaches:

Option A: Use isolated port (preferred for parallel test suites)

# Run tests on custom port - script handles everything
PORT=3105 pnpm test:e2e test/query-presets/e2e.spec.ts

Option B: Kill existing ports and use default

# Kill all dev server ports
lsof -ti:3000,3001,3002,3003,3004,3005,3006,3007,3008,3009 | xargs kill -9 2>/dev/null

# Tests use 3000 by default
pnpm test:e2e test/query-presets/e2e.spec.ts

Wrong test suite running: Each test suite (fields, query-presets, localization, etc.) has its own Payload config. Tests will fail or behave unexpectedly if the wrong dev server is running.

Not running tests before fixing: Always verify tests actually fail before making changes. If a test passes, don't change it.

Not checking helper files: Test helpers in test/*/helpers/ often contain shared selectors that affect multiple tests.

Missing popup interactions: When elements move into popups, tests need to open the popup first.

Forgetting confirmation dialogs: Delete actions often add confirmation modals - tests need to handle the confirm step.

Placeholder text changes: Search placeholders, button labels, and other text content may change.

Modal slug mismatches: When deleting/confirming actions, the modal slug may change. Check the component code for the actual slug prop passed to <Modal> or drawer components.

Example: QueryPresetBar Changes

Old structure (chips):

// Direct buttons visible
await page.click('#create-new-preset')
await page.click('#edit-preset')
await page.click('#delete-preset')
await page.click('.chip__remove') // clear

New structure (popup dropdown):

// Open popup first
await page.click('#select-preset')
// Then click menu items
await page.click('.popup-button-list__button:has-text("Create New")')
await page.click('.popup-button-list__button:has-text("Edit")')
await page.click('.popup-button-list__button:has-text("Delete")')
// Clear uses dedicated button
await page.click('.query-preset-bar__clear')

Alternatives

Compare before choosing

Computed 10043,183

coreyhaines31/marketingskills

ab-testing

When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program

Computed 100148

JasonColapietro/suede-creator-skills

suede-ab-testing

Suede-owned experimentation discipline for hypotheses, sample sizing, test duration, significance, and repeatable experiment programs. Use when comparing variants, deciding whether a result is reliable, or building an experiment backlog and cadence. NOT FOR: analytics instrumentation (use suede-analytics), post-click conversion diagnosis (use suede-site-alchemy), or writing the variant copy itself (use suede-copy).

Computed 1007

narrative-io/narrative-skills-marketplace

design-analysis

Translate a fuzzy analytical question into a rigorous investigation plan. Interrogates the ask, grounds the plan in the available data dictionary, applies analytical best practices, and produces a structured brief of query specifications for a downstream query-writing skill. Plans, does not write SQL. Use when: "why did X drop", "is there a relationship between A and B", "who are our highest-value customers", "what's driving the change in Y", "investigate this trend", "design an analysis for", "

Computed 97237

Aperivue/medsci-skills

calc-sample-size

Interactive sample size calculator for medical research. Decision-tree guided test selection, reproducible R/Python code, effect size interpretation, and IRB-ready justification text. Supports diagnostic accuracy, agreement, proportions, continuous outcomes, survival, ANOVA, logistic regression, and non-inferiority/equivalence designs.