diff --git a/res/css/structures/_SpaceRoomView.pcss b/res/css/structures/_SpaceRoomView.pcss index dff60c3fb5..a4a4aa7884 100644 --- a/res/css/structures/_SpaceRoomView.pcss +++ b/res/css/structures/_SpaceRoomView.pcss @@ -189,10 +189,6 @@ limitations under the License. .mx_FacePile { display: inline-block; - - .mx_FacePile_faces { - cursor: pointer; - } } .mx_SpaceRoomView_landing_inviteButton, diff --git a/res/css/views/elements/_FacePile.pcss b/res/css/views/elements/_FacePile.pcss index 2976873b1a..ecc801cb51 100644 --- a/res/css/views/elements/_FacePile.pcss +++ b/res/css/views/elements/_FacePile.pcss @@ -14,53 +14,32 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_FacePile { - display: flex; - align-items: center; +.mx_FacePile_more { + position: relative; + border-radius: 100%; + width: 30px; + height: 30px; + background-color: $spacePanel-bg-color; - .mx_FacePile_faces { - display: inline-flex; - flex-direction: row-reverse; - vertical-align: middle; - margin: 0 -1px; /* to cancel out the border on the edges */ - - /* Overlap the children */ - > * + * { - margin-right: -8px; - } - - .mx_BaseAvatar { - border: 1px solid var(--facepile-background, $background); - } - - .mx_FacePile_more { - position: relative; - border-radius: 100%; - width: 30px; - height: 30px; - background-color: $spacePanel-bg-color; - - &::before { - content: ""; - z-index: 1; - position: absolute; - top: 0; - left: 0; - height: inherit; - width: inherit; - background: $tertiary-content; - mask-position: center; - mask-size: 20px; - mask-repeat: no-repeat; - mask-image: url("$(res)/img/element-icons/room/ellipsis.svg"); - } - } - } - - .mx_FacePile_summary { - margin-left: 12px; - font: var(--cpd-font-body-md-regular); - line-height: $font-24px; - color: $tertiary-content; + &::before { + content: ""; + z-index: 1; + position: absolute; + top: 0; + left: 0; + height: inherit; + width: inherit; + background: $tertiary-content; + mask-position: center; + mask-size: 20px; + mask-repeat: no-repeat; + mask-image: url("$(res)/img/element-icons/room/ellipsis.svg"); } } + +.mx_FacePile_summary { + margin-left: 12px; + font: var(--cpd-font-body-md-regular); + line-height: $font-24px; + color: $tertiary-content; +} diff --git a/res/css/views/rooms/_RoomHeader.pcss b/res/css/views/rooms/_RoomHeader.pcss index e545649464..edb596aa29 100644 --- a/res/css/views/rooms/_RoomHeader.pcss +++ b/res/css/views/rooms/_RoomHeader.pcss @@ -23,6 +23,7 @@ limitations under the License. .mx_RoomHeader_info { cursor: pointer; + flex: 1; } .mx_RoomHeader_topic { @@ -45,3 +46,19 @@ limitations under the License. height: calc($font-13px * 1.5); opacity: 1; } + +.mx_RoomHeader .mx_FacePile { + color: $secondary-content; + display: flex; + align-items: center; + gap: var(--cpd-space-2x); + border-radius: 9999px; + padding: var(--cpd-space-1-5x); + cursor: pointer; + user-select: none; + + &:hover { + color: $primary-content; + background: var(--cpd-color-bg-subtle-primary); + } +} diff --git a/src/components/views/elements/FacePile.tsx b/src/components/views/elements/FacePile.tsx index 6c31614c06..47c05598ba 100644 --- a/src/components/views/elements/FacePile.tsx +++ b/src/components/views/elements/FacePile.tsx @@ -16,27 +16,27 @@ limitations under the License. import React, { FC, HTMLAttributes, ReactNode } from "react"; import { RoomMember } from "matrix-js-sdk/src/matrix"; +import { AvatarStack, Tooltip } from "@vector-im/compound-web"; import MemberAvatar from "../avatars/MemberAvatar"; -import TooltipTarget from "./TooltipTarget"; -import TextWithTooltip from "./TextWithTooltip"; interface IProps extends HTMLAttributes { members: RoomMember[]; size: string; overflow: boolean; - tooltip?: ReactNode; + tooltipLabel?: string; + tooltipShortcut?: string; children?: ReactNode; } -const FacePile: FC = ({ members, size, overflow, tooltip, children, ...props }) => { +const FacePile: FC = ({ members, size, overflow, tooltipLabel, tooltipShortcut, children, ...props }) => { const faces = members.map( - tooltip + tooltipLabel ? (m) => : (m) => ( - + - + ), ); @@ -47,18 +47,20 @@ const FacePile: FC = ({ members, size, overflow, tooltip, children, ...p ); - return ( -
- {tooltip ? ( - - {pileContents} - - ) : ( -
{pileContents}
- )} + const content = ( +
+ {pileContents} {children}
); + + return tooltipLabel ? ( + + {content} + + ) : ( + content + ); }; export default FacePile; diff --git a/src/components/views/elements/RoomFacePile.tsx b/src/components/views/elements/RoomFacePile.tsx index 44dea8b329..f1a0ba03a4 100644 --- a/src/components/views/elements/RoomFacePile.tsx +++ b/src/components/views/elements/RoomFacePile.tsx @@ -63,21 +63,21 @@ const RoomFacePile: FC = ({ room, onlyKnownUsers = true, numShown = DEFA .reverse() .join(", "); - const tooltip = ( -
-
- {props.onClick ? _t("View all %(count)s members", { count }) : _t("%(count)s members", { count })} -
-
- {isJoined - ? _t("Including you, %(commaSeparatedMembers)s", { commaSeparatedMembers }) - : _t("Including %(commaSeparatedMembers)s", { commaSeparatedMembers })} -
-
- ); - return ( - numShown} tooltip={tooltip} {...props}> + numShown} + tooltipLabel={ + props.onClick ? _t("View all %(count)s members", { count }) : _t("%(count)s members", { count }) + } + tooltipShortcut={ + isJoined + ? _t("Including you, %(commaSeparatedMembers)s", { commaSeparatedMembers }) + : _t("Including %(commaSeparatedMembers)s", { commaSeparatedMembers }) + } + {...props} + > {onlyKnownUsers && ( {_t("%(count)s people you know have already joined", { count: members.length })} diff --git a/src/components/views/rooms/RoomHeader.tsx b/src/components/views/rooms/RoomHeader.tsx index eb32443964..0027278549 100644 --- a/src/components/views/rooms/RoomHeader.tsx +++ b/src/components/views/rooms/RoomHeader.tsx @@ -21,14 +21,18 @@ import { Icon as VoiceCallIcon } from "@vector-im/compound-design-tokens/icons/v import { Icon as ThreadsIcon } from "@vector-im/compound-design-tokens/icons/threads-solid.svg"; import { Icon as NotificationsIcon } from "@vector-im/compound-design-tokens/icons/notifications-solid.svg"; import { CallType } from "matrix-js-sdk/src/webrtc/call"; +import { EventType } from "matrix-js-sdk/src/matrix"; import type { Room } from "matrix-js-sdk/src/matrix"; -import { _t } from "../../../languageHandler"; import { useRoomName } from "../../../hooks/useRoomName"; import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar"; import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePhases"; import RightPanelStore from "../../../stores/right-panel/RightPanelStore"; import { useTopic } from "../../../hooks/room/useTopic"; +import { useAccountData } from "../../../hooks/useAccountData"; +import { useMatrixClientContext } from "../../../contexts/MatrixClientContext"; +import { useRoomMemberCount, useRoomMembers } from "../../../hooks/useRoomMembers"; +import { _t, getCurrentLanguage } from "../../../languageHandler"; import { Flex } from "../../utils/Flex"; import { Box } from "../../utils/Box"; import { useRoomCallStatus } from "../../../hooks/room/useRoomCallStatus"; @@ -41,6 +45,7 @@ import { NotificationColor } from "../../../stores/notifications/NotificationCol import { useGlobalNotificationState } from "../../../hooks/useGlobalNotificationState"; import SdkConfig from "../../../SdkConfig"; import { useFeatureEnabled } from "../../../hooks/useSettings"; +import FacePile from "../elements/FacePile"; /** * A helper to transform a notification color to the what the Compound Icon Button @@ -67,9 +72,24 @@ function showOrHidePanel(phase: RightPanelPhases): void { } export default function RoomHeader({ room }: { room: Room }): JSX.Element { + const client = useMatrixClientContext(); + const roomName = useRoomName(room); const roomTopic = useTopic(room); + const members = useRoomMembers(room); + const memberCount = useRoomMemberCount(room); + + const directRoomsList = useAccountData>(client, EventType.Direct); + const isDirectMessage = useMemo(() => { + for (const [, dmRoomList] of Object.entries(directRoomsList)) { + if (dmRoomList.includes(room?.roomId ?? "")) { + return true; + } + } + return false; + }, [directRoomsList, room?.roomId]); + const { voiceCallDisabledReason, voiceCallType, videoCallDisabledReason, videoCallType } = useRoomCallStatus(room); const groupCallsEnabled = useFeatureEnabled("feature_group_calls"); @@ -119,10 +139,7 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element { gap="var(--cpd-space-3x)" className="mx_RoomHeader light-panel" onClick={() => { - const rightPanel = RightPanelStore.instance; - rightPanel.isOpen - ? rightPanel.togglePanel(null) - : rightPanel.setCard({ phase: RightPanelPhases.RoomSummary }); + showOrHidePanel(RightPanelPhases.RoomSummary); }} > @@ -170,7 +187,7 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element { onClick={() => { showOrHidePanel(RightPanelPhases.ThreadPanel); }} - title={_t("Threads")} + title={_t("common|threads")} > @@ -184,6 +201,27 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element { + {!isDirectMessage && ( + { + showOrHidePanel(RightPanelPhases.RoomMemberList); + e.stopPropagation(); + }} + > + + {memberCount.toLocaleString(getCurrentLanguage())} + + + )} ); } diff --git a/src/hooks/useAccountData.ts b/src/hooks/useAccountData.ts index b9399c25ea..032d4d4676 100644 --- a/src/hooks/useAccountData.ts +++ b/src/hooks/useAccountData.ts @@ -15,7 +15,7 @@ limitations under the License. */ import { useCallback, useState } from "react"; -import { ClientEvent, MatrixClient, MatrixEvent, Room, RoomEvent } from "matrix-js-sdk/src/matrix"; +import { ClientEvent, MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { useTypedEventEmitter } from "./useEventEmitter"; @@ -38,17 +38,20 @@ export const useAccountData = (cli: MatrixClient, eventType: strin }; // Hook to simplify listening to Matrix room account data -export const useRoomAccountData = (room: Room, eventType: string): T => { - const [value, setValue] = useState(() => tryGetContent(room.getAccountData(eventType))); +// Currently not used, commenting out otherwise the dead code CI is unhappy. +// But this code is valid and probably will be needed. - const handler = useCallback( - (event) => { - if (event.getType() !== eventType) return; - setValue(event.getContent()); - }, - [eventType], - ); - useTypedEventEmitter(room, RoomEvent.AccountData, handler); +// export const useRoomAccountData = (room: Room, eventType: string): T => { +// const [value, setValue] = useState(() => tryGetContent(room.getAccountData(eventType))); - return value || ({} as T); -}; +// const handler = useCallback( +// (event) => { +// if (event.getType() !== eventType) return; +// setValue(event.getContent()); +// }, +// [eventType], +// ); +// useTypedEventEmitter(room, RoomEvent.AccountData, handler); + +// return value || ({} as T); +// }; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a4ecb6d551..f5a5a6a1e5 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1821,16 +1821,15 @@ "Room %(name)s": "Room %(name)s", "Recently visited rooms": "Recently visited rooms", "No recently visited rooms": "No recently visited rooms", - "Threads": "Threads", + "%(count)s members": { + "other": "%(count)s members", + "one": "%(count)s member" + }, "Video room": "Video room", "Public space": "Public space", "Public room": "Public room", "Private space": "Private space", "Private room": "Private room", - "%(count)s members": { - "other": "%(count)s members", - "one": "%(count)s member" - }, "Start new chat": "Start new chat", "Invite to space": "Invite to space", "You do not have permissions to invite people to this space": "You do not have permissions to invite people to this space", diff --git a/test/components/views/elements/FacePile-test.tsx b/test/components/views/elements/FacePile-test.tsx index fbb48a96a5..31f6451561 100644 --- a/test/components/views/elements/FacePile-test.tsx +++ b/test/components/views/elements/FacePile-test.tsx @@ -23,7 +23,7 @@ describe("", () => { const member = mkRoomMember("123", "456", "join"); const { asFragment } = render( - tooltip} />, + , ); expect(asFragment()).toMatchSnapshot(); diff --git a/test/components/views/elements/RoomFacePile-test.tsx b/test/components/views/elements/RoomFacePile-test.tsx new file mode 100644 index 0000000000..e733fdcf5f --- /dev/null +++ b/test/components/views/elements/RoomFacePile-test.tsx @@ -0,0 +1,38 @@ +/* +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 { render } from "@testing-library/react"; +import React from "react"; + +import { mkRoom, mkRoomMember, stubClient, withClientContextRenderOptions } from "../../../test-utils"; +import RoomFacePile from "../../../../src/components/views/elements/RoomFacePile"; +import DMRoomMap from "../../../../src/utils/DMRoomMap"; +import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; + +describe("", () => { + it("renders", () => { + const cli = stubClient(); + DMRoomMap.makeShared(cli); + const room = mkRoom(cli, "!123"); + + jest.spyOn(room, "getJoinedMembers").mockReturnValue([mkRoomMember(room.roomId, "@bob:example.org", "join")]); + + const { asFragment } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); + + expect(asFragment()).toMatchSnapshot(); + }); +}); diff --git a/test/components/views/elements/__snapshots__/FacePile-test.tsx.snap b/test/components/views/elements/__snapshots__/FacePile-test.tsx.snap index 5f95a68002..ab12a66b22 100644 --- a/test/components/views/elements/__snapshots__/FacePile-test.tsx.snap +++ b/test/components/views/elements/__snapshots__/FacePile-test.tsx.snap @@ -4,11 +4,10 @@ exports[` renders with a tooltip 1`] = `
renders 1`] = ` + +
+
+ + b + +
+
+
+`; diff --git a/test/components/views/rooms/RoomHeader-test.tsx b/test/components/views/rooms/RoomHeader-test.tsx index 73317a054e..f0d4d25489 100644 --- a/test/components/views/rooms/RoomHeader-test.tsx +++ b/test/components/views/rooms/RoomHeader-test.tsx @@ -15,12 +15,12 @@ limitations under the License. */ import React from "react"; -import { getAllByTitle, getByText, getByTitle, render, screen } from "@testing-library/react"; -import { Room, EventType, MatrixEvent, PendingEventOrdering, MatrixCall } from "matrix-js-sdk/src/matrix"; import userEvent from "@testing-library/user-event"; -import { CallType } from "matrix-js-sdk/src/webrtc/call"; +import { CallType, MatrixCall } from "matrix-js-sdk/src/webrtc/call"; +import { EventType, MatrixEvent, PendingEventOrdering, Room } from "matrix-js-sdk/src/matrix"; +import { getAllByTitle, getByLabelText, getByText, getByTitle, render, screen } from "@testing-library/react"; -import { stubClient } from "../../../test-utils"; +import { mkEvent, stubClient, withClientContextRenderOptions } from "../../../test-utils"; import RoomHeader from "../../../../src/components/views/rooms/RoomHeader"; import DMRoomMap from "../../../../src/utils/DMRoomMap"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; @@ -33,7 +33,7 @@ import dispatcher from "../../../../src/dispatcher/dispatcher"; import { CallStore } from "../../../../src/stores/CallStore"; import { Call, ElementCall } from "../../../../src/models/Call"; -describe("Roomeader", () => { +describe("RoomHeader", () => { let room: Room; const ROOM_ID = "!1:example.org"; @@ -57,7 +57,10 @@ describe("Roomeader", () => { }); it("renders the room header", () => { - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); expect(container).toHaveTextContent(ROOM_ID); }); @@ -75,26 +78,129 @@ describe("Roomeader", () => { }); await room.addLiveEvents([roomTopic]); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); expect(container).toHaveTextContent(TOPIC); }); it("opens the room summary", async () => { - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); await userEvent.click(getByText(container, ROOM_ID)); expect(setCardSpy).toHaveBeenCalledWith({ phase: RightPanelPhases.RoomSummary }); }); + it("does not show the face pile for DMs", () => { + const client = MatrixClientPeg.get()!; + + jest.spyOn(client, "getAccountData").mockReturnValue( + mkEvent({ + event: true, + type: EventType.Direct, + user: client.getSafeUserId(), + content: { + "user@example.com": [room.roomId], + }, + }), + ); + + room.getJoinedMembers = jest.fn().mockReturnValue([ + { + userId: "@me:example.org", + name: "Member", + rawDisplayName: "Member", + roomId: room.roomId, + membership: "join", + getAvatarUrl: () => "mxc://avatar.url/image.png", + getMxcAvatarUrl: () => "mxc://avatar.url/image.png", + }, + ]); + + const { asFragment } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); + + expect(asFragment()).toMatchSnapshot(); + }); + + it("shows a face pile for rooms", async () => { + const members = [ + { + userId: "@me:example.org", + name: "Member", + rawDisplayName: "Member", + roomId: room.roomId, + membership: "join", + getAvatarUrl: () => "mxc://avatar.url/image.png", + getMxcAvatarUrl: () => "mxc://avatar.url/image.png", + }, + { + userId: "@you:example.org", + name: "Member", + rawDisplayName: "Member", + roomId: room.roomId, + membership: "join", + getAvatarUrl: () => "mxc://avatar.url/image.png", + getMxcAvatarUrl: () => "mxc://avatar.url/image.png", + }, + { + userId: "@them:example.org", + name: "Member", + rawDisplayName: "Member", + roomId: room.roomId, + membership: "join", + getAvatarUrl: () => "mxc://avatar.url/image.png", + getMxcAvatarUrl: () => "mxc://avatar.url/image.png", + }, + { + userId: "@bot:example.org", + name: "Bot user", + rawDisplayName: "Bot user", + roomId: room.roomId, + membership: "join", + getAvatarUrl: () => "mxc://avatar.url/image.png", + getMxcAvatarUrl: () => "mxc://avatar.url/image.png", + }, + ]; + room.currentState.setJoinedMemberCount(members.length); + room.getJoinedMembers = jest.fn().mockReturnValue(members); + + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); + + expect(container).toHaveTextContent("4"); + + const facePile = getByLabelText(container, "4 members"); + expect(facePile).toHaveTextContent("4"); + + await userEvent.click(facePile); + + expect(setCardSpy).toHaveBeenCalledWith({ phase: RightPanelPhases.RoomMemberList }); + }); + it("opens the thread panel", async () => { - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); await userEvent.click(getByTitle(container, "Threads")); expect(setCardSpy).toHaveBeenCalledWith({ phase: RightPanelPhases.ThreadPanel }); }); it("opens the notifications panel", async () => { - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); await userEvent.click(getByTitle(container, "Notifications")); expect(setCardSpy).toHaveBeenCalledWith({ phase: RightPanelPhases.NotificationPanel }); @@ -103,7 +209,10 @@ describe("Roomeader", () => { describe("groups call disabled", () => { it("you can't call if you're alone", () => { mockRoomMembers(room, 1); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); for (const button of getAllByTitle(container, "There's no one here to call")) { expect(button).toBeDisabled(); } @@ -111,7 +220,10 @@ describe("Roomeader", () => { it("you can call when you're two in the room", async () => { mockRoomMembers(room, 2); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); const voiceButton = getByTitle(container, "Voice call"); const videoButton = getByTitle(container, "Video call"); expect(voiceButton).not.toBeDisabled(); @@ -132,7 +244,10 @@ describe("Roomeader", () => { // The JS-SDK does not export the class `MatrixCall` only the type {} as MatrixCall, ); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); for (const button of getAllByTitle(container, "Ongoing call")) { expect(button).toBeDisabled(); } @@ -141,7 +256,10 @@ describe("Roomeader", () => { it("can calls in large rooms if able to edit widgets", () => { mockRoomMembers(room, 10); jest.spyOn(room.currentState, "mayClientSendStateEvent").mockReturnValue(true); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); expect(getByTitle(container, "Voice call")).not.toBeDisabled(); expect(getByTitle(container, "Video call")).not.toBeDisabled(); @@ -150,7 +268,10 @@ describe("Roomeader", () => { it("disable calls in large rooms by default", () => { mockRoomMembers(room, 10); jest.spyOn(room.currentState, "mayClientSendStateEvent").mockReturnValue(false); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); expect(getByTitle(container, "You do not have permission to start voice calls")).toBeDisabled(); expect(getByTitle(container, "You do not have permission to start video calls")).toBeDisabled(); }); @@ -166,7 +287,10 @@ describe("Roomeader", () => { // allow element calls jest.spyOn(room.currentState, "mayClientSendStateEvent").mockReturnValue(true); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); expect(screen.queryByTitle("Voice call")).toBeNull(); @@ -187,7 +311,10 @@ describe("Roomeader", () => { jest.spyOn(CallStore.instance, "getCall").mockReturnValue({} as Call); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); expect(getByTitle(container, "Ongoing call")).toBeDisabled(); }); @@ -197,7 +324,10 @@ describe("Roomeader", () => { // The JS-SDK does not export the class `MatrixCall` only the type {} as MatrixCall, ); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); for (const button of getAllByTitle(container, "Ongoing call")) { expect(button).toBeDisabled(); } @@ -205,7 +335,10 @@ describe("Roomeader", () => { it("can't call if you have no friends", () => { mockRoomMembers(room, 1); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); for (const button of getAllByTitle(container, "There's no one here to call")) { expect(button).toBeDisabled(); } @@ -213,7 +346,10 @@ describe("Roomeader", () => { it("calls using legacy or jitsi", async () => { mockRoomMembers(room, 2); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); const voiceButton = getByTitle(container, "Voice call"); const videoButton = getByTitle(container, "Video call"); @@ -236,7 +372,10 @@ describe("Roomeader", () => { return false; }); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); const voiceButton = getByTitle(container, "Voice call"); const videoButton = getByTitle(container, "Video call"); @@ -260,7 +399,10 @@ describe("Roomeader", () => { return false; }); - const { container } = render(); + const { container } = render( + , + withClientContextRenderOptions(MatrixClientPeg.get()!), + ); const voiceButton = getByTitle(container, "Voice call"); const videoButton = getByTitle(container, "Video call"); diff --git a/test/components/views/rooms/__snapshots__/RoomHeader-test.tsx.snap b/test/components/views/rooms/__snapshots__/RoomHeader-test.tsx.snap new file mode 100644 index 0000000000..bfcc954454 --- /dev/null +++ b/test/components/views/rooms/__snapshots__/RoomHeader-test.tsx.snap @@ -0,0 +1,75 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RoomHeader does not show the face pile for DMs 1`] = ` + +
+
+ + ! + +
+
+
+ !1:example.org +
+
+ +
+
+`;