UNPKG

av-kit

Version:

AVFoundation Recorder kit for Node.js

192 lines (158 loc) 5 kB
// Required by Jest: hoisting mocks to the top jest.mock("../src/ffmpeg-manager", () => ({ FFmpegProcessManager: jest.fn(), })); jest.mock("../src/utils"); import { Recorder } from "../src/recorder"; import { Camera, Display, DisplayRecordingItem, Microphone, RecorderOptions, WebcamRecordingItem, } from "../src/types"; // Mock devices const devicesMock = { displays: [ { id: "display1", name: "Main Display" } as Display, { id: "display2", name: "Secondary Display" } as Display, ], cameras: [ { id: "camera1", name: "FaceTime HD Camera" } as Camera, { id: "camera2", name: "External Camera" } as Camera, ], microphones: [ { id: "mic1", name: "Built-in Microphone" } as Microphone, { id: "mic2", name: "External Microphone" } as Microphone, ], }; // Mock process manager const mockProcessManager = { startProcess: jest.fn().mockResolvedValue(undefined), stopProcess: jest.fn().mockResolvedValue(undefined), stopAllProcesses: jest.fn().mockResolvedValue(undefined), }; describe("Recorder", () => { let recorder: Recorder; // Mock utilities that will be spied on const utils = require("../src/utils"); const FFmpegProcessManager = require("../src/ffmpeg-manager").FFmpegProcessManager; // Ensure we have valid Display and Camera objects with non-null assertion const display = devicesMock.displays[0]!; const camera = devicesMock.cameras[0]!; const microphone = devicesMock.microphones[0]!; const displayItem: DisplayRecordingItem = { type: "display", display, }; const webcamItem: WebcamRecordingItem = { type: "webcam", camera, microphone, }; const options: RecorderOptions = { output_directory: "/test/output", items: [displayItem, webcamItem], }; beforeEach(() => { // Clear all mocks before each test jest.clearAllMocks(); // Configure the mocks for this test utils.createOutputDirectory.mockImplementation((dir: string) => dir); utils.getAbsolutePath.mockImplementation((path: string) => path); utils.getDeviceIndex.mockResolvedValue(0); utils.getVideoMetadata.mockResolvedValue({ dimensions: { width: 1920, height: 1080, }, durationInSeconds: 60, }); utils.waitForFile.mockResolvedValue(true); // Make FFmpegProcessManager return our mock FFmpegProcessManager.mockImplementation(() => mockProcessManager); // Create a fresh recorder for each test recorder = new Recorder(options); }); describe("prepare", () => { it("should prepare recorder for recording", async () => { // Act await recorder.prepare(); // Assert expect(utils.createOutputDirectory).toHaveBeenCalledWith( options.output_directory ); }); it("should throw error if already prepared", async () => { // Arrange await recorder.prepare(); // Act & Assert await expect(recorder.prepare()).rejects.toThrow(); }); it("should throw error if no recording items provided", async () => { // Arrange const emptyRecorder = new Recorder({ output_directory: "/test/output", items: [], }); // Act & Assert await expect(emptyRecorder.prepare()).rejects.toThrow(); }); }); describe("start", () => { it("should start recording", async () => { // Arrange await recorder.prepare(); // Act await recorder.start(); // Assert - each item should spawn a process expect(mockProcessManager.startProcess).toHaveBeenCalledTimes( options.items.length ); }); it("should throw error if already recording", async () => { // Arrange await recorder.prepare(); await recorder.start(); // Set the recording flag manually Object.defineProperty(recorder, "recording", { value: true, writable: true, }); // Act & Assert await expect(recorder.start()).rejects.toThrow(); }); it("should auto-prepare if not prepared", async () => { // Act await recorder.start(); // Assert expect(mockProcessManager.startProcess).toHaveBeenCalledTimes( options.items.length ); }); }); describe("stop", () => { it("should stop recording and return results", async () => { // Arrange await recorder.prepare(); await recorder.start(); // Set the recording flag manually Object.defineProperty(recorder, "recording", { value: true, writable: true, }); // Act const result = await recorder.stop(); // Assert expect(mockProcessManager.stopAllProcesses).toHaveBeenCalled(); expect(result).toHaveProperty("files"); expect(result.files.length).toBe(options.items.length); }); it("should throw error if no recording in progress", async () => { // Act & Assert await expect(recorder.stop()).rejects.toThrow(); }); }); });