Refactor pill and add tests (#10304)
This commit is contained in:
parent
c0e40217f3
commit
ad26925bb6
10 changed files with 653 additions and 275 deletions
189
test/components/views/elements/Pill-test.tsx
Normal file
189
test/components/views/elements/Pill-test.tsx
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
Copyright 2023 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 React from "react";
|
||||
import { act, render, RenderResult, screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { mocked, Mocked } from "jest-mock";
|
||||
import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import dis from "../../../../src/dispatcher/dispatcher";
|
||||
import { Pill, PillProps, PillType } from "../../../../src/components/views/elements/Pill";
|
||||
import {
|
||||
filterConsole,
|
||||
flushPromises,
|
||||
mkRoomCanonicalAliasEvent,
|
||||
mkRoomMemberJoinEvent,
|
||||
stubClient,
|
||||
} from "../../../test-utils";
|
||||
import DMRoomMap from "../../../../src/utils/DMRoomMap";
|
||||
import { Action } from "../../../../src/dispatcher/actions";
|
||||
|
||||
describe("<Pill>", () => {
|
||||
let client: Mocked<MatrixClient>;
|
||||
const permalinkPrefix = "https://matrix.to/#/";
|
||||
const room1Alias = "#room1:example.com";
|
||||
const room1Id = "!room1:example.com";
|
||||
let room1: Room;
|
||||
const user1Id = "@user1:example.com";
|
||||
const user2Id = "@user2:example.com";
|
||||
let renderResult: RenderResult;
|
||||
|
||||
const renderPill = (props: PillProps): void => {
|
||||
const withDefault = {
|
||||
inMessage: true,
|
||||
shouldShowPillAvatar: true,
|
||||
...props,
|
||||
} as PillProps;
|
||||
renderResult = render(<Pill {...withDefault} />);
|
||||
};
|
||||
|
||||
filterConsole(
|
||||
"Failed to parse permalink Error: Unknown entity type in permalink",
|
||||
"Room !room1:example.com does not have an m.room.create event",
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
client = mocked(stubClient());
|
||||
DMRoomMap.makeShared();
|
||||
room1 = new Room(room1Id, client, client.getSafeUserId());
|
||||
room1.name = "Room 1";
|
||||
const user1JoinRoom1Event = mkRoomMemberJoinEvent(user1Id, room1Id, {
|
||||
displayname: "User 1",
|
||||
});
|
||||
room1.currentState.setStateEvents([
|
||||
mkRoomCanonicalAliasEvent(client.getSafeUserId(), room1Id, room1Alias),
|
||||
user1JoinRoom1Event,
|
||||
]);
|
||||
room1.getMember(user1Id)!.setMembershipEvent(user1JoinRoom1Event);
|
||||
|
||||
client.getRooms.mockReturnValue([room1]);
|
||||
client.getRoom.mockImplementation((roomId: string) => {
|
||||
if (roomId === room1.roomId) return room1;
|
||||
return null;
|
||||
});
|
||||
|
||||
client.getProfileInfo.mockImplementation(async (userId: string) => {
|
||||
if (userId === user2Id) return { displayname: "User 2" };
|
||||
throw new Error(`Unknown user ${userId}`);
|
||||
});
|
||||
|
||||
jest.spyOn(dis, "dispatch");
|
||||
});
|
||||
|
||||
describe("when rendering a pill for a room", () => {
|
||||
beforeEach(() => {
|
||||
renderPill({
|
||||
url: permalinkPrefix + room1Id,
|
||||
});
|
||||
});
|
||||
|
||||
it("should render the expected pill", () => {
|
||||
expect(renderResult.asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when hovering the pill", () => {
|
||||
beforeEach(async () => {
|
||||
await userEvent.hover(screen.getByText("Room 1"));
|
||||
});
|
||||
|
||||
it("should show a tooltip with the room Id", () => {
|
||||
expect(screen.getByRole("tooltip", { name: room1Id })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe("when not hovering the pill any more", () => {
|
||||
beforeEach(async () => {
|
||||
await userEvent.unhover(screen.getByText("Room 1"));
|
||||
});
|
||||
|
||||
it("should dimiss a tooltip with the room Id", () => {
|
||||
expect(screen.queryByRole("tooltip")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should render the expected pill for a room alias", () => {
|
||||
renderPill({
|
||||
url: permalinkPrefix + room1Alias,
|
||||
});
|
||||
expect(renderResult.asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should render the expected pill for @room", () => {
|
||||
renderPill({
|
||||
room: room1,
|
||||
type: PillType.AtRoomMention,
|
||||
});
|
||||
expect(renderResult.asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when rendering a pill for a user in the room", () => {
|
||||
beforeEach(() => {
|
||||
renderPill({
|
||||
room: room1,
|
||||
url: permalinkPrefix + user1Id,
|
||||
});
|
||||
});
|
||||
|
||||
it("should render as expected", () => {
|
||||
expect(renderResult.asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when clicking the pill", () => {
|
||||
beforeEach(async () => {
|
||||
await userEvent.click(screen.getByText("User 1"));
|
||||
});
|
||||
|
||||
it("should dipsatch a view user action", () => {
|
||||
expect(dis.dispatch).toHaveBeenCalledWith({
|
||||
action: Action.ViewUser,
|
||||
member: room1.getMember(user1Id),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should render the expected pill for a user not in the room", async () => {
|
||||
renderPill({
|
||||
room: room1,
|
||||
url: permalinkPrefix + user2Id,
|
||||
});
|
||||
|
||||
// wait for profile query via API
|
||||
await act(async () => {
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
expect(renderResult.asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should not render anything if the type cannot be detected", () => {
|
||||
renderPill({
|
||||
url: permalinkPrefix,
|
||||
});
|
||||
expect(renderResult.asFragment()).toMatchInlineSnapshot(`<DocumentFragment />`);
|
||||
});
|
||||
|
||||
it("should not render an avatar or link when called with inMessage = false and shouldShowPillAvatar = false", () => {
|
||||
renderPill({
|
||||
inMessage: false,
|
||||
shouldShowPillAvatar: false,
|
||||
url: permalinkPrefix + room1Id,
|
||||
});
|
||||
expect(renderResult.asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
206
test/components/views/elements/__snapshots__/Pill-test.tsx.snap
Normal file
206
test/components/views/elements/__snapshots__/Pill-test.tsx.snap
Normal file
|
@ -0,0 +1,206 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Pill> should not render an avatar or link when called with inMessage = false and shouldShowPillAvatar = false 1`] = `
|
||||
<DocumentFragment>
|
||||
<bdi>
|
||||
<span
|
||||
class="mx_Pill mx_RoomPill"
|
||||
>
|
||||
<span
|
||||
class="mx_Pill_linkText"
|
||||
>
|
||||
Room 1
|
||||
</span>
|
||||
</span>
|
||||
</bdi>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<Pill> should render the expected pill for @room 1`] = `
|
||||
<DocumentFragment>
|
||||
<bdi>
|
||||
<span
|
||||
class="mx_Pill mx_AtRoomPill"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar"
|
||||
role="presentation"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_initial"
|
||||
style="font-size: 10.4px; width: 16px; line-height: 16px;"
|
||||
>
|
||||
R
|
||||
</span>
|
||||
<img
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_image"
|
||||
data-testid="avatar-img"
|
||||
src="data:image/png;base64,00"
|
||||
style="width: 16px; height: 16px;"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="mx_Pill_linkText"
|
||||
>
|
||||
@room
|
||||
</span>
|
||||
</span>
|
||||
</bdi>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<Pill> should render the expected pill for a room alias 1`] = `
|
||||
<DocumentFragment>
|
||||
<bdi>
|
||||
<a
|
||||
class="mx_Pill mx_RoomPill"
|
||||
href="https://matrix.to/#/#room1:example.com"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar"
|
||||
role="presentation"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_initial"
|
||||
style="font-size: 10.4px; width: 16px; line-height: 16px;"
|
||||
>
|
||||
R
|
||||
</span>
|
||||
<img
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_image"
|
||||
data-testid="avatar-img"
|
||||
src="data:image/png;base64,00"
|
||||
style="width: 16px; height: 16px;"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="mx_Pill_linkText"
|
||||
>
|
||||
Room 1
|
||||
</span>
|
||||
</a>
|
||||
</bdi>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<Pill> should render the expected pill for a user not in the room 1`] = `
|
||||
<DocumentFragment>
|
||||
<bdi>
|
||||
<a
|
||||
class="mx_Pill mx_UserPill"
|
||||
href="https://matrix.to/#/@user2:example.com"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar"
|
||||
role="presentation"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_initial"
|
||||
style="font-size: 10.4px; width: 16px; line-height: 16px;"
|
||||
>
|
||||
U
|
||||
</span>
|
||||
<img
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_image"
|
||||
data-testid="avatar-img"
|
||||
src="data:image/png;base64,00"
|
||||
style="width: 16px; height: 16px;"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="mx_Pill_linkText"
|
||||
>
|
||||
User 2
|
||||
</span>
|
||||
</a>
|
||||
</bdi>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<Pill> when rendering a pill for a room should render the expected pill 1`] = `
|
||||
<DocumentFragment>
|
||||
<bdi>
|
||||
<a
|
||||
class="mx_Pill mx_RoomPill"
|
||||
href="https://matrix.to/#/!room1:example.com"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar"
|
||||
role="presentation"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_initial"
|
||||
style="font-size: 10.4px; width: 16px; line-height: 16px;"
|
||||
>
|
||||
R
|
||||
</span>
|
||||
<img
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_image"
|
||||
data-testid="avatar-img"
|
||||
src="data:image/png;base64,00"
|
||||
style="width: 16px; height: 16px;"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="mx_Pill_linkText"
|
||||
>
|
||||
Room 1
|
||||
</span>
|
||||
</a>
|
||||
</bdi>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<Pill> when rendering a pill for a user in the room should render as expected 1`] = `
|
||||
<DocumentFragment>
|
||||
<bdi>
|
||||
<a
|
||||
class="mx_Pill mx_UserPill"
|
||||
href="https://matrix.to/#/@user1:example.com"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar"
|
||||
role="presentation"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_initial"
|
||||
style="font-size: 10.4px; width: 16px; line-height: 16px;"
|
||||
>
|
||||
U
|
||||
</span>
|
||||
<img
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_image"
|
||||
data-testid="avatar-img"
|
||||
src="data:image/png;base64,00"
|
||||
style="width: 16px; height: 16px;"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="mx_Pill_linkText"
|
||||
>
|
||||
User 1
|
||||
</span>
|
||||
</a>
|
||||
</bdi>
|
||||
</DocumentFragment>
|
||||
`;
|
|
@ -152,7 +152,7 @@ describe("<TextualBody />", () => {
|
|||
const { container } = getComponent({ mxEvent: ev });
|
||||
const content = container.querySelector(".mx_EventTile_body");
|
||||
expect(content.innerHTML).toMatchInlineSnapshot(
|
||||
`"Chat with <span><bdi><a class="mx_Pill mx_UserPill"><img class="mx_BaseAvatar mx_BaseAvatar_image" src="mxc://avatar.url/image.png" style="width: 16px; height: 16px;" alt="" data-testid="avatar-img" aria-hidden="true"><span class="mx_Pill_linkText">Member</span></a></bdi></span>"`,
|
||||
`"Chat with <span><bdi><a class="mx_Pill mx_UserPill mx_UserPill_me" href="https://matrix.to/#/@user:example.com"><img class="mx_BaseAvatar mx_BaseAvatar_image" src="mxc://avatar.url/image.png" style="width: 16px; height: 16px;" alt="" data-testid="avatar-img" aria-hidden="true"><span class="mx_Pill_linkText">Member</span></a></bdi></span>"`,
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ exports[`<TextualBody /> renders formatted m.text correctly pills get injected c
|
|||
<bdi>
|
||||
<a
|
||||
class="mx_Pill mx_UserPill"
|
||||
href="https://matrix.to/#/@user:server"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue