diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index 3cac66a79c..1ec7fae751 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -59,6 +59,7 @@ import { Action } from "../../../dispatcher/actions"; import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload"; import useFavouriteMessages from "../../../hooks/useFavouriteMessages"; import { GetRelationsForEvent } from "../rooms/EventTile"; +import { VoiceBroadcastInfoEventType } from "../../../voice-broadcast/types"; interface IOptionsButtonProps { mxEvent: MatrixEvent; @@ -394,7 +395,8 @@ export default class MessageActionBar extends React.PureComponent ({ copyPlaintext: jest.fn(), getSelectedText: jest.fn(), })); jest.mock("../../../../src/utils/EventUtils", () => ({ - // @ts-ignore don't mock everything - ...jest.requireActual("../../../../src/utils/EventUtils"), + ...(jest.requireActual("../../../../src/utils/EventUtils") as object), canEditContent: jest.fn(), })); jest.mock("../../../../src/dispatcher/dispatcher"); @@ -241,6 +242,17 @@ describe("MessageContextMenu", () => { expect(menu.find('div[aria-label="Forward"]')).toHaveLength(0); }); + it("should not allow forwarding a voice broadcast", () => { + const broadcastStartEvent = mkVoiceBroadcastInfoStateEvent( + roomId, + VoiceBroadcastInfoState.Started, + "@user:example.com", + "ABC123", + ); + const menu = createMenu(broadcastStartEvent); + expect(menu.find('div[aria-label="Forward"]')).toHaveLength(0); + }); + describe("forwarding beacons", () => { const aliceId = "@alice:server.org"; diff --git a/test/components/views/messages/MessageActionBar-test.tsx b/test/components/views/messages/MessageActionBar-test.tsx index a3a3ffe141..8b64f205f0 100644 --- a/test/components/views/messages/MessageActionBar-test.tsx +++ b/test/components/views/messages/MessageActionBar-test.tsx @@ -15,8 +15,7 @@ limitations under the License. */ import React from "react"; -import { render, fireEvent } from "@testing-library/react"; -import { act } from "react-test-renderer"; +import { act, render, fireEvent } from "@testing-library/react"; import { EventType, EventStatus, MatrixEvent, MatrixEventEvent, MsgType, Room } from "matrix-js-sdk/src/matrix"; import { FeatureSupport, Thread } from "matrix-js-sdk/src/models/thread"; @@ -34,6 +33,8 @@ import dispatcher from "../../../../src/dispatcher/dispatcher"; import SettingsStore from "../../../../src/settings/SettingsStore"; import { Action } from "../../../../src/dispatcher/actions"; import { UserTab } from "../../../../src/components/views/dialogs/UserTab"; +import { mkVoiceBroadcastInfoStateEvent } from "../../../voice-broadcast/utils/test-utils"; +import { VoiceBroadcastInfoState } from "../../../../src/voice-broadcast"; jest.mock("../../../../src/dispatcher/dispatcher"); @@ -405,6 +406,17 @@ describe("", () => { expect(queryByLabelText("Reply in thread")).toBeTruthy(); }); + it("does not render thread button for a voice broadcast", () => { + const broadcastEvent = mkVoiceBroadcastInfoStateEvent( + roomId, + VoiceBroadcastInfoState.Started, + userId, + "ABC123", + ); + const { queryByLabelText } = getComponent({ mxEvent: broadcastEvent }); + expect(queryByLabelText("Reply in thread")).not.toBeInTheDocument(); + }); + it("opens user settings on click", () => { jest.spyOn(SettingsStore, "getValue").mockReturnValue(false); const { getByLabelText } = getComponent({ mxEvent: alicesMessageEvent }); diff --git a/test/utils/EventUtils-test.ts b/test/utils/EventUtils-test.ts index ca77e64662..decf42931a 100644 --- a/test/utils/EventUtils-test.ts +++ b/test/utils/EventUtils-test.ts @@ -43,6 +43,8 @@ import { import { getMockClientWithEventEmitter, makeBeaconInfoEvent, makePollStartEvent, stubClient } from "../test-utils"; import dis from "../../src/dispatcher/dispatcher"; import { Action } from "../../src/dispatcher/actions"; +import { mkVoiceBroadcastInfoStateEvent } from "../voice-broadcast/utils/test-utils"; +import { VoiceBroadcastInfoState } from "../../src/voice-broadcast/types"; jest.mock("../../src/dispatcher/dispatcher"); @@ -151,6 +153,20 @@ describe("EventUtils", () => { }, }); + const voiceBroadcastStart = mkVoiceBroadcastInfoStateEvent( + "!room:example.com", + VoiceBroadcastInfoState.Started, + "@user:example.com", + "ABC123", + ); + + const voiceBroadcastStop = mkVoiceBroadcastInfoStateEvent( + "!room:example.com", + VoiceBroadcastInfoState.Stopped, + "@user:example.com", + "ABC123", + ); + describe("isContentActionable()", () => { type TestCase = [string, MatrixEvent]; it.each([ @@ -161,6 +177,7 @@ describe("EventUtils", () => { ["room member event", roomMemberEvent], ["event without msgtype", noMsgType], ["event without content body property", noContentBody], + ["broadcast stop event", voiceBroadcastStop], ])("returns false for %s", (_description, event) => { expect(isContentActionable(event)).toBe(false); }); @@ -171,6 +188,7 @@ describe("EventUtils", () => { ["event with empty content body", emptyContentBody], ["event with a content body", niceTextMessage], ["beacon_info event", beaconInfoEvent], + ["broadcast start event", voiceBroadcastStart], ])("returns true for %s", (_description, event) => { expect(isContentActionable(event)).toBe(true); }); diff --git a/test/voice-broadcast/utils/test-utils.ts b/test/voice-broadcast/utils/test-utils.ts index cbf0a5989a..fc1ffd4b15 100644 --- a/test/voice-broadcast/utils/test-utils.ts +++ b/test/voice-broadcast/utils/test-utils.ts @@ -21,7 +21,7 @@ import { VoiceBroadcastChunkEventType, VoiceBroadcastInfoEventType, VoiceBroadcastInfoState, -} from "../../../src/voice-broadcast"; +} from "../../../src/voice-broadcast/types"; import { mkEvent } from "../../test-utils"; // timestamp incremented on each call to prevent duplicate timestamp