From cc4e24bc8af2a1ed3eed17d4e4e2e820d06cdf19 Mon Sep 17 00:00:00 2001 From: BountyGrid Date: Fri, 28 Aug 2026 15:17:08 -0700 Subject: [PATCH 1/4] test(chrome-extension): add unit test coverage for toSessionDescriptionInit --- .../src/shared/webrtc.test.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) 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", + ); + }); +}); + From f5e0c2245b417cc21b25049ee5765a8623951823 Mon Sep 17 00:00:00 2001 From: BountyGrid Date: Fri, 28 Aug 2026 15:55:19 -0700 Subject: [PATCH 2/4] test(recorder-core): add test coverage for detectRecordingModeFromTrack --- .../__tests__/recorder-utils.test.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/recorder-core/__tests__/recorder-utils.test.ts b/packages/recorder-core/__tests__/recorder-utils.test.ts index 2c8da9b20f..95383ad766 100644 --- a/packages/recorder-core/__tests__/recorder-utils.test.ts +++ b/packages/recorder-core/__tests__/recorder-utils.test.ts @@ -198,3 +198,35 @@ 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"); + }); +}); + From 872ea398b711983f00b072862166424a6646af73 Mon Sep 17 00:00:00 2001 From: BountyGrid Date: Fri, 28 Aug 2026 16:01:19 -0700 Subject: [PATCH 3/4] style: apply biome formatting to recorder-utils.test.ts --- packages/recorder-core/__tests__/recorder-utils.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/recorder-core/__tests__/recorder-utils.test.ts b/packages/recorder-core/__tests__/recorder-utils.test.ts index 95383ad766..51704559ae 100644 --- a/packages/recorder-core/__tests__/recorder-utils.test.ts +++ b/packages/recorder-core/__tests__/recorder-utils.test.ts @@ -229,4 +229,3 @@ describe("detectRecordingModeFromTrack", () => { expect(detectRecordingModeFromTrack(tabTrack)).toBe("tab"); }); }); - From d8a07a9e524d5d0860de96598fe5475650628289 Mon Sep 17 00:00:00 2001 From: BountyGrid Date: Sat, 29 Aug 2026 03:05:23 -0700 Subject: [PATCH 4/4] test(recorder-core): add unit tests for error retry and user cancellation utilities --- .../__tests__/recorder-utils.test.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/packages/recorder-core/__tests__/recorder-utils.test.ts b/packages/recorder-core/__tests__/recorder-utils.test.ts index 51704559ae..0244fff6f9 100644 --- a/packages/recorder-core/__tests__/recorder-utils.test.ts +++ b/packages/recorder-core/__tests__/recorder-utils.test.ts @@ -229,3 +229,47 @@ describe("detectRecordingModeFromTrack", () => { 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); + }); +});