Agent skill
standards-testing
Comprehensive testing patterns for modern TypeScript applications covering Vitest, React Testing Library, Playwright E2E, and MSW API mocking.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/testing/standards-testing-korallis-amp-os
SKILL.md
Testing Standards
Standards for unit, integration, and E2E testing in modern TypeScript applications.
When to Use
- Writing unit tests for functions/components
- Setting up integration tests
- Creating E2E test suites
- Mocking APIs and external services
Resources
| Resource | Use When |
|---|---|
| test-patterns.md | Unit/integration test patterns |
| coverage-guidelines.md | Coverage targets and strategies |
Quick Reference
Test Structure (AAA Pattern)
test('should add item to cart', async () => {
// Arrange
const user = userEvent.setup();
render(<Cart />);
// Act
await user.click(screen.getByRole('button', { name: /add to cart/i }));
// Assert
expect(screen.getByText(/1 item in cart/i)).toBeInTheDocument();
});
Vitest Setup
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
import tsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
plugins: [tsconfigPaths(), react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./vitest.setup.ts'],
include: ['src/**/*.{test,spec}.{ts,tsx}'],
coverage: {
provider: 'v8',
thresholds: { lines: 80, functions: 80, branches: 75 },
},
},
});
// vitest.setup.ts
import '@testing-library/jest-dom/vitest';
import { cleanup } from '@testing-library/react';
import { afterEach, afterAll, beforeAll, vi } from 'vitest';
import { server } from './mocks/server';
// MSW server lifecycle
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterEach(() => {
server.resetHandlers();
cleanup();
});
afterAll(() => server.close());
// Mock browser APIs
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation((query) => ({
matches: false,
media: query,
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
})),
});
RTL Query Priority
// ✅ Accessible queries (preferred)
screen.getByRole('button', { name: /submit/i });
screen.getByLabelText(/email address/i);
screen.getByText(/welcome back/i);
// ⚠️ Semantic queries (acceptable)
screen.getByAltText(/company logo/i);
// ❌ Test IDs (last resort)
screen.getByTestId('submit-button');
Custom Render with Providers
// test-utils.tsx
import { render, RenderOptions } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const createTestQueryClient = () =>
new QueryClient({
defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
});
export function renderWithProviders(ui: ReactElement, options: RenderOptions = {}) {
const queryClient = createTestQueryClient();
function Wrapper({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);
}
return {
user: userEvent.setup(),
queryClient,
...render(ui, { wrapper: Wrapper, ...options }),
};
}
MSW Handlers
// mocks/handlers.ts
import { http, HttpResponse } from 'msw';
export const handlers = [
http.get('/api/users', () => {
return HttpResponse.json([
{ id: '1', name: 'Alice' },
{ id: '2', name: 'Bob' },
]);
}),
http.post('/api/users', async ({ request }) => {
const body = await request.json();
return HttpResponse.json({ id: '3', ...body }, { status: 201 });
}),
];
// mocks/server.ts
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
Runtime Handler Override
test('handles server error', async () => {
server.use(
http.get('/api/users', () => {
return HttpResponse.json({ message: 'Error' }, { status: 500 });
})
);
render(<UserList />);
await waitFor(() => {
expect(screen.getByText(/error loading/i)).toBeInTheDocument();
});
});
Playwright E2E
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './e2e',
fullyParallel: true,
retries: process.env.CI ? 2 : 0,
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
],
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
},
});
Page Object Model
// e2e/pages/login.page.ts
import { Page, Locator, expect } from '@playwright/test';
export class LoginPage {
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
constructor(private page: Page) {
this.emailInput = page.getByLabel(/email/i);
this.passwordInput = page.getByLabel(/password/i);
this.submitButton = page.getByRole('button', { name: /sign in/i });
}
async goto() {
await this.page.goto('/login');
}
async login(email: string, password: string) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
}
Coverage Targets
| Metric | Minimum | Notes |
|---|---|---|
| Lines | 80% | Overall code coverage |
| Functions | 80% | All functions tested |
| Branches | 75% | Conditional paths covered |
NPM Scripts
{
"scripts": {
"test": "vitest",
"test:watch": "vitest --watch",
"test:coverage": "vitest run --coverage",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui"
}
}
Amp Tools to Use
finder- Find existing test patternsRead- Check test file conventionsoracle- Guidance on complex test scenarios
Related Skills
standards-global- TypeScript conventionsstandards-frontend- Component patterns to teststandards-backend- API patterns to test
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?