import { describe, it, expect } from "vitest"; import { readFileSync } from "fs"; import { resolve } from "path"; import { extractPdfText, liteLLMExtractor } from "../../lib/intake-extract"; import { reconcileItems, toLineItems, validateHeader } from "../../lib/intake-rules"; /** * Opt-in: the real model over the real Burgertory export. * * INTAKE_LIVE_TEST=1 LITELLM_BASE_URL=http://localhost:4200 LITELLM_KEY=... npm test * * Skipped otherwise — CI has no LiteLLM, and a unit run must not depend on one. * What it proves is the thing the mock cannot: that `cloud-budget` keeps the * names verbatim ("Michael", "Joel", not "Burger") under the order-item prompt. */ const live = process.env.INTAKE_LIVE_TEST === "1" && !!process.env.LITELLM_BASE_URL && !!process.env.LITELLM_KEY; describe.skipIf(!live)("live extraction via LiteLLM (opt-in)", () => { it("Burgertory PDF: header exact, two items named verbatim, reconciles", async () => { const text = await extractPdfText(readFileSync(resolve(__dirname, "../fixtures/intake/ubereats-burgertory-2026-08-19.pdf"))); const extracted = await liteLLMExtractor()([{ kind: "text", text, name: "Receipt_19Aug2026.pdf" }]); const header = validateHeader(extracted); expect(header.ok && header.header).toEqual({ merchant: "Burgertory (Werribee)", order_date: "2026-08-19", total: 22.4 }); const items = toLineItems(extracted.items); expect(items.map((i) => i.description)).toEqual(["Michael", "Joel"]); expect(reconcileItems(extracted).ok).toBe(true); }, 120_000); it("Coles PDF: header exact, 15 items", async () => { const text = await extractPdfText(readFileSync(resolve(__dirname, "../fixtures/intake/ubereats-coles-2026-08-18.pdf"))); const extracted = await liteLLMExtractor()([{ kind: "text", text, name: "Receipt_18Aug2026.pdf" }]); const header = validateHeader(extracted); expect(header.ok && header.header).toEqual({ merchant: "Coles (Wyndham Vale)", order_date: "2026-08-18", total: 85.74 }); expect(toLineItems(extracted.items)).toHaveLength(15); expect(reconcileItems(extracted).ok).toBe(true); }, 120_000); });