diff options
| author | David Göransson <david.goransson@mullvad.net> | 2024-03-19 15:05:26 +0100 |
|---|---|---|
| committer | David Göransson <david.goransson@mullvad.net> | 2024-03-19 16:15:43 +0100 |
| commit | 25c885541ca7638d1d3936e822820ce2bf717edc (patch) | |
| tree | 937b7d80a6dc237d7de062bd9b31426369e35d2b | |
| parent | 2b31f2863ffb574db9f9cdd4578d7fa59e577022 (diff) | |
| download | mullvadvpn-25c885541ca7638d1d3936e822820ce2bf717edc.tar.xz mullvadvpn-25c885541ca7638d1d3936e822820ce2bf717edc.zip | |
Add Server IP overrides ViewModel tests
2 files changed, 181 insertions, 0 deletions
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ResetServerIpOverridesConfirmationViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ResetServerIpOverridesConfirmationViewModelTest.kt new file mode 100644 index 0000000000..9be365e7ae --- /dev/null +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ResetServerIpOverridesConfirmationViewModelTest.kt @@ -0,0 +1,63 @@ +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.unmockkAll +import io.mockk.verify +import kotlin.test.assertEquals +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runTest +import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule +import net.mullvad.mullvadvpn.model.RelayOverride +import net.mullvad.mullvadvpn.repository.RelayOverridesRepository +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestCoroutineRule::class) +class ResetServerIpOverridesConfirmationViewModelTest { + private lateinit var viewModel: ResetServerIpOverridesConfirmationViewModel + + private val mockRelayOverridesRepository: RelayOverridesRepository = mockk() + private val relayOverrides = MutableStateFlow<List<RelayOverride>?>(null) + + @BeforeEach + fun setup() { + coEvery { mockRelayOverridesRepository.relayOverrides } returns relayOverrides + + viewModel = + ResetServerIpOverridesConfirmationViewModel( + relayOverridesRepository = mockRelayOverridesRepository, + ) + } + + @AfterEach + fun teardown() { + viewModel.viewModelScope.coroutineContext.cancel() + unmockkAll() + } + + @Test + fun `successful clear of override should result in side effect`() = runTest { + every { mockRelayOverridesRepository.clearAllOverrides() } returns Unit + viewModel.uiSideEffect.test { + viewModel.clearAllOverrides() + assertEquals( + ResetServerIpOverridesConfirmationUiSideEffect.OverridesCleared, + awaitItem() + ) + } + } + + @Test + fun `clear overrides should invoke repository`() = runTest { + every { mockRelayOverridesRepository.clearAllOverrides() } returns Unit + viewModel.clearAllOverrides() + verify { mockRelayOverridesRepository.clearAllOverrides() } + } +} diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ServerIpOverridesViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ServerIpOverridesViewModelTest.kt new file mode 100644 index 0000000000..16e89ac20b --- /dev/null +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ServerIpOverridesViewModelTest.kt @@ -0,0 +1,118 @@ +package net.mullvad.mullvadvpn.viewmodel + +import android.content.ContentResolver +import android.net.Uri +import androidx.lifecycle.viewModelScope +import app.cash.turbine.test +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.unmockkAll +import java.io.InputStream +import java.io.InputStreamReader +import kotlin.test.assertEquals +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runTest +import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule +import net.mullvad.mullvadvpn.lib.ipc.Event +import net.mullvad.mullvadvpn.model.RelayOverride +import net.mullvad.mullvadvpn.model.SettingsPatchError +import net.mullvad.mullvadvpn.repository.RelayOverridesRepository +import net.mullvad.mullvadvpn.repository.SettingsRepository +import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager +import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestCoroutineRule::class) +class ServerIpOverridesViewModelTest { + private lateinit var viewModel: ServerIpOverridesViewModel + + private val mockServiceConnectionManager: ServiceConnectionManager = mockk() + private val mockRelayOverridesRepository: RelayOverridesRepository = mockk() + private val mockSettingsRepository: SettingsRepository = mockk(relaxed = true) + private val mockContentResolver: ContentResolver = mockk() + + private val relayOverrides = MutableStateFlow<List<RelayOverride>?>(null) + private val serviceConnectionState = + MutableStateFlow<ServiceConnectionState>(ServiceConnectionState.ConnectedReady(mockk())) + + @BeforeEach + fun setup() { + coEvery { mockRelayOverridesRepository.relayOverrides } returns relayOverrides + coEvery { mockServiceConnectionManager.connectionState } returns serviceConnectionState + + mockkStatic(READ_TEXT) + + viewModel = + ServerIpOverridesViewModel( + serviceConnectionManager = mockServiceConnectionManager, + relayOverridesRepository = mockRelayOverridesRepository, + settingsRepository = mockSettingsRepository, + contentResolver = mockContentResolver + ) + } + + @AfterEach + fun teardown() { + viewModel.viewModelScope.coroutineContext.cancel() + unmockkAll() + } + + @Test + fun `ensure state is loading by default`() = runTest { + viewModel.uiState.test { assertEquals(ServerIpOverridesViewState.Loading, awaitItem()) } + } + + @Test + fun `when server ip overrides are empty ui state overrides should be inactive`() = runTest { + viewModel.uiState.test { + assertEquals(ServerIpOverridesViewState.Loading, awaitItem()) + relayOverrides.emit(emptyList()) + assertEquals(ServerIpOverridesViewState.Loaded(false), awaitItem()) + } + } + + @Test + fun `when import is finished we should get side effect`() = runTest { + val mockkResult: SettingsPatchError = mockk() + coEvery { mockSettingsRepository.applySettingsPatch(TEXT_INPUT) } returns + Event.ApplyJsonSettingsResult(mockkResult) + + viewModel.uiSideEffect.test { + viewModel.importText(TEXT_INPUT) + assertEquals(ServerIpOverridesUiSideEffect.ImportResult(mockkResult), awaitItem()) + } + } + + @Test + fun `ensure import text invokes repository`() = runTest { + viewModel.importText(TEXT_INPUT) + + coVerify { mockSettingsRepository.applySettingsPatch(TEXT_INPUT) } + } + + @Test + fun `ensure import file invokes repository`() = runTest { + val uri: Uri = mockk() + + val mockInputStream: InputStream = mockk() + every { mockContentResolver.openInputStream(uri) } returns mockInputStream + every { any<InputStreamReader>().readText() } returns TEXT_INPUT + + viewModel.importFile(uri) + + coVerify { mockSettingsRepository.applySettingsPatch(TEXT_INPUT) } + } + + companion object { + private const val TEXT_INPUT = "My cool json patch" + + private const val READ_TEXT = "kotlin.io.TextStreamsKt" + } +} |
