Skip to content

Commit 465e9f0

Browse files
JiayuuWangclaude
andauthored
test: add coverage for formatRelativeTimeAgo and formatLogMetadata (#94)
These two exported functions in src/utils/format.ts had no test coverage. formatRelativeTimeAgo wraps formatRelativeTime and forces numeric:'always' for past dates; formatLogMetadata assembles parts (time, branch, size/count, tag, agentSetting, prNumber) into a ' · '-separated string. Added 8 tests for formatRelativeTimeAgo covering past dates, future dates, equal-to-now, and the no-'ago'-for-future invariant. Added 9 tests for formatLogMetadata covering all optional fields and the separator format. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 29db9d9 commit 465e9f0

1 file changed

Lines changed: 143 additions & 0 deletions

File tree

src/utils/__tests__/format.test.ts

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66
formatNumber,
77
formatTokens,
88
formatRelativeTime,
9+
formatRelativeTimeAgo,
10+
formatLogMetadata,
911
} from "../format";
1012

1113
describe("formatFileSize", () => {
@@ -153,3 +155,144 @@ describe("formatRelativeTime", () => {
153155
expect(formatRelativeTime(date, { now })).toBe("2w ago");
154156
});
155157
});
158+
159+
describe("formatRelativeTimeAgo", () => {
160+
const now = new Date("2026-01-15T12:00:00Z");
161+
162+
test("formats past date with 'ago' suffix", () => {
163+
const date = new Date("2026-01-15T11:59:30Z");
164+
const result = formatRelativeTimeAgo(date, { now });
165+
expect(result).toBe("30s ago");
166+
});
167+
168+
test("formats future date without 'ago' suffix", () => {
169+
const date = new Date("2026-01-15T13:00:00Z");
170+
const result = formatRelativeTimeAgo(date, { now });
171+
expect(result).toBe("in 1h");
172+
});
173+
174+
test("formats minutes ago", () => {
175+
const date = new Date("2026-01-15T11:55:00Z");
176+
const result = formatRelativeTimeAgo(date, { now });
177+
expect(result).toBe("5m ago");
178+
});
179+
180+
test("formats hours ago", () => {
181+
const date = new Date("2026-01-15T09:00:00Z");
182+
const result = formatRelativeTimeAgo(date, { now });
183+
expect(result).toBe("3h ago");
184+
});
185+
186+
test("formats days ago", () => {
187+
const date = new Date("2026-01-13T12:00:00Z");
188+
const result = formatRelativeTimeAgo(date, { now });
189+
expect(result).toBe("2d ago");
190+
});
191+
192+
test("handles date equal to now as past", () => {
193+
// date === now, treated as past (not future)
194+
const result = formatRelativeTimeAgo(now, { now });
195+
expect(result).toBe("0s ago");
196+
});
197+
198+
test("uses numeric always for past dates", () => {
199+
// Should always use numeric format for past dates
200+
const date = new Date("2026-01-15T11:59:00Z");
201+
const result = formatRelativeTimeAgo(date, { now });
202+
expect(result).toContain("ago");
203+
});
204+
205+
test("future date does not contain 'ago'", () => {
206+
const date = new Date("2026-01-15T14:00:00Z");
207+
const result = formatRelativeTimeAgo(date, { now });
208+
expect(result).not.toContain("ago");
209+
});
210+
});
211+
212+
describe("formatLogMetadata", () => {
213+
// Use a date very recently in the past so it always shows "Xs ago" or similar
214+
const modified = new Date(Date.now() - 5 * 60 * 1000); // 5 minutes ago
215+
216+
test("includes relative time and message count", () => {
217+
const result = formatLogMetadata({
218+
modified,
219+
messageCount: 10,
220+
});
221+
expect(result).toContain("ago");
222+
expect(result).toContain("10 messages");
223+
});
224+
225+
test("uses fileSize instead of messageCount when provided", () => {
226+
const result = formatLogMetadata({
227+
modified,
228+
messageCount: 5,
229+
fileSize: 1536,
230+
});
231+
expect(result).toContain("1.5KB");
232+
expect(result).not.toContain("messages");
233+
});
234+
235+
test("includes gitBranch when provided", () => {
236+
const result = formatLogMetadata({
237+
modified,
238+
messageCount: 3,
239+
gitBranch: "main",
240+
});
241+
expect(result).toContain("main");
242+
});
243+
244+
test("omits gitBranch when not provided", () => {
245+
const result = formatLogMetadata({
246+
modified,
247+
messageCount: 3,
248+
});
249+
// Should not have a dangling separator from missing branch
250+
expect(result).not.toMatch(/^ · | · $/);
251+
});
252+
253+
test("includes tag when provided", () => {
254+
const result = formatLogMetadata({
255+
modified,
256+
messageCount: 3,
257+
tag: "my-tag",
258+
});
259+
expect(result).toContain("#my-tag");
260+
});
261+
262+
test("includes agentSetting when provided", () => {
263+
const result = formatLogMetadata({
264+
modified,
265+
messageCount: 3,
266+
agentSetting: "custom-agent",
267+
});
268+
expect(result).toContain("@custom-agent");
269+
});
270+
271+
test("includes prNumber when provided", () => {
272+
const result = formatLogMetadata({
273+
modified,
274+
messageCount: 3,
275+
prNumber: 42,
276+
});
277+
expect(result).toContain("#42");
278+
});
279+
280+
test("includes prRepository with prNumber when both provided", () => {
281+
const result = formatLogMetadata({
282+
modified,
283+
messageCount: 3,
284+
prNumber: 99,
285+
prRepository: "owner/repo",
286+
});
287+
expect(result).toContain("owner/repo#99");
288+
});
289+
290+
test("parts are joined with ' · ' separator", () => {
291+
const result = formatLogMetadata({
292+
modified,
293+
messageCount: 5,
294+
gitBranch: "feat/x",
295+
});
296+
expect(result).toContain(" · ");
297+
});
298+
});

0 commit comments

Comments
 (0)