import { describe, expect, it } from "bun:test"; import { parseAppcastItems } from "./_appcast"; // The /changelog page renders exactly what the Sparkle updater receives, so // the parser's contract is the appcast's contract: newest-first items, a // shortVersionString title with the raw as fallback, CDATA and // plain-encoded descriptions both accepted, garbage in → empty list out. const item = (over: Record<string, string>) => ` <item> <title>Version ${over.title ?? "1.0.0"} ${over.short ? `${over.short}` : ""} ${over.build ? `${over.build}` : ""} ${over.date ? `${over.date}` : ""} ${over.desc ?? `
  • Fixes
  • ]]>
    `} `; describe("parseAppcastItems", () => { it("parses newest-first items with version, build, date and CDATA notes", () => { const xml = ` ${item({ title: "1.2.0", short: "1.2.0", build: "42", date: "Sat, 03 Oct 2026 12:00:00 +0000" })} ${item({ title: "1.1.0", short: "1.1.0", build: "41", date: "Fri, 02 Oct 2026 12:00:00 +0000" })} `; const releases = parseAppcastItems(xml); expect(releases.length).toBe(2); expect(releases[0].version).toBe("1.2.0"); expect(releases[0].build).toBe("42"); expect(releases[0].date).toContain("03 Oct 2026"); expect(releases[0].notesHtml).toBe(""); expect(releases[1].version).toBe("1.1.0"); }); it("falls back to the plain title when shortVersionString is absent", () => { const xml = `${item({ title: "1.0.0" })}`; const releases = parseAppcastItems(xml); expect(releases[0].version).toBe("1.0.0"); expect(releases[0].build).toBeNull(); }); it("accepts non-CDATA escaped-HTML descriptions", () => { const xml = ` ${item({ desc: "<p>Hello</p>" })} `; expect(parseAppcastItems(xml)[0].notesHtml).toBe("

    Hello

    "); }); it("returns [] for empty, non-XML, or item-less input", () => { expect(parseAppcastItems("")).toEqual([]); expect(parseAppcastItems("not an appcast")).toEqual([]); expect(parseAppcastItems("")).toEqual([]); }); it("skips items with no version signal at all", () => { const xml = ` orphan

    ]]>
    ${item({ title: "1.0.0" })}
    `; const releases = parseAppcastItems(xml); expect(releases.length).toBe(1); expect(releases[0].version).toBe("1.0.0"); }); });