Skip to content

Commit 7680d8b

Browse files
authored
fix(authenticator): Fix emission of NetworkErrorMessage (#152)
1 parent d8d4779 commit 7680d8b

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

authenticator/src/main/java/com/amplifyframework/ui/authenticator/AuthenticatorViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ import com.amplifyframework.ui.authenticator.util.PasswordResetMessage
7676
import com.amplifyframework.ui.authenticator.util.RealAuthProvider
7777
import com.amplifyframework.ui.authenticator.util.UnableToResetPasswordMessage
7878
import com.amplifyframework.ui.authenticator.util.UnknownErrorMessage
79+
import com.amplifyframework.ui.authenticator.util.isConnectivityIssue
7980
import com.amplifyframework.ui.authenticator.util.toFieldError
80-
import java.net.UnknownHostException
8181
import kotlinx.coroutines.channels.BufferOverflow
8282
import kotlinx.coroutines.flow.MutableSharedFlow
8383
import kotlinx.coroutines.flow.MutableStateFlow
@@ -554,7 +554,7 @@ internal class AuthenticatorViewModel(
554554
is CodeExpiredException -> sendMessage(ExpiredCodeMessage(error))
555555
is CodeValidationException -> sendMessage(UnknownErrorMessage(error))
556556
is UnknownException -> {
557-
if (error.cause is UnknownHostException) {
557+
if (error.isConnectivityIssue()) {
558558
sendMessage(NetworkErrorMessage(error))
559559
} else {
560560
sendMessage(UnknownErrorMessage(error))

authenticator/src/main/java/com/amplifyframework/ui/authenticator/util/Exceptions.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.amplifyframework.ui.authenticator.util
1717

1818
import com.amplifyframework.auth.AuthException
19+
import java.net.UnknownHostException
1920

2021
/**
2122
* Exception that is passed to the errorContent if the application does not have the auth plugin
@@ -36,3 +37,13 @@ class InvalidConfigurationException(message: String, cause: Exception?) : AuthEx
3637
recoverySuggestion = "Check that the configuration passed to Amplify.configure has all required fields",
3738
cause = cause
3839
)
40+
41+
internal fun Throwable.isConnectivityIssue(): Boolean {
42+
if (this is UnknownHostException) {
43+
return true
44+
}
45+
return when (val cause = this.cause) {
46+
null -> false
47+
else -> cause.isConnectivityIssue()
48+
}
49+
}

authenticator/src/test/java/com/amplifyframework/ui/authenticator/AuthenticatorMatchers.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
package com.amplifyframework.ui.authenticator
1717

18+
import app.cash.turbine.test
1819
import com.amplifyframework.ui.authenticator.util.AuthenticatorMessage
1920
import io.kotest.matchers.Matcher
2021
import io.kotest.matchers.MatcherResult
@@ -45,3 +46,12 @@ fun AuthenticatorMessage?.shouldBeError(
4546
causeMessage?.let { casted should haveMessage(it) }
4647
recoverySuggestion?.let { casted should haveRecoverySuggestion(it) }
4748
}
49+
50+
internal suspend inline fun <reified T : AuthenticatorMessage> AuthenticatorViewModel.shouldEmitMessage(
51+
crossinline block: suspend () -> Unit
52+
) {
53+
events.test {
54+
block()
55+
awaitItem().shouldBeInstanceOf<T>()
56+
}
57+
}

authenticator/src/test/java/com/amplifyframework/ui/authenticator/AuthenticatorViewModelTest.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,27 @@
1616
package com.amplifyframework.ui.authenticator
1717

1818
import android.app.Application
19+
import aws.smithy.kotlin.runtime.http.HttpException
1920
import com.amplifyframework.auth.AuthUserAttributeKey.email
2021
import com.amplifyframework.auth.AuthUserAttributeKey.emailVerified
2122
import com.amplifyframework.auth.MFAType
23+
import com.amplifyframework.auth.exceptions.UnknownException
2224
import com.amplifyframework.auth.result.step.AuthSignInStep
2325
import com.amplifyframework.ui.authenticator.auth.VerificationMechanism
2426
import com.amplifyframework.ui.authenticator.enums.AuthenticatorStep
2527
import com.amplifyframework.ui.authenticator.util.AmplifyResult
28+
import com.amplifyframework.ui.authenticator.util.AmplifyResult.Error
2629
import com.amplifyframework.ui.authenticator.util.AmplifyResult.Success
2730
import com.amplifyframework.ui.authenticator.util.AuthConfigurationResult
2831
import com.amplifyframework.ui.authenticator.util.AuthProvider
32+
import com.amplifyframework.ui.authenticator.util.NetworkErrorMessage
2933
import com.amplifyframework.ui.testing.CoroutineTestRule
3034
import io.kotest.matchers.shouldBe
3135
import io.mockk.coEvery
3236
import io.mockk.coVerify
37+
import io.mockk.every
3338
import io.mockk.mockk
39+
import java.net.UnknownHostException
3440
import kotlinx.coroutines.ExperimentalCoroutinesApi
3541
import kotlinx.coroutines.test.advanceUntilIdle
3642
import kotlinx.coroutines.test.runTest
@@ -323,6 +329,29 @@ class AuthenticatorViewModelTest {
323329
viewModel.currentStep shouldBe AuthenticatorStep.SignedIn
324330
}
325331

332+
@Test
333+
fun `signing in with no internet results in network error message`() = runTest {
334+
coEvery { authProvider.fetchAuthSession() } returns Success(mockAuthSession(isSignedIn = false))
335+
coEvery { authProvider.signIn(any(), any()) } returns
336+
Error(
337+
mockk<UnknownException> {
338+
every { cause } returns
339+
mockk<HttpException> {
340+
every { cause } returns mockk<UnknownHostException>()
341+
}
342+
}
343+
)
344+
345+
viewModel.start(mockAuthenticatorConfiguration())
346+
347+
viewModel.shouldEmitMessage<NetworkErrorMessage> {
348+
viewModel.signIn("username", "password")
349+
}
350+
351+
// Assert step does not change
352+
viewModel.currentStep shouldBe AuthenticatorStep.SignIn
353+
}
354+
326355
//endregion
327356
//region helpers
328357
private val AuthenticatorViewModel.currentStep: AuthenticatorStep

0 commit comments

Comments
 (0)