1
0
Fork 0
docsearch/packages/docsearch-react/src/hooks/__tests__/useRelativeFormattedDate.test.tsx
Paul Jankowski 0da291bb95
feat(v5): UI updates (#2896)
* feat(v5): UI updates

* fix: css file size

* fix: e2e tests

* fix: e2e tests

* fix: e2e tests

* chore: add theme toggle to react demo example

* Update sources panel display, update dark theme

* fix: lint

* fix(askai): address ui review feedback

* fix: pin icon positioning

* fix(askai): improve a11y and dark-mode shimmer for thinking and error states

- add role=alert/status and aria-hidden on error/thinking UI
- support dark-mode shimmer gradients via CSS variables
- respect prefers-reduced-motion for shimmer
- handle null date in useRelativeFormattedDate with fallback translation
2026-06-11 12:51:22 -04:00

136 lines
4.4 KiB
TypeScript

import { renderHook } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { useRelativeFormattedDate } from '../useRelativeFormattedDate';
const NOW = new Date('2024-01-15T12:00:00.000Z').getTime();
describe('useRelativeFormattedDate', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.setSystemTime(NOW);
});
afterEach(() => {
vi.useRealTimers();
});
it('returns days when elapsed time is at least one day', () => {
const start = new Date(NOW - 3 * 24 * 60 * 60 * 1000);
const { result } = renderHook(() => useRelativeFormattedDate(start));
expect(result.current).toEqual('3 days ago');
});
it('returns hours when elapsed time is at least one hour but less than a day', () => {
const start = new Date(NOW - 5 * 60 * 60 * 1000);
const { result } = renderHook(() => useRelativeFormattedDate(start));
expect(result.current).toEqual('5 hours ago');
});
it('returns minutes when elapsed time is at least one minute but less than an hour', () => {
const start = new Date(NOW - 42 * 60 * 1000);
const { result } = renderHook(() => useRelativeFormattedDate(start));
expect(result.current).toEqual('42 minutes ago');
});
it('returns seconds when elapsed time is at least one second but less than a minute', () => {
const start = new Date(NOW - 30 * 1000);
const { result } = renderHook(() => useRelativeFormattedDate(start));
expect(result.current).toEqual('30 seconds ago');
});
it('falls back to seconds for sub-second differences', () => {
const start = new Date(NOW - 500);
const { result } = renderHook(() => useRelativeFormattedDate(start));
expect(result.current).toEqual('0 seconds ago');
});
it('returns zero seconds when start and end are equal', () => {
const start = new Date(NOW);
const { result } = renderHook(() => useRelativeFormattedDate(start));
expect(result.current).toEqual('0 seconds ago');
});
it('returns null when start is null', () => {
const { result } = renderHook(() => useRelativeFormattedDate(null));
expect(result.current).toBeNull();
});
it('floors the elapsed value to the unit', () => {
// 2 hours and 59 minutes -> 2 hours
const start = new Date(NOW - (2 * 60 * 60 * 1000 + 59 * 60 * 1000));
const { result } = renderHook(() => useRelativeFormattedDate(start));
expect(result.current).toEqual('2 hours ago');
});
it('uses the largest matching unit at boundaries', () => {
// Exactly one day
const start = new Date(NOW - 24 * 60 * 60 * 1000);
const { result } = renderHook(() => useRelativeFormattedDate(start));
expect(result.current).toEqual('1 day ago');
});
it('uses the absolute value when end is before start (future dates)', () => {
const start = new Date(NOW + 3 * 60 * 60 * 1000);
const { result } = renderHook(() => useRelativeFormattedDate(start));
expect(result.current).toEqual('3 hours ago');
});
it('respects an explicit end value over Date.now()', () => {
const start = new Date('2024-01-01T00:00:00.000Z');
const end = new Date('2024-01-08T00:00:00.000Z').getTime();
const { result } = renderHook(() => useRelativeFormattedDate(start, end));
expect(result.current).toEqual('7 days ago');
});
it('returns a stable reference when inputs do not change', () => {
const start = new Date(NOW - 60 * 60 * 1000);
const end = NOW;
const { result, rerender } = renderHook(() => useRelativeFormattedDate(start, end));
const first = result.current;
rerender();
expect(result.current).toBe(first);
});
it('does not recompute when inputs change', () => {
const end = NOW;
const { result, rerender } = renderHook(({ start }) => useRelativeFormattedDate(start, end), {
initialProps: { start: new Date(NOW - 60 * 60 * 1000) },
});
const first = result.current;
expect(result.current).toEqual('1 hour ago');
rerender({ start: new Date(NOW - 2 * 24 * 60 * 60 * 1000) });
expect(result.current).toBe(first);
expect(result.current).toEqual('1 hour ago');
});
it('does not recompute when Date.now changes', () => {
const start = new Date(NOW - 60 * 60 * 1000);
const { result, rerender } = renderHook(() => useRelativeFormattedDate(start));
const first = result.current;
vi.setSystemTime(NOW + 2 * 24 * 60 * 60 * 1000);
rerender();
expect(result.current).toBe(first);
expect(result.current).toEqual('1 hour ago');
});
});