authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-05 16:18:13-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-05 16:18:13-07:00
log585ce2c2ab396e4c3c5ffcfc422449c07896ddf9
tree7d53828edda8453291e504df684dd8fb3c0c476f
parent183c3433091c30a19117ee733832b1c44a6af074
signature Signed by PGP key B5690EEEBB952194

refactor(web): test formatted timestamps instead of formatter options (#10221)


2 files changed, 19 insertions(+), 40 deletions(-)

apps/web/src/timestampFormat.test.ts+18-39
......@@ -8,37 +8,9 @@ import {
88 formatRelativeTimeLabel,
99 formatShortTimestamp,
1010 getRelativeTimeState,
11 getTimestampFormatOptions,
1211 resolveTimestampLocale,
1312} from "./timestampFormat";
1413
15describe("getTimestampFormatOptions", () => {
16 it("omits hour12 when locale formatting is requested", () => {
17 expect(getTimestampFormatOptions("locale", true)).toEqual({
18 hour: "numeric",
19 minute: "2-digit",
20 second: "2-digit",
21 });
22 });
23
24 it("builds a 12-hour formatter with seconds when requested", () => {
25 expect(getTimestampFormatOptions("12-hour", true)).toEqual({
26 hour: "numeric",
27 minute: "2-digit",
28 second: "2-digit",
29 hour12: true,
30 });
31 });
32
33 it("builds a 24-hour formatter without seconds when requested", () => {
34 expect(getTimestampFormatOptions("24-hour", false)).toEqual({
35 hour: "numeric",
36 minute: "2-digit",
37 hour12: false,
38 });
39 });
40});
41
4214describe("resolveTimestampLocale", () => {
4315 it("defers to the runtime default when the host reports no locale", () => {
4416 expect(resolveTimestampLocale(null)).toBeUndefined();
......@@ -57,19 +29,26 @@ describe("resolveTimestampLocale", () => {
5729 expect(resolveTimestampLocale("not a locale")).toBeUndefined();
5830 expect(resolveTimestampLocale("en_GB")).toBeUndefined();
5931 });
32});
6033
61 it("renders the host locale's hour cycle under the locale setting", () => {
62 const formatAt1544 = (systemLocale: string | null) =>
63 new Intl.DateTimeFormat(resolveTimestampLocale(systemLocale), {
64 ...getTimestampFormatOptions("locale", false),
65 timeZone: "UTC",
66 })
67 .format(new Date("2026-04-07T15:44:00.000Z"))
68 // ICU separates the day period with a narrow no-break space.
69 .replace(/[  ]/g, " ");
34describe("formatShortTimestamp", () => {
35 afterEach(() => {
36 vi.unstubAllGlobals();
37 vi.resetModules();
38 });
7039
71 expect(formatAt1544("en-GB")).toBe("15:44");
72 expect(formatAt1544("en-US")).toBe("3:44 PM");
40 it.each([
41 ["en-GB", "15:44"],
42 ["en-US", "3:44 PM"],
43 ])("honors %s and the explicit hour-cycle settings", async (locale, localTime) => {
44 vi.stubGlobal("window", { desktopBridge: { getSystemLocale: () => locale } });
45 vi.resetModules();
46 const { formatShortTimestamp: format } = await import("./timestampFormat");
47 const date = new Date(2026, 3, 7, 15, 44).toISOString();
48 // ICU can separate the day period with a narrow no-break space.
49 expect(format(date, "locale").replace(/[  ]/g, " ")).toBe(localTime);
50 expect(format(date, "12-hour").replace(/[  ]/g, " ")).toMatch(/^3:44 [ap]m$/i);
51 expect(format(date, "24-hour")).toBe("15:44");
7352 });
7453});
7554
apps/web/src/timestampFormat.ts+1-1
......@@ -1,6 +1,6 @@
11import { type TimestampFormat } from "@t3tools/contracts/settings";
22
3export function getTimestampFormatOptions(
3function getTimestampFormatOptions(
44 timestampFormat: TimestampFormat,
55 includeSeconds: boolean,
66): Intl.DateTimeFormatOptions {