mirror of
https://github.com/bitwarden/android.git
synced 2026-10-23 03:23:53 -05:00
BIT-808: Conditionally show log in with device on login (#681)
This commit is contained in:
1 parent
2fa7851b42
commit
6cbfff254c
14 files changed
+265
-14
No files matched your search
+33
@@ -0,0 +1,33 @@
|
||||
package com.x8bit.bitwarden.data.auth.datasource.network.service
|
||||
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.api.DevicesApi
|
||||
import com.x8bit.bitwarden.data.platform.base.BaseServiceTest
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import okhttp3.mockwebserver.MockResponse
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import retrofit2.create
|
||||
|
||||
class DevicesServiceTest : BaseServiceTest() {
|
||||
|
||||
private val devicesApi: DevicesApi = retrofit.create()
|
||||
private val service = DevicesServiceImpl(
|
||||
devicesApi = devicesApi,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `getIsKnownDevice when request response is Failure should return Failure`() = runTest {
|
||||
val response = MockResponse().setResponseCode(400)
|
||||
server.enqueue(response)
|
||||
val actual = service.getIsKnownDevice("email", "id")
|
||||
assertTrue(actual.isFailure)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getIsKnownDevice when request response is Success should return Success`() = runTest {
|
||||
val response = MockResponse().setBody("false").setResponseCode(200)
|
||||
server.enqueue(response)
|
||||
val actual = service.getIsKnownDevice("email", "id")
|
||||
assertTrue(actual.isSuccess)
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.RefreshTokenRespon
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterRequestJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterResponseJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.service.AccountsService
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.service.DevicesService
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.service.HaveIBeenPwnedService
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.service.IdentityService
|
||||
import com.x8bit.bitwarden.data.auth.datasource.sdk.AuthSdkSource
|
||||
@@ -28,6 +29,7 @@ import com.x8bit.bitwarden.data.auth.manager.UserLogoutManager
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.AuthState
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.DeleteAccountResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.KnownDeviceResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.LoginResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.PasswordStrengthResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.RegisterResult
|
||||
@@ -76,6 +78,7 @@ class AuthRepositoryTest {
|
||||
|
||||
private val dispatcherManager: DispatcherManager = FakeDispatcherManager()
|
||||
private val accountsService: AccountsService = mockk()
|
||||
private val devicesService: DevicesService = mockk()
|
||||
private val identityService: IdentityService = mockk()
|
||||
private val haveIBeenPwnedService: HaveIBeenPwnedService = mockk()
|
||||
private val mutableVaultStateFlow = MutableStateFlow(VAULT_STATE)
|
||||
@@ -127,6 +130,7 @@ class AuthRepositoryTest {
|
||||
|
||||
private val repository = AuthRepositoryImpl(
|
||||
accountsService = accountsService,
|
||||
devicesService = devicesService,
|
||||
identityService = identityService,
|
||||
haveIBeenPwnedService = haveIBeenPwnedService,
|
||||
authSdkSource = authSdkSource,
|
||||
@@ -1173,6 +1177,35 @@ class AuthRepositoryTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getIsKnownDevice should return failure when service returns failure`() = runTest {
|
||||
coEvery {
|
||||
devicesService.getIsKnownDevice(EMAIL, UNIQUE_APP_ID)
|
||||
} returns Throwable("Fail").asFailure()
|
||||
|
||||
val result = repository.getIsKnownDevice(EMAIL)
|
||||
|
||||
coVerify(exactly = 1) {
|
||||
devicesService.getIsKnownDevice(EMAIL, UNIQUE_APP_ID)
|
||||
}
|
||||
assertEquals(KnownDeviceResult.Error, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getIsKnownDevice should return success when service returns success`() = runTest {
|
||||
val isKnownDevice = true
|
||||
coEvery {
|
||||
devicesService.getIsKnownDevice(EMAIL, UNIQUE_APP_ID)
|
||||
} returns isKnownDevice.asSuccess()
|
||||
|
||||
val result = repository.getIsKnownDevice(EMAIL)
|
||||
|
||||
coVerify(exactly = 1) {
|
||||
devicesService.getIsKnownDevice(EMAIL, UNIQUE_APP_ID)
|
||||
}
|
||||
assertEquals(KnownDeviceResult.Success(isKnownDevice), result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPasswordBreachCount should return failure when service returns failure`() = runTest {
|
||||
val password = "password"
|
||||
|
||||
@@ -203,6 +203,17 @@ class LoginScreenTest : BaseComposeTest() {
|
||||
composeTestRule.assertNoDialogExists()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `log in with device button visibility should update according to state`() {
|
||||
val buttonText = "Log in with device"
|
||||
composeTestRule.onNodeWithText(buttonText).assertDoesNotExist()
|
||||
|
||||
mutableStateFlow.update {
|
||||
it.copy(shouldShowLoginWithDevice = true)
|
||||
}
|
||||
composeTestRule.onNodeWithText(buttonText).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `close button click should send CloseButtonClick action`() {
|
||||
composeTestRule.onNodeWithContentDescription("Close").performClick()
|
||||
@@ -302,4 +313,5 @@ private val DEFAULT_STATE =
|
||||
loadingDialogState = LoadingDialogState.Hidden,
|
||||
errorDialogState = BasicDialogState.Hidden,
|
||||
accountSummaries = emptyList(),
|
||||
shouldShowLoginWithDevice = false,
|
||||
)
|
||||
@@ -6,6 +6,7 @@ import app.cash.turbine.test
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.KnownDeviceResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.LoginResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
import com.x8bit.bitwarden.data.auth.repository.util.CaptchaCallbackTokenResult
|
||||
@@ -45,6 +46,9 @@ class LoginViewModelTest : BaseViewModelTest() {
|
||||
bufferedMutableSharedFlow<CaptchaCallbackTokenResult>()
|
||||
private val mutableUserStateFlow = MutableStateFlow<UserState?>(null)
|
||||
private val authRepository: AuthRepository = mockk(relaxed = true) {
|
||||
coEvery {
|
||||
getIsKnownDevice("test@gmail.com")
|
||||
} returns KnownDeviceResult.Success(false)
|
||||
every { captchaTokenResultFlow } returns mutableCaptchaTokenResultFlow
|
||||
every { userStateFlow } returns mutableUserStateFlow
|
||||
every { logout(any()) } just runs
|
||||
@@ -150,6 +154,33 @@ class LoginViewModelTest : BaseViewModelTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should set shouldShowLoginWithDevice when isKnownDevice returns true`() = runTest {
|
||||
val expectedState = DEFAULT_STATE.copy(
|
||||
shouldShowLoginWithDevice = true,
|
||||
)
|
||||
coEvery {
|
||||
authRepository.getIsKnownDevice("test@gmail.com")
|
||||
} returns KnownDeviceResult.Success(true)
|
||||
val viewModel = createViewModel()
|
||||
|
||||
viewModel.stateFlow.test {
|
||||
assertEquals(expectedState, awaitItem())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should have default state when isKnownDevice returns error`() = runTest {
|
||||
coEvery {
|
||||
authRepository.getIsKnownDevice("test@gmail.com")
|
||||
} returns KnownDeviceResult.Error
|
||||
val viewModel = createViewModel()
|
||||
|
||||
viewModel.stateFlow.test {
|
||||
assertEquals(DEFAULT_STATE, awaitItem())
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `on AddAccountClick should send NavigateBack`() = runTest {
|
||||
@@ -434,6 +465,7 @@ class LoginViewModelTest : BaseViewModelTest() {
|
||||
errorDialogState = BasicDialogState.Hidden,
|
||||
captchaToken = null,
|
||||
accountSummaries = emptyList(),
|
||||
shouldShowLoginWithDevice = false,
|
||||
)
|
||||
|
||||
private const val LOGIN_RESULT_PATH =
|
||||
|
||||
Reference in new issue
Block a user