/e2e-tests-studio
REQUIRED when modifying any file in packages/playground-ui or packages/playground. Triggers on: React component creation/modification/refactoring, UI changes, new playground features, bug fixes affecting studio UI. Generates Playwright E2E tests that validate PRODUCT BEHAVIOR,
$ npx -y skills add mastra-ai/mastra --skill e2e-tests-studio --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/e2e-tests-studio
Context preview
The summary Claude sees to decide when to auto-load this skill.
REQUIRED when modifying any file in packages/playground-ui or packages/playground. Triggers on: React component creation/modification/refactoring, UI changes, new playground features, bug fixes affecting studio UI. Generates Playwright E2E tests that validate PRODUCT BEHAVIOR,
SKILL.md
e2e-tests-studio.SKILL.mdname: e2e-tests-studio
description: >
REQUIRED when modifying any file in packages/playground-ui or packages/playground.
Triggers on: React component creation/modification/refactoring, UI changes,
new playground features, bug fixes affecting studio UI. Generates Playwright E2E tests
that validate PRODUCT BEHAVIOR, not just UI states.
model: claude-opus-4-5
E2E Behavior Validation for Frontend Modifications
Core Principle: Test Product Behavior, Not UI States
**CRITICAL**: Tests must verify that product features WORK correctly, not just that UI elements render.
What NOT to test (UI States):
- ❌ "Dropdown opens when clicked"
- ❌ "Modal appears after button click"
- ❌ "Loading spinner shows during request"
- ❌ "Form fields are visible"
- ❌ "Sidebar collapses"
What TO test (Product Behavior):
- ✅ "Selecting an LLM provider configures the agent to use that provider"
- ✅ "Creating a new agent persists it and shows in the agents list"
- ✅ "Running a tool with parameters returns the expected output"
- ✅ "Chat messages stream correctly and maintain conversation context"
- ✅ "Workflow execution triggers tools in the correct order"
BDD Structure (REQUIRED)
**Every E2E spec MUST follow the same BDD shape as the MSW tests.** In `packages/playground`, `e2e-bdd/test-needs-when-describe` enforces this shape.
The structure has exactly three levels:
1. **Outer `test.describe`** = the unit under test (one page or feature per file). 2. **Inner `test.describe('when …')`** = exactly ONE precondition. The title MUST start with `when`. 3. **Each `test`** = exactly ONE observable outcome.
import { test, expect } from '@playwright/test';
import { resetStorage } from '../__utils__/reset-storage';
test.describe('Tools list page', () => {
// the unit
test.afterEach(async () => {
await resetStorage();
});
test.describe('when a registered tool is clicked', () => {
// ONE precondition (starts with "when")
test('navigates to that tool detail page', async ({ page }) => {
// ONE outcome
await page.goto('/tools');
await page.locator('text=Get current weather for a location').click();
await expect(page).toHaveURL(/\/tools\/weatherInfo$/);
});
test('shows the tool name as the page heading', async ({ page }) => {
// ONE outcome
await page.goto('/tools');
await page.locator('text=Get current weather for a location').click();
await expect(page.locator('h2')).toHaveText('weatherInfo');
});
});
});Rules:
- One outer `test.describe` per file naming the unit.
- Every leaf `test` lives inside a `test.describe('when …')` precondition group. **No top-level flat `test()`.**
- Split a multi-assertion `test()` only where assertions represent **distinct outcomes**; keep tightly-coupled assertions that prove a single outcome together. Never drop an assertion.
- Place `beforeEach`/`afterEach` in the narrowest `describe` scope that needs them.
Prerequisites
Requires Playwright MCP server. If the `browser_navigate` tool is unavailable, instruct the user to add it:
claude mcp add playwright -- npx @playwright/mcp@latest
Step 1: Understand the Feature Intent
Before writing ANY test, answer these questions:
1. **What user problem does this feature solve?** 2. **What is the expected outcome when the feature works correctly?** 3. **What data flows through the system?** (user input → API → state → UI) 4. **What should persist after page reload?** 5. **What downstream effects should this action have?**
Document these answers as comments in your test file.
Step 2: Build and Start
pnpm build:cli
cd packages/playground/e2e/kitchen-sink && pnpm dev
Verify server at http://localhost:4111
Step 3: Map Feature to Behavior Tests
Feature-to-Test Mapping Guide
| Feature Category | What to Test | Example Assertion | | -------------------------- | ------------------------------------------------- | ------------------------------------------------------------ | | **Agent Configuration** | Config changes affect agent behavior | Send message → verify response uses selected model | | **LLM Provider Selection** | Selected provider is used in requests | Intercept API call → verify provider in request payload | | **Tool Execution** | Tool runs with correct params & returns result | Execute tool → verify output matches expected transformation | | **Workflow Execution** | Steps execute in order, data flows between steps | Run workflow → verify each step's output feeds next step | | **Chat/Streaming** | Messages persist, context maintained across turns | Multi-turn conversation → verify context awareness | | **MCP Server Tools** | Server tools are callable and return data | Call MCP tool → verify response structure and content | | **Memory/Persistence** | Data survives page reload | Create item → reload → verify item exists | | **Error Handling** | Errors surface correctly to user | Trigger error condition → verify error message + recovery |
Step 4: Write Behavior-Focused Tests
Test Structure Template
import { test, expect, Page } from '@playwright/test';
import { resetStorage } from '../__utils__/reset-storage';
import { selectFixture } from '../__utils__/select-fixture';
import { nanoid } from 'nanoid';
/**
* FEATURE: [Name of feature]
* USER STORY: As a user, I want to [action] so that [outcome]
* BEHAVIOR UNDER TEST: [Specific behavior being validated]
*/
test.describe('[Feature Name] - Behavior Tests', () => {
let page: Page;
test.beforeEach(async ({ browser }) => {
const context = await browser.newContext();
page = await context.newPage();
});
test.afterEach(async () => {
aRead more
name: e2e-tests-studio description: > REQUIRED when modifying any file in packages/playground-ui or packages/playground. Triggers on: React component creation/modification/refactoring, UI changes, new playground features, bug fixes affecting studio UI. Generates Playwright E2E tests that validate PRODUCT BEHAVIOR, not just UI states. model: claude-opus-4-5
E2E Behavior Validation for Frontend Modifications
Core Principle: Test Product Behavior, Not UI States
**CRITICAL**: Tests must verify that product features WORK correctly, not just that UI elements render.
What NOT to test (UI States):
- ❌ "Dropdown opens when clicked"
- ❌ "Modal appears after button click"
- ❌ "Loading spinner shows during request"
- ❌ "Form fields are visible"
- ❌ "Sidebar collapses"
What TO test (Product Behavior):
- ✅ "Selecting an LLM provider configures the agent to use that provider"
- ✅ "Creating a new agent persists it and shows in the agents list"
- ✅ "Running a tool with parameters returns the expected output"
- ✅ "Chat messages stream correctly and maintain conversation context"
- ✅ "Workflow execution triggers tools in the correct order"
BDD Structure (REQUIRED)
**Every E2E spec MUST follow the same BDD shape as the MSW tests.** In `packages/playground`, `e2e-bdd/test-needs-when-describe` enforces this shape.
The structure has exactly three levels:
1. **Outer `test.describe`** = the unit under test (one page or feature per file). 2. **Inner `test.describe('when …')`** = exactly ONE precondition. The title MUST start with `when`. 3. **Each `test`** = exactly ONE observable outcome.
import { test, expect } from '@playwright/test';
import { resetStorage } from '../__utils__/reset-storage';
test.describe('Tools list page', () => {
// the unit
test.afterEach(async () => {
await resetStorage();
});
test.describe('when a registered tool is clicked', () => {
// ONE precondition (starts with "when")
test('navigates to that tool detail page', async ({ page }) => {
// ONE outcome
await page.goto('/tools');
await page.locator('text=Get current weather for a location').click();
await expect(page).toHaveURL(/\/tools\/weatherInfo$/);
});
test('shows the tool name as the page heading', async ({ page }) => {
// ONE outcome
await page.goto('/tools');
await page.locator('text=Get current weather for a location').click();
await expect(page.locator('h2')).toHaveText('weatherInfo');
});
});
});Rules:
- One outer `test.describe` per file naming the unit.
- Every leaf `test` lives inside a `test.describe('when …')` precondition group. **No top-level flat `test()`.**
- Split a multi-assertion `test()` only where assertions represent **distinct outcomes**; keep tightly-coupled assertions that prove a single outcome together. Never drop an assertion.
- Place `beforeEach`/`afterEach` in the narrowest `describe` scope that needs them.
Prerequisites
Requires Playwright MCP server. If the `browser_navigate` tool is unavailable, instruct the user to add it:
claude mcp add playwright -- npx @playwright/mcp@latest
Step 1: Understand the Feature Intent
Before writing ANY test, answer these questions:
1. **What user problem does this feature solve?** 2. **What is the expected outcome when the feature works correctly?** 3. **What data flows through the system?** (user input → API → state → UI) 4. **What should persist after page reload?** 5. **What downstream effects should this action have?**
Document these answers as comments in your test file.
Step 2: Build and Start
pnpm build:cli cd packages/playground/e2e/kitchen-sink && pnpm dev
Verify server at http://localhost:4111
Step 3: Map Feature to Behavior Tests
Feature-to-Test Mapping Guide
| Feature Category | What to Test | Example Assertion | | -------------------------- | ------------------------------------------------- | ------------------------------------------------------------ | | **Agent Configuration** | Config changes affect agent behavior | Send message → verify response uses selected model | | **LLM Provider Selection** | Selected provider is used in requests | Intercept API call → verify provider in request payload | | **Tool Execution** | Tool runs with correct params & returns result | Execute tool → verify output matches expected transformation | | **Workflow Execution** | Steps execute in order, data flows between steps | Run workflow → verify each step's output feeds next step | | **Chat/Streaming** | Messages persist, context maintained across turns | Multi-turn conversation → verify context awareness | | **MCP Server Tools** | Server tools are callable and return data | Call MCP tool → verify response structure and content | | **Memory/Persistence** | Data survives page reload | Create item → reload → verify item exists | | **Error Handling** | Errors surface correctly to user | Trigger error condition → verify error message + recovery |
Step 4: Write Behavior-Focused Tests
Test Structure Template
import { test, expect, Page } from '@playwright/test';
import { resetStorage } from '../__utils__/reset-storage';
import { selectFixture } from '../__utils__/select-fixture';
import { nanoid } from 'nanoid';
/**
* FEATURE: [Name of feature]
* USER STORY: As a user, I want to [action] so that [outcome]
* BEHAVIOR UNDER TEST: [Specific behavior being validated]
*/
test.describe('[Feature Name] - Behavior Tests', () => {
let page: Page;
test.beforeEach(async ({ browser }) => {
const context = await browser.newContext();
page = await context.newPage();
});
test.afterEach(async () => {
aMastra 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.
Repo: mastra-ai/mastra
Other skills on mastra.
- /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 worktree). Covers workspace reconciliation, stored agents/skills CRUD, ownership, visibility, stars, registry/library Copy flow, picker allowlists,
Open skill - /debugging-difficult-bugs
Use early when debugging a medium or hard bug, especially when tests alone may not reveal the real runtime failure. Trigger this before extended TDD iteration when a bug involves runtime state, ordering, persistence, streaming, concurrency, UI/manual reproduction, external
Open skill - /docs-audit
Interactive documentation quality review for Mastra docs. Use when auditing, reviewing, or critiquing Mastra documentation; checking docs against source code; validating code examples, API accuracy, or property completeness; checking whether docs follow the styleguide and
Open skill - /mastra-docs
Documentation guidelines for Mastra. This skill should be used when writing or editing documentation for Mastra. Triggers on tasks involving documentation creation or updates.
Open skill - /mastra-frontend
How to build Mastra frontend interfaces with the @mastra/playground-ui design system. This skill should be used when creating or modifying any application UI — pages, components, styling, or tokens — in this repo or in an external consumer of the design system. The docs site has
Open skill - /mastra-smoke-test
Smoke test Mastra projects locally or deploy to staging/production. Tests Studio UI, agents, tools, workflows, traces, memory, and more. Supports both local development and cloud deployments.
Open skill

