AgentSkillsCN

E2e Selectors

适用于 Playwright 端到端测试的稳定 data-* 选择器

SKILL.md
--- frontmatter
description: Stable data-* selectors for Playwright E2E tests
category: Testing
boundary: Frontend + E2E (fe/ and e2e/)
version: 2.2

E2E Selectors

Use stable data-* attributes for Playwright E2E tests.

Why

  • CSS classes change (Tailwind refactors)
  • Text changes (i18n translations)
  • DOM structure changes (component rewrites)
  • Portals render dropdowns under document.body, breaking scoped selectors

Rules

Naming

  • Use kebab-case for attribute names
  • Use short, explicit ids: edit, delete, view, create, submit
  • Prefix by feature when needed: storage-<id>, product-<id>

Standard Attributes

AttributePurposeExample
data-nav-idSidebar nav itemdata-nav-id="storage"
data-menu-idAction menu instancedata-menu-id="storage-<uuid>"
data-action-idAction inside menudata-action-id="edit"
data-target-idEntity id for menudata-target-id="<uuid>"
data-modal-idModal instancedata-modal-id="create-storage"
data-modal-confirmModal confirm buttondata-modal-confirm

Patterns

Sidebar Navigation

tsx
// Component
<button data-nav-id="storage">Storage</button>

// Playwright
await page.locator('[data-nav-id="storage"]').click();

Action Menu (with Portal)

tsx
// Component uses ActiveMenu with menuId prop
<ActiveMenu menuId={`storage-${item.id}`} items={[
  { id: 'edit', label: 'Edit', ... },
  { id: 'delete', label: 'Delete', ... }
]} />

// Playwright - open menu
await page.locator('[data-menu-trigger][data-menu-id="storage-<id>"]').click();

// Playwright - click action (works even with portal!)
await page.locator('[data-menu-action][data-menu-id="storage-<id>"][data-action-id="delete"]').click();

Modal Confirm

tsx
// Playwright
await page.locator('[data-modal-confirm][data-modal-id="create-storage"]').click();

When to Add Selectors

Add data-* when element is:

  • Part of critical flow (create/edit/delete, navigation, submit)
  • Hard to select reliably (portals, hover-only, icons without text, i18n)

Don't add everywhere—only where E2E needs stability.

Checklist (PR Review)

  • Selectors don't depend on Tailwind classes
  • Selectors don't depend on translated text
  • Portaled UI has stable data-menu-id
  • Actions have stable data-action-id
  • Values are deterministic (no random strings)