Files
supabase/.github/instructions/studio-e2e-tests.instructions.md
T
Danny WhiteandCursor 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

87 lines
2.2 KiB
Markdown

---
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
```typescript
page.getByRole('button', { name: 'Save' })
```
2. **`getByTestId`** — stable, explicit test hooks
```typescript
page.getByTestId('table-editor-side-panel')
```
3. **`getByText` with exact match** — good for unique text
```typescript
page.getByText('Data API access', { exact: true })
```
4. **`locator` with CSS** — use sparingly, more fragile
```typescript
page.locator('[data-state="open"]')
```
## Patterns to Flag
- **XPath selectors** — fragile to DOM changes
```typescript
// BAD
locator('xpath=ancestor::div[contains(@class, "space-y")]')
```
- **Parent traversal with `locator('..')`** — breaks when structure changes
```typescript
// BAD
element.locator('..').getByRole('button')
```
- **`waitForTimeout`** — never use; wait for something specific instead
```typescript
// 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
```typescript
// 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`