From e91405ebf9eec0fdc3c30462198d397efb8c3e1b Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Sun, 5 Apr 2026 18:22:47 -0400 Subject: [PATCH] test(matrix): isolate migration snapshot seam --- .../matrix/src/migration-snapshot.test.ts | 33 +++++++++++++++++-- extensions/matrix/src/migration-snapshot.ts | 4 ++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/extensions/matrix/src/migration-snapshot.test.ts b/extensions/matrix/src/migration-snapshot.test.ts index 18dbb1b08d0..95c04a1425a 100644 --- a/extensions/matrix/src/migration-snapshot.test.ts +++ b/extensions/matrix/src/migration-snapshot.test.ts @@ -1,6 +1,6 @@ import fs from "node:fs"; import path from "node:path"; -import { describe, expect, it } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import { withTempHome } from "../../../test/helpers/temp-home.js"; import { detectLegacyMatrixCrypto } from "./legacy-crypto.js"; import { @@ -11,13 +11,38 @@ import { } from "./migration-snapshot.js"; import { resolveMatrixAccountStorageRoot } from "./storage-paths.js"; +const createBackupArchiveMock = vi.hoisted(() => vi.fn()); + describe("matrix migration snapshots", () => { + beforeEach(() => { + createBackupArchiveMock.mockReset(); + createBackupArchiveMock.mockImplementation( + async (params: { output?: string; includeWorkspace?: boolean }) => { + const outputDir = params.output; + if (!outputDir) { + throw new Error("expected migration snapshot output dir"); + } + fs.mkdirSync(outputDir, { recursive: true }); + const archivePath = path.join(outputDir, "matrix-migration-backup.tar.gz"); + fs.writeFileSync(archivePath, "archive\n", "utf8"); + return { + createdAt: "2026-04-05T00:00:00.000Z", + archivePath, + includeWorkspace: params.includeWorkspace ?? true, + }; + }, + ); + }); + it("creates a backup marker after writing a pre-migration snapshot", async () => { await withTempHome(async (home) => { fs.writeFileSync(path.join(home, ".openclaw", "openclaw.json"), "{}\n", "utf8"); fs.writeFileSync(path.join(home, ".openclaw", "state.txt"), "state\n", "utf8"); - const result = await maybeCreateMatrixMigrationSnapshot({ trigger: "unit-test" }); + const result = await maybeCreateMatrixMigrationSnapshot({ + trigger: "unit-test", + createBackupArchive: createBackupArchiveMock, + }); expect(result.created).toBe(true); expect(result.markerPath).toBe(resolveMatrixMigrationSnapshotMarkerPath(process.env)); @@ -25,6 +50,10 @@ describe("matrix migration snapshots", () => { result.archivePath.startsWith(resolveMatrixMigrationSnapshotOutputDir(process.env)), ).toBe(true); expect(fs.existsSync(result.archivePath)).toBe(true); + expect(createBackupArchiveMock).toHaveBeenCalledWith({ + output: resolveMatrixMigrationSnapshotOutputDir(process.env), + includeWorkspace: false, + }); }); }); diff --git a/extensions/matrix/src/migration-snapshot.ts b/extensions/matrix/src/migration-snapshot.ts index 16f587c3b4a..0f6b4b1adfd 100644 --- a/extensions/matrix/src/migration-snapshot.ts +++ b/extensions/matrix/src/migration-snapshot.ts @@ -100,10 +100,12 @@ export async function maybeCreateMatrixMigrationSnapshot(params: { trigger: string; env?: NodeJS.ProcessEnv; outputDir?: string; + createBackupArchive?: typeof import("openclaw/plugin-sdk/runtime").createBackupArchive; log?: { info?: (message: string) => void; warn?: (message: string) => void }; }): Promise { - const { createBackupArchive } = await import("openclaw/plugin-sdk/runtime"); const env = params.env ?? process.env; + const createBackupArchive = + params.createBackupArchive ?? (await import("openclaw/plugin-sdk/runtime")).createBackupArchive; const markerPath = resolveMatrixMigrationSnapshotMarkerPath(env); const existingMarker = loadSnapshotMarker(markerPath); if (existingMarker?.archivePath && fs.existsSync(existingMarker.archivePath)) {