Files
growqr-backend/scripts/artifact-transport.test.ts
2026-07-16 13:19:06 +05:30

74 lines
3.8 KiB
TypeScript

import assert from "node:assert/strict";
import { createServer } from "node:http";
import type { AddressInfo } from "node:net";
import { serviceRoutes } from "../src/routes/services.js";
const originalFetch = globalThis.fetch;
const requests: Request[] = [];
const artifactTypes: Record<string, { mime: string; bytes: number[] }> = {
session_dual_wav: { mime: "audio/wav", bytes: [0x52, 0x49, 0x46, 0x46] },
session_mixed_mp3: { mime: "audio/mpeg", bytes: [0x49, 0x44, 0x33, 0x04] },
session_video: { mime: "video/webm", bytes: [0x1a, 0x45, 0xdf, 0xa3] },
session_video_mp4: { mime: "video/mp4", bytes: [0x00, 0x00, 0x00, 0x18] },
};
const storageServer = createServer((request, response) => {
const artifactType = request.url?.replace(/^\/stored\//, "") ?? "";
const artifact = artifactTypes[artifactType];
if (!artifact) { response.writeHead(404); response.end(); return; }
response.writeHead(200, { "content-type": artifact.mime, "content-length": artifact.bytes.length });
response.end(Buffer.from(artifact.bytes));
});
await new Promise<void>((resolve) => storageServer.listen(0, "127.0.0.1", resolve));
const storagePort = (storageServer.address() as AddressInfo).port;
const storageBaseUrl = `http://127.0.0.1:${storagePort}`;
globalThis.fetch = (async (input, init) => {
const request = new Request(input, init);
requests.push(request);
const path = new URL(request.url).pathname;
const metadataMatch = path.match(/\/api\/v1\/artifacts\/sess-1\/([^/]+)$/);
if (metadataMatch && artifactTypes[metadataMatch[1]]) {
const artifact = artifactTypes[metadataMatch[1]];
return new Response(JSON.stringify({ url: `${storageBaseUrl}/stored/${metadataMatch[1]}`, mime_type: artifact.mime }), { headers: { "content-type": "application/json" } });
}
if (path.startsWith("/stored/")) return originalFetch(input, init);
if (path.endsWith("/api/v1/sessions/sess-1/video/upload-url")) {
return new Response(JSON.stringify({ url: "http://s3.test/put", mime_type: "video/webm" }), { headers: { "content-type": "application/json" } });
}
if (path === "/put") return new Response(null, { status: 200 });
throw new Error(`unexpected upstream ${request.method} ${request.url}`);
}) as typeof fetch;
const app = serviceRoutes({ skipAuth: true });
try {
const artifacts = [
["session_dual_wav", "audio/wav", [0x52, 0x49, 0x46, 0x46], "wav"],
["session_mixed_mp3", "audio/mpeg", [0x49, 0x44, 0x33, 0x04], "mp3"],
["session_video", "video/webm", [0x1a, 0x45, 0xdf, 0xa3], "webm"],
["session_video_mp4", "video/mp4", [0x00, 0x00, 0x00, 0x18], "mp4"],
] as const;
for (const product of ["interview", "roleplay"] as const) {
for (const [artifactType, mime, expectedBytes, extension] of artifacts) {
const download = await app.request(`http://backend.test/${product}/artifacts/sess-1/${artifactType}/download`);
assert.equal(download.status, 200);
const downloadedBytes = new Uint8Array(await download.arrayBuffer());
assert.deepEqual(Array.from(downloadedBytes), expectedBytes);
assert.equal(download.headers.get("content-type"), mime);
assert.match(download.headers.get("content-disposition") ?? "", new RegExp(`^attachment; filename="${artifactType}\\.${extension}"$`));
assert.ok(downloadedBytes.byteLength > 0);
}
const upload = await app.request(`http://backend.test/${product}/sessions/sess-1/video/upload`, { method: "PUT", headers: { "content-type": "video/webm" }, body: new Uint8Array([9, 8, 7]) });
assert.equal(upload.status, 204);
const put = requests.at(-1)!;
assert.equal(put.method, "PUT");
assert.equal(put.headers.get("content-type"), "video/webm");
assert.deepEqual(Array.from(new Uint8Array(await put.arrayBuffer())), [9, 8, 7]);
}
} finally {
globalThis.fetch = originalFetch;
storageServer.close();
}
console.log("artifact transport gateway tests passed");