diff --git a/source/ui/src/main/java/com/clerk/ui/auth/AuthStartViewModel.kt b/source/ui/src/main/java/com/clerk/ui/auth/AuthStartViewModel.kt index 84a4f1c6b..6f6e914f2 100644 --- a/source/ui/src/main/java/com/clerk/ui/auth/AuthStartViewModel.kt +++ b/source/ui/src/main/java/com/clerk/ui/auth/AuthStartViewModel.kt @@ -8,7 +8,6 @@ import com.clerk.api.credentials.shouldFallbackToOAuthFromGoogleOneTap import com.clerk.api.credentials.shouldSuppressAutomaticCredentialFlowError import com.clerk.api.credentials.shouldSuppressCredentialFlowError import com.clerk.api.log.ClerkLog -import com.clerk.api.network.model.error.ClerkErrorResponse import com.clerk.api.network.serialization.ClerkResult import com.clerk.api.network.serialization.errorMessage import com.clerk.api.network.serialization.onFailure @@ -180,14 +179,13 @@ internal class AuthStartViewModel(private val ioDispatcher: CoroutineDispatcher SignIn.create(SignIn.CreateParams.Strategy.Identifier(identifier = resolvedIdentifier)) .onSuccess { signIn -> handleSignInSuccess(signIn, transferable) } .onFailure { - if (withSignUp && it.error is ClerkErrorResponse) { - val matchingCodes = listOf(FORM_IDENTIFIER_NOT_FOUND, INVITATION_ACCOUNT_NOT_EXISTS) - val hasMatchingError = it.error?.errors?.any { it.code in matchingCodes } ?: false - if (hasMatchingError) { - signUp(isPhoneNumberFieldActive, identifier, phoneNumber, unsafeMetadata) - } else { - _state.value = AuthState.Error(it.errorMessage) - } + val matchingCodes = listOf(FORM_IDENTIFIER_NOT_FOUND, INVITATION_ACCOUNT_NOT_EXISTS) + val shouldSignUp = + withSignUp && it.error?.errors?.any { error -> error.code in matchingCodes } == true + if (shouldSignUp) { + signUp(isPhoneNumberFieldActive, identifier, phoneNumber, unsafeMetadata) + } else { + _state.value = AuthState.Error(it.errorMessage) } } } diff --git a/source/ui/src/test/java/com/clerk/ui/auth/AuthViewModelTest.kt b/source/ui/src/test/java/com/clerk/ui/auth/AuthViewModelTest.kt index 8157e9cfa..564af9619 100644 --- a/source/ui/src/test/java/com/clerk/ui/auth/AuthViewModelTest.kt +++ b/source/ui/src/test/java/com/clerk/ui/auth/AuthViewModelTest.kt @@ -83,6 +83,53 @@ class AuthViewModelTest { } } + @Test + fun startAuthWithSignInModeShouldSurfaceApiFailure() = runTest { + mockkObject(SignIn.Companion) + coEvery { SignIn.create(any()) } returns + ClerkResult.apiFailure( + ClerkErrorResponse(errors = listOf(ClerkError(longMessage = "Couldn't find your account."))) + ) + + viewModel.state.test { + assertEquals(AuthStartViewModel.AuthState.Idle, awaitItem()) + + viewModel.startAuth( + authMode = AuthMode.SignIn, + isPhoneNumberFieldActive = false, + phoneNumber = "", + identifier = "test@example.com", + ) + + assertEquals(AuthStartViewModel.AuthState.Loading, awaitItem()) + assertEquals(AuthStartViewModel.AuthState.Error("Couldn't find your account."), awaitItem()) + } + } + + @Test + fun startAuthWithSignInModeShouldSurfaceUnknownFailure() = runTest { + mockkObject(SignIn.Companion) + coEvery { SignIn.create(any()) } returns + ClerkResult.unknownFailure(IllegalStateException("Network unavailable")) + + viewModel.state.test { + assertEquals(AuthStartViewModel.AuthState.Idle, awaitItem()) + + viewModel.startAuth( + authMode = AuthMode.SignIn, + isPhoneNumberFieldActive = false, + phoneNumber = "", + identifier = "test@example.com", + ) + + assertEquals(AuthStartViewModel.AuthState.Loading, awaitItem()) + assertEquals( + AuthStartViewModel.AuthState.Error("Error occurred with unknown message."), + awaitItem(), + ) + } + } + @Test fun automaticPasskeySignInUsesPasskeyStrategy() = runTest { val signIn = SignIn(id = "sign_in_123")