From 107575692996f89123e082156767ab0f4e3760e0 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 23 Apr 2021 09:55:30 +0100 Subject: [PATCH] add more tests --- src/stores/SpaceStore.tsx | 4 +- test/stores/SpaceStore-test.ts | 73 +++++++++++++++++++++++++++++----- test/utils/test-utils.ts | 10 ++++- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx index a9a73e164f..a6ccf314d9 100644 --- a/src/stores/SpaceStore.tsx +++ b/src/stores/SpaceStore.tsx @@ -583,7 +583,9 @@ export class SpaceStoreClass extends AsyncStoreWithClient { return state; } - // traverse space tree with DFS calling fn on each space including the given root one + // traverse space tree with DFS calling fn on each space including the given root one, + // if includeRooms is true then fn will be called on each leaf room, if it is present in multiple sub-spaces + // then fn will be called with it multiple times. public traverseSpace( spaceId: string, fn: (roomId: string) => void, diff --git a/test/stores/SpaceStore-test.ts b/test/stores/SpaceStore-test.ts index 60960fd5cf..5528fff66d 100644 --- a/test/stores/SpaceStore-test.ts +++ b/test/stores/SpaceStore-test.ts @@ -18,7 +18,7 @@ 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 { resetAsyncStoreWithClient, setupAsyncStoreWithClient } from "../utils/test-utils"; import { createTestClient, mkEvent, mkStubRoom } from "../test-utils"; import { EnhancedMap } from "../../src/utils/maps"; import SettingsStore from "../../src/settings/SettingsStore"; @@ -45,8 +45,14 @@ const testUserId = "@test:user"; let rooms = []; +const mkRoom = (roomId: string) => { + const room = mkStubRoom(roomId); + rooms.push(room); + return room; +}; + const mkSpace = (spaceId: string, children: string[] = []) => { - const space = mkStubRoom(spaceId); + const space = mkRoom(spaceId); space.isSpaceRoom.mockReturnValue(true); space.currentState.getStateEvents.mockImplementation(mockStateEventImplementation(children.map(roomId => mkEvent({ @@ -59,7 +65,6 @@ const mkSpace = (spaceId: string, children: string[] = []) => { ts: Date.now(), }), ))); - rooms.push(space); return space; }; @@ -84,9 +89,8 @@ describe("SpaceStore", () => { } }); }); - afterEach(() => { - // @ts-ignore - store.onNotReady(); + afterEach(async () => { + await resetAsyncStoreWithClient(store); }); describe("static hierarchy resolution tests", () => { @@ -237,8 +241,59 @@ describe("SpaceStore", () => { }); describe("traverseSpace", () => { - test.todo("avoids cycles"); - test.todo("including rooms"); - test.todo("excluding rooms"); + beforeEach(() => { + mkSpace("!a:server", [ + mkSpace("!b:server", [ + mkSpace("!c:server", [ + "!a:server", + mkRoom("!c-child:server").roomId, + mkRoom("!shared-child:server").roomId, + ]).roomId, + mkRoom("!b-child:server").roomId, + ]).roomId, + mkRoom("!a-child:server").roomId, + "!shared-child:server", + ]); + }); + + it("avoids cycles", () => { + const seenMap = new Map(); + store.traverseSpace("!b:server", roomId => { + seenMap.set(roomId, (seenMap.get(roomId) || 0) + 1); + }); + + expect(seenMap.size).toBe(3); + expect(seenMap.get("!a:server")).toBe(1); + expect(seenMap.get("!b:server")).toBe(1); + expect(seenMap.get("!c:server")).toBe(1); + }); + + it("including rooms", () => { + const seenMap = new Map(); + store.traverseSpace("!b:server", roomId => { + seenMap.set(roomId, (seenMap.get(roomId) || 0) + 1); + }, true); + + expect(seenMap.size).toBe(7); + expect(seenMap.get("!a:server")).toBe(1); + expect(seenMap.get("!a-child:server")).toBe(1); + expect(seenMap.get("!b:server")).toBe(1); + expect(seenMap.get("!b-child:server")).toBe(1); + expect(seenMap.get("!c:server")).toBe(1); + expect(seenMap.get("!c-child:server")).toBe(1); + expect(seenMap.get("!shared-child:server")).toBe(2); + }); + + it("excluding rooms", () => { + const seenMap = new Map(); + store.traverseSpace("!b:server", roomId => { + seenMap.set(roomId, (seenMap.get(roomId) || 0) + 1); + }, false); + + expect(seenMap.size).toBe(3); + expect(seenMap.get("!a:server")).toBe(1); + expect(seenMap.get("!b:server")).toBe(1); + expect(seenMap.get("!c:server")).toBe(1); + }); }); }); diff --git a/test/utils/test-utils.ts b/test/utils/test-utils.ts index f86196ffbd..af92987a3d 100644 --- a/test/utils/test-utils.ts +++ b/test/utils/test-utils.ts @@ -15,7 +15,10 @@ limitations under the License. */ import { MatrixClient } from "matrix-js-sdk/src/client"; -import {AsyncStoreWithClient} from "../../src/stores/AsyncStoreWithClient"; +import { AsyncStoreWithClient } from "../../src/stores/AsyncStoreWithClient"; + +// These methods make some use of some private methods on the AsyncStoreWithClient to simplify getting into a consistent +// ready state without needing to wire up a dispatcher and pretend to be a js-sdk client. export const setupAsyncStoreWithClient = async (store: AsyncStoreWithClient, client: MatrixClient) => { // @ts-ignore @@ -23,3 +26,8 @@ export const setupAsyncStoreWithClient = async (store: AsyncStoreWithClient // @ts-ignore await store.onReady(); }; + +export const resetAsyncStoreWithClient = async (store: AsyncStoreWithClient) => { + // @ts-ignore + await store.onNotReady(); +};