Skip to content

A powerful Angular HTTP interceptor for mocking API responses with support for dynamic data generation, path matching, response delays, and simulated file operations. Perfect for development and testing.

License

Notifications You must be signed in to change notification settings

MaloPolese/ngx-api-mocks-interceptor

Repository files navigation

Ngx API Mock Interceptor

npm version npm downloads CI Quality License Angular Version

A powerful HTTP mock interceptor for Angular applications that helps you simulate API responses during development and testing.

🔥 Live Demo

Features

  • 🚀 Easy to set up and use
  • 🎯 Path matching with typed parameters support
  • 📝 Query parameters and headers matching
  • ⏱️ Configurable response delays
  • 🔄 Counter-based responses
  • 🎮 Full control over mock responses
  • 📦 Mock data factory
  • 🔄 Progress events simulation
  • 📁 File download simulation

Installation

npm i ngx-api-mocks-interceptor

Quick Start

  1. Create and Import the interceptor in your app.config.ts:
ng g interceptor mockInterceptor
import { HttpInterceptorFn } from "@angular/common/http";

export const mockInterceptor: HttpInterceptorFn = (req, next) => {
  return next(req);
};

export const appConfig: ApplicationConfig = {
  providers: [provideHttpClient(withInterceptors([mockInterceptor]))],
};
  1. Create your mock data using the factory:
import { autoIncrement, boolean, mocks, lorem, array, literal } from "ngx-api-mocks-interceptor";
import { faker } from "@faker-js/faker";

interface Todo {
  id: number;
  label: string;
  description: string;
  completed: boolean;
  status: 'OPEN' | 'CLOSE' | 'WAITING';
  options: {
    id: number;
    name: string;
  }[];
}

// Create several mocks with the `mocks` factory
export const todosMock = mocks<Todo>(
  {
    id: autoIncrement(1),
    label: () => faker.lorem.words(3), // We can use faker or any other generator
    description: lorem(6),
    completed: boolean(0.3),
    status: literal(['OPEN', 'CLOSE', 'WAITING'])
    options: array({
      id: autoIncrement(1),
      name: value('foo'),
    }, {count: 2}),
  },
  {
    count: 10, // Generate 10 items
  }
);

// Or a single mock with the `mock` factory
export const todoMock = mock<Todo>({
  id: autoIncrement(1),
  label: () => faker.lorem.words(3),
  description: lorem(6),
  completed: boolean(0.3),
  status: literal(['OPEN', 'WAITING'])
  options: array({
    id: autoIncrement(1),
    name: value('foo'),
  }, { min: 2, max: 5 }),
});
  1. Configure your mock interceptor:
import { match, mockRouter } from "ngx-api-mocks-interceptor";

export const mockInterceptor: HttpInterceptorFn = (req, next) => {
  const endpoint = "http://localhost:3000/api/v1";

  return mockRouter(req, next, {
    delay: 1000,
    pathMatch: "full",
    routes: [
      match(`${endpoint}/api/todos/`, "GET", () => new HttpResponse({ status: 200, body: todosMock.value })),
      match(`${endpoint}/api/todos/:id`, "GET", (_, params) => {
        const todo = todosMock.get((todo) => todo.id === +params.id);
        return new HttpResponse({ status: 200, body: todo });
      }),
      match(
        `${endpoint}/api/todos`,
        "POST",
        (req: HttpRequest<Partial<Todo>>) =>
          new HttpResponse({
            status: 201,
            body: todosMock.add(req.body!),
          })
      ),
    ],
    // Handle unmatched routes
    onNoMatch: () => of(new HttpResponse({ status: 404, body: { error: "Not Found" } })),
  });
};
  1. Advenced configuration:
import { createRouteCounter, match, mockRouter, createFileMockResponse } from "ngx-api-mocks-interceptor";

const getItemCounter = createRouteCounter();
export const mockInterceptor: HttpInterceptorFn = (req, next) => {
  const endpoint = "http://localhost:3000/api/v1";

  return mockRouter(req, next, {
    delay: 1000, // Global delay
    pathMatch: "full",
    routes: [
      match(
        `${endpoint}/api/todos`,
        "GET",
        () =>
          new HttpResponse({
            status: 200,
            body: todosMock.value,
          }),
        {
          delay: 800,
          counter: getItemCounter,
          responses: [
            {
              count: "2n", // Every second request
              response: () =>
                new HttpResponse({
                  status: 429,
                  body: { error: "Rate limited" },
                }),
            },
            {
              count: ">5", // After 5 requests
              response: () =>
                new HttpResponse({
                  status: 503,
                  body: { error: "Service degraded" },
                }),
            },
          ],
        }
      ),

      // GET with path parameters
      match(`${endpoint}/api/todos/:id`, "GET", (_, params) => {
        const todo = todosMock.get((todo) => todo.id === +params.id);
        return new HttpResponse({ status: 200, body: todo });
      }),

      // POST with request body
      match(
        `${endpoint}/api/todos`,
        "POST",
        (req: HttpRequest<Partial<Todo>>) =>
          new HttpResponse({
            status: 201,
            body: todosMock.add(req.body!),
          })
      ),

      // File download simulation
      match(`${endpoint}/api/todos/download`, "GET", () =>
        createFileMockResponse({
          path: "/mocks/example.txt",
          filename: "todos.txt",
          contentType: "text/plain",
          headers: {
            "Cache-Control": "no-cache",
          },
          chunkDelay: 200,
        })
      ),

      // Upload progress simulation
      match(`${endpoint}/api/upload`, "POST", () => [
        {
          type: HttpEventType.UploadProgress,
          loaded: 0,
          total: 100,
        },
        {
          type: HttpEventType.UploadProgress,
          loaded: 50,
          total: 100,
        },
        new HttpResponse({
          status: 200,
          body: { message: "Upload complete" },
        }),
      ]),
    ],
    // Handle unmatched routes
    onNoMatch: () =>
      of(
        new HttpResponse({
          status: 404,
          body: { error: "Not Found" },
        })
      ),
  });
};

Contributing

We welcome contributions! Please see our Contributing Guide for details.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A powerful Angular HTTP interceptor for mocking API responses with support for dynamic data generation, path matching, response delays, and simulated file operations. Perfect for development and testing.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published