diff --git a/apps/chrome-extension/src/shared/webrtc.test.ts b/apps/chrome-extension/src/shared/webrtc.test.ts index 8bbcc249ce..1461d556ee 100644 --- a/apps/chrome-extension/src/shared/webrtc.test.ts +++ b/apps/chrome-extension/src/shared/webrtc.test.ts @@ -50,3 +50,26 @@ describe("waitForIceGatheringComplete", () => { ); }); }); + +describe("toSessionDescriptionInit", () => { + it("formats valid RTCSessionDescription to RTCSessionDescriptionInit", async () => { + const { toSessionDescriptionInit } = await import("./webrtc"); + const desc = { + type: "offer" as RTCSdpType, + sdp: "v=0\r\no=- 123456 2 IN IP4 127.0.0.1\r\n", + toJSON: () => ({}), + }; + expect(toSessionDescriptionInit(desc as RTCSessionDescription)).toEqual({ + type: "offer", + sdp: "v=0\r\no=- 123456 2 IN IP4 127.0.0.1\r\n", + }); + }); + + it("throws error when session description is null or undefined", async () => { + const { toSessionDescriptionInit } = await import("./webrtc"); + expect(() => toSessionDescriptionInit(null)).toThrow( + "Missing session description", + ); + }); +}); + diff --git a/packages/recorder-core/__tests__/recorder-utils.test.ts b/packages/recorder-core/__tests__/recorder-utils.test.ts index 2c8da9b20f..0244fff6f9 100644 --- a/packages/recorder-core/__tests__/recorder-utils.test.ts +++ b/packages/recorder-core/__tests__/recorder-utils.test.ts @@ -198,3 +198,78 @@ describe("openShareUrlInNewTab", () => { expect(openShareUrlInNewTab("")).toBe(false); }); }); + +describe("detectRecordingModeFromTrack", () => { + it("returns null when track is null", async () => { + const { detectRecordingModeFromTrack } = await import( + "@cap/recorder-core/recorder-utils" + ); + expect(detectRecordingModeFromTrack(null)).toBeNull(); + }); + + it("detects fullscreen, window, and tab from track label heuristics", async () => { + const { detectRecordingModeFromTrack } = await import( + "@cap/recorder-core/recorder-utils" + ); + const screenTrack = { + label: "Entire Screen 1", + getSettings: () => ({}), + } as unknown as MediaStreamTrack; + const windowTrack = { + label: "Application Window (Cap)", + getSettings: () => ({}), + } as unknown as MediaStreamTrack; + const tabTrack = { + label: "Browser Tab - YouTube", + getSettings: () => ({}), + } as unknown as MediaStreamTrack; + + expect(detectRecordingModeFromTrack(screenTrack)).toBe("fullscreen"); + expect(detectRecordingModeFromTrack(windowTrack)).toBe("window"); + expect(detectRecordingModeFromTrack(tabTrack)).toBe("tab"); + }); +}); + +describe("error retry utilities", () => { + it("identifies user cancellation errors correctly", async () => { + const { isUserCancellationError } = await import( + "@cap/recorder-core/recorder-utils" + ); + const notAllowed = new DOMException("Permission denied", "NotAllowedError"); + const abort = new DOMException("Aborted by user", "AbortError"); + const other = new DOMException("Format unsupported", "NotSupportedError"); + + expect(isUserCancellationError(notAllowed)).toBe(true); + expect(isUserCancellationError(abort)).toBe(true); + expect(isUserCancellationError(other)).toBe(false); + expect(isUserCancellationError(new Error("generic error"))).toBe(false); + }); + + it("identifies retryable display media preference errors", async () => { + const { shouldRetryDisplayMediaWithoutPreferences } = await import( + "@cap/recorder-core/recorder-utils" + ); + const notSupported = new DOMException( + "Preferences not supported", + "NotSupportedError", + ); + const overconstrained = new DOMException( + "Constraint unfulfilled", + "OverconstrainedError", + ); + const invalidAccess = new DOMException( + "Invalid access", + "InvalidAccessError", + ); + const typeError = new TypeError("Invalid parameter"); + const notAllowed = new DOMException("Permission denied", "NotAllowedError"); + + expect(shouldRetryDisplayMediaWithoutPreferences(notSupported)).toBe(true); + expect(shouldRetryDisplayMediaWithoutPreferences(overconstrained)).toBe( + true, + ); + expect(shouldRetryDisplayMediaWithoutPreferences(invalidAccess)).toBe(true); + expect(shouldRetryDisplayMediaWithoutPreferences(typeError)).toBe(true); + expect(shouldRetryDisplayMediaWithoutPreferences(notAllowed)).toBe(false); + }); +});