107 lines
3.7 KiB
TypeScript
107 lines
3.7 KiB
TypeScript
import { setupServer } from "msw/node";
|
|
|
|
import { fromJson, toJson } from "../../src/core/json";
|
|
import { MockServer } from "./MockServer";
|
|
import { randomBaseUrl } from "./randomBaseUrl";
|
|
|
|
const mswServer = setupServer();
|
|
interface MockServerOptions {
|
|
baseUrl?: string;
|
|
}
|
|
|
|
async function formatHttpRequest(request: Request, id?: string): Promise<string> {
|
|
try {
|
|
const clone = request.clone();
|
|
const headers = [...clone.headers.entries()].map(([k, v]) => `${k}: ${v}`).join("\n");
|
|
|
|
let body = "";
|
|
try {
|
|
const contentType = clone.headers.get("content-type");
|
|
if (contentType?.includes("application/json")) {
|
|
body = toJson(fromJson(await clone.text()), undefined, 2);
|
|
} else if (clone.body) {
|
|
body = await clone.text();
|
|
}
|
|
} catch (_e) {
|
|
body = "(unable to parse body)";
|
|
}
|
|
|
|
const title = id ? `### Request ${id} ###\n` : "";
|
|
const firstLine = `${title}${request.method} ${request.url.toString()} HTTP/1.1`;
|
|
|
|
return `\n${firstLine}\n${headers}\n\n${body || "(no body)"}\n`;
|
|
} catch (e) {
|
|
return `Error formatting request: ${e}`;
|
|
}
|
|
}
|
|
|
|
async function formatHttpResponse(response: Response, id?: string): Promise<string> {
|
|
try {
|
|
const clone = response.clone();
|
|
const headers = [...clone.headers.entries()].map(([k, v]) => `${k}: ${v}`).join("\n");
|
|
|
|
let body = "";
|
|
try {
|
|
const contentType = clone.headers.get("content-type");
|
|
if (contentType?.includes("application/json")) {
|
|
body = toJson(fromJson(await clone.text()), undefined, 2);
|
|
} else if (clone.body) {
|
|
body = await clone.text();
|
|
}
|
|
} catch (_e) {
|
|
body = "(unable to parse body)";
|
|
}
|
|
|
|
const title = id ? `### Response for ${id} ###\n` : "";
|
|
const firstLine = `${title}HTTP/1.1 ${response.status} ${response.statusText}`;
|
|
|
|
return `\n${firstLine}\n${headers}\n\n${body || "(no body)"}\n`;
|
|
} catch (e) {
|
|
return `Error formatting response: ${e}`;
|
|
}
|
|
}
|
|
|
|
class MockServerPool {
|
|
private servers: MockServer[] = [];
|
|
|
|
public createServer(options?: Partial<MockServerOptions>): MockServer {
|
|
const baseUrl = options?.baseUrl || randomBaseUrl();
|
|
const server = new MockServer({ baseUrl, server: mswServer });
|
|
this.servers.push(server);
|
|
return server;
|
|
}
|
|
|
|
public getServers(): MockServer[] {
|
|
return [...this.servers];
|
|
}
|
|
|
|
public listen(): void {
|
|
const onUnhandledRequest = process.env.LOG_LEVEL === "debug" ? "warn" : "bypass";
|
|
mswServer.listen({ onUnhandledRequest });
|
|
|
|
if (process.env.LOG_LEVEL === "debug") {
|
|
mswServer.events.on("request:start", async ({ request, requestId }) => {
|
|
const formattedRequest = await formatHttpRequest(request, requestId);
|
|
console.debug(`request:start\n${formattedRequest}`);
|
|
});
|
|
|
|
mswServer.events.on("request:unhandled", async ({ request, requestId }) => {
|
|
const formattedRequest = await formatHttpRequest(request, requestId);
|
|
console.debug(`request:unhandled\n${formattedRequest}`);
|
|
});
|
|
|
|
mswServer.events.on("response:mocked", async ({ request, response, requestId }) => {
|
|
const formattedResponse = await formatHttpResponse(response, requestId);
|
|
console.debug(`response:mocked\n${formattedResponse}`);
|
|
});
|
|
}
|
|
}
|
|
|
|
public close(): void {
|
|
this.servers = [];
|
|
mswServer.close();
|
|
}
|
|
}
|
|
|
|
export const mockServerPool = new MockServerPool();
|