Zod Validation
> **Skill Purpose:** TypeScript-first schema validation and runtime type checking patterns
> **Skill Purpose:** API testing strategies, test automation patterns, and quality assurance procedures
Full skill instructions
Skill Purpose: API testing strategies, test automation patterns, and quality assurance procedures
Objective: Establish comprehensive testing strategy with automated test suites, coverage requirements, and quality gates.
Universal Pattern:
Key Decisions (Project-Specific):
Customize per project:
Note: This is an example pattern using Jest, Vitest, and Playwright for Next.js. Adapt testing frameworks and patterns based on your specific project requirements and tech stack.
Framework-Specific Example: This demonstrates API testing patterns with Jest and Playwright. Adapt for your testing framework and API requirements.
// jest.config.js
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleNameMapping: {
'^@/(.*)$': '<rootDir>/$1',
},
testEnvironment: 'jest-environment-jsdom',
collectCoverageFrom: [
'app/**/*.{js,jsx,ts,tsx}',
'lib/**/*.{js,jsx,ts,tsx}',
'!**/*.d.ts',
'!**/node_modules/**',
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
};
module.exports = createJestConfig(customJestConfig);
// jest.setup.js
import '@testing-library/jest-dom';
// Mock Supabase client
jest.mock('@/lib/supabase', () => ({
supabase: {
from: jest.fn(() => ({
select: jest.fn(() => ({
eq: jest.fn(() => ({
single: jest.fn(() => ({
data: null,
error: null,
})),
})),
insert: jest.fn(() => ({
select: jest.fn(() => ({
single: jest.fn(() => ({
data: { id: 1, created_at: new Date().toISOString() },
error: null,
})),
})),
})),
})),
})),
},
}));
// Global test utilities
global.testUser = {
id: 'test-user-id',
email: '[email protected]',
name: 'Test User',
};
// __tests__/api/users.test.ts
import { createMocks } from 'node-mocks-http';
import { GET, POST } from '@/app/api/users/route';
import { supabase } from '@/lib/supabase';
// Mock Supabase
jest.mock('@/lib/supabase');
const mockSupabase = supabase as jest.Mocked<typeof supabase>;
describe('/api/users', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('GET', () => {
it('should return users list', async () => {
const mockUsers = [
{ id: 1, email: '[email protected]', name: 'User 1' },
{ id: 2, email: '[email protected]', name: 'User 2' },
];
mockSupabase.from.mockReturnValue({
select: jest.fn().mockReturnValue({
eq: jest.fn().mockReturnValue({
data: mockUsers,
error: null,
}),
}),
} as any);
const { req } = createMocks({ method: 'GET' });
const response = await GET(req);
expect(response.status).toBe(200);
const data = await response.json();
expect(data.data).toEqual(mockUsers);
});
it('should handle database errors', async () => {
mockSupabase.from.mockReturnValue({
select: jest.fn().mockReturnValue({
eq: jest.fn().mockReturnValue({
data: null,
error: new Error('Database error'),
}),
}),
} as any);
const { req } = createMocks({ method: 'GET' });
const response = await GET(req);
expect(response.status).toBe(500);
const data = await response.json();
expect(data.error).toBe('Internal server error');
});
});
describe('POST', () => {
it('should create a new user', async () => {
const newUser = {
email: '[email protected]',
name: 'New User',
};
mockSupabase.from.mockReturnValue({
insert: jest.fn().mockReturnValue({
select: jest.fn().mockReturnValue({
single: jest.fn().mockReturnValue({
data: { id: 3, ...newUser, created_at: new Date().toISOString() },
error: null,
}),
}),
}),
} as any);
const { req } = createMocks({
method: 'POST',
body: newUser,
});
const response = await POST(req);
expect(response.status).toBe(201);
const data = await response.json();
expect(data.data.email).toBe(newUser.email);
expect(data.data.name).toBe(newUser.name);
});
it('should validate required fields', async () => {
const invalidUser = {
name: 'Invalid User',
// Missing email
};
const { req } = createMocks({
method: 'POST',
body: invalidUser,
});
const response = await POST(req);
expect(response.status).toBe(400);
const data = await response.json();
expect(data.error).toContain('Email is required');
});
});
});
// __tests__/integration/user-workflow.test.ts
import { createMocks } from 'node-mocks-http';
import { GET as getUser } from '@/app/api/users/[id]/route';
import { POST as createUser } from '@/app/api/users/route';
import { supabase } from '@/lib/supabase';
jest.mock('@/lib/supabase');
const mockSupabase = supabase as jest.Mocked<typeof supabase>;
describe('User Workflow Integration', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('should complete user creation and retrieval workflow', async () => {
const userData = {
email: '[email protected]',
name: 'Workflow User',
};
const createdUser = {
id: 999,
...userData,
created_at: new Date().toISOString(),
};
// Mock user creation
mockSupabase.from.mockReturnValue({
insert: jest.fn().mockReturnValue({
select: jest.fn().mockReturnValue({
single: jest.fn().mockReturnValue({
data: createdUser,
error: null,
}),
}),
}),
} as any);
// Create user
const { req: createReq } = createMocks({
method: 'POST',
body: userData,
});
const createResponse = await createUser(createReq);
expect(createResponse.status).toBe(201);
// Mock user retrieval
mockSupabase.from.mockReturnValue({
select: jest.fn().mockReturnValue({
eq: jest.fn().mockReturnValue({
single: jest.fn().mockReturnValue({
data: createdUser,
error: null,
}),
}),
}),
} as any);
// Retrieve user
const { req: getReq } = createMocks({
method: 'GET',
query: { id: '999' },
});
const getResponse = await getUser(getReq);
expect(getResponse.status).toBe(200);
const retrievedData = await getResponse.json();
expect(retrievedData.data.email).toBe(userData.email);
});
});
// e2e/api-testing.spec.ts
import { test, expect } from '@playwright/test';
test.describe('API E2E Tests', () => {
test.beforeEach(async ({ request }) => {
// Setup test data or authentication
});
test('should handle complete user lifecycle', async ({ request }) => {
// Create user
const createUserResponse = await request.post('/api/users', {
data: {
email: '[email protected]',
name: 'E2E Test User',
},
});
expect(createUserResponse.ok()).toBeTruthy();
const createdUser = await createUserResponse.json();
const userId = createdUser.data.id;
// Get user
const getUserResponse = await request.get(`/api/users/${userId}`);
expect(getUserResponse.ok()).toBeTruthy();
const retrievedUser = await getUserResponse.json();
expect(retrievedUser.data.email).toBe('[email protected]');
// Update user (if endpoint exists)
const updateUserResponse = await request.put(`/api/users/${userId}`, {
data: {
name: 'Updated E2E User',
},
});
expect(updateUserResponse.ok()).toBeTruthy();
// Delete user (if endpoint exists)
const deleteUserResponse = await request.delete(`/api/users/${userId}`);
expect(deleteUserResponse.ok()).toBeTruthy();
});
test('should handle authentication flows', async ({ request }) => {
// Test login
const loginResponse = await request.post('/api/auth/login', {
data: {
email: '[email protected]',
password: 'testpassword',
},
});
expect(loginResponse.ok()).toBeTruthy();
const loginData = await loginResponse.json();
expect(loginData.token).toBeDefined();
// Use token for authenticated request
const protectedResponse = await request.get('/api/protected', {
headers: {
Authorization: `Bearer ${loginData.token}`,
},
});
expect(protectedResponse.ok()).toBeTruthy();
});
test('should handle error scenarios', async ({ request }) => {
// Test 404 for non-existent user
const notFoundResponse = await request.get('/api/users/99999');
expect(notFoundResponse.status()).toBe(404);
// Test validation errors
const validationResponse = await request.post('/api/users', {
data: {
name: 'Invalid User',
// Missing required email
},
});
expect(validationResponse.status()).toBe(400);
const validationData = await validationResponse.json();
expect(validationData.error).toContain('required');
});
});
// __tests__/utils/test-data.ts
export class TestDataFactory {
static createUser(overrides?: Partial<User>): User {
return {
id: Math.floor(Math.random() * 10000),
email: `test-${Date.now()}@example.com`,
name: 'Test User',
created_at: new Date().toISOString(),
...overrides,
};
}
static createUsers(count: number): User[] {
return Array.from({ length: count }, () => this.createUser());
}
static createApiRequest(overrides?: Partial<ApiRequest>): ApiRequest {
return {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
body: null,
...overrides,
};
}
}
// __tests__/utils/test-helpers.ts
export class TestHelpers {
static async setupTestDatabase(): Promise<void> {
// Setup test database with fixtures
// This could involve running migrations, seeding data, etc.
}
static async cleanupTestDatabase(): Promise<void> {
// Clean up test data after tests
}
static mockSupabaseResponse(data: any, error: Error | null = null) {
return {
data,
error,
count: data?.length || 0,
};
}
}
// __tests__/performance/api-load.test.ts
import { test, expect } from '@playwright/test';
test.describe('API Load Testing', () => {
test('should handle concurrent requests', async ({ request }) => {
const concurrentRequests = 50;
const promises = Array.from({ length: concurrentRequests }, () =>
request.get('/api/users')
);
const responses = await Promise.all(promises);
// All requests should succeed
responses.forEach(response => {
expect(response.ok()).toBeTruthy();
});
// Response times should be reasonable
const responseTimes = responses.map(response =>
response.headers()['x-response-time']
);
const avgResponseTime = responseTimes.reduce(
(sum, time) => sum + parseInt(time), 0
) / responseTimes.length;
expect(avgResponseTime).toBeLessThan(1000); // Less than 1 second average
});
});
STOP and escalate if:
Skill Version: 1.0.0
> **Skill Purpose:** TypeScript-first schema validation and runtime type checking patterns
> **Skill Purpose:** Database schema alignment and data flow verification patterns
> **Skill Purpose:** API security assessment, vulnerability scanning, and security validation procedures
> **Skill Purpose:** Maintain baselines for regression, performance, and snapshot tests to detect meaningful changes.
> **Skill Purpose:** Authentication and authorization security patterns with access control
> **Skill Purpose:** Backend-as-a-Service client integration and configuration patterns
> **Skill Purpose:** Multi-environment configuration and deployment patterns
> **Skill Purpose:** Mobile-first design implementation, breakpoint management, and responsive component patterns
> **Skill Purpose:** Plan and execute authorized penetration testing to identify exploitable security weaknesses.
> **Skill Purpose:** CSS framework configuration and styling system patterns
> **Skill Purpose:** Establish code quality enforcement patterns before commits
> **Skill Purpose:** Instrument and monitor application performance with metrics, alerts, and trend analysis.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience