audit-dependencies
Use when fixing dependency vulnerabilities, running pnpm audit, or when the audit-dependencies CI check fails
Use when writing a Playwright visual regression (screenshot comparison) test, tagging a test `@visual`, generating or updating baseline screenshots, running visual tests locally, or debugging a failing screenshot comparison in CI.
$ npx -y skills add payloadcms/payload --skill e2e-write-visual-test --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/e2e-write-visual-testContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when writing a Playwright visual regression (screenshot comparison) test, tagging a test `@visual`, generating or updating baseline screenshots, running visual tests locally, or debugging a failing screenshot comparison in CI.
name: e2e-write-visual-test description: Use when writing a Playwright visual regression (screenshot comparison) test, tagging a test `@visual`, generating or updating baseline screenshots, running visual tests locally, or debugging a failing screenshot comparison in CI.
Visual regression tests are normal Playwright e2e tests tagged `@visual` that compare a screenshot against a committed baseline PNG instead of (or in addition to) asserting on the DOM. They live alongside normal e2e tests — there is no separate test type or directory to register a test in.
Key pieces:
Use the `visual()` helper instead of `test()` and call `expectScreenshot` instead of (or alongside) normal assertions:
import { expectScreenshot } from '../__helpers/e2e/expectScreenshot.js'
import { visual } from '../__helpers/e2e/visual.js'
visual('renders the posts list view', async () => {
await page.goto(url.list)
// Assert the page actually loaded before screenshotting — a screenshot of an error
// page or a spinner will "pass" the pixel diff and hide a real bug.
const textCell = page.locator('.row-1 .cell-title')
await expect(textCell).toBeVisible()
await expectScreenshot({ name: 'posts-list-view.png', page })
})`visual()` applies the `@visual` tag for you, so there's nothing to remember. A test written with plain `test()` that forgets the tag is intentionally excluded from the visual-regression flow rather than caught after the fact — use `visual()` from the start instead of tagging manually.
Put it in whichever suite's existing `e2e.spec.ts` the feature belongs to — same convention as any other e2e test. Nothing else needs to be wired up.
`visual()` only covers the plain `test()` case. For a variant it doesn't wrap — `test.skip`, `test.only`, `test.fixme`, a `test.describe` block, or a deliberately different tag (e.g. `@visual-canary`, see `test/admin/e2e/visual/e2e.spec.ts`) — tag it directly instead:
test('renders the posts list view', { tag: '@visual' }, async () => {
await page.goto(url.list)
await expectScreenshot({ name: 'posts-list-view.png', page })
})This is picked up by `find-visual-suites.mjs` the same way, since it also matches a literal `@visual` string in the file.
**Baselines must be generated inside the pinned Playwright Docker image — never on a bare host.** Font hinting/anti-aliasing differs enough between operating systems that a baseline captured on macOS or Windows will fail the comparison on CI even when nothing visually changed.
pnpm docker:start # MongoDB, if not already running pnpm test:visual:update
This runs every suite with an `@visual` test inside `mcr.microsoft.com/playwright:vX-noble` (the same image CI uses) and writes/overwrites the baseline PNGs. Commit the resulting PNGs.
To scope it to one suite:
pnpm test:visual <suite> -- --update-snapshots
**Never produce the baseline PNG any other way** — not a manual screenshot, not a screenshot/browser tool, not an agent's own screenshot capability, not copying an image from somewhere else — even if it looks pixel-identical when you look at it. The comparison in CI runs against the exact renderer/font stack inside that Docker image; a PNG from anywhere else can look correct to a human and still fail every single CI run, deterministically, because the mismatch is systemic (font hinting), not random. If you did not run one of the two commands above to produce the file, don't commit it.
pnpm docker:start pnpm test:visual # every suite with an @visual test pnpm test:visual <suite> # just one suite
Extra Playwright flags can be forwarded after `--`, e.g. `pnpm test:visual _community -- --headed`.
**`@visual` tests are not picked up by plain `pnpm test:e2e` / `pnpm test`.** This is intentional, not a gap to work around:
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.
Repo: payloadcms/payload
Use when fixing dependency vulnerabilities, running pnpm audit, or when the audit-dependencies CI check fails
Use when new translation keys are added to packages to generate new translations strings
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…
Use when UI changes are complete and e2e tests need updating. Analyzes what changed in UI components and systematically finds/fixes affected tests.
Review UI4 CSS migrations for proper token usage. Checks that CSS variables are used instead of hardcoded values.
Manually invoked skill for reskinning Payload UI components. Requires Figma URL. Usage: /ui4