diff --git a/src/server.test.ts b/src/server.test.ts index ed51df3..006d716 100644 --- a/src/server.test.ts +++ b/src/server.test.ts @@ -3,6 +3,9 @@ import { after, describe, it } from "node:test"; import { buildApp } from "./server.js"; import { setServers } from "node:dns"; +import { allowedNodeEnvironmentFlags } from "node:process"; +import { unescape } from "node:querystring"; +import { error } from "node:console"; describe("API endpoints", () => { const app = buildApp(); @@ -212,4 +215,85 @@ describe("API endpoints", () => { }); assert.equal(response.body.includes("Sensitive internal detail"), false); }); + + it("POST /documents ingests a valid document", async () => { + const app = buildApp(undefined, undefined, async (document) => { + assert.equal(document.title, "Test document"); + assert.equal(document.source, "unit-test"); + assert.equal(document.content, "Document content."); + return { documentId: "42", chunkCount: 1 }; + }); + + try { + const response = await app.inject({ + method: "POST", + url: "/documents", + payload: { + title: "Test document", + source: "unit-test", + content: "Document content.", + }, + }); + + assert.equal(response.statusCode, 201); + assert.deepEqual(response.json(), { + documentId: "42", + chunkCount: 1, + }); + } finally { + await app.close(); + } + }); + + it("POST / documents rejects invalid input", async () => { + const app = buildApp(undefined, undefined, async () => { + throw new Error("Ingestions should not run"); + }); + + try { + const response = await app.inject({ + method: "POST", + url: "/documents", + payload: { + title: " ", + content: "Document content.", + }, + }); + + assert.equal(response.statusCode, 400); + assert.deepEqual(response.json(), { + error: "Invalid document", + }); + } finally { + await app.close(); + } + }); + + it("POST /documents returns 503 when ingestion fails", async () => { + const app = buildApp(undefined, undefined, async () => { + throw new Error("Database connection details"); + }); + + try { + const response = await app.inject({ + method: "POST", + url: "/documents", + payload: { + title: "Test document", + content: "Document content.", + }, + }); + + assert.equal(response.statusCode, 503); + assert.deepEqual(response.json(), { + error: "Document ingestion failed", + }); + assert.equal( + response.body.includes("Database connection details"), + false, + ); + } finally { + await app.close(); + } + }); }); diff --git a/src/server.ts b/src/server.ts index 07b96c1..8c473d7 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,7 +1,7 @@ import Fastify, { type FastifyError } from "fastify"; import { z } from "zod"; -import { ingestDocument } from "./ingestion.js"; +import { ingestDocument as ingestDocumentDefault } from "./ingestion.js"; import { checkOllamaHealth, generateResponse } from "./ollama.js"; const echoSchema = z.object({ @@ -10,13 +10,14 @@ const echoSchema = z.object({ const documentSchema = z.object({ title: z.string().trim().min(1).max(200), - source: z.string().trim().max(2_00).optional(), + source: z.string().trim().max(2_000).optional(), content: z.string().trim().min(1).max(100_000), }); export const buildApp = ( generate = generateResponse, checkHealth = checkOllamaHealth, + ingest = ingestDocumentDefault, ) => { const app = Fastify({ logger: true, @@ -112,7 +113,7 @@ export const buildApp = ( } try { - const document = await ingestDocument(result.data); + const document = await ingest(result.data); return reply.code(201).send(document); } catch (error) {