Add focused Course and Matchmaking route tests

This commit is contained in:
-Puter
2026-07-13 20:12:59 +05:30
parent 7a0c762fde
commit a1e05b0337
2 changed files with 50 additions and 3 deletions
+45
View File
@@ -0,0 +1,45 @@
import assert from "node:assert/strict";
import { serviceRoutes } from "../src/routes/services.js";
const originalFetch = globalThis.fetch;
const calls: Array<{ url: string; body: Record<string, unknown> }> = [];
globalThis.fetch = (async (input, init) => {
const body = JSON.parse(String(init?.body ?? "{}")) as Record<string, unknown>;
calls.push({ url: String(input), body });
return new Response(JSON.stringify({ task_id: "a2a-task", status: "completed", messages: [] }), { status: 200, headers: { "content-type": "application/json" } });
}) as typeof fetch;
const recorded: Array<Record<string, unknown>> = [];
const recordEvent = async (input: Record<string, unknown>) => {
recorded.push(input);
return { id: "event-test" } as never;
};
const app = serviceRoutes({ skipAuth: true, recordEvent: recordEvent as never });
try {
const courseResponse = await app.request("http://backend.test/courses/a2a?missionId=mission-1&missionInstanceId=instance-1&stageId=stage-1&curatorTaskId=task-1", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ action: "record_swipe", params: { video_id: "video-1" } }),
});
assert.equal(courseResponse.status, 200);
assert.ok(calls[0]?.url.endsWith("/a2a/tasks"));
assert.equal(calls[0]?.body.user_id, "user_test");
const courseParams = calls[0]?.body.params as Record<string, unknown>;
assert.equal(courseParams.missionId, "mission-1");
assert.equal(courseParams.curatorTaskId, "task-1");
assert.equal(recorded.length, 1);
assert.equal((recorded[0].mission as Record<string, unknown>).missionId, "mission-1");
recorded.length = 0;
calls.length = 0;
const matchmakingResponse = await app.request("http://backend.test/matchmaking/a2a", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ action: "mark_applied", params: { opportunity_id: "job-1" } }),
});
assert.equal(matchmakingResponse.status, 200);
assert.ok(calls[0]?.url.endsWith("/a2a/tasks"));
assert.equal(recorded.length, 0, "matchmaking service owns canonical event emission");
} finally {
globalThis.fetch = originalFetch;
}
console.log("course-matchmaking HTTP route tests passed");
+5 -3
View File
@@ -755,9 +755,11 @@ async function proxySocialRequest(req: Request, rest: string, userId: string) {
});
}
export function serviceRoutes() {
export function serviceRoutes(options: { skipAuth?: boolean; recordEvent?: typeof recordGatewayEvent } = {}) {
const app = new Hono<AuthContext>();
app.use("*", requireUser);
if (!options.skipAuth) app.use("*", requireUser);
const recordEvent = options.recordEvent ?? recordGatewayEvent;
if (options.skipAuth) app.use("*", async (c, next) => { c.set("userId", "user_test"); c.set("userEmail", "user_test@example.com"); await next(); });
app.get("/catalog", (c) => c.json({ services: listServiceCapabilities({ public: true }) }));
@@ -1072,7 +1074,7 @@ export function serviceRoutes() {
params: { ...missionParams, ...params },
});
const event = buildCourseGatewayEvent({ userId, action, body: { ...body, params: { ...missionParams, ...params } }, result: result as Record<string, unknown> });
await recordGatewayEvent({
await recordEvent({
userId,
source: event.source,
type: event.type,