summaryrefslogtreecommitdiffhomepage
path: root/android/app
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2022-05-03 16:37:20 +0200
committerAlbin <albin@mullvad.net>2022-05-17 15:06:04 +0200
commitd2b3deb89ba20cb0af6e82cad85e718624bb20df (patch)
treeda3bbe450396253b66029640c7c4f5126d8bddc2 /android/app
parentf00ad159a30c12c778e1602d277425f9e196d2ff (diff)
downloadmullvadvpn-d2b3deb89ba20cb0af6e82cad85e718624bb20df.tar.xz
mullvadvpn-d2b3deb89ba20cb0af6e82cad85e718624bb20df.zip
Fix login vm unit tests
Diffstat (limited to 'android/app')
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModel.kt7
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt136
2 files changed, 38 insertions, 105 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModel.kt
index 4ec72c529d..cb4f151fd1 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModel.kt
@@ -84,9 +84,10 @@ class LoginViewModel(
}
private fun AccountCreationResult.mapToUiState(): LoginUiState {
- return when (this) {
- is AccountCreationResult.Success -> LoginUiState.AccountCreated
- AccountCreationResult.Failure -> LoginUiState.UnableToCreateAccountError
+ return if (this is AccountCreationResult.Success) {
+ LoginUiState.AccountCreated
+ } else {
+ LoginUiState.UnableToCreateAccountError
}
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt
index 174c378e23..6147a77a1d 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt
@@ -3,20 +3,21 @@ package net.mullvad.mullvadvpn.viewmodel
import app.cash.turbine.FlowTurbine
import app.cash.turbine.test
import io.mockk.MockKAnnotations
-import io.mockk.Runs
import io.mockk.every
import io.mockk.impl.annotations.MockK
-import io.mockk.invoke
-import io.mockk.just
import io.mockk.mockk
-import io.mockk.slot
import io.mockk.verify
import junit.framework.Assert.assertEquals
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.setMain
+import net.mullvad.mullvadvpn.ipc.Event
+import net.mullvad.mullvadvpn.model.AccountCreationResult
+import net.mullvad.mullvadvpn.model.AccountHistory
import net.mullvad.mullvadvpn.model.LoginResult
-import net.mullvad.mullvadvpn.model.LoginStatus
import net.mullvad.mullvadvpn.ui.serviceconnection.AccountCache
-import net.mullvad.talpid.util.EventNotifier
import org.junit.Before
import org.junit.Test
@@ -25,37 +26,20 @@ class LoginViewModelTest {
@MockK
private lateinit var mockedAccountCache: AccountCache
- @MockK
- private lateinit var mockedLoginStatusNotifier: EventNotifier<LoginStatus?>
-
- @MockK
- private lateinit var mockedAccountHistoryNotifier: EventNotifier<String?>
-
private lateinit var loginViewModel: LoginViewModel
- private val capturedLoginStatusNotifierCallback = slot<(LoginStatus?) -> Unit>()
- private val capturedAccountHistoryNotifierCallback = slot<(String?) -> Unit>()
+
+ private val accountCreationTestEvents = MutableSharedFlow<AccountCreationResult>()
+ private val accountHistoryTestEvents = MutableSharedFlow<AccountHistory>()
+ private val loginTestEvents = MutableSharedFlow<Event.LoginEvent>()
@Before
fun setup() {
+ Dispatchers.setMain(TestCoroutineDispatcher())
MockKAnnotations.init(this, relaxUnitFun = true)
- every {
- mockedLoginStatusNotifier.subscribe(
- any(),
- any(),
- capture(capturedLoginStatusNotifierCallback)
- )
- } just Runs
-
- every {
- mockedAccountHistoryNotifier.subscribe(
- any(),
- capture(capturedAccountHistoryNotifierCallback)
- )
- } just Runs
-
- every { mockedAccountCache.onLoginStatusChange } returns mockedLoginStatusNotifier
- every { mockedAccountCache.onAccountHistoryChange } returns mockedAccountHistoryNotifier
+ every { mockedAccountCache.accountCreationEvents } returns accountCreationTestEvents
+ every { mockedAccountCache.accountHistoryEvents } returns accountHistoryTestEvents
+ every { mockedAccountCache.loginEvents } returns loginTestEvents
loginViewModel = LoginViewModel(mockk())
}
@@ -69,23 +53,13 @@ class LoginViewModelTest {
}
@Test
- fun testClearingViewModel() {
- loginViewModel.updateAccountCacheInstance(mockedAccountCache)
- loginViewModel.onCleared()
- verify {
- mockedLoginStatusNotifier.unsubscribe(any())
- mockedAccountHistoryNotifier.unsubscribe(any())
- }
- }
-
- @Test
fun testCreateAccount() = runBlockingTest {
loginViewModel.updateAccountCacheInstance(mockedAccountCache)
loginViewModel.uiState.test {
skipDefaultItem()
loginViewModel.createAccount()
assertEquals(LoginViewModel.LoginUiState.CreatingAccount, awaitItem())
- capturedLoginStatusNotifierCallback.captured.invoke(DummyLoginStatus.ACCOUNT_CREATED)
+ accountCreationTestEvents.emit(AccountCreationResult.Success(DUMMY_ACCOUNT_TOKEN))
assertEquals(LoginViewModel.LoginUiState.AccountCreated, awaitItem())
}
}
@@ -95,9 +69,9 @@ class LoginViewModelTest {
loginViewModel.updateAccountCacheInstance(mockedAccountCache)
loginViewModel.uiState.test {
skipDefaultItem()
- loginViewModel.login("")
+ loginViewModel.login(DUMMY_ACCOUNT_TOKEN)
assertEquals(LoginViewModel.LoginUiState.Loading, awaitItem())
- capturedLoginStatusNotifierCallback.captured.invoke(DummyLoginStatus.SUCCESSFUL_LOGIN)
+ loginTestEvents.emit(Event.LoginEvent(LoginResult.Ok))
assertEquals(LoginViewModel.LoginUiState.Success(isOutOfTime = false), awaitItem())
}
}
@@ -107,11 +81,9 @@ class LoginViewModelTest {
loginViewModel.updateAccountCacheInstance(mockedAccountCache)
loginViewModel.uiState.test {
skipDefaultItem()
- loginViewModel.login("")
+ loginViewModel.login(DUMMY_ACCOUNT_TOKEN)
assertEquals(LoginViewModel.LoginUiState.Loading, awaitItem())
- capturedLoginStatusNotifierCallback.captured.invoke(
- DummyLoginStatus.INVALID_ACCOUNT_ERROR
- )
+ loginTestEvents.emit(Event.LoginEvent(LoginResult.InvalidAccount))
assertEquals(LoginViewModel.LoginUiState.InvalidAccountError, awaitItem())
}
}
@@ -121,9 +93,9 @@ class LoginViewModelTest {
loginViewModel.updateAccountCacheInstance(mockedAccountCache)
loginViewModel.uiState.test {
skipDefaultItem()
- loginViewModel.login("")
+ loginViewModel.login(DUMMY_ACCOUNT_TOKEN)
assertEquals(LoginViewModel.LoginUiState.Loading, awaitItem())
- capturedLoginStatusNotifierCallback.captured.invoke(DummyLoginStatus.MAX_DEVICES_ERROR)
+ loginTestEvents.emit(Event.LoginEvent(LoginResult.MaxDevicesReached))
assertEquals(LoginViewModel.LoginUiState.TooManyDevicesError, awaitItem())
}
}
@@ -133,10 +105,10 @@ class LoginViewModelTest {
loginViewModel.updateAccountCacheInstance(mockedAccountCache)
loginViewModel.uiState.test {
skipDefaultItem()
- loginViewModel.login("")
+ loginViewModel.login(DUMMY_ACCOUNT_TOKEN)
assertEquals(LoginViewModel.LoginUiState.Loading, awaitItem())
- capturedLoginStatusNotifierCallback.captured.invoke(DummyLoginStatus.RPC_ERROR)
- assertEquals(LoginViewModel.LoginUiState.OtherError("RpcError"), awaitItem())
+ loginTestEvents.emit(Event.LoginEvent(LoginResult.RpcError))
+ assertEquals(LoginViewModel.LoginUiState.OtherError(EXPECTED_RPC_ERROR_MESSAGE), awaitItem())
}
}
@@ -145,10 +117,10 @@ class LoginViewModelTest {
loginViewModel.updateAccountCacheInstance(mockedAccountCache)
loginViewModel.uiState.test {
skipDefaultItem()
- loginViewModel.login("")
+ loginViewModel.login(DUMMY_ACCOUNT_TOKEN)
assertEquals(LoginViewModel.LoginUiState.Loading, awaitItem())
- capturedLoginStatusNotifierCallback.captured.invoke(DummyLoginStatus.OTHER_ERROR)
- assertEquals(LoginViewModel.LoginUiState.OtherError("OtherError"), awaitItem())
+ loginTestEvents.emit(Event.LoginEvent(LoginResult.OtherError))
+ assertEquals(LoginViewModel.LoginUiState.OtherError(EXPECTED_OTHER_ERROR_MESSAGE), awaitItem())
}
}
@@ -156,8 +128,10 @@ class LoginViewModelTest {
fun testAccountHistory() = runBlockingTest {
loginViewModel.updateAccountCacheInstance(mockedAccountCache)
loginViewModel.accountHistory.test { skipDefaultItem() }
- capturedAccountHistoryNotifierCallback.invoke(DUMMY_ACCOUNT_TOKEN)
- loginViewModel.accountHistory.test { assertEquals(DUMMY_ACCOUNT_TOKEN, awaitItem()) }
+ accountHistoryTestEvents.emit(AccountHistory.Available(DUMMY_ACCOUNT_TOKEN))
+ loginViewModel.accountHistory.test {
+ assertEquals(AccountHistory.Available(DUMMY_ACCOUNT_TOKEN), awaitItem())
+ }
}
@Test
@@ -173,49 +147,7 @@ class LoginViewModelTest {
companion object {
private const val DUMMY_ACCOUNT_TOKEN = "DUMMY"
-
- private object DummyLoginStatus {
- val ACCOUNT_CREATED = LoginStatus(
- DUMMY_ACCOUNT_TOKEN,
- mockk(),
- isNewAccount = true,
- mockk()
- )
-
- val SUCCESSFUL_LOGIN = LoginStatus(
- DUMMY_ACCOUNT_TOKEN,
- mockk(),
- isNewAccount = false,
- LoginResult.Ok
- )
-
- val INVALID_ACCOUNT_ERROR = LoginStatus(
- DUMMY_ACCOUNT_TOKEN,
- mockk(),
- isNewAccount = false,
- LoginResult.InvalidAccount
- )
-
- val MAX_DEVICES_ERROR = LoginStatus(
- DUMMY_ACCOUNT_TOKEN,
- mockk(),
- isNewAccount = false,
- LoginResult.MaxDevicesReached
- )
-
- val RPC_ERROR = LoginStatus(
- DUMMY_ACCOUNT_TOKEN,
- mockk(),
- isNewAccount = false,
- LoginResult.RpcError
- )
-
- val OTHER_ERROR = LoginStatus(
- DUMMY_ACCOUNT_TOKEN,
- mockk(),
- isNewAccount = false,
- LoginResult.OtherError
- )
- }
+ private const val EXPECTED_RPC_ERROR_MESSAGE = "RpcError"
+ private const val EXPECTED_OTHER_ERROR_MESSAGE = "OtherError"
}
}