Official agent skill

Studio Mock API Tests

by supabase in supabase/supabase

Component tests for Supabase Studio that mock API requests at the network layer with MSW.

OfficialApache-2.0Auto-check passedTesting & QA

Install Studio Mock API Tests

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

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

GitHub CLI
$ gh skill install supabase/supabase studio-mock-api-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-mock-api-tests .claude/skills/studio-mock-api-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-mock-api-tests
GitHub stars
111k
Token cost
~3k tokens
SKILL.md length
928 words
Files
1
Skills in repo
22
Repo updated
First seen
Licence
Apache-2.0

At a glance

Component tests for Supabase Studio that mock API requests at the network layer with MSW.

  • Works in 8 steps: Path params use :slug, not {slug} → Use HttpResponse.json, not new… → Submit buttons in Sheets/Modals need… → …
  • Reviewing a component test that exercises a React Query hook
  • SKILL.md covers When to use, The template, Gotchas that will eat your… and Prefer asserting on UI state, plus 4 more sections
  • Needs API_KEY

What it does

Studio Mock API Tests is an agent skill from supabase/supabase, published by the product's own GitHub organization. Component tests for Supabase Studio that mock API requests at the network layer with MSW. Use when writing or reviewing a component test that exercises a React Query hook or mutation, or when migrating an existing test away from vi.mock('@/data/...'). Covers the customRender + addAPIMock template and the jsdom/MSW gotchas that cost real debugging time.

Its SKILL.md is about 3k 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 API testing. It works with Supabase, TanStack and OpenAPI. 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

  • Reviewing a component test that exercises a React Query hook
  • Migrating an existing test away from vi.mock(@/data/...)

Example prompts

  • “@/data/...”
  • “/studio-mock-api-tests”

Requirements

  • A credential in API_KEY

Workflow steps

8 steps, taken from the step headings in SKILL.md.

  1. Path params use :slug, not {slug}
  2. Use HttpResponse.json, not new HttpResponse
  3. Submit buttons in Sheets/Modals need fireEvent.click
  4. Profile-gated queries need a profileContext
  5. useParams is globally mocked to { ref: 'default' }
  6. Unhandled requests fail loudly — mock every endpoint a render triggers
  7. Don't put query strings in the handler path
  8. Always pass an explicit generic to HttpResponse.json

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

    No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).

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

  • Network

    Links to these hosts (documentation or services it may open):

    • mswjs.io
    • tkdodo.eu

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

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • API_KEY

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

Context cost

Studio Mock API Tests loads about 3k tokens when it runs. Until then it costs about 94 tokens; SKILL.md has 928 words of instructions outside code blocks.

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

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). 928 words, ~3,032 tokens.

Download SKILL.mdSave it as .claude/skills/studio-mock-api-tests/SKILL.md (or your agent's skills folder).
name
studio-mock-api-tests
description
Component tests for Supabase Studio that mock API requests at the network layer with MSW. Use when writing or reviewing a component test that exercises a React Query hook or mutation, or when migrating an existing test away from vi.mock('@/data/...'). Covers the customRender + addAPIMock template and the jsdom/MSW gotchas that cost real debugging time.

Studio MSW component tests

Mount a Studio component, intercept its network calls with MSW, assert what renders and what gets sent. The infrastructure is already wired up — this skill is the working template plus the gotchas.

When to use

  • The component (or any descendant it renders) calls a React Query hook or mutation that hits /platform/..., /v1/..., or another endpoint in apps/studio/data/api.d.ts.
  • You'd otherwise be tempted to write vi.mock('@/data/some-query', ...). Don't. Mock the network instead — see "Why not vi.mock" below.

If the component is purely presentational with no data fetching, you don't need MSW; render and assert directly.

The template

tsx
import { screen } from '@testing-library/react'
import { platformComponents as components } from 'api-types'
import { mockAnimationsApi } from 'jsdom-testing-mocks'
import { HttpResponse } from 'msw'
import { describe, expect, test } from 'vitest'

import { MyComponent } from './MyComponent'
import { customRender } from '@/tests/lib/custom-render'
import { addAPIMock } from '@/tests/lib/msw'

type OrganizationResponse = components['schemas']['OrganizationResponse']

// Needed if the component renders inside a Sheet, Modal, Popover, or
// anything else built on Radix that uses Web Animations.
mockAnimationsApi()

describe('MyComponent', () => {
  test('renders rows from the API', async () => {
    addAPIMock({
      method: 'get',
      path: '/platform/organizations',
      response: () =>
        HttpResponse.json<OrganizationResponse[]>([
          {
            /* ... */
          },
        ]),
    })

    customRender(<MyComponent />)

    expect(await screen.findByText('Acme')).toBeInTheDocument()
  })
})

That's the whole pattern (add fireEvent, waitFor, or userEvent as the interactions need them — see the gotchas below). Server lifecycle (listen/resetHandlers/ close) is handled by apps/studio/tests/vitestSetup.ts — handlers registered via addAPIMock are scoped to the current test.

Gotchas that will eat your afternoon

1. Path params use :slug, not {slug}

addAPIMock is typed from the OpenAPI paths, but path params are remapped to MSW's :param format. Autocomplete will guide you, but if typecheck reports the path isn't assignable, you're using the OpenAPI {slug} form.

ts
// ❌ TypeScript error, MSW won't match
path: '/platform/organizations/{slug}/projects'

// ✅ Correct
path: '/platform/organizations/:slug/projects'
2. Use HttpResponse.json, not new HttpResponse

For success responses, always go through HttpResponse.json — even for 204/201-no-content endpoints. A raw new HttpResponse(null, { status: 201 }) returns no content-type, and openapi-fetch can hang the mutation flow, which silently breaks onSuccess callbacks.

ts
// ❌ Mutation onSuccess silently never fires
response: () => new HttpResponse(null, { status: 201 })

// ✅ Works (pass the OpenAPI body shape explicitly — see gotcha #8)
response: () => HttpResponse.json<MyResponse>({}, { status: 201 })
3. Submit buttons in Sheets/Modals need fireEvent.click

The convention <Button form={FORM_ID} type="submit" /> (button outside the form, associated by id) doesn't reliably trigger submission under userEvent.click in jsdom. Use fireEvent.click for the submit button. Continue to use userEvent.type for inputs.

ts
await userEvent.type(screen.getByPlaceholderText('value'), 'hello')
fireEvent.click(await screen.findByRole('button', { name: 'Save' }))
4. Profile-gated queries need a profileContext

Many hooks (useOrganizationsQuery, anything in data/projects/, anything that calls useProfile) refuse to fire until a profile is loaded. Pass one explicitly:

ts
import type { ProfileContextType } from '@/lib/profile'

const PROFILE_CONTEXT: ProfileContextType = {
  profile: {
    id: 1,
    auth0_id: 'auth0|test',
    gotrue_id: 'gotrue-test',
    username: 'testuser',
    primary_email: 'test@example.com',
    first_name: null,
    last_name: null,
    mobile: null,
    is_alpha_user: false,
    is_sso_user: false,
    disabled_features: [],
    free_project_limit: null,
  },
  error: null,
  isLoading: false,
  isError: false,
  isSuccess: true,
}

customRender(<MyComponent />, { profileContext: PROFILE_CONTEXT })
5. useParams is globally mocked to { ref: 'default' }

You don't need to mock the Next router for project-scoped components. Just use 'default' as the project ref in your mock paths: /v1/projects/default/secrets, /platform/projects/default/.... If you need a different ref, override with routerMock.setCurrentUrl(...) (see apps/studio/tests/lib/route-mock.ts).

6. Unhandled requests fail loudly — mock every endpoint a render triggers

mswServer.listen({ onUnhandledRequest: 'error' }) is set globally. If a component (or any child it renders) fires an unmocked request, you'll see MSW errors in stderr and likely flaky behavior. Cards, lists, and details panels often fire nested queries (e.g. OrganizationCard calls useOrgProjectsInfiniteQuery) — read what the rendered subtree does and mock all of it, or stub it with vi.mock for nested components only.

7. Don't put query strings in the handler path

addAPIMock accepts ?foo=bar suffixes via TrimQueryParams, but the helper strips them before matching. MSW v2 doesn't match query params via path strings — read them inside the resolver instead:

ts
addAPIMock({
  method: 'get',
  path: '/platform/projects',
  response: ({ request }) => {
    const limit = new URL(request.url).searchParams.get('limit')
    // ...
  },
})
8. Always pass an explicit generic to HttpResponse.json

addAPIMock's resolver is typed against the OpenAPI success body (and the standard { message: string } error envelope, exported as APIErrorBody). But MSW's HttpResponse.json uses NoInfer, so the body type doesn't narrow from context. Pass the expected shape explicitly — it doubles as a self-documenting contract assertion:

ts
import { addAPIMock, type APIErrorBody } from '@/tests/lib/msw'

response: () => HttpResponse.json<OrganizationResponse[]>([...])
response: () =>
  HttpResponse.json<APIErrorBody>({ message: 'Boom' }, { status: 500 })

A mock that drifts from the contract (wrong envelope, missing fields, stale enum values) now fails at compile time, not at runtime. The cost is one type annotation per resolver — well worth it.

For mocks at the network boundary, also prefer createMockOrganizationResponse (returns the raw OpenAPI OrganizationResponse) over createMockOrganization (which extends with frontend-derived managed_by / partner_id that the query layer attaches). Same pattern applies to any type that's a frontend extension of an OpenAPI schema: build a createMockXResponse helper that returns the raw API shape.

Show full SKILL.md (354 more words)Show less

Prefer asserting on UI state

MSW's own best-practices doc explicitly recommends asserting on what renders, not on whether a handler was called. The "did the form submit?" question is best answered by expect(onClose).toHaveBeenCalled() or by findByText('Saved') — not by spying on the resolver.

There's one legitimate exception: the request body itself is the contract you care about, and the server's reply doesn't reflect it back. Bulk-create endpoints (like POST /v1/projects/:ref/secrets) are the canonical case — 201 with no body, so the only way to verify the shape sent is to capture it:

ts
const requests: Array<{ ref: string | undefined; body: unknown }> = []
addAPIMock({
  method: 'post',
  path: '/v1/projects/:ref/secrets',
  response: async ({ request, params }) => {
    requests.push({ ref: params.ref as string | undefined, body: await request.json() })
    return HttpResponse.json<CreateSecretsResponse>({}, { status: 201 })
  },
})

// ... drive the UI ...

expect(requests).toEqual([{ ref: 'default', body: [{ name: 'API_KEY', value: 'new-value' }] }])

When in doubt, assert on the UI first; reach for request capture only when the UI doesn't observably encode the contract.

Debugging an MSW test

If a request isn't being matched, wire up MSW's lifecycle events at the top of the test file (or temporarily in msw.ts):

ts
import { mswServer } from '@/tests/lib/msw'

mswServer.events.on('request:unhandled', ({ request }) => {
  console.log('[MSW] UNHANDLED:', request.method, request.url)
})
mswServer.events.on('response:mocked', ({ request, response }) => {
  console.log('[MSW] MATCHED:', request.method, request.url, response.status)
})

request:start is already wired in msw.ts. Add request:unhandled and response:mocked locally when a test misbehaves — usually surfaces a path-param mismatch or a nested query you forgot to mock.

Why not vi.mock('@/data/...')

It bypasses the network boundary, so:

  • It hides real bugs: a renamed query key or a changed request payload passes the test, then breaks in production.
  • It doesn't exercise React Query's caching, retry, or invalidation paths — onMutate, onSuccess, and onError callbacks won't run as they do in real life. (tkdodo.eu/blog/testing-react-query)
  • It drifts independently from the OpenAPI types — handlers stay in sync, module-level mocks don't.

Reach for vi.mock only for non-network concerns: a heavy child component (e.g. a Monaco editor) you want to stub, or a common-package hook with global state.

Further reading

Codebase references

WhatWhere
Query-only example (loading, error, success)apps/studio/components/interfaces/Organization/OrgNotFound.test.tsx
Mutation example (form, payload assertion)apps/studio/components/interfaces/Functions/EdgeFunctionSecrets/EditSecretSheet.test.tsx
SQL-via-pg-meta example (POST resolver branch on query body)apps/studio/components/interfaces/Integrations/Vault/Secrets/__tests__/EditSecretModal.test.tsx
addAPIMock sourceapps/studio/tests/lib/msw.ts
customRender sourceapps/studio/tests/lib/custom-render.tsx
Global handlers + lifecycleapps/studio/tests/lib/msw-global-api-mocks.ts, apps/studio/tests/vitestSetup.ts
Related skillsstudio-testing (when to write a component test at all), studio-queries (hook conventions), vitest

© 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-mock-api-tests of supabase/supabase.

Open the folder on GitHubat commit 26c838a

Compare with similar skills

Studio Mock API 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 Mock API Tests compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Studio Mock API Tests this skillsupabase/supabase111k—~3kAutomated safety check: PassApache-2.0
Type Safetyidavidov13/agentic-playwright223—~3.5kAutomated safety check: PassMIT
API Testingpetrkindlmann/qa-skills165—~2.7kAutomated safety check: PassMIT
Automating API Testingjeremylongshore/tons-of-skills-marketplace2.8k—~1.7kAutomated safety check: PassMIT
Use Yaakmountain-loop/yaak19k—~1.9kAutomated safety check: PassMIT
API Testingidavidov13/agentic-playwright223—~5.7kAutomated safety check: PassMIT

Similar skills

  • Type Safety

    idavidov13/agentic-playwright

    TypeScript type safety conventions for the Playwright scaffold — the "no any" rule, Zod 4 schema patterns (z.strictObject, top-level validators like z.uuid / z.email / z.url / z.int / z.enum)…

    223 GitHub stars~3.5k tokensUpdated 7 days ago
    Testing & QAAuto-check passed
  • API Testing

    petrkindlmann/qa-skills

    Test REST and GraphQL APIs with Playwright APIRequestContext, Supertest, or standalone HTTP clients.

    165 GitHub stars~2.7k tokensUpdated 3 mo ago
    Testing & QAAuto-check passed
  • Automating API Testing

    jeremylongshore/tons-of-skills-marketplace

    Test automate API endpoint testing including request generation, validation, and comprehensive test coverage for REST and GraphQL APIs.

    2.8k GitHub stars~1.7k tokensUpdated today
    Testing & QAAuto-check passed
  • Use Yaak

    mountain-loop/yaak

    A skill your agent uses when the user mentions Yaak, a Yaak workspace, or the yaak command, or asks to call, hit, or smoke test HTTP/REST endpoints, save or organize API requests for reuse or manual…

    19k GitHub stars~1.9k tokensUpdated yesterday
    Backend & APIsAuto-check passed
  • API Testing

    idavidov13/agentic-playwright

    API testing patterns for Playwright -- apiRequest fixture usage, Zod response schema creation and validation, test.step wrapping for multi-call tests, per-field negative/validation testing, path…

    223 GitHub stars~5.7k tokensUpdated 7 days ago
    Testing & QAAuto-check passed
  • API Test Suite Builder

    borghei/Claude-Skills

    Generate API test suites from route definitions across frameworks: auth, input validation, contract, k6 load testing, mocking, and OpenAPI-driven generation.

    881 GitHub stars~1.6k tokensUpdated yesterday
    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 E2E Tests

    supabase/supabase

    Official

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

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

Questions about Studio Mock API Tests

What does Studio Mock API Tests do?

Component tests for Supabase Studio that mock API requests at the network layer with MSW. Studio Mock API Tests is an agent skill from supabase/supabase, published by the product's own GitHub organization. Component tests for Supabase Studio that mock API requests at the network layer with MSW.

When should I use Studio Mock API Tests?

Studio Mock API Tests fits situations like: reviewing a component test that exercises a React Query hook; migrating an existing test away from vi.mock(@/data/...).

How do I install Studio Mock API Tests in Claude Code?

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

How do I install Studio Mock API Tests in Codex?

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

Can I use Studio Mock API 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-mock-api-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-mock-api-tests, .gemini/skills/studio-mock-api-tests, .github/skills/studio-mock-api-tests and .opencode/skills/studio-mock-api-tests in your project.

What does Studio Mock API Tests need to run?

Going by SKILL.md and its folder, Studio Mock API Tests needs credentials named API_KEY. Our summary lists: A credential in API_KEY.

Does Studio Mock API Tests access the network?

SKILL.md names 2 domains. As links in the text: mswjs.io and tkdodo.eu. This is read from the text; nothing was executed.

Is Studio Mock API 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 Mock API Tests use?

Studio Mock API 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 Mock API Tests use?

About 3k tokens (SKILL.md is roughly 12k 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 Mock API Tests?

Skills that share tags, products or a category with Studio Mock API Tests: Type Safety (idavidov13/agentic-playwright, 223 stars), API Testing (petrkindlmann/qa-skills, 165 stars), Automating API Testing (jeremylongshore/tons-of-skills-marketplace, 2.8k stars) and Use Yaak (mountain-loop/yaak, 19k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Studio Mock API 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.