Initial SpaceStore tests work
This commit is contained in:
parent
e219fe082a
commit
fba7465ad4
3 changed files with 272 additions and 2 deletions
244
test/stores/SpaceStore-test.ts
Normal file
244
test/stores/SpaceStore-test.ts
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
|
||||||
|
import "../skinned-sdk"; // Must be first for skinning to work
|
||||||
|
import SpaceStore from "../../src/stores/SpaceStore";
|
||||||
|
import { setupAsyncStoreWithClient } from "../utils/test-utils";
|
||||||
|
import { createTestClient, mkEvent, mkStubRoom } from "../test-utils";
|
||||||
|
import { EnhancedMap } from "../../src/utils/maps";
|
||||||
|
import SettingsStore from "../../src/settings/SettingsStore";
|
||||||
|
|
||||||
|
type MatrixEvent = any; // importing from js-sdk upsets things
|
||||||
|
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
const mockStateEventImplementation = (events: MatrixEvent[]) => {
|
||||||
|
const stateMap = new EnhancedMap<string, Map<string, MatrixEvent>>();
|
||||||
|
events.forEach(event => {
|
||||||
|
stateMap.getOrCreate(event.getType(), new Map()).set(event.getStateKey(), event);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (eventType: string, stateKey?: string) => {
|
||||||
|
if (stateKey || stateKey === "") {
|
||||||
|
return stateMap.get(eventType)?.get(stateKey) || null;
|
||||||
|
}
|
||||||
|
return Array.from(stateMap.get(eventType)?.values() || []);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const testUserId = "@test:user";
|
||||||
|
|
||||||
|
let rooms = [];
|
||||||
|
|
||||||
|
const mkSpace = (spaceId: string, children: string[] = []) => {
|
||||||
|
const space = mkStubRoom(spaceId);
|
||||||
|
space.isSpaceRoom.mockReturnValue(true);
|
||||||
|
space.currentState.getStateEvents.mockImplementation(mockStateEventImplementation(children.map(roomId =>
|
||||||
|
mkEvent({
|
||||||
|
event: true,
|
||||||
|
type: EventType.SpaceChild,
|
||||||
|
room: spaceId,
|
||||||
|
user: testUserId,
|
||||||
|
skey: roomId,
|
||||||
|
content: { via: [] },
|
||||||
|
ts: Date.now(),
|
||||||
|
}),
|
||||||
|
)));
|
||||||
|
rooms.push(space);
|
||||||
|
return space;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getValue = jest.fn();
|
||||||
|
SettingsStore.getValue = getValue;
|
||||||
|
|
||||||
|
describe("SpaceStore", () => {
|
||||||
|
const store = SpaceStore.instance;
|
||||||
|
const client = createTestClient();
|
||||||
|
|
||||||
|
const run = async () => {
|
||||||
|
client.getRoom.mockImplementation(roomId => rooms.find(room => room.roomId === roomId));
|
||||||
|
await setupAsyncStoreWithClient(store, client);
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
client.getVisibleRooms.mockReturnValue(rooms = []);
|
||||||
|
getValue.mockImplementation(settingName => {
|
||||||
|
if (settingName === "feature_spaces") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
// @ts-ignore
|
||||||
|
store.onNotReady();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("static hierarchy resolution tests", () => {
|
||||||
|
it("handles no spaces", async () => {
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(store.spacePanelSpaces).toStrictEqual([]);
|
||||||
|
expect(store.invitedSpaces).toStrictEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles 3 joined top level spaces", async () => {
|
||||||
|
mkSpace("!space1:server");
|
||||||
|
mkSpace("!space2:server");
|
||||||
|
mkSpace("!space3:server");
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(store.spacePanelSpaces.sort()).toStrictEqual(client.getVisibleRooms().sort());
|
||||||
|
expect(store.invitedSpaces).toStrictEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles a basic hierarchy", async () => {
|
||||||
|
mkSpace("!space1:server");
|
||||||
|
mkSpace("!space2:server");
|
||||||
|
mkSpace("!company:server", [
|
||||||
|
mkSpace("!company_dept1:server", [
|
||||||
|
mkSpace("!company_dept1_group1:server").roomId,
|
||||||
|
]).roomId,
|
||||||
|
mkSpace("!company_dept2:server").roomId,
|
||||||
|
]);
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(store.spacePanelSpaces.map(r => r.roomId).sort()).toStrictEqual([
|
||||||
|
"!space1:server",
|
||||||
|
"!space2:server",
|
||||||
|
"!company:server",
|
||||||
|
].sort());
|
||||||
|
expect(store.invitedSpaces).toStrictEqual([]);
|
||||||
|
// TODO verify actual tree structure
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles a sub-space existing in multiple places in the space tree", async () => {
|
||||||
|
const subspace = mkSpace("!subspace:server");
|
||||||
|
mkSpace("!space1:server");
|
||||||
|
mkSpace("!space2:server");
|
||||||
|
mkSpace("!company:server", [
|
||||||
|
mkSpace("!company_dept1:server", [
|
||||||
|
mkSpace("!company_dept1_group1:server", [subspace.roomId]).roomId,
|
||||||
|
]).roomId,
|
||||||
|
mkSpace("!company_dept2:server", [subspace.roomId]).roomId,
|
||||||
|
subspace.roomId,
|
||||||
|
]);
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(store.spacePanelSpaces.map(r => r.roomId).sort()).toStrictEqual([
|
||||||
|
"!space1:server",
|
||||||
|
"!space2:server",
|
||||||
|
"!company:server",
|
||||||
|
].sort());
|
||||||
|
expect(store.invitedSpaces).toStrictEqual([]);
|
||||||
|
// TODO verify actual tree structure
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles basic cycles", async () => {
|
||||||
|
// TODO test all input order permutations
|
||||||
|
mkSpace("!a:server", [
|
||||||
|
mkSpace("!b:server", [
|
||||||
|
mkSpace("!c:server", [
|
||||||
|
"!a:server",
|
||||||
|
]).roomId,
|
||||||
|
]).roomId,
|
||||||
|
]);
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(store.spacePanelSpaces.map(r => r.roomId)).toStrictEqual(["!a:server"]);
|
||||||
|
expect(store.invitedSpaces).toStrictEqual([]);
|
||||||
|
// TODO verify actual tree structure
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles complex cycles", async () => {
|
||||||
|
// TODO test all input order permutations
|
||||||
|
mkSpace("!b:server", [
|
||||||
|
mkSpace("!a:server", [
|
||||||
|
mkSpace("!c:server", [
|
||||||
|
"!a:server",
|
||||||
|
]).roomId,
|
||||||
|
]).roomId,
|
||||||
|
]);
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(store.spacePanelSpaces.map(r => r.roomId)).toStrictEqual(["!b:server"]);
|
||||||
|
expect(store.invitedSpaces).toStrictEqual([]);
|
||||||
|
// TODO verify actual tree structure
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles really complex cycles", async () => {
|
||||||
|
// TODO test all input order permutations
|
||||||
|
mkSpace("!a:server", [
|
||||||
|
mkSpace("!b:server", [
|
||||||
|
mkSpace("!c:server", [
|
||||||
|
"!a:server",
|
||||||
|
mkSpace("!d:server").roomId,
|
||||||
|
]).roomId,
|
||||||
|
]).roomId,
|
||||||
|
]);
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(store.spacePanelSpaces.map(r => r.roomId)).toStrictEqual(["!a:server"]);
|
||||||
|
expect(store.invitedSpaces).toStrictEqual([]);
|
||||||
|
// TODO verify actual tree structure
|
||||||
|
// TODO this test should be failing right now
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("home space behaviour", () => {
|
||||||
|
test.todo("home space contains orphaned rooms");
|
||||||
|
test.todo("home space contains favourites");
|
||||||
|
test.todo("home space contains dm rooms");
|
||||||
|
test.todo("home space contains invites");
|
||||||
|
test.todo("home space contains invites even if they are also shown in a space");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("hierarchy resolution update tests", () => {
|
||||||
|
test.todo("updates state when spaces are joined");
|
||||||
|
test.todo("updates state when spaces are left");
|
||||||
|
test.todo("updates state when space invite comes in");
|
||||||
|
test.todo("updates state when space invite is accepted");
|
||||||
|
test.todo("updates state when space invite is rejected");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("notification state tests", () => {
|
||||||
|
test.todo("//notification states");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("room list prefilter tests", () => {
|
||||||
|
test.todo("//room list filter");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("active space switching tests", () => {
|
||||||
|
test.todo("//active space");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("context switching tests", () => {
|
||||||
|
test.todo("//context switching");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("space auto switching tests", () => {
|
||||||
|
test.todo("//auto pick space for a room");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("traverseSpace", () => {
|
||||||
|
test.todo("avoids cycles");
|
||||||
|
test.todo("including rooms");
|
||||||
|
test.todo("excluding rooms");
|
||||||
|
});
|
||||||
|
});
|
|
@ -88,8 +88,8 @@ export function createTestClient() {
|
||||||
* @param {string} opts.type The event.type
|
* @param {string} opts.type The event.type
|
||||||
* @param {string} opts.room The event.room_id
|
* @param {string} opts.room The event.room_id
|
||||||
* @param {string} opts.user The event.user_id
|
* @param {string} opts.user The event.user_id
|
||||||
* @param {string} opts.skey Optional. The state key (auto inserts empty string)
|
* @param {string=} opts.skey Optional. The state key (auto inserts empty string)
|
||||||
* @param {Number} opts.ts Optional. Timestamp for the event
|
* @param {number=} opts.ts Optional. Timestamp for the event
|
||||||
* @param {Object} opts.content The event.content
|
* @param {Object} opts.content The event.content
|
||||||
* @param {boolean} opts.event True to make a MatrixEvent.
|
* @param {boolean} opts.event True to make a MatrixEvent.
|
||||||
* @return {Object} a JSON object representing this event.
|
* @return {Object} a JSON object representing this event.
|
||||||
|
@ -244,6 +244,7 @@ export function mkStubRoom(roomId = null) {
|
||||||
getDMInviter: jest.fn(),
|
getDMInviter: jest.fn(),
|
||||||
getAvatarUrl: () => 'mxc://avatar.url/room.png',
|
getAvatarUrl: () => 'mxc://avatar.url/room.png',
|
||||||
getMxcAvatarUrl: () => 'mxc://avatar.url/room.png',
|
getMxcAvatarUrl: () => 'mxc://avatar.url/room.png',
|
||||||
|
isSpaceRoom: jest.fn(() => false),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
25
test/utils/test-utils.ts
Normal file
25
test/utils/test-utils.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
|
import {AsyncStoreWithClient} from "../../src/stores/AsyncStoreWithClient";
|
||||||
|
|
||||||
|
export const setupAsyncStoreWithClient = async (store: AsyncStoreWithClient<any>, client: MatrixClient) => {
|
||||||
|
// @ts-ignore
|
||||||
|
store.readyStore.useUnitTestClient(client);
|
||||||
|
// @ts-ignore
|
||||||
|
await store.onReady();
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue