100 lines
3.4 KiB
TypeScript
100 lines
3.4 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { mkdtempSync, statSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { X509Certificate } from "node:crypto";
|
|
import {
|
|
createLocalServicesHandler,
|
|
ensureLocalCertificate,
|
|
startLocalServices,
|
|
} from "../src/services.ts";
|
|
|
|
describe("local production service simulator", () => {
|
|
test("simulates bounded mail, cache, storage, auth and health APIs", async () => {
|
|
const handler = createLocalServicesHandler();
|
|
expect((await handler(new Request("http://local/healthz"))).status).toBe(200);
|
|
expect(
|
|
(
|
|
await handler(
|
|
new Request("http://local/mail", {
|
|
method: "POST",
|
|
body: JSON.stringify({ to: "u@test", subject: "Welcome" }),
|
|
}),
|
|
)
|
|
).status,
|
|
).toBe(202);
|
|
expect(await (await handler(new Request("http://local/mail"))).json()).toHaveLength(1);
|
|
await handler(
|
|
new Request("http://local/cache", {
|
|
method: "POST",
|
|
body: JSON.stringify({ key: "user", value: 1 }),
|
|
}),
|
|
);
|
|
expect(await (await handler(new Request("http://local/cache"))).json()).toHaveProperty(
|
|
"user.value",
|
|
1,
|
|
);
|
|
expect(
|
|
(
|
|
await handler(
|
|
new Request("http://local/storage?key=file.txt", { method: "POST", body: "hello" }),
|
|
)
|
|
).status,
|
|
).toBe(201);
|
|
expect(await (await handler(new Request("http://local/storage/file.txt"))).text()).toBe(
|
|
"hello",
|
|
);
|
|
expect(
|
|
(
|
|
await handler(
|
|
new Request("http://local/auth", {
|
|
method: "POST",
|
|
body: JSON.stringify({ email: "u@test" }),
|
|
}),
|
|
)
|
|
).status,
|
|
).toBe(201);
|
|
});
|
|
test("rejects unsafe storage keys and oversized declared JSON", async () => {
|
|
const handler = createLocalServicesHandler();
|
|
expect(
|
|
(
|
|
await handler(
|
|
new Request("http://local/storage?key=../secret", { method: "POST", body: "bad" }),
|
|
)
|
|
).status,
|
|
).toBe(400);
|
|
const response = await handler(
|
|
new Request("http://local/mail", {
|
|
method: "POST",
|
|
body: JSON.stringify({ value: "x".repeat(300_000) }),
|
|
}),
|
|
);
|
|
expect(response.status).toBe(413);
|
|
});
|
|
test("generates and safely reuses a localhost HTTPS certificate", async () => {
|
|
const root = mkdtempSync(join(tmpdir(), "wrnexus-services-cert-"));
|
|
const first = await ensureLocalCertificate(root);
|
|
const certificate = new X509Certificate(first.cert);
|
|
expect(certificate.subjectAltName).toContain("DNS:localhost");
|
|
expect(certificate.subjectAltName).toContain("IP Address:127.0.0.1");
|
|
expect(statSync(first.keyFile).size).toBeGreaterThan(100);
|
|
const second = await ensureLocalCertificate(root);
|
|
expect(second.reused).toBe(true);
|
|
expect(second.cert).toBe(first.cert);
|
|
});
|
|
test("serves the simulator over generated HTTPS", async () => {
|
|
const root = mkdtempSync(join(tmpdir(), "wrnexus-services-tls-"));
|
|
const server = await startLocalServices({ appRoot: root, port: 0, hostname: "127.0.0.1" });
|
|
try {
|
|
const response = await fetch(`https://127.0.0.1:${server.port}/healthz`, {
|
|
tls: { rejectUnauthorized: false },
|
|
});
|
|
expect(response.status).toBe(200);
|
|
expect(await response.json()).toHaveProperty("service", "wrnexus-local-services");
|
|
} finally {
|
|
server.stop(true);
|
|
}
|
|
});
|
|
});
|