You've already forked matrix-js-sdk
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:
@ -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();
|
||||
});
|
||||
|
Reference in New Issue
Block a user