diff --git a/src/utils/__tests__/format.test.ts b/src/utils/__tests__/format.test.ts index 7fb33ff96..444d79b84 100644 --- a/src/utils/__tests__/format.test.ts +++ b/src/utils/__tests__/format.test.ts @@ -6,6 +6,8 @@ import { formatNumber, formatTokens, formatRelativeTime, + formatRelativeTimeAgo, + formatLogMetadata, } from "../format"; describe("formatFileSize", () => { @@ -153,3 +155,144 @@ describe("formatRelativeTime", () => { expect(formatRelativeTime(date, { now })).toBe("2w ago"); }); }); + +describe("formatRelativeTimeAgo", () => { + const now = new Date("2026-01-15T12:00:00Z"); + + test("formats past date with 'ago' suffix", () => { + const date = new Date("2026-01-15T11:59:30Z"); + const result = formatRelativeTimeAgo(date, { now }); + expect(result).toBe("30s ago"); + }); + + test("formats future date without 'ago' suffix", () => { + const date = new Date("2026-01-15T13:00:00Z"); + const result = formatRelativeTimeAgo(date, { now }); + expect(result).toBe("in 1h"); + }); + + test("formats minutes ago", () => { + const date = new Date("2026-01-15T11:55:00Z"); + const result = formatRelativeTimeAgo(date, { now }); + expect(result).toBe("5m ago"); + }); + + test("formats hours ago", () => { + const date = new Date("2026-01-15T09:00:00Z"); + const result = formatRelativeTimeAgo(date, { now }); + expect(result).toBe("3h ago"); + }); + + test("formats days ago", () => { + const date = new Date("2026-01-13T12:00:00Z"); + const result = formatRelativeTimeAgo(date, { now }); + expect(result).toBe("2d ago"); + }); + + test("handles date equal to now as past", () => { + // date === now, treated as past (not future) + const result = formatRelativeTimeAgo(now, { now }); + expect(result).toBe("0s ago"); + }); + + test("uses numeric always for past dates", () => { + // Should always use numeric format for past dates + const date = new Date("2026-01-15T11:59:00Z"); + const result = formatRelativeTimeAgo(date, { now }); + expect(result).toContain("ago"); + }); + + test("future date does not contain 'ago'", () => { + const date = new Date("2026-01-15T14:00:00Z"); + const result = formatRelativeTimeAgo(date, { now }); + expect(result).not.toContain("ago"); + }); +}); + +describe("formatLogMetadata", () => { + // Use a date very recently in the past so it always shows "Xs ago" or similar + const modified = new Date(Date.now() - 5 * 60 * 1000); // 5 minutes ago + + test("includes relative time and message count", () => { + const result = formatLogMetadata({ + modified, + messageCount: 10, + }); + expect(result).toContain("ago"); + expect(result).toContain("10 messages"); + }); + + test("uses fileSize instead of messageCount when provided", () => { + const result = formatLogMetadata({ + modified, + messageCount: 5, + fileSize: 1536, + }); + expect(result).toContain("1.5KB"); + expect(result).not.toContain("messages"); + }); + + test("includes gitBranch when provided", () => { + const result = formatLogMetadata({ + modified, + messageCount: 3, + gitBranch: "main", + }); + expect(result).toContain("main"); + }); + + test("omits gitBranch when not provided", () => { + const result = formatLogMetadata({ + modified, + messageCount: 3, + }); + // Should not have a dangling separator from missing branch + expect(result).not.toMatch(/^ · | · $/); + }); + + test("includes tag when provided", () => { + const result = formatLogMetadata({ + modified, + messageCount: 3, + tag: "my-tag", + }); + expect(result).toContain("#my-tag"); + }); + + test("includes agentSetting when provided", () => { + const result = formatLogMetadata({ + modified, + messageCount: 3, + agentSetting: "custom-agent", + }); + expect(result).toContain("@custom-agent"); + }); + + test("includes prNumber when provided", () => { + const result = formatLogMetadata({ + modified, + messageCount: 3, + prNumber: 42, + }); + expect(result).toContain("#42"); + }); + + test("includes prRepository with prNumber when both provided", () => { + const result = formatLogMetadata({ + modified, + messageCount: 3, + prNumber: 99, + prRepository: "owner/repo", + }); + expect(result).toContain("owner/repo#99"); + }); + + test("parts are joined with ' · ' separator", () => { + const result = formatLogMetadata({ + modified, + messageCount: 5, + gitBranch: "feat/x", + }); + expect(result).toContain(" · "); + }); +});