feat: add Deepbrid, daily scheduling, and notification center
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.
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
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"]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user