293 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			TypeScript
		
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			TypeScript
		
	
	
/*
 | 
						|
Copyright 2022 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 { mount } from "enzyme";
 | 
						|
import { IProtocol, IPublicRoomsChunkRoom, MatrixClient, RoomMember } from "matrix-js-sdk/src/matrix";
 | 
						|
import { sleep } from "matrix-js-sdk/src/utils";
 | 
						|
import React from "react";
 | 
						|
import { act } from "react-dom/test-utils";
 | 
						|
import sanitizeHtml from "sanitize-html";
 | 
						|
 | 
						|
import SpotlightDialog, { Filter } from "../../../../src/components/views/dialogs/spotlight/SpotlightDialog";
 | 
						|
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
 | 
						|
import { stubClient } from "../../../test-utils";
 | 
						|
 | 
						|
interface IUserChunkMember {
 | 
						|
    user_id: string;
 | 
						|
    display_name?: string;
 | 
						|
    avatar_url?: string;
 | 
						|
}
 | 
						|
 | 
						|
interface MockClientOptions {
 | 
						|
    userId?: string;
 | 
						|
    homeserver?: string;
 | 
						|
    thirdPartyProtocols?: Record<string, IProtocol>;
 | 
						|
    rooms?: IPublicRoomsChunkRoom[];
 | 
						|
    members?: RoomMember[];
 | 
						|
    users?: IUserChunkMember[];
 | 
						|
}
 | 
						|
 | 
						|
function mockClient(
 | 
						|
    {
 | 
						|
        userId = "testuser",
 | 
						|
        homeserver = "example.tld",
 | 
						|
        thirdPartyProtocols = {},
 | 
						|
        rooms = [],
 | 
						|
        members = [],
 | 
						|
        users = [],
 | 
						|
    }: MockClientOptions = {},
 | 
						|
): MatrixClient {
 | 
						|
    stubClient();
 | 
						|
    const cli = MatrixClientPeg.get();
 | 
						|
    MatrixClientPeg.getHomeserverName = jest.fn(() => homeserver);
 | 
						|
    cli.getUserId = jest.fn(() => userId);
 | 
						|
    cli.getHomeserverUrl = jest.fn(() => homeserver);
 | 
						|
    cli.getThirdpartyProtocols = jest.fn(() => Promise.resolve(thirdPartyProtocols));
 | 
						|
    cli.publicRooms = jest.fn((options) => {
 | 
						|
        const searchTerm = options?.filter?.generic_search_term?.toLowerCase();
 | 
						|
        const chunk = rooms.filter(it =>
 | 
						|
            !searchTerm ||
 | 
						|
            it.room_id.toLowerCase().includes(searchTerm) ||
 | 
						|
            it.name?.toLowerCase().includes(searchTerm) ||
 | 
						|
            sanitizeHtml(it?.topic, { allowedTags: [] }).toLowerCase().includes(searchTerm) ||
 | 
						|
            it.canonical_alias?.toLowerCase().includes(searchTerm) ||
 | 
						|
            it.aliases?.find(alias => alias.toLowerCase().includes(searchTerm)));
 | 
						|
        return Promise.resolve({
 | 
						|
            chunk,
 | 
						|
            total_room_count_estimate: chunk.length,
 | 
						|
        });
 | 
						|
    });
 | 
						|
    cli.searchUserDirectory = jest.fn(({ term, limit }) => {
 | 
						|
        const searchTerm = term?.toLowerCase();
 | 
						|
        const results = users.filter(it => !searchTerm ||
 | 
						|
            it.user_id.toLowerCase().includes(searchTerm) ||
 | 
						|
            it.display_name.toLowerCase().includes(searchTerm));
 | 
						|
        return Promise.resolve({
 | 
						|
            results: results.slice(0, limit ?? +Infinity),
 | 
						|
            limited: limit && limit < results.length,
 | 
						|
        });
 | 
						|
    });
 | 
						|
    cli.getProfileInfo = jest.fn(async (userId) => {
 | 
						|
        const member = members.find(it => it.userId === userId);
 | 
						|
        if (member) {
 | 
						|
            return Promise.resolve({
 | 
						|
                displayname: member.rawDisplayName,
 | 
						|
                avatar_url: member.getMxcAvatarUrl(),
 | 
						|
            });
 | 
						|
        } else {
 | 
						|
            return Promise.reject();
 | 
						|
        }
 | 
						|
    });
 | 
						|
    return cli;
 | 
						|
}
 | 
						|
 | 
						|
describe("Spotlight Dialog", () => {
 | 
						|
    const testPerson: IUserChunkMember = {
 | 
						|
        user_id: "@janedoe:matrix.org",
 | 
						|
        display_name: "Jane Doe",
 | 
						|
        avatar_url: undefined,
 | 
						|
    };
 | 
						|
 | 
						|
    const testPublicRoom: IPublicRoomsChunkRoom = {
 | 
						|
        room_id: "@room247:matrix.org",
 | 
						|
        name: "Room #247",
 | 
						|
        topic: "We hope you'll have a <b>shining</b> experience!",
 | 
						|
        world_readable: false,
 | 
						|
        num_joined_members: 1,
 | 
						|
        guest_can_join: false,
 | 
						|
    };
 | 
						|
 | 
						|
    beforeEach(() => {
 | 
						|
        mockClient({ rooms: [testPublicRoom], users: [testPerson] });
 | 
						|
    });
 | 
						|
 | 
						|
    describe("should apply filters supplied via props", () => {
 | 
						|
        it("without filter", async () => {
 | 
						|
            const wrapper = mount(
 | 
						|
                <SpotlightDialog
 | 
						|
                    initialFilter={null}
 | 
						|
                    onFinished={() => null} />,
 | 
						|
            );
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(200);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
 | 
						|
            const filterChip = wrapper.find("div.mx_SpotlightDialog_filter");
 | 
						|
            expect(filterChip.exists()).toBeFalsy();
 | 
						|
 | 
						|
            wrapper.unmount();
 | 
						|
        });
 | 
						|
        it("with public room filter", async () => {
 | 
						|
            const wrapper = mount(
 | 
						|
                <SpotlightDialog
 | 
						|
                    initialFilter={Filter.PublicRooms}
 | 
						|
                    onFinished={() => null} />,
 | 
						|
            );
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(200);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
 | 
						|
            const filterChip = wrapper.find("div.mx_SpotlightDialog_filter");
 | 
						|
            expect(filterChip.exists()).toBeTruthy();
 | 
						|
            expect(filterChip.text()).toEqual("Public rooms");
 | 
						|
 | 
						|
            const content = wrapper.find("#mx_SpotlightDialog_content");
 | 
						|
            const options = content.find("div.mx_SpotlightDialog_option");
 | 
						|
            expect(options.length).toBe(1);
 | 
						|
            expect(options.first().text()).toContain(testPublicRoom.name);
 | 
						|
 | 
						|
            wrapper.unmount();
 | 
						|
        });
 | 
						|
        it("with people filter", async () => {
 | 
						|
            const wrapper = mount(
 | 
						|
                <SpotlightDialog
 | 
						|
                    initialFilter={Filter.People}
 | 
						|
                    initialText={testPerson.display_name}
 | 
						|
                    onFinished={() => null} />,
 | 
						|
            );
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(200);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
 | 
						|
            const filterChip = wrapper.find("div.mx_SpotlightDialog_filter");
 | 
						|
            expect(filterChip.exists()).toBeTruthy();
 | 
						|
            expect(filterChip.text()).toEqual("People");
 | 
						|
 | 
						|
            const content = wrapper.find("#mx_SpotlightDialog_content");
 | 
						|
            const options = content.find("div.mx_SpotlightDialog_option");
 | 
						|
            expect(options.length).toBeGreaterThanOrEqual(1);
 | 
						|
            expect(options.first().text()).toContain(testPerson.display_name);
 | 
						|
 | 
						|
            wrapper.unmount();
 | 
						|
        });
 | 
						|
    });
 | 
						|
 | 
						|
    describe("should apply manually selected filter", () => {
 | 
						|
        it("with public rooms", async () => {
 | 
						|
            const wrapper = mount(
 | 
						|
                <SpotlightDialog
 | 
						|
                    onFinished={() => null} />,
 | 
						|
            );
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(1);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
            wrapper.find("#mx_SpotlightDialog_button_explorePublicRooms").first().simulate("click");
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(200);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
 | 
						|
            const filterChip = wrapper.find("div.mx_SpotlightDialog_filter");
 | 
						|
            expect(filterChip.exists()).toBeTruthy();
 | 
						|
            expect(filterChip.text()).toEqual("Public rooms");
 | 
						|
 | 
						|
            const content = wrapper.find("#mx_SpotlightDialog_content");
 | 
						|
            const options = content.find("div.mx_SpotlightDialog_option");
 | 
						|
            expect(options.length).toBe(1);
 | 
						|
            expect(options.first().text()).toContain(testPublicRoom.name);
 | 
						|
 | 
						|
            wrapper.unmount();
 | 
						|
        });
 | 
						|
        it("with people", async () => {
 | 
						|
            const wrapper = mount(
 | 
						|
                <SpotlightDialog
 | 
						|
                    initialText={testPerson.display_name}
 | 
						|
                    onFinished={() => null} />,
 | 
						|
            );
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(1);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
            wrapper.find("#mx_SpotlightDialog_button_startChat").first().simulate("click");
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(200);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
 | 
						|
            const filterChip = wrapper.find("div.mx_SpotlightDialog_filter");
 | 
						|
            expect(filterChip.exists()).toBeTruthy();
 | 
						|
            expect(filterChip.text()).toEqual("People");
 | 
						|
 | 
						|
            const content = wrapper.find("#mx_SpotlightDialog_content");
 | 
						|
            const options = content.find("div.mx_SpotlightDialog_option");
 | 
						|
            expect(options.length).toBeGreaterThanOrEqual(1);
 | 
						|
            expect(options.first().text()).toContain(testPerson.display_name);
 | 
						|
 | 
						|
            wrapper.unmount();
 | 
						|
        });
 | 
						|
    });
 | 
						|
 | 
						|
    describe("should allow clearing filter manually", () => {
 | 
						|
        it("with public room filter", async () => {
 | 
						|
            const wrapper = mount(
 | 
						|
                <SpotlightDialog
 | 
						|
                    initialFilter={Filter.PublicRooms}
 | 
						|
                    onFinished={() => null} />,
 | 
						|
            );
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(200);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
 | 
						|
            let filterChip = wrapper.find("div.mx_SpotlightDialog_filter");
 | 
						|
            expect(filterChip.exists()).toBeTruthy();
 | 
						|
            expect(filterChip.text()).toEqual("Public rooms");
 | 
						|
 | 
						|
            filterChip.find("div.mx_SpotlightDialog_filter--close").simulate("click");
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(1);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
 | 
						|
            filterChip = wrapper.find("div.mx_SpotlightDialog_filter");
 | 
						|
            expect(filterChip.exists()).toBeFalsy();
 | 
						|
 | 
						|
            wrapper.unmount();
 | 
						|
        });
 | 
						|
        it("with people filter", async () => {
 | 
						|
            const wrapper = mount(
 | 
						|
                <SpotlightDialog
 | 
						|
                    initialFilter={Filter.People}
 | 
						|
                    initialText={testPerson.display_name}
 | 
						|
                    onFinished={() => null} />,
 | 
						|
            );
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(200);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
 | 
						|
            let filterChip = wrapper.find("div.mx_SpotlightDialog_filter");
 | 
						|
            expect(filterChip.exists()).toBeTruthy();
 | 
						|
            expect(filterChip.text()).toEqual("People");
 | 
						|
 | 
						|
            filterChip.find("div.mx_SpotlightDialog_filter--close").simulate("click");
 | 
						|
            await act(async () => {
 | 
						|
                await sleep(1);
 | 
						|
            });
 | 
						|
            wrapper.update();
 | 
						|
 | 
						|
            filterChip = wrapper.find("div.mx_SpotlightDialog_filter");
 | 
						|
            expect(filterChip.exists()).toBeFalsy();
 | 
						|
 | 
						|
            wrapper.unmount();
 | 
						|
        });
 | 
						|
    });
 | 
						|
});
 |