1.1.0 • Published 18 days ago

mocaron v1.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
18 days ago


Installation

# npm
npm install -D mocaron

# yarn
yarn add -D mocaron

# pnpm
pnpm add -D mocaron

Quick Start

import { MockServer } from "mocaron";

const mockServer = new MockServer({ port: 3000 });

await mockServer.start();

mockServer.get("/test", { status: 200, body: { message: "Hello World" } });

const response = await fetch("http://localhost:3000/test");

console.log(response.status); // 200
console.log(await response.json()); // { message: "Hello World" }

await mockServer.stop();

Usage

Starting and stopping the mock server

See constructor() start() stop()

import { MockServer } from "mocaron";

const mockServer = new MockServer({ port: 3000 });

await mockServer.start();

// ...

await mockServer.stop();

Registering a mock

Register a mock using mock().

mockServer.mock(
  { path: "/test", method: "GET" },
  { status: 200, body: { message: "Hello World" } },
);

const response = await fetch("http://localhost:3000/test");

console.log(response.status); // 200
console.log(await response.json()); // { message: "Hello World" }

Method specific mocks

You can also register mocks that only match a specific HTTP method.

See get() post() put() patch() delete()

mockServer
  .get("/test", { status: 200, body: { message: "Hello World" } })
  .post("/test", { status: 201, body: { message: "Created" } })
  .put("/test", { status: 200, body: { message: "Replaced" } })
  .patch("/test", { status: 200, body: { message: "Updated" } })
  .delete("/test", { status: 204 });

Unmatched requests

If a request does not match any of the registered mocks the server will respond with a 404 status code.

const response = await fetch("http://localhost:3000/test");

console.log(response.status); // 404

Ambiguous mocks

If two or more mocks match the same request the server will respond with a 404 status code.

mockServer.mock({ path: "/foo" }, "foo").mock({ path: "/foo" }, "bar");

const response = await fetch("http://localhost:3000/foo");

console.log(response.status); // 404

You can override this behavior by passing the overwrite option to the last matching mock.

mockServer
  .mock({ path: "/foo" }, "foo")
  .mock({ path: "/foo" }, "bar", { overwrite: true });

const response = await fetch("http://localhost:3000/foo");

console.log(response.status); // 200
console.log(await response.text()); // bar

Resetting the mock server

Calling reset() will reset the mock server to its initial state.

mockServer.get("/test", { status: 200 });

let response = await fetch("http://localhost:3000/test");
console.log(response.status); // 200

mockServer.reset();

response = await fetch("http://localhost:3000/test");
console.log(response.status); // 404

Testing

Set up the mock server for each test using start(), stop() and reset().

import { MockServer } from "mocaron";
import { beforeAll, afterAll, beforeEach, test, assert } from "my-test-library";

const mockServer = new MockServer({ port: 3000 });

beforeAll(() => mockServer.start());
afterAll(() => mockServer.stop());
beforeEach(() => mockServer.reset());

Test that a mock has been called using hasBeenCalledWith().

test("mock has been called", async () => {
  mockServer.get("/test", { status: 200 });

  await fetch("http://localhost:3000/test");

  assert(mockServer.hasBeenCalledWith({ path: "/test" }));
});

Test that a mock has been called a specific number of times using hasBeenCalledTimes().

test("mock has been called 3 times", async () => {
  mockServer.get("/test", { status: 200 });

  await fetch("http://localhost:3000/test");
  await fetch("http://localhost:3000/test");
  await fetch("http://localhost:3000/test");

  assert(mockServer.hasBeenCalledTimes(3, { path: "/test" }));
});

Custom assertions using calls().

test("custom assertion", async () => {
  mockServer.get("/test", { status: 200 });

  await fetch("http://localhost:3000/test");

  assert(mockServer.calls().length === 1);
  assert(mockServer.calls()[0].request.path === "/test");
});

API

MockServer

constructor(options): MockServer

Create a new MockServer instance.

ParamTypeDefault
optionsOptions-

Example

const mockServer = new MockServer({ port: 3000 });

start(): Promise<void>

Start the mock server.

Example

await mockServer.start();

stop(): Promise<void>

Stop the mock server.

Example

await mockServer.stop();

port(): number

Get the port the mock server is running on.

Example

const port = mockServer.port();
console.log(port); // 3000

mock(matcher, response, options): MockServer

Register a mock.

ParamTypeDefault
matcherstring | RegExp | Matcher-
responsestring | number | Response-
optionsMockOptions{}

If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.

Returns the MockServer instance.

Example

mockServer.mock({ path: "/test" }, { status: 204 });

const response = await fetch("http://localhost:3000/test");

console.log(response.status); // 204

get(matcher, response, options): MockServer

Register a mock that only responds to requests using the HTTP GET method.

ParamTypeDefault
matcherstring | RegExp | MatcherObj-
responsestring | number | Response-
optionsMockOptions{}

If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.

Returns the MockServer instance.

Example

mockServer.get("/test", {
  status: 200,
  body: { message: "Hello World" },
});

const response = await fetch("http://localhost:3000/test");

console.log(response.status); // 200
console.log(await response.json()); // { message: "Hello World" }

post(matcher, response, options): MockServer

Register a mock that only responds to requests using the HTTP POST method.

ParamTypeDefault
matcherstring | RegExp | MatcherObj-
responsestring | number | Response-
optionsMockOptions{}

If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.

Returns the MockServer instance.

Example

mockServer.post("/test", {
  status: 201,
  body: { message: "Hello World" },
});

const response = await fetch("http://localhost:3000/test", {
  method: "POST",
  body: JSON.stringify({ message: "Hello World" }),
});

console.log(response.status); // 201
console.log(await response.json()); // { message: "Hello World" }

put(matcher, response, options): MockServer

Register a mock that only responds to requests using the HTTP PUT method.

ParamTypeDefault
matcherstring | RegExp | MatcherObj-
responsestring | number | Response-
optionsMockOptions{}

If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.

Returns the MockServer instance.

Example

mockServer.put("/test", {
  status: 200,
  body: { message: "Hello World" },
});

const response = await fetch("http://localhost:3000/test", {
  method: "PUT",
  body: JSON.stringify({ message: "Hello World" }),
});

console.log(response.status); // 200
console.log(await response.json()); // { message: "Hello World" }

patch(matcher, response, options): MockServer

Register a mock that only responds to requests using the HTTP PATCH method.

ParamTypeDefault
matcherstring | RegExp | MatcherObj-
responsestring | number | Response-
optionsMockOptions{}

If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.

Returns the MockServer instance.

Example

mockServer.patch("/test", {
  status: 200,
  body: { message: "Hello World" },
});

const response = await fetch("http://localhost:3000/test", {
  method: "PATCH",
  body: JSON.stringify({ message: "Hello World" }),
});

console.log(response.status); // 200
console.log(await response.json()); // { message: "Hello World" }

delete(matcher, response, options): MockServer

Register a mock that only responds to requests using the HTTP DELETE method.

ParamTypeDefault
matcherstring | RegExp | MatcherObj-
responsestring | number | Response-
optionsMockOptions{}

If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.

Returns the MockServer instance.

Example

mockServer.delete("/test", { status: 204 });

const response = await fetch("http://localhost:3000/test", {
  method: "DELETE",
});

console.log(response.status); // 204

mocks(): readonly Mock[]

Get all registered mocks.

Returns an array of Mock objects.

Example

mockServer.mock({ path: "/test" }, { status: 204 });

const mocks = mockServer.mocks();

console.log(mocks);
// [{ matcher: { path: "/test" }, response: { status: 204 } }]

calls(): readonly Call[]

Get all registered calls.

Returns an array of Call objects.

Example

mockServer.mock({ path: "/test" }, { status: 204 });
await fetch("http://localhost:3000/test");

const calls = mockServer.calls();

console.log(calls);
// [{ matcher: { path: "/test" }, request: <express.Request> }]

hasBeenCalledWith(matcher): boolean

Check if the route has been called with the given matcher.

ParamTypeDefault
matcherstring | RegExp | Matcher-

If matcher is a string or RegExp, it will be used to match the request path.

Returns true if the route has been called with the given matcher, false otherwise.

Example

mockServer.get("/test", { status: 200 });

console.log(mockServer.hasBeenCalledWith({ path: "/test" })); // false

await fetch("http://localhost:3000/test");

console.log(mockServer.hasBeenCalledWith({ path: "/test" })); // true

hasBeenCalledTimes(times, matcher): boolean

Check if the route has been called a certain number of times with the given matcher.

ParamTypeDefault
timesnumber-
matcherstring | RegExp | Matcher-

If matcher is a string or RegExp, it will be used to match the request path.

Returns true if the route has been called times times with the given matcher, false otherwise.

Example

mockServer.get("/test", { status: 200 });

console.log(mockServer.hasBeenCalledTimes(0, { path: "/test" })); // true
console.log(mockServer.hasBeenCalledTimes(1, { path: "/test" })); // false

await fetch("http://localhost:3000/test");

console.log(mockServer.hasBeenCalledTimes(0, { path: "/test" })); // false
console.log(mockServer.hasBeenCalledTimes(1, { path: "/test" })); // true

countCalls(matcher): number

Count the number of times the server was called with the given matcher.

ParamTypeDefault
matcherstring | RegExp | Matcher-

If matcher is a string or RegExp, it will be used to match the request path.

Returns the number of times the server has been called with the given matcher.

Example

mockServer.get("/test", { status: 200 });

console.log(mockServer.countCalls({ path: "/test" })); // 0

await fetch("http://localhost:3000/test");

console.log(mockServer.countCalls({ path: "/test" })); // 1

reset(): void

Reset all mocks and calls.

Example

mockServer.get("/test", { status: 200 });
await fetch("http://localhost:3000/test");

console.log(mockServer.mocks());
// [{ matcher: { path: "/test", method: "GET" }, response: { status: 200 } }]

console.log(mockServer.calls());
// [{ matcher: { path: "/test", method: "GET" }, request: <express.Request> }]

mockServer.reset();

console.log(mockServer.mocks()); // []
console.log(mockServer.calls()); // []

resetMocks(): void

Reset all mocks.

Example

mockServer.get("/test", { status: 200 });

console.log(mockServer.mocks());
// [{ matcher: { path: "/test", method: "GET" }, response: { status: 200 } }]

mockServer.resetMocks();

console.log(mockServer.mocks()); // []

resetCalls(): void

Reset all calls.

Example

mockServer.get("/test", { status: 200 });
await fetch("http://localhost:3000/test");

console.log(mockServer.calls());
// [{ matcher: { path: "/test", method: "GET" }, request: <express.Request> }]

mockServer.resetCalls();

console.log(mockServer.calls()); // []

ExpectationMessage

hasBeenCalledWith(mockServer, matcher): string

Format an expectation message for hasBeenCalledWith().

ParamTypeDefault
mockServerMockServer-
matcherMatcher-

Returns a string with the formatted expectation message.

Example

if (!mockServer.hasBeenCalledWith(matcher)) {
  throw new Error(ExpectationMessage.hasBeenCalledWith(mockServer, matcher));
}

hasBeenCalledTimes(mockServer, times, matcher): string

Format an expectation message for hasBeenCalledTimes().

ParamTypeDefault
mockServerMockServer-
timesnumber-
matcherMatcher-

Returns a string with the formatted expectation message.

Example

if (!mockServer.hasBeenCalledTimes(mockServer, 2, matcher)) {
  throw new Error(
    ExpectationMessage.hasBeenCalledTimes(mockServer, 2, matcher),
  );
}

Options

Object with the following properties:

PropertyTypeDescription
portnumberport to run the mock server on

Request

Type alias for express.Request with the body property typed as Buffer | undefined.

type Request = express.Request<{}, unknown, Buffer | undefined>;

Matcher

Type alias for MatcherObj | MatcherFn.

type Matcher = MatcherObj | MatcherFn;

MatcherObj

Object with the following properties:

PropertyTypeDescription
methodstring | undefinedHTTP method to match against
pathstring | RegExp | undefinedpath to match against
queryRequest["query"] | undefinedquery parameters to match against.Parameters explicitly set to undefined will not match when provided.
headersRecord<string, string \| undefined> | undefinedheaders to match against.Headers explicitly set to undefined will not match when provided.
bodystring | object | undefinedbody to match against.If an object is given it will be compared to the request body parsed as JSON.

MatcherFn

Function that takes a Request and returns whether the request should match.

type MatcherFn = (req: Request) => boolean;

Response

Type alias for ResponseObj | ResponseFn.

type Response = ResponseObj | ResponseFn;

ResponseObj

Object with the following properties:

PropertyTypeDescription
statusnumber | undefinedstatus code to respond with (defaults to 200)
headersRecord<string, string> | undefinedheaders to respond with
bodystring | object | undefinedbody to respond with.If an object is given it will be converted to a JSON string.
delaynumber | undefineddelay in milliseconds before responding

ResponseFn

Function or async function that takes a Request and returns a ResponseObj.

type ResponseFn = (req: Request) => ResponseObj | Promise<ResponseObj>;

MockOptions

Object with the following properties:

PropertyTypeDescription
overwriteboolean | undefinedwhen set to true,previous ambiguous mocks matching the same request will be overwritten

Mock

Object with the following properties:

PropertyTypeDescription
matcherMatchermatcher to match against the request
responseResponseresponse the server will respond with when matched
optionsMockOptionssee MockOptions

Call

Object with the following properties:

PropertyTypeDescription
requestRequestrequest the server was called with
matcherMatchermatcher the request matched against

Changelog

CHANGELOG.md

License

MIT

1.1.0

18 days ago

1.1.0-beta.0

18 days ago

0.1.0-beta.3

9 months ago

0.1.0-beta.2

9 months ago

1.0.0

9 months ago

0.1.0-beta.5

9 months ago

0.1.0-beta.4

9 months ago

0.1.0-beta.1

9 months ago

0.1.0-beta.0

9 months ago

0.3.0

9 months ago

0.1.0-beta.7

9 months ago

0.1.0-beta.6

9 months ago

0.0.3-alpha.1

9 months ago

0.0.3-alpha.0

9 months ago

0.0.2

2 years ago

0.0.1

2 years ago

0.0.0-empty

2 years ago