Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Api Testing

ASecurity

REST and GraphQL API testing with Playwright. Use when testing APIs, mocking endpoints, validating responses, or integrating API tests with E2E flows.

3 stars
0 votes
0 copies
0 views
Added 2/8/2026
testingtypescriptgobashtestingapi

Works with

api

Security Analysis

A96/100
mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 3 files and shows the line behind each finding

Scanned 2/12/2026

$npx -y skills add adaptationio/Skrillz --skill api-testing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Api Testing?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Api Testing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adaptationio-api-testing/badge)](https://www.skillsdirectory.com/skills/adaptationio-api-testing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: api-testing
description: REST and GraphQL API testing with Playwright. Use when testing APIs, mocking endpoints, validating responses, or integrating API tests with E2E flows.
version: 1.0.0
tags: [testing, api, rest, graphql, playwright, automation]
---

# API Testing with Playwright

Comprehensive API testing for REST and GraphQL endpoints using Playwright's built-in API testing capabilities.

## Quick Start

```typescript
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');
});
```

## Installation

```bash
# Playwright includes API testing - no extra packages needed
npm install -D @playwright/test
```

## Configuration

**playwright.config.ts:**
```typescript
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' },
    },
  ],
});
```

## REST API Testing

### GET Requests

```typescript
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(/@/);
});
```

### POST Requests

```typescript
test('create new user', async ({ request }) => {
  const response = await request.post('/api/users', {
    data: {
      name: 'John Doe',
      email: 'john@example.com',
    },
  });

  expect(response.status()).toBe(201);

  const user = await response.json();
  expect(user.id).toBeDefined();
  expect(user.name).toBe('John Doe');
});
```

### PUT/PATCH Requests

```typescript
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');
});
```

### DELETE Requests

```typescript
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);
});
```

## Authentication

### Bearer Token

```typescript
test.describe('authenticated requests', () => {
  let token: string;

  test.beforeAll(async ({ request }) => {
    const response = await request.post('/api/auth/login', {
      data: {
        email: 'test@example.com',
        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();
  });
});
```

### Cookie-Based Auth

```typescript
test('login and access dashboard', async ({ request, context }) => {
  // Login (sets cookie automatically)
  await request.post('/api/auth/login', {
    data: { email: 'test@example.com', password: 'pass' },
  });

  // Cookie is automatically included in subsequent requests
  const response = await request.get('/api/dashboard');
  expect(response.ok()).toBeTruthy();
});
```

## GraphQL Testing

### Query

```typescript
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);
});
```

### Mutation

```typescript
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: 'john@example.com',
        },
      },
    },
  });

  const { data, errors } = await response.json();
  expect(errors).toBeUndefined();
  expect(data.createUser.id).toBeDefined();
});
```

### With Authentication

```typescript
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');
});
```

## API Mocking (for E2E tests)

### Mock API Responses

```typescript
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');
});
```

### Simulate Errors

```typescript
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();
});
```

### Delay Responses

```typescript
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();
});
```

## Response Validation

### JSON Schema Validation

```typescript
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();
});
```

### Response Headers

```typescript
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();
});
```

## File Upload

```typescript
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');
});
```

## Best Practices

1. **Separate API and E2E tests** - Use different test files/projects
2. **Use fixtures for common data** - Avoid repetition
3. **Test error cases** - 400, 401, 403, 404, 500 responses
4. **Validate response schemas** - Catch breaking changes early
5. **Mock external APIs** - Don't depend on third-party availability
6. **Clean up test data** - Use `afterEach` or `afterAll` hooks

## References

- `references/graphql-testing.md` - Advanced GraphQL patterns
- `references/schema-validation.md` - JSON Schema with Ajv

Attribution

adaptationioadaptationio
View sourceSee grades on GitHubMore from adaptationio →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Screen Reader Testing

Practical guide to testing web applications with screen readers for comprehensive accessibility validation.

401991 votes

Tdd Workflow

在编写新功能、修复错误或重构代码时使用此技能。强制执行测试驱动开发,包含单元测试、集成测试和端到端测试,覆盖率超过80%。

2456590 votes

Eval Harness

克劳德代码会话的正式评估框架,实施评估驱动开发(EDD)原则

2456590 votes

Python Testing

使用pytest、TDD方法、夹具、模拟、参数化和覆盖率要求的Python测试策略。

2456590 votes

Django Tdd

Django测试策略,包括pytest-django、TDD方法论、factory_boy、模拟、覆盖率以及测试Django REST Framework API。

2456590 votes
View all in testing →