






















@@ -18,6 +18,55 @@ function requestUrl(input: RequestInfo | URL | undefined): string {
1818return input.url;
1919}
202021+function requireRecord(value: unknown, label: string): Record<string, unknown> {
22+expect(typeof value).toBe("object");
23+expect(value).not.toBeNull();
24+if (typeof value !== "object" || value === null) {
25+throw new Error(`${label} was not an object`);
26+}
27+return value as Record<string, unknown>;
28+}
29+30+function expectRecordFields(record: Record<string, unknown>, fields: Record<string, unknown>) {
31+for (const [key, value] of Object.entries(fields)) {
32+expect(record[key]).toEqual(value);
33+}
34+}
35+36+async function expectAbortError(promise: Promise<unknown>) {
37+const err = await promise.catch((caught: unknown) => caught);
38+expect(err).toBeInstanceOf(Error);
39+expectRecordFields(requireRecord(err, "abort error"), {
40+message: "Matrix startup aborted",
41+name: "AbortError",
42+});
43+}
44+45+function expectMockCallOptions(
46+mock: ReturnType<typeof vi.fn>,
47+callIndex: number,
48+fields: Record<string, unknown>,
49+) {
50+const call = (mock.mock.calls as unknown[][])[callIndex]?.[0];
51+expectRecordFields(requireRecord(call, `mock call ${callIndex + 1} options`), fields);
52+}
53+54+function expectSomeMockCallOptions(
55+mock: ReturnType<typeof vi.fn>,
56+fields: Record<string, unknown>,
57+) {
58+const calls = mock.mock.calls as unknown[][];
59+const matched = calls.some((call) => {
60+const arg = call[0];
61+if (typeof arg !== "object" || arg === null) {
62+return false;
63+}
64+const record = arg as Record<string, unknown>;
65+return Object.entries(fields).every(([key, value]) => Object.is(record[key], value));
66+});
67+expect(matched).toBe(true);
68+}
69+2170const TEST_UNDICI_RUNTIME_DEPS_KEY = "__OPENCLAW_TEST_UNDICI_RUNTIME_DEPS__";
22712372function clearTestUndiciRuntimeDepsOverride(): void {
@@ -296,7 +345,7 @@ describe("MatrixClient request hardening", () => {
296345const client = new MatrixClient("https://matrix.example.org", "token");
297346expect(client).toBeInstanceOf(MatrixClient);
298347299-expect(lastCreateClientOpts).toMatchObject({
348+expectRecordFields(requireRecord(lastCreateClientOpts, "create client options"), {
300349baseUrl: "https://matrix.example.org",
301350accessToken: "token",
302351});
@@ -394,7 +443,7 @@ describe("MatrixClient request hardening", () => {
394443const event = await client.getEvent("!room:example.org", "$poll");
395444396445expect(matrixJsClient.decryptEventIfNeeded).toHaveBeenCalledTimes(1);
397-expect(event).toMatchObject({
446+expectRecordFields(requireRecord(event, "decrypted event"), {
398447event_id: "$poll",
399448type: "m.poll.start",
400449sender: "@alice:example.org",
@@ -505,14 +554,16 @@ describe("MatrixClient request hardening", () => {
505554506555const page = await client.getRelations("!room:example.org", "$poll", "m.reference");
507556508-expect(page.originalEvent).toMatchObject({ event_id: "$poll", type: "m.poll.start" });
509-expect(page.events).toEqual([
510-expect.objectContaining({
511-event_id: "$vote",
512-type: "m.poll.response",
513-sender: "@bob:example.org",
514-}),
515-]);
557+expectRecordFields(requireRecord(page.originalEvent, "original relation event"), {
558+event_id: "$poll",
559+type: "m.poll.start",
560+});
561+expect(page.events).toHaveLength(1);
562+expectRecordFields(requireRecord(page.events[0], "relation event"), {
563+event_id: "$vote",
564+type: "m.poll.response",
565+sender: "@bob:example.org",
566+});
516567});
517568518569it("blocks cross-protocol redirects when absolute endpoints are allowed", async () => {
@@ -1223,10 +1274,7 @@ describe("MatrixClient event bridge", () => {
1223127412241275abortController.abort();
122512761226-await expect(startPromise).rejects.toMatchObject({
1227-message: "Matrix startup aborted",
1228-name: "AbortError",
1229-});
1277+await expectAbortError(startPromise);
12301278});
1231127912321280it("aborts before post-ready startup work when shutdown races ready sync", async () => {
@@ -1250,10 +1298,7 @@ describe("MatrixClient event bridge", () => {
12501298}
12511299});
125213001253-await expect(client.start({ abortSignal: abortController.signal })).rejects.toMatchObject({
1254-message: "Matrix startup aborted",
1255-name: "AbortError",
1256-});
1301+await expectAbortError(client.start({ abortSignal: abortController.signal }));
12571302expect(bootstrapCryptoSpy).not.toHaveBeenCalled();
12581303});
12591304@@ -1367,11 +1412,11 @@ describe("MatrixClient crypto bootstrapping", () => {
1367141213681413await client.start();
136914141370-expect(bootstrapCrossSigning).toHaveBeenCalledWith(
1371-expect.objectContaining({
1372-authUploadDeviceSigningKeys: expect.any(Function),
1373-}),
1415+const crossSigningOptions = requireRecord(
1416+(bootstrapCrossSigning.mock.calls as unknown[][])[0]?.[0],
1417+"cross-signing options",
13741418);
1419+expect(crossSigningOptions.authUploadDeviceSigningKeys).toBeTypeOf("function");
13751420});
1376142113771422it("trusts the own Matrix identity after completed self-verification", async () => {
@@ -1623,12 +1668,8 @@ describe("MatrixClient crypto bootstrapping", () => {
16231668debug?: (...args: unknown[]) => void;
16241669getChild?: (namespace: string) => unknown;
16251670} | null;
1626-expect(logger).toEqual(
1627-expect.objectContaining({
1628-debug: expect.any(Function),
1629-getChild: expect.any(Function),
1630-}),
1631-);
1671+expect(logger?.debug).toBeTypeOf("function");
1672+expect(logger?.getChild).toBeTypeOf("function");
16321673});
1633167416341675it("passes a custom sync filter to matrix-js-sdk startup", async () => {
@@ -1664,7 +1705,9 @@ describe("MatrixClient crypto bootstrapping", () => {
16641705await client.start();
1665170616661707expect(databasesSpy).toHaveBeenCalled();
1667-expect(setIntervalSpy).toHaveBeenCalledWith(expect.any(Function), 60_000);
1708+const intervalCall = setIntervalSpy.mock.calls[0] as unknown[];
1709+expect(intervalCall[0]).toBeTypeOf("function");
1710+expect(intervalCall[1]).toBe(60_000);
16681711client.stop();
16691712});
16701713@@ -1747,7 +1790,7 @@ describe("MatrixClient crypto bootstrapping", () => {
1747179017481791const status = await client.getOwnDeviceVerificationStatus();
17491792expect(status.verified).toBe(true);
1750-expect(status.backup).toMatchObject({
1793+expectRecordFields(requireRecord(status.backup, "backup status"), {
17511794serverVersion: null,
17521795activeVersion: null,
17531796trusted: null,
@@ -1864,7 +1907,7 @@ describe("MatrixClient crypto bootstrapping", () => {
1864190718651908const status = await client.getDeviceVerificationStatus("@peer:example.org", "PEERDEVICE");
18661909expect(getDeviceVerificationStatus).toHaveBeenCalledWith("@peer:example.org", "PEERDEVICE");
1867-expect(status).toMatchObject({
1910+expectRecordFields(requireRecord(status, "device verification status"), {
18681911deviceId: "PEERDEVICE",
18691912encryptionEnabled: true,
18701913localVerified: true,
@@ -2476,7 +2519,7 @@ describe("MatrixClient crypto bootstrapping", () => {
24762519});
2477252024782521const backup = await client.getRoomKeyBackupStatus();
2479-expect(backup).toMatchObject({
2522+expectRecordFields(requireRecord(backup, "room key backup status"), {
24802523serverVersion: "9",
24812524activeVersion: "9",
24822525trusted: true,
@@ -2520,7 +2563,7 @@ describe("MatrixClient crypto bootstrapping", () => {
25202563});
2521256425222565const backup = await client.getRoomKeyBackupStatus();
2523-expect(backup).toMatchObject({
2566+expectRecordFields(requireRecord(backup, "room key backup status"), {
25242567serverVersion: "49262",
25252568activeVersion: "49262",
25262569trusted: true,
@@ -2801,9 +2844,7 @@ describe("MatrixClient crypto bootstrapping", () => {
28012844expect(result.previousVersion).toBe("21868");
28022845expect(result.deletedVersion).toBe("21868");
28032846expect(result.createdVersion).toBe("21869");
2804-expect(bootstrapSecretStorage).toHaveBeenCalledWith(
2805-expect.objectContaining({ setupNewKeyBackup: true }),
2806-);
2847+expectSomeMockCallOptions(bootstrapSecretStorage, { setupNewKeyBackup: true });
28072848expect(checkKeyBackupAndEnable).toHaveBeenCalledTimes(1);
28082849});
28092850@@ -2853,12 +2894,10 @@ describe("MatrixClient crypto bootstrapping", () => {
2853289428542895expect(result.success).toBe(true);
28552896expect(createRecoveryKeyFromPassphrase).toHaveBeenCalledTimes(1);
2856-expect(bootstrapSecretStorage).toHaveBeenCalledWith(
2857-expect.objectContaining({
2858-setupNewKeyBackup: true,
2859-setupNewSecretStorage: true,
2860-}),
2861-);
2897+expectSomeMockCallOptions(bootstrapSecretStorage, {
2898+setupNewKeyBackup: true,
2899+setupNewSecretStorage: true,
2900+});
28622901});
2863290228642903it("reloads the new backup decryption key after reset when the old cached key mismatches", async () => {
@@ -3007,12 +3046,10 @@ describe("MatrixClient crypto bootstrapping", () => {
30073046expect(result.createdVersion).toBe("22000");
30083047// bootstrapSecretStorage must have been called with setupNewSecretStorage: true
30093048// because the pre-reset bad MAC status triggered forceNewSecretStorage.
3010-expect(bootstrapSecretStorage).toHaveBeenCalledWith(
3011-expect.objectContaining({
3012-setupNewKeyBackup: true,
3013-setupNewSecretStorage: true,
3014-}),
3015-);
3049+expectSomeMockCallOptions(bootstrapSecretStorage, {
3050+setupNewKeyBackup: true,
3051+setupNewSecretStorage: true,
3052+});
30163053expect(loadSessionBackupPrivateKeyFromSecretStorage).toHaveBeenCalledTimes(1);
30173054});
30183055@@ -3064,12 +3101,10 @@ describe("MatrixClient crypto bootstrapping", () => {
30643101expect(result.previousVersion).toBe(null);
30653102expect(result.deletedVersion).toBe(null);
30663103expect(result.createdVersion).toBe("22001");
3067-expect(bootstrapSecretStorage).toHaveBeenCalledWith(
3068-expect.objectContaining({
3069-setupNewKeyBackup: true,
3070-setupNewSecretStorage: true,
3071-}),
3072-);
3104+expectSomeMockCallOptions(bootstrapSecretStorage, {
3105+setupNewKeyBackup: true,
3106+setupNewSecretStorage: true,
3107+});
30733108expect(loadSessionBackupPrivateKeyFromSecretStorage).toHaveBeenCalledTimes(1);
30743109expect(doRequest).not.toHaveBeenCalledWith(
30753110"DELETE",
@@ -3122,12 +3157,10 @@ describe("MatrixClient crypto bootstrapping", () => {
3122315731233158expect(result.success).toBe(true);
31243159expect(result.createdVersion).toBe("22002");
3125-expect(bootstrapSecretStorage).toHaveBeenCalledWith(
3126-expect.objectContaining({
3127-setupNewKeyBackup: true,
3128-setupNewSecretStorage: true,
3129-}),
3130-);
3160+expectSomeMockCallOptions(bootstrapSecretStorage, {
3161+setupNewKeyBackup: true,
3162+setupNewSecretStorage: true,
3163+});
31313164expect(loadSessionBackupPrivateKeyFromSecretStorage).toHaveBeenCalledTimes(1);
31323165});
31333166@@ -3307,9 +3340,7 @@ describe("MatrixClient crypto bootstrapping", () => {
3307334033083341expect(result.success).toBe(true);
33093342expect(result.verification.backupVersion).toBe("7");
3310-expect(bootstrapSecretStorage).toHaveBeenCalledWith(
3311-expect.objectContaining({ setupNewKeyBackup: true }),
3312-);
3343+expectSomeMockCallOptions(bootstrapSecretStorage, { setupNewKeyBackup: true });
33133344});
3314334533153346it("does not recreate key backup during bootstrap when one already exists", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。