From e530a174d2d01a5b68754ae4422db56023dd2e56 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 11 May 2026 00:09:33 +0100 Subject: [PATCH] test: tighten installed plugin index assertions --- .../installed-plugin-index-records.test.ts | 166 +++++++++--------- 1 file changed, 79 insertions(+), 87 deletions(-) diff --git a/src/plugins/installed-plugin-index-records.test.ts b/src/plugins/installed-plugin-index-records.test.ts index afc2bf84a8a..53a72e0d5d4 100644 --- a/src/plugins/installed-plugin-index-records.test.ts +++ b/src/plugins/installed-plugin-index-records.test.ts @@ -45,6 +45,15 @@ function createPluginCandidate(stateDir: string, pluginId: string): PluginCandid }; } +function expectRecordFields(record: unknown, expected: Record) { + expect(record).toBeDefined(); + const actual = record as Record; + for (const [key, value] of Object.entries(expected)) { + expect(actual[key]).toEqual(value); + } + return actual; +} + afterEach(() => { for (const dir of tempDirs.splice(0)) { fs.rmSync(dir, { recursive: true, force: true }); @@ -73,23 +82,22 @@ describe("plugin index install records store", () => { const indexPath = resolveInstalledPluginIndexRecordsStorePath({ stateDir }); expect(indexPath).toBe(path.join(stateDir, "plugins", "installs.json")); - expect(JSON.parse(fs.readFileSync(indexPath, "utf8"))).toMatchObject({ - version: 1, - generatedAtMs: 1777118400000, - installRecords: { - twitch: { - source: "npm", - spec: "@openclaw/plugin-twitch@1.0.0", - installPath: "plugins/npm/@openclaw/plugin-twitch", - }, - }, - plugins: [ - { - pluginId: "twitch", - installRecordHash: expect.stringMatching(/^[a-f0-9]{64}$/u), - }, - ], + const persisted = JSON.parse(fs.readFileSync(indexPath, "utf8")) as { + version?: number; + generatedAtMs?: number; + installRecords?: Record; + plugins?: Array<{ pluginId?: string; installRecordHash?: string }>; + }; + expect(persisted.version).toBe(1); + expect(persisted.generatedAtMs).toBe(1777118400000); + expectRecordFields(persisted.installRecords?.twitch, { + source: "npm", + spec: "@openclaw/plugin-twitch@1.0.0", + installPath: "plugins/npm/@openclaw/plugin-twitch", }); + expect(persisted.plugins).toHaveLength(1); + expect(persisted.plugins?.[0]?.pluginId).toBe("twitch"); + expect(persisted.plugins?.[0]?.installRecordHash).toMatch(/^[a-f0-9]{64}$/u); await expect(readPersistedInstalledPluginIndexInstallRecords({ stateDir })).resolves.toEqual({ twitch: { source: "npm", @@ -117,20 +125,15 @@ describe("plugin index install records store", () => { }, ); - expect( - JSON.parse( - fs.readFileSync(resolveInstalledPluginIndexRecordsStorePath({ stateDir }), "utf8"), - ), - ).toMatchObject({ - installRecords: { - missing: { - source: "npm", - spec: "missing-plugin@1.0.0", - installPath: path.join(stateDir, "plugins", "missing"), - }, - }, - plugins: [], + const persisted = JSON.parse( + fs.readFileSync(resolveInstalledPluginIndexRecordsStorePath({ stateDir }), "utf8"), + ) as { installRecords?: Record; plugins?: unknown[] }; + expectRecordFields(persisted.installRecords?.missing, { + source: "npm", + spec: "missing-plugin@1.0.0", + installPath: path.join(stateDir, "plugins", "missing"), }); + expect(persisted.plugins).toEqual([]); await expect(loadInstalledPluginIndexInstallRecords({ stateDir })).resolves.toEqual({ missing: { source: "npm", @@ -210,36 +213,28 @@ describe("plugin index install records store", () => { fs.mkdirSync(path.dirname(indexPath), { recursive: true }); fs.writeFileSync(indexPath, JSON.stringify({ installRecords: {}, plugins: [] }), "utf8"); - await expect(loadInstalledPluginIndexInstallRecords({ stateDir })).resolves.toMatchObject({ - codex: { - source: "npm", - spec: "@openclaw/codex@2026.5.2", - installPath: codexDir, - version: "2026.5.2", - resolvedName: "@openclaw/codex", - resolvedVersion: "2026.5.2", - resolvedSpec: "@openclaw/codex@2026.5.2", - }, - discord: { - source: "npm", - spec: "@openclaw/discord@2026.5.2", - installPath: discordDir, - version: "2026.5.2", - resolvedName: "@openclaw/discord", - resolvedVersion: "2026.5.2", - resolvedSpec: "@openclaw/discord@2026.5.2", - }, + const loaded = await loadInstalledPluginIndexInstallRecords({ stateDir }); + expectRecordFields(loaded.codex, { + source: "npm", + spec: "@openclaw/codex@2026.5.2", + installPath: codexDir, + version: "2026.5.2", + resolvedName: "@openclaw/codex", + resolvedVersion: "2026.5.2", + resolvedSpec: "@openclaw/codex@2026.5.2", }); - expect(loadInstalledPluginIndexInstallRecordsSync({ stateDir })).toMatchObject({ - codex: { - source: "npm", - installPath: codexDir, - }, - discord: { - source: "npm", - installPath: discordDir, - }, + expectRecordFields(loaded.discord, { + source: "npm", + spec: "@openclaw/discord@2026.5.2", + installPath: discordDir, + version: "2026.5.2", + resolvedName: "@openclaw/discord", + resolvedVersion: "2026.5.2", + resolvedSpec: "@openclaw/discord@2026.5.2", }); + const loadedSync = loadInstalledPluginIndexInstallRecordsSync({ stateDir }); + expectRecordFields(loadedSync.codex, { source: "npm", installPath: codexDir }); + expectRecordFields(loadedSync.discord, { source: "npm", installPath: discordDir }); }); it("keeps persisted install record metadata over recovered npm records", async () => { @@ -263,13 +258,12 @@ describe("plugin index install records store", () => { { stateDir, candidates: [candidate] }, ); - await expect(loadInstalledPluginIndexInstallRecords({ stateDir })).resolves.toMatchObject({ - discord: { - source: "npm", - spec: "@openclaw/discord@beta", - installPath: path.join(stateDir, "custom", "discord"), - integrity: "sha512-persisted", - }, + const loaded = await loadInstalledPluginIndexInstallRecords({ stateDir }); + expectRecordFields(loaded.discord, { + source: "npm", + spec: "@openclaw/discord@beta", + installPath: path.join(stateDir, "custom", "discord"), + integrity: "sha512-persisted", }); }); @@ -290,14 +284,13 @@ describe("plugin index install records store", () => { { stateDir, candidates: [candidate] }, ); - await expect(loadInstalledPluginIndexInstallRecords({ stateDir })).resolves.toMatchObject({ - "git-demo": { - source: "git", - spec: "git:file:///tmp/git-demo@abc123", - gitUrl: "file:///tmp/git-demo", - gitRef: "abc123", - gitCommit: "abc123", - }, + const loaded = await loadInstalledPluginIndexInstallRecords({ stateDir }); + expectRecordFields(loaded["git-demo"], { + source: "git", + spec: "git:file:///tmp/git-demo@abc123", + gitUrl: "file:///tmp/git-demo", + gitRef: "abc123", + gitCommit: "abc123", }); }); @@ -329,20 +322,19 @@ describe("plugin index install records store", () => { { stateDir, candidates: [candidate] }, ); - await expect(loadInstalledPluginIndexInstallRecords({ stateDir })).resolves.toMatchObject({ - "clawpack-demo": { - source: "clawhub", - spec: "clawhub:clawpack-demo", - artifactKind: "npm-pack", - artifactFormat: "tgz", - npmIntegrity: "sha512-clawpack", - npmShasum: "1".repeat(40), - npmTarballName: "clawpack-demo-2026.5.1-beta.2.tgz", - clawpackSha256: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - clawpackSpecVersion: 1, - clawpackManifestSha256: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", - clawpackSize: 4096, - }, + const loaded = await loadInstalledPluginIndexInstallRecords({ stateDir }); + expectRecordFields(loaded["clawpack-demo"], { + source: "clawhub", + spec: "clawhub:clawpack-demo", + artifactKind: "npm-pack", + artifactFormat: "tgz", + npmIntegrity: "sha512-clawpack", + npmShasum: "1".repeat(40), + npmTarballName: "clawpack-demo-2026.5.1-beta.2.tgz", + clawpackSha256: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + clawpackSpecVersion: 1, + clawpackManifestSha256: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + clawpackSize: 4096, }); }); @@ -376,7 +368,7 @@ describe("plugin index install records store", () => { spec: "keep@1.0.0", }, }); - expect(withInstall.demo).toMatchObject({ + expectRecordFields(withInstall.demo, { source: "npm", spec: "demo@latest", installedAt: "2026-04-25T00:00:00.000Z",