From 8fd089ac388f0424e9b92e8af33d7e9da0b18426 Mon Sep 17 00:00:00 2001 From: MaryamShaghaghi <122574719+MaryamShaghaghi@users.noreply.github.com> Date: Wed, 6 Dec 2023 14:59:43 +0100 Subject: [PATCH] Add test for split tunneling view model and update the other tests Co-Authored-By: Boban Sijuk <49131853+Boki91@users.noreply.github.com> --- .../screen/SplitTunnelingScreenTest.kt | 68 ++++++---- .../viewmodel/SplitTunnelingViewModelTest.kt | 119 +++++++++++++----- 2 files changed, 138 insertions(+), 49 deletions(-) diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreenTest.kt index a4f6d1ab4a38..7d814e0fdc12 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreenTest.kt @@ -10,6 +10,7 @@ import io.mockk.unmockkAll import io.mockk.verify import net.mullvad.mullvadvpn.applist.AppData import net.mullvad.mullvadvpn.compose.setContentWithTheme +import net.mullvad.mullvadvpn.compose.state.AppListState import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach @@ -34,7 +35,12 @@ class SplitTunnelingScreenTest { fun testLoadingState() = composeExtension.use { // Arrange - setContentWithTheme { SplitTunnelingScreen(uiState = SplitTunnelingUiState.Loading) } + setContentWithTheme { + SplitTunnelingScreen( + uiState = + SplitTunnelingUiState(enabled = true, appListState = AppListState.Loading) + ) + } // Assert onNodeWithText(TITLE).assertExists() @@ -63,10 +69,14 @@ class SplitTunnelingScreenTest { setContentWithTheme { SplitTunnelingScreen( uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(excludedApp), - includedApps = listOf(includedApp), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = listOf(excludedApp), + includedApps = listOf(includedApp), + showSystemApps = false + ) ) ) } @@ -94,10 +104,14 @@ class SplitTunnelingScreenTest { setContentWithTheme { SplitTunnelingScreen( uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = emptyList(), - includedApps = listOf(includedApp), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = emptyList(), + includedApps = listOf(includedApp), + showSystemApps = false + ) ) ) } @@ -132,10 +146,14 @@ class SplitTunnelingScreenTest { setContentWithTheme { SplitTunnelingScreen( uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(excludedApp), - includedApps = listOf(includedApp), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = listOf(excludedApp), + includedApps = listOf(includedApp), + showSystemApps = false + ) ), onExcludeAppClick = mockedClickHandler ) @@ -168,10 +186,14 @@ class SplitTunnelingScreenTest { setContentWithTheme { SplitTunnelingScreen( uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(excludedApp), - includedApps = listOf(includedApp), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = listOf(excludedApp), + includedApps = listOf(includedApp), + showSystemApps = false + ) ), onIncludeAppClick = mockedClickHandler ) @@ -204,10 +226,14 @@ class SplitTunnelingScreenTest { setContentWithTheme { SplitTunnelingScreen( uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(excludedApp), - includedApps = listOf(includedApp), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = listOf(excludedApp), + includedApps = listOf(includedApp), + showSystemApps = false + ) ), onShowSystemAppsClick = mockedClickHandler ) diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt index 7b2b4cacd5fb..b0ceb7840b72 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt @@ -19,6 +19,7 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import net.mullvad.mullvadvpn.applist.AppData import net.mullvad.mullvadvpn.applist.ApplicationsProvider +import net.mullvad.mullvadvpn.compose.state.AppListState import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer @@ -57,7 +58,7 @@ class SplitTunnelingViewModelTest { initTestSubject(emptyList()) val actualState: SplitTunnelingUiState = testSubject.uiState.value - val initialExpectedState = SplitTunnelingUiState.Loading + val initialExpectedState = SplitTunnelingUiState() assertEquals(initialExpectedState, actualState) @@ -70,12 +71,20 @@ class SplitTunnelingViewModelTest { { lambda<(Set) -> Unit>().invoke(emptySet()) } + every { mockedSplitTunneling.enabledChange = captureLambda() } answers + { + lambda<(Boolean) -> Unit>().invoke(true) + } initTestSubject(emptyList()) val expectedState = - SplitTunnelingUiState.ShowAppList( - excludedApps = emptyList(), - includedApps = emptyList(), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = emptyList(), + includedApps = emptyList(), + showSystemApps = false + ) ) testSubject.uiState.test { assertEquals(expectedState, awaitItem()) } } @@ -88,21 +97,29 @@ class SplitTunnelingViewModelTest { { lambda<(Set) -> Unit>().invoke(setOf(appExcluded.packageName)) } + every { mockedSplitTunneling.enabledChange = captureLambda() } answers + { + lambda<(Boolean) -> Unit>().invoke(true) + } initTestSubject(listOf(appExcluded, appNotExcluded)) val expectedState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(appExcluded), - includedApps = listOf(appNotExcluded), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = listOf(appExcluded), + includedApps = listOf(appNotExcluded), + showSystemApps = false + ) ) testSubject.uiState.test { val actualState = awaitItem() assertEquals(expectedState, actualState) verifyAll { - mockedSplitTunneling.enabled + mockedSplitTunneling.enabledChange = any() mockedSplitTunneling.excludedAppsChange = any() } } @@ -118,20 +135,32 @@ class SplitTunnelingViewModelTest { excludedAppsCallback = lambda() excludedAppsCallback.invoke(setOf(app.packageName)) } + every { mockedSplitTunneling.enabledChange = captureLambda() } answers + { + lambda<(Boolean) -> Unit>().invoke(true) + } initTestSubject(listOf(app)) val expectedStateBeforeAction = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(app), - includedApps = emptyList(), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = listOf(app), + includedApps = emptyList(), + showSystemApps = false + ) ) val expectedStateAfterAction = - SplitTunnelingUiState.ShowAppList( - excludedApps = emptyList(), - includedApps = listOf(app), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = emptyList(), + includedApps = listOf(app), + showSystemApps = false + ) ) testSubject.uiState.test { @@ -141,7 +170,7 @@ class SplitTunnelingViewModelTest { assertEquals(expectedStateAfterAction, awaitItem()) verifyAll { - mockedSplitTunneling.enabled + mockedSplitTunneling.enabledChange = any() mockedSplitTunneling.excludedAppsChange = any() mockedSplitTunneling.includeApp(app.packageName) } @@ -158,21 +187,33 @@ class SplitTunnelingViewModelTest { excludedAppsCallback = lambda() excludedAppsCallback.invoke(emptySet()) } + every { mockedSplitTunneling.enabledChange = captureLambda() } answers + { + lambda<(Boolean) -> Unit>().invoke(true) + } initTestSubject(listOf(app)) val expectedStateBeforeAction = - SplitTunnelingUiState.ShowAppList( - excludedApps = emptyList(), - includedApps = listOf(app), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = emptyList(), + includedApps = listOf(app), + showSystemApps = false + ) ) val expectedStateAfterAction = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(app), - includedApps = emptyList(), - showSystemApps = false + SplitTunnelingUiState( + enabled = true, + appListState = + AppListState.ShowAppList( + excludedApps = listOf(app), + includedApps = emptyList(), + showSystemApps = false + ) ) testSubject.uiState.test { @@ -182,13 +223,35 @@ class SplitTunnelingViewModelTest { assertEquals(expectedStateAfterAction, awaitItem()) verifyAll { - mockedSplitTunneling.enabled + mockedSplitTunneling.enabledChange = any() mockedSplitTunneling.excludedAppsChange = any() mockedSplitTunneling.excludeApp(app.packageName) } } } + @Test + fun test_disabled_state() = runTest { + every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers + { + lambda<(Set) -> Unit>().invoke(emptySet()) + } + every { mockedSplitTunneling.enabledChange = captureLambda() } answers + { + lambda<(Boolean) -> Unit>().invoke(false) + } + + initTestSubject(emptyList()) + + val expectedState = + SplitTunnelingUiState(enabled = false, appListState = AppListState.Disabled) + + testSubject.uiState.test { + val actualState = awaitItem() + assertEquals(expectedState, actualState) + } + } + private fun initTestSubject(appList: List) { every { mockedApplicationsProvider.getAppsList() } returns appList every { mockedServiceConnectionManager.connectionState } returns