Fix tests
This commit is contained in:
@@ -17,7 +17,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
@@ -39,7 +38,6 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.sync.SyncState
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||
import io.element.android.libraries.network.useragent.UserAgentProvider
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.services.analytics.api.ScreenTracker
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -80,10 +78,10 @@ class CallScreenPresenter @AssistedInject constructor(
|
||||
val callWidgetDriver = remember { mutableStateOf<MatrixWidgetDriver?>(null) }
|
||||
val messageInterceptor = remember { mutableStateOf<WidgetMessageInterceptor?>(null) }
|
||||
var isJoinedCall by rememberSaveable { mutableStateOf(false) }
|
||||
var canRenderWebViewInCaseOfError by rememberSaveable { mutableStateOf(false) }
|
||||
var ignoreWebViewError by rememberSaveable { mutableStateOf(false) }
|
||||
var webViewError by remember { mutableStateOf<String?>(null) }
|
||||
val languageTag = languageTagProvider.provideLanguageTag()
|
||||
val theme = if (ElementTheme.isLightTheme) "light" else "dark"
|
||||
val errorMessage = stringResource(id = CommonStrings.error_unknown)
|
||||
DisposableEffect(Unit) {
|
||||
coroutineScope.launch {
|
||||
// Sets the call as joined
|
||||
@@ -130,7 +128,7 @@ class CallScreenPresenter @AssistedInject constructor(
|
||||
interceptor.interceptedMessages
|
||||
.onEach {
|
||||
// We are receiving messages from the WebView, consider that the application is loaded
|
||||
canRenderWebViewInCaseOfError = true
|
||||
ignoreWebViewError = true
|
||||
// Relay message to Widget Driver
|
||||
callWidgetDriver.value?.send(it)
|
||||
|
||||
@@ -170,15 +168,8 @@ class CallScreenPresenter @AssistedInject constructor(
|
||||
messageInterceptor.value = event.widgetMessageInterceptor
|
||||
}
|
||||
is CallScreenEvents.OnWebViewError -> {
|
||||
if (!canRenderWebViewInCaseOfError) {
|
||||
urlState.value = AsyncData.Failure(
|
||||
Exception(
|
||||
buildString {
|
||||
append(errorMessage)
|
||||
event.description?.let { append("\n\n").append(it) }
|
||||
}
|
||||
)
|
||||
)
|
||||
if (!ignoreWebViewError) {
|
||||
webViewError = event.description.orEmpty()
|
||||
}
|
||||
// Else ignore the error, give a chance the Element Call to recover by itself.
|
||||
}
|
||||
@@ -187,7 +178,7 @@ class CallScreenPresenter @AssistedInject constructor(
|
||||
|
||||
return CallScreenState(
|
||||
urlState = urlState.value,
|
||||
canRenderWebViewInCaseOfError = canRenderWebViewInCaseOfError,
|
||||
webViewError = webViewError,
|
||||
userAgent = userAgent,
|
||||
isInWidgetMode = isInWidgetMode,
|
||||
eventSink = { handleEvents(it) },
|
||||
|
||||
@@ -11,7 +11,7 @@ import io.element.android.libraries.architecture.AsyncData
|
||||
|
||||
data class CallScreenState(
|
||||
val urlState: AsyncData<String>,
|
||||
val canRenderWebViewInCaseOfError: Boolean,
|
||||
val webViewError: String?,
|
||||
val userAgent: String,
|
||||
val isInWidgetMode: Boolean,
|
||||
val eventSink: (CallScreenEvents) -> Unit,
|
||||
|
||||
@@ -16,19 +16,20 @@ open class CallScreenStateProvider : PreviewParameterProvider<CallScreenState> {
|
||||
aCallScreenState(),
|
||||
aCallScreenState(urlState = AsyncData.Loading()),
|
||||
aCallScreenState(urlState = AsyncData.Failure(Exception("An error occurred"))),
|
||||
aCallScreenState(webViewError = "Error details from WebView"),
|
||||
)
|
||||
}
|
||||
|
||||
internal fun aCallScreenState(
|
||||
urlState: AsyncData<String> = AsyncData.Success("https://call.element.io/some-actual-call?with=parameters"),
|
||||
canRenderWebViewInCaseOfError: Boolean = true,
|
||||
webViewError: String? = null,
|
||||
userAgent: String = "",
|
||||
isInWidgetMode: Boolean = false,
|
||||
eventSink: (CallScreenEvents) -> Unit = {},
|
||||
): CallScreenState {
|
||||
return CallScreenState(
|
||||
urlState = urlState,
|
||||
canRenderWebViewInCaseOfError = canRenderWebViewInCaseOfError,
|
||||
webViewError = webViewError,
|
||||
userAgent = userAgent,
|
||||
isInWidgetMode = isInWidgetMode,
|
||||
eventSink = eventSink,
|
||||
|
||||
@@ -85,7 +85,15 @@ internal fun CallScreenView(
|
||||
BackHandler {
|
||||
handleBack()
|
||||
}
|
||||
if (state.urlState !is AsyncData.Failure || state.canRenderWebViewInCaseOfError) {
|
||||
if (state.webViewError != null) {
|
||||
ErrorDialog(
|
||||
content = buildString {
|
||||
append(stringResource(CommonStrings.error_unknown))
|
||||
state.webViewError.takeIf { it.isNotEmpty() }?.let { append("\n\n").append(it) }
|
||||
},
|
||||
onSubmit = { state.eventSink(CallScreenEvents.Hangup) },
|
||||
)
|
||||
} else {
|
||||
CallWebView(
|
||||
modifier = Modifier
|
||||
.padding(padding)
|
||||
@@ -108,17 +116,17 @@ internal fun CallScreenView(
|
||||
pipState.eventSink(PictureInPictureEvents.SetPipController(pipController))
|
||||
}
|
||||
)
|
||||
}
|
||||
when (state.urlState) {
|
||||
AsyncData.Uninitialized,
|
||||
is AsyncData.Loading ->
|
||||
ProgressDialog(text = stringResource(id = CommonStrings.common_please_wait))
|
||||
is AsyncData.Failure ->
|
||||
ErrorDialog(
|
||||
content = state.urlState.error.message.orEmpty(),
|
||||
onSubmit = { state.eventSink(CallScreenEvents.Hangup) },
|
||||
)
|
||||
is AsyncData.Success -> Unit
|
||||
when (state.urlState) {
|
||||
AsyncData.Uninitialized,
|
||||
is AsyncData.Loading ->
|
||||
ProgressDialog(text = stringResource(id = CommonStrings.common_please_wait))
|
||||
is AsyncData.Failure ->
|
||||
ErrorDialog(
|
||||
content = state.urlState.error.message.orEmpty(),
|
||||
onSubmit = { state.eventSink(CallScreenEvents.Hangup) },
|
||||
)
|
||||
is AsyncData.Success -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ class CallScreenPresenterTest {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.urlState).isEqualTo(AsyncData.Success("https://call.element.io"))
|
||||
assertThat(initialState.webViewError).isNull()
|
||||
assertThat(initialState.isInWidgetMode).isFalse()
|
||||
analyticsLambda.assertions().isNeverCalled()
|
||||
joinedCallLambda.assertions().isCalledOnce()
|
||||
@@ -270,6 +271,48 @@ class CallScreenPresenterTest {
|
||||
assert(stopSyncLambda).isCalledOnce()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - error from WebView are updating the state`() = runTest {
|
||||
val presenter = createCallScreenPresenter(
|
||||
callType = CallType.ExternalUrl("https://call.element.io"),
|
||||
activeCallManager = FakeActiveCallManager(),
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
// Wait until the URL is loaded
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink(CallScreenEvents.OnWebViewError("A Webview error"))
|
||||
val finalState = awaitItem()
|
||||
assertThat(finalState.webViewError).isEqualTo("A Webview error")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - error from WebView are ignored if Element Call is loaded`() = runTest {
|
||||
val presenter = createCallScreenPresenter(
|
||||
callType = CallType.ExternalUrl("https://call.element.io"),
|
||||
activeCallManager = FakeActiveCallManager(),
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
// Wait until the URL is loaded
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
|
||||
val messageInterceptor = FakeWidgetMessageInterceptor()
|
||||
initialState.eventSink(CallScreenEvents.SetupMessageChannels(messageInterceptor))
|
||||
// Emit a message
|
||||
messageInterceptor.givenInterceptedMessage("A message")
|
||||
// WebView emits an error, but it will be ignored
|
||||
initialState.eventSink(CallScreenEvents.OnWebViewError("A Webview error"))
|
||||
val finalState = awaitItem()
|
||||
assertThat(finalState.webViewError).isNull()
|
||||
}
|
||||
}
|
||||
|
||||
private fun TestScope.createCallScreenPresenter(
|
||||
callType: CallType,
|
||||
navigator: CallScreenNavigator = FakeCallScreenNavigator(),
|
||||
|
||||
Reference in New Issue
Block a user