summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorJonatan Rhodin <jonatan.rhodin@mullvad.net>2023-08-16 08:28:05 +0200
committerJonatan Rhodin <jonatan.rhodin@mullvad.net>2023-09-06 09:07:53 +0200
commit8cfe2faac5a275de7a553ca26bee9e0ea58fd0f8 (patch)
treebfd4aa86d1d40bb0d775bfcb239945621728f9b0 /android
parent7e8158b02b5ba5af654c3d705d29dee1e65b74ef (diff)
downloadmullvadvpn-8cfe2faac5a275de7a553ca26bee9e0ea58fd0f8.tar.xz
mullvadvpn-8cfe2faac5a275de7a553ca26bee9e0ea58fd0f8.zip
Add unit tests for notification state
Diffstat (limited to 'android')
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt153
1 files changed, 128 insertions, 25 deletions
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt
index a621e80ff2..d8ec2b26f7 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt
@@ -2,6 +2,7 @@ package net.mullvad.mullvadvpn.viewmodel
import androidx.lifecycle.viewModelScope
import app.cash.turbine.test
+import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
@@ -9,26 +10,35 @@ import io.mockk.slot
import io.mockk.unmockkAll
import io.mockk.verify
import kotlin.test.assertEquals
+import kotlin.test.assertIs
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
+import net.mullvad.mullvadvpn.compose.state.ConnectNotificationState
import net.mullvad.mullvadvpn.compose.state.ConnectUiState
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
+import net.mullvad.mullvadvpn.model.AccountExpiry
import net.mullvad.mullvadvpn.model.GeoIpLocation
import net.mullvad.mullvadvpn.model.TunnelState
import net.mullvad.mullvadvpn.relaylist.RelayCountry
import net.mullvad.mullvadvpn.relaylist.RelayItem
+import net.mullvad.mullvadvpn.repository.AccountRepository
import net.mullvad.mullvadvpn.ui.VersionInfo
import net.mullvad.mullvadvpn.ui.serviceconnection.AppVersionInfoCache
+import net.mullvad.mullvadvpn.ui.serviceconnection.AuthTokenCache
import net.mullvad.mullvadvpn.ui.serviceconnection.ConnectionProxy
import net.mullvad.mullvadvpn.ui.serviceconnection.LocationInfoCache
import net.mullvad.mullvadvpn.ui.serviceconnection.RelayListListener
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
+import net.mullvad.mullvadvpn.ui.serviceconnection.authTokenCache
import net.mullvad.mullvadvpn.ui.serviceconnection.connectionProxy
import net.mullvad.mullvadvpn.util.appVersionCallbackFlow
+import net.mullvad.talpid.tunnel.ErrorState
import net.mullvad.talpid.util.EventNotifier
+import org.joda.time.DateTime
+import org.joda.time.ReadableInstant
import org.junit.After
import org.junit.Before
import org.junit.Rule
@@ -48,9 +58,10 @@ class ConnectViewModelTest {
currentVersion = null,
upgradeVersion = null,
isOutdated = false,
- isSupported = false
+ isSupported = true
)
)
+ private val accountExpiryState = MutableStateFlow<AccountExpiry>(AccountExpiry.Missing)
// Service connections
private val mockServiceConnectionContainer: ServiceConnectionContainer = mockk()
@@ -60,6 +71,9 @@ class ConnectViewModelTest {
private val mockConnectionProxy: ConnectionProxy = mockk()
private val mockLocation: GeoIpLocation = mockk(relaxed = true)
+ // Account Repository
+ private val mockAccountRepository: AccountRepository = mockk()
+
// Captures
private val locationSlot = slot<((GeoIpLocation?) -> Unit)>()
private val relaySlot = slot<(List<RelayCountry>, RelayItem?) -> Unit>()
@@ -84,6 +98,8 @@ class ConnectViewModelTest {
every { mockServiceConnectionContainer.appVersionInfoCache } returns mockAppVersionInfoCache
every { mockServiceConnectionContainer.connectionProxy } returns mockConnectionProxy
+ every { mockAccountRepository.accountExpiryState } returns accountExpiryState
+
every { mockConnectionProxy.onUiStateChange } returns eventNotifierTunnelUiState
every { mockConnectionProxy.onStateChange } returns eventNotifierTunnelRealState
@@ -94,7 +110,12 @@ class ConnectViewModelTest {
every { mockRelayListListener.onRelayCountriesChange = capture(relaySlot) } answers {}
every { mockAppVersionInfoCache.onUpdate = any() } answers {}
- viewModel = ConnectViewModel(mockServiceConnectionManager)
+ viewModel =
+ ConnectViewModel(
+ serviceConnectionManager = mockServiceConnectionManager,
+ accountRepository = mockAccountRepository,
+ isVersionInfoNotificationEnabled = true
+ )
}
@After
@@ -160,29 +181,6 @@ class ConnectViewModelTest {
}
@Test
- fun testAppVersionInfoUpdate() =
- runTest(testCoroutineRule.testDispatcher) {
- val versionInfoTestItem =
- VersionInfo(
- currentVersion = "1.0",
- upgradeVersion = "2.0",
- isOutdated = false,
- isSupported = false
- )
-
- viewModel.uiState.test {
- assertEquals(ConnectUiState.INITIAL, awaitItem())
- serviceConnectionState.value =
- ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
- locationSlot.captured.invoke(mockLocation)
- relaySlot.captured.invoke(mockk(), mockk())
- versionInfo.value = versionInfoTestItem
- val result = awaitItem()
- assertEquals(versionInfoTestItem, result.versionInfo)
- }
- }
-
- @Test
fun testRelayItemUpdate() =
runTest(testCoroutineRule.testDispatcher) {
val relayTestItem =
@@ -258,6 +256,111 @@ class ConnectViewModelTest {
verify { mockConnectionProxy.disconnect() }
}
+ @Test
+ fun testBlockingNotificationState() =
+ runTest(testCoroutineRule.testDispatcher) {
+ // Arrange
+ val expectedConnectNotificationState =
+ ConnectNotificationState.ShowTunnelStateNotificationBlocked
+ val tunnelUiState = TunnelState.Connecting(null, null)
+
+ // Act, Assert
+ viewModel.uiState.test {
+ assertEquals(ConnectUiState.INITIAL, awaitItem())
+ serviceConnectionState.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ locationSlot.captured.invoke(mockLocation)
+ relaySlot.captured.invoke(mockk(), mockk())
+ eventNotifierTunnelUiState.notify(tunnelUiState)
+ val result = awaitItem()
+ assertEquals(expectedConnectNotificationState, result.connectNotificationState)
+ }
+ }
+
+ @Test
+ fun testErrorNotificationState() =
+ runTest(testCoroutineRule.testDispatcher) {
+ // Arrange
+ val mockErrorState: ErrorState = mockk()
+ val expectedConnectNotificationState =
+ ConnectNotificationState.ShowTunnelStateNotificationError(mockErrorState)
+ val tunnelUiState = TunnelState.Error(mockErrorState)
+
+ // Act, Assert
+ viewModel.uiState.test {
+ assertEquals(ConnectUiState.INITIAL, awaitItem())
+ serviceConnectionState.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ locationSlot.captured.invoke(mockLocation)
+ relaySlot.captured.invoke(mockk(), mockk())
+ eventNotifierTunnelUiState.notify(tunnelUiState)
+ val result = awaitItem()
+ assertEquals(expectedConnectNotificationState, result.connectNotificationState)
+ }
+ }
+
+ @Test
+ fun testVersionInfoNotificationState() =
+ runTest(testCoroutineRule.testDispatcher) {
+ // Arrange
+ val mockVersionInfo: VersionInfo = mockk()
+ val expectedConnectNotificationState =
+ ConnectNotificationState.ShowVersionInfoNotification(mockVersionInfo)
+ every { mockVersionInfo.isOutdated } returns true
+
+ // Act, Assert
+ viewModel.uiState.test {
+ assertEquals(ConnectUiState.INITIAL, awaitItem())
+ serviceConnectionState.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ locationSlot.captured.invoke(mockLocation)
+ relaySlot.captured.invoke(mockk(), mockk())
+ versionInfo.value = mockVersionInfo
+ val result = awaitItem()
+ assertEquals(expectedConnectNotificationState, result.connectNotificationState)
+ }
+ }
+
+ @Test
+ fun testAccountExpiryNotificationState() =
+ runTest(testCoroutineRule.testDispatcher) {
+ // Arrange
+ val mockDateTime: DateTime = mockk()
+ val expectedConnectNotificationState =
+ ConnectNotificationState.ShowAccountExpiryNotification(mockDateTime)
+ every { mockDateTime.isBefore(any<ReadableInstant>()) } returns true
+
+ // Act, Assert
+ viewModel.uiState.test {
+ assertEquals(ConnectUiState.INITIAL, awaitItem())
+ serviceConnectionState.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ locationSlot.captured.invoke(mockLocation)
+ relaySlot.captured.invoke(mockk(), mockk())
+ accountExpiryState.value = AccountExpiry.Available(mockDateTime)
+ val result = awaitItem()
+ assertEquals(expectedConnectNotificationState, result.connectNotificationState)
+ }
+ }
+
+ @Test
+ fun testOnShowAccountClick() =
+ runTest(testCoroutineRule.testDispatcher) {
+ // Arrange
+ val mockToken = "4444 5555 6666 7777"
+ val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true)
+ every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache
+ coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken
+
+ // Act, Assert
+ viewModel.viewActions.test {
+ viewModel.onManageAccountClick()
+ val action = awaitItem()
+ assertIs<ConnectViewModel.ViewAction.OpenAccountManagementPageInBrowser>(action)
+ assertEquals(mockToken, action.token)
+ }
+ }
+
companion object {
private const val CACHE_EXTENSION_CLASS = "net.mullvad.mullvadvpn.util.CacheExtensionsKt"
private const val SERVICE_CONNECTION_MANAGER_EXTENSIONS =