lyrebird
Version:
A wrapper for writing more reusable and cleaner mocks using mswjs.io.
146 lines (143 loc) • 3.91 kB
JavaScript
// src/RestHandler.ts
import { RestHandler as MSWRestHandler, RESTMethods } from "msw";
var RestHandler = class {
constructor() {
this.method = RESTMethods.GET;
this.responseStatusCode = 200;
this.name = null;
}
on(method, url) {
this.method = typeof method === "string" ? RESTMethods[method] : method;
this.url = url;
return this;
}
onGet(url) {
return this.on(RESTMethods.GET, url);
}
onPost(url) {
return this.on(RESTMethods.POST, url);
}
onPatch(url) {
return this.on(RESTMethods.PATCH, url);
}
onPut(url) {
return this.on(RESTMethods.PUT, url);
}
onOptions(url) {
return this.on(RESTMethods.OPTIONS, url);
}
onHead(url) {
return this.on(RESTMethods.HEAD, url);
}
onDelete(url) {
return this.on(RESTMethods.DELETE, url);
}
withParams(params) {
this.params = params;
return this;
}
withPayload(payload) {
this.requestPayload = payload;
return this;
}
reply(status, body) {
this.responseStatusCode = status;
this.responseBody = body;
return this;
}
resolve(resolver) {
this.resolver = resolver;
return this;
}
as(name) {
this.name = name;
return this;
}
run() {
if (!this.url)
throw new Error("No url provided");
return new MSWRestHandler(this.method, this.url, (request, response, context) => {
if (this.resolver) {
return this.resolver({ request, response, context });
}
if (this.params && paramsMismatched(this.params, request.url.searchParams)) {
return response.networkError("Params mismatch.");
}
if (payloadMismatched(this.requestPayload, request.body)) {
return response.networkError("Payload mismatch.");
}
return response(context.status(this.responseStatusCode), context.json(this.responseBody));
});
}
};
function paramsMismatched(expected, actual) {
for (const property in expected) {
if (expected[property] !== actual.get(property)) {
return true;
}
}
return false;
}
function payloadMismatched(expected, actual) {
return expected && JSON.stringify(expected) !== JSON.stringify(actual);
}
// src/MockServer.ts
var MockServer = class {
constructor(server, options) {
this.server = server;
if (options) {
this.collection = options.collection;
}
}
use(...handlers) {
if (Array.isArray(handlers)) {
handlers.forEach((handler) => {
if (handler instanceof RestHandler) {
return this.enableHandlerInstance(handler);
}
this.enableHandlerFromCollection(handler);
});
}
}
enable(...handlers) {
return this.use(...handlers);
}
enableHandlerInstance(handler) {
return this.server.use(handler.run());
}
enableHandlerFromCollection(handlerName) {
if (!this.collection) {
throw new Error(`
Lyrebird: Unable to find handler \`${handlerName}\` because there isn't a HandlerCollection associated with the current MockServer instance. Please consider creating a HandlerCollection or using an inline handler instead.`);
}
this.server.use(this.collection.find(handlerName).run());
}
};
// src/HandlerCollection.ts
var HandlerCollection = class {
constructor() {
this.collection = new Map();
}
collect(...handlers) {
handlers.forEach((handler) => {
const key = handler.name;
if (!key) {
throw new Error('\nLyrebird: Each handler should contain a name to be stored in the collection. \nFor future reference, name your handler using the `as("...")` method');
}
this.collection.set(key, handler);
});
}
find(name) {
const handler = this.collection.get(name);
if (!handler) {
throw new Error(`
Lyrebird: No Handler found with the given name \`${name}\` in the collection.`);
}
return handler;
}
};
export {
HandlerCollection,
MockServer,
RestHandler
};