Skip to content
Development
Skill

/playground-msw-tests

REQUIRED and PRIMARY testing approach for packages/playground and packages/playground-ui. Triggers on: adding or modifying hooks, pages, route components, data-fetching code, React Query interactions, or any test work in these packages. Generates Vitest tests that drive the real

From plugin
mastra
30k33 skills14 commands

Claude Code

$ npx -y skills add mastra-ai/mastra --skill playground-msw-tests --agent claude-code

SKILL.md

playground-msw-tests.SKILL.md
name: playground-msw-tests
description: >
  REQUIRED and PRIMARY testing approach for packages/playground and packages/playground-ui.
  Triggers on: adding or modifying hooks, pages, route components, data-fetching code,
  React Query interactions, or any test work in these packages. Generates Vitest tests
  that drive the real @mastra/client-js + React Query stack through MSW handlers and
  typed fixtures derived from @mastra/client-js response types. This is the #1 way to
  test the playground packages — ABOVE Playwright E2E. Use Playwright only for
  cross-page user journeys that MSW cannot model.

MSW + client-js Fixtures: Primary Testing Strategy

Core Principle

**Drive the real transport, mock the network.**

Tests in `packages/playground` and `packages/playground-ui` MUST be written as Vitest tests that exercise the real `@mastra/client-js` SDK, the real React Query cache, and the real component/hook code paths. The only seam we mock is the network boundary, via [MSW](https://mswjs.io/).

This catches contract drift between the playground and `@mastra/client-js` at typecheck time and at test time — something `vi.mock('@/hooks/...')` style tests cannot do.

Priority Order

When you write or refactor a test for these packages, choose in this order:

1. **MSW + typed client-js fixtures (THIS SKILL)** — for hooks, pages, routes, data-fetching, gating, redirect logic, query/mutation flows, error paths. 2. **Playwright E2E** (`e2e-tests-studio` skill) — only for genuine cross-page user journeys, real browser concerns (focus/keyboard/viewport), or anything that requires a real running Mastra server. 3. **Pure unit tests** — only for self-contained utilities/services with no network, no React Query, no router involvement.

If the same behavior can be covered by both #1 and #2, **prefer #1**. MSW tests are faster, deterministic, run in CI without browsers, and assert the real wire contract.

What NOT to do

  • ❌ `vi.mock('@/domains/.../hooks/use-agents')` — mocking our own hooks hides

cache, gating and transport bugs.

  • ❌ Implementation-mirror tests — do not duplicate source class strings,

branch logic, generated shapes, or calculations without asserting a real behavior or regression.

  • ❌ Class-name-only visual tests — `expect(node.className).toContain(...)`

usually just tests that the implementation string exists. Prefer no test over a className duplication test; use computed style, user-visible behavior, or a browser/Storybook check unless the class string itself is the public API.

  • ❌ Inline TypeScript types in tests (`type AgentLite = { id: string }`) —

these drift silently from the real SDK.

  • ❌ `as any` / `as unknown as ListAgentsResponse` on fixture data, MSW

responses, request payloads, hook inputs, or component event inputs.

  • ❌ Returning bespoke shapes from MSW handlers that don't match the real

`@mastra/client-js` response. If a field is optional, include it as optional in the fixture, don't omit the type.

What TO do

  • ✅ Put fixtures in a `__tests__/fixtures/` folder next to the test file.
  • ✅ Type every fixture with a response type re-exported from `@mastra/client-js`

(e.g. `ListStoredAgentsResponse`, `GetAgentResponse`, `BuilderSettingsResponse`, `GetToolResponse`, `GetWorkflowResponse`, `ListStoredSkillsResponse`).

  • ✅ Use direct imports and inferred types from real SDK, hook, component, DOM,

or Testing Library APIs for MSW payloads, request payloads, hook inputs, and component events.

  • ✅ Register MSW handlers per test with `server.use(...)` so handlers reset

between tests via the global `afterEach`.

  • ✅ Render through `MastraReactProvider` + `QueryClientProvider` + `MemoryRouter`

so the real client SDK is the transport.

  • ✅ Use `vi.fn()` wrappers inside MSW handlers to assert which endpoints were

hit (great for testing `enabled: ...` gating without mocking hooks).

Standard Test Skeleton

// @vitest-environment jsdom
import { MastraReactProvider } from '@mastra/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { cleanup, render, screen } from '@testing-library/react';
import { http, HttpResponse } from 'msw';
import { MemoryRouter } from 'react-router';
import { afterEach, describe, expect, it } from 'vitest';

import { server } from '@/test/msw-server';
import { Subject } from '../subject';
import { happyPathResponse } from './fixtures/subject';

const BASE_URL = 'http://localhost:4111';

const renderSubject = () => {
  const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  return render(
    <MastraReactProvider baseUrl={BASE_URL}>
      <QueryClientProvider client={queryClient}>
        <MemoryRouter>
          <Subject />
        </MemoryRouter>
      </QueryClientProvider>
    </MastraReactProvider>,
  );
};

afterEach(() => cleanup());

describe('Subject', () => {
  it('renders the happy path', async () => {
    server.use(http.get(`${BASE_URL}/api/agents`, () => HttpResponse.json(happyPathResponse)));

    renderSubject();

    expect(await screen.findByText('Expected behavior')).not.toBeNull();
  });
});

Standard Fixture File

// packages/playground/src/.../__tests__/fixtures/subject.ts
import type { ListStoredAgentsResponse } from '@mastra/client-js';

export const emptyStoredAgents: ListStoredAgentsResponse = {
  agents: [],
  total: 0,
  page: 1,
  perPage: 50,
  hasMore: false,
};

export const oneDraftAgent: ListStoredAgentsResponse = {
  ...emptyStoredAgents,
  agents: [
    {
      id: 'agent-1',
      name: 'Draft Agent',
      instructions: '',
      model: { provider: 'openai', name: 'gpt-4o-mini' },
      status: 'draft',
      // ...other required fields from StoredAgentResponse
    },
  ],
  total: 1,
};

**If a required field on the SDK response type is missing from your fixture, that's a real test failure — fix the fixture, never `as any` it.** The same applies to hook inputs, compo

Read more
@mastra-ai
Ships withmastra

Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack. It includes everything you need to go from early prototypes to production-ready applications.

Stars on GitHub

Momentum

stars in total
29.5k
Star history of mastra-ai/mastra on GitHub, a chart by star-history.com

Other skills on mastra.

builder-smoke-test

builder-smoke-test

Smoke test the Agent Builder feature branch end-to-end against a hermetic project scaffolded by the skill (linked to the current…

@mastra-ai@mastra-aiInstall Skill
debugging-difficult-bugs

debugging-difficult-bu…

Use early when debugging a medium or hard bug, especially when tests alone may not reveal the real runtime failure. Trigger this…

@mastra-ai@mastra-aiInstall Skill
docs-audit

docs-audit

Autonomous, report-only documentation review for Mastra docs. Use when auditing changed docs against source, validating…

@mastra-ai@mastra-aiInstall Skill
docs-diagrams

docs-diagrams

Convert existing docs diagram images to Mermaid, and author new Mermaid diagrams for Mastra docs. Use when replacing an…

@mastra-ai@mastra-aiInstall Skill
e2e-tests-studio

e2e-tests-studio

REQUIRED when modifying any file in packages/playground-ui or packages/playground. Triggers on: React component…

@mastra-ai@mastra-aiInstall Skill
label-core-bugs

label-core-bugs

Review open mastra-ai/mastra GitHub issues, identify direct @mastra/core bugs, and apply the @mastra/core label. Use when…

@mastra-ai@mastra-aiInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about playground-msw-tests.

Which coding agents can use playground-msw-tests?
playground-msw-tests installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.