mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 08:13:50 +00:00
63 lines
3.2 KiB
TypeScript
63 lines
3.2 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import { formatDate } from '../utils';
|
|
import { useSettingsStore } from '@/stores/settings-store';
|
|
|
|
// The list formats every row's date on every render. formatDate keeps its
|
|
// Intl.DateTimeFormat instances instead of building one per call (which each
|
|
// toLocale*String call does), without changing a single output.
|
|
|
|
describe('formatDate formatters', () => {
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
useSettingsStore.setState({ dateFormat: 'smart', timeFormat: '24h', dateLocale: 'auto' });
|
|
});
|
|
|
|
it('builds a formatter once per locale and option set, not once per row', () => {
|
|
useSettingsStore.setState({ dateFormat: 'smart', timeFormat: '12h', dateLocale: 'auto', timeZone: 'Europe/Berlin' });
|
|
const old = new Date(Date.now() - 40 * 86_400_000);
|
|
formatDate(old); // warm
|
|
const Real = Intl.DateTimeFormat;
|
|
let built = 0;
|
|
vi.spyOn(Intl, 'DateTimeFormat').mockImplementation(((...args: ConstructorParameters<typeof Intl.DateTimeFormat>) => {
|
|
built++;
|
|
return new Real(...args);
|
|
}) as never);
|
|
vi.spyOn(Date.prototype, 'toLocaleDateString').mockImplementation(function (this: Date, ...args) { built++; return Real.prototype.format.call(new Real(...args), this); });
|
|
vi.spyOn(Date.prototype, 'toLocaleTimeString').mockImplementation(function (this: Date, ...args) { built++; return Real.prototype.format.call(new Real(...args), this); });
|
|
vi.spyOn(Date.prototype, 'toLocaleString').mockImplementation(function (this: Date, ...args) { built++; return Real.prototype.format.call(new Real(...args), this); });
|
|
|
|
for (let i = 0; i < 50; i++) formatDate(new Date(old.getTime() - i * 60_000));
|
|
|
|
expect(built).toBe(0);
|
|
});
|
|
|
|
it.each([
|
|
['smart', '24h', 'auto'],
|
|
['smart', '12h', 'en-GB'],
|
|
['smart', '24h', 'iso'],
|
|
['full', '12h', 'auto'],
|
|
['full', '24h', 'en-US'],
|
|
['relative', '24h', 'auto'],
|
|
] as const)('formats as the toLocale* calls did (%s, %s, %s)', (dateFormat, timeFormat, dateLocale) => {
|
|
useSettingsStore.setState({ dateFormat, timeFormat, dateLocale, timeZone: 'America/New_York' });
|
|
const now = Date.now();
|
|
const zone = 'America/New_York';
|
|
const hour12 = timeFormat === '12h';
|
|
const numeric = dateLocale === 'auto' ? 'en-US' : dateLocale === 'iso' ? 'en-CA' : dateLocale;
|
|
for (const ago of [5 * 60_000, 3 * 86_400_000, 40 * 86_400_000, 400 * 86_400_000]) {
|
|
const d = new Date(now - ago);
|
|
const got = formatDate(d);
|
|
if (dateFormat === 'full') {
|
|
expect(got).toBe(d.toLocaleString(numeric, { timeZone: zone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12 }));
|
|
} else if (dateFormat === 'smart' && ago > 7 * 86_400_000) {
|
|
expect(got).toBe(d.toLocaleDateString(numeric, { timeZone: zone, year: 'numeric', month: '2-digit', day: '2-digit' }));
|
|
} else if (dateFormat === 'smart' && ago > 86_400_000) {
|
|
const weekday = d.toLocaleDateString('en-US', { timeZone: zone, weekday: 'short' });
|
|
expect(got).toBe(`${weekday} ${d.toLocaleTimeString('en-US', { timeZone: zone, hour: '2-digit', minute: '2-digit', hour12 })}`);
|
|
} else {
|
|
expect(got.length).toBeGreaterThan(0);
|
|
}
|
|
}
|
|
});
|
|
});
|