1import { describe, expect, it } from "vite-plus/test";
2
3import { resolveSnoozePresets, snoozeWakeDescription } from "./Sidebar.snooze";
4
5// Local-time constructor so preset math is timezone-stable in tests.
6function localDate(year: number, month: number, day: number, hour: number, minute = 0): Date {
7 return new Date(year, month - 1, day, hour, minute, 0, 0);
8}
9
10describe("resolveSnoozePresets", () => {
11 it("offers one hour, three hours, evening, tomorrow, and next week in the morning", () => {
12 // Wednesday 2026-04-08 10:00 local.
13 const presets = resolveSnoozePresets(localDate(2026, 4, 8, 10), "locale");
14 expect(presets.map((preset) => preset.id)).toEqual([
15 "hour",
16 "three-hours",
17 "evening",
18 "tomorrow",
19 "next-week",
20 ]);
21 const threeHours = presets.find((preset) => preset.id === "three-hours");
22 expect(new Date(threeHours!.snoozedUntil).getHours()).toBe(13);
23 const evening = presets.find((preset) => preset.id === "evening");
24 expect(new Date(evening!.snoozedUntil).getHours()).toBe(18);
25 const tomorrow = presets.find((preset) => preset.id === "tomorrow");
26 const tomorrowDate = new Date(tomorrow!.snoozedUntil);
27 expect(tomorrowDate.getDate()).toBe(9);
28 expect(tomorrowDate.getHours()).toBe(9);
29 const nextWeek = presets.find((preset) => preset.id === "next-week");
30 const nextWeekDate = new Date(nextWeek!.snoozedUntil);
31 expect(nextWeekDate.getDay()).toBe(1);
32 expect(nextWeekDate.getDate()).toBe(13);
33 });
34
35 it("whenLabel complements the label instead of repeating it", () => {
36 const presets = resolveSnoozePresets(localDate(2026, 4, 8, 10), "locale");
37 for (const preset of presets) {
38 // Day words live in the label column; the time column is time-only
39 // (plus a weekday for next week, which names a different day).
40 expect(preset.whenLabel.toLowerCase()).not.toContain("tomorrow");
41 }
42 const tomorrow = presets.find((preset) => preset.id === "tomorrow");
43 expect(tomorrow!.whenLabel).toMatch(/9/);
44 const nextWeek = presets.find((preset) => preset.id === "next-week");
45 expect(nextWeek!.whenLabel).toMatch(/Mon/);
46 });
47
48 it("drops the evening preset once evening is near or past", () => {
49 expect(
50 resolveSnoozePresets(localDate(2026, 4, 8, 17, 30), "locale").map((preset) => preset.id),
51 ).toEqual(["hour", "three-hours", "tomorrow", "next-week"]);
52 expect(
53 resolveSnoozePresets(localDate(2026, 4, 8, 21), "locale").map((preset) => preset.id),
54 ).toEqual(["hour", "three-hours", "tomorrow", "next-week"]);
55 });
56
57 it("puts next week a full week out when today is Monday", () => {
58 // Monday 2026-04-06.
59 const presets = resolveSnoozePresets(localDate(2026, 4, 6, 10), "locale");
60 const nextWeek = new Date(presets.find((preset) => preset.id === "next-week")!.snoozedUntil);
61 expect(nextWeek.getDay()).toBe(1);
62 expect(nextWeek.getDate()).toBe(13);
63 });
64 it("formats preset times with the selected clock preference", () => {
65 const twelveHour = resolveSnoozePresets(localDate(2026, 4, 8, 10), "12-hour");
66 const twentyFourHour = resolveSnoozePresets(localDate(2026, 4, 8, 10), "24-hour");
67
68 expect(twelveHour.find((preset) => preset.id === "evening")!.whenLabel).toMatch(/PM/i);
69 expect(twentyFourHour.find((preset) => preset.id === "evening")!.whenLabel).toBe("18:00");
70 });
71});
72
73describe("snoozeWakeDescription", () => {
74 const now = localDate(2026, 4, 8, 10);
75
76 it("uses bare time today, 'tomorrow' next day, weekday within the week", () => {
77 expect(
78 snoozeWakeDescription(localDate(2026, 4, 8, 18).toISOString(), now, "locale"),
79 ).not.toContain("tomorrow");
80 expect(snoozeWakeDescription(localDate(2026, 4, 9, 9).toISOString(), now, "locale")).toContain(
81 "tomorrow",
82 );
83 expect(snoozeWakeDescription(localDate(2026, 4, 13, 9).toISOString(), now, "locale")).toMatch(
84 /Mon/,
85 );
86 });
87
88 it("formats wake descriptions with the selected clock preference", () => {
89 expect(snoozeWakeDescription(localDate(2026, 4, 8, 18).toISOString(), now, "12-hour")).toMatch(
90 /PM/i,
91 );
92 expect(snoozeWakeDescription(localDate(2026, 4, 8, 18).toISOString(), now, "24-hour")).toBe(
93 "18:00",
94 );
95 });
96});