mirror of
https://github.com/TautvydasDerzinskas/Thingport.git
synced 2026-10-19 05:10:01 -05:00
48 lines
1.9 KiB
TypeScript
48 lines
1.9 KiB
TypeScript
import type { Server } from "node:http";
|
|
import { Test } from "supertest";
|
|
|
|
// supertest's request(app) listens on port 0 on every interface, then connects to 127.0.0.1 on the
|
|
// port it got. On macOS a wildcard bind succeeds even when another program already holds that port
|
|
// on 127.0.0.1 alone (VS Code helpers and limactl do), and that program takes the connection: the
|
|
// test then gets someone else's reply -- "Parse Error: Expected HTTP/", or a body without the field
|
|
// it expects -- in whichever test happens to draw the port.
|
|
//
|
|
// Binding to 127.0.0.1 itself means the port it's given is free there. That bind is asynchronous,
|
|
// though, and supertest reads the port the moment the request is built, so the bind waits until
|
|
// the request is sent and the port is filled into its URL then.
|
|
const PLACEHOLDER = "127.0.0.1:0";
|
|
|
|
type DeferredTest = InstanceType<typeof Test> & {
|
|
url: string;
|
|
_server?: Server;
|
|
unboundApp?: Server;
|
|
};
|
|
|
|
const proto = Test.prototype as unknown as {
|
|
serverAddress(this: DeferredTest, app: Server, path: string): string;
|
|
end(this: DeferredTest, fn?: (err: unknown, res: unknown) => void): DeferredTest;
|
|
};
|
|
const { serverAddress, end } = proto;
|
|
|
|
proto.serverAddress = function (app, path) {
|
|
if (app.address()) return serverAddress.call(this, app, path);
|
|
this.unboundApp = app;
|
|
return `http://${PLACEHOLDER}${path}`;
|
|
};
|
|
|
|
proto.end = function (fn) {
|
|
const app = this.unboundApp;
|
|
if (!app) return end.call(this, fn);
|
|
this.unboundApp = undefined;
|
|
app.once("error", (err) => fn?.(err, undefined));
|
|
app.listen(0, "127.0.0.1", () => {
|
|
const { port } = app.address() as { port: number };
|
|
// supertest's own field: it closes this server once the response is in.
|
|
// eslint-disable-next-line no-underscore-dangle
|
|
this._server = app;
|
|
this.url = this.url.replace(PLACEHOLDER, `127.0.0.1:${port}`);
|
|
end.call(this, fn);
|
|
});
|
|
return this;
|
|
};
|