Skip to content

Commit c537a36

Browse files
authoredFeb 10, 2025··
MatrixClient.setAccountData: await remote echo. (#4695)
* Rewrite `deleteAccountData` test use fetch-mock rather than whatever this was * `MatrixClient.setAccountData`: await remote echo Wait for the echo to come back from the server before we assume the account data has been successfully set * Update integration tests Fix up the integ tests which call `setAccountData` and now need a sync response. * Address review comment
1 parent 30d9b05 commit c537a36

File tree

6 files changed

+303
-80
lines changed

6 files changed

+303
-80
lines changed
 

‎spec/integ/crypto/cross-signing.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ describe("cross-signing", () => {
269269
// a *different* device. Then, when we call `bootstrapCrossSigning` again, it should do the honours.
270270

271271
mockSetupCrossSigningRequests();
272-
const accountDataAccumulator = new AccountDataAccumulator();
272+
const accountDataAccumulator = new AccountDataAccumulator(syncResponder);
273273
accountDataAccumulator.interceptGetAccountData();
274274

275275
const authDict = { type: "test" };

‎spec/integ/crypto/crypto.spec.ts

+6-34
Original file line numberDiff line numberDiff line change
@@ -1760,7 +1760,7 @@ describe("crypto", () => {
17601760

17611761
beforeEach(async () => {
17621762
createSecretStorageKey.mockClear();
1763-
accountDataAccumulator = new AccountDataAccumulator();
1763+
accountDataAccumulator = new AccountDataAccumulator(syncResponder);
17641764
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
17651765
await startClientAndAwaitFirstSync();
17661766
});
@@ -1787,28 +1787,18 @@ describe("crypto", () => {
17871787
repeat: 1,
17881788
overwriteRoutes: true,
17891789
});
1790-
accountDataAccumulator.sendSyncResponseWithUpdatedAccountData(syncResponder);
17911790
if (content.key) {
17921791
return content.key;
17931792
}
17941793
}
17951794
}
17961795

1797-
function awaitMegolmBackupKeyUpload(): Promise<Record<string, {}>> {
1798-
return new Promise((resolve) => {
1799-
// Called when the megolm backup key is uploaded
1800-
fetchMock.put(
1801-
`express:/_matrix/client/v3/user/:userId/account_data/m.megolm_backup.v1`,
1802-
(url: string, options: RequestInit) => {
1803-
const content = JSON.parse(options.body as string);
1804-
// update account data for sync response
1805-
accountDataAccumulator.accountDataEvents.set("m.megolm_backup.v1", content);
1806-
resolve(content.encrypted);
1807-
return {};
1808-
},
1809-
{ overwriteRoutes: true },
1810-
);
1796+
async function awaitMegolmBackupKeyUpload(): Promise<Record<string, {}>> {
1797+
const content = await accountDataAccumulator.interceptSetAccountData("m.megolm_backup.v1", {
1798+
repeat: 1,
1799+
overwriteRoutes: true,
18111800
});
1801+
return content.encrypted;
18121802
}
18131803

18141804
function awaitAccountDataUpdate(type: string): Promise<void> {
@@ -1866,9 +1856,6 @@ describe("crypto", () => {
18661856
// wait for bootstrapSecretStorage to finished
18671857
await bootstrapPromise;
18681858

1869-
// Return the newly created key in the sync response
1870-
accountDataAccumulator.sendSyncResponseWithUpdatedAccountData(syncResponder);
1871-
18721859
// Finally ensure backup is working
18731860
await aliceClient.getCrypto()!.checkKeyBackupAndEnable();
18741861

@@ -1928,9 +1915,6 @@ describe("crypto", () => {
19281915
expect(keyContent.iv).toBeDefined();
19291916
expect(keyContent.mac).toBeDefined();
19301917

1931-
// Return the newly created key in the sync response
1932-
accountDataAccumulator.sendSyncResponseWithUpdatedAccountData(syncResponder);
1933-
19341918
// Finally, wait for bootstrapSecretStorage to finished
19351919
await bootstrapPromise;
19361920

@@ -1950,9 +1934,6 @@ describe("crypto", () => {
19501934
// Wait for the key to be uploaded in the account data
19511935
await awaitSecretStorageKeyStoredInAccountData();
19521936

1953-
// Return the newly created key in the sync response
1954-
accountDataAccumulator.sendSyncResponseWithUpdatedAccountData(syncResponder);
1955-
19561937
// Wait for bootstrapSecretStorage to finished
19571938
await bootstrapPromise;
19581939

@@ -1971,9 +1952,6 @@ describe("crypto", () => {
19711952
// Wait for the key to be uploaded in the account data
19721953
await awaitSecretStorageKeyStoredInAccountData();
19731954

1974-
// Return the newly created key in the sync response
1975-
accountDataAccumulator.sendSyncResponseWithUpdatedAccountData(syncResponder);
1976-
19771955
// Wait for bootstrapSecretStorage to finished
19781956
await bootstrapPromise;
19791957

@@ -1985,9 +1963,6 @@ describe("crypto", () => {
19851963
// Wait for the key to be uploaded in the account data
19861964
await awaitSecretStorageKeyStoredInAccountData();
19871965

1988-
// Return the newly created key in the sync response
1989-
accountDataAccumulator.sendSyncResponseWithUpdatedAccountData(syncResponder);
1990-
19911966
// Wait for bootstrapSecretStorage to finished
19921967
await bootstrapPromise;
19931968

@@ -2009,9 +1984,6 @@ describe("crypto", () => {
20091984
// Wait for the key to be uploaded in the account data
20101985
const secretStorageKey = await awaitSecretStorageKeyStoredInAccountData();
20111986

2012-
// Return the newly created key in the sync response
2013-
accountDataAccumulator.sendSyncResponseWithUpdatedAccountData(syncResponder);
2014-
20151987
// Wait for the cross signing keys to be uploaded
20161988
const [masterKey, userSigningKey, selfSigningKey] = await Promise.all([
20171989
awaitCrossSigningKeyUpload("master"),

‎spec/test-utils/AccountDataAccumulator.ts

+14-4
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,23 @@ import fetchMock from "fetch-mock-jest";
1919
import { type ISyncResponder } from "./SyncResponder";
2020

2121
/**
22-
* An object which intercepts `account_data` get and set requests via fetch-mock.
22+
* An object which intercepts `account_data` get and set requests via fetch-mock.
23+
*
24+
* To use this, call {@link interceptSetAccountData} for each type of account date that should be handled. The updated
25+
* account data will be stored in {@link accountDataEvents}; it will also trigger a sync response echoing the updated
26+
* data.
27+
*
28+
* Optionally, you can also call {@link interceptGetAccountData}.
2329
*/
2430
export class AccountDataAccumulator {
2531
/**
2632
* The account data events to be returned by the sync.
2733
* Will be updated when fetchMock intercepts calls to PUT `/_matrix/client/v3/user/:userId/account_data/`.
28-
* Will be used by `sendSyncResponseWithUpdatedAccountData`
2934
*/
3035
public accountDataEvents: Map<string, any> = new Map();
3136

37+
public constructor(private syncResponder: ISyncResponder) {}
38+
3239
/**
3340
* Intercept requests to set a particular type of account data.
3441
*
@@ -53,6 +60,9 @@ export class AccountDataAccumulator {
5360
// update account data for sync response
5461
this.accountDataEvents.set(type!, content);
5562
resolve(content);
63+
64+
// return a sync response
65+
this.sendSyncResponseWithUpdatedAccountData();
5666
return {};
5767
},
5868
opts,
@@ -90,9 +100,9 @@ export class AccountDataAccumulator {
90100
/**
91101
* Send a sync response the current account data events.
92102
*/
93-
public sendSyncResponseWithUpdatedAccountData(syncResponder: ISyncResponder): void {
103+
private sendSyncResponseWithUpdatedAccountData(): void {
94104
try {
95-
syncResponder.sendOrQueueSyncResponse({
105+
this.syncResponder.sendOrQueueSyncResponse({
96106
next_batch: 1,
97107
account_data: {
98108
events: Array.from(this.accountDataEvents, ([type, content]) => ({

‎spec/test-utils/mockEndpoints.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ import { type KeyBackupInfo } from "../../src/crypto-api";
2222
* Mock out the endpoints that the js-sdk calls when we call `MatrixClient.start()`.
2323
*
2424
* @param homeserverUrl - the homeserver url for the client under test
25+
* @param userId - the local user's ID. Defaults to `@alice:localhost`.
2526
*/
26-
export function mockInitialApiRequests(homeserverUrl: string) {
27+
export function mockInitialApiRequests(homeserverUrl: string, userId: string = "@alice:localhost") {
2728
fetchMock.getOnce(
2829
new URL("/_matrix/client/versions", homeserverUrl).toString(),
2930
{ versions: ["v1.1"] },
@@ -35,7 +36,7 @@ export function mockInitialApiRequests(homeserverUrl: string) {
3536
{ overwriteRoutes: true },
3637
);
3738
fetchMock.postOnce(
38-
new URL("/_matrix/client/v3/user/%40alice%3Alocalhost/filter", homeserverUrl).toString(),
39+
new URL(`/_matrix/client/v3/user/${encodeURIComponent(userId)}/filter`, homeserverUrl).toString(),
3940
{ filter_id: "fid" },
4041
{ overwriteRoutes: true },
4142
);

0 commit comments

Comments
 (0)
Please sign in to comment.