74 lines
3.8 KiB
TypeScript
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");
|