import { describe, expect, it } from "bun:test"; import { extractContentFromCompletionBody, isLikelyTruncatedJson, parseAiJsonResponse, stripReasoningBlocks, } from "../parse-response"; describe("stripReasoningBlocks", () => { it("removes closed redacted_thinking blocks", () => { const input = "plan\n{\"ok\":true}"; expect(stripReasoningBlocks(input)).toBe('{"ok":true}'); }); it("removes think blocks", () => { const input = ["<", "think", ">planning\n", '{"ok":true}'].join(""); expect(stripReasoningBlocks(input)).toBe('{"ok":true}'); }); it("removes unclosed thinking at start", () => { const input = "still streaming..."; expect(stripReasoningBlocks(input)).toBe(""); }); it("does not treat XML-like tags in JSON as reasoning", () => { const input = '{"questionText":"highlight"}'; expect(stripReasoningBlocks(input)).toBe(input); }); }); describe("parseAiJsonResponse", () => { it("parses JSON after reasoning preamble", () => { const parsed = parseAiJsonResponse( "planning\n```json\n{\"questions\":[]}\n```", ); expect(parsed).toEqual({ questions: [] }); }); it("extracts JSON object embedded in prose", () => { const parsed = parseAiJsonResponse( "Here is the result:\n{\"questions\":[{\"format\":\"multiple_choice\"}]}\nThanks!", ); expect(parsed).toEqual({ questions: [{ format: "multiple_choice" }] }); }); it("throws on empty content after stripping", () => { expect(() => parseAiJsonResponse("only thinking")).toThrow( "Empty response from AI", ); }); it("detects truncated JSON and throws a clear truncation error", () => { const truncated = '{"title":"The Global Rise of Coffee Culture","passage":"Coffee has a rich history in the highl'; expect(isLikelyTruncatedJson(truncated)).toBe(true); expect(() => parseAiJsonResponse(truncated)).toThrow("JSON response was truncated"); }); }); describe("extractContentFromCompletionBody", () => { it("reads non-stream chat completion JSON", () => { const body = JSON.stringify({ choices: [{ message: { content: '{"questions":[]}' } }], }); expect(extractContentFromCompletionBody(body)).toBe('{"questions":[]}'); }); it("returns null for non-JSON bodies", () => { expect(extractContentFromCompletionBody("error")).toBeNull(); }); });