From f89fcd1fe9c3df9d44add57f160bab408b3e5ec6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 7 Jul 2020 15:45:59 -0600 Subject: [PATCH] Fix tests and add general safety We don't need the fake clock anymore, but we do have to wait for async actions to complete before moving forward. This also exposes a number of functions for the store to be puppetted with. --- src/stores/room-list/RoomListStore2.ts | 43 ++++++++++++++------ test/components/views/rooms/RoomList-test.js | 40 ++++++++++-------- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/src/stores/room-list/RoomListStore2.ts b/src/stores/room-list/RoomListStore2.ts index 1acff9d3fd..63c3abdf09 100644 --- a/src/stores/room-list/RoomListStore2.ts +++ b/src/stores/room-list/RoomListStore2.ts @@ -72,6 +72,34 @@ export class RoomListStore2 extends AsyncStore { return this._matrixClient; } + // Intended for test usage + public async resetStore() { + await this.reset(); + this.tagWatcher = new TagWatcher(this); + this.filterConditions = []; + this.initialListsGenerated = false; + this._matrixClient = null; + + this.algorithm.off(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated); + this.algorithm = new Algorithm(); + this.algorithm.on(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated); + } + + // Public for test usage. Do not call this. + public async makeReady(client: MatrixClient) { + // TODO: Remove with https://github.com/vector-im/riot-web/issues/14367 + this.checkEnabled(); + if (!this.enabled) return; + + this._matrixClient = client; + + // Update any settings here, as some may have happened before we were logically ready. + console.log("Regenerating room lists: Startup"); + await this.readAndCacheSettingsFromStore(); + await this.regenerateAllLists(); + this.onRVSUpdate(); // fake an RVS update to adjust sticky room, if needed + } + // TODO: Remove enabled flag with the old RoomListStore: https://github.com/vector-im/riot-web/issues/14367 private checkEnabled() { this.enabled = SettingsStore.getValue("feature_new_room_list"); @@ -115,17 +143,7 @@ export class RoomListStore2 extends AsyncStore { return; } - // TODO: Remove with https://github.com/vector-im/riot-web/issues/14367 - this.checkEnabled(); - if (!this.enabled) return; - - this._matrixClient = payload.matrixClient; - - // Update any settings here, as some may have happened before we were logically ready. - console.log("Regenerating room lists: Startup"); - await this.readAndCacheSettingsFromStore(); - await this.regenerateAllLists(); - this.onRVSUpdate(); // fake an RVS update to adjust sticky room, if needed + await this.makeReady(payload.matrixClient); } // TODO: Remove this once the RoomListStore becomes default @@ -372,7 +390,8 @@ export class RoomListStore2 extends AsyncStore { this.emit(LISTS_UPDATE_EVENT, this); }; - private async regenerateAllLists() { + // This is only exposed externally for the tests. Do not call this within the app. + public async regenerateAllLists() { console.warn("Regenerating all room lists"); const sorts: ITagSortingMap = {}; diff --git a/test/components/views/rooms/RoomList-test.js b/test/components/views/rooms/RoomList-test.js index 681f5ccb6b..ba53676fc1 100644 --- a/test/components/views/rooms/RoomList-test.js +++ b/test/components/views/rooms/RoomList-test.js @@ -15,11 +15,17 @@ import GroupStore from '../../../../src/stores/GroupStore.js'; import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk'; import {DefaultTagID} from "../../../../src/stores/room-list/models"; +import RoomListStore, {LISTS_UPDATE_EVENT} from "../../../../src/stores/room-list/RoomListStore2"; function generateRoomId() { return '!' + Math.random().toString().slice(2, 10) + ':domain'; } +function waitForRoomListStoreUpdate() { + return new Promise((resolve) => { + RoomListStore.instance.once(LISTS_UPDATE_EVENT, () => resolve()); + }); +} describe('RoomList', () => { function createRoom(opts) { @@ -34,7 +40,6 @@ describe('RoomList', () => { let client = null; let root = null; const myUserId = '@me:domain'; - let clock = null; const movingRoomId = '!someroomid'; let movingRoom; @@ -43,15 +48,13 @@ describe('RoomList', () => { let myMember; let myOtherMember; - beforeEach(function() { + beforeEach(async function(done) { TestUtils.stubClient(); client = MatrixClientPeg.get(); client.credentials = {userId: myUserId}; //revert this to prototype method as the test-utils monkey-patches this to return a hardcoded value client.getUserId = MatrixClient.prototype.getUserId; - clock = lolex.install(); - DMRoomMap.makeShared(); parentDiv = document.createElement('div'); @@ -102,16 +105,22 @@ describe('RoomList', () => { }); client.getRoom = (roomId) => roomMap[roomId]; + + // Now that everything has been set up, prepare and update the store + await RoomListStore.instance.makeReady(client); + + done(); }); - afterEach((done) => { + afterEach(async (done) => { if (parentDiv) { ReactDOM.unmountComponentAtNode(parentDiv); parentDiv.remove(); parentDiv = null; } - clock.uninstall(); + await RoomListStore.instance.resetLayouts(); + await RoomListStore.instance.resetStore(); done(); }); @@ -127,6 +136,7 @@ describe('RoomList', () => { try { const roomTiles = ReactTestUtils.scryRenderedComponentsWithType(containingSubList, RoomTile); console.info({roomTiles: roomTiles.length}); + console.log("IS SAME?", room === roomTiles[0].props.room, room, roomTiles[0].props.room); expectedRoomTile = roomTiles.find((tile) => tile.props.room === room); } catch (err) { // truncate the error message because it's spammy @@ -162,17 +172,12 @@ describe('RoomList', () => { dis.dispatch({action: 'MatrixActions.sync', prevState: null, state: 'PREPARED', matrixClient: client}); - clock.runAll(); - expectRoomInSubList(movingRoom, srcSubListTest); dis.dispatch({action: 'RoomListActions.tagRoom.pending', request: { oldTagId, newTagId, room: movingRoom, }}); - // Run all setTimeouts for dispatches and room list rate limiting - clock.runAll(); - expectRoomInSubList(movingRoom, destSubListTest); } @@ -269,6 +274,12 @@ describe('RoomList', () => { }; GroupStore._notifyListeners(); + // We also have to mock the client's getGroup function for the room list to filter it. + // It's not smart enough to tell the difference between a real group and a template though. + client.getGroup = (groupId) => { + return {groupId}; + }; + // Select tag dis.dispatch({action: 'select_tag', tag: '+group:domain'}, true); } @@ -277,16 +288,13 @@ describe('RoomList', () => { setupSelectedTag(); }); - it('displays the correct rooms when the groups rooms are changed', () => { + it('displays the correct rooms when the groups rooms are changed', async () => { GroupStore.getGroupRooms = (groupId) => { return [movingRoom, otherRoom]; }; GroupStore._notifyListeners(); - // Run through RoomList debouncing - clock.runAll(); - - // By default, the test will + await waitForRoomListStoreUpdate(); expectRoomInSubList(otherRoom, (s) => s.props.tagId === DefaultTagID.Untagged); });