Update tests

This commit is contained in:
2026-03-21 10:14:38 +01:00
parent cf010ad4f5
commit d2ddaef0d4
26 changed files with 798 additions and 101 deletions
@@ -0,0 +1 @@
export {};
@@ -0,0 +1,73 @@
import { describe, expect, test, mock, afterAll } from "bun:test";
import bunextRequestHandler from "../../../../src/functions/server/bunext-req-handler";
mock.module("../../../../src/utils/is-development", () => ({
default: () => true
}));
mock.module("../../../../src/utils/grab-constants", () => ({
default: () => ({
config: {
middleware: async ({ url }) => {
if (url.pathname === "/blocked") {
return new Response("Blocked by middleware", { status: 403 });
}
return undefined;
}
}
})
}));
mock.module("../../../../src/functions/server/handle-routes", () => ({
default: async () => new Response("api-routes")
}));
mock.module("../../../../src/functions/server/handle-public", () => ({
default: async () => new Response("public")
}));
mock.module("../../../../src/functions/server/handle-files", () => ({
default: async () => new Response("files")
}));
mock.module("../../../../src/functions/server/web-pages/handle-web-pages", () => ({
default: async () => new Response("web-pages")
}));
/**
* Tests for the `bunext-req-handler` module.
* Ensures that requests are correctly routed to the proper subsystem.
*/
describe("bunext-req-handler", () => {
afterAll(() => {
mock.restore();
});
test("middleware is caught", async () => {
const req = new Request("http://localhost/blocked");
const res = await bunextRequestHandler({ req });
expect(res.status).toBe(403);
expect(await res.text()).toBe("Blocked by middleware");
});
test("routes /__hmr to handleHmr in dev", async () => {
global.ROUTER = { match: () => ({}) };
global.HMR_CONTROLLERS = [];
const req = new Request("http://localhost/__hmr", {
headers: { referer: "http://localhost/" }
});
const res = await bunextRequestHandler({ req });
expect(res.headers.get("Content-Type")).toBe("text/event-stream");
});
test("routes /api/ to handleRoutes", async () => {
const req = new Request("http://localhost/api/users");
const res = await bunextRequestHandler({ req });
expect(await res.text()).toBe("api-routes");
});
test("routes /public/ to handlePublic", async () => {
const req = new Request("http://localhost/public/image.png");
const res = await bunextRequestHandler({ req });
expect(await res.text()).toBe("public");
});
test("routes files like .js to handleFiles", async () => {
const req = new Request("http://localhost/script.js");
const res = await bunextRequestHandler({ req });
expect(await res.text()).toBe("files");
});
test("routes anything else to handleWebPages", async () => {
const req = new Request("http://localhost/about");
const res = await bunextRequestHandler({ req });
expect(await res.text()).toBe("web-pages");
});
});
+1
View File
@@ -0,0 +1 @@
export {};
+37
View File
@@ -0,0 +1,37 @@
import { describe, expect, test, mock, beforeEach, afterEach } from "bun:test";
import handleHmr from "../../../../src/functions/server/handle-hmr";
describe("handle-hmr", () => {
beforeEach(() => {
global.ROUTER = {
match: (path) => {
if (path === "/test")
return { filePath: "/test-file" };
return null;
}
};
global.HMR_CONTROLLERS = [];
global.BUNDLER_CTX_MAP = [
{ local_path: "/test-file" }
];
});
afterEach(() => {
global.ROUTER = undefined;
global.HMR_CONTROLLERS = [];
global.BUNDLER_CTX_MAP = undefined;
});
test("sets up SSE stream and pushes to HMR_CONTROLLERS", async () => {
const req = new Request("http://localhost/hmr", {
headers: {
"referer": "http://localhost/test"
}
});
const res = await handleHmr({ req });
expect(res.status).toBe(200);
expect(res.headers.get("Content-Type")).toBe("text/event-stream");
expect(res.headers.get("Connection")).toBe("keep-alive");
expect(global.HMR_CONTROLLERS.length).toBe(1);
const controller = global.HMR_CONTROLLERS[0];
expect(controller.page_url).toBe("http://localhost/test");
expect(controller.target_map?.local_path).toBe("/test-file");
});
});
@@ -0,0 +1 @@
export {};
+65
View File
@@ -0,0 +1,65 @@
import { describe, expect, test, mock, afterAll } from "bun:test";
import handleRoutes from "../../../../src/functions/server/handle-routes";
mock.module("../../../../src/utils/is-development", () => ({
default: () => false
}));
mock.module("../../../../src/utils/grab-constants", () => ({
default: () => ({ MBInBytes: 1048576, ServerDefaultRequestBodyLimitBytes: 5242880 })
}));
mock.module("../../../../src/utils/grab-router", () => ({
default: () => ({
match: (path) => {
if (path === "/api/test")
return { filePath: "/test-path" };
if (path === "/api/large")
return { filePath: "/large-path" };
return null;
}
})
}));
mock.module("../../../../src/utils/grab-route-params", () => ({
default: async () => ({ params: {}, searchParams: {} })
}));
mock.module("/test-path", () => ({
default: async () => new Response("OK", { status: 200 })
}));
mock.module("/large-path", () => ({
default: async () => new Response("Large OK", { status: 200 }),
config: { maxRequestBodyMB: 1 }
}));
/**
* Tests for routing logic within `handle-routes`.
*/
describe("handle-routes", () => {
afterAll(() => {
mock.restore();
});
test("returns 401 for unknown route", async () => {
const req = new Request("http://localhost/api/unknown");
const res = await handleRoutes({ req });
expect(res.status).toBe(401);
const json = await res.json();
expect(json.success).toBe(false);
expect(json.msg).toContain("not found");
});
test("calls matched module default export", async () => {
const req = new Request("http://localhost/api/test");
const res = await handleRoutes({ req });
expect(res.status).toBe(200);
expect(await res.text()).toBe("OK");
});
test("enforces request body size limits", async () => {
// limit is 1MB from mock config
const req = new Request("http://localhost/api/large", {
method: "POST",
headers: {
"content-length": "2000000" // ~2MB
},
body: "x".repeat(10) // the actual body doesn't matter since handleRoutes only checks the header
});
const res = await handleRoutes({ req });
expect(res.status).toBe(413);
const json = await res.json();
expect(json.success).toBe(false);
});
});
@@ -0,0 +1 @@
export {};
+36
View File
@@ -0,0 +1,36 @@
import { describe, expect, test, mock, afterEach } from "bun:test";
import startServer from "../../../../src/functions/server/start-server";
import { log } from "../../../../src/utils/log";
// Mock log so we don't spam terminal during tests
mock.module("../../../../src/utils/log", () => ({
log: {
server: mock((msg) => { }),
info: mock((msg) => { }),
error: mock((msg) => { }),
}
}));
// Mock grabConfig so it doesn't try to look for bunext.config.ts and exit process
mock.module("../../../../src/functions/grab-config", () => ({
default: async () => ({})
}));
// Mock grabAppPort to return 0 so Bun.serve picks a random port
mock.module("../../../../src/utils/grab-app-port", () => ({
default: () => 0
}));
describe("startServer", () => {
afterEach(() => {
if (global.SERVER) {
global.SERVER.stop(true);
global.SERVER = undefined;
}
});
test("starts the server and assigns to global.SERVER", async () => {
global.CONFIG = { development: true };
const server = await startServer();
expect(server).toBeDefined();
expect(server.port).toBeGreaterThan(0);
expect(global.SERVER).toBe(server);
expect(log.server).toHaveBeenCalled();
server.stop(true);
});
});