JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 118
  • Score
    100M100P100Q85750F
  • License MIT

Mock any API for testing and development.

Package Exports

  • ecko
  • ecko/package.json

Readme

Ecko

Mock any API for testing and development.

Most testing libraries offer the ability to mock external requests. But what if your tests are running on a client and you need to mock requests that the server is making? Or what if you're testing a CLI script by executing it and you need to mock requests that the script makes?

Ecko is an http server that allows you to register endpoints and responses, and then any requests made to those endpoints will return the responses you defined. This essentially lets you mock any third-party service in a way that can be used by code running in any context in your tests.

Contributing

See the the Contributing doc for how to contribute.

Install

npm install ecko

Release

npm run local-release

Examples

How does it work?

Setup the server

import { EckoServer, type EckoApi } from "../src/index.js";

const PORT = 3005;

let ecko: EckoApi;
let eckoServer: EckoServer;
let baseUrl: string;

beforeAll(async () => {
  eckoServer = EckoServer();

  const startResult = await eckoServer.start({
    port: PORT,
    logLevel: "error",
  });

  ecko = startResult.ecko;
  baseUrl = startResult.baseUrl;
});

afterEach(() => {
  eckoServer.reset();
});

afterAll(async () => {
  await eckoServer.stop();
});

This will start Ecko on port 3005. The eckoServer.start will also give you ecko which is what you'll use to register responses and baseUrl which is the base URL that ecko is running on (e.g. http://localhost:3005).

Register endpoints

ecko.register("/test/endpoint", "get", {
  frequency: "always",
  payload: "Response from request",
});

ecko.register("/test/endpoint", "get", {
  frequency: "once",
  payload: "Response from request",
});

ecko.register("/test/endpoint", "get", {
  frequency: { type: "limit", limit: 5 },
  payload: "Response from request",
});

ecko.register("/test/endpoint", "put", {
  frequency: "always",
  status: 500,
  headers: { "x-my-header": "VALUE" },
  payload: { orderId: "1234" },
  beforeResponse: async ({ method, headers, queryParams, body }) => {},
  afterResponse: async ({ method, headers, queryParams, body }) => {},
});

ecko.register("/test/endpoint", "post", {
  frequency: "always",
  getResponse: async ({ method, headers, queryParams, body }) => {
    return {
      status: 202,
      headers: { "x-my-header": "VALUE" },
      payload: { orderId: "1234" },
      beforeResponse: async (args) => {},
      afterResponse: async (args) => {},
    };
  },
});

Calling ecko.register will register an endpoint. You specific the path, the method, the frequency, and the payload. When that endpoint is called, it will respond with the payload provided.

Endpoints are registered in a stack. So if you have a frequency: "once" before a "frequency: "all", the first call to the endpoint will return the with frequency: "once" and then all subsequence calls will return the response with frequency: "all".

Same if you have multiple endpoints with the same path and method and each with frequency: "all". The last endpoint registered will always be returned.

ecko.register arguments

  • path: The path of the endpoint.
  • method: get, post, put, delete, etc (all methods are supported).
  • options:
    • frequency (required):
      • always: Return this response every time.
      • once: Return this response once.
      • {type: "limit", limit: 5}. Return this response five times.
    • headers (optional). An object where the keys are the name of the headers. These headers will be returned in the response exactly as provided.
    • status (optional). And HTTP status integer.
    • payload (optional). The response body. This can be anything.
    • beforeResponse (optional). An async function that will be called before a response is returned from the endpoint. The function accepts and object with these arguments:
      • method. The lower-case version of the method (e.g. get, post, etc).
      • headers. The headers of the request. Note that all the keys will be lower-case.
      • queryParams. Key-value pair of all query params.
      • body. The request body. This will be an object if the request body was sent as JSON. Otherwise it will be plain text.
      • textBody. The plain text version of the request body.
    • afterResponse (optional). A function that will be called after a response is returned from the endpoint.
  • Instead of the options arguments above, you can instead provide:
    • frequency. Same values as above.
    • getResponse. An async function that takes the arguments defined above for beforeResponse and returns an object with these properties (see options above for descriptions):
      • headers (optional).
      • status (optional).
      • payload (optional).
      • beforeResponse (optional).
      • afterResponse (optional).