Skip to content

Conversation

@zibet27
Copy link
Collaborator

@zibet27 zibet27 commented Oct 17, 2025

Subsystem
WebRTC Client.

Motivation
JS tests were failing lately because of the Chrome for Testing update. Previous tests were based on the assumption that using the real browser media API should throw a NotFoundError. Moreover, Chrome was ignoring useful flags for testing like --use-fake-device-for-media-stream or --use-fake-ui-for-media-stream. Now, when we were trying to access the Browser Media API, it was "showing" an alert window and blocking the test.

Solution
Now, we can use mock media streams by enabling --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream, see Chromium options.

Extra:

  • Kotlin 2.2.0 shows a warning when using the experimental wasm api, so I've added suppressions.
  • updated to the version of kotlin-wrappers, which added useful extensions for ByteArray (before, we wrote them manually).

@zibet27 zibet27 requested review from bjhham and osipxd October 17, 2025 15:34
@zibet27 zibet27 self-assigned this Oct 17, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 17, 2025

Walkthrough

Updates Kotlin wrappers catalog version, adds ChromeHeadless media-stream mocking flags, removes internal JS interop conversion helpers, adds ExperimentalWasmJsInterop opt-ins across WebRTC JS/WASM files, refactors DataChannel/Browser interop conversions, and updates WebRTC media tests to create and inspect tracks explicitly.

Changes

Cohort / File(s) Change Summary
Build and test configuration
build-settings-logic/src/main/kotlin/ktorsettings.dependency-resolution-management.settings.gradle.kts, karma/chrome_bin.js
Bumps kotlin-wrappers catalog to 2025.10.8; adds ChromeHeadless flags --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream.
WebRTC JS/WASM utils removal
ktor-client/ktor-client-webrtc/js/src/io/ktor/client/webrtc/Utils.js.kt, ktor-client/ktor-client-webrtc/wasmJs/src/io/ktor/client/webrtc/Utils.wasmJs.kt
Removes internal JsArray/List conversion helpers (JsArray<T>.toArray(), List<T>.toJs()); keeps Throwable.asDomException() unchanged.
Shared interop opt-ins
ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/... (MediaDevices.kt, PeerConnection.kt, Rtp.kt, MockMediaDevices.kt)
Adds file-level @file:OptIn(ExperimentalWasmJsInterop::class) and imports like kotlin.js.toArray; no behavioral signature changes.
Browser conversion and stats
ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Browser.kt
Opts into ExperimentalWasmJsInterop; changes iceServers serialization to toJsArray(); refactors null-safe assignments for data fields; suppresses unchecked cast when iterating RTCStatsReport and returns collected list.
DataChannel interop changes
ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt
Opts into ExperimentalWasmJsInterop; sends ByteArray via Int8Array view, updates imports for typed-array conversions, and extends onmessage handling to support JsString, ArrayBuffer, and Blob conversions.
Utilities cleanup
ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Utils.kt
Removes ByteArray↔ArrayBuffer conversion helpers and JsArray expect declarations; adds ExperimentalWasmJsInterop opt-in.
Media tests refactoring
ktor-client/ktor-client-webrtc/jsAndWasmShared/test/io/ktor/client/webrtc/JsWebRtcMediaTest.kt
Adds ExperimentalWasmJsInterop opt-in; replaces device-absent flows with explicit track creation, introduces getSettings() helper, and asserts width/height/aspectRatio on tracks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • WebRTC Client #5069: Overlapping WebRTC JS/WASM interop changes (JsArray/List helper removal and ExperimentalWasmJsInterop opt-ins) impacting the same module and files.

Suggested labels

bug

Suggested reviewers

  • bjhham

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Fix WebRTC JS tests" directly and clearly addresses the primary objective of this pull request, which is to resolve failing WebRTC JavaScript tests caused by the Chrome for Testing update. The title is concise, specific about what is being fixed (WebRTC JS tests), and avoids vague terminology. While it does not detail the specific technical solution (mock media streams or kotlin-wrappers updates), it sufficiently captures the main change from the developer's perspective: the tests were broken and this PR fixes them. A teammate scanning the history would immediately understand that this PR addresses a broken test suite for WebRTC JS functionality.
Description Check ✅ Passed The pull request description fully complies with the required template structure. It includes all three mandatory sections: Subsystem (WebRTC Client), Motivation (explaining the Chrome for Testing update broke tests by ignoring fake media flags and showing blocking alerts), and Solution (enabling mock media streams using specific Chromium flags). The description is comprehensive, clearly explaining the problem and its resolution, and includes additional context about Kotlin 2.2.0 warnings and kotlin-wrappers updates that provide important context for understanding the broader changes in the PR. The information is specific and well-articulated, not vague or incomplete.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch zibet27/webrtc-fix-js-tests

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59e4807 and ed17431.

📒 Files selected for processing (1)
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt (3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{kt,kts}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{kt,kts}: Follow Kotlin official style guide for all Kotlin source and build scripts
Use star imports for io.ktor.* packages
Max line length is 120 characters
Indent with 4 spaces in Kotlin code
Include a copyright header in new Kotlin files

Files:

  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt
**/*.kt

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.kt: Document all public Kotlin APIs, including parameters, return types, and exceptions
Annotate internal APIs with @internalapi
Follow Kotlin error-handling conventions and use specific Ktor exceptions

Files:

  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt
🔇 Additional comments (3)
ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt (3)

8-9: LGTM! Import additions align with kotlin-wrappers update.

The new imports support the updated ByteArray extension methods from kotlin-wrappers and enable WASM interop functionality, consistent with the PR objectives.

Also applies to: 13-15, 17-18


66-66: LGTM! Correct use of TypedArray for data channel sends.

The change to toInt8Array() creates an Int8Array (ArrayBufferView), which is compatible with RTCDataChannel.send() and aligns with the updated kotlin-wrappers ByteArray extensions.


77-77: LGTM! Proper opt-in for experimental WASM API.

The @OptIn(ExperimentalWasmJsInterop::class) annotation is correctly placed and aligns with the PR objective to handle Kotlin 2.2.0 experimental WASM API warnings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt (2)

87-93: Text messages won’t match JsString. Use String (or typeof) check.

In browsers, e.data for text is a primitive string, not JsString. Current check can miss text and fall through.

-            when {
-                e.data is JsString -> {
-                    emitMessage(WebRtc.DataChannel.Message.Text(e.data.toString()))
-                }
+            when {
+                e.data is String -> {
+                    emitMessage(WebRtc.DataChannel.Message.Text(e.data as String))
+                }

Alternatively: when (jsTypeOf(e.data)) { "string" -> ... }.


97-100: Await Blob.arrayBuffer() before converting.

Blob.arrayBuffer() returns a Promise. You must await it before toByteArray().

+import kotlinx.coroutines.await
@@
-                    val buffer = (e.data as Blob).arrayBuffer()
-                    emitMessage(WebRtc.DataChannel.Message.Binary(buffer.toByteArray()))
+                    val buffer = (e.data as Blob).arrayBuffer().await()
+                    emitMessage(WebRtc.DataChannel.Message.Binary(buffer.toByteArray()))
ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Browser.kt (1)

94-103: Wrong enum used for ICE connection “completed” state.

Mapping uses RTCIceGatheringState.complete inside RTCIceConnectionState mapping; should be RTCIceConnectionState.completed.

 internal fun RTCIceConnectionState?.toKtor(): WebRtc.IceConnectionState = when (this) {
   RTCIceConnectionState.new -> WebRtc.IceConnectionState.NEW
   RTCIceConnectionState.checking -> WebRtc.IceConnectionState.CHECKING
   RTCIceConnectionState.connected -> WebRtc.IceConnectionState.CONNECTED
   RTCIceConnectionState.disconnected -> WebRtc.IceConnectionState.DISCONNECTED
   RTCIceConnectionState.failed -> WebRtc.IceConnectionState.FAILED
   RTCIceConnectionState.closed -> WebRtc.IceConnectionState.CLOSED
-  RTCIceGatheringState.complete -> WebRtc.IceConnectionState.COMPLETED
+  RTCIceConnectionState.completed -> WebRtc.IceConnectionState.COMPLETED
   else -> error("Unknown ice connection state: $this")
 }
🧹 Nitpick comments (3)
ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt (1)

65-67: Send typed array, not its underlying buffer.

Avoid sending the backing ArrayBuffer; send the Int8Array view to preserve length/offset correctness.

-        channel.send(bytes.toInt8Array().buffer)
+        channel.send(bytes.toInt8Array())
ktor-client/ktor-client-webrtc/jsAndWasmShared/test/io/ktor/client/webrtc/JsWebRtcMediaTest.kt (2)

42-45: Avoid string round‑trip for Boolean assertion.

Assert Boolean directly or via safe cast; this is clearer and avoids locale/format surprises.

-            assertEquals(true, settings1.echoCancellation.toString().toBoolean())
+            assertTrue(settings1.echoCancellation == true)

72-77: Use tolerance for Double comparison.

Floating values can be non‑exact; use delta.

-            assertEquals(2.0, settings2.aspectRatio)
+            assertEquals(2.0, settings2.aspectRatio, 0.001)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 931540f and 59e4807.

📒 Files selected for processing (12)
  • build-settings-logic/src/main/kotlin/ktorsettings.dependency-resolution-management.settings.gradle.kts (1 hunks)
  • karma/chrome_bin.js (1 hunks)
  • ktor-client/ktor-client-webrtc/js/src/io/ktor/client/webrtc/Utils.js.kt (0 hunks)
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Browser.kt (4 hunks)
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt (3 hunks)
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/MediaDevices.kt (2 hunks)
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/PeerConnection.kt (1 hunks)
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Rtp.kt (2 hunks)
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Utils.kt (2 hunks)
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/test/io/ktor/client/webrtc/JsWebRtcMediaTest.kt (2 hunks)
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/test/io/ktor/client/webrtc/MockMediaDevices.kt (2 hunks)
  • ktor-client/ktor-client-webrtc/wasmJs/src/io/ktor/client/webrtc/Utils.wasmJs.kt (1 hunks)
💤 Files with no reviewable changes (1)
  • ktor-client/ktor-client-webrtc/js/src/io/ktor/client/webrtc/Utils.js.kt
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{kt,kts}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{kt,kts}: Follow Kotlin official style guide for all Kotlin source and build scripts
Use star imports for io.ktor.* packages
Max line length is 120 characters
Indent with 4 spaces in Kotlin code
Include a copyright header in new Kotlin files

Files:

  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Rtp.kt
  • build-settings-logic/src/main/kotlin/ktorsettings.dependency-resolution-management.settings.gradle.kts
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Browser.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/PeerConnection.kt
  • ktor-client/ktor-client-webrtc/wasmJs/src/io/ktor/client/webrtc/Utils.wasmJs.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/test/io/ktor/client/webrtc/JsWebRtcMediaTest.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Utils.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/MediaDevices.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/test/io/ktor/client/webrtc/MockMediaDevices.kt
**/*.kt

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.kt: Document all public Kotlin APIs, including parameters, return types, and exceptions
Annotate internal APIs with @internalapi
Follow Kotlin error-handling conventions and use specific Ktor exceptions

Files:

  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Rtp.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Browser.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/PeerConnection.kt
  • ktor-client/ktor-client-webrtc/wasmJs/src/io/ktor/client/webrtc/Utils.wasmJs.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/test/io/ktor/client/webrtc/JsWebRtcMediaTest.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Utils.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/MediaDevices.kt
  • ktor-client/ktor-client-webrtc/jsAndWasmShared/test/io/ktor/client/webrtc/MockMediaDevices.kt
🧠 Learnings (1)
📚 Learning: 2025-08-15T09:12:47.243Z
Learnt from: zibet27
PR: ktorio/ktor#5044
File: ktor-client/ktor-client-webrtc/ktor-client-webrtc-rs/common/rust/senders.rs:88-96
Timestamp: 2025-08-15T09:12:47.243Z
Learning: In the webrtc Rust crate version used in the Ktor WebRTC RS implementation, the RTCRtpCodingParameters struct's rtx field is NOT optional and can be accessed directly as params.rtx.ssrc without needing Option handling.

Applied to files:

  • ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Rtp.kt
🧬 Code graph analysis (1)
ktor-client/ktor-client-webrtc/jsAndWasmShared/test/io/ktor/client/webrtc/JsWebRtcMediaTest.kt (1)
ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/MediaDevices.kt (1)
  • getNative (100-102)
🔇 Additional comments (9)
build-settings-logic/src/main/kotlin/ktorsettings.dependency-resolution-management.settings.gradle.kts (1)

29-29: LGTM!

The kotlin-wrappers catalog version update to 2025.10.8 aligns with the PR objective to use new ByteArray extensions and enables the experimental Wasm/JS interop features used throughout the WebRTC module.

ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Rtp.kt (1)

4-5: LGTM!

The opt-in annotation and imports properly enable experimental Wasm/JS interop features, allowing usage of toArray() on JS iterables throughout the file. This change is consistent with the PR-wide adoption of ExperimentalWasmJsInterop.

Also applies to: 16-17

karma/chrome_bin.js (1)

17-19: LGTM!

The Chrome headless flags correctly enable fake media device and UI mocking, directly addressing the test blocking issue described in the PR objectives. These flags prevent Chrome from displaying permission dialogs and ensure tests use fake media devices instead of attempting to access real hardware.

ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/PeerConnection.kt (1)

4-4: LGTM!

The opt-in annotation and imports enable experimental Wasm/JS interop features consistently with other WebRTC module files. The toArray() function is now available from kotlin-wrappers, replacing previously internal conversion helpers.

Also applies to: 10-11

ktor-client/ktor-client-webrtc/jsAndWasmShared/test/io/ktor/client/webrtc/MockMediaDevices.kt (1)

1-1: LGTM!

The test file properly adopts the experimental Wasm/JS interop opt-in, maintaining consistency with the production code changes.

Also applies to: 10-10

ktor-client/ktor-client-webrtc/wasmJs/src/io/ktor/client/webrtc/Utils.wasmJs.kt (1)

5-6: LGTM!

The opt-in annotation enables experimental Wasm/JS interop features. The removal of internal conversion helpers (toArray() and toJs()) is appropriate as these are now provided by kotlin-wrappers 2025.10.8, eliminating the need for manual implementations.

ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/MediaDevices.kt (1)

4-4: LGTM!

The opt-in annotation and imports enable experimental Wasm/JS interop features for converting JS iterables to arrays. The toArray() function is now used for extracting audio and video tracks from media streams, replacing internal conversion helpers.

Also applies to: 14-15

ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/Utils.kt (1)

5-6: LGTM!

The opt-in annotation enables experimental Wasm/JS interop features across the shared utilities. The removal of internal conversion helpers (ByteArray ↔ ArrayBuffer, JsArray expect declarations) is appropriate as these are now provided by kotlin-wrappers 2025.10.8, avoiding code duplication.

Also applies to: 19-19

ktor-client/ktor-client-webrtc/jsAndWasmShared/src/io/ktor/client/webrtc/DataChannel.kt (1)

111-113: onerror payload may differ across browsers; add fallback.

RTCDataChannel error events aren’t consistently shaped. Consider a defensive fallback to avoid null messages.

-        channel.onerror = eventHandler(coroutineScope) { e ->
-            eventsEmitter.emitDataChannelEvent(DataChannelEvent.Error(this, e.error.message))
-        }
+        channel.onerror = eventHandler(coroutineScope) { e ->
+            val msg = (e.asDynamic().error?.message ?: e.asDynamic().message ?: "Unknown data channel error") as String
+            eventsEmitter.emitDataChannelEvent(DataChannelEvent.Error(this, msg))
+        }

@zibet27 zibet27 enabled auto-merge (squash) October 21, 2025 07:56
@zibet27 zibet27 merged commit 08c0440 into main Oct 21, 2025
14 of 17 checks passed
@zibet27 zibet27 deleted the zibet27/webrtc-fix-js-tests branch October 21, 2025 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants