Files
dockhand-upstream/tests/format-relative-time.test.ts
T

71 lines
2.6 KiB
TypeScript

/**
* formatRelativeTime — compact "N ago" formatting with null/NaN/future safety.
* Pure function in the import-light utils/format module (stores/settings re-exports it).
*
* Run with: bun test tests/unit/format-relative-time.test.ts
*/
import { describe, test, expect } from 'bun:test';
import { formatRelativeTime } from '../src/lib/utils/format';
// Build a timestamp `n` seconds in the past relative to now, so the tests are
// independent of the wall clock (no fixed dates that drift into other buckets).
const agoSec = (s: number) => new Date(Date.now() - s * 1000);
const MIN = 60, HR = 3600, DAY = 86400;
describe('formatRelativeTime — buckets', () => {
test('under 45s reads "just now"', () => {
expect(formatRelativeTime(agoSec(0))).toBe('just now');
expect(formatRelativeTime(agoSec(44))).toBe('just now');
});
test('45s..59s rounds into minutes ("1m ago")', () => {
// 45s -> round(45/60)=1 min
expect(formatRelativeTime(agoSec(45))).toBe('1m ago');
});
test('minutes bucket (< 60m)', () => {
expect(formatRelativeTime(agoSec(5 * MIN))).toBe('5m ago');
expect(formatRelativeTime(agoSec(59 * MIN))).toBe('59m ago');
});
test('hours bucket (< 24h)', () => {
expect(formatRelativeTime(agoSec(2 * HR))).toBe('2h ago');
expect(formatRelativeTime(agoSec(23 * HR))).toBe('23h ago');
});
test('days bucket (< 30d)', () => {
expect(formatRelativeTime(agoSec(3 * DAY))).toBe('3d ago');
expect(formatRelativeTime(agoSec(29 * DAY))).toBe('29d ago');
});
test('months bucket (< 12mo)', () => {
expect(formatRelativeTime(agoSec(60 * DAY))).toBe('2mo ago');
expect(formatRelativeTime(agoSec(300 * DAY))).toBe('10mo ago');
});
test('years bucket', () => {
expect(formatRelativeTime(agoSec(400 * DAY))).toBe('1y ago');
expect(formatRelativeTime(agoSec(800 * DAY))).toBe('2y ago');
});
});
describe('formatRelativeTime — input forms & edges', () => {
test('accepts a Date, an ISO string, and an epoch-ms number equivalently', () => {
const d = agoSec(5 * MIN);
expect(formatRelativeTime(d)).toBe('5m ago');
expect(formatRelativeTime(d.toISOString())).toBe('5m ago');
expect(formatRelativeTime(d.getTime())).toBe('5m ago');
});
test('a future timestamp reads "in the future"', () => {
expect(formatRelativeTime(new Date(Date.now() + 60_000))).toBe('in the future');
});
test('an unparseable / NaN date returns empty string (no crash)', () => {
expect(formatRelativeTime('garbage')).toBe('');
expect(formatRelativeTime(new Date('not-a-date'))).toBe('');
expect(formatRelativeTime(NaN)).toBe('');
expect(formatRelativeTime(undefined as unknown as string)).toBe('');
});
});