Confirm listen to a broadcast while recording (#9831)

This commit is contained in:
Michael Weimann 2023-01-02 13:21:33 +01:00 committed by GitHub
parent 91e078d96b
commit 0f7a2ce6df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 213 additions and 29 deletions

View file

@ -26,6 +26,7 @@ import {
VoiceBroadcastRecording,
VoiceBroadcastPlaybackBody,
VoiceBroadcastPlayback,
VoiceBroadcastRecordingsStore,
} from "../../../src/voice-broadcast";
import { stubClient, wrapInSdkContext } from "../../test-utils";
import { mkVoiceBroadcastInfoStateEvent } from "../utils/test-utils";
@ -91,7 +92,7 @@ describe("VoiceBroadcastBody", () => {
);
room.addEventsToTimeline([infoEvent], true, room.getLiveTimeline());
testRecording = new VoiceBroadcastRecording(infoEvent, client);
testPlayback = new VoiceBroadcastPlayback(infoEvent, client);
testPlayback = new VoiceBroadcastPlayback(infoEvent, client, new VoiceBroadcastRecordingsStore());
mocked(VoiceBroadcastRecordingBody).mockImplementation(({ recording }): ReactElement | null => {
if (testRecording === recording) {
return <div data-testid="voice-broadcast-recording-body" />;

View file

@ -32,6 +32,7 @@ import { stubClient } from "../../../test-utils";
import { mkVoiceBroadcastInfoStateEvent } from "../../utils/test-utils";
import dis from "../../../../src/dispatcher/dispatcher";
import { Action } from "../../../../src/dispatcher/actions";
import { SdkContextClass } from "../../../../src/contexts/SDKContext";
jest.mock("../../../../src/dispatcher/dispatcher");
@ -66,7 +67,11 @@ describe("VoiceBroadcastPlaybackBody", () => {
});
beforeEach(() => {
playback = new VoiceBroadcastPlayback(infoEvent, client);
playback = new VoiceBroadcastPlayback(
infoEvent,
client,
SdkContextClass.instance.voiceBroadcastRecordingsStore,
);
jest.spyOn(playback, "toggle").mockImplementation(() => Promise.resolve());
jest.spyOn(playback, "getLiveness");
jest.spyOn(playback, "getState");

View file

@ -66,8 +66,8 @@ describe("VoiceBroadcastPreRecordingPip", () => {
client = stubClient();
room = new Room("!room@example.com", client, client.getUserId() || "");
sender = new RoomMember(room.roomId, client.getUserId() || "");
playbacksStore = new VoiceBroadcastPlaybacksStore();
recordingsStore = new VoiceBroadcastRecordingsStore();
playbacksStore = new VoiceBroadcastPlaybacksStore(recordingsStore);
mocked(requestMediaPermissions).mockResolvedValue({
getTracks: (): Array<MediaStreamTrack> => [],
} as unknown as MediaStream);

View file

@ -29,6 +29,7 @@ import {
} from "../../../../src/voice-broadcast";
import { stubClient } from "../../../test-utils";
import { mkVoiceBroadcastInfoStateEvent } from "../../utils/test-utils";
import { SdkContextClass } from "../../../../src/contexts/SDKContext";
// mock RoomAvatar, because it is doing too much fancy stuff
jest.mock("../../../../src/components/views/avatars/RoomAvatar", () => ({
@ -60,7 +61,11 @@ describe("<VoiceBroadcastSmallPlaybackBody />", () => {
});
beforeEach(() => {
playback = new VoiceBroadcastPlayback(infoEvent, client);
playback = new VoiceBroadcastPlayback(
infoEvent,
client,
SdkContextClass.instance.voiceBroadcastRecordingsStore,
);
jest.spyOn(playback, "toggle").mockImplementation(() => Promise.resolve());
jest.spyOn(playback, "getLiveness");
jest.spyOn(playback, "getState");

View file

@ -15,10 +15,13 @@ limitations under the License.
*/
import { mocked } from "jest-mock";
import { screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
import { Playback, PlaybackState } from "../../../src/audio/Playback";
import { PlaybackManager } from "../../../src/audio/PlaybackManager";
import { SdkContextClass } from "../../../src/contexts/SDKContext";
import { MediaEventHelper } from "../../../src/utils/MediaEventHelper";
import {
VoiceBroadcastInfoState,
@ -26,6 +29,7 @@ import {
VoiceBroadcastPlayback,
VoiceBroadcastPlaybackEvent,
VoiceBroadcastPlaybackState,
VoiceBroadcastRecording,
} from "../../../src/voice-broadcast";
import { flushPromises, stubClient } from "../../test-utils";
import { createTestPlayback } from "../../test-utils/audio";
@ -65,6 +69,17 @@ describe("VoiceBroadcastPlayback", () => {
let chunk2Playback: Playback;
let chunk3Playback: Playback;
const queryConfirmListeningDialog = () => {
return screen.queryByText(
"If you start listening to this live broadcast, your current live broadcast recording will be ended.",
);
};
const waitForDialog = async () => {
await flushPromises();
await flushPromises();
};
const itShouldSetTheStateTo = (state: VoiceBroadcastPlaybackState) => {
it(`should set the state to ${state}`, () => {
expect(playback.getState()).toBe(state);
@ -119,7 +134,11 @@ describe("VoiceBroadcastPlayback", () => {
};
const mkPlayback = async () => {
const playback = new VoiceBroadcastPlayback(infoEvent, client);
const playback = new VoiceBroadcastPlayback(
infoEvent,
client,
SdkContextClass.instance.voiceBroadcastRecordingsStore,
);
jest.spyOn(playback, "removeAllListeners");
jest.spyOn(playback, "destroy");
playback.on(VoiceBroadcastPlaybackEvent.StateChanged, onStateChanged);
@ -178,7 +197,11 @@ describe("VoiceBroadcastPlayback", () => {
onStateChanged = jest.fn();
});
afterEach(() => {
afterEach(async () => {
SdkContextClass.instance.voiceBroadcastPlaybacksStore.getCurrent()?.stop();
SdkContextClass.instance.voiceBroadcastPlaybacksStore.clearCurrent();
await SdkContextClass.instance.voiceBroadcastRecordingsStore.getCurrent()?.stop();
SdkContextClass.instance.voiceBroadcastRecordingsStore.clearCurrent();
playback.destroy();
});
@ -347,6 +370,59 @@ describe("VoiceBroadcastPlayback", () => {
});
});
});
describe("and currently recording a broadcast", () => {
let recording: VoiceBroadcastRecording;
beforeEach(async () => {
recording = new VoiceBroadcastRecording(
mkVoiceBroadcastInfoStateEvent(
roomId,
VoiceBroadcastInfoState.Started,
client.getSafeUserId(),
client.deviceId,
),
client,
);
jest.spyOn(recording, "stop");
SdkContextClass.instance.voiceBroadcastRecordingsStore.setCurrent(recording);
playback.start();
await waitForDialog();
});
it("should display a confirm modal", () => {
expect(queryConfirmListeningDialog()).toBeInTheDocument();
});
describe("when confirming the dialog", () => {
beforeEach(async () => {
await userEvent.click(screen.getByText("Yes, end my recording"));
});
it("should stop the recording", () => {
expect(recording.stop).toHaveBeenCalled();
expect(SdkContextClass.instance.voiceBroadcastRecordingsStore.getCurrent()).toBeNull();
});
it("should not start the playback", () => {
expect(playback.getState()).toBe(VoiceBroadcastPlaybackState.Playing);
});
});
describe("when not confirming the dialog", () => {
beforeEach(async () => {
await userEvent.click(screen.getByText("No"));
});
it("should not stop the recording", () => {
expect(recording.stop).not.toHaveBeenCalled();
});
it("should start the playback", () => {
expect(playback.getState()).toBe(VoiceBroadcastPlaybackState.Stopped);
});
});
});
});
describe("when there is a stopped voice broadcast", () => {
@ -375,6 +451,12 @@ describe("VoiceBroadcastPlayback", () => {
expect(chunk2Playback.play).not.toHaveBeenCalled();
});
describe("and calling start again", () => {
it("should not play the first chunk a second time", () => {
expect(chunk1Playback.play).toHaveBeenCalledTimes(1);
});
});
describe("and the chunk playback progresses", () => {
beforeEach(() => {
chunk1Playback.clockInfo.liveData.update([11]);

View file

@ -40,8 +40,8 @@ describe("VoiceBroadcastPreRecording", () => {
client = stubClient();
room = new Room(roomId, client, client.getUserId() || "");
sender = new RoomMember(roomId, client.getUserId() || "");
playbacksStore = new VoiceBroadcastPlaybacksStore();
recordingsStore = new VoiceBroadcastRecordingsStore();
playbacksStore = new VoiceBroadcastPlaybacksStore(recordingsStore);
});
beforeEach(() => {

View file

@ -24,6 +24,7 @@ import {
VoiceBroadcastPlaybacksStore,
VoiceBroadcastPlaybacksStoreEvent,
VoiceBroadcastPlaybackState,
VoiceBroadcastRecordingsStore,
} from "../../../src/voice-broadcast";
import { mkStubRoom, stubClient } from "../../test-utils";
import { mkVoiceBroadcastInfoStateEvent } from "../utils/test-utils";
@ -59,12 +60,13 @@ describe("VoiceBroadcastPlaybacksStore", () => {
infoEvent1 = mkVoiceBroadcastInfoStateEvent(roomId, VoiceBroadcastInfoState.Started, userId, deviceId);
infoEvent2 = mkVoiceBroadcastInfoStateEvent(roomId, VoiceBroadcastInfoState.Started, userId, deviceId);
playback1 = new VoiceBroadcastPlayback(infoEvent1, client);
const recordings = new VoiceBroadcastRecordingsStore();
playback1 = new VoiceBroadcastPlayback(infoEvent1, client, recordings);
jest.spyOn(playback1, "off");
playback2 = new VoiceBroadcastPlayback(infoEvent2, client);
playback2 = new VoiceBroadcastPlayback(infoEvent2, client, recordings);
jest.spyOn(playback2, "off");
playbacks = new VoiceBroadcastPlaybacksStore();
playbacks = new VoiceBroadcastPlaybacksStore(recordings);
jest.spyOn(playbacks, "removeAllListeners");
onCurrentChanged = jest.fn();
playbacks.on(VoiceBroadcastPlaybacksStoreEvent.CurrentChanged, onCurrentChanged);

View file

@ -25,8 +25,6 @@ import {
} from "../../../src/voice-broadcast";
import { stubClient } from "../../test-utils";
jest.mock("../../../src/voice-broadcast/stores/VoiceBroadcastRecordingsStore");
describe("VoiceBroadcastPreRecordingStore", () => {
const roomId = "!room:example.com";
let client: MatrixClient;
@ -41,8 +39,8 @@ describe("VoiceBroadcastPreRecordingStore", () => {
client = stubClient();
room = new Room(roomId, client, client.getUserId() || "");
sender = new RoomMember(roomId, client.getUserId() || "");
playbacksStore = new VoiceBroadcastPlaybacksStore();
recordingsStore = new VoiceBroadcastRecordingsStore();
playbacksStore = new VoiceBroadcastPlaybacksStore(recordingsStore);
});
beforeEach(() => {

View file

@ -20,6 +20,7 @@ import {
VoiceBroadcastInfoState,
VoiceBroadcastPlayback,
VoiceBroadcastPlaybacksStore,
VoiceBroadcastRecordingsStore,
} from "../../../src/voice-broadcast";
import { pauseNonLiveBroadcastFromOtherRoom } from "../../../src/voice-broadcast/utils/pauseNonLiveBroadcastFromOtherRoom";
import { stubClient } from "../../test-utils";
@ -32,6 +33,7 @@ describe("pauseNonLiveBroadcastFromOtherRoom", () => {
let client: MatrixClient;
let playback: VoiceBroadcastPlayback;
let playbacks: VoiceBroadcastPlaybacksStore;
let recordings: VoiceBroadcastRecordingsStore;
const mkPlayback = (infoState: VoiceBroadcastInfoState, roomId: string): VoiceBroadcastPlayback => {
const infoEvent = mkVoiceBroadcastInfoStateEvent(
@ -40,7 +42,7 @@ describe("pauseNonLiveBroadcastFromOtherRoom", () => {
client.getSafeUserId(),
client.getDeviceId()!,
);
const playback = new VoiceBroadcastPlayback(infoEvent, client);
const playback = new VoiceBroadcastPlayback(infoEvent, client, recordings);
jest.spyOn(playback, "pause");
playbacks.setCurrent(playback);
return playback;
@ -49,7 +51,8 @@ describe("pauseNonLiveBroadcastFromOtherRoom", () => {
beforeEach(() => {
client = stubClient();
room = new Room(roomId, client, client.getSafeUserId());
playbacks = new VoiceBroadcastPlaybacksStore();
recordings = new VoiceBroadcastRecordingsStore();
playbacks = new VoiceBroadcastPlaybacksStore(recordings);
jest.spyOn(playbacks, "clearCurrent");
});

View file

@ -80,10 +80,10 @@ describe("setUpVoiceBroadcastPreRecording", () => {
);
preRecording = null;
preRecordingStore = new VoiceBroadcastPreRecordingStore();
playback = new VoiceBroadcastPlayback(infoEvent, client);
jest.spyOn(playback, "pause");
playbacksStore = new VoiceBroadcastPlaybacksStore();
recordingsStore = new VoiceBroadcastRecordingsStore();
playback = new VoiceBroadcastPlayback(infoEvent, client, recordingsStore);
jest.spyOn(playback, "pause");
playbacksStore = new VoiceBroadcastPlaybacksStore(recordingsStore);
});
describe("when the preconditions fail", () => {

View file

@ -84,7 +84,7 @@ describe("startNewVoiceBroadcastRecording", () => {
skey: "",
});
playbacksStore = new VoiceBroadcastPlaybacksStore();
playbacksStore = new VoiceBroadcastPlaybacksStore(recordingsStore);
recordingsStore = {
setCurrent: jest.fn(),
getCurrent: jest.fn(),
@ -112,7 +112,7 @@ describe("startNewVoiceBroadcastRecording", () => {
let playback: VoiceBroadcastPlayback;
beforeEach(() => {
playback = new VoiceBroadcastPlayback(infoEvent, client);
playback = new VoiceBroadcastPlayback(infoEvent, client, recordingsStore);
jest.spyOn(playback, "pause");
playbacksStore.setCurrent(playback);
});