/* Unit tests for feed covering buildRssFeed; buildJsonFeed. It also guards the documented public contract and regression-sensitive edge cases. Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. RFC-1311: Compass header sweep — declares the feed suite's contract for test-file scaffold coverage. */ import { describe, expect, it } from "vitest"; import { buildJsonFeed, buildRssFeed } from "../feed.ts"; const channel = { title: "Test Feed", url: "https://example.com", description: "A test feed", language: "de", selfUrl: "https://example.com/feed.xml", }; const items = [ { title: "Item 1", url: "https://example.com/1", summary: "Summary 1", publishedAt: "2024-01-01", }, { title: "Item 2", url: "https://example.com/2", summary: "Summary 2", publishedAt: "2024-06-01", }, ]; describe("buildRssFeed", () => { it("produces valid RSS XML", () => { const result = buildRssFeed(channel, items); expect(result).toContain('"); expect(result).toContain("Test Feed"); expect(result).toContain("de"); }); it("sorts items by publishedAt descending", () => { const result = buildRssFeed(channel, items); const item1Idx = result.indexOf("Item 1"); const item2Idx = result.indexOf("Item 2"); expect(item2Idx).toBeLessThan(item1Idx); }); it("escapes XML special characters", () => { const result = buildRssFeed(channel, [ { title: "A & B ", url: "https://example.com/x", summary: "S", publishedAt: "2024-01-01" }, ]); expect(result).toContain("A & B <C>"); }); it("includes atom self link", () => { const result = buildRssFeed(channel, items); expect(result).toContain('href="https://example.com/feed.xml"'); expect(result).toContain('rel="self"'); }); it("derives lastBuildDate from latest item", () => { const result = buildRssFeed(channel, items); expect(result).toContain(""); }); it("omits lastBuildDate for empty feed", () => { const result = buildRssFeed(channel, []); expect(result).not.toContain(""); }); }); describe("buildJsonFeed", () => { it("produces JSON Feed v1.1", () => { const result = buildJsonFeed({ title: "Test Feed", home_page_url: "https://example.com", feed_url: "https://example.com/feed.json", description: "A test feed", language: "de", items, }); const parsed = JSON.parse(result); expect(parsed.version).toBe("https://jsonfeed.org/version/1.1"); expect(parsed.title).toBe("Test Feed"); expect(parsed.items).toHaveLength(2); }); it("sorts items by publishedAt descending", () => { const result = buildJsonFeed({ title: "Test", home_page_url: "https://example.com", feed_url: "https://example.com/feed.json", description: "", language: "de", items, }); const parsed = JSON.parse(result); expect(parsed.items[0].title).toBe("Item 2"); expect(parsed.items[1].title).toBe("Item 1"); }); it("includes date_modified when updatedAt provided", () => { const result = buildJsonFeed({ title: "Test", home_page_url: "https://example.com", feed_url: "https://example.com/feed.json", description: "", language: "de", items: [ { title: "T", url: "https://example.com/1", summary: "S", publishedAt: "2024-01-01", updatedAt: "2024-06-01", }, ], }); const parsed = JSON.parse(result); expect(parsed.items[0].date_modified).toBe("2024-06-01"); }); it("omits items array for empty feed", () => { const result = buildJsonFeed({ title: "Test", home_page_url: "https://example.com", feed_url: "https://example.com/feed.json", description: "", language: "de", items: [], }); const parsed = JSON.parse(result); expect(parsed.items).toBeUndefined(); }); });