From 4cfebae118b92e067baf20a05f4f90b1dedf3b88 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 12 Apr 2026 09:24:32 +0100 Subject: [PATCH] test(matrix): share client startup and backfill fixtures --- .../matrix/src/matrix/client/shared.test.ts | 54 +++--- .../matrix/src/matrix/client/storage.test.ts | 174 +++++++++--------- 2 files changed, 107 insertions(+), 121 deletions(-) diff --git a/extensions/matrix/src/matrix/client/shared.test.ts b/extensions/matrix/src/matrix/client/shared.test.ts index 158cba4a8e5..d41401227ea 100644 --- a/extensions/matrix/src/matrix/client/shared.test.ts +++ b/extensions/matrix/src/matrix/client/shared.test.ts @@ -70,6 +70,24 @@ function primeAccountClientMocks(params?: { return { mainAuth, opsAuth, mainClient, opsClient }; } +function createPendingSharedStartup(mainAuth = authFor("main")) { + let resolveStartup: (() => void) | undefined; + const mainClient = { + ...createMockClient("main"), + start: vi.fn( + async () => + await new Promise((resolve) => { + resolveStartup = resolve; + }), + ), + }; + + resolveMatrixAuthMock.mockResolvedValue(mainAuth); + createMatrixClientMock.mockResolvedValue(mainClient); + + return { mainClient, resolveStartup: () => resolveStartup?.() }; +} + describe("resolveSharedMatrixClient", () => { beforeAll(async () => { ({ @@ -234,25 +252,11 @@ describe("resolveSharedMatrixClient", () => { }); it("lets a later waiter abort while shared startup continues for the owner", async () => { - const mainAuth = authFor("main"); - let resolveStartup: (() => void) | undefined; - const mainClient = { - ...createMockClient("main"), - start: vi.fn( - async () => - await new Promise((resolve) => { - resolveStartup = resolve; - }), - ), - }; - - resolveMatrixAuthMock.mockResolvedValue(mainAuth); - createMatrixClientMock.mockResolvedValue(mainClient); + const { mainClient, resolveStartup } = createPendingSharedStartup(); const ownerPromise = resolveSharedMatrixClient({ accountId: "main" }); await vi.waitFor(() => { expect(mainClient.start).toHaveBeenCalledTimes(1); - expect(resolveStartup).toEqual(expect.any(Function)); }); const abortController = new AbortController(); @@ -267,30 +271,16 @@ describe("resolveSharedMatrixClient", () => { name: "AbortError", }); - resolveStartup?.(); + resolveStartup(); await expect(ownerPromise).resolves.toBe(mainClient); }); it("keeps the shared startup lock while an aborted waiter exits early", async () => { - const mainAuth = authFor("main"); - let resolveStartup: (() => void) | undefined; - const mainClient = { - ...createMockClient("main"), - start: vi.fn( - async () => - await new Promise((resolve) => { - resolveStartup = resolve; - }), - ), - }; - - resolveMatrixAuthMock.mockResolvedValue(mainAuth); - createMatrixClientMock.mockResolvedValue(mainClient); + const { mainClient, resolveStartup } = createPendingSharedStartup(); const ownerPromise = resolveSharedMatrixClient({ accountId: "main" }); await vi.waitFor(() => { expect(mainClient.start).toHaveBeenCalledTimes(1); - expect(resolveStartup).toEqual(expect.any(Function)); }); const abortController = new AbortController(); @@ -307,7 +297,7 @@ describe("resolveSharedMatrixClient", () => { const followerPromise = resolveSharedMatrixClient({ accountId: "main" }); expect(mainClient.start).toHaveBeenCalledTimes(1); - resolveStartup?.(); + resolveStartup(); await expect(ownerPromise).resolves.toBe(mainClient); await expect(followerPromise).resolves.toBe(mainClient); expect(mainClient.start).toHaveBeenCalledTimes(1); diff --git a/extensions/matrix/src/matrix/client/storage.test.ts b/extensions/matrix/src/matrix/client/storage.test.ts index f3312a9bf56..bd12c128b8a 100644 --- a/extensions/matrix/src/matrix/client/storage.test.ts +++ b/extensions/matrix/src/matrix/client/storage.test.ts @@ -129,6 +129,85 @@ describe("matrix client storage paths", () => { }); } + function setupCurrentTokenBackfillScenario(params: { + currentRootFiles: "thread-bindings" | "startup-verification"; + oldRootFiles: "crypto-only" | "thread-bindings"; + }) { + const stateDir = setupStateDir(); + const canonicalPaths = resolveMatrixAccountStorageRoot({ + stateDir, + homeserver: defaultStorageAuth.homeserver, + userId: defaultStorageAuth.userId, + accessToken: "secret-token-new", + }); + fs.mkdirSync(canonicalPaths.rootDir, { recursive: true }); + writeJson(canonicalPaths.rootDir, "storage-meta.json", { + homeserver: defaultStorageAuth.homeserver, + userId: defaultStorageAuth.userId, + accountId: "default", + accessTokenHash: canonicalPaths.tokenHash, + deviceId: null, + }); + if (params.currentRootFiles === "thread-bindings") { + writeJson(canonicalPaths.rootDir, "thread-bindings.json", { + version: 1, + bindings: [ + { + accountId: "default", + conversationId: "$thread-new", + targetKind: "subagent", + targetSessionKey: "agent:ops:subagent:new", + boundAt: 1, + lastActivityAt: 1, + }, + ], + }); + expect( + claimCurrentTokenStorageState({ + rootDir: canonicalPaths.rootDir, + }), + ).toBe(true); + } else { + writeJson(canonicalPaths.rootDir, "startup-verification.json", { + deviceId: "DEVICE123", + }); + } + + const oldStoragePaths = seedExistingStorageRoot({ + accessToken: "secret-token-old", + deviceId: "DEVICE123", + storageMeta: { + homeserver: defaultStorageAuth.homeserver, + userId: defaultStorageAuth.userId, + accountId: "default", + accessTokenHash: resolveDefaultStoragePaths({ accessToken: "secret-token-old" }).tokenHash, + deviceId: "DEVICE123", + }, + }); + fs.mkdirSync(oldStoragePaths.cryptoPath, { recursive: true }); + if (params.oldRootFiles === "thread-bindings") { + writeJson(oldStoragePaths.rootDir, "thread-bindings.json", { + version: 1, + bindings: [ + { + accountId: "default", + conversationId: "$thread-old", + targetKind: "subagent", + targetSessionKey: "agent:ops:subagent:old", + boundAt: 1, + lastActivityAt: 1, + }, + ], + }); + } else { + writeJson(oldStoragePaths.rootDir, "startup-verification.json", { + deviceId: "DEVICE123", + }); + } + + return { stateDir, canonicalPaths, oldStoragePaths }; + } + it("resolves state file paths inside the selected storage root", () => { setupStateDir(); const filePath = resolveMatrixStateFilePath({ @@ -497,53 +576,9 @@ describe("matrix client storage paths", () => { }); it("keeps the current-token storage root stable after deviceId backfill when startup claimed state there", () => { - const stateDir = setupStateDir(); - const canonicalPaths = resolveMatrixAccountStorageRoot({ - stateDir, - homeserver: defaultStorageAuth.homeserver, - userId: defaultStorageAuth.userId, - accessToken: "secret-token-new", - }); - fs.mkdirSync(canonicalPaths.rootDir, { recursive: true }); - writeJson(canonicalPaths.rootDir, "storage-meta.json", { - homeserver: defaultStorageAuth.homeserver, - userId: defaultStorageAuth.userId, - accountId: "default", - accessTokenHash: canonicalPaths.tokenHash, - deviceId: null, - }); - writeJson(canonicalPaths.rootDir, "thread-bindings.json", { - version: 1, - bindings: [ - { - accountId: "default", - conversationId: "$thread-new", - targetKind: "subagent", - targetSessionKey: "agent:ops:subagent:new", - boundAt: 1, - lastActivityAt: 1, - }, - ], - }); - expect( - claimCurrentTokenStorageState({ - rootDir: canonicalPaths.rootDir, - }), - ).toBe(true); - const oldStoragePaths = seedExistingStorageRoot({ - accessToken: "secret-token-old", - deviceId: "DEVICE123", - storageMeta: { - homeserver: defaultStorageAuth.homeserver, - userId: defaultStorageAuth.userId, - accountId: "default", - accessTokenHash: resolveDefaultStoragePaths({ accessToken: "secret-token-old" }).tokenHash, - deviceId: "DEVICE123", - }, - }); - fs.mkdirSync(oldStoragePaths.cryptoPath, { recursive: true }); - writeJson(oldStoragePaths.rootDir, "startup-verification.json", { - deviceId: "DEVICE123", + const { stateDir, canonicalPaths } = setupCurrentTokenBackfillScenario({ + currentRootFiles: "thread-bindings", + oldRootFiles: "crypto-only", }); repairCurrentTokenStorageMetaDeviceId({ @@ -572,48 +607,9 @@ describe("matrix client storage paths", () => { }); it("does not keep the current-token storage root sticky when only marker files exist after backfill", () => { - const stateDir = setupStateDir(); - const canonicalPaths = resolveMatrixAccountStorageRoot({ - stateDir, - homeserver: defaultStorageAuth.homeserver, - userId: defaultStorageAuth.userId, - accessToken: "secret-token-new", - }); - fs.mkdirSync(canonicalPaths.rootDir, { recursive: true }); - writeJson(canonicalPaths.rootDir, "storage-meta.json", { - homeserver: defaultStorageAuth.homeserver, - userId: defaultStorageAuth.userId, - accountId: "default", - accessTokenHash: canonicalPaths.tokenHash, - deviceId: null, - }); - writeJson(canonicalPaths.rootDir, "startup-verification.json", { - deviceId: "DEVICE123", - }); - const oldStoragePaths = seedExistingStorageRoot({ - accessToken: "secret-token-old", - deviceId: "DEVICE123", - storageMeta: { - homeserver: defaultStorageAuth.homeserver, - userId: defaultStorageAuth.userId, - accountId: "default", - accessTokenHash: resolveDefaultStoragePaths({ accessToken: "secret-token-old" }).tokenHash, - deviceId: "DEVICE123", - }, - }); - fs.mkdirSync(oldStoragePaths.cryptoPath, { recursive: true }); - writeJson(oldStoragePaths.rootDir, "thread-bindings.json", { - version: 1, - bindings: [ - { - accountId: "default", - conversationId: "$thread-old", - targetKind: "subagent", - targetSessionKey: "agent:ops:subagent:old", - boundAt: 1, - lastActivityAt: 1, - }, - ], + const { stateDir, oldStoragePaths } = setupCurrentTokenBackfillScenario({ + currentRootFiles: "startup-verification", + oldRootFiles: "thread-bindings", }); repairCurrentTokenStorageMetaDeviceId({