| |
| |
| |
| |
| |
| |
| |
| |
| import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; |
| import request from "supertest"; |
| import { mkdtempSync, rmSync } from "fs"; |
| import { mkdirSync } from "fs"; |
| import { tmpdir } from "os"; |
| import { join } from "path"; |
| import { setDataDir } from "../src/utils.js"; |
| import { createApp, resetSaveTimers } from "../src/create-app.js"; |
|
|
| let tmpDir: string; |
| let app: ReturnType<typeof createApp>["app"]; |
| let httpServer: ReturnType<typeof createApp>["httpServer"]; |
| let hocuspocus: ReturnType<typeof createApp>["hocuspocus"]; |
|
|
| beforeEach(() => { |
| tmpDir = mkdtempSync(join(tmpdir(), "collab-agent-test-")); |
| mkdirSync(tmpDir, { recursive: true }); |
| setDataDir(tmpDir); |
| const result = createApp(); |
| app = result.app; |
| httpServer = result.httpServer; |
| hocuspocus = result.hocuspocus; |
| }); |
|
|
| afterEach(async () => { |
| resetSaveTimers(); |
| try { await hocuspocus.destroy(); } catch {} |
| try { httpServer.close(); } catch {} |
| setDataDir(undefined); |
| try { rmSync(tmpDir, { recursive: true, force: true }); } catch {} |
| vi.restoreAllMocks(); |
| }); |
|
|
| describe("/api/models", () => { |
| it("returns a non-empty array of models", async () => { |
| const res = await request(app).get("/api/models").expect(200); |
| expect(Array.isArray(res.body)).toBe(true); |
| expect(res.body.length).toBeGreaterThan(0); |
| expect(res.body[0]).toHaveProperty("id"); |
| expect(res.body[0]).toHaveProperty("label"); |
| expect(res.body[0]).toHaveProperty("context"); |
| expect(res.body[0]).toHaveProperty("cost"); |
| }); |
| }); |
|
|
| describe("/api/chat - validation", () => { |
| it("rejects request without messages", async () => { |
| const res = await request(app) |
| .post("/api/chat") |
| .send({ context: {} }) |
| .expect(400); |
|
|
| expect(res.body).toHaveProperty("error"); |
| expect(res.body.error).toContain("messages"); |
| }); |
|
|
| it("rejects request with non-array messages", async () => { |
| const res = await request(app) |
| .post("/api/chat") |
| .send({ messages: "not-an-array" }) |
| .expect(400); |
|
|
| expect(res.body).toHaveProperty("error"); |
| }); |
|
|
| it("returns 500 when no HF token is available", async () => { |
| const original = process.env.HF_TOKEN; |
| delete process.env.HF_TOKEN; |
|
|
| const res = await request(app) |
| .post("/api/chat") |
| .send({ |
| messages: [{ id: "1", role: "user", parts: [{ type: "text", text: "hello" }] }], |
| }) |
| .expect(500); |
|
|
| expect(res.body).toHaveProperty("error"); |
| expect(res.body.error).toContain("Hugging Face token"); |
|
|
| if (original) process.env.HF_TOKEN = original; |
| }); |
| }); |
|
|
| describe("/api/embed-chat - validation", () => { |
| it("rejects request without messages", async () => { |
| const res = await request(app) |
| .post("/api/embed-chat") |
| .send({ context: {} }) |
| .expect(400); |
|
|
| expect(res.body).toHaveProperty("error"); |
| expect(res.body.error).toContain("messages"); |
| }); |
|
|
| it("rejects request with non-array messages", async () => { |
| const res = await request(app) |
| .post("/api/embed-chat") |
| .send({ messages: 42 }) |
| .expect(400); |
|
|
| expect(res.body).toHaveProperty("error"); |
| }); |
|
|
| it("returns 500 when no HF token is available", async () => { |
| const original = process.env.HF_TOKEN; |
| delete process.env.HF_TOKEN; |
|
|
| const res = await request(app) |
| .post("/api/embed-chat") |
| .send({ |
| messages: [{ id: "1", role: "user", parts: [{ type: "text", text: "make a chart" }] }], |
| }) |
| .expect(500); |
|
|
| expect(res.body).toHaveProperty("error"); |
| expect(res.body.error).toContain("Hugging Face token"); |
|
|
| if (original) process.env.HF_TOKEN = original; |
| }); |
| }); |
|
|