Official agent skill

Studio E2E Tests

by supabase in supabase/supabase

Write and run Playwright E2E tests for Supabase Studio (e2e/studio).

OfficialApache-2.0Auto-check passedTesting & QA

Install Studio E2E Tests

skills CLI
$ npx skills add supabase/supabase --skill studio-e2e-tests -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install supabase/supabase studio-e2e-tests --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/supabase/supabase.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/studio-e2e-tests .claude/skills/studio-e2e-tests && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
studio-e2e-tests
GitHub stars
111k
Token cost
~2.8k tokens
SKILL.md length
669 words
Files
1
Skills in repo
22
Repo updated
First seen
Licence
Apache-2.0

At a glance

Write and run Playwright E2E tests for Supabase Studio (e2e/studio).

  • Works in 4 steps: getByRole with accessible name - Most… → getByTestId - Stable, explicit test hooks → getByText with exact match - Good for… → …
  • Asked to run e2e tests
  • SKILL.md covers Running Tests, Environment Setup, Test File Structure and Common Patterns, plus 12 more sections
  • Calls pnpm

What it does

Studio E2E Tests is an agent skill from supabase/supabase, published by the product's own GitHub organization. Write and run Playwright E2E tests for Supabase Studio (e2e/studio). Use when asked to run e2e tests, write new E2E tests, or debug flaky or failing Playwright tests. Covers running commands, avoiding race conditions, waiting strategies, selectors, helper functions, and CI vs local differences.

Its SKILL.md is about 2.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Testing & QA, covering End-to-end testing, Async programming and Browser testing. It works with Supabase and Playwright. The repository describes itself as: The Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications. The licence is Apache-2.0.

When your agent uses it

  • Asked to run e2e tests
  • Write new E2E tests
  • Failing Playwright tests

Example prompts

  • “/studio-e2e-tests”

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. getByRole with accessible name - Most robust, tests accessibility
  2. getByTestId - Stable, explicit test hooks
  3. getByText with exact match - Good for unique text
  4. locator with CSS - Use sparingly, more fragile

What it can do on your machine

Read from SKILL.md and the folder at commit 26c838a. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • pnpm

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use pnpm, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Studio E2E Tests loads about 2.8k tokens when it runs. Until then it costs about 78 tokens; SKILL.md has 669 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~78
When it runs · the whole SKILL.md, loaded when a task matches
~2.8k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from supabase/supabase at commit 26c838a, republished under its Apache-2.0 licence (© supabase). 669 words, ~2,762 tokens.

Download SKILL.mdSave it as .claude/skills/studio-e2e-tests/SKILL.md (or your agent's skills folder).
name
studio-e2e-tests
description
Write and run Playwright E2E tests for Supabase Studio (e2e/studio). Use when asked to run e2e tests, write new E2E tests, or debug flaky or failing Playwright tests. Covers running commands, avoiding race conditions, waiting strategies, selectors, helper functions, and CI vs local differences.

E2E Studio Tests

Run Playwright end-to-end tests for the Studio application.

Running Tests

Tests must be run from the e2e/studio directory:

bash
cd e2e/studio && pnpm run e2e
Run specific file
bash
cd e2e/studio && pnpm run e2e -- features/cron-jobs.spec.ts
Run with grep filter
bash
cd e2e/studio && pnpm run e2e -- --grep "test name pattern"
UI mode for debugging
bash
cd e2e/studio && pnpm run e2e -- --ui

Environment Setup

  • Tests auto-start Supabase local containers via web server config
  • Self-hosted mode (IS_PLATFORM=false) runs tests in parallel (3 workers)
  • No manual setup needed for self-hosted tests

Test File Structure

  • Tests are in e2e/studio/features/*.spec.ts
  • Use custom test utility: import { test } from '../utils/test.js'
  • Test fixtures provide page, ref, and other helpers

Common Patterns

Wait for elements with generous timeouts:

typescript
await expect(locator).toBeVisible({ timeout: 30000 })

Use serial mode for tests sharing database state:

typescript
test.describe.configure({ mode: 'serial' })

Writing Robust Selectors

Selector priority (best to worst)
  1. getByRole with accessible name - Most robust, tests accessibility

    typescript
    page.getByRole('button', { name: 'Save' })
    page.getByRole('button', { name: 'Configure API privileges' })
  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 avoid
  • 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')
  • Broad filter({ hasText }) on generic elements - May match multiple elements

    typescript
    // BAD - popover may have more than one combobox
    // Could consider scoping down the container or filtering the combobox more specifically
    popover.getByRole('combobox')
Add accessible labels to components

When a component lacks a good accessible name, add one in the source code:

tsx
// In the React component
<Button aria-label="Configure API privileges">
  <Settings />
</Button>

Then use it in tests:

typescript
page.getByRole('button', { name: 'Configure API privileges' })
Narrowing search scope

Scope selectors to specific containers to avoid matching wrong elements:

typescript
// Good - scoped to side panel
const sidePanel = page.getByTestId('table-editor-side-panel')
const toggle = sidePanel.getByRole('switch')

// Good - find unique element, then scope from there
const popover = page.locator('[data-radix-popper-content-wrapper]')
const roleSection = popover.getByText('Anonymous (anon)', { exact: true })

Avoiding Race Conditions

Set up API waiters BEFORE triggering actions. This is the most common source of flaky tests.

ts
// ❌ Race condition — response may complete before waiter is set up
await page.getByRole('button', { name: 'Save' }).click()
await waitForApiResponse(page, 'pg-meta', ref, 'query?key=table-create')

// ✅ Waiter is ready before the action
const apiPromise = waitForApiResponse(page, 'pg-meta', ref, 'query?key=table-create')
await page.getByRole('button', { name: 'Save' }).click()
await apiPromise

Same rule applies before navigation:

ts
const loadPromise = waitForTableToLoad(page, ref)
await page.goto(toUrl(`/project/${ref}/editor?schema=public`))
await loadPromise

When an action triggers multiple API calls, wait for all of them:

ts
const createTablePromise = waitForApiResponseWithTimeout(page, (r) =>
  r.url().includes('query?key=table-create')
)
const tablesPromise = waitForApiResponseWithTimeout(page, (r) =>
  r.url().includes('tables?include_columns=true')
)

await page.getByRole('button', { name: 'Save' }).click()
await Promise.all([createTablePromise, tablesPromise])

Waiting Strategies

Playwright auto-waits for elements to be actionable — prefer this over manual timeouts.

Use expect.poll for dynamic state changes:

ts
await expect.poll(async () => await page.getByLabel(`View ${tableName}`).count()).toBe(0)

Use waitForSelector with state for element lifecycle:

ts
await page.waitForSelector('[data-testid="side-panel"]', { state: 'detached' })

Avoid networkidle — use specific API waits instead:

ts
// ❌ Unreliable and slow
await page.waitForLoadState('networkidle')

// ✅ Specific API response
await waitForApiResponse(page, 'pg-meta', ref, 'tables')

The only acceptable use of waitForTimeout is a client-side debounce:

ts
await page.getByRole('textbox').fill('search term')
await page.waitForTimeout(300) // allow debounce

Avoiding waitForTimeout

Never use waitForTimeout to wait for UI or network — always wait for something specific (the debounce case above is the sole exception):

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

// GOOD - wait for toast indicating operation complete
await expect(page.getByText('Table created successfully')).toBeVisible({ timeout: 15000 })

Avoiding force: true on clicks

Instead of forcing clicks on hidden elements, make them visible first:

typescript
// BAD
await menuButton.click({ force: true })

// GOOD - hover to reveal, then click
await tableRow.hover()
await expect(menuButton).toBeVisible()
await menuButton.click()

Test Structure

Always import from the custom test utility:

ts
import { test } from '../utils/test.js'

Use withFileOnceSetup for expensive setup that should run once per file:

ts
test.beforeAll(async ({ browser, ref }) => {
  await withFileOnceSetup(import.meta.url, async () => {
    const ctx = await browser.newContext()
    const page = await ctx.newPage()
    await deleteTestTables(page, ref)
  })
})

test.afterAll(async () => {
  await releaseFileOnceCleanup(import.meta.url)
})

Dismiss toasts before interacting — they can overlay buttons:

ts
const dismissToastsIfAny = async (page: Page) => {
  const closeButtons = page.getByRole('button', { name: 'Close toast' })
  const count = await closeButtons.count()
  for (let i = 0; i < count; i++) {
    await closeButtons.nth(i).click()
  }
}

await dismissToastsIfAny(page)
await page.getByRole('button', { name: 'New table' }).click()

Assertions

Always include descriptive messages for easier debugging:

ts
// ❌ No context on failure
await expect(page.getByRole('button', { name: 'Save' })).toBeVisible()

// ✅ Clear message on failure
await expect(
  page.getByRole('button', { name: 'Save' }),
  'Save button should be visible after form is filled'
).toBeVisible()

Use explicit timeouts for slow operations:

ts
await expect(
  page.getByText(`Table ${tableName} is good to go!`),
  'Success toast should be visible after table creation'
).toBeVisible({ timeout: 50000 })

Helper Functions

Extract reusable operations into domain helpers (e.g. e2e/studio/utils/storage-helpers.ts). Use the existing wait utilities:

ts
import {
  createApiResponseWaiter,
  waitForApiResponse,
  waitForGridDataToLoad,
  waitForTableToLoad,
} from '../utils/wait-for-response.js'

Use expectClipboardValue instead of manual clipboard reads with hardcoded timeouts:

ts
// ❌ Brittle
await page.evaluate(() => navigator.clipboard.readText())
await page.waitForTimeout(500)

// ✅ Uses Playwright auto-retries
await expectClipboardValue({ page, value: 'expectedValue' })
Show full SKILL.md (280 more words)Show less

API Mocking

ts
await page.route('*/**/logs.all*', async (route) => {
  await route.fulfill({ body: JSON.stringify(mockAPILogs) })
})

Use soft waits for optional API calls:

ts
await waitForApiResponse(page, 'pg-meta', ref, 'optional-endpoint', {
  soft: true,
  fallbackWaitMs: 1000,
})

Cleanup

Clean up test data in beforeAll/beforeEach. Check before deleting to handle existing state gracefully:

ts
const bucketRow = page.getByRole('row').filter({ hasText: bucketName })
if ((await bucketRow.count()) === 0) return
// proceed with deletion

Reset local storage after tests that modify it:

ts
import { resetLocalStorage } from '../utils/reset-local-storage.js'

await resetLocalStorage(page, ref)

Debugging

View trace
bash
cd e2e/studio && pnpm exec playwright show-trace <path-to-trace.zip>
View HTML report
bash
cd e2e/studio && pnpm exec playwright show-report
Error context

Error context files are saved in the test-results/ directory.

Playwright MCP tools

Use Playwright MCP tools to inspect UI when debugging locally.

CI vs Local Development

The key difference is cold start vs warm state:

CI (cold start)

Tests run from a blank database slate. Each test run resets the database and starts fresh containers. Extensions like pg_cron are NOT enabled by default.

Local dev with pnpm dev:studio-local

When debugging with a running dev server, the database may already have state from previous runs (extensions enabled, test data present).

Handling Cold Start Bugs

Tests that work locally but fail in CI often have assumptions about existing state.

Common issues
  1. Extension not enabled (must enable in test setup)
  2. Race conditions when parallel tests try to modify shared state (use test.describe.configure({ mode: 'serial' }))
  3. Locators matching wrong elements because the page structure differs when state isn't set up
Reproducing CI behavior locally

The test framework automatically resets the database when running pnpm run e2e. This matches CI behavior.

If using pnpm dev:studio-local for Playwright MCP debugging, remember the state differs from CI.

Debugging Workflow for CI Failures

  1. First, run the test locally with pnpm run e2e -- features/<file>.spec.ts (cold start)
  2. Check error context in test-results/ directory
  3. If you need to inspect UI state, start pnpm dev:studio-local and use Playwright MCP tools
  4. Remember: what you see in the dev server may have state that doesn't exist in CI

© supabase, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/studio-e2e-tests of supabase/supabase.

Open the folder on GitHubat commit 26c838a

Compare with similar skills

Studio E2E Tests next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Studio E2E Tests compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Studio E2E Tests this skillsupabase/supabase111k—~2.8kAutomated safety check: PassApache-2.0
Hardening Flaky E2E TestsComfy-Org/ComfyUI_frontend2.1k—~2.8kAutomated safety check: PassGPL-3.0
Web Application Testinganthropics/skills180k51 repos~966Automated safety check: PassApache-2.0
playwright-cli Browser Automationgithub/gh-aw5.4k24 repos~2.8kAutomated safety check: PassMIT
Write and Verify Playwright Testsappsmithorg/appsmith41k—~2.9kAutomated safety check: NotesApache-2.0
Cucumber and Playwright E2E Testslanggenius/dify158k—~682Automated safety check: PassCustom licence

Similar skills

  • Hardening Flaky E2E Tests

    Comfy-Org/ComfyUI_frontend

    Diagnoses and fixes flaky Playwright e2e tests by replacing race-prone patterns with retry-safe alternatives.

    2.1k GitHub stars~2.8k tokensUpdated today
    Testing & QAAuto-check passed
  • Web Application Testing

    anthropics/skills

    Official

    Tests local web applications with Python Playwright scripts, checking frontend behavior, capturing screenshots and reading browser console logs.

    180k GitHub starsUsed in 51 repos~966 tokens
    Testing & QAAuto-check passed
  • Official

    Drives a real browser from the command line with playwright-cli to open pages, interact, mock requests, save state and work with Playwright tests.

    5.4k GitHub starsUsed in 24 repos~2.8k tokens
    Testing & QAAuto-check passed
  • Writes a Playwright end-to-end test from a prompt, runs it against a live Appsmith deployment and retries with fixes up to three times until it passes.

    41k GitHub stars~2.9k tokensUpdated today
    Testing & QAAuto-check: notes
  • Guides changes and reviews of the Cucumber and Playwright end-to-end suite under `e2e/`: feature files, step definitions, support code, tags, locators and assertions.

    158k GitHub stars~682 tokensUpdated today
    Testing & QAAuto-check passed
  • E2E Testing

    langflow-ai/langflow

    Write and review Playwright E2E tests for Langflow. An agent skill from langflow-ai/langflow.

    156k GitHub stars~3.3k tokensUpdated today
    Testing & QAAuto-check passed

More from supabase/supabase

All 22 skills in this repo
  • Official

    React composition patterns that scale. An agent skill from supabase/supabase.

    111k GitHub starsUsed in 59 repos~726 tokens
    Auto-check passed
  • Clickhouse Logs Queries

    supabase/supabase

    Official

    Write, review, and migrate Supabase logs queries against the ClickHouse-backed logs table (the logs.all.otel analytics endpoint).

    111k GitHub stars~2.4k tokensUpdated today
    Auto-check passed
  • Review The Docs

    supabase/supabase

    Official

    Review Supabase docs changes locally in your supabase/supabase checkout — either an open PR (triage, classify, verify) or your own branch before opening a PR (local self-review).

    111k GitHub stars~4.6k tokensUpdated today
    Auto-check passed
  • Vitest

    supabase/supabase

    Official

    Vitest API and config reference (Jest-compatible) — mocking with vi., spies, fake timers, coverage configuration, fixtures, snapshots, and test filtering.

    111k GitHub starsUsed in 12 repos~1.1k tokens
    Auto-check passed
  • Safe SQL Execution

    supabase/supabase

    Official

    A skill your agent uses whenever code will build, return, fetch, or execute SQL that runs against a user's real Postgres database — even when the request reads like an ordinary feature or bug fix…

    111k GitHub stars~4.2k tokensUpdated today
    Auto-check passed
  • Studio Error Handling

    supabase/supabase

    Official

    Error display and troubleshooting pattern for Supabase Studio.

    111k GitHub stars~1.3k tokensUpdated today
    Auto-check passed

Categories

Questions about Studio E2E Tests

What does Studio E2E Tests do?

Write and run Playwright E2E tests for Supabase Studio (e2e/studio). Studio E2E Tests is an agent skill from supabase/supabase, published by the product's own GitHub organization. Write and run Playwright E2E tests for Supabase Studio (e2e/studio).

When should I use Studio E2E Tests?

Studio E2E Tests fits situations like: asked to run e2e tests; write new E2E tests; failing Playwright tests.

How do I install Studio E2E Tests in Claude Code?

Run `npx skills add supabase/supabase --skill studio-e2e-tests -a claude-code`. Or copy the skill folder (.agents/skills/studio-e2e-tests in supabase/supabase) into .claude/skills/studio-e2e-tests in your project. Claude Code loads it when a task matches its description.

How do I install Studio E2E Tests in Codex?

Run `npx skills add supabase/supabase --skill studio-e2e-tests -a codex`. Or copy the skill folder (.agents/skills/studio-e2e-tests in supabase/supabase) into .agents/skills/studio-e2e-tests in your project. Codex loads it when a task matches its description.

Can I use Studio E2E Tests in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add supabase/supabase --skill studio-e2e-tests -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/studio-e2e-tests, .gemini/skills/studio-e2e-tests, .github/skills/studio-e2e-tests and .opencode/skills/studio-e2e-tests in your project.

What does Studio E2E Tests need to run?

Going by SKILL.md and its folder, Studio E2E Tests needs the command-line tools its instructions call (pnpm).

Does Studio E2E Tests access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Studio E2E Tests safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Studio E2E Tests use?

Studio E2E Tests is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Studio E2E Tests use?

About 2.8k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Studio E2E Tests?

Skills that share tags, products or a category with Studio E2E Tests: Hardening Flaky E2E Tests (Comfy-Org/ComfyUI_frontend, 2.1k stars), Web Application Testing (anthropics/skills, 180k stars), playwright-cli Browser Automation (github/gh-aw, 5.4k stars) and Write and Verify Playwright Tests (appsmithorg/appsmith, 41k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Studio E2E Tests?

supabase (a GitHub organization, an official publisher) maintains it in supabase/supabase, which has 111,222 GitHub stars. The repository holds 22 skills in this directory. The repository was last updated on October 8, 2026.

Source: supabase/supabase on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.