Will Hunt c02db4ebb8
Port over linkifyJS to shared-components. (#32731)
* Port over linkifyJS to shared-components.

* Drop rubbish

* update lock

* quickfix test

* drop group id

* Modernize tests

* Remove stories that aren't in use.

* Complete working version

* Add copyright

* tidy up

* update lock

* Update snaps

* update snap

* undo change

* remove unused

* More test updates

* fix typo

* fix margin on preview

* move margin block

* snapupdate

* prettier

* cleanup a test mistake

* Fixup sonar issues

* Don't expose linkifyjs to applications, just provide helper functions.

* Add story for documentation.

* remove $

* Use a const

* typo

* cleanup var name

* remove console line

* Changes checkpoint

* Convert to context

* Revert unrelated change.

* more cleanup

* Add a test to cover ignoring incoming data elements

* Make tests happy

* Update tests for LinkedText

* Underlines!

* fix lock

* remove unused linkify packages

* import move

* Remove mod to remove underline

* undo

* fix snap

* another snapshot fix

* Tidy up based on review.

* fix story

* Pass in args
2026-03-12 15:54:01 +00:00

165 lines
6.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Copyright 2024 New Vector Ltd.
Copyright 2015-2022 The Matrix.org Foundation C.I.C.
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { render, screen } from "jest-matrix-react";
import { EventTimeline, type MatrixClient, Room } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { LinkedTextContext } from "@element-hq/web-shared-components";
import { LocalRoom } from "../../../../../src/models/LocalRoom";
import {
filterConsole,
mkEvent,
mkRoomMemberJoinEvent,
mkThirdPartyInviteEvent,
stubClient,
} from "../../../../test-utils";
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
import NewRoomIntro from "../../../../../src/components/views/rooms/NewRoomIntro";
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
import { DirectoryMember } from "../../../../../src/utils/direct-messages";
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
import defaultDispatcher from "../../../../../src/dispatcher/dispatcher";
import type { RoomContextType } from "../../../../../src/contexts/RoomContext.ts";
const renderNewRoomIntro = (client: MatrixClient, room: Room | LocalRoom) => {
render(
<MatrixClientContext.Provider value={client}>
<ScopedRoomContextProvider {...({ room, roomId: room.roomId } as unknown as RoomContextType)}>
<LinkedTextContext.Provider value={{}}>
<NewRoomIntro />
</LinkedTextContext.Provider>
</ScopedRoomContextProvider>
</MatrixClientContext.Provider>,
);
};
describe("NewRoomIntro", () => {
let client: MatrixClient;
const roomId = "!room:example.com";
const userId = "@user:example.com";
filterConsole("Room !room:example.com does not have an m.room.create event");
beforeEach(() => {
client = stubClient();
DMRoomMap.makeShared(client);
});
afterEach(() => {
jest.resetAllMocks();
});
describe("for a DM Room", () => {
beforeEach(() => {
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(userId);
const room = new Room(roomId, client, client.getUserId()!);
room.name = "test_room";
renderNewRoomIntro(client, room);
});
it("should render the expected intro", () => {
const expected = `This is the beginning of your direct message history with test_room.`;
screen.getByText((id, element) => element?.tagName === "SPAN" && element?.textContent === expected);
});
});
it("should render as expected for a DM room with a single third-party invite", () => {
const room = new Room(roomId, client, client.getSafeUserId());
room.currentState.setStateEvents([
mkRoomMemberJoinEvent(client.getSafeUserId(), room.roomId),
mkThirdPartyInviteEvent(client.getSafeUserId(), "user@example.com", room.roomId),
]);
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(userId);
jest.spyOn(DMRoomMap.shared(), "getRoomIds").mockReturnValue(new Set([room.roomId]));
renderNewRoomIntro(client, room);
expect(screen.getByText("Once everyone has joined, youll be able to chat")).toBeInTheDocument();
expect(
screen.queryByText(
"Only the two of you are in this conversation, unless either of you invites anyone to join.",
),
).not.toBeInTheDocument();
});
describe("for a DM LocalRoom", () => {
beforeEach(() => {
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(userId);
const localRoom = new LocalRoom(roomId, client, client.getUserId()!);
localRoom.name = "test_room";
localRoom.targets.push(new DirectoryMember({ user_id: userId }));
renderNewRoomIntro(client, localRoom);
});
it("should render the expected intro", () => {
const expected = `Send your first message to invite test_room to chat`;
screen.getByText((id, element) => element?.tagName === "SPAN" && element?.textContent === expected);
});
});
describe("topic", () => {
let room: Room;
beforeEach(() => {
room = new Room(roomId, client, userId);
room.getLiveTimeline()
.getState(EventTimeline.FORWARDS)
?.setStateEvents([mkRoomMemberJoinEvent(client.getSafeUserId(), room.roomId)]);
jest.spyOn(DMRoomMap.shared(), "getRoomIds").mockReturnValue(new Set([room.roomId]));
});
function addTopicToRoom(topic: string) {
const topicEvent = mkEvent({
type: "m.room.topic",
room: roomId,
user: userId,
content: {
topic,
},
ts: 123,
event: true,
});
room.addLiveEvents([topicEvent], { addToState: true });
}
it("should render the topic", () => {
addTopicToRoom("Test topic");
renderNewRoomIntro(client, room);
screen.getByText("Test topic");
});
it("should render a link in the topic", () => {
addTopicToRoom("This is a link: https://matrix.org/");
renderNewRoomIntro(client, room);
expect(screen.getByTestId("topic")).toMatchSnapshot();
});
it("should be able to add a topic", () => {
addTopicToRoom("Test topic");
jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join);
jest.spyOn(room.getLiveTimeline().getState(EventTimeline.FORWARDS)!, "maySendStateEvent").mockReturnValue(
true,
);
const spyDispatcher = jest.spyOn(defaultDispatcher, "dispatch");
renderNewRoomIntro(client, room);
screen.getByRole("button", { name: "edit" }).click();
expect(spyDispatcher).toHaveBeenCalledWith(
{
action: "open_room_settings",
room_id: room.roomId,
},
true,
);
});
});
});