Skip to content
Development
Skill

/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.

From plugin
payload
44k7 skills3 commands2 MCP
Install
$ npx -y skills add payloadcms/payload --skill ui4-convert-tests --agent claude-code

How 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.md
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 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
Read more
Ships withpayload

Payload 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.

Get the whole plugin