Handle broadcast chunk errors (#9970)
* Use strings for broadcast playback states * Handle broadcast decode errors
This commit is contained in:
parent
60edb85a1a
commit
533b250bb6
10 changed files with 483 additions and 275 deletions
|
@ -659,6 +659,7 @@
|
||||||
"%(senderName)s ended a <a>voice broadcast</a>": "%(senderName)s 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",
|
"You ended a voice broadcast": "You ended a voice broadcast",
|
||||||
"%(senderName)s ended a voice broadcast": "%(senderName)s ended a voice broadcast",
|
"%(senderName)s ended a voice broadcast": "%(senderName)s ended a voice broadcast",
|
||||||
|
"Unable to play this voice broadcast": "Unable to play this voice broadcast",
|
||||||
"Stop live broadcasting?": "Stop live broadcasting?",
|
"Stop live broadcasting?": "Stop live broadcasting?",
|
||||||
"Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.": "Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.",
|
"Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.": "Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.",
|
||||||
"Yes, stop broadcast": "Yes, stop broadcast",
|
"Yes, stop broadcast": "Yes, stop broadcast",
|
||||||
|
|
32
src/voice-broadcast/components/atoms/VoiceBroadcastError.tsx
Normal file
32
src/voice-broadcast/components/atoms/VoiceBroadcastError.tsx
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
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 React from "react";
|
||||||
|
|
||||||
|
import { Icon as WarningIcon } from "../../../../res/img/element-icons/warning.svg";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const VoiceBroadcastError: React.FC<Props> = ({ message }) => {
|
||||||
|
return (
|
||||||
|
<div className="mx_VoiceBroadcastRecordingConnectionError">
|
||||||
|
<WarningIcon className="mx_Icon mx_Icon_16" />
|
||||||
|
{message}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -18,6 +18,7 @@ import React, { ReactElement } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
VoiceBroadcastError,
|
||||||
VoiceBroadcastHeader,
|
VoiceBroadcastHeader,
|
||||||
VoiceBroadcastPlayback,
|
VoiceBroadcastPlayback,
|
||||||
VoiceBroadcastPlaybackControl,
|
VoiceBroadcastPlaybackControl,
|
||||||
|
@ -67,6 +68,24 @@ export const VoiceBroadcastPlaybackBody: React.FC<VoiceBroadcastPlaybackBodyProp
|
||||||
["mx_VoiceBroadcastBody--pip"]: pip,
|
["mx_VoiceBroadcastBody--pip"]: pip,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const content =
|
||||||
|
playbackState === VoiceBroadcastPlaybackState.Error ? (
|
||||||
|
<VoiceBroadcastError message={playback.errorMessage} />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="mx_VoiceBroadcastBody_controls">
|
||||||
|
{seekBackwardButton}
|
||||||
|
<VoiceBroadcastPlaybackControl state={playbackState} onClick={toggle} />
|
||||||
|
{seekForwardButton}
|
||||||
|
</div>
|
||||||
|
<SeekBar playback={playback} />
|
||||||
|
<div className="mx_VoiceBroadcastBody_timerow">
|
||||||
|
<Clock seconds={times.position} />
|
||||||
|
<Clock seconds={-times.timeLeft} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<VoiceBroadcastHeader
|
<VoiceBroadcastHeader
|
||||||
|
@ -77,16 +96,7 @@ export const VoiceBroadcastPlaybackBody: React.FC<VoiceBroadcastPlaybackBodyProp
|
||||||
showBroadcast={playbackState !== VoiceBroadcastPlaybackState.Buffering}
|
showBroadcast={playbackState !== VoiceBroadcastPlaybackState.Buffering}
|
||||||
showBuffering={playbackState === VoiceBroadcastPlaybackState.Buffering}
|
showBuffering={playbackState === VoiceBroadcastPlaybackState.Buffering}
|
||||||
/>
|
/>
|
||||||
<div className="mx_VoiceBroadcastBody_controls">
|
{content}
|
||||||
{seekBackwardButton}
|
|
||||||
<VoiceBroadcastPlaybackControl state={playbackState} onClick={toggle} />
|
|
||||||
{seekForwardButton}
|
|
||||||
</div>
|
|
||||||
<SeekBar playback={playback} />
|
|
||||||
<div className="mx_VoiceBroadcastBody_timerow">
|
|
||||||
<Clock seconds={times.position} />
|
|
||||||
<Clock seconds={-times.timeLeft} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@ export * from "./audio/VoiceBroadcastRecorder";
|
||||||
export * from "./components/VoiceBroadcastBody";
|
export * from "./components/VoiceBroadcastBody";
|
||||||
export * from "./components/atoms/LiveBadge";
|
export * from "./components/atoms/LiveBadge";
|
||||||
export * from "./components/atoms/VoiceBroadcastControl";
|
export * from "./components/atoms/VoiceBroadcastControl";
|
||||||
|
export * from "./components/atoms/VoiceBroadcastError";
|
||||||
export * from "./components/atoms/VoiceBroadcastHeader";
|
export * from "./components/atoms/VoiceBroadcastHeader";
|
||||||
export * from "./components/atoms/VoiceBroadcastPlaybackControl";
|
export * from "./components/atoms/VoiceBroadcastPlaybackControl";
|
||||||
export * from "./components/atoms/VoiceBroadcastRecordingConnectionError";
|
export * from "./components/atoms/VoiceBroadcastRecordingConnectionError";
|
||||||
|
|
|
@ -43,12 +43,14 @@ import {
|
||||||
import { RelationsHelper, RelationsHelperEvent } from "../../events/RelationsHelper";
|
import { RelationsHelper, RelationsHelperEvent } from "../../events/RelationsHelper";
|
||||||
import { VoiceBroadcastChunkEvents } from "../utils/VoiceBroadcastChunkEvents";
|
import { VoiceBroadcastChunkEvents } from "../utils/VoiceBroadcastChunkEvents";
|
||||||
import { determineVoiceBroadcastLiveness } from "../utils/determineVoiceBroadcastLiveness";
|
import { determineVoiceBroadcastLiveness } from "../utils/determineVoiceBroadcastLiveness";
|
||||||
|
import { _t } from "../../languageHandler";
|
||||||
|
|
||||||
export enum VoiceBroadcastPlaybackState {
|
export enum VoiceBroadcastPlaybackState {
|
||||||
Paused,
|
Paused = "pause",
|
||||||
Playing,
|
Playing = "playing",
|
||||||
Stopped,
|
Stopped = "stopped",
|
||||||
Buffering,
|
Buffering = "buffering",
|
||||||
|
Error = "error",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum VoiceBroadcastPlaybackEvent {
|
export enum VoiceBroadcastPlaybackEvent {
|
||||||
|
@ -205,12 +207,24 @@ export class VoiceBroadcastPlayback
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private async tryLoadPlayback(chunkEvent: MatrixEvent): Promise<void> {
|
||||||
|
try {
|
||||||
|
return await this.loadPlayback(chunkEvent);
|
||||||
|
} catch (err) {
|
||||||
|
logger.warn("Unable to load broadcast playback", {
|
||||||
|
message: err.message,
|
||||||
|
broadcastId: this.infoEvent.getId(),
|
||||||
|
chunkId: chunkEvent.getId(),
|
||||||
|
});
|
||||||
|
this.setError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async loadPlayback(chunkEvent: MatrixEvent): Promise<void> {
|
private async loadPlayback(chunkEvent: MatrixEvent): Promise<void> {
|
||||||
const eventId = chunkEvent.getId();
|
const eventId = chunkEvent.getId();
|
||||||
|
|
||||||
if (!eventId) {
|
if (!eventId) {
|
||||||
logger.warn("got voice broadcast chunk event without ID", this.infoEvent, chunkEvent);
|
throw new Error("Broadcast chunk event without Id occurred");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const helper = new MediaEventHelper(chunkEvent);
|
const helper = new MediaEventHelper(chunkEvent);
|
||||||
|
@ -311,16 +325,28 @@ export class VoiceBroadcastPlayback
|
||||||
private async playEvent(event: MatrixEvent): Promise<void> {
|
private async playEvent(event: MatrixEvent): Promise<void> {
|
||||||
this.setState(VoiceBroadcastPlaybackState.Playing);
|
this.setState(VoiceBroadcastPlaybackState.Playing);
|
||||||
this.currentlyPlaying = event;
|
this.currentlyPlaying = event;
|
||||||
const playback = await this.getOrLoadPlaybackForEvent(event);
|
const playback = await this.tryGetOrLoadPlaybackForEvent(event);
|
||||||
playback?.play();
|
playback?.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async tryGetOrLoadPlaybackForEvent(event: MatrixEvent): Promise<Playback | undefined> {
|
||||||
|
try {
|
||||||
|
return await this.getOrLoadPlaybackForEvent(event);
|
||||||
|
} catch (err) {
|
||||||
|
logger.warn("Unable to load broadcast playback", {
|
||||||
|
message: err.message,
|
||||||
|
broadcastId: this.infoEvent.getId(),
|
||||||
|
chunkId: event.getId(),
|
||||||
|
});
|
||||||
|
this.setError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async getOrLoadPlaybackForEvent(event: MatrixEvent): Promise<Playback | undefined> {
|
private async getOrLoadPlaybackForEvent(event: MatrixEvent): Promise<Playback | undefined> {
|
||||||
const eventId = event.getId();
|
const eventId = event.getId();
|
||||||
|
|
||||||
if (!eventId) {
|
if (!eventId) {
|
||||||
logger.warn("event without id occurred");
|
throw new Error("Broadcast chunk event without Id occurred");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.playbacks.has(eventId)) {
|
if (!this.playbacks.has(eventId)) {
|
||||||
|
@ -330,13 +356,12 @@ export class VoiceBroadcastPlayback
|
||||||
const playback = this.playbacks.get(eventId);
|
const playback = this.playbacks.get(eventId);
|
||||||
|
|
||||||
if (!playback) {
|
if (!playback) {
|
||||||
// logging error, because this should not happen
|
throw new Error(`Unable to find playback for event ${event.getId()}`);
|
||||||
logger.warn("unable to find playback for event", event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to load the playback for the next event for a smooth(er) playback
|
// try to load the playback for the next event for a smooth(er) playback
|
||||||
const nextEvent = this.chunkEvents.getNext(event);
|
const nextEvent = this.chunkEvents.getNext(event);
|
||||||
if (nextEvent) this.loadPlayback(nextEvent);
|
if (nextEvent) this.tryLoadPlayback(nextEvent);
|
||||||
|
|
||||||
return playback;
|
return playback;
|
||||||
}
|
}
|
||||||
|
@ -405,8 +430,8 @@ export class VoiceBroadcastPlayback
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentPlayback = this.getCurrentPlayback();
|
const currentPlayback = this.getCurrentPlayback();
|
||||||
|
const skipToPlayback = await this.tryGetOrLoadPlaybackForEvent(event);
|
||||||
const currentPlaybackEvent = this.currentlyPlaying;
|
const currentPlaybackEvent = this.currentlyPlaying;
|
||||||
const skipToPlayback = await this.getOrLoadPlaybackForEvent(event);
|
|
||||||
|
|
||||||
if (!skipToPlayback) {
|
if (!skipToPlayback) {
|
||||||
logger.warn("voice broadcast chunk to skip to not found", event);
|
logger.warn("voice broadcast chunk to skip to not found", event);
|
||||||
|
@ -464,6 +489,9 @@ export class VoiceBroadcastPlayback
|
||||||
}
|
}
|
||||||
|
|
||||||
public stop(): void {
|
public stop(): void {
|
||||||
|
// error is a final state
|
||||||
|
if (this.getState() === VoiceBroadcastPlaybackState.Error) return;
|
||||||
|
|
||||||
this.setState(VoiceBroadcastPlaybackState.Stopped);
|
this.setState(VoiceBroadcastPlaybackState.Stopped);
|
||||||
this.getCurrentPlayback()?.stop();
|
this.getCurrentPlayback()?.stop();
|
||||||
this.currentlyPlaying = null;
|
this.currentlyPlaying = null;
|
||||||
|
@ -471,6 +499,9 @@ export class VoiceBroadcastPlayback
|
||||||
}
|
}
|
||||||
|
|
||||||
public pause(): void {
|
public pause(): void {
|
||||||
|
// error is a final state
|
||||||
|
if (this.getState() === VoiceBroadcastPlaybackState.Error) return;
|
||||||
|
|
||||||
// stopped voice broadcasts cannot be paused
|
// stopped voice broadcasts cannot be paused
|
||||||
if (this.getState() === VoiceBroadcastPlaybackState.Stopped) return;
|
if (this.getState() === VoiceBroadcastPlaybackState.Stopped) return;
|
||||||
|
|
||||||
|
@ -479,6 +510,9 @@ export class VoiceBroadcastPlayback
|
||||||
}
|
}
|
||||||
|
|
||||||
public resume(): void {
|
public resume(): void {
|
||||||
|
// error is a final state
|
||||||
|
if (this.getState() === VoiceBroadcastPlaybackState.Error) return;
|
||||||
|
|
||||||
if (!this.currentlyPlaying) {
|
if (!this.currentlyPlaying) {
|
||||||
// no playback to resume, start from the beginning
|
// no playback to resume, start from the beginning
|
||||||
this.start();
|
this.start();
|
||||||
|
@ -496,6 +530,9 @@ export class VoiceBroadcastPlayback
|
||||||
* paused → playing
|
* paused → playing
|
||||||
*/
|
*/
|
||||||
public async toggle(): Promise<void> {
|
public async toggle(): Promise<void> {
|
||||||
|
// error is a final state
|
||||||
|
if (this.getState() === VoiceBroadcastPlaybackState.Error) return;
|
||||||
|
|
||||||
if (this.state === VoiceBroadcastPlaybackState.Stopped) {
|
if (this.state === VoiceBroadcastPlaybackState.Stopped) {
|
||||||
await this.start();
|
await this.start();
|
||||||
return;
|
return;
|
||||||
|
@ -514,6 +551,9 @@ export class VoiceBroadcastPlayback
|
||||||
}
|
}
|
||||||
|
|
||||||
private setState(state: VoiceBroadcastPlaybackState): void {
|
private setState(state: VoiceBroadcastPlaybackState): void {
|
||||||
|
// error is a final state
|
||||||
|
if (this.getState() === VoiceBroadcastPlaybackState.Error) return;
|
||||||
|
|
||||||
if (this.state === state) {
|
if (this.state === state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -522,6 +562,16 @@ export class VoiceBroadcastPlayback
|
||||||
this.emit(VoiceBroadcastPlaybackEvent.StateChanged, state, this);
|
this.emit(VoiceBroadcastPlaybackEvent.StateChanged, state, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set error state. Stop current playback, if any.
|
||||||
|
*/
|
||||||
|
private setError(): void {
|
||||||
|
this.setState(VoiceBroadcastPlaybackState.Error);
|
||||||
|
this.getCurrentPlayback()?.stop();
|
||||||
|
this.currentlyPlaying = null;
|
||||||
|
this.setPosition(0);
|
||||||
|
}
|
||||||
|
|
||||||
public getInfoState(): VoiceBroadcastInfoState {
|
public getInfoState(): VoiceBroadcastInfoState {
|
||||||
return this.infoState;
|
return this.infoState;
|
||||||
}
|
}
|
||||||
|
@ -536,6 +586,10 @@ export class VoiceBroadcastPlayback
|
||||||
this.setLiveness(determineVoiceBroadcastLiveness(this.infoState));
|
this.setLiveness(determineVoiceBroadcastLiveness(this.infoState));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get errorMessage(): string {
|
||||||
|
return this.getState() === VoiceBroadcastPlaybackState.Error ? _t("Unable to play this voice broadcast") : "";
|
||||||
|
}
|
||||||
|
|
||||||
public destroy(): void {
|
public destroy(): void {
|
||||||
this.chunkRelationHelper.destroy();
|
this.chunkRelationHelper.destroy();
|
||||||
this.infoRelationHelper.destroy();
|
this.infoRelationHelper.destroy();
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`<VoiceBroadcastPlaybackControl /> should render state 0 as expected 1`] = `
|
exports[`<VoiceBroadcastPlaybackControl /> should render state buffering as expected 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
aria-label="pause voice broadcast"
|
||||||
|
class="mx_AccessibleButton mx_VoiceBroadcastControl"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`<VoiceBroadcastPlaybackControl /> should render state pause as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
aria-label="resume voice broadcast"
|
aria-label="resume voice broadcast"
|
||||||
|
@ -15,7 +30,7 @@ exports[`<VoiceBroadcastPlaybackControl /> should render state 0 as expected 1`]
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<VoiceBroadcastPlaybackControl /> should render state 1 as expected 1`] = `
|
exports[`<VoiceBroadcastPlaybackControl /> should render state playing as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
aria-label="pause voice broadcast"
|
aria-label="pause voice broadcast"
|
||||||
|
@ -30,7 +45,7 @@ exports[`<VoiceBroadcastPlaybackControl /> should render state 1 as expected 1`]
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<VoiceBroadcastPlaybackControl /> should render state 2 as expected 1`] = `
|
exports[`<VoiceBroadcastPlaybackControl /> should render state stopped as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
aria-label="play voice broadcast"
|
aria-label="play voice broadcast"
|
||||||
|
@ -44,18 +59,3 @@ exports[`<VoiceBroadcastPlaybackControl /> should render state 2 as expected 1`]
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<VoiceBroadcastPlaybackControl /> should render state 3 as expected 1`] = `
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
aria-label="pause voice broadcast"
|
|
||||||
class="mx_AccessibleButton mx_VoiceBroadcastControl"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_16"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ import {
|
||||||
VoiceBroadcastPlaybackEvent,
|
VoiceBroadcastPlaybackEvent,
|
||||||
VoiceBroadcastPlaybackState,
|
VoiceBroadcastPlaybackState,
|
||||||
} from "../../../../src/voice-broadcast";
|
} from "../../../../src/voice-broadcast";
|
||||||
import { stubClient } from "../../../test-utils";
|
import { filterConsole, stubClient } from "../../../test-utils";
|
||||||
import { mkVoiceBroadcastInfoStateEvent } from "../../utils/test-utils";
|
import { mkVoiceBroadcastInfoStateEvent } from "../../utils/test-utils";
|
||||||
import dis from "../../../../src/dispatcher/dispatcher";
|
import dis from "../../../../src/dispatcher/dispatcher";
|
||||||
import { Action } from "../../../../src/dispatcher/actions";
|
import { Action } from "../../../../src/dispatcher/actions";
|
||||||
|
@ -53,6 +53,11 @@ describe("VoiceBroadcastPlaybackBody", () => {
|
||||||
let playback: VoiceBroadcastPlayback;
|
let playback: VoiceBroadcastPlayback;
|
||||||
let renderResult: RenderResult;
|
let renderResult: RenderResult;
|
||||||
|
|
||||||
|
filterConsole(
|
||||||
|
// expected for some tests
|
||||||
|
"voice broadcast chunk event to skip to not found",
|
||||||
|
);
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
client = stubClient();
|
client = stubClient();
|
||||||
mocked(client.relations).mockClear();
|
mocked(client.relations).mockClear();
|
||||||
|
@ -214,6 +219,17 @@ describe("VoiceBroadcastPlaybackBody", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("when rendering an error broadcast", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mocked(playback.getState).mockReturnValue(VoiceBroadcastPlaybackState.Error);
|
||||||
|
renderResult = render(<VoiceBroadcastPlaybackBody playback={playback} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render as expected", () => {
|
||||||
|
expect(renderResult.container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe.each([
|
describe.each([
|
||||||
[VoiceBroadcastPlaybackState.Paused, "not-live"],
|
[VoiceBroadcastPlaybackState.Paused, "not-live"],
|
||||||
[VoiceBroadcastPlaybackState.Playing, "live"],
|
[VoiceBroadcastPlaybackState.Playing, "live"],
|
||||||
|
|
|
@ -1,235 +1,5 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`VoiceBroadcastPlaybackBody when rendering a 0/not-live broadcast should render as expected 1`] = `
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastBody"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastHeader"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
data-testid="room-avatar"
|
|
||||||
>
|
|
||||||
room avatar:
|
|
||||||
My room
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastHeader_content"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastHeader_room_wrapper"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastHeader_room"
|
|
||||||
>
|
|
||||||
My room
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
aria-label="Change input device"
|
|
||||||
class="mx_AccessibleButton mx_VoiceBroadcastHeader_line"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_16"
|
|
||||||
/>
|
|
||||||
<span>
|
|
||||||
@user:example.com
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastHeader_line"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_16"
|
|
||||||
/>
|
|
||||||
Voice broadcast
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastBody_controls"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-label="30s backward"
|
|
||||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_secondary_content"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_24"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
aria-label="resume voice broadcast"
|
|
||||||
class="mx_AccessibleButton mx_VoiceBroadcastControl mx_VoiceBroadcastControl-play"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_16"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
aria-label="30s forward"
|
|
||||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_secondary_content"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_24"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<input
|
|
||||||
class="mx_SeekBar"
|
|
||||||
max="1"
|
|
||||||
min="0"
|
|
||||||
step="0.001"
|
|
||||||
style="--fillTo: 0;"
|
|
||||||
tabindex="0"
|
|
||||||
type="range"
|
|
||||||
value="0"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastBody_timerow"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="mx_Clock"
|
|
||||||
>
|
|
||||||
00:00
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="mx_Clock"
|
|
||||||
>
|
|
||||||
-23:42
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`VoiceBroadcastPlaybackBody when rendering a 1/live broadcast should render as expected 1`] = `
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastBody"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastHeader"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
data-testid="room-avatar"
|
|
||||||
>
|
|
||||||
room avatar:
|
|
||||||
My room
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastHeader_content"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastHeader_room_wrapper"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastHeader_room"
|
|
||||||
>
|
|
||||||
My room
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
aria-label="Change input device"
|
|
||||||
class="mx_AccessibleButton mx_VoiceBroadcastHeader_line"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_16"
|
|
||||||
/>
|
|
||||||
<span>
|
|
||||||
@user:example.com
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastHeader_line"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_16"
|
|
||||||
/>
|
|
||||||
Voice broadcast
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mx_LiveBadge"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_16"
|
|
||||||
/>
|
|
||||||
Live
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastBody_controls"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-label="30s backward"
|
|
||||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_secondary_content"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_24"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
aria-label="pause voice broadcast"
|
|
||||||
class="mx_AccessibleButton mx_VoiceBroadcastControl"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_16"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
aria-label="30s forward"
|
|
||||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_secondary_content"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Icon mx_Icon_24"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<input
|
|
||||||
class="mx_SeekBar"
|
|
||||||
max="1"
|
|
||||||
min="0"
|
|
||||||
step="0.001"
|
|
||||||
style="--fillTo: 0;"
|
|
||||||
tabindex="0"
|
|
||||||
type="range"
|
|
||||||
value="0"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="mx_VoiceBroadcastBody_timerow"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="mx_Clock"
|
|
||||||
>
|
|
||||||
00:00
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="mx_Clock"
|
|
||||||
>
|
|
||||||
-23:42
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`VoiceBroadcastPlaybackBody when rendering a buffering voice broadcast should render as expected 1`] = `
|
exports[`VoiceBroadcastPlaybackBody when rendering a buffering voice broadcast should render as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
@ -357,6 +127,117 @@ exports[`VoiceBroadcastPlaybackBody when rendering a buffering voice broadcast s
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`VoiceBroadcastPlaybackBody when rendering a pause/not-live broadcast should render as expected 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastBody"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="room-avatar"
|
||||||
|
>
|
||||||
|
room avatar:
|
||||||
|
My room
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_room_wrapper"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_room"
|
||||||
|
>
|
||||||
|
My room
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-label="Change input device"
|
||||||
|
class="mx_AccessibleButton mx_VoiceBroadcastHeader_line"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
<span>
|
||||||
|
@user:example.com
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_line"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
Voice broadcast
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastBody_controls"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
aria-label="30s backward"
|
||||||
|
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_secondary_content"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-label="resume voice broadcast"
|
||||||
|
class="mx_AccessibleButton mx_VoiceBroadcastControl mx_VoiceBroadcastControl-play"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-label="30s forward"
|
||||||
|
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_secondary_content"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
class="mx_SeekBar"
|
||||||
|
max="1"
|
||||||
|
min="0"
|
||||||
|
step="0.001"
|
||||||
|
style="--fillTo: 0;"
|
||||||
|
tabindex="0"
|
||||||
|
type="range"
|
||||||
|
value="0"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastBody_timerow"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="mx_Clock"
|
||||||
|
>
|
||||||
|
00:00
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mx_Clock"
|
||||||
|
>
|
||||||
|
-23:42
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`VoiceBroadcastPlaybackBody when rendering a playing broadcast in pip mode should render as expected 1`] = `
|
exports[`VoiceBroadcastPlaybackBody when rendering a playing broadcast in pip mode should render as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
@ -591,6 +472,125 @@ exports[`VoiceBroadcastPlaybackBody when rendering a playing broadcast should re
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`VoiceBroadcastPlaybackBody when rendering a playing/live broadcast should render as expected 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastBody"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="room-avatar"
|
||||||
|
>
|
||||||
|
room avatar:
|
||||||
|
My room
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_room_wrapper"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_room"
|
||||||
|
>
|
||||||
|
My room
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-label="Change input device"
|
||||||
|
class="mx_AccessibleButton mx_VoiceBroadcastHeader_line"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
<span>
|
||||||
|
@user:example.com
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_line"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
Voice broadcast
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_LiveBadge"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
Live
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastBody_controls"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
aria-label="30s backward"
|
||||||
|
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_secondary_content"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-label="pause voice broadcast"
|
||||||
|
class="mx_AccessibleButton mx_VoiceBroadcastControl"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-label="30s forward"
|
||||||
|
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_secondary_content"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
class="mx_SeekBar"
|
||||||
|
max="1"
|
||||||
|
min="0"
|
||||||
|
step="0.001"
|
||||||
|
style="--fillTo: 0;"
|
||||||
|
tabindex="0"
|
||||||
|
type="range"
|
||||||
|
value="0"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastBody_timerow"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="mx_Clock"
|
||||||
|
>
|
||||||
|
00:00
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mx_Clock"
|
||||||
|
>
|
||||||
|
-23:42
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`VoiceBroadcastPlaybackBody when rendering a stopped broadcast should render as expected 1`] = `
|
exports[`VoiceBroadcastPlaybackBody when rendering a stopped broadcast should render as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
@ -681,3 +681,64 @@ exports[`VoiceBroadcastPlaybackBody when rendering a stopped broadcast should re
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`VoiceBroadcastPlaybackBody when rendering an error broadcast should render as expected 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastBody"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="room-avatar"
|
||||||
|
>
|
||||||
|
room avatar:
|
||||||
|
My room
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_room_wrapper"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_room"
|
||||||
|
>
|
||||||
|
My room
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-label="Change input device"
|
||||||
|
class="mx_AccessibleButton mx_VoiceBroadcastHeader_line"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
<span>
|
||||||
|
@user:example.com
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastHeader_line"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
Voice broadcast
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_VoiceBroadcastRecordingConnectionError"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Icon mx_Icon_16"
|
||||||
|
/>
|
||||||
|
Unable to play this voice broadcast
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`<VoiceBroadcastSmallPlaybackBody /> when rendering a { state: 0, liveness: 'not-live' }/%s broadcast should render as expected 1`] = `
|
exports[`<VoiceBroadcastSmallPlaybackBody /> when rendering a { state: 'pause', liveness: 'not-live' }/%s broadcast should render as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastBody mx_VoiceBroadcastBody--pip mx_VoiceBroadcastBody--small"
|
class="mx_VoiceBroadcastBody mx_VoiceBroadcastBody--pip mx_VoiceBroadcastBody--small"
|
||||||
|
@ -76,7 +76,7 @@ exports[`<VoiceBroadcastSmallPlaybackBody /> when rendering a { state: 0, livene
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<VoiceBroadcastSmallPlaybackBody /> when rendering a { state: 1, liveness: 'live' }/%s broadcast should render as expected 1`] = `
|
exports[`<VoiceBroadcastSmallPlaybackBody /> when rendering a { state: 'playing', liveness: 'live' }/%s broadcast should render as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastBody mx_VoiceBroadcastBody--pip mx_VoiceBroadcastBody--small"
|
class="mx_VoiceBroadcastBody mx_VoiceBroadcastBody--pip mx_VoiceBroadcastBody--small"
|
||||||
|
|
|
@ -186,7 +186,11 @@ describe("VoiceBroadcastPlayback", () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
filterConsole("Starting load of AsyncWrapper for modal");
|
filterConsole(
|
||||||
|
"Starting load of AsyncWrapper for modal",
|
||||||
|
// expected for some tests
|
||||||
|
"Unable to load broadcast playback",
|
||||||
|
);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
client = stubClient();
|
client = stubClient();
|
||||||
|
@ -283,6 +287,35 @@ describe("VoiceBroadcastPlayback", () => {
|
||||||
expect(playback.durationSeconds).toEqual(6.5);
|
expect(playback.durationSeconds).toEqual(6.5);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("and starting a playback with a broken chunk", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
mocked(chunk2Playback.prepare).mockRejectedValue("Error decoding chunk");
|
||||||
|
await playback.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Error);
|
||||||
|
|
||||||
|
it("start() should keep it in the error state)", async () => {
|
||||||
|
await playback.start();
|
||||||
|
expect(playback.getState()).toBe(VoiceBroadcastPlaybackState.Error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("stop() should keep it in the error state)", () => {
|
||||||
|
playback.stop();
|
||||||
|
expect(playback.getState()).toBe(VoiceBroadcastPlaybackState.Error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("toggle() should keep it in the error state)", async () => {
|
||||||
|
await playback.toggle();
|
||||||
|
expect(playback.getState()).toBe(VoiceBroadcastPlaybackState.Error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("pause() should keep it in the error state)", () => {
|
||||||
|
playback.pause();
|
||||||
|
expect(playback.getState()).toBe(VoiceBroadcastPlaybackState.Error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("and an event with the same transaction Id occurs", () => {
|
describe("and an event with the same transaction Id occurs", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
room.addLiveEvents([chunk2BEvent]);
|
room.addLiveEvents([chunk2BEvent]);
|
||||||
|
|
Loading…
Reference in a new issue