diff --git a/apps/web/lib/rss.test.ts b/apps/web/lib/rss.test.ts index 9a453df..ffedd1d 100644 --- a/apps/web/lib/rss.test.ts +++ b/apps/web/lib/rss.test.ts @@ -1,5 +1,6 @@ import { describe, it, expect } from "vitest"; -import { buildRss } from "./rss"; +import { buildRss, mediaCardsToFeed } from "./rss"; +import type { MediaCard } from "./queries"; describe("buildRss", () => { const xml = buildRss({ @@ -37,3 +38,67 @@ describe("buildRss", () => { expect(xml).not.toContain("hello]]>

]]>"); }); }); + +describe("mediaCardsToFeed", () => { + const card = (mediaUrl: string): MediaCard => ({ + id: "media-1", + slug: "photo", + title: "Photo", + description: null, + mediaType: "image", + mediaUrl, + thumbnailUrl: null, + posterUrl: null, + sourceUrl: null, + sourceProvider: null, + truthLabel: "unknown", + truthConfidence: "unverified", + revealStatus: "revealed", + isFeatured: false, + isScoreEligible: true, + createdAt: "2026-01-01T00:00:00.000Z", + approvedAt: "2026-01-01T00:00:00.000Z", + stats: { + aiGuesses: 0, + notAiGuesses: 0, + totalGuesses: 0, + crowdAccuracy: 0, + aiPct: 0, + }, + tags: [], + }); + + const channel = { + title: "Latest", + link: "https://aiornot.vote", + feedUrl: "https://aiornot.vote/rss.xml", + description: "Latest media", + }; + + it("uses the image URL's actual MIME type for RSS enclosures", () => { + const xml = mediaCardsToFeed( + [ + card("https://cdn.example/photo.jpg"), + { ...card("https://cdn.example/generated.webp?width=1200"), id: "media-2", slug: "generated" }, + ], + channel, + ); + + expect(xml).toContain('url="https://cdn.example/photo.jpg" type="image/jpeg"'); + expect(xml).toContain( + 'url="https://cdn.example/generated.webp?width=1200" type="image/webp"', + ); + }); + + it("omits an enclosure when the image MIME type cannot be inferred", () => { + const xml = mediaCardsToFeed( + [card("https://picsum.photos/seed/example/1000/1250")], + channel, + ); + + expect(xml).not.toContain(" ({ - title: m.title, - link: `${env.appUrl}/m/${m.slug}`, - guid: `media:${m.id}`, - pubDate: m.approvedAt || m.createdAt, - descriptionHtml: mediaItemDescription(m), - categories: m.tags.filter((t) => !t.isAnswerSpoiler).map((t) => t.slug), - enclosure: m.mediaType === "image" ? { url: abs(m.mediaUrl), type: "image/webp" } : undefined, - })), + items: cards.map((m) => { + const enclosureType = m.mediaType === "image" ? imageMimeType(m.mediaUrl) : null; + return { + title: m.title, + link: `${env.appUrl}/m/${m.slug}`, + guid: `media:${m.id}`, + pubDate: m.approvedAt || m.createdAt, + descriptionHtml: mediaItemDescription(m), + categories: m.tags.filter((t) => !t.isAnswerSpoiler).map((t) => t.slug), + enclosure: enclosureType ? { url: abs(m.mediaUrl), type: enclosureType } : undefined, + }; + }), }); }