import { afterEach, describe, expect, it } from "bun:test"; import { mkdtempSync, rmSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; import { reseedDatabase } from "../src/database"; import { createServer } from "../src/index"; let tempDir: string | null = null; function createTestServer() { tempDir = mkdtempSync(join(tmpdir(), "mock-task-api-http-")); const db = reseedDatabase(join(tempDir, "test.sqlite")); return createServer(db); } async function readJson(response: Response) { return (await response.json()) as Record; } afterEach(() => { if (tempDir) { rmSync(tempDir, { recursive: true, force: true }); tempDir = null; } }); describe("mock task API", () => { it("serves a health endpoint", async () => { const server = createTestServer(); const response = await server.fetch(new Request("http://mock.local/health")); const body = await readJson(response); expect(response.status).toBe(200); expect(body.status).toBe("ok"); }); it("lists organizations", async () => { const server = createTestServer(); const response = await server.fetch(new Request("http://mock.local/orgs")); const body = await readJson(response); expect(response.status).toBe(200); expect(Array.isArray(body.organizations)).toBe(true); expect((body.organizations as unknown[]).length).toBe(3); }); it("filters tasks by org and status", async () => { const server = createTestServer(); const response = await server.fetch( new Request("http://mock.local/tasks?orgId=org_acme&status=blocked"), ); const body = await readJson(response); const tasks = body.tasks as Array>; expect(response.status).toBe(200); expect(tasks.length).toBe(1); expect(tasks[0]?.id).toBe("task_1003"); }); it("creates a task through the HTTP contract", async () => { const server = createTestServer(); const response = await server.fetch( new Request("http://mock.local/tasks", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ orgId: "org_acme", projectId: "proj_acme_ops", title: "Run API smoke test", priority: "low", }), }), ); const body = await readJson(response); expect(response.status).toBe(201); expect((body.task as Record).title).toBe("Run API smoke test"); }); it("updates a task through the HTTP contract", async () => { const server = createTestServer(); const response = await server.fetch( new Request("http://mock.local/tasks/task_1001", { method: "PATCH", headers: { "content-type": "application/json" }, body: JSON.stringify({ status: "done", assigneeUserId: null, }), }), ); const body = await readJson(response); expect(response.status).toBe(200); expect((body.task as Record).status).toBe("done"); expect((body.task as Record).assigneeUserId).toBeNull(); }); it("returns a valid openapi document at the import path", async () => { const server = createTestServer(); const response = await server.fetch(new Request("http://mock.local/openapi.json")); const body = await readJson(response); const paths = body.paths as Record; expect(response.status).toBe(200); expect(body.openapi).toBe("3.1.0"); expect(paths["/tasks"]).toBeDefined(); expect(paths["/orgs/{orgId}/tasks"]).toBeDefined(); }); it("supports the swagger alias path used by import tools", async () => { const server = createTestServer(); const response = await server.fetch(new Request("http://mock.local/swagger.json")); expect(response.status).toBe(200); }); });