/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.
$ npx -y skills add payloadcms/payload --skill ui4-convert-tests --agent claude-codeHow 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.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/ui4-convert-tests
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when UI changes are complete and e2e tests need updating. Analyzes what changed in UI components and systematically finds/fixes affected tests.
SKILL.md
ui4-convert-tests.SKILL.mdname: ui4-convert-tests
description: Use when UI changes are complete and e2e tests need updating. Analyzes what changed in UI components and systematically finds/fixes affected tests.
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 Type | What Changed | Test Impact | | ----------- | --------------------------------------------- | ------------------- | | Selector | `.btn:has-text("Create")` → `#create-new-doc` | Update locators | | Structure | Button moved into popup | Add 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:**
| Pattern | Where to Look | | -------------------------------------- | ----------------------------- | | Component-specific | `test/<feature>/e2e.spec.ts` | | Shared helpers | `test/<feature>/helpers/*.ts` | | Cross-cutting | `test/__helpers/e2e/*.ts` | | Multiple features using same component | Search 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 Type | Fix Strategy | | --------------------------- | ----------------------------------------------- | | **Selector renamed** | Direct string replacement | | **Element moved to popup** | Add click to open popup before clicking element | | **Element moved to drawer** | Add drawer open/close handling | | **Text simplified** | Update assertion to match new text | | **Element removed** | Rework test logic or delete test | | **Props changed** | Update attribute assertions | | **Conditional rendering** | May 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 popupPattern 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 pageRead more
name: ui4-convert-tests description: Use when UI changes are complete and e2e tests need updating. Analyzes what changed in UI components and systematically finds/fixes affected tests.
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 Type | What Changed | Test Impact | | ----------- | --------------------------------------------- | ------------------- | | Selector | `.btn:has-text("Create")` → `#create-new-doc` | Update locators | | Structure | Button moved into popup | Add 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:**
| Pattern | Where to Look | | -------------------------------------- | ----------------------------- | | Component-specific | `test/<feature>/e2e.spec.ts` | | Shared helpers | `test/<feature>/helpers/*.ts` | | Cross-cutting | `test/__helpers/e2e/*.ts` | | Multiple features using same component | Search 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 Type | Fix Strategy | | --------------------------- | ----------------------------------------------- | | **Selector renamed** | Direct string replacement | | **Element moved to popup** | Add click to open popup before clicking element | | **Element moved to drawer** | Add drawer open/close handling | | **Text simplified** | Update assertion to match new text | | **Element removed** | Rework test logic or delete test | | **Props changed** | Update attribute assertions | | **Conditional rendering** | May 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 popupPattern 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 pagePayload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.
Repo: payloadcms/payload
Other skills on payload.
- /audit-dependencies
Use when fixing dependency vulnerabilities, running pnpm audit, or when the audit-dependencies CI check fails
Open skill - /generate-translations
Use when new translation keys are added to packages to generate new translations strings
Open skill - /triage-ci-flake
Use when CI tests fail on main branch after PR merge, when investigating flaky test failures, or when user provides a PR URL/number to aggregate all failing tests
Open skill - /ui4-review
Review UI4 CSS migrations for proper token usage. Checks that CSS variables are used instead of hardcoded values.
Open skill - /ui4
Manually invoked skill for reskinning Payload UI components. Requires Figma URL. Usage: /ui4
Open skill - /payload
Use when working with Payload projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.
Open skill

