From e261985a485a1e09b4dfb859ce9d9f6d6aeca2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Wed, 8 Jul 2026 22:05:05 +0200 Subject: [PATCH] test(documents): pin contentIndexSource provenance through list/detail/PATCH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cover the new DTO provenance end-to-end against a real Postgres: the index source threads through the list and detail reads, and — the regression the UI wave flagged — survives a metadata PATCH, which now reads the index row rather than returning a stale null source. --- .../documents-content-index.test.ts | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/integration/documents-content-index.test.ts b/tests/integration/documents-content-index.test.ts index 76856c5fc..0436158f3 100644 --- a/tests/integration/documents-content-index.test.ts +++ b/tests/integration/documents-content-index.test.ts @@ -97,6 +97,10 @@ async function routes() { r: Request, c: RouteCtx, ) => Promise, + patchById: byId.PATCH as unknown as ( + r: Request, + c: RouteCtx, + ) => Promise, postIndex: index.POST as unknown as ( r: Request, c: RouteCtx, @@ -191,6 +195,52 @@ describe("document vault — content index (text mode)", () => { }); }); + it("threads contentIndexSource through list + detail and preserves it across a metadata PATCH", async () => { + await seedVaultUser("vault-provenance"); + const { post, get, getById, patchById, postIndex } = await routes(); + + const up = await post(uploadRequest(PNG_1X1, "scan.png", "Vorher")); + const { data: doc } = await up.json(); + + await postIndex( + textIndexRequest(doc.id, "kreatinin natrium kalium werte"), + ctx(doc.id), + ); + + // List surfaces the real provenance (text-ocr here — no provider). + const listed = await get( + new Request("http://localhost/api/documents/inbound"), + ); + const listRow = (await listed.json()).data.documents.find( + (d: { id: string }) => d.id === doc.id, + ); + expect(listRow.hasContentIndex).toBe(true); + expect(listRow.contentIndexSource).toBe("text-ocr"); + + // Detail agrees. + const detail = await getById( + new Request(`http://localhost/api/documents/inbound/${doc.id}`), + ctx(doc.id), + ); + expect((await detail.json()).data.contentIndexSource).toBe("text-ocr"); + + // Regression (the UI wave flagged this): a metadata PATCH must return the + // index provenance from the freshly-read index row, not a stale null. + const patched = await patchById( + new Request(`http://localhost/api/documents/inbound/${doc.id}`, { + method: "PATCH", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ title: "Nachher" }), + }), + ctx(doc.id), + ); + expect(patched.status).toBe(200); + const patchedBody = (await patched.json()).data; + expect(patchedBody.title).toBe("Nachher"); + expect(patchedBody.hasContentIndex).toBe(true); + expect(patchedBody.contentIndexSource).toBe("text-ocr"); + }); + it("re-indexing the same document is idempotent (upsert in place)", async () => { await seedVaultUser("vault-reindex"); const { post, postIndex } = await routes();