Coding
PromptBeginner5 minmarkdown
Markdown Converter
Agent skill for markdown-converter
7
REST and GraphQL API testing with Playwright. Use when testing APIs, mocking endpoints, validating responses, or integrating API tests with E2E flows.
Sign in to like and favorite skills
Comprehensive API testing for REST and GraphQL endpoints using Playwright's built-in API testing capabilities.
import { test, expect } from '@playwright/test'; test('GET /api/users returns users', async ({ request }) => { const response = await request.get('/api/users'); expect(response.ok()).toBeTruthy(); expect(response.status()).toBe(200); const users = await response.json(); expect(users).toHaveLength(10); expect(users[0]).toHaveProperty('email'); });
# Playwright includes API testing - no extra packages needed npm install -D @playwright/test
playwright.config.ts:
import { defineConfig } from '@playwright/test'; export default defineConfig({ testDir: './tests', use: { baseURL: 'http://localhost:3000', extraHTTPHeaders: { 'Accept': 'application/json', }, }, projects: [ { name: 'api', testMatch: /.*\.api\.spec\.ts/, }, { name: 'e2e', testMatch: /.*\.e2e\.spec\.ts/, use: { browserName: 'chromium' }, }, ], });
test('fetch user by ID', async ({ request }) => { const response = await request.get('/api/users/123'); expect(response.ok()).toBeTruthy(); const user = await response.json(); expect(user.id).toBe(123); expect(user.email).toMatch(/@/); });
test('create new user', async ({ request }) => { const response = await request.post('/api/users', { data: { name: 'John Doe', email: '[email protected]', }, }); expect(response.status()).toBe(201); const user = await response.json(); expect(user.id).toBeDefined(); expect(user.name).toBe('John Doe'); });
test('update user', async ({ request }) => { const response = await request.put('/api/users/123', { data: { name: 'Jane Doe', }, }); expect(response.ok()).toBeTruthy(); const user = await response.json(); expect(user.name).toBe('Jane Doe'); });
test('delete user', async ({ request }) => { const response = await request.delete('/api/users/123'); expect(response.status()).toBe(204); // Verify deletion const getResponse = await request.get('/api/users/123'); expect(getResponse.status()).toBe(404); });
test.describe('authenticated requests', () => { let token: string; test.beforeAll(async ({ request }) => { const response = await request.post('/api/auth/login', { data: { email: '[email protected]', password: 'password123', }, }); const data = await response.json(); token = data.token; }); test('access protected endpoint', async ({ request }) => { const response = await request.get('/api/protected', { headers: { 'Authorization': `Bearer ${token}`, }, }); expect(response.ok()).toBeTruthy(); }); });
test('login and access dashboard', async ({ request, context }) => { // Login (sets cookie automatically) await request.post('/api/auth/login', { data: { email: '[email protected]', password: 'pass' }, }); // Cookie is automatically included in subsequent requests const response = await request.get('/api/dashboard'); expect(response.ok()).toBeTruthy(); });
test('GraphQL query users', async ({ request }) => { const response = await request.post('/graphql', { data: { query: ` query GetUsers { users { id name email } } `, }, }); const { data, errors } = await response.json(); expect(errors).toBeUndefined(); expect(data.users).toHaveLength(10); });
test('GraphQL create user', async ({ request }) => { const response = await request.post('/graphql', { data: { query: ` mutation CreateUser($input: CreateUserInput!) { createUser(input: $input) { id name email } } `, variables: { input: { name: 'John Doe', email: '[email protected]', }, }, }, }); const { data, errors } = await response.json(); expect(errors).toBeUndefined(); expect(data.createUser.id).toBeDefined(); });
test('GraphQL with auth', async ({ request }) => { const response = await request.post('/graphql', { headers: { 'Authorization': `Bearer ${token}`, }, data: { query: ` query Me { me { id email role } } `, }, }); const { data } = await response.json(); expect(data.me.role).toBe('admin'); });
test('display mocked products', async ({ page }) => { // Mock the API await page.route('**/api/products', route => { route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify([ { id: 1, name: 'Mock Product', price: 99.99 }, ]), }); }); await page.goto('/products'); await expect(page.locator('.product')).toHaveCount(1); await expect(page.locator('.product-name')).toHaveText('Mock Product'); });
test('handle API error gracefully', async ({ page }) => { await page.route('**/api/products', route => { route.fulfill({ status: 500, body: JSON.stringify({ error: 'Server error' }), }); }); await page.goto('/products'); await expect(page.locator('.error-message')).toBeVisible(); });
test('show loading state', async ({ page }) => { await page.route('**/api/products', async route => { await new Promise(r => setTimeout(r, 2000)); route.fulfill({ status: 200, body: JSON.stringify([]), }); }); await page.goto('/products'); await expect(page.locator('.loading-spinner')).toBeVisible(); });
import Ajv from 'ajv'; const ajv = new Ajv(); const userSchema = { type: 'object', properties: { id: { type: 'number' }, name: { type: 'string' }, email: { type: 'string', format: 'email' }, }, required: ['id', 'name', 'email'], }; test('validate response schema', async ({ request }) => { const response = await request.get('/api/users/1'); const user = await response.json(); const validate = ajv.compile(userSchema); expect(validate(user)).toBeTruthy(); });
test('check response headers', async ({ request }) => { const response = await request.get('/api/users'); expect(response.headers()['content-type']).toContain('application/json'); expect(response.headers()['x-rate-limit-remaining']).toBeDefined(); });
import path from 'path'; test('upload file', async ({ request }) => { const response = await request.post('/api/upload', { multipart: { file: { name: 'test.pdf', mimeType: 'application/pdf', buffer: Buffer.from('PDF content'), }, description: 'Test document', }, }); expect(response.ok()).toBeTruthy(); const result = await response.json(); expect(result.filename).toBe('test.pdf'); });
afterEach or afterAll hooksreferences/graphql-testing.md - Advanced GraphQL patternsreferences/schema-validation.md - JSON Schema with Ajv