From 7321acdde6821e2be9d0745a33a50d8235f68de1 Mon Sep 17 00:00:00 2001 From: Cesar Alcazar Date: Mon, 19 Oct 2026 22:14:17 -0600 Subject: [PATCH] 8zbhzr21j: Read the video duration from videoDuration and test its m:ss format --- src/dev/fixtures.ts | 2 +- src/lib/feed-model.ts | 2 +- tests/feed-view.test.ts | 20 +++++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/dev/fixtures.ts b/src/dev/fixtures.ts index 3defd88..2794d42 100644 --- a/src/dev/fixtures.ts +++ b/src/dev/fixtures.ts @@ -86,7 +86,7 @@ export const FIXTURE_FEED_ITEMS: unknown[] = [ id: "p3", content: "A short walkthrough of how we run weekly reviews with a remote team.", author: author("a3", "Marcus Bell"), - mediaItems: [{ mediaType: "video", thumbnailUrl: placeholderImage(210, "Weekly reviews"), mp4Url: FIXTURE_VIDEO_URL, durationSeconds: 154, order: 0 }], + mediaItems: [{ mediaType: "video", thumbnailUrl: placeholderImage(210, "Weekly reviews"), mp4Url: FIXTURE_VIDEO_URL, videoDuration: 154, order: 0 }], }, }, { diff --git a/src/lib/feed-model.ts b/src/lib/feed-model.ts index 7a07bf4..74b2e5a 100644 --- a/src/lib/feed-model.ts +++ b/src/lib/feed-model.ts @@ -104,7 +104,7 @@ function toMedia(raw: unknown): CardMedia[] { const hls = muxHlsUrl(m.hlsUrl); const mp4 = feedMp4Url(m.mp4Url); // Keep a video even with no thumbnail or playable URL yet (just published). - const dur = typeof m.durationSeconds === "number" ? m.durationSeconds : typeof m.duration === "number" ? m.duration : null; + const dur = [m.videoDuration, m.durationSeconds, m.duration].find((v): v is number => typeof v === "number" && v > 0) ?? null; out.push({ kind: "video", src: thumb, hlsUrl: hls, mp4Url: mp4, ...(dur ? { durationSeconds: dur } : {}) }); continue; } diff --git a/tests/feed-view.test.ts b/tests/feed-view.test.ts index 48bcfbb..a82437d 100644 --- a/tests/feed-view.test.ts +++ b/tests/feed-view.test.ts @@ -3,7 +3,7 @@ import { createElement } from "react"; import { renderToStaticMarkup } from "react-dom/server"; import { FeedView, type FeedViewProps } from "@/components/FeedView"; import { fetchFeedPage, FeedLoadError } from "@/lib/feed-client"; -import { mergePosts, relativeTime, toCardPosts, upgradeVideos } from "@/lib/feed-model"; +import { formatDuration, mergePosts, relativeTime, toCardPost, toCardPosts, upgradeVideos } from "@/lib/feed-model"; const NOW = Date.parse("2026-10-19T12:00:00Z"); const post = (id: string, publishedAt: string, extra: Record = {}) => ({ @@ -185,3 +185,21 @@ describe("video transcoding", () => { expect(live).toContain(" { + it("reads videoDuration (seconds) first and formats it as m:ss", () => { + const [m] = toCardPost({ type: "post", post: { id: "v", author: {}, mediaItems: [{ mediaType: "video", videoDuration: 154, duration: 9 }] } })!.media; + expect(m.durationSeconds).toBe(154); + expect(formatDuration(154)).toBe("2:34"); + expect(formatDuration(5)).toBe("0:05"); + expect(formatDuration(3725)).toBe("1:02:05"); + expect(formatDuration(0)).toBeNull(); + expect(formatDuration(undefined)).toBeNull(); + }); + it("falls back to durationSeconds, then duration, else none", () => { + const dur = (item: object) => toCardPost({ type: "post", post: { id: "v", author: {}, mediaItems: [{ mediaType: "video", ...item }] } })!.media[0].durationSeconds; + expect(dur({ durationSeconds: 30 })).toBe(30); + expect(dur({ duration: 12 })).toBe(12); + expect(dur({})).toBeUndefined(); + }); +});