mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 03:45:46 -06:00
fix(cron): preserve enabled-with-defaults failure alert through store roundtrip (fixes #96589) (AI-assisted) (#96615)
Summary:
- The PR preserves `failure_alert_disabled === 0` as the enabled-with-defaults failure-alert state and adds focused codec roundtrip tests.
- PR surface: Source +2, Tests +54. Total +56 across 2 files.
- Reproducibility: yes. At source level, current main encodes `failureAlert: {}` with `failure_alert_disabled = 0`, then decodes it as `undefined` when all explicit alert option columns are null.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head bd9b2a1798.
- Required merge gates passed before the squash merge.
Prepared head SHA: bd9b2a1798
Review: https://github.com/openclaw/openclaw/pull/96615#issuecomment-4794949533
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: liuhao1024 <11816344+liuhao1024@users.noreply.github.com>
Approved-by: takhoffman
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
// Unit tests for failure-alert SQLite column codec roundtrip.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { bindFailureAlertColumns, failureAlertFromRow } from "./failure-alert-codec.js";
|
||||
import type { CronJobRow } from "./schema.js";
|
||||
|
||||
function roundtrip(
|
||||
input: Parameters<typeof bindFailureAlertColumns>[0],
|
||||
): ReturnType<typeof failureAlertFromRow> {
|
||||
const columns = bindFailureAlertColumns(input);
|
||||
return failureAlertFromRow(columns as CronJobRow);
|
||||
}
|
||||
|
||||
describe("failureAlertFromRow", () => {
|
||||
it("round-trips disabled config (false)", () => {
|
||||
expect(roundtrip(false)).toBe(false);
|
||||
});
|
||||
|
||||
it("round-trips undefined (no alert config) as undefined", () => {
|
||||
expect(roundtrip(undefined)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("round-trips enabled-with-defaults ({}) as {}", () => {
|
||||
const result = roundtrip({});
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
it("round-trips populated config with all fields", () => {
|
||||
const config = {
|
||||
after: 3,
|
||||
cooldownMs: 120_000,
|
||||
channel: "telegram" as const,
|
||||
to: "@user",
|
||||
mode: "announce" as const,
|
||||
accountId: "acc-1",
|
||||
includeSkipped: true,
|
||||
};
|
||||
expect(roundtrip(config)).toEqual(config);
|
||||
});
|
||||
|
||||
it("round-trips partial config (only after)", () => {
|
||||
expect(roundtrip({ after: 5 })).toEqual({ after: 5 });
|
||||
});
|
||||
|
||||
it("enabled-with-defaults does not collapse to undefined on read", () => {
|
||||
const columns = bindFailureAlertColumns({});
|
||||
const row = columns as CronJobRow;
|
||||
expect(row.failure_alert_disabled).toBe(0);
|
||||
expect(row.failure_alert_after).toBeNull();
|
||||
const decoded = failureAlertFromRow(row);
|
||||
expect(decoded).toEqual({});
|
||||
expect(decoded).not.toBeUndefined();
|
||||
expect(decoded).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -46,6 +46,7 @@ export function failureAlertFromRow(row: CronJobRow): CronFailureAlert | false |
|
||||
if (row.failure_alert_disabled === 1) {
|
||||
return false;
|
||||
}
|
||||
const failureAlertExplicitlyEnabled = row.failure_alert_disabled === 0;
|
||||
if (
|
||||
row.failure_alert_after == null &&
|
||||
!row.failure_alert_channel &&
|
||||
@@ -53,7 +54,8 @@ export function failureAlertFromRow(row: CronJobRow): CronFailureAlert | false |
|
||||
row.failure_alert_cooldown_ms == null &&
|
||||
row.failure_alert_include_skipped == null &&
|
||||
!row.failure_alert_mode &&
|
||||
!row.failure_alert_account_id
|
||||
!row.failure_alert_account_id &&
|
||||
!failureAlertExplicitlyEnabled
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user