Files
supabase/.github/instructions/studio-e2e-tests.instructions.md
Danny White a074b62ed1 chore(studio): use sentence case for Data API access label (#47353)
## What kind of change does this PR introduce?

UI copy + agent guidance.

## What is the current behavior?

- The Table Editor labels the Data API setting as "Data API Access"
(title case).
-  Agents have no scoped pointer to our copywriting rules

## What is the new behavior?

- Label uses sentence case: "Data API access" (e2e and test docs
updated).
- Agents are pointed at
`apps/design-system/content/docs/copywriting.mdx` via
`studio-copy.instructions.md` and `studio-ui-patterns` skill.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Standardized the **“Data API access”** label casing across the Studio
UI.
  * Updated end-to-end tests to assert the corrected label text.
* **Documentation**
* Updated Studio E2E test review instructions and examples to use
**“Data API access”**.
* Added/expanded Studio UI copywriting guidance, including where to
source copy and how to apply consistent casing.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 14:50:37 -06:00

2.2 KiB

applyTo
applyTo
e2e/studio/**,apps/studio/**

Studio E2E Test Review Rules

All comments are advisory.

Selector Priority (best to worst)

  1. getByRole with accessible name — most robust, tests accessibility

    page.getByRole('button', { name: 'Save' })
    
  2. getByTestId — stable, explicit test hooks

    page.getByTestId('table-editor-side-panel')
    
  3. getByText with exact match — good for unique text

    page.getByText('Data API access', { exact: true })
    
  4. locator with CSS — use sparingly, more fragile

    page.locator('[data-state="open"]')
    

Patterns to Flag

  • XPath selectors — fragile to DOM changes

    // BAD
    locator('xpath=ancestor::div[contains(@class, "space-y")]')
    
  • Parent traversal with locator('..') — breaks when structure changes

    // BAD
    element.locator('..').getByRole('button')
    
  • waitForTimeout — never use; wait for something specific instead

    // BAD
    await page.waitForTimeout(1000)
    
    // GOOD — wait for UI element
    await expect(page.getByText('Success')).toBeVisible()
    
    // GOOD — wait for API response
    const apiPromise = waitForApiResponse(page, 'pg-meta', ref, 'query?key=table-create')
    await saveButton.click()
    await apiPromise
    
  • force: true on clicks — make elements visible first instead

    // BAD
    await menuButton.click({ force: true })
    
    // GOOD — hover to reveal, then click
    await tableRow.hover()
    await expect(menuButton).toBeVisible()
    await menuButton.click()
    
  • Broad filter({ hasText }) on generic elements — may match multiple elements; scope to specific containers instead

Good Practices to Encourage

  • Scope selectors to containers: page.getByTestId('side-panel').getByRole('switch')
  • Add aria-label to icon-only buttons in source code for better test selectors
  • Use test.describe.configure({ mode: 'serial' }) for tests sharing database state
  • Add messages to expects: await expect(locator, 'why').toBeVisible({ timeout: 30000 })

Canonical standard: .claude/skills/studio-e2e-tests/SKILL.md