Add encrypted Deepbrid API accounts with account validation, provider routing, fallback, usage tracking, safe error handling, and verified 1Fichier downloads. Restore persistent recurring daily starts with local-calendar deduplication and legacy schedule compatibility. Add durable Discord package, run, remaining-volume, stall, and recovery notifications with privacy-safe telemetry and disk-failure recovery.
128 lines
4.7 KiB
TypeScript
128 lines
4.7 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import type { RendererSettings, UiSnapshot } from "../src/shared/types";
|
|
import {
|
|
activateDailyScheduleSettings,
|
|
buildScheduleCancellationSettingsUpdate,
|
|
buildDailyScheduleSettingsUpdate,
|
|
persistDailyScheduleSettingsUpdate,
|
|
resolveDailyScheduleInitialTime
|
|
} from "../src/renderer/App";
|
|
|
|
describe("daily schedule settings form", () => {
|
|
it("maps local time and the chosen start day to the recurring schedule settings", () => {
|
|
const now = new Date(2026, 7, 22, 18, 30, 0, 0);
|
|
|
|
expect(buildDailyScheduleSettingsUpdate("08:15", "today", now)).toEqual({
|
|
dailyStartEnabled: true,
|
|
dailyStartMinuteOfDay: 8 * 60 + 15,
|
|
dailyStartFirstLocalDate: "2026-08-22"
|
|
});
|
|
expect(buildDailyScheduleSettingsUpdate("23:45", "tomorrow", now)).toEqual({
|
|
dailyStartEnabled: true,
|
|
dailyStartMinuteOfDay: 23 * 60 + 45,
|
|
dailyStartFirstLocalDate: "2026-08-23"
|
|
});
|
|
});
|
|
|
|
it("prefills a previously saved disabled rule and uses local time only for the empty default", () => {
|
|
const now = new Date(2026, 7, 22, 18, 30, 0, 0);
|
|
const disabledSavedRule = {
|
|
dailyStartEnabled: false,
|
|
dailyStartMinuteOfDay: 8 * 60 + 15,
|
|
dailyStartFirstLocalDate: "2026-08-21"
|
|
};
|
|
|
|
expect(resolveDailyScheduleInitialTime(disabledSavedRule, now)).toBe("08:15");
|
|
expect(resolveDailyScheduleInitialTime({
|
|
dailyStartMinuteOfDay: 0,
|
|
dailyStartFirstLocalDate: ""
|
|
}, now)).toBe("18:30");
|
|
});
|
|
|
|
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);
|
|
const applySettings = vi.fn();
|
|
const getSnapshot = vi.fn();
|
|
const applySnapshot = vi.fn();
|
|
const showError = vi.fn();
|
|
const update = {
|
|
dailyStartEnabled: true,
|
|
dailyStartMinuteOfDay: 495,
|
|
dailyStartFirstLocalDate: "2026-08-23"
|
|
};
|
|
|
|
await expect(persistDailyScheduleSettingsUpdate(update, "activate", {
|
|
updateSettings,
|
|
getSnapshot,
|
|
applySettings,
|
|
applySnapshot,
|
|
showError
|
|
})).resolves.toBe(true);
|
|
|
|
expect(updateSettings).toHaveBeenCalledWith(update);
|
|
expect(applySettings).toHaveBeenCalledWith(persisted);
|
|
expect(getSnapshot).not.toHaveBeenCalled();
|
|
expect(showError).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("cancels the active schedule through its owning settings field", () => {
|
|
expect(buildScheduleCancellationSettingsUpdate({
|
|
dailyStartEnabled: true,
|
|
scheduledStartEpochMs: 1_800_000_000_000
|
|
})).toEqual({ dailyStartEnabled: false });
|
|
expect(buildScheduleCancellationSettingsUpdate({
|
|
dailyStartEnabled: false,
|
|
scheduledStartEpochMs: 1_800_000_000_000
|
|
})).toEqual({ scheduledStartEpochMs: 0 });
|
|
});
|
|
|
|
it.each([
|
|
["activate" as const, "Zeitplan konnte nicht aktiviert werden: Error: Speichern fehlgeschlagen"],
|
|
["cancel" as const, "Zeitplan konnte nicht abgebrochen werden: Error: Speichern fehlgeschlagen"]
|
|
])("shows %s failures before reconciling the authoritative snapshot", async (operation, expectedMessage) => {
|
|
const authoritative = { settings: { dailyStartEnabled: false } } as UiSnapshot;
|
|
const sequence: string[] = [];
|
|
const updateSettings = vi.fn().mockRejectedValue(new Error("Speichern fehlgeschlagen"));
|
|
const getSnapshot = vi.fn(async () => {
|
|
sequence.push("snapshot");
|
|
return authoritative;
|
|
});
|
|
const applySnapshot = vi.fn((snapshot: UiSnapshot) => {
|
|
sequence.push(`apply:${String(snapshot.settings.dailyStartEnabled)}`);
|
|
});
|
|
const showError = vi.fn((message: string) => {
|
|
sequence.push(`error:${message}`);
|
|
});
|
|
|
|
await expect(persistDailyScheduleSettingsUpdate({ dailyStartEnabled: false }, operation, {
|
|
updateSettings,
|
|
getSnapshot,
|
|
applySettings: vi.fn(),
|
|
applySnapshot,
|
|
showError
|
|
})).resolves.toBe(false);
|
|
|
|
expect(showError).toHaveBeenCalledWith(expectedMessage);
|
|
expect(getSnapshot).toHaveBeenCalledTimes(1);
|
|
expect(applySnapshot).toHaveBeenCalledWith(authoritative);
|
|
expect(sequence).toEqual([`error:${expectedMessage}`, "snapshot", "apply:false"]);
|
|
});
|
|
});
|