gradio/js/image/shared/stream_utils.test.ts
Hannah 057d171c71
Correctly handle device selection in Image and ImageEditor (#7754)
* move on:change to <select>

* add changeset

* move device logic to separate file + fix safari incompatability

* improve selected logic

* add stream_utils unit tests

* refactor default device logic

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2024-04-08 19:20:47 +01:00

135 lines
3.3 KiB
TypeScript

import { describe, expect, vi } from "vitest";
import {
get_devices,
get_video_stream,
set_available_devices,
set_local_stream
} from "./stream_utils";
import * as stream_utils from "./stream_utils";
let test_device: MediaDeviceInfo = {
deviceId: "test-device",
kind: "videoinput",
label: "Test Device",
groupId: "camera",
toJSON: () => ({
deviceId: "test-device",
kind: "videoinput",
label: "Test Device",
groupId: "camera"
})
};
const mock_enumerateDevices = vi.fn(async () => {
return new Promise<MediaDeviceInfo[]>((resolve) => {
resolve([test_device]);
});
});
const mock_getUserMedia = vi.fn(async () => {
return new Promise<MediaStream>((resolve) => {
resolve(new MediaStream());
});
});
window.MediaStream = vi.fn().mockImplementation(() => ({}));
Object.defineProperty(global.navigator, "mediaDevices", {
value: {
getUserMedia: mock_getUserMedia,
enumerateDevices: mock_enumerateDevices
}
});
describe("stream_utils", () => {
test("get_devices should enumerate media devices", async () => {
const devices = await get_devices();
expect(devices).toEqual([test_device]);
});
test("set_local_stream should set the local stream to the video source", () => {
const mock_stream = {}; // mocked MediaStream obj as it's not available in a node env
const mock_video_source = {
srcObject: null,
muted: false,
play: vi.fn()
};
// @ts-ignore
set_local_stream(mock_stream, mock_video_source);
expect(mock_video_source.srcObject).toEqual(mock_stream);
expect(mock_video_source.muted).toBeTruthy();
expect(mock_video_source.play).toHaveBeenCalled();
});
test("get_video_stream requests user media with the correct constraints and sets the local stream", async () => {
const mock_video_source = document.createElement("video");
const mock_stream = new MediaStream();
global.navigator.mediaDevices.getUserMedia = vi
.fn()
.mockResolvedValue(mock_stream);
await get_video_stream(true, mock_video_source);
expect(navigator.mediaDevices.getUserMedia).toHaveBeenCalledWith({
video: { width: { ideal: 1920 }, height: { ideal: 1440 } },
audio: true
});
const spy_set_local_stream = vi.spyOn(stream_utils, "set_local_stream");
stream_utils.set_local_stream(mock_stream, mock_video_source);
expect(spy_set_local_stream).toHaveBeenCalledWith(
mock_stream,
mock_video_source
);
spy_set_local_stream.mockRestore();
});
test("set_available_devices should return only video input devices", () => {
const mockDevices: MediaDeviceInfo[] = [
{
deviceId: "camera1",
kind: "videoinput",
label: "Camera 1",
groupId: "camera",
toJSON: () => ({
deviceId: "camera1",
kind: "videoinput",
label: "Camera 1",
groupId: "camera"
})
},
{
deviceId: "camera2",
kind: "videoinput",
label: "Camera 2",
groupId: "camera",
toJSON: () => ({
deviceId: "camera2",
kind: "videoinput",
label: "Camera 2",
groupId: "camera"
})
},
{
deviceId: "audio1",
kind: "audioinput",
label: "Audio 2",
groupId: "audio",
toJSON: () => ({
deviceId: "audio1",
kind: "audioinput",
label: "Audio 2",
groupId: "audio"
})
}
];
const videoDevices = set_available_devices(mockDevices);
expect(videoDevices).toEqual(mockDevices.splice(0, 2));
});
});