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 7f4ee36d47bc..f9e47646a996 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 @@ -12,6 +12,7 @@ import io.mockk.verify import net.mullvad.mullvadvpn.applist.AppData import net.mullvad.mullvadvpn.applist.ApplicationsIconManager import net.mullvad.mullvadvpn.compose.setContentWithTheme +import net.mullvad.mullvadvpn.compose.state.AppListState import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState import org.junit.After import org.junit.Before @@ -49,7 +50,7 @@ class SplitTunnelingScreenTest { fun testLoadingState() { // Arrange composeTestRule.setContentWithTheme { - SplitTunnelingScreen(uiState = SplitTunnelingUiState.Loading) + SplitTunnelingScreen(uiState = SplitTunnelingUiState()) } // Assert @@ -72,10 +73,13 @@ class SplitTunnelingScreenTest { composeTestRule.setContentWithTheme { SplitTunnelingScreen( uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(excludedApp), - includedApps = listOf(includedApp), - showSystemApps = false + SplitTunnelingUiState( + appListState = + AppListState.ShowAppList( + excludedApps = listOf(excludedApp), + includedApps = listOf(includedApp), + showSystemApps = false + ) ) ) } @@ -100,10 +104,13 @@ class SplitTunnelingScreenTest { composeTestRule.setContentWithTheme { SplitTunnelingScreen( uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = emptyList(), - includedApps = listOf(includedApp), - showSystemApps = false + SplitTunnelingUiState( + appListState = + AppListState.ShowAppList( + excludedApps = emptyList(), + includedApps = listOf(includedApp), + showSystemApps = false + ) ) ) } @@ -131,10 +138,13 @@ class SplitTunnelingScreenTest { composeTestRule.setContentWithTheme { SplitTunnelingScreen( uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(excludedApp), - includedApps = listOf(includedApp), - showSystemApps = false + SplitTunnelingUiState( + appListState = + AppListState.ShowAppList( + excludedApps = listOf(excludedApp), + includedApps = listOf(includedApp), + showSystemApps = false + ) ), onExcludeAppClick = mockedClickHandler ) @@ -158,10 +168,13 @@ class SplitTunnelingScreenTest { composeTestRule.setContentWithTheme { SplitTunnelingScreen( uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(excludedApp), - includedApps = listOf(includedApp), - showSystemApps = false + SplitTunnelingUiState( + appListState = + AppListState.ShowAppList( + excludedApps = listOf(excludedApp), + includedApps = listOf(includedApp), + showSystemApps = false + ) ), onIncludeAppClick = mockedClickHandler ) @@ -185,10 +198,13 @@ class SplitTunnelingScreenTest { composeTestRule.setContentWithTheme { SplitTunnelingScreen( uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(excludedApp), - includedApps = listOf(includedApp), - showSystemApps = false + SplitTunnelingUiState( + 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 5409b7f736ac..f0b6e00883ab 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 @@ -11,13 +11,12 @@ import io.mockk.slot import io.mockk.unmockkAll import io.mockk.verify import io.mockk.verifyAll -import java.util.concurrent.TimeUnit -import kotlin.test.assertEquals import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow 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 @@ -29,6 +28,8 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.rules.Timeout +import java.util.concurrent.TimeUnit +import kotlin.test.assertEquals class SplitTunnelingViewModelTest { @get:Rule val testCoroutineRule = TestCoroutineRule() @@ -57,7 +58,7 @@ class SplitTunnelingViewModelTest { initTestSubject(emptyList()) val actualState: SplitTunnelingUiState = testSubject.uiState.value - val initialExpectedState = SplitTunnelingUiState.Loading + val initialExpectedState = SplitTunnelingUiState() assertEquals(initialExpectedState, actualState) @@ -71,12 +72,21 @@ 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( + checked = true, + appListState = + AppListState.ShowAppList( + excludedApps = emptyList(), + includedApps = emptyList(), + showSystemApps = false + ) ) testSubject.uiState.test { assertEquals(expectedState, awaitItem()) } } @@ -90,21 +100,31 @@ class SplitTunnelingViewModelTest { { lambda<(Set) -> Unit>().invoke(setOf(appExcluded.packageName)) } + every { mockedSplitTunneling.enabledChange = captureLambda() } answers + { + lambda<(Boolean) -> Unit>().invoke(true) + } + + every { mockedSplitTunneling.enableSplitTunneling(any()) } just runs initTestSubject(listOf(appExcluded, appNotExcluded)) val expectedState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(appExcluded), - includedApps = listOf(appNotExcluded), - showSystemApps = false + SplitTunnelingUiState( + checked = 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() } } @@ -121,20 +141,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( + checked = true, + appListState = + AppListState.ShowAppList( + excludedApps = listOf(app), + includedApps = emptyList(), + showSystemApps = false + ) ) val expectedStateAfterAction = - SplitTunnelingUiState.ShowAppList( - excludedApps = emptyList(), - includedApps = listOf(app), - showSystemApps = false + SplitTunnelingUiState( + checked = true, + appListState = + AppListState.ShowAppList( + excludedApps = emptyList(), + includedApps = listOf(app), + showSystemApps = false + ) ) testSubject.uiState.test { @@ -144,7 +176,7 @@ class SplitTunnelingViewModelTest { assertEquals(expectedStateAfterAction, awaitItem()) verifyAll { - mockedSplitTunneling.enabled + mockedSplitTunneling.enabledChange = any() mockedSplitTunneling.excludedAppsChange = any() mockedSplitTunneling.includeApp(app.packageName) } @@ -162,21 +194,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( + checked = true, + appListState = + AppListState.ShowAppList( + excludedApps = emptyList(), + includedApps = listOf(app), + showSystemApps = false + ) ) val expectedStateAfterAction = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(app), - includedApps = emptyList(), - showSystemApps = false + SplitTunnelingUiState( + checked = true, + appListState = + AppListState.ShowAppList( + excludedApps = listOf(app), + includedApps = emptyList(), + showSystemApps = false + ) ) testSubject.uiState.test { @@ -186,13 +230,36 @@ class SplitTunnelingViewModelTest { assertEquals(expectedStateAfterAction, awaitItem()) verifyAll { - mockedSplitTunneling.enabled + mockedSplitTunneling.enabledChange = any() mockedSplitTunneling.excludedAppsChange = any() mockedSplitTunneling.excludeApp(app.packageName) } } } + @Test + fun test_disabled_state() = + runTest(testCoroutineRule.testDispatcher) { + 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(checked = 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