import { describe, expect, it, vi } from "vitest"; import type { BobbinContext } from "#lib/api/client.ts"; import type { BlogFeedItem } from "#lib/blog.ts"; import { date, fromBlogFeed, resolveAuthorDids } from "#lib/components/landing/updates/updates.ts"; const lookups = new Map>(); vi.mock("#lib/api/identity.ts", () => ({ resolveMiniDoc: (_ctx: unknown, handle: string) => { const lookup = Promise.withResolvers<{ did: string }>(); lookups.set(handle, lookup); return lookup.promise; } })); const item = (slug: string, extra: Partial = {}): BlogFeedItem => ({ url: `https://tangled.org/blog/${slug}`, title: slug, summary: `${slug} summary`, date_published: "2026-10-01T00:00:00.000Z", ...extra }); describe("fromBlogFeed", () => { it("maps a post to a blog card linking to it", () => { const [card] = fromBlogFeed([ item("bobbin", { image: "https://img/bobbin", authors: [{ name: "Akshay", url: "https://tangled.org/oppi.li" }, { name: "Guest" }] }) ]); expect(card).toEqual({ kind: "blog", id: "https://tangled.org/blog/bobbin", href: "https://tangled.org/blog/bobbin", at: "2026-10-01T00:00:00.000Z", title: "bobbin", authors: [ { name: "Akshay", handle: "oppi.li" }, { name: "Guest", handle: undefined } ], summary: "bobbin summary", image: { src: "https://img/bobbin", alt: "" } }); }); it("leaves out an empty summary and a missing image", () => { const [card] = fromBlogFeed([item("a", { summary: "" })]); expect(card).toMatchObject({ authors: [], summary: undefined, image: undefined }); }); it("keeps every post, tagged or not, up to the count", () => { const items = [item("a", { tags: ["announcement"] }), item("b"), item("c")]; expect(fromBlogFeed(items, 2).map((c) => c.id.split("/").pop())).toEqual(["a", "b"]); }); }); describe("date", () => { it("pads the day", () => expect(date("2026-10-08T12:00:00Z")).toBe("Oct 08, 2026")); }); describe("resolveAuthorDids", () => { it("fills in each author's did as it resolves, leaving the rest as they are", async () => { lookups.clear(); const updates = fromBlogFeed([ item("a", { authors: [ { name: "Fast", url: "https://tangled.org/fast.example" }, { name: "Slow", url: "https://tangled.org/slow.example" }, { name: "Gone", url: "https://tangled.org/gone.example" }, { name: "Nobody" } ] }) ]); resolveAuthorDids({} as BobbinContext, updates); expect([...lookups.keys()]).toEqual(["fast.example", "slow.example", "gone.example"]); lookups.get("fast.example")!.resolve({ did: "did:plc:fast" }); lookups.get("gone.example")!.reject(new Error("not found")); await new Promise((resolve) => setTimeout(resolve)); const [card] = updates; expect(card.kind === "blog" && card.authors.map((author) => author.did)).toEqual([ "did:plc:fast", undefined, undefined, undefined ]); }); });