1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-07-30 04:23:07 +03:00

Merge branch 'develop' into madlittlemods/stablize-msc3030-timestamp-to-event

Conflicts:
	spec/unit/matrix-client.spec.ts
	src/client.ts
This commit is contained in:
Eric Eastwood
2022-12-08 18:29:14 -06:00
163 changed files with 7453 additions and 6686 deletions

View File

@ -17,14 +17,8 @@ limitations under the License.
import { mocked } from "jest-mock";
import { logger } from "../../src/logger";
import { MatrixClient, ClientEvent } from "../../src/client";
import { ClientEvent, ITurnServerResponse, MatrixClient, Store } from "../../src/client";
import { Filter } from "../../src/filter";
import {
Method,
ClientPrefix,
IRequestOpts,
} from "../../src/http-api";
import { QueryDict } from "../../src/utils";
import { DEFAULT_TREE_POWER_LEVELS_TEMPLATE } from "../../src/models/MSC3089TreeSpace";
import {
EventType,
@ -42,7 +36,18 @@ import { ReceiptType } from "../../src/@types/read_receipts";
import * as testUtils from "../test-utils/test-utils";
import { makeBeaconInfoContent } from "../../src/content-helpers";
import { M_BEACON_INFO } from "../../src/@types/beacon";
import { ContentHelpers, EventTimeline, MatrixError, Room } from "../../src";
import {
ContentHelpers,
ClientPrefix,
Direction,
EventTimeline, ICreateRoomOpts,
IRequestOpts,
MatrixError,
MatrixHttpApi,
MatrixScheduler,
Method,
Room,
} from "../../src";
import { supportsMatrixCall } from "../../src/webrtc/call";
import { makeBeaconEvent } from "../test-utils/beacon";
import {
@ -50,6 +55,9 @@ import {
POLICIES_ACCOUNT_EVENT_TYPE,
PolicyScope,
} from "../../src/models/invites-ignorer";
import { IOlmDevice } from "../../src/crypto/algorithms/megolm";
import { QueryDict } from "../../src/utils";
import { SyncState } from "../../src/sync";
jest.useFakeTimers();
@ -71,17 +79,37 @@ function convertQueryDictToStringRecord(queryDict?: QueryDict): Record<string, s
}, {} as Record<string, string>);
}
type HttpLookup = {
method: string;
path: string;
prefix?: string;
data?: Record<string, any>;
error?: object;
expectBody?: Record<string, any>;
expectQueryParams?: QueryDict;
thenCall?: Function;
};
interface Options extends ICreateRoomOpts {
_roomId?: string;
}
type WrappedRoom = Room & {
_options: Options;
_state: Map<string, any>;
};
describe("MatrixClient", function() {
const userId = "@alice:bar";
const identityServerUrl = "https://identity.server";
const identityServerDomain = "identity.server";
let client;
let store;
let scheduler;
let client: MatrixClient;
let store: Store;
let scheduler: MatrixScheduler;
const KEEP_ALIVE_PATH = "/_matrix/client/versions";
const PUSH_RULES_RESPONSE = {
const PUSH_RULES_RESPONSE: HttpLookup = {
method: "GET",
path: "/pushrules/",
data: {},
@ -89,7 +117,7 @@ describe("MatrixClient", function() {
const FILTER_PATH = "/user/" + encodeURIComponent(userId) + "/filter";
const FILTER_RESPONSE = {
const FILTER_RESPONSE: HttpLookup = {
method: "POST",
path: FILTER_PATH,
data: { filter_id: "f1lt3r" },
@ -101,23 +129,14 @@ describe("MatrixClient", function() {
rooms: {},
};
const SYNC_RESPONSE = {
const SYNC_RESPONSE: HttpLookup = {
method: "GET",
path: "/sync",
data: SYNC_DATA,
};
// items are popped off when processed and block if no items left.
let httpLookups: {
method: string;
path: string;
prefix?: string;
data?: object;
error?: object;
expectBody?: object;
expectQueryParams?: QueryDict;
thenCall?: Function;
}[] = [];
let httpLookups: HttpLookup[] = [];
let acceptKeepalives: boolean;
let pendingLookup: {
promise: Promise<any>;
@ -128,7 +147,7 @@ describe("MatrixClient", function() {
method: Method,
path: string,
queryParams?: QueryDict,
body?: Body,
body?: BodyInit,
requestOpts: IRequestOpts = {},
) {
const { prefix } = requestOpts;
@ -224,24 +243,38 @@ describe("MatrixClient", function() {
userId: userId,
});
// FIXME: We shouldn't be yanking http like this.
client.http = [
"authedRequest", "getContentUri", "request", "uploadContent",
].reduce((r, k) => { r[k] = jest.fn(); return r; }, {});
client.http.authedRequest.mockImplementation(httpReq);
client.http.request.mockImplementation(httpReq);
client.http = ([
"authedRequest",
"getContentUri",
"request",
"uploadContent",
] as const).reduce((r, k) => {
r[k] = jest.fn();
return r;
}, {} as MatrixHttpApi<any>);
mocked(client.http.authedRequest).mockImplementation(httpReq);
mocked(client.http.request).mockImplementation(httpReq);
}
beforeEach(function() {
scheduler = [
"getQueueForEvent", "queueEvent", "removeEventFromQueue",
scheduler = ([
"getQueueForEvent",
"queueEvent",
"removeEventFromQueue",
"setProcessFunction",
].reduce((r, k) => { r[k] = jest.fn(); return r; }, {});
store = [
] as const).reduce((r, k) => {
r[k] = jest.fn();
return r;
}, {} as MatrixScheduler);
store = ([
"getRoom", "getRooms", "getUser", "getSyncToken", "scrollback",
"save", "wantsSave", "setSyncToken", "storeEvents", "storeRoom", "storeUser",
"getFilterIdByName", "setFilterIdByName", "getFilter", "storeFilter",
"getSyncAccumulator", "startup", "deleteAllData",
].reduce((r, k) => { r[k] = jest.fn(); return r; }, {});
"startup", "deleteAllData",
] as const).reduce((r, k) => {
r[k] = jest.fn();
return r;
}, {} as Store);
store.getSavedSync = jest.fn().mockReturnValue(Promise.resolve(null));
store.getSavedSyncToken = jest.fn().mockReturnValue(Promise.resolve(null));
store.setSyncData = jest.fn().mockReturnValue(Promise.resolve(null));
@ -265,7 +298,7 @@ describe("MatrixClient", function() {
// means they may call /events and then fail an expect() which will fail
// a DIFFERENT test (pollution between tests!) - we return unresolved
// promises to stop the client from continuing to run.
client.http.authedRequest.mockImplementation(function() {
mocked(client.http.authedRequest).mockImplementation(function() {
return new Promise(() => {});
});
client.stopClient();
@ -287,10 +320,10 @@ describe("MatrixClient", function() {
},
}];
await client.timestampToEvent(roomId, 0, 'f');
await client.timestampToEvent(roomId, 0, Direction.Forward);
expect(client.http.authedRequest.mock.calls.length).toStrictEqual(1);
const [method, path, queryParams,, { prefix }] = client.http.authedRequest.mock.calls[0];
expect(mocked(client.http.authedRequest).mock.calls.length).toStrictEqual(1);
const [method, path, queryParams,, { prefix }] = mocked(client.http.authedRequest).mock.calls[0];
expect(method).toStrictEqual('GET');
expect(prefix).toStrictEqual(ClientPrefix.V1);
expect(path).toStrictEqual(
@ -326,16 +359,16 @@ describe("MatrixClient", function() {
},
}];
await client.timestampToEvent(roomId, 0, 'f');
await client.timestampToEvent(roomId, 0, Direction.Forward);
expect(client.http.authedRequest.mock.calls.length).toStrictEqual(2);
expect(mocked(client.http.authedRequest).mock.calls.length).toStrictEqual(2);
const [
stableMethod,
stablePath,
stableQueryParams,
,
{ prefix: stablePrefix },
] = client.http.authedRequest.mock.calls[0];
] = mocked(client.http.authedRequest).mock.calls[0];
expect(stableMethod).toStrictEqual('GET');
expect(stablePrefix).toStrictEqual(ClientPrefix.V1);
expect(stablePath).toStrictEqual(
@ -352,7 +385,7 @@ describe("MatrixClient", function() {
unstableQueryParams,
,
{ prefix: unstablePrefix },
] = client.http.authedRequest.mock.calls[1];
] = mocked(client.http.authedRequest).mock.calls[1];
expect(unstableMethod).toStrictEqual('GET');
expect(unstablePrefix).toStrictEqual(unstableMSC3030Prefix);
expect(unstablePath).toStrictEqual(
@ -379,10 +412,10 @@ describe("MatrixClient", function() {
},
}];
await expect(client.timestampToEvent(roomId, 0, 'f')).rejects.toBeDefined();
await expect(client.timestampToEvent(roomId, 0, Direction.Forward)).rejects.toBeDefined();
expect(client.http.authedRequest.mock.calls.length).toStrictEqual(1);
const [method, path, queryParams,, { prefix }] = client.http.authedRequest.mock.calls[0];
expect(mocked(client.http.authedRequest).mock.calls.length).toStrictEqual(1);
const [method, path, queryParams,, { prefix }] = mocked(client.http.authedRequest).mock.calls[0];
expect(method).toStrictEqual('GET');
expect(prefix).toStrictEqual(ClientPrefix.V1);
expect(path).toStrictEqual(
@ -453,7 +486,7 @@ describe("MatrixClient", function() {
const txnId = client.makeTxnId();
const room = new Room(roomId, client, userId);
store.getRoom.mockReturnValue(room);
mocked(store.getRoom).mockReturnValue(room);
const rootEvent = new MatrixEvent({ event_id: threadId });
room.createThread(threadId, rootEvent, [rootEvent], false);
@ -493,7 +526,7 @@ describe("MatrixClient", function() {
};
const room = new Room(roomId, client, userId);
store.getRoom.mockReturnValue(room);
mocked(store.getRoom).mockReturnValue(room);
const rootEvent = new MatrixEvent({ event_id: threadId });
room.createThread(threadId, rootEvent, [rootEvent], false);
@ -523,7 +556,7 @@ describe("MatrixClient", function() {
const userId = "@test:example.org";
const roomId = "!room:example.org";
const roomName = "Test Tree";
const mockRoom = {};
const mockRoom = {} as unknown as Room;
const fn = jest.fn().mockImplementation((opts) => {
expect(opts).toMatchObject({
name: roomName,
@ -595,23 +628,23 @@ describe("MatrixClient", function() {
throw new Error("Unexpected event type or state key");
}
},
},
};
} as Room["currentState"],
} as unknown as Room;
client.getRoom = (getRoomId) => {
expect(getRoomId).toEqual(roomId);
return mockRoom;
};
const tree = client.unstableGetFileTreeSpace(roomId);
expect(tree).toBeDefined();
expect(tree.roomId).toEqual(roomId);
expect(tree.room).toBe(mockRoom);
expect(tree!.roomId).toEqual(roomId);
expect(tree!.room).toBe(mockRoom);
});
it("should not get (unstable) file trees if not joined", async () => {
const roomId = "!room:example.org";
const mockRoom = {
getMyMembership: () => "leave", // "not join"
};
} as unknown as Room;
client.getRoom = (getRoomId) => {
expect(getRoomId).toEqual(roomId);
return mockRoom;
@ -655,8 +688,8 @@ describe("MatrixClient", function() {
throw new Error("Unexpected event type or state key");
}
},
},
};
} as Room["currentState"],
} as unknown as Room;
client.getRoom = (getRoomId) => {
expect(getRoomId).toEqual(roomId);
return mockRoom;
@ -689,8 +722,8 @@ describe("MatrixClient", function() {
throw new Error("Unexpected event type or state key");
}
},
},
};
} as Room["currentState"],
} as unknown as Room;
client.getRoom = (getRoomId) => {
expect(getRoomId).toEqual(roomId);
return mockRoom;
@ -705,15 +738,15 @@ describe("MatrixClient", function() {
SYNC_RESPONSE,
];
const filterId = "ehfewf";
store.getFilterIdByName.mockReturnValue(filterId);
mocked(store.getFilterIdByName).mockReturnValue(filterId);
const filter = new Filter("0", filterId);
filter.setDefinition({ "room": { "timeline": { "limit": 8 } } });
store.getFilter.mockReturnValue(filter);
mocked(store.getFilter).mockReturnValue(filter);
const syncPromise = new Promise<void>((resolve, reject) => {
client.on("sync", function syncListener(state) {
client.on(ClientEvent.Sync, function syncListener(state) {
if (state === "SYNCING") {
expect(httpLookups.length).toEqual(0);
client.removeListener("sync", syncListener);
client.removeListener(ClientEvent.Sync, syncListener);
resolve();
} else if (state === "ERROR") {
reject(new Error("sync error"));
@ -731,10 +764,10 @@ describe("MatrixClient", function() {
it("should return the same sync state as emitted sync events", async function() {
const syncingPromise = new Promise<void>((resolve) => {
client.on("sync", function syncListener(state) {
client.on(ClientEvent.Sync, function syncListener(state) {
expect(state).toEqual(client.getSyncState());
if (state === "SYNCING") {
client.removeListener("sync", syncListener);
client.removeListener(ClientEvent.Sync, syncListener);
resolve();
}
});
@ -750,7 +783,7 @@ describe("MatrixClient", function() {
it("should use an existing filter if id is present in localStorage", function() {
});
it("should handle localStorage filterId missing from the server", function(done) {
function getFilterName(userId, suffix?: string) {
function getFilterName(userId: string, suffix?: string) {
// scope this on the user ID because people may login on many accounts
// and they all need to be stored!
return "FILTER_SYNC_" + userId + (suffix ? "_" + suffix : "");
@ -769,14 +802,14 @@ describe("MatrixClient", function() {
},
});
httpLookups.push(FILTER_RESPONSE);
store.getFilterIdByName.mockReturnValue(invalidFilterId);
mocked(store.getFilterIdByName).mockReturnValue(invalidFilterId);
const filterName = getFilterName(client.credentials.userId);
const filterName = getFilterName(client.credentials.userId!);
client.store.setFilterIdByName(filterName, invalidFilterId);
const filter = new Filter(client.credentials.userId);
client.getOrCreateFilter(filterName, filter).then(function(filterId) {
expect(filterId).toEqual(FILTER_RESPONSE.data.filter_id);
expect(filterId).toEqual(FILTER_RESPONSE.data?.filter_id);
done();
});
});
@ -798,13 +831,13 @@ describe("MatrixClient", function() {
httpLookups.push(FILTER_RESPONSE);
httpLookups.push(SYNC_RESPONSE);
client.on("sync", function syncListener(state) {
client.on(ClientEvent.Sync, function syncListener(state) {
if (state === "ERROR" && httpLookups.length > 0) {
expect(httpLookups.length).toEqual(2);
expect(client.retryImmediately()).toBe(true);
jest.advanceTimersByTime(1);
} else if (state === "PREPARED" && httpLookups.length === 0) {
client.removeListener("sync", syncListener);
client.removeListener(ClientEvent.Sync, syncListener);
done();
} else {
// unexpected state transition!
@ -822,7 +855,7 @@ describe("MatrixClient", function() {
method: "GET", path: "/sync", data: SYNC_DATA,
});
client.on("sync", function syncListener(state) {
client.on(ClientEvent.Sync, function syncListener(state) {
if (state === "ERROR" && httpLookups.length > 0) {
expect(httpLookups.length).toEqual(1);
expect(client.retryImmediately()).toBe(
@ -832,7 +865,7 @@ describe("MatrixClient", function() {
} else if (state === "RECONNECTING" && httpLookups.length > 0) {
jest.advanceTimersByTime(10000);
} else if (state === "SYNCING" && httpLookups.length === 0) {
client.removeListener("sync", syncListener);
client.removeListener(ClientEvent.Sync, syncListener);
done();
}
});
@ -848,13 +881,13 @@ describe("MatrixClient", function() {
httpLookups.push(FILTER_RESPONSE);
httpLookups.push(SYNC_RESPONSE);
client.on("sync", function syncListener(state) {
client.on(ClientEvent.Sync, function syncListener(state) {
if (state === "ERROR" && httpLookups.length > 0) {
expect(httpLookups.length).toEqual(3);
expect(client.retryImmediately()).toBe(true);
jest.advanceTimersByTime(1);
} else if (state === "PREPARED" && httpLookups.length === 0) {
client.removeListener("sync", syncListener);
client.removeListener(ClientEvent.Sync, syncListener);
done();
} else {
// unexpected state transition!
@ -866,8 +899,8 @@ describe("MatrixClient", function() {
});
describe("emitted sync events", function() {
function syncChecker(expectedStates, done) {
return function syncListener(state, old) {
function syncChecker(expectedStates: [string, string | null][], done: Function) {
return function syncListener(state: SyncState, old: SyncState | null) {
const expected = expectedStates.shift();
logger.log(
"'sync' curr=%s old=%s EXPECT=%s", state, old, expected,
@ -879,7 +912,7 @@ describe("MatrixClient", function() {
expect(state).toEqual(expected[0]);
expect(old).toEqual(expected[1]);
if (expectedStates.length === 0) {
client.removeListener("sync", syncListener);
client.removeListener(ClientEvent.Sync, syncListener);
done();
}
// standard retry time is 5 to 10 seconds
@ -890,7 +923,7 @@ describe("MatrixClient", function() {
it("should transition null -> PREPARED after the first /sync", function(done) {
const expectedStates: [string, string | null][] = [];
expectedStates.push(["PREPARED", null]);
client.on("sync", syncChecker(expectedStates, done));
client.on(ClientEvent.Sync, syncChecker(expectedStates, done));
client.startClient();
});
@ -902,7 +935,7 @@ describe("MatrixClient", function() {
method: "POST", path: FILTER_PATH, error: { errcode: "NOPE_NOPE_NOPE" },
});
expectedStates.push(["ERROR", null]);
client.on("sync", syncChecker(expectedStates, done));
client.on(ClientEvent.Sync, syncChecker(expectedStates, done));
client.startClient();
});
@ -932,7 +965,7 @@ describe("MatrixClient", function() {
expectedStates.push(["RECONNECTING", null]);
expectedStates.push(["ERROR", "RECONNECTING"]);
expectedStates.push(["CATCHUP", "ERROR"]);
client.on("sync", syncChecker(expectedStates, done));
client.on(ClientEvent.Sync, syncChecker(expectedStates, done));
client.startClient();
});
@ -940,7 +973,7 @@ describe("MatrixClient", function() {
const expectedStates: [string, string | null][] = [];
expectedStates.push(["PREPARED", null]);
expectedStates.push(["SYNCING", "PREPARED"]);
client.on("sync", syncChecker(expectedStates, done));
client.on(ClientEvent.Sync, syncChecker(expectedStates, done));
client.startClient();
});
@ -959,7 +992,7 @@ describe("MatrixClient", function() {
expectedStates.push(["SYNCING", "PREPARED"]);
expectedStates.push(["RECONNECTING", "SYNCING"]);
expectedStates.push(["ERROR", "RECONNECTING"]);
client.on("sync", syncChecker(expectedStates, done));
client.on(ClientEvent.Sync, syncChecker(expectedStates, done));
client.startClient();
});
@ -973,7 +1006,7 @@ describe("MatrixClient", function() {
expectedStates.push(["PREPARED", null]);
expectedStates.push(["SYNCING", "PREPARED"]);
expectedStates.push(["ERROR", "SYNCING"]);
client.on("sync", syncChecker(expectedStates, done));
client.on(ClientEvent.Sync, syncChecker(expectedStates, done));
client.startClient();
});
@ -985,7 +1018,7 @@ describe("MatrixClient", function() {
expectedStates.push(["PREPARED", null]);
expectedStates.push(["SYNCING", "PREPARED"]);
expectedStates.push(["SYNCING", "SYNCING"]);
client.on("sync", syncChecker(expectedStates, done));
client.on(ClientEvent.Sync, syncChecker(expectedStates, done));
client.startClient();
});
@ -1009,7 +1042,7 @@ describe("MatrixClient", function() {
expectedStates.push(["RECONNECTING", "SYNCING"]);
expectedStates.push(["ERROR", "RECONNECTING"]);
expectedStates.push(["ERROR", "ERROR"]);
client.on("sync", syncChecker(expectedStates, done));
client.on(ClientEvent.Sync, syncChecker(expectedStates, done));
client.startClient();
});
});
@ -1078,14 +1111,14 @@ describe("MatrixClient", function() {
throw new Error("Unexpected event type or state key");
}
},
},
} as Room["currentState"],
getThread: jest.fn(),
addPendingEvent: jest.fn(),
updatePendingEvent: jest.fn(),
reEmitter: {
reEmit: jest.fn(),
},
};
} as unknown as Room;
beforeEach(() => {
client.getRoom = (getRoomId) => {
@ -1151,7 +1184,7 @@ describe("MatrixClient", function() {
const mockRoom = {
getMyMembership: () => "join",
updatePendingEvent: (event, status) => event.setStatus(status),
updatePendingEvent: (event: MatrixEvent, status: EventStatus) => event.setStatus(status),
currentState: {
getStateEvents: (eventType, stateKey) => {
if (eventType === EventType.RoomCreate) {
@ -1168,15 +1201,14 @@ describe("MatrixClient", function() {
throw new Error("Unexpected event type or state key");
}
},
},
};
} as Room["currentState"],
} as unknown as Room;
let event;
let event: MatrixEvent;
beforeEach(async () => {
event = new MatrixEvent({
event_id: "~" + roomId + ":" + txnId,
user_id: client.credentials.userId,
sender: client.credentials.userId,
sender: client.credentials.userId!,
room_id: roomId,
origin_server_ts: new Date().getTime(),
});
@ -1187,25 +1219,26 @@ describe("MatrixClient", function() {
return mockRoom;
};
client.crypto = { // mock crypto
encryptEvent: (event, room) => new Promise(() => {}),
encryptEvent: () => new Promise(() => {}),
stop: jest.fn(),
};
} as unknown as Crypto;
});
function assertCancelled() {
expect(event.status).toBe(EventStatus.CANCELLED);
expect(client.scheduler.removeEventFromQueue(event)).toBeFalsy();
expect(client.scheduler?.removeEventFromQueue(event)).toBeFalsy();
expect(httpLookups.filter(h => h.path.includes("/send/")).length).toBe(0);
}
it("should cancel an event which is queued", () => {
event.setStatus(EventStatus.QUEUED);
client.scheduler.queueEvent(event);
client.scheduler?.queueEvent(event);
client.cancelPendingEvent(event);
assertCancelled();
});
it("should cancel an event which is encrypting", async () => {
// @ts-ignore protected method access
client.encryptAndSendEvent(null, event);
await testUtils.emitPromise(event, "Event.status");
client.cancelPendingEvent(event);
@ -1267,7 +1300,7 @@ describe("MatrixClient", function() {
const room = {
hasPendingEvent: jest.fn().mockReturnValue(false),
addLocalEchoReceipt: jest.fn(),
};
} as unknown as Room;
const rrEvent = new MatrixEvent({ event_id: "read_event_id" });
const rpEvent = new MatrixEvent({ event_id: "read_private_event_id" });
client.getRoom = () => room;
@ -1306,7 +1339,7 @@ describe("MatrixClient", function() {
const content = makeBeaconInfoContent(100, true);
beforeEach(() => {
client.http.authedRequest.mockClear().mockResolvedValue({});
mocked(client.http.authedRequest).mockClear().mockResolvedValue({});
});
it("creates new beacon info", async () => {
@ -1314,7 +1347,7 @@ describe("MatrixClient", function() {
// event type combined
const expectedEventType = M_BEACON_INFO.name;
const [method, path, queryParams, requestContent] = client.http.authedRequest.mock.calls[0];
const [method, path, queryParams, requestContent] = mocked(client.http.authedRequest).mock.calls[0];
expect(method).toBe('PUT');
expect(path).toEqual(
`/rooms/${encodeURIComponent(roomId)}/state/` +
@ -1328,7 +1361,7 @@ describe("MatrixClient", function() {
await client.unstable_setLiveBeacon(roomId, content);
// event type combined
const [, path, , requestContent] = client.http.authedRequest.mock.calls[0];
const [, path, , requestContent] = mocked(client.http.authedRequest).mock.calls[0];
expect(path).toEqual(
`/rooms/${encodeURIComponent(roomId)}/state/` +
`${encodeURIComponent(M_BEACON_INFO.name)}/${encodeURIComponent(userId)}`,
@ -1406,7 +1439,7 @@ describe("MatrixClient", function() {
const newPassword = 'newpassword';
const passwordTest = (expectedRequestContent: any) => {
const [method, path, queryParams, requestContent] = client.http.authedRequest.mock.calls[0];
const [method, path, queryParams, requestContent] = mocked(client.http.authedRequest).mock.calls[0];
expect(method).toBe('POST');
expect(path).toEqual('/account/password');
expect(queryParams).toBeFalsy();
@ -1414,7 +1447,7 @@ describe("MatrixClient", function() {
};
beforeEach(() => {
client.http.authedRequest.mockClear().mockResolvedValue({});
mocked(client.http.authedRequest).mockClear().mockResolvedValue({});
});
it("no logout_devices specified", async () => {
@ -1453,13 +1486,13 @@ describe("MatrixClient", function() {
const response = {
aliases: ["#woop:example.org", "#another:example.org"],
};
client.http.authedRequest.mockClear().mockResolvedValue(response);
mocked(client.http.authedRequest).mockClear().mockResolvedValue(response);
const roomId = "!whatever:example.org";
const result = await client.getLocalAliases(roomId);
// Current version of the endpoint we support is v3
const [method, path, queryParams, data, opts] = client.http.authedRequest.mock.calls[0];
const [method, path, queryParams, data, opts] = mocked(client.http.authedRequest).mock.calls[0];
expect(data).toBeFalsy();
expect(method).toBe('GET');
expect(path).toEqual(`/rooms/${encodeURIComponent(roomId)}/aliases`);
@ -1516,11 +1549,11 @@ describe("MatrixClient", function() {
],
username: "1443779631:@user:example.com",
password: "JlKfBy1QwLrO20385QyAtEyIv0=",
};
} as unknown as ITurnServerResponse;
jest.spyOn(client, "turnServer").mockResolvedValue(turnServer);
const events: any[][] = [];
const onTurnServers = (...args) => events.push(args);
const onTurnServers = (...args: any[]) => events.push(args);
client.on(ClientEvent.TurnServers, onTurnServers);
expect(await client.checkTurnServers()).toBe(true);
client.off(ClientEvent.TurnServers, onTurnServers);
@ -1536,7 +1569,7 @@ describe("MatrixClient", function() {
jest.spyOn(client, "turnServer").mockRejectedValue(error);
const events: any[][] = [];
const onTurnServersError = (...args) => events.push(args);
const onTurnServersError = (...args: any[]) => events.push(args);
client.on(ClientEvent.TurnServersError, onTurnServersError);
expect(await client.checkTurnServers()).toBe(false);
client.off(ClientEvent.TurnServersError, onTurnServersError);
@ -1548,7 +1581,7 @@ describe("MatrixClient", function() {
jest.spyOn(client, "turnServer").mockRejectedValue(error);
const events: any[][] = [];
const onTurnServersError = (...args) => events.push(args);
const onTurnServersError = (...args: any[]) => events.push(args);
client.on(ClientEvent.TurnServersError, onTurnServersError);
expect(await client.checkTurnServers()).toBe(false);
client.off(ClientEvent.TurnServersError, onTurnServersError);
@ -1564,7 +1597,7 @@ describe("MatrixClient", function() {
it("is an alias for the crypto method", async () => {
client.crypto = testUtils.mock(Crypto, "Crypto");
const deviceInfos = [];
const deviceInfos: IOlmDevice[] = [];
const payload = {};
await client.encryptAndSendToDevices(deviceInfos, payload);
expect(client.crypto.encryptAndSendToDevices).toHaveBeenLastCalledWith(deviceInfos, payload);
@ -1577,7 +1610,7 @@ describe("MatrixClient", function() {
const dataStore = new Map();
client.setAccountData = function(eventType, content) {
dataStore.set(eventType, content);
return Promise.resolve();
return Promise.resolve({});
};
client.getAccountData = function(eventType) {
const data = dataStore.get(eventType);
@ -1588,9 +1621,9 @@ describe("MatrixClient", function() {
// Mockup `createRoom`/`getRoom`/`joinRoom`, including state.
const rooms = new Map();
client.createRoom = function(options = {}) {
client.createRoom = function(options: Options = {}) {
const roomId = options["_roomId"] || `!room-${rooms.size}:example.org`;
const state = new Map();
const state = new Map<string, any>();
const room = {
roomId,
_options: options,
@ -1608,24 +1641,24 @@ describe("MatrixClient", function() {
},
};
},
};
} as EventTimeline;
},
};
},
};
} as unknown as WrappedRoom;
rooms.set(roomId, room);
return Promise.resolve({ room_id: roomId });
};
client.getRoom = function(roomId) {
return rooms.get(roomId);
};
client.joinRoom = function(roomId) {
return this.getRoom(roomId) || this.createRoom({ _roomId: roomId });
client.joinRoom = async function(roomId) {
return this.getRoom(roomId)! || this.createRoom({ _roomId: roomId } as ICreateRoomOpts);
};
// Mockup state events
client.sendStateEvent = function(roomId, type, content) {
const room = this.getRoom(roomId);
const room = this.getRoom(roomId) as WrappedRoom;
const state: Map<string, any> = room._state;
let store = state.get(type);
if (!store) {
@ -1644,14 +1677,15 @@ describe("MatrixClient", function() {
return content;
},
};
return { event_id: eventId };
return Promise.resolve({ event_id: eventId });
};
client.redactEvent = function(roomId, eventId) {
const room = this.getRoom(roomId);
const room = this.getRoom(roomId) as WrappedRoom;
const state: Map<string, any> = room._state;
for (const store of state.values()) {
delete store[eventId];
delete store[eventId!];
}
return Promise.resolve({ event_id: "$" + eventId + "-" + Math.random() });
};
});
@ -1687,7 +1721,7 @@ describe("MatrixClient", function() {
roomId: "!snafu:somewhere.org",
});
expect(ruleMatch).toBeTruthy();
expect(ruleMatch.getContent()).toMatchObject({
expect(ruleMatch!.getContent()).toMatchObject({
recommendation: "m.ban",
reason: "just a test",
});
@ -1716,7 +1750,7 @@ describe("MatrixClient", function() {
roomId: "!snafu:somewhere.org",
});
expect(ruleSenderMatch).toBeTruthy();
expect(ruleSenderMatch.getContent()).toMatchObject({
expect(ruleSenderMatch!.getContent()).toMatchObject({
recommendation: "m.ban",
reason: REASON,
});
@ -1726,7 +1760,7 @@ describe("MatrixClient", function() {
roomId: "!snafu:example.org",
});
expect(ruleRoomMatch).toBeTruthy();
expect(ruleRoomMatch.getContent()).toMatchObject({
expect(ruleRoomMatch!.getContent()).toMatchObject({
recommendation: "m.ban",
reason: REASON,
});
@ -1751,7 +1785,7 @@ describe("MatrixClient", function() {
roomId: BAD_ROOM_ID,
});
expect(ruleSenderMatch).toBeTruthy();
expect(ruleSenderMatch.getContent()).toMatchObject({
expect(ruleSenderMatch!.getContent()).toMatchObject({
recommendation: "m.ban",
reason: REASON,
});
@ -1785,7 +1819,7 @@ describe("MatrixClient", function() {
roomId: "!snafu:somewhere.org",
});
expect(ruleMatch).toBeTruthy();
expect(ruleMatch.getContent()).toMatchObject({
expect(ruleMatch!.getContent()).toMatchObject({
recommendation: "m.ban",
reason: "just a test",
});
@ -1813,13 +1847,13 @@ describe("MatrixClient", function() {
roomId: "!snafu:somewhere.org",
});
expect(ruleMatch).toBeTruthy();
expect(ruleMatch.getContent()).toMatchObject({
expect(ruleMatch!.getContent()).toMatchObject({
recommendation: "m.ban",
reason: "just a test",
});
// After removing the invite, we shouldn't reject it anymore.
await client.ignoredInvites.removeRule(ruleMatch);
await client.ignoredInvites.removeRule(ruleMatch as MatrixEvent);
const ruleMatch2 = await client.ignoredInvites.getRuleForInvite({
sender: "@foobar:example.org",
roomId: "!snafu:somewhere.org",
@ -1833,10 +1867,10 @@ describe("MatrixClient", function() {
// Make sure that everything is initialized.
await client.ignoredInvites.getOrCreateSourceRooms();
await client.joinRoom(NEW_SOURCE_ROOM_ID);
const newSourceRoom = client.getRoom(NEW_SOURCE_ROOM_ID);
const newSourceRoom = client.getRoom(NEW_SOURCE_ROOM_ID) as WrappedRoom;
// Fetch the list of sources and check that we do not have the new room yet.
const policies = await client.getAccountData(POLICIES_ACCOUNT_EVENT_TYPE.name).getContent();
const policies = await client.getAccountData(POLICIES_ACCOUNT_EVENT_TYPE.name)!.getContent();
expect(policies).toBeTruthy();
const ignoreInvites = policies[IGNORE_INVITES_ACCOUNT_EVENT_KEY.name];
expect(ignoreInvites).toBeTruthy();
@ -1850,7 +1884,7 @@ describe("MatrixClient", function() {
expect(added2).toBe(false);
// Fetch the list of sources and check that we have added the new room.
const policies2 = await client.getAccountData(POLICIES_ACCOUNT_EVENT_TYPE.name).getContent();
const policies2 = await client.getAccountData(POLICIES_ACCOUNT_EVENT_TYPE.name)!.getContent();
expect(policies2).toBeTruthy();
const ignoreInvites2 = policies2[IGNORE_INVITES_ACCOUNT_EVENT_KEY.name];
expect(ignoreInvites2).toBeTruthy();
@ -1862,7 +1896,7 @@ describe("MatrixClient", function() {
// Check where it shows up.
const targetRoomId = ignoreInvites2.target;
const targetRoom = client.getRoom(targetRoomId);
const targetRoom = client.getRoom(targetRoomId) as WrappedRoom;
expect(targetRoom._state.get(PolicyScope.User)[eventId]).toBeTruthy();
expect(newSourceRoom._state.get(PolicyScope.User)?.[eventId]).toBeFalsy();
});