fix(scheduler): harden daily start reconciliation
Preserve legacy one-time schedules across internal account state saves and clear them only for explicit renderer daily-rule updates. Enforce monotone handled and pending calendar receipts across backward local-date changes, invalidate late in-flight start results on shutdown, and align queue eligibility with enabled non-cancelled packages. Replace the in-memory restart assertion with real settings persistence and add RED/GREEN regression coverage for every reviewed behavior.
This commit is contained in:
@@ -5,6 +5,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { AppController } from "../src/main/app-controller";
|
||||
import { defaultSettings } from "../src/main/constants";
|
||||
import { configureCredentialProtector } from "../src/main/credential-protection";
|
||||
import { prepareDailyStartSettingsPatch } from "../src/main/daily-start-scheduler";
|
||||
import { createStoragePaths } from "../src/main/storage";
|
||||
import type { AppSettings } from "../src/shared/types";
|
||||
|
||||
@@ -55,11 +56,11 @@ describe("AppController daily start settings", () => {
|
||||
scheduledStartEpochMs: 1_800_000_000_000
|
||||
});
|
||||
|
||||
const updated = controller.updateSettings({
|
||||
const updated = controller.updateSettings(prepareDailyStartSettingsPatch({
|
||||
dailyStartEnabled: true,
|
||||
dailyStartMinuteOfDay: 18 * 60 + 45,
|
||||
dailyStartFirstLocalDate: "2026-08-23"
|
||||
});
|
||||
}));
|
||||
|
||||
expect(updated.scheduledStartEpochMs).toBe(0);
|
||||
expect(updated).toMatchObject({
|
||||
@@ -68,4 +69,27 @@ describe("AppController daily start settings", () => {
|
||||
dailyStartFirstLocalDate: "2026-08-23"
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves a legacy one-time schedule when an account mutation saves a complete settings state", async () => {
|
||||
configureCredentialProtector({
|
||||
isEncryptionAvailable: () => false,
|
||||
encryptString: (value) => Buffer.from(value, "utf8"),
|
||||
decryptString: (value) => Buffer.from(value).toString("utf8")
|
||||
});
|
||||
const scheduledStartEpochMs = 1_800_000_000_000;
|
||||
const controller = createController({
|
||||
...defaultSettings(),
|
||||
ddownloadLogin: "account@example.test",
|
||||
ddownloadPassword: "secret",
|
||||
scheduledStartEpochMs
|
||||
});
|
||||
|
||||
await controller.executeAccountCommand({
|
||||
action: "delete",
|
||||
kind: "ddownload-login",
|
||||
accountId: "svc-ddownload"
|
||||
});
|
||||
|
||||
expect(controller.getSettings().scheduledStartEpochMs).toBe(scheduledStartEpochMs);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user