Handle starting a call while listen to a broadcast (#9764)
This commit is contained in:
parent
af3715821b
commit
35a187a231
8 changed files with 312 additions and 29 deletions
|
@ -63,6 +63,8 @@ import { OpenInviteDialogPayload } from "./dispatcher/payloads/OpenInviteDialogP
|
|||
import { findDMForUser } from "./utils/dm/findDMForUser";
|
||||
import { getJoinedNonFunctionalMembers } from "./utils/room/getJoinedNonFunctionalMembers";
|
||||
import { localNotificationsAreSilenced } from "./utils/notifications";
|
||||
import { SdkContextClass } from "./contexts/SDKContext";
|
||||
import { showCantStartACallDialog } from "./voice-broadcast/utils/showCantStartACallDialog";
|
||||
|
||||
export const PROTOCOL_PSTN = "m.protocol.pstn";
|
||||
export const PROTOCOL_PSTN_PREFIXED = "im.vector.protocol.pstn";
|
||||
|
@ -932,6 +934,15 @@ export default class LegacyCallHandler extends EventEmitter {
|
|||
}
|
||||
|
||||
public async placeCall(roomId: string, type?: CallType, transferee?: MatrixCall): Promise<void> {
|
||||
// Pause current broadcast, if any
|
||||
SdkContextClass.instance.voiceBroadcastPlaybacksStore.getCurrent()?.pause();
|
||||
|
||||
if (SdkContextClass.instance.voiceBroadcastRecordingsStore.getCurrent()) {
|
||||
// Do not start a call, if recording a broadcast
|
||||
showCantStartACallDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
// We might be using managed hybrid widgets
|
||||
if (isManagedHybridWidgetEnabled()) {
|
||||
await addManagedHybridWidget(roomId);
|
||||
|
|
|
@ -648,6 +648,8 @@
|
|||
"You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.": "You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.",
|
||||
"You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.": "You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.",
|
||||
"Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.": "Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.",
|
||||
"Can’t start a call": "Can’t start a call",
|
||||
"You can’t start a call as you are currently recording a live broadcast. Please end your live broadcast in order to start a call.": "You can’t start a call as you are currently recording a live broadcast. Please end your live broadcast in order to start a call.",
|
||||
"You ended a <a>voice broadcast</a>": "You ended a <a>voice broadcast</a>",
|
||||
"%(senderName)s ended a <a>voice broadcast</a>": "%(senderName)s ended a <a>voice broadcast</a>",
|
||||
"You ended a voice broadcast": "You ended a voice broadcast",
|
||||
|
|
|
@ -56,6 +56,7 @@ import {
|
|||
doMaybeSetCurrentVoiceBroadcastPlayback,
|
||||
} from "../voice-broadcast";
|
||||
import { IRoomStateEventsActionPayload } from "../actions/MatrixActionCreators";
|
||||
import { showCantStartACallDialog } from "../voice-broadcast/utils/showCantStartACallDialog";
|
||||
|
||||
const NUM_JOIN_RETRY = 5;
|
||||
|
||||
|
@ -180,6 +181,16 @@ export class RoomViewStore extends EventEmitter {
|
|||
return;
|
||||
}
|
||||
|
||||
if (newState.viewingCall) {
|
||||
// Pause current broadcast, if any
|
||||
this.stores.voiceBroadcastPlaybacksStore.getCurrent()?.pause();
|
||||
|
||||
if (this.stores.voiceBroadcastRecordingsStore.getCurrent()) {
|
||||
showCantStartACallDialog();
|
||||
newState.viewingCall = false;
|
||||
}
|
||||
}
|
||||
|
||||
const lastRoomId = this.state.roomId;
|
||||
this.state = Object.assign(this.state, newState);
|
||||
if (lastRoomId !== this.state.roomId) {
|
||||
|
|
36
src/voice-broadcast/utils/showCantStartACallDialog.tsx
Normal file
36
src/voice-broadcast/utils/showCantStartACallDialog.tsx
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright 2022 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 InfoDialog from "../../components/views/dialogs/InfoDialog";
|
||||
import { _t } from "../../languageHandler";
|
||||
import Modal from "../../Modal";
|
||||
|
||||
export const showCantStartACallDialog = () => {
|
||||
Modal.createDialog(InfoDialog, {
|
||||
title: _t("Can’t start a call"),
|
||||
description: (
|
||||
<p>
|
||||
{_t(
|
||||
"You can’t start a call as you are currently recording a live broadcast. " +
|
||||
"Please end your live broadcast in order to start a call.",
|
||||
)}
|
||||
</p>
|
||||
),
|
||||
hasCloseButton: true,
|
||||
});
|
||||
};
|
|
@ -19,6 +19,7 @@ import {
|
|||
LOCAL_NOTIFICATION_SETTINGS_PREFIX,
|
||||
MatrixEvent,
|
||||
PushRuleKind,
|
||||
Room,
|
||||
RuleId,
|
||||
TweakName,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
|
@ -43,6 +44,28 @@ import { Action } from "../src/dispatcher/actions";
|
|||
import { getFunctionalMembers } from "../src/utils/room/getFunctionalMembers";
|
||||
import SettingsStore from "../src/settings/SettingsStore";
|
||||
import { UIFeature } from "../src/settings/UIFeature";
|
||||
import { VoiceBroadcastInfoState, VoiceBroadcastPlayback, VoiceBroadcastRecording } from "../src/voice-broadcast";
|
||||
import { mkVoiceBroadcastInfoStateEvent } from "./voice-broadcast/utils/test-utils";
|
||||
import { SdkContextClass } from "../src/contexts/SDKContext";
|
||||
import Modal from "../src/Modal";
|
||||
|
||||
jest.mock("../src/Modal");
|
||||
|
||||
// mock VoiceRecording because it contains all the audio APIs
|
||||
jest.mock("../src/audio/VoiceRecording", () => ({
|
||||
VoiceRecording: jest.fn().mockReturnValue({
|
||||
disableMaxLength: jest.fn(),
|
||||
liveData: {
|
||||
onUpdate: jest.fn(),
|
||||
},
|
||||
off: jest.fn(),
|
||||
on: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
destroy: jest.fn(),
|
||||
contentType: "audio/ogg",
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock("../src/utils/room/getFunctionalMembers", () => ({
|
||||
getFunctionalMembers: jest.fn(),
|
||||
|
@ -71,7 +94,7 @@ const VIRTUAL_ROOM_BOB = "$virtual_bob_room:example.org";
|
|||
// Bob's phone number
|
||||
const BOB_PHONE_NUMBER = "01818118181";
|
||||
|
||||
function mkStubDM(roomId, userId) {
|
||||
function mkStubDM(roomId: string, userId: string) {
|
||||
const room = mkStubRoom(roomId, "room", MatrixClientPeg.get());
|
||||
room.getJoinedMembers = jest.fn().mockReturnValue([
|
||||
{
|
||||
|
@ -134,23 +157,24 @@ function untilCallHandlerEvent(callHandler: LegacyCallHandler, event: LegacyCall
|
|||
|
||||
describe("LegacyCallHandler", () => {
|
||||
let dmRoomMap;
|
||||
let callHandler;
|
||||
let callHandler: LegacyCallHandler;
|
||||
let audioElement: HTMLAudioElement;
|
||||
let fakeCall;
|
||||
let fakeCall: MatrixCall | null;
|
||||
|
||||
// what addresses the app has looked up via pstn and native lookup
|
||||
let pstnLookup: string;
|
||||
let nativeLookup: string;
|
||||
let pstnLookup: string | null;
|
||||
let nativeLookup: string | null;
|
||||
const deviceId = "my-device";
|
||||
|
||||
beforeEach(async () => {
|
||||
stubClient();
|
||||
MatrixClientPeg.get().createCall = (roomId) => {
|
||||
fakeCall = null;
|
||||
MatrixClientPeg.get().createCall = (roomId: string): MatrixCall | null => {
|
||||
if (fakeCall && fakeCall.roomId !== roomId) {
|
||||
throw new Error("Only one call is supported!");
|
||||
}
|
||||
fakeCall = new FakeCall(roomId);
|
||||
return fakeCall;
|
||||
fakeCall = new FakeCall(roomId) as unknown as MatrixCall;
|
||||
return fakeCall as unknown as MatrixCall;
|
||||
};
|
||||
MatrixClientPeg.get().deviceId = deviceId;
|
||||
|
||||
|
@ -172,7 +196,7 @@ describe("LegacyCallHandler", () => {
|
|||
const nativeRoomCharie = mkStubDM(NATIVE_ROOM_CHARLIE, NATIVE_CHARLIE);
|
||||
const virtualBobRoom = mkStubDM(VIRTUAL_ROOM_BOB, VIRTUAL_BOB);
|
||||
|
||||
MatrixClientPeg.get().getRoom = (roomId) => {
|
||||
MatrixClientPeg.get().getRoom = (roomId: string): Room | null => {
|
||||
switch (roomId) {
|
||||
case NATIVE_ROOM_ALICE:
|
||||
return nativeRoomAlice;
|
||||
|
@ -183,6 +207,8 @@ describe("LegacyCallHandler", () => {
|
|||
case VIRTUAL_ROOM_BOB:
|
||||
return virtualBobRoom;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
dmRoomMap = {
|
||||
|
@ -212,13 +238,13 @@ describe("LegacyCallHandler", () => {
|
|||
return [];
|
||||
}
|
||||
},
|
||||
};
|
||||
} as DMRoomMap;
|
||||
DMRoomMap.setShared(dmRoomMap);
|
||||
|
||||
pstnLookup = null;
|
||||
nativeLookup = null;
|
||||
|
||||
MatrixClientPeg.get().getThirdpartyUser = (proto, params) => {
|
||||
MatrixClientPeg.get().getThirdpartyUser = (proto: string, params: any) => {
|
||||
if ([PROTOCOL_PSTN, PROTOCOL_PSTN_PREFIXED].includes(proto)) {
|
||||
pstnLookup = params["m.id.phone"];
|
||||
return Promise.resolve([
|
||||
|
@ -261,6 +287,8 @@ describe("LegacyCallHandler", () => {
|
|||
}
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
return Promise.resolve([]);
|
||||
};
|
||||
|
||||
audioElement = document.createElement("audio");
|
||||
|
@ -270,10 +298,10 @@ describe("LegacyCallHandler", () => {
|
|||
|
||||
afterEach(() => {
|
||||
callHandler.stop();
|
||||
// @ts-ignore
|
||||
DMRoomMap.setShared(null);
|
||||
// @ts-ignore
|
||||
window.mxLegacyCallHandler = null;
|
||||
fakeCall = null;
|
||||
MatrixClientPeg.unset();
|
||||
|
||||
document.body.removeChild(audioElement);
|
||||
|
@ -292,25 +320,27 @@ describe("LegacyCallHandler", () => {
|
|||
|
||||
// Check that a call was started: its room on the protocol level
|
||||
// should be the virtual room
|
||||
expect(fakeCall.roomId).toEqual(VIRTUAL_ROOM_BOB);
|
||||
expect(fakeCall).not.toBeNull();
|
||||
expect(fakeCall?.roomId).toEqual(VIRTUAL_ROOM_BOB);
|
||||
|
||||
// but it should appear to the user to be in thw native room for Bob
|
||||
expect(callHandler.roomIdForCall(fakeCall)).toEqual(NATIVE_ROOM_BOB);
|
||||
expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_BOB);
|
||||
});
|
||||
|
||||
it("should look up the correct user and start a call in the room when a call is transferred", async () => {
|
||||
// we can pass a very minimal object as as the call since we pass consultFirst=true:
|
||||
// we don't need to actually do any transferring
|
||||
const mockTransferreeCall = { type: CallType.Voice };
|
||||
const mockTransferreeCall = { type: CallType.Voice } as unknown as MatrixCall;
|
||||
await callHandler.startTransferToPhoneNumber(mockTransferreeCall, BOB_PHONE_NUMBER, true);
|
||||
|
||||
// same checks as above
|
||||
const viewRoomPayload = await untilDispatch(Action.ViewRoom);
|
||||
expect(viewRoomPayload.room_id).toEqual(NATIVE_ROOM_BOB);
|
||||
|
||||
expect(fakeCall.roomId).toEqual(VIRTUAL_ROOM_BOB);
|
||||
expect(fakeCall).not.toBeNull();
|
||||
expect(fakeCall!.roomId).toEqual(VIRTUAL_ROOM_BOB);
|
||||
|
||||
expect(callHandler.roomIdForCall(fakeCall)).toEqual(NATIVE_ROOM_BOB);
|
||||
expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_BOB);
|
||||
});
|
||||
|
||||
it("should move calls between rooms when remote asserted identity changes", async () => {
|
||||
|
@ -331,10 +361,11 @@ describe("LegacyCallHandler", () => {
|
|||
|
||||
// Now emit an asserted identity for Bob: this should be ignored
|
||||
// because we haven't set the config option to obey asserted identity
|
||||
fakeCall.getRemoteAssertedIdentity = jest.fn().mockReturnValue({
|
||||
expect(fakeCall).not.toBeNull();
|
||||
fakeCall!.getRemoteAssertedIdentity = jest.fn().mockReturnValue({
|
||||
id: NATIVE_BOB,
|
||||
});
|
||||
fakeCall.emit(CallEvent.AssertedIdentityChanged);
|
||||
fakeCall!.emit(CallEvent.AssertedIdentityChanged);
|
||||
|
||||
// Now set the config option
|
||||
SdkConfig.add({
|
||||
|
@ -344,10 +375,10 @@ describe("LegacyCallHandler", () => {
|
|||
});
|
||||
|
||||
// ...and send another asserted identity event for a different user
|
||||
fakeCall.getRemoteAssertedIdentity = jest.fn().mockReturnValue({
|
||||
fakeCall!.getRemoteAssertedIdentity = jest.fn().mockReturnValue({
|
||||
id: NATIVE_CHARLIE,
|
||||
});
|
||||
fakeCall.emit(CallEvent.AssertedIdentityChanged);
|
||||
fakeCall!.emit(CallEvent.AssertedIdentityChanged);
|
||||
|
||||
await roomChangePromise;
|
||||
callHandler.removeAllListeners();
|
||||
|
@ -362,21 +393,68 @@ describe("LegacyCallHandler", () => {
|
|||
expect(callHandler.getCallForRoom(NATIVE_ROOM_BOB)).toBeNull();
|
||||
expect(callHandler.getCallForRoom(NATIVE_ROOM_CHARLIE)).toBe(fakeCall);
|
||||
});
|
||||
|
||||
describe("when listening to a voice broadcast", () => {
|
||||
let voiceBroadcastPlayback: VoiceBroadcastPlayback;
|
||||
|
||||
beforeEach(() => {
|
||||
voiceBroadcastPlayback = new VoiceBroadcastPlayback(
|
||||
mkVoiceBroadcastInfoStateEvent(
|
||||
"!room:example.com",
|
||||
VoiceBroadcastInfoState.Started,
|
||||
MatrixClientPeg.get().getSafeUserId(),
|
||||
"d42",
|
||||
),
|
||||
MatrixClientPeg.get(),
|
||||
);
|
||||
SdkContextClass.instance.voiceBroadcastPlaybacksStore.setCurrent(voiceBroadcastPlayback);
|
||||
jest.spyOn(voiceBroadcastPlayback, "pause").mockImplementation();
|
||||
});
|
||||
|
||||
it("and placing a call should pause the broadcast", async () => {
|
||||
callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice);
|
||||
await untilCallHandlerEvent(callHandler, LegacyCallHandlerEvent.CallState);
|
||||
|
||||
expect(voiceBroadcastPlayback.pause).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when recording a voice broadcast", () => {
|
||||
beforeEach(() => {
|
||||
SdkContextClass.instance.voiceBroadcastRecordingsStore.setCurrent(
|
||||
new VoiceBroadcastRecording(
|
||||
mkVoiceBroadcastInfoStateEvent(
|
||||
"!room:example.com",
|
||||
VoiceBroadcastInfoState.Started,
|
||||
MatrixClientPeg.get().getSafeUserId(),
|
||||
"d42",
|
||||
),
|
||||
MatrixClientPeg.get(),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("and placing a call should show the info dialog", async () => {
|
||||
callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice);
|
||||
expect(Modal.createDialog).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("LegacyCallHandler without third party protocols", () => {
|
||||
let dmRoomMap;
|
||||
let callHandler: LegacyCallHandler;
|
||||
let audioElement: HTMLAudioElement;
|
||||
let fakeCall;
|
||||
let fakeCall: MatrixCall | null;
|
||||
|
||||
beforeEach(() => {
|
||||
stubClient();
|
||||
fakeCall = null;
|
||||
MatrixClientPeg.get().createCall = (roomId) => {
|
||||
if (fakeCall && fakeCall.roomId !== roomId) {
|
||||
throw new Error("Only one call is supported!");
|
||||
}
|
||||
fakeCall = new FakeCall(roomId);
|
||||
fakeCall = new FakeCall(roomId) as unknown as MatrixCall;
|
||||
return fakeCall;
|
||||
};
|
||||
|
||||
|
@ -389,11 +467,13 @@ describe("LegacyCallHandler without third party protocols", () => {
|
|||
|
||||
const nativeRoomAlice = mkStubDM(NATIVE_ROOM_ALICE, NATIVE_ALICE);
|
||||
|
||||
MatrixClientPeg.get().getRoom = (roomId) => {
|
||||
MatrixClientPeg.get().getRoom = (roomId: string): Room | null => {
|
||||
switch (roomId) {
|
||||
case NATIVE_ROOM_ALICE:
|
||||
return nativeRoomAlice;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
dmRoomMap = {
|
||||
|
@ -411,7 +491,7 @@ describe("LegacyCallHandler without third party protocols", () => {
|
|||
return [];
|
||||
}
|
||||
},
|
||||
};
|
||||
} as DMRoomMap;
|
||||
DMRoomMap.setShared(dmRoomMap);
|
||||
|
||||
MatrixClientPeg.get().getThirdpartyUser = (_proto, _params) => {
|
||||
|
@ -421,14 +501,17 @@ describe("LegacyCallHandler without third party protocols", () => {
|
|||
audioElement = document.createElement("audio");
|
||||
audioElement.id = "remoteAudio";
|
||||
document.body.appendChild(audioElement);
|
||||
|
||||
SdkContextClass.instance.voiceBroadcastPlaybacksStore.clearCurrent();
|
||||
SdkContextClass.instance.voiceBroadcastRecordingsStore.clearCurrent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
callHandler.stop();
|
||||
// @ts-ignore
|
||||
DMRoomMap.setShared(null);
|
||||
// @ts-ignore
|
||||
window.mxLegacyCallHandler = null;
|
||||
fakeCall = null;
|
||||
MatrixClientPeg.unset();
|
||||
|
||||
document.body.removeChild(audioElement);
|
||||
|
@ -442,10 +525,11 @@ describe("LegacyCallHandler without third party protocols", () => {
|
|||
|
||||
// Check that a call was started: its room on the protocol level
|
||||
// should be the virtual room
|
||||
expect(fakeCall.roomId).toEqual(NATIVE_ROOM_ALICE);
|
||||
expect(fakeCall).not.toBeNull();
|
||||
expect(fakeCall!.roomId).toEqual(NATIVE_ROOM_ALICE);
|
||||
|
||||
// but it should appear to the user to be in thw native room for Bob
|
||||
expect(callHandler.roomIdForCall(fakeCall)).toEqual(NATIVE_ROOM_ALICE);
|
||||
expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_ALICE);
|
||||
});
|
||||
|
||||
describe("incoming calls", () => {
|
||||
|
|
24
test/__snapshots__/LegacyCallHandler-test.ts.snap
Normal file
24
test/__snapshots__/LegacyCallHandler-test.ts.snap
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`LegacyCallHandler when recording a voice broadcast and placing a call should show the info dialog 1`] = `
|
||||
[MockFunction] {
|
||||
"calls": [
|
||||
[
|
||||
[Function],
|
||||
{
|
||||
"description": <p>
|
||||
You can’t start a call as you are currently recording a live broadcast. Please end your live broadcast in order to start a call.
|
||||
</p>,
|
||||
"hasCloseButton": true,
|
||||
"title": "Can’t start a call",
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
|
@ -28,6 +28,17 @@ import { UPDATE_EVENT } from "../../src/stores/AsyncStore";
|
|||
import { ActiveRoomChangedPayload } from "../../src/dispatcher/payloads/ActiveRoomChangedPayload";
|
||||
import { SpaceStoreClass } from "../../src/stores/spaces/SpaceStore";
|
||||
import { TestSdkContext } from "../TestSdkContext";
|
||||
import { ViewRoomPayload } from "../../src/dispatcher/payloads/ViewRoomPayload";
|
||||
import {
|
||||
VoiceBroadcastInfoState,
|
||||
VoiceBroadcastPlayback,
|
||||
VoiceBroadcastPlaybacksStore,
|
||||
VoiceBroadcastRecording,
|
||||
} from "../../src/voice-broadcast";
|
||||
import { mkVoiceBroadcastInfoStateEvent } from "../voice-broadcast/utils/test-utils";
|
||||
import Modal from "../../src/Modal";
|
||||
|
||||
jest.mock("../../src/Modal");
|
||||
|
||||
// mock out the injected classes
|
||||
jest.mock("../../src/PosthogAnalytics");
|
||||
|
@ -37,6 +48,22 @@ const MockSlidingSyncManager = <jest.Mock<SlidingSyncManager>>(<unknown>SlidingS
|
|||
jest.mock("../../src/stores/spaces/SpaceStore");
|
||||
const MockSpaceStore = <jest.Mock<SpaceStoreClass>>(<unknown>SpaceStoreClass);
|
||||
|
||||
// mock VoiceRecording because it contains all the audio APIs
|
||||
jest.mock("../../src/audio/VoiceRecording", () => ({
|
||||
VoiceRecording: jest.fn().mockReturnValue({
|
||||
disableMaxLength: jest.fn(),
|
||||
liveData: {
|
||||
onUpdate: jest.fn(),
|
||||
},
|
||||
off: jest.fn(),
|
||||
on: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
destroy: jest.fn(),
|
||||
contentType: "audio/ogg",
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock("../../src/utils/DMRoomMap", () => {
|
||||
const mock = {
|
||||
getUserIdForRoomId: jest.fn(),
|
||||
|
@ -60,12 +87,24 @@ describe("RoomViewStore", function () {
|
|||
getRoom: jest.fn(),
|
||||
getRoomIdForAlias: jest.fn(),
|
||||
isGuest: jest.fn(),
|
||||
getSafeUserId: jest.fn(),
|
||||
});
|
||||
const room = new Room(roomId, mockClient, userId);
|
||||
|
||||
const viewCall = async (): Promise<void> => {
|
||||
dis.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
room_id: roomId,
|
||||
view_call: true,
|
||||
metricsTrigger: undefined,
|
||||
});
|
||||
await untilDispatch(Action.ViewRoom, dis);
|
||||
};
|
||||
|
||||
let roomViewStore: RoomViewStore;
|
||||
let slidingSyncManager: SlidingSyncManager;
|
||||
let dis: MatrixDispatcher;
|
||||
let stores: TestSdkContext;
|
||||
|
||||
beforeEach(function () {
|
||||
jest.clearAllMocks();
|
||||
|
@ -73,14 +112,16 @@ describe("RoomViewStore", function () {
|
|||
mockClient.joinRoom.mockResolvedValue(room);
|
||||
mockClient.getRoom.mockReturnValue(room);
|
||||
mockClient.isGuest.mockReturnValue(false);
|
||||
mockClient.getSafeUserId.mockReturnValue(userId);
|
||||
|
||||
// Make the RVS to test
|
||||
dis = new MatrixDispatcher();
|
||||
slidingSyncManager = new MockSlidingSyncManager();
|
||||
const stores = new TestSdkContext();
|
||||
stores = new TestSdkContext();
|
||||
stores._SlidingSyncManager = slidingSyncManager;
|
||||
stores._PosthogAnalytics = new MockPosthogAnalytics();
|
||||
stores._SpaceStore = new MockSpaceStore();
|
||||
stores._VoiceBroadcastPlaybacksStore = new VoiceBroadcastPlaybacksStore();
|
||||
roomViewStore = new RoomViewStore(dis, stores);
|
||||
stores._RoomViewStore = roomViewStore;
|
||||
});
|
||||
|
@ -206,6 +247,56 @@ describe("RoomViewStore", function () {
|
|||
expect(roomViewStore.getRoomId()).toBeNull();
|
||||
});
|
||||
|
||||
it("when viewing a call without a broadcast, it should not raise an error", async () => {
|
||||
await viewCall();
|
||||
});
|
||||
|
||||
describe("when listening to a voice broadcast", () => {
|
||||
let voiceBroadcastPlayback: VoiceBroadcastPlayback;
|
||||
|
||||
beforeEach(() => {
|
||||
voiceBroadcastPlayback = new VoiceBroadcastPlayback(
|
||||
mkVoiceBroadcastInfoStateEvent(
|
||||
roomId,
|
||||
VoiceBroadcastInfoState.Started,
|
||||
mockClient.getSafeUserId(),
|
||||
"d42",
|
||||
),
|
||||
mockClient,
|
||||
);
|
||||
stores.voiceBroadcastPlaybacksStore.setCurrent(voiceBroadcastPlayback);
|
||||
jest.spyOn(voiceBroadcastPlayback, "pause").mockImplementation();
|
||||
});
|
||||
|
||||
it("and viewing a call it should pause the current broadcast", async () => {
|
||||
await viewCall();
|
||||
expect(voiceBroadcastPlayback.pause).toHaveBeenCalled();
|
||||
expect(roomViewStore.isViewingCall()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when recording a voice broadcast", () => {
|
||||
beforeEach(() => {
|
||||
stores.voiceBroadcastRecordingsStore.setCurrent(
|
||||
new VoiceBroadcastRecording(
|
||||
mkVoiceBroadcastInfoStateEvent(
|
||||
roomId,
|
||||
VoiceBroadcastInfoState.Started,
|
||||
mockClient.getSafeUserId(),
|
||||
"d42",
|
||||
),
|
||||
mockClient,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("and trying to view a call, it should not actually view it and show the info dialog", async () => {
|
||||
await viewCall();
|
||||
expect(Modal.createDialog).toMatchSnapshot();
|
||||
expect(roomViewStore.isViewingCall()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Sliding Sync", function () {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName, roomId, value) => {
|
||||
|
|
24
test/stores/__snapshots__/RoomViewStore-test.ts.snap
Normal file
24
test/stores/__snapshots__/RoomViewStore-test.ts.snap
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`RoomViewStore when recording a voice broadcast and trying to view a call, it should not actually view it and show the info dialog 1`] = `
|
||||
[MockFunction] {
|
||||
"calls": [
|
||||
[
|
||||
[Function],
|
||||
{
|
||||
"description": <p>
|
||||
You can’t start a call as you are currently recording a live broadcast. Please end your live broadcast in order to start a call.
|
||||
</p>,
|
||||
"hasCloseButton": true,
|
||||
"title": "Can’t start a call",
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
Loading…
Reference in a new issue