Fix device selection in pre-join screen for Element Call video rooms (#9321)
* Fix device selection in pre-join screen for Element Call video rooms As per https://github.com/vector-im/element-call/pull/609 * Update unit test * Lint * Hold a media stream while we enumerate device so we can do so reliably. This means we can remove the device fallback labels. * i18n * Remove unnecessary useState * Fix fetching video devices when video muted * Actually fix preview stream code * Fix unit test now fallback is no longer a thing * Test changing devices
This commit is contained in:
parent
eaff7e945c
commit
07a5a1dc6f
7 changed files with 123 additions and 66 deletions
|
@ -187,6 +187,35 @@ describe("CallLobby", () => {
|
|||
});
|
||||
|
||||
describe("device buttons", () => {
|
||||
const fakeVideoInput1: MediaDeviceInfo = {
|
||||
deviceId: "v1",
|
||||
groupId: "v1",
|
||||
label: "Webcam",
|
||||
kind: "videoinput",
|
||||
toJSON: () => {},
|
||||
};
|
||||
const fakeVideoInput2: MediaDeviceInfo = {
|
||||
deviceId: "v2",
|
||||
groupId: "v2",
|
||||
label: "Othercam",
|
||||
kind: "videoinput",
|
||||
toJSON: () => {},
|
||||
};
|
||||
const fakeAudioInput1: MediaDeviceInfo = {
|
||||
deviceId: "v1",
|
||||
groupId: "v1",
|
||||
label: "Headphones",
|
||||
kind: "audioinput",
|
||||
toJSON: () => {},
|
||||
};
|
||||
const fakeAudioInput2: MediaDeviceInfo = {
|
||||
deviceId: "v2",
|
||||
groupId: "v2",
|
||||
label: "Tailphones",
|
||||
kind: "audioinput",
|
||||
toJSON: () => {},
|
||||
};
|
||||
|
||||
it("hide when no devices are available", async () => {
|
||||
await renderView();
|
||||
expect(screen.queryByRole("button", { name: /microphone/ })).toBe(null);
|
||||
|
@ -194,13 +223,7 @@ describe("CallLobby", () => {
|
|||
});
|
||||
|
||||
it("show without dropdown when only one device is available", async () => {
|
||||
mocked(navigator.mediaDevices.enumerateDevices).mockResolvedValue([{
|
||||
deviceId: "1",
|
||||
groupId: "1",
|
||||
label: "Webcam",
|
||||
kind: "videoinput",
|
||||
toJSON: () => {},
|
||||
}]);
|
||||
mocked(navigator.mediaDevices.enumerateDevices).mockResolvedValue([fakeVideoInput1]);
|
||||
|
||||
await renderView();
|
||||
screen.getByRole("button", { name: /camera/ });
|
||||
|
@ -209,27 +232,40 @@ describe("CallLobby", () => {
|
|||
|
||||
it("show with dropdown when multiple devices are available", async () => {
|
||||
mocked(navigator.mediaDevices.enumerateDevices).mockResolvedValue([
|
||||
{
|
||||
deviceId: "1",
|
||||
groupId: "1",
|
||||
label: "Headphones",
|
||||
kind: "audioinput",
|
||||
toJSON: () => {},
|
||||
},
|
||||
{
|
||||
deviceId: "2",
|
||||
groupId: "1",
|
||||
label: "", // Should fall back to "Audio input 2"
|
||||
kind: "audioinput",
|
||||
toJSON: () => {},
|
||||
},
|
||||
fakeAudioInput1, fakeAudioInput2,
|
||||
]);
|
||||
|
||||
await renderView();
|
||||
screen.getByRole("button", { name: /microphone/ });
|
||||
fireEvent.click(screen.getByRole("button", { name: "Audio devices" }));
|
||||
screen.getByRole("menuitem", { name: "Headphones" });
|
||||
screen.getByRole("menuitem", { name: "Audio input 2" });
|
||||
screen.getByRole("menuitem", { name: "Tailphones" });
|
||||
});
|
||||
|
||||
it("sets video device when selected", async () => {
|
||||
mocked(navigator.mediaDevices.enumerateDevices).mockResolvedValue([
|
||||
fakeVideoInput1, fakeVideoInput2,
|
||||
]);
|
||||
|
||||
await renderView();
|
||||
screen.getByRole("button", { name: /camera/ });
|
||||
fireEvent.click(screen.getByRole("button", { name: "Video devices" }));
|
||||
fireEvent.click(screen.getByRole("menuitem", { name: fakeVideoInput2.label }));
|
||||
|
||||
expect(client.getMediaHandler().setVideoInput).toHaveBeenCalledWith(fakeVideoInput2.deviceId);
|
||||
});
|
||||
|
||||
it("sets audio device when selected", async () => {
|
||||
mocked(navigator.mediaDevices.enumerateDevices).mockResolvedValue([
|
||||
fakeAudioInput1, fakeAudioInput2,
|
||||
]);
|
||||
|
||||
await renderView();
|
||||
screen.getByRole("button", { name: /microphone/ });
|
||||
fireEvent.click(screen.getByRole("button", { name: "Audio devices" }));
|
||||
fireEvent.click(screen.getByRole("menuitem", { name: fakeAudioInput2.label }));
|
||||
|
||||
expect(client.getMediaHandler().setAudioInput).toHaveBeenCalledWith(fakeAudioInput2.deviceId);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -616,8 +616,8 @@ describe("ElementCall", () => {
|
|||
await call.connect();
|
||||
expect(call.connectionState).toBe(ConnectionState.Connected);
|
||||
expect(messaging.transport.send).toHaveBeenCalledWith(ElementWidgetActions.JoinCall, {
|
||||
audioInput: "1",
|
||||
videoInput: "2",
|
||||
audioInput: "Headphones",
|
||||
videoInput: "Built-in webcam",
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import {
|
|||
} from 'matrix-js-sdk/src/matrix';
|
||||
import { normalize } from "matrix-js-sdk/src/utils";
|
||||
import { ReEmitter } from "matrix-js-sdk/src/ReEmitter";
|
||||
import { MediaHandler } from "matrix-js-sdk/src/webrtc/mediaHandler";
|
||||
|
||||
import { MatrixClientPeg as peg } from '../../src/MatrixClientPeg';
|
||||
import { makeType } from "../../src/utils/TypeUtils";
|
||||
|
@ -175,6 +176,11 @@ export function createTestClient(): MatrixClient {
|
|||
sendToDevice: jest.fn().mockResolvedValue(undefined),
|
||||
queueToDevice: jest.fn().mockResolvedValue(undefined),
|
||||
encryptAndSendToDevices: jest.fn().mockResolvedValue(undefined),
|
||||
|
||||
getMediaHandler: jest.fn().mockReturnValue({
|
||||
setVideoInput: jest.fn(),
|
||||
setAudioInput: jest.fn(),
|
||||
} as unknown as MediaHandler),
|
||||
} as unknown as MatrixClient;
|
||||
|
||||
client.reEmitter = new ReEmitter(client);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue