Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
2e50889
Upgrade to `m145` webrtc and noise-cancellation lib `v3.0.0` (#1678)
PratimMallick May 26, 2026
4fc3437
[skip ci] Update SDK sizes
github-actions[bot] May 26, 2026
d395d7a
AUTOMATION: Version Bump
github-actions[bot] May 26, 2026
29acfef
Honor SFU-provided degradation preference for adaptive video publishi…
PratimMallick Jun 1, 2026
645b9e6
fix(core): initialize Call.events before CallState to avoid NPE in so…
aleksandar-apostolov Jun 1, 2026
367a793
AUTOMATION: Version Bump
github-actions[bot] Jun 1, 2026
07fc1e7
[skip ci] Update SDK sizes
github-actions[bot] Jun 1, 2026
386bd77
Merge remote-tracking branch 'origin/release-develop-v1.25.0' into de…
github-actions[bot] Jun 1, 2026
7ce2a23
Add ability to add custom user in demo-app (#1700)
rahul-lohra Jun 3, 2026
7b1a318
fix(core): send only the changed track in UpdateMuteStates (#1706)
PratimMallick Jun 4, 2026
21e159c
fix(core): clear stored push device even when deleteDevice API fails …
aleksandar-apostolov Jun 4, 2026
310f96b
[skip ci] Update SDK sizes
github-actions[bot] Jun 4, 2026
e5213f5
fix(core): make apiCall wait for guestUserJob to avoid anonymous push…
aleksandar-apostolov Jun 8, 2026
5339bad
[skip ci] Update SDK sizes
github-actions[bot] Jun 8, 2026
8e53765
Adopt createGuest's server-issued identity for guest users (#1704)
aleksandar-apostolov Jun 8, 2026
88c88a4
[skip ci] Update SDK sizes
github-actions[bot] Jun 8, 2026
dede308
Introduce UserRepository as single source of truth for SDK user (#1708)
aleksandar-apostolov Jun 8, 2026
9a8da36
Include internal audio switch to fix concurrency issue (#1710)
rahul-lohra Jun 9, 2026
ab730e8
chore(core): deprecate StreamVideo.logOut (#1709)
aleksandar-apostolov Jun 9, 2026
56770cd
fix(core): prevent DevicePreferences ClassCastException in updateDevi…
PratimMallick Jun 9, 2026
295666d
AUTOMATION: Version Bump
github-actions[bot] Jun 9, 2026
c4b8e32
fix(core): stop coordinator events from clobbering SFU participant co…
aleksandar-apostolov Jun 10, 2026
aac5778
Prevent "MediaSource has been disposed" crash when leaving a call (#1…
PratimMallick Jun 11, 2026
82f80e9
[skip ci] Update SDK sizes
github-actions[bot] Jun 11, 2026
f35ef0a
Revert audio switch local AAR (#1710) and reset version to allow re-r…
aleksandar-apostolov Jun 11, 2026
e8e731f
AUTOMATION: Version Bump
github-actions[bot] Jun 11, 2026
9ef821f
fix(core): set small icon on setting-up-call notification (#1720)
PratimMallick Jun 12, 2026
6eb1e59
Update open api generated models in Video SDK(1/4) (#1713)
rahul-lohra Jun 12, 2026
380b1b7
Fix self cancelling coroutine code (2/4) (#1714)
rahul-lohra Jun 12, 2026
1fb3603
Send standardized call leave reason instead of string when leaving th…
rahul-lohra Jun 12, 2026
168c664
[skip ci] Update SDK sizes
github-actions[bot] Jun 12, 2026
2016186
Add Video Analytics in call-join flow (#1716)
rahul-lohra Jun 12, 2026
8b11db4
AUTOMATION: Version Bump
github-actions[bot] Jun 12, 2026
cbb3ed0
[skip ci] Update SDK sizes
github-actions[bot] Jun 12, 2026
2349888
Merge remote-tracking branch 'origin/release-develop-v1.27.0' into de…
github-actions[bot] Jun 12, 2026
c5bcc10
Do not show error message while video is loading (#1721)
PratimMallick Jun 16, 2026
6ed3bcd
feat(ui-compose): add participantLabelContent slot to CallLobby (#1726)
aleksandar-apostolov Jun 19, 2026
eda6cc9
[skip ci] Update SDK sizes
github-actions[bot] Jun 19, 2026
0a52f05
Chore(deps): Bump actions/checkout from 6 to 7 (#1728)
dependabot[bot] Jun 19, 2026
a7ecf80
Move @Preview composables out of published artifact to fix R8 builds …
PratimMallick Jun 22, 2026
14f61cf
[skip ci] Update SDK sizes
github-actions[bot] Jun 22, 2026
d0e1456
Fix `runCallServiceInForeground` handling for incoming PN and non-rin…
rahul-lohra Jun 23, 2026
6c062f4
Improve video analytics by correctly sending ice state (#1724)
rahul-lohra Jun 23, 2026
4b776c6
Code refactor for Video Analytics (#1727)
rahul-lohra Jun 23, 2026
b6460a0
Fix a crash when application put to background restriction (#1731)
rahul-lohra Jun 23, 2026
245c08d
[skip ci] Update SDK sizes
github-actions[bot] Jun 23, 2026
a60b820
Fix notification dismissal for Leave/Hang Up notification actions (#1…
rahul-lohra Jun 23, 2026
8754b29
feat(ui-compose): add videoPreviewModifier slot to CallLobby (#1733)
aleksandar-apostolov Jun 23, 2026
6035a0d
AUTOMATION: Version Bump
github-actions[bot] Jun 23, 2026
205daee
fix: fix tracer timestamp and remove additional lock (#1734)
rahul-lohra Jul 6, 2026
b11959b
Report SFU WebSocket connection and join timeouts accurately (#1740)
PratimMallick Jul 6, 2026
374d8c1
[skip ci] Update SDK sizes
github-actions[bot] Jul 6, 2026
5e3547d
CI: add least-privilege permissions to GitHub Actions workflows (#1742)
peter-matkovski Jul 9, 2026
1d8b702
e2e: Port the chat test harness improvements: retry visibility, video…
andremion Jul 13, 2026
96bc4bc
Recover initial join when connect safety-timeout leaves no reconnect …
PratimMallick Jul 13, 2026
be52131
AUTOMATION: Version Bump
github-actions[bot] Jul 14, 2026
8fbaea4
test(e2e): harden recording and outgoing-call waits against backend l…
PratimMallick Jul 23, 2026
0600b65
chore: pass OpenAPI generator config via --opt flags (#1743)
gpunto Jul 28, 2026
53976d2
Chore(deps): Bump actions/checkout from 7.0.0 to 7.0.1 (#1748)
dependabot[bot] Jul 30, 2026
8a55912
fix(core): stop orphaned publisher transceivers to prevent SFU rejoin…
PratimMallick Aug 3, 2026
5dfc2e5
Decompose Call into focused internal components (#1747)
PratimMallick Aug 5, 2026
28d379d
[skip ci] Update SDK sizes
github-actions[bot] Aug 5, 2026
ac82e4e
Make the Android Video SDK compatible with Android 17. (#1752)
rahul-lohra Aug 5, 2026
b1ba57b
AUTOMATION: Version Bump
github-actions[bot] Aug 5, 2026
d82741c
[Fix] Keep Float in generated models (#1766)
gpunto Aug 12, 2026
47c2c34
Chore(deps): Bump the stream-conventions group with 6 updates (#1769)
dependabot[bot] Aug 17, 2026
f8b5ea5
Fix peer connection previous-connect analytics scope (#1763)
rahul-lohra Aug 18, 2026
0a3a20c
Always announce video layers on SetPublisher (#1765)
PratimMallick Aug 18, 2026
2aec2e1
Update build conventions to 0.14.0 (#1767)
gpunto Aug 20, 2026
b4c8d8b
Signal noise cancellation state to the SFU (#1770)
aleksandar-apostolov Aug 21, 2026
d192195
[skip ci] Update SDK sizes
github-actions[bot] Aug 21, 2026
e137d7b
Noise cancellation state no longer leaks between calls or misreports …
aleksandar-apostolov Aug 21, 2026
93b5cbf
[skip ci] Update SDK sizes
github-actions[bot] Aug 21, 2026
ff290bd
Enforce the noise-cancellation capability and call settings in core (…
aleksandar-apostolov Aug 21, 2026
280a09d
Remove CHANGELOG.md and all references to it (#1779)
andremion Aug 24, 2026
25868bd
Add Join Analytics docs in video sdk (#1780)
rahul-lohra Aug 25, 2026
9068a2c
AUTOMATION: Version Bump
github-actions[bot] Aug 26, 2026
a465dbb
Stabilize the flaky E2E emulator tests (#1782)
andremion Aug 27, 2026
5e75fed
Fix the flaky MockK Context setup in PictureInPictureTest (#1781)
andremion Aug 27, 2026
24da669
Snapshot test baseline for the Compose Video SDK (#1776)
andremion Aug 27, 2026
774a326
[skip ci] Update SDK sizes
github-actions[bot] Aug 27, 2026
f1bfd12
Introduce VideoComponentFactory as the component override mechanism (…
andremion Aug 28, 2026
53af1bd
[skip ci] Update SDK sizes
github-actions[bot] Aug 28, 2026
ff9ae01
Route the remaining internal render paths through VideoComponentFacto…
andremion Aug 28, 2026
b530e34
Harden the racy signal assertions in NoiseCancellationSignalTest (#1791)
andremion Aug 31, 2026
c9acc94
Wait for the SDK re-initialization before joining a call after re-log…
andremion Aug 31, 2026
622f5ed
Null-check the stop intent before stopService in cleanup (#1794)
andremion Aug 31, 2026
2d417c8
Single-flight Call.join to stop concurrent-join race (#1764)
PratimMallick Sep 1, 2026
d784943
[skip ci] Update SDK sizes
github-actions[bot] Sep 1, 2026
03b2b0a
Avoid leaking pending broadcast in GenericCallActionBroadcastReceiver…
rahul-lohra Sep 1, 2026
354ed25
AUTOMATION: Version Bump
github-actions[bot] Sep 1, 2026
f16134d
Recover the connection state when a peer connection stays NEW after a…
andremion Sep 2, 2026
0233a92
Fix the outgoing ringing state stuck on Connecting in join-and-ring (…
andremion Sep 2, 2026
01799d5
Outgoing ring timeout no longer restarts on every call state update (…
aleksandar-apostolov Sep 3, 2026
083e929
add more users (#1806)
rahul-lohra Sep 4, 2026
4294af4
End-to-end encryption for call media (#1801)
PratimMallick Sep 8, 2026
93baaa7
[skip ci] Update SDK sizes
github-actions[bot] Sep 8, 2026
9b1b41d
Avoid fetching FCM token during logout in demo-app (#1797)
rahul-lohra Sep 8, 2026
9646f50
Add e2e tests for join and ring (#1799)
rahul-lohra Sep 9, 2026
4c72d16
Send the SDK name and version as X-Stream-Client on SFU requests (#1818)
aleksandar-apostolov Sep 9, 2026
eb894cf
Demo app: join encrypted from a scanned encryption_key link (#1820)
aleksandar-apostolov Sep 9, 2026
693f242
fix(compose): request Bluetooth permission for audio-only calls (#1811)
rahul-lohra Sep 10, 2026
d653ec2
Pin coordinator join to a specific SFU via sfu_id (#1819)
PratimMallick Sep 10, 2026
947a4bd
Pin the video buddy to 1.8.1 and widen the flaky E2E waits (#1822)
andremion Sep 11, 2026
bb56dbf
chore: record the develop history already merged by #1790
andremion Sep 11, 2026
44e4bf7
chore: merge develop into develop-v2
andremion Sep 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

<div align="center">

![stream-video-android-core](https://img.shields.io/badge/stream--video--android--core-12.30%20MB-lightgreen)
![stream-video-android-ui-xml](https://img.shields.io/badge/stream--video--android--ui--xml-5.69%20MB-lightgreen)
![stream-video-android-core](https://img.shields.io/badge/stream--video--android--core-12.36%20MB-lightgreen)
![stream-video-android-ui-xml](https://img.shields.io/badge/stream--video--android--ui--xml-5.67%20MB-lightgreen)
![stream-video-android-ui-compose](https://img.shields.io/badge/stream--video--android--ui--compose-6.23%20MB-lightgreen)

</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class DirectCallPage {

companion object {
val participantName = By.res("Stream_DirectCallUserName")
val joinAndRingCheckbox = By.res("Stream_JoinAndRingCheckbox")
val audioCallButton = By.res("Stream_AudioCallButton")
val videoCallButton = By.res("Stream_VideoCallButton")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,14 @@ class UserRobot {
return this
}

fun directCall(audioOnly: Boolean): UserRobot {
fun directCall(audioOnly: Boolean, joinAndRing: Boolean = false): UserRobot {
CallDetailsPage.wheelIcon.waitToAppearAndClick()
CallDetailsPage.directCallButton.waitToAppearAndClick()
DirectCallPage.joinAndRingCheckbox.waitToAppear().let { checkbox ->
if (checkbox.isChecked != joinAndRing) {
checkbox.click()
}
}
DirectCallPage.participantName.waitToAppearAndClick()
val callButton = if (audioOnly) audioCallButton else videoCallButton
callButton.waitToAppearAndClick()
Expand All @@ -103,7 +108,10 @@ class UserRobot {
if (callId != null) {
CallDetailsPage.callIdInputField.waitToAppear().typeText(callId)
}
CallDetailsPage.joinCallButton.waitToAppearAndClick()
// The call details screen is the first screen after launch or login, so this wait
// overlaps app startup on an emulator that is still settling. The 5s default was the
// single most common nightly failure, so the window is deliberately wider.
CallDetailsPage.joinCallButton.waitToAppearAndClick(timeOutMillis = 15.seconds)
waitForLobbyToOpen()
return this
}
Expand All @@ -122,7 +130,9 @@ class UserRobot {
}

private fun waitForLobbyToOpen(): UserRobot {
LobbyPage.closeButton.waitToAppear()
// Reached right after a login, so the lobby composes while the app is still starting
// up. At the 5s default this failed about half the time locally on the re-enter tests.
LobbyPage.closeButton.waitToAppear(timeOutMillis = 15.seconds)
return this
}

Expand Down Expand Up @@ -150,7 +160,9 @@ class UserRobot {
}

fun waitForIncomingCall(): UserRobot {
RingPage.acceptCallButton.waitToAppear(timeOutMillis = 15.seconds)
// Ring delivery goes through the coordinator and the push or socket path before the
// incoming screen renders, and 15s timed out on the nightlies.
RingPage.acceptCallButton.waitToAppear(timeOutMillis = 30.seconds)
return this
}

Expand Down Expand Up @@ -337,7 +349,8 @@ class UserRobot {
CallPage.callViewButton.waitToAppearAndClick()
// With many live video tiles the emulator UI is busy, and the opened menu can take
// several seconds to land in the accessibility tree, so the items get a wide window.
val timeOutMillis = 15.seconds
// 15s still timed out on the six-participant test, so the window is wider again.
val timeOutMillis = 30.seconds
when (mode) {
VideoView.DYNAMIC -> CallPage.ViewMenu.dynamic.waitToAppearAndClick(timeOutMillis)
VideoView.SPOTLIGHT -> CallPage.ViewMenu.spotlight.waitToAppearAndClick(timeOutMillis)
Expand All @@ -353,15 +366,18 @@ class UserRobot {

fun acceptCallRecording(): UserRobot {
// The recording-consent dialog only appears once the backend composite recorder
// emits call.recording_started, which can take 20-30s, so 10s is too short.
CallPage.RecordingButtons.accept.waitToAppearAndClick(timeOutMillis = 30.seconds)
// emits call.recording_started. The buddy starts the recording within seconds, so
// this wait is really the recorder's start-up latency: usually 10-20s, but 30s still
// timed out four times in the nightlies. Callers with a recording window have to
// outlive this wait, see testReconnectionDuringCallRecording.
CallPage.RecordingButtons.accept.waitToAppearAndClick(timeOutMillis = 60.seconds)
return this
}

fun declineCallRecording(): UserRobot {
// See acceptCallRecording: the consent dialog is gated on the backend recorder
// starting (call.recording_started), which can take 20-30s.
CallPage.RecordingButtons.leave.waitToAppearAndClick(timeOutMillis = 30.seconds)
// starting (call.recording_started).
CallPage.RecordingButtons.leave.waitToAppearAndClick(timeOutMillis = 60.seconds)
return this
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import io.getstream.video.android.uiautomator.findObjects
import io.getstream.video.android.uiautomator.isDisplayed
import io.getstream.video.android.uiautomator.retryOnStaleObjectException
import io.getstream.video.android.uiautomator.seconds
import io.getstream.video.android.uiautomator.wait
import io.getstream.video.android.uiautomator.waitDisplayed
import io.getstream.video.android.uiautomator.waitForCount
import io.getstream.video.android.uiautomator.waitForText
Expand Down Expand Up @@ -130,8 +131,10 @@ fun UserRobot.assertBackground(background: Background, isEnabled: Boolean): User
Background.IMAGE -> SettingsMenu.imageBackgroundEnabledToggle
Background.BLUR -> SettingsMenu.blurBackgroundEnabledToggle
}
val expectedCount = if (isEnabled) 1 else 0
assertEquals(expectedCount, locator.findObjects().size)
// The menu items land in the accessibility tree a moment after the sheet opens, so an
// instant count right after settings(ENABLE) can read 0 for a toggle that is there.
val toggles = if (isEnabled) locator.wait().findObjects() else locator.waitToDisappear().findObjects()
assertEquals(if (isEnabled) 1 else 0, toggles.size)
return this
}

Expand Down Expand Up @@ -270,7 +273,12 @@ fun UserRobot.assertSpotlightView(): UserRobot {

fun UserRobot.assertIncomingCall(isDisplayed: Boolean): UserRobot {
if (isDisplayed) {
assertTrue("Accept call button", RingPage.acceptCallButton.waitToAppear().isDisplayed())
// Often the first wait after the participant rings, so it carries the whole ring
// delivery latency. Same budget as waitForIncomingCall.
assertTrue(
"Accept call button",
RingPage.acceptCallButton.waitToAppear(timeOutMillis = 30.seconds).isDisplayed(),
)
assertTrue("Decline call button", RingPage.declineCallButton.isDisplayed())
assertTrue("Call label", RingPage.incomingCallLabel.isDisplayed())
assertTrue("Avatar", RingPage.callParticipantAvatar.isDisplayed())
Expand All @@ -292,12 +300,20 @@ fun UserRobot.assertOutgoingCall(audioOnly: Boolean = true, isDisplayed: Boolean
// muted state right after the screen renders), so poll instead of instant asserts.
assertTrue("Call label", RingPage.outgoingCallLabel.waitDisplayed())
assertTrue("Avatar", RingPage.callParticipantAvatar.waitDisplayed())
assertTrue("Microphone", RingPage.microphoneEnabledToggle.waitDisplayed())
assertTrue(
"Microphone",
RingPage.microphoneEnabledToggle.waitDisplayed() ||
RingPage.microphoneDisabledToggle.waitDisplayed(),
)
if (audioOnly) {
assertFalse("Camera enabled toggle", RingPage.cameraEnabledToggle.isDisplayed())
assertFalse("Camera disabled toggle", RingPage.cameraDisabledToggle.isDisplayed())
} else {
assertTrue("Camera", RingPage.cameraEnabledToggle.waitDisplayed())
assertTrue(
"Camera",
RingPage.cameraEnabledToggle.waitDisplayed() ||
RingPage.cameraDisabledToggle.waitDisplayed(),
)
}
} else {
assertFalse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,14 @@ class ReconnectionTests : StreamTestCase() {
}
step("AND participant joins the call") {
// The recording window counts from the participant's start request, and the
// composite recorder alone can take 20-30s to start. The window has to outlive
// the drop, the reconnect and the final polling assert on a slow CI emulator,
// otherwise the participant stops the recording on schedule before the assert
// and the test fails on a recording that legitimately ended.
// composite recorder alone can take up to the 60s acceptCallRecording waits for.
// The window has to outlive that, the drop, the reconnect and the final polling
// assert on a slow CI emulator, otherwise the participant stops the recording on
// schedule before the assert and the test fails on a recording that
// legitimately ended.
participantRobot
.setUserCount(participants)
.setCallRecordingDuration(90)
.setCallRecordingDuration(120)
.joinCall(callId, actions = arrayOf(Actions.RECORD_CALL))
}
step("AND participant starts recording a call") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

package io.getstream.video.android.tests

import io.getstream.video.android.core.Call
import io.getstream.video.android.core.RealtimeConnection
import io.getstream.video.android.core.RingingState
import io.getstream.video.android.core.StreamVideo
import io.getstream.video.android.robots.UserControls.DISABLE
import io.getstream.video.android.robots.assertAudioCallControls
import io.getstream.video.android.robots.assertConnectingView
Expand All @@ -24,12 +28,114 @@ import io.getstream.video.android.robots.assertOutgoingCall
import io.getstream.video.android.robots.assertOutgoingCallNotification
import io.getstream.video.android.robots.assertThatCallIsEnded
import io.getstream.video.android.robots.assertVideoCallControls
import io.getstream.video.android.uiautomator.seconds
import io.qameta.allure.kotlin.Allure.step
import io.qameta.allure.kotlin.AllureId
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.withTimeoutOrNull
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Test

class RingingTests : StreamTestCase() {

@Test
fun testJoinAndRingRemainsOutgoingAfterFastReconnectBeforeCalleeAccepts() {
startUnansweredJoinAndRingCall()

step("WHEN the caller completes a fast reconnect before the callee accepts") {
reconnectOutgoingCall(expectSessionReplacement = false) {
fastReconnect("E2E: outgoing join-and-ring")
}
}
step("THEN the outgoing call screen is still displayed") {
userRobot.assertOutgoingCall(audioOnly = false, isDisplayed = true)
}

userRobot.declineOutgoingCall()
}

@Test
fun testJoinAndRingRemainsOutgoingAfterRejoinBeforeCalleeAccepts() {
startUnansweredJoinAndRingCall()

step("WHEN the caller completes a rejoin before the callee accepts") {
reconnectOutgoingCall(expectSessionReplacement = true) {
rejoin("E2E: outgoing join-and-ring")
}
}
step("THEN the outgoing call screen is still displayed") {
userRobot.assertOutgoingCall(audioOnly = false, isDisplayed = true)
}

userRobot.declineOutgoingCall()
}

private fun startUnansweredJoinAndRingCall() {
step("GIVEN the caller joins first and rings a callee who has not accepted") {
// Do not start the participant robot: the selected callee remains unanswered.
userRobot
.logout()
.loginAsRandomUser()
.directCall(audioOnly = false, joinAndRing = true)
.assertOutgoingCall(audioOnly = false, isDisplayed = true)
}
}

private fun reconnectOutgoingCall(
expectSessionReplacement: Boolean,
reconnect: suspend Call.() -> Unit,
) {
val call = requireNotNull(StreamVideo.instance().state.ringingCall.value) {
"Expected the join-and-ring call to be registered as the ringing call"
}
assertTrue(call.state.ringingState.value is RingingState.Outgoing)
assertEquals(RealtimeConnection.Connected, call.state.connection.value)
val sessionIdBeforeReconnect = call.sessionId

runBlocking {
// Subscribe before triggering the reconnect so a fast Reconnecting transition
// cannot be missed by a polling assertion.
val enteredReconnecting = async(start = CoroutineStart.UNDISPATCHED) {
call.state.connection.first { it is RealtimeConnection.Reconnecting }
}
val reconnectCompleted = async {
reconnect(call)
}

val reconnectingState = withTimeoutOrNull(30.seconds) {
enteredReconnecting.await()
}
assertNotNull(
"Expected the connection to enter Reconnecting within 30 seconds, " +
"but its current state is ${call.state.connection.value}",
reconnectingState,
)
withTimeout(60.seconds) { reconnectCompleted.await() }
val connectedState = withTimeoutOrNull(30.seconds) {
call.state.connection.first { it is RealtimeConnection.Connected }
}
assertNotNull(
"Expected the connection to recover to Connected within 30 seconds, " +
"but its current state is ${call.state.connection.value}",
connectedState,
)
}

if (expectSessionReplacement) {
assertNotEquals(sessionIdBeforeReconnect, call.sessionId)
} else {
assertEquals(sessionIdBeforeReconnect, call.sessionId)
}
assertTrue(call.state.ringingState.value is RingingState.Outgoing)
}

@AllureId("7774")
@Test
fun testParticipantRejectsTheOutgoingCall() {
Expand Down
Loading
Loading