Skip to content

Commit f77fa15

Browse files
committed
refactor(ui): consolidates timeInfo memo and adds boundary test
1 parent c8150cf commit f77fa15

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

src/app/components/dashboard/ItemRow.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ export default function ItemRow(props: ItemRowProps) {
3333
const updated = shortRelativeTime(props.updatedAt);
3434
const createdLabel = `Created ${relativeTime(props.createdAt)}`;
3535
const updatedLabel = `Updated ${relativeTime(props.updatedAt)}`;
36-
return { created, updated, createdLabel, updatedLabel };
36+
const createdTitle = `Created: ${new Date(props.createdAt).toLocaleString()}`;
37+
const updatedTitle = `Updated: ${new Date(props.updatedAt).toLocaleString()}`;
38+
const diffMs = Date.parse(props.updatedAt) - Date.parse(props.createdAt);
39+
return { created, updated, createdLabel, updatedLabel, createdTitle, updatedTitle, diffMs };
3740
});
3841
const hasUpdate = createMemo(() => {
39-
const diff = new Date(props.updatedAt).getTime() - new Date(props.createdAt).getTime();
40-
if (diff <= 60_000) return false;
41-
const { created, updated } = timeInfo();
42+
const { diffMs, created, updated } = timeInfo();
43+
if (diffMs <= 60_000) return false;
4244
return created !== "" && updated !== "" && created !== updated;
4345
});
4446

@@ -121,15 +123,15 @@ export default function ItemRow(props: ItemRowProps) {
121123
</Show>
122124
<span class="inline-flex items-center gap-1 whitespace-nowrap">
123125
<span
124-
title={`Created: ${new Date(props.createdAt).toLocaleString()}`}
126+
title={timeInfo().createdTitle}
125127
aria-label={timeInfo().createdLabel}
126128
>
127129
{timeInfo().created}
128130
</span>
129131
<Show when={hasUpdate()}>
130132
<span aria-hidden="true">{"\u00B7"}</span>
131133
<span
132-
title={`Updated: ${new Date(props.updatedAt).toLocaleString()}`}
134+
title={timeInfo().updatedTitle}
133135
aria-label={timeInfo().updatedLabel}
134136
>
135137
{timeInfo().updated}

tests/components/ItemRow.test.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ describe("ItemRow", () => {
4949
// Should show compact format like "2h"
5050
const timeEl = screen.getByTitle(`Created: ${new Date(defaultProps.createdAt).toLocaleString()}`);
5151
expect(timeEl).toBeDefined();
52-
expect(timeEl.textContent).toMatch(/^\d+h$/);
52+
expect(timeEl.textContent).toBe("2h");
5353
});
5454

5555
it("renders children slot when provided", () => {
@@ -198,6 +198,18 @@ describe("ItemRow", () => {
198198
expect(screen.queryByTitle(`Updated: ${new Date("2026-03-30T11:59:30Z").toLocaleString()}`)).toBeNull();
199199
});
200200

201+
it("shows single date when updatedAt is exactly 60s after createdAt", () => {
202+
const { container } = render(() => (
203+
<ItemRow
204+
{...defaultProps}
205+
createdAt="2026-03-30T11:59:00Z"
206+
updatedAt="2026-03-30T12:00:00Z"
207+
/>
208+
));
209+
// diff === 60_000ms, condition is <=, so still suppressed
210+
expect(container.querySelector('span[aria-hidden="true"]')).toBeNull();
211+
});
212+
201213
it("shows single date when both compact values are identical (display-equality guard)", () => {
202214
// Both 3 days ago — createdAt 3d+2min ago, updatedAt exactly 3d ago, both display "3d"
203215
const createdAt = new Date(MOCK_NOW - (3 * 24 * 60 * 60 + 2 * 60) * 1000).toISOString();

0 commit comments

Comments
 (0)