Test d'API avec Playwright

VérifiéSûr

Utilisez les capacités de test API intégrées de Playwright pour tester les endpoints REST et GraphQL. Cela permet de valider les réponses, de simuler des points d'accès et d'intégrer des tests API dans des flux de bout en bout.

Spar Skills Guide Bot
TestingIntermédiaire
16002/06/2026
Claude Code
#testing#api#playwright#rest#graphql

Recommandé pour

Notre avis

Cette compétence fournit des capacités complètes de test d'API pour les endpoints REST et GraphQL en utilisant les fonctionnalités de test d'API intégrées de Playwright.

Points forts

  • Utilise les tests d'API intégrés de Playwright sans packages supplémentaires.
  • Prend en charge à la fois REST et GraphQL.
  • Gère l'authentification (jeton Bearer, cookies).
  • Permet de simuler des endpoints et de valider les réponses.

Limites

  • Dépend du test runner de Playwright, pas autonome.
  • Non adapté aux tests de charge ou de performance.
  • Nécessite une configuration existante de Playwright et un environnement Node.js.
Quand l'utiliser

Lorsque vous devez écrire des tests automatisés pour des API REST ou GraphQL et les intégrer avec des tests de bout en bout.

Quand l'éviter

Lorsque vous devez effectuer des tests de performance ou utiliser des bibliothèques HTTP spécifiques à un langage en dehors de Playwright.

Analyse de sécurité

Sûr
Score qualité90/100

The skill provides instructions for API testing using Playwright. It contains no destructive or exfiltrating actions, no obfuscated code, and no disabling of safety features. All examples are standard testing patterns.

Aucun point d'attention détecté

Exemples

Test REST GET endpoint
Write a Playwright test for a GET request to /api/users that verifies the status code is 200 and the response body contains an array of users with email addresses.
Test GraphQL query
Write a Playwright test that sends a GraphQL query to /graphql to retrieve a list of users and validates that each user has an id and name.
Test authenticated API
Write a Playwright test that logs in via POST /api/auth/login to obtain a bearer token, then uses that token to access a protected endpoint and checks for a successful response.

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

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

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

Configuration

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' },
    },
  ],
});

REST API Testing

GET Requests

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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
Skills similaires