Validate daily schedule start times

Disable schedule activation until the local time input matches a strict HH:MM value.

Keep a defensive activation guard that surfaces a localized validation error and skips persistence when invoked with invalid state.

Add red-green coverage for empty, malformed, out-of-range hour, and out-of-range minute values.
This commit is contained in:
Sucukdeluxe
2026-08-22 10:12:25 +02:00
parent 30bedd17dd
commit 2e94484274
5 changed files with 54 additions and 7 deletions
+10
View File
@@ -791,6 +791,7 @@ function withRuntime(input: DownloadsModelInput, overrides: Partial<DownloadsVie
scheduleActive: false,
scheduleOpen: false,
scheduleTime: "23:30",
scheduleTimeValid: true,
scheduleStartDay: "today",
scheduleLabel: "",
packageSpeedBps: { "package-a": 12_000_000 },
@@ -1235,6 +1236,15 @@ describe("downloads view", () => {
expect(calls).toEqual(["time:09:45", "day:today"]);
});
it.each(["", "8:15", "24:00", "12:60"])("disables schedule activation for the invalid time %j", (scheduleTime) => {
const toolbar = DownloadsToolbar({
actions: createActions(),
model: withRuntime(createInput(), { scheduleOpen: true, scheduleTime, scheduleTimeValid: false })
});
expect(findButton(toolbar, "Planen").props.disabled).toBe(true);
});
it("animates the persistent schedule slot horizontally and disables it through the global motion setting", () => {
const closed = renderToStaticMarkup(<DownloadsToolbar actions={createActions()} model={withRuntime(createInput())} />);
const open = renderToStaticMarkup(<DownloadsToolbar actions={createActions()} model={withRuntime(createInput(), { scheduleOpen: true })} />);
+17
View File
@@ -1,6 +1,7 @@
import { describe, expect, it, vi } from "vitest";
import type { RendererSettings, UiSnapshot } from "../src/shared/types";
import {
activateDailyScheduleSettings,
buildDailyScheduleSettingsUpdate,
persistDailyScheduleSettingsUpdate
} from "../src/renderer/App";
@@ -21,6 +22,22 @@ describe("daily schedule settings form", () => {
});
});
it.each(["", "8:15", "24:00", "12:60"])("reports the invalid time %j when activation is invoked directly", async (time) => {
const persist = vi.fn();
const showError = vi.fn();
await expect(activateDailyScheduleSettings(
time,
"today",
persist,
showError,
new Date(2026, 7, 22, 18, 30, 0, 0)
)).resolves.toBe(false);
expect(showError).toHaveBeenCalledWith("Bitte eine gültige Startzeit auswählen.");
expect(persist).not.toHaveBeenCalled();
});
it("applies persisted settings after a successful activation", async () => {
const persisted = { dailyStartEnabled: true } as RendererSettings;
const updateSettings = vi.fn().mockResolvedValue(persisted);