mirror of
https://github.com/vector-im/element-web.git
synced 2025-12-06 18:01:38 +01:00
Add option to pick call options for voice calls. (#31407)
* Add option to pick call options for voice calls. * hook on the right thing * Fix wrong call being disabled * update snaps * Add tests for menus * more snaps * snap snap
This commit is contained in:
parent
61168f0531
commit
a352a3838e
@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
Copyright (C) 2025 Element Creations Ltd
|
||||||
Copyright 2024 New Vector Ltd.
|
Copyright 2024 New Vector Ltd.
|
||||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
@ -6,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { type JSX, useCallback, useMemo, useState } from "react";
|
import React, { type JSX, useCallback, useState } from "react";
|
||||||
import { Text, Button, IconButton, Menu, MenuItem, Tooltip } from "@vector-im/compound-web";
|
import { Text, Button, IconButton, Menu, MenuItem, Tooltip } from "@vector-im/compound-web";
|
||||||
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid";
|
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid";
|
||||||
import VoiceCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/voice-call-solid";
|
import VoiceCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/voice-call-solid";
|
||||||
@ -29,7 +30,6 @@ import { _t } from "../../../../languageHandler.tsx";
|
|||||||
import { getPlatformCallTypeProps, useRoomCall } from "../../../../hooks/room/useRoomCall.tsx";
|
import { getPlatformCallTypeProps, useRoomCall } from "../../../../hooks/room/useRoomCall.tsx";
|
||||||
import { useRoomThreadNotifications } from "../../../../hooks/room/useRoomThreadNotifications.ts";
|
import { useRoomThreadNotifications } from "../../../../hooks/room/useRoomThreadNotifications.ts";
|
||||||
import { useGlobalNotificationState } from "../../../../hooks/useGlobalNotificationState.ts";
|
import { useGlobalNotificationState } from "../../../../hooks/useGlobalNotificationState.ts";
|
||||||
import SdkConfig from "../../../../SdkConfig.ts";
|
|
||||||
import { useFeatureEnabled } from "../../../../hooks/useSettings.ts";
|
import { useFeatureEnabled } from "../../../../hooks/useSettings.ts";
|
||||||
import { useEncryptionStatus } from "../../../../hooks/useEncryptionStatus.ts";
|
import { useEncryptionStatus } from "../../../../hooks/useEncryptionStatus.ts";
|
||||||
import { E2EStatus } from "../../../../utils/ShieldUtils.ts";
|
import { E2EStatus } from "../../../../utils/ShieldUtils.ts";
|
||||||
@ -78,16 +78,6 @@ function RoomHeaderButtons({
|
|||||||
showVoiceCallButton,
|
showVoiceCallButton,
|
||||||
showVideoCallButton,
|
showVideoCallButton,
|
||||||
} = useRoomCall(room);
|
} = useRoomCall(room);
|
||||||
|
|
||||||
const groupCallsEnabled = useFeatureEnabled("feature_group_calls");
|
|
||||||
/**
|
|
||||||
* A special mode where only Element Call is used. In this case we want to
|
|
||||||
* hide the voice call button
|
|
||||||
*/
|
|
||||||
const useElementCallExclusively = useMemo(() => {
|
|
||||||
return SdkConfig.get("element_call").use_exclusively && groupCallsEnabled;
|
|
||||||
}, [groupCallsEnabled]);
|
|
||||||
|
|
||||||
const threadNotifications = useRoomThreadNotifications(room);
|
const threadNotifications = useRoomThreadNotifications(room);
|
||||||
const globalNotificationState = useGlobalNotificationState();
|
const globalNotificationState = useGlobalNotificationState();
|
||||||
|
|
||||||
@ -101,6 +91,11 @@ function RoomHeaderButtons({
|
|||||||
[callOptions, videoCallClick],
|
[callOptions, videoCallClick],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const voiceClick = useCallback(
|
||||||
|
(ev: React.MouseEvent) => voiceCallClick(ev, callOptions[0]),
|
||||||
|
[callOptions, voiceCallClick],
|
||||||
|
);
|
||||||
|
|
||||||
const toggleCallButton = (
|
const toggleCallButton = (
|
||||||
<Tooltip label={isViewingCall ? _t("voip|minimise_call") : _t("voip|maximise_call")}>
|
<Tooltip label={isViewingCall ? _t("voip|minimise_call") : _t("voip|maximise_call")}>
|
||||||
<IconButton onClick={toggleCall}>
|
<IconButton onClick={toggleCall}>
|
||||||
@ -126,35 +121,50 @@ function RoomHeaderButtons({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
|
|
||||||
const callIconWithTooltip = (
|
const videoCallIconWithTooltip = (
|
||||||
<Tooltip label={videoCallDisabledReason ?? _t("voip|video_call")}>
|
<Tooltip label={videoCallDisabledReason ?? _t("voip|video_call")}>
|
||||||
<VideoCallIcon />
|
<VideoCallIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
|
|
||||||
const [menuOpen, setMenuOpen] = useState(false);
|
const voiceCallIconWithTooltip = (
|
||||||
|
<Tooltip label={videoCallDisabledReason ?? _t("voip|voice_call")}>
|
||||||
|
<VoiceCallIcon />
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
|
||||||
const onOpenChange = useCallback(
|
const [videoMenuOpen, setVideoMenuOpen] = useState(false);
|
||||||
|
|
||||||
|
const onVideoOpenChange = useCallback(
|
||||||
(newOpen: boolean) => {
|
(newOpen: boolean) => {
|
||||||
if (!videoCallDisabledReason) setMenuOpen(newOpen);
|
if (!videoCallDisabledReason) setVideoMenuOpen(newOpen);
|
||||||
},
|
},
|
||||||
[videoCallDisabledReason],
|
[videoCallDisabledReason],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [voiceMenuOpen, setVoiceMenuOpen] = useState(false);
|
||||||
|
|
||||||
|
const onVoiceOpenChange = useCallback(
|
||||||
|
(newOpen: boolean) => {
|
||||||
|
if (!voiceCallDisabledReason) setVoiceMenuOpen(newOpen);
|
||||||
|
},
|
||||||
|
[voiceCallDisabledReason],
|
||||||
|
);
|
||||||
|
|
||||||
const startVideoCallButton = (
|
const startVideoCallButton = (
|
||||||
<>
|
<>
|
||||||
{/* Can be either a menu or just a button depending on the number of call options.*/}
|
{/* Can be either a menu or just a button depending on the number of call options.*/}
|
||||||
{callOptions.length > 1 ? (
|
{callOptions.length > 1 ? (
|
||||||
<Menu
|
<Menu
|
||||||
open={menuOpen}
|
open={videoMenuOpen}
|
||||||
onOpenChange={onOpenChange}
|
onOpenChange={onVideoOpenChange}
|
||||||
title={_t("voip|video_call_using")}
|
title={_t("voip|video_call_using")}
|
||||||
trigger={
|
trigger={
|
||||||
<IconButton
|
<IconButton
|
||||||
disabled={!!videoCallDisabledReason}
|
disabled={!!videoCallDisabledReason}
|
||||||
aria-label={videoCallDisabledReason ?? _t("voip|video_call")}
|
aria-label={videoCallDisabledReason ?? _t("voip|video_call")}
|
||||||
>
|
>
|
||||||
{callIconWithTooltip}
|
{videoCallIconWithTooltip}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
}
|
}
|
||||||
side="left"
|
side="left"
|
||||||
@ -170,7 +180,7 @@ function RoomHeaderButtons({
|
|||||||
children={children}
|
children={children}
|
||||||
className="mx_RoomHeader_videoCallOption"
|
className="mx_RoomHeader_videoCallOption"
|
||||||
onClick={(ev) => {
|
onClick={(ev) => {
|
||||||
setMenuOpen(false);
|
setVideoMenuOpen(false);
|
||||||
videoCallClick(ev, option);
|
videoCallClick(ev, option);
|
||||||
}}
|
}}
|
||||||
Icon={VideoCallIcon}
|
Icon={VideoCallIcon}
|
||||||
@ -185,25 +195,61 @@ function RoomHeaderButtons({
|
|||||||
aria-label={videoCallDisabledReason ?? _t("voip|video_call")}
|
aria-label={videoCallDisabledReason ?? _t("voip|video_call")}
|
||||||
onClick={videoClick}
|
onClick={videoClick}
|
||||||
>
|
>
|
||||||
{callIconWithTooltip}
|
{videoCallIconWithTooltip}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
let voiceCallButton: JSX.Element | undefined = (
|
const startVoiceCallButton = (
|
||||||
<Tooltip label={voiceCallDisabledReason ?? _t("voip|voice_call")}>
|
<>
|
||||||
<IconButton
|
{/* Can be either a menu or just a button depending on the number of call options.*/}
|
||||||
// We need both: isViewingCall and isConnectedToCall
|
{callOptions.length > 1 ? (
|
||||||
// - in the Lobby we are viewing a call but are not connected to it.
|
<Menu
|
||||||
// - in pip view we are connected to the call but not viewing it.
|
open={voiceMenuOpen}
|
||||||
disabled={!!voiceCallDisabledReason || isViewingCall || isConnectedToCall}
|
onOpenChange={onVoiceOpenChange}
|
||||||
aria-label={voiceCallDisabledReason ?? _t("voip|voice_call")}
|
title={_t("voip|voice_call_using")}
|
||||||
onClick={(ev) => voiceCallClick(ev, callOptions[0])}
|
trigger={
|
||||||
>
|
<IconButton
|
||||||
<VoiceCallIcon />
|
disabled={!!voiceCallDisabledReason}
|
||||||
</IconButton>
|
aria-label={voiceCallDisabledReason ?? _t("voip|voice_call")}
|
||||||
</Tooltip>
|
>
|
||||||
|
{voiceCallIconWithTooltip}
|
||||||
|
</IconButton>
|
||||||
|
}
|
||||||
|
side="left"
|
||||||
|
align="start"
|
||||||
|
>
|
||||||
|
{callOptions.map((option) => {
|
||||||
|
const { label, children } = getPlatformCallTypeProps(option);
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
key={option}
|
||||||
|
label={label}
|
||||||
|
aria-label={label}
|
||||||
|
children={children}
|
||||||
|
className="mx_RoomHeader_videoCallOption"
|
||||||
|
onClick={(ev) => {
|
||||||
|
setVoiceMenuOpen(false);
|
||||||
|
voiceCallClick(ev, option);
|
||||||
|
}}
|
||||||
|
Icon={VoiceCallIcon}
|
||||||
|
onSelect={() => {} /* Dummy handler since we want the click event.*/}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Menu>
|
||||||
|
) : (
|
||||||
|
<IconButton
|
||||||
|
disabled={!!voiceCallDisabledReason}
|
||||||
|
aria-label={voiceCallDisabledReason ?? _t("voip|voice_call")}
|
||||||
|
onClick={voiceClick}
|
||||||
|
>
|
||||||
|
{voiceCallIconWithTooltip}
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const closeLobbyButton = (
|
const closeLobbyButton = (
|
||||||
<Tooltip label={_t("voip|close_lobby")}>
|
<Tooltip label={_t("voip|close_lobby")}>
|
||||||
<IconButton onClick={toggleCall}>
|
<IconButton onClick={toggleCall}>
|
||||||
@ -212,15 +258,19 @@ function RoomHeaderButtons({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
let videoCallButton: JSX.Element | undefined = startVideoCallButton;
|
let videoCallButton: JSX.Element | undefined = startVideoCallButton;
|
||||||
|
let voiceCallButton: JSX.Element | undefined = startVoiceCallButton;
|
||||||
if (isConnectedToCall) {
|
if (isConnectedToCall) {
|
||||||
videoCallButton = toggleCallButton;
|
videoCallButton = toggleCallButton;
|
||||||
|
voiceCallButton = undefined;
|
||||||
} else if (isViewingCall) {
|
} else if (isViewingCall) {
|
||||||
videoCallButton = closeLobbyButton;
|
videoCallButton = closeLobbyButton;
|
||||||
|
voiceCallButton = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!showVideoCallButton) {
|
if (!showVideoCallButton) {
|
||||||
videoCallButton = undefined;
|
videoCallButton = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!showVoiceCallButton) {
|
if (!showVoiceCallButton) {
|
||||||
voiceCallButton = undefined;
|
voiceCallButton = undefined;
|
||||||
}
|
}
|
||||||
@ -258,7 +308,7 @@ function RoomHeaderButtons({
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{!isVideoRoom && videoCallButton}
|
{!isVideoRoom && videoCallButton}
|
||||||
{!useElementCallExclusively && !isVideoRoom && voiceCallButton}
|
{!isVideoRoom && voiceCallButton}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -4103,6 +4103,7 @@
|
|||||||
"video_call_using": "Video call using:",
|
"video_call_using": "Video call using:",
|
||||||
"voice_call": "Voice call",
|
"voice_call": "Voice call",
|
||||||
"voice_call_incoming": "Incoming voice call",
|
"voice_call_incoming": "Incoming voice call",
|
||||||
|
"voice_call_using": "Voice call using:",
|
||||||
"you_are_presenting": "You are presenting"
|
"you_are_presenting": "You are presenting"
|
||||||
},
|
},
|
||||||
"web_default_device_name": "%(appName)s: %(browserName)s on %(osName)s",
|
"web_default_device_name": "%(appName)s: %(browserName)s on %(osName)s",
|
||||||
|
|||||||
@ -1023,7 +1023,6 @@ exports[`RoomView should hide the composer when hideComposer=true 1`] = `
|
|||||||
<button
|
<button
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
aria-label="Voice call"
|
aria-label="Voice call"
|
||||||
aria-labelledby="_r_5_"
|
|
||||||
class="_icon-button_1pz9o_8"
|
class="_icon-button_1pz9o_8"
|
||||||
data-kind="primary"
|
data-kind="primary"
|
||||||
role="button"
|
role="button"
|
||||||
@ -1035,6 +1034,7 @@ exports[`RoomView should hide the composer when hideComposer=true 1`] = `
|
|||||||
style="--cpd-icon-button-size: 100%;"
|
style="--cpd-icon-button-size: 100%;"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-labelledby="_r_5_"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height="1em"
|
height="1em"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@ -1519,7 +1519,6 @@ exports[`RoomView should hide the pinned message banner when hidePinnedMessageBa
|
|||||||
<button
|
<button
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
aria-label="Voice call"
|
aria-label="Voice call"
|
||||||
aria-labelledby="_r_5g_"
|
|
||||||
class="_icon-button_1pz9o_8"
|
class="_icon-button_1pz9o_8"
|
||||||
data-kind="primary"
|
data-kind="primary"
|
||||||
role="button"
|
role="button"
|
||||||
@ -1531,6 +1530,7 @@ exports[`RoomView should hide the pinned message banner when hidePinnedMessageBa
|
|||||||
style="--cpd-icon-button-size: 100%;"
|
style="--cpd-icon-button-size: 100%;"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-labelledby="_r_5g_"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height="1em"
|
height="1em"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@ -1953,7 +1953,6 @@ exports[`RoomView should hide the right panel when hideRightPanel=true 1`] = `
|
|||||||
<button
|
<button
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
aria-label="Voice call"
|
aria-label="Voice call"
|
||||||
aria-labelledby="_r_2j_"
|
|
||||||
class="_icon-button_1pz9o_8"
|
class="_icon-button_1pz9o_8"
|
||||||
data-kind="primary"
|
data-kind="primary"
|
||||||
role="button"
|
role="button"
|
||||||
@ -1965,6 +1964,7 @@ exports[`RoomView should hide the right panel when hideRightPanel=true 1`] = `
|
|||||||
style="--cpd-icon-button-size: 100%;"
|
style="--cpd-icon-button-size: 100%;"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-labelledby="_r_2j_"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height="1em"
|
height="1em"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@ -2387,7 +2387,6 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
|||||||
<button
|
<button
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
aria-label="Voice call"
|
aria-label="Voice call"
|
||||||
aria-labelledby="_r_ag_"
|
|
||||||
class="_icon-button_1pz9o_8"
|
class="_icon-button_1pz9o_8"
|
||||||
data-kind="primary"
|
data-kind="primary"
|
||||||
role="button"
|
role="button"
|
||||||
@ -2399,6 +2398,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
|||||||
style="--cpd-icon-button-size: 100%;"
|
style="--cpd-icon-button-size: 100%;"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-labelledby="_r_ag_"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height="1em"
|
height="1em"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@ -2599,7 +2599,6 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
|||||||
<button
|
<button
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
aria-label="Voice call"
|
aria-label="Voice call"
|
||||||
aria-labelledby="_r_ag_"
|
|
||||||
class="_icon-button_1pz9o_8"
|
class="_icon-button_1pz9o_8"
|
||||||
data-kind="primary"
|
data-kind="primary"
|
||||||
role="button"
|
role="button"
|
||||||
@ -2611,6 +2610,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
|
|||||||
style="--cpd-icon-button-size: 100%;"
|
style="--cpd-icon-button-size: 100%;"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-labelledby="_r_ag_"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height="1em"
|
height="1em"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
Copyright (C) 2025 Element Creations Ltd
|
||||||
Copyright 2024, 2025 New Vector Ltd.
|
Copyright 2024, 2025 New Vector Ltd.
|
||||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
@ -458,7 +459,10 @@ describe("RoomHeader", () => {
|
|||||||
} as unknown as Call);
|
} as unknown as Call);
|
||||||
jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue([widget]);
|
jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue([widget]);
|
||||||
render(<RoomHeader room={room} />, getWrapper());
|
render(<RoomHeader room={room} />, getWrapper());
|
||||||
expect(screen.getByRole("button", { name: "Ongoing call" })).toHaveAttribute("aria-disabled", "true");
|
// Voice and video
|
||||||
|
for (const button of screen.getAllByRole("button", { name: "Ongoing call" })) {
|
||||||
|
expect(button).toHaveAttribute("aria-disabled", "true");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("clicking on ongoing (unpinned) call re-pins it", async () => {
|
it("clicking on ongoing (unpinned) call re-pins it", async () => {
|
||||||
@ -632,6 +636,41 @@ describe("RoomHeader", () => {
|
|||||||
|
|
||||||
expect(getByLabelText(document.body, _t("voip|get_call_link"))).toBeInTheDocument();
|
expect(getByLabelText(document.body, _t("voip|get_call_link"))).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("gives the option of element call or legacy calling for video", async () => {
|
||||||
|
const user = userEvent.setup();
|
||||||
|
mockRoomMembers(room, 2);
|
||||||
|
jest.spyOn(room.currentState, "mayClientSendStateEvent").mockImplementation((key) => {
|
||||||
|
if (key === ElementCallMemberEventType.name) return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
render(<RoomHeader room={room} />, getWrapper());
|
||||||
|
|
||||||
|
const button = screen.getByRole("button", { name: "Video call" });
|
||||||
|
expect(button).not.toHaveAttribute("aria-disabled", "true");
|
||||||
|
await user.click(button);
|
||||||
|
const elementCallButton = screen.getByRole("menuitem", { name: "Element Call" });
|
||||||
|
const legacyCallButton = screen.getByRole("menuitem", { name: "Legacy Call" });
|
||||||
|
expect(elementCallButton).toBeInTheDocument();
|
||||||
|
expect(legacyCallButton).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
it("gives the option of element call or legacy calling for voice in DM rooms", async () => {
|
||||||
|
const user = userEvent.setup();
|
||||||
|
mockRoomMembers(room, 2);
|
||||||
|
jest.spyOn(room.currentState, "mayClientSendStateEvent").mockImplementation((key) => {
|
||||||
|
if (key === ElementCallMemberEventType.name) return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
render(<RoomHeader room={room} />, getWrapper());
|
||||||
|
|
||||||
|
const button = screen.getByRole("button", { name: "Voice call" });
|
||||||
|
expect(button).not.toHaveAttribute("aria-disabled", "true");
|
||||||
|
await user.click(button);
|
||||||
|
const elementCallButton = screen.getByRole("menuitem", { name: "Element Call" });
|
||||||
|
const legacyCallButton = screen.getByRole("menuitem", { name: "Legacy Call" });
|
||||||
|
expect(elementCallButton).toBeInTheDocument();
|
||||||
|
expect(legacyCallButton).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("public room", () => {
|
describe("public room", () => {
|
||||||
|
|||||||
@ -56,7 +56,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
|
|||||||
style="--cpd-icon-button-size: 100%;"
|
style="--cpd-icon-button-size: 100%;"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
aria-labelledby="_r_14k_"
|
aria-labelledby="_r_17e_"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height="1em"
|
height="1em"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@ -72,7 +72,6 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
|
|||||||
<button
|
<button
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
aria-label="Voice call"
|
aria-label="Voice call"
|
||||||
aria-labelledby="_r_14p_"
|
|
||||||
class="_icon-button_1pz9o_8"
|
class="_icon-button_1pz9o_8"
|
||||||
data-kind="primary"
|
data-kind="primary"
|
||||||
role="button"
|
role="button"
|
||||||
@ -84,6 +83,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
|
|||||||
style="--cpd-icon-button-size: 100%;"
|
style="--cpd-icon-button-size: 100%;"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-labelledby="_r_17j_"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height="1em"
|
height="1em"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@ -98,7 +98,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
aria-label="Threads"
|
aria-label="Threads"
|
||||||
aria-labelledby="_r_14u_"
|
aria-labelledby="_r_17o_"
|
||||||
class="_icon-button_1pz9o_8"
|
class="_icon-button_1pz9o_8"
|
||||||
data-kind="primary"
|
data-kind="primary"
|
||||||
role="button"
|
role="button"
|
||||||
@ -125,7 +125,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
aria-label="Room info"
|
aria-label="Room info"
|
||||||
aria-labelledby="_r_153_"
|
aria-labelledby="_r_17t_"
|
||||||
class="_icon-button_1pz9o_8"
|
class="_icon-button_1pz9o_8"
|
||||||
data-kind="primary"
|
data-kind="primary"
|
||||||
role="button"
|
role="button"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user