





















11// Update method tests cover update.run/status, restart sentinel metadata,
22// managed-service handoff, restart scheduling, and delivery context preservation.
33import { beforeEach, describe, expect, it, vi } from "vitest";
4+import type { ConfigFileSnapshot, OpenClawConfig } from "../../config/types.openclaw.js";
45import type { RestartSentinelPayload } from "../../infra/restart-sentinel.js";
56import type { RespawnSupervisor } from "../../infra/supervisor-markers.js";
67import type { UpdateInstallSurface, UpdateRunResult } from "../../infra/update-runner.js";
@@ -24,6 +25,7 @@ const isRestartEnabledMock = vi.fn(() => true);
2425const readPackageVersionMock = vi.fn(async () => "1.0.0");
2526const detectRespawnSupervisorMock = vi.fn<() => RespawnSupervisor | null>(() => null);
2627const normalizeUpdateChannelMock = vi.fn((): "stable" | "beta" | "dev" | null => null);
28+const readConfigFileSnapshotMock = vi.fn<() => Promise<ConfigFileSnapshot>>();
2729const startManagedServiceUpdateHandoffMock = vi.fn(async () => ({
2830status: "started" as const,
2931pid: 12345,
@@ -52,6 +54,7 @@ type UpdateRunPayload = {
52545355vi.mock("../../config/config.js", () => ({
5456getRuntimeConfig: () => ({ update: {} }),
57+readConfigFileSnapshot: readConfigFileSnapshotMock,
5558}));
56595760vi.mock("../../config/commands.flags.js", () => ({
@@ -179,6 +182,21 @@ beforeEach(() => {
179182readPackageVersionMock.mockResolvedValue("1.0.0");
180183normalizeUpdateChannelMock.mockReset();
181184normalizeUpdateChannelMock.mockReturnValue(null);
185+readConfigFileSnapshotMock.mockReset();
186+readConfigFileSnapshotMock.mockResolvedValue({
187+path: "/tmp/openclaw.json",
188+exists: true,
189+raw: "{}",
190+parsed: {},
191+resolved: {} as OpenClawConfig,
192+sourceConfig: {} as OpenClawConfig,
193+valid: true,
194+config: {} as OpenClawConfig,
195+runtimeConfig: {} as OpenClawConfig,
196+issues: [],
197+warnings: [],
198+legacyIssues: [],
199+});
182200detectRespawnSupervisorMock.mockReset();
183201detectRespawnSupervisorMock.mockReturnValue(null);
184202runGatewayUpdateMock.mockClear();
@@ -724,6 +742,46 @@ describe("update.run post-core plugin finalize", () => {
724742expect(payload?.result?.status).toBe("ok");
725743});
726744745+it("carries the pre-doctor source config into the git finalizer", async () => {
746+const preUpdateConfig = {
747+channels: {
748+whatsapp: {
749+enabled: true,
750+},
751+},
752+} as OpenClawConfig;
753+readConfigFileSnapshotMock.mockResolvedValueOnce({
754+path: "/tmp/openclaw.json",
755+exists: true,
756+raw: JSON.stringify(preUpdateConfig),
757+parsed: preUpdateConfig,
758+resolved: preUpdateConfig,
759+sourceConfig: preUpdateConfig,
760+valid: true,
761+config: preUpdateConfig,
762+runtimeConfig: preUpdateConfig,
763+issues: [],
764+warnings: [],
765+legacyIssues: [],
766+});
767+runPostCoreFinalizeAfterGatewayUpdateMock.mockResolvedValueOnce({
768+status: "ok",
769+entrypoint: "/tmp/openclaw-git/dist/index.mjs",
770+});
771+mockGitOkUpdate("/tmp/openclaw-git");
772+773+await captureUpdateRunPayload();
774+775+const [finalizeParams] = firstMockCall(
776+runPostCoreFinalizeAfterGatewayUpdateMock,
777+"post-core finalize",
778+) as [{ preUpdateConfig?: { sourceConfig?: OpenClawConfig; authoredConfig?: OpenClawConfig } }];
779+expect(finalizeParams.preUpdateConfig).toEqual({
780+sourceConfig: preUpdateConfig,
781+authoredConfig: preUpdateConfig,
782+});
783+});
784+727785it("blocks the restart when post-core plugin finalize fails", async () => {
728786runPostCoreFinalizeAfterGatewayUpdateMock.mockResolvedValueOnce({
729787status: "error",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。