diff options
| author | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2023-05-12 11:22:39 +0200 |
|---|---|---|
| committer | Albin <albin@mullvad.net> | 2023-05-23 16:27:32 +0200 |
| commit | 893b8bd55ac6d926a4eda240956530677782aa3b (patch) | |
| tree | f2d5634480c859d0246d77d82e10fd99013b7de0 /android/app/src | |
| parent | af8ebd0abb958c026d6e6e672ed651289b59b8b9 (diff) | |
| download | mullvadvpn-893b8bd55ac6d926a4eda240956530677782aa3b.tar.xz mullvadvpn-893b8bd55ac6d926a4eda240956530677782aa3b.zip | |
Update SplitTunnelingViewModel unit tests
Diffstat (limited to 'android/app/src')
| -rw-r--r-- | android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt | 238 |
1 files changed, 97 insertions, 141 deletions
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 9fa0e9ea88..bc31165ebe 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 @@ -1,26 +1,24 @@ package net.mullvad.mullvadvpn.viewmodel -import androidx.annotation.StringRes import androidx.lifecycle.viewModelScope -import io.mockk.Runs +import app.cash.turbine.test import io.mockk.every +import io.mockk.invoke import io.mockk.just import io.mockk.mockk +import io.mockk.runs +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.first -import kotlinx.coroutines.test.runBlockingTest -import net.mullvad.mullvadvpn.R +import kotlinx.coroutines.test.runTest import net.mullvad.mullvadvpn.TestCoroutineRule import net.mullvad.mullvadvpn.applist.AppData import net.mullvad.mullvadvpn.applist.ApplicationsProvider -import net.mullvad.mullvadvpn.applist.ViewIntent -import net.mullvad.mullvadvpn.assertLists -import net.mullvad.mullvadvpn.model.ListItemData -import net.mullvad.mullvadvpn.model.WidgetState +import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState import net.mullvad.mullvadvpn.ui.serviceconnection.SplitTunneling import org.junit.After import org.junit.Before @@ -49,146 +47,143 @@ class SplitTunnelingViewModelTest { @Test fun test_has_progress_on_start() = - runBlockingTest(testCoroutineRule.testDispatcher) { + runTest(testCoroutineRule.testDispatcher) { initTestSubject(emptyList()) - val actualList: List<ListItemData> = testSubject.listItems.first() + val actualState: SplitTunnelingUiState = testSubject.uiState.value - val initialExpectedList = - listOf( - createTextItem(R.string.split_tunneling_description), - createDivider(0), - createProgressItem() - ) + val initialExpectedState = SplitTunnelingUiState.Loading - assertLists(initialExpectedList, actualList) + assertEquals(initialExpectedState, actualState) verify(exactly = 1) { mockedApplicationsProvider.getAppsList() } } @Test fun test_empty_app_list() = - runBlockingTest(testCoroutineRule.testDispatcher) { + runTest(testCoroutineRule.testDispatcher) { + every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers + { + lambda<(Set<String>) -> Unit>().invoke(emptySet()) + } initTestSubject(emptyList()) - testSubject.processIntent(ViewIntent.ViewIsReady) - val actualList = testSubject.listItems.first() - val expectedList = listOf(createTextItem(R.string.split_tunneling_description)) - assertLists(expectedList, actualList) + val expectedState = + SplitTunnelingUiState.Data( + excludedApps = emptyList(), + includedApps = emptyList(), + showSystemApps = false + ) + testSubject.uiState.test { assertEquals(expectedState, awaitItem()) } } @Test fun test_apps_list_delivered() = - runBlockingTest(testCoroutineRule.testDispatcher) { + runTest(testCoroutineRule.testDispatcher) { val appExcluded = AppData("test.excluded", 0, "testName1") val appNotExcluded = AppData("test.not.excluded", 0, "testName2") - every { mockedSplitTunneling.isAppExcluded(appExcluded.packageName) } returns true - every { mockedSplitTunneling.isAppExcluded(appNotExcluded.packageName) } returns false + every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers + { + lambda<(Set<String>) -> Unit>().invoke(setOf(appExcluded.packageName)) + } initTestSubject(listOf(appExcluded, appNotExcluded)) - testSubject.processIntent(ViewIntent.ViewIsReady) - val actualList = testSubject.listItems.first() - val expectedList = - listOf( - createTextItem(R.string.split_tunneling_description), - createDivider(0), - createMainItem(R.string.exclude_applications), - createApplicationItem(appExcluded, true), - createDivider(1), - createSwitchItem(R.string.show_system_apps, false), - createMainItem(R.string.all_applications), - createApplicationItem(appNotExcluded, false), + val expectedState = + SplitTunnelingUiState.Data( + excludedApps = listOf(appExcluded), + includedApps = listOf(appNotExcluded), + showSystemApps = false ) - assertLists(expectedList, actualList) - verifyAll { - mockedSplitTunneling.enabled - mockedSplitTunneling.isAppExcluded(appExcluded.packageName) - mockedSplitTunneling.isAppExcluded(appNotExcluded.packageName) + testSubject.uiState.test { + val actualState = awaitItem() + assertEquals(expectedState, actualState) + verifyAll { + mockedSplitTunneling.enabled + mockedSplitTunneling.excludedAppsChange = any() + } } } @Test fun test_remove_app_from_excluded() = - runBlockingTest(testCoroutineRule.testDispatcher) { + runTest(testCoroutineRule.testDispatcher) { + var excludedAppsCallback = slot<(Set<String>) -> Unit>() val app = AppData("test", 0, "testName") - every { mockedSplitTunneling.isAppExcluded(app.packageName) } returns true - every { mockedSplitTunneling.includeApp(app.packageName) } just Runs + every { mockedSplitTunneling.includeApp(app.packageName) } just runs + every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers + { + excludedAppsCallback = lambda() + excludedAppsCallback.invoke(setOf(app.packageName)) + } initTestSubject(listOf(app)) - testSubject.processIntent(ViewIntent.ViewIsReady) - val listBeforeAction = testSubject.listItems.first() - val expectedListBeforeAction = - listOf( - createTextItem(R.string.split_tunneling_description), - createDivider(0), - createMainItem(R.string.exclude_applications), - createApplicationItem(app, true), + val expectedStateBeforeAction = + SplitTunnelingUiState.Data( + excludedApps = listOf(app), + includedApps = emptyList(), + showSystemApps = false ) - - assertLists(expectedListBeforeAction, listBeforeAction) - - val item = listBeforeAction.first { it.identifier == app.packageName } - testSubject.processIntent(ViewIntent.ChangeApplicationGroup(item)) - - val itemsAfterAction = testSubject.listItems.first() - val expectedList = - listOf( - createTextItem(R.string.split_tunneling_description), - createDivider(1), - createSwitchItem(R.string.show_system_apps, false), - createMainItem(R.string.all_applications), - createApplicationItem(app, false), + val expectedStateAfterAction = + SplitTunnelingUiState.Data( + excludedApps = emptyList(), + includedApps = listOf(app), + showSystemApps = false ) - assertLists(expectedList, itemsAfterAction) + testSubject.uiState.test { + assertEquals(expectedStateBeforeAction, awaitItem()) + testSubject.removeFromExcluded(app.packageName) + excludedAppsCallback.invoke(emptySet()) + assertEquals(expectedStateAfterAction, awaitItem()) - verifyAll { - mockedSplitTunneling.enabled - mockedSplitTunneling.isAppExcluded(app.packageName) - mockedSplitTunneling.includeApp(app.packageName) + verifyAll { + mockedSplitTunneling.enabled + mockedSplitTunneling.excludedAppsChange = any() + mockedSplitTunneling.includeApp(app.packageName) + } } } @Test fun test_add_app_to_excluded() = - runBlockingTest(testCoroutineRule.testDispatcher) { + runTest(testCoroutineRule.testDispatcher) { + var excludedAppsCallback = slot<(Set<String>) -> Unit>() val app = AppData("test", 0, "testName") - every { mockedSplitTunneling.isAppExcluded(app.packageName) } returns false - every { mockedSplitTunneling.excludeApp(app.packageName) } just Runs + every { mockedSplitTunneling.excludeApp(app.packageName) } just runs + every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers + { + excludedAppsCallback = lambda() + excludedAppsCallback.invoke(emptySet()) + } + initTestSubject(listOf(app)) - testSubject.processIntent(ViewIntent.ViewIsReady) - val listBeforeAction = testSubject.listItems.first() - val expectedListBeforeAction = - listOf( - createTextItem(R.string.split_tunneling_description), - createDivider(1), - createSwitchItem(R.string.show_system_apps, false), - createMainItem(R.string.all_applications), - createApplicationItem(app, false), + val expectedStateBeforeAction = + SplitTunnelingUiState.Data( + excludedApps = emptyList(), + includedApps = listOf(app), + showSystemApps = false ) - assertLists(expectedListBeforeAction, listBeforeAction) - - val item = listBeforeAction.first { it.identifier == app.packageName } - testSubject.processIntent(ViewIntent.ChangeApplicationGroup(item)) - - val itemsAfterAction = testSubject.listItems.first() - val expectedList = - listOf( - createTextItem(R.string.split_tunneling_description), - createDivider(0), - createMainItem(R.string.exclude_applications), - createApplicationItem(app, true), + val expectedStateAfterAction = + SplitTunnelingUiState.Data( + excludedApps = listOf(app), + includedApps = emptyList(), + showSystemApps = false ) - assertLists(expectedList, itemsAfterAction) + testSubject.uiState.test { + assertEquals(expectedStateBeforeAction, awaitItem()) + testSubject.addToExcluded(app.packageName) + excludedAppsCallback.invoke(setOf(app.packageName)) + assertEquals(expectedStateAfterAction, awaitItem()) - verifyAll { - mockedSplitTunneling.enabled - mockedSplitTunneling.isAppExcluded(app.packageName) - mockedSplitTunneling.excludeApp(app.packageName) + verifyAll { + mockedSplitTunneling.enabled + mockedSplitTunneling.excludedAppsChange = any() + mockedSplitTunneling.excludeApp(app.packageName) + } } } @@ -201,43 +196,4 @@ class SplitTunnelingViewModelTest { testCoroutineRule.testDispatcher ) } - - private fun createApplicationItem(appData: AppData, checked: Boolean): ListItemData = - ListItemData.build(appData.packageName) { - type = ListItemData.APPLICATION - text = appData.name - iconRes = appData.iconRes - action = ListItemData.ItemAction(appData.packageName) - widget = - WidgetState.ImageState( - if (checked) R.drawable.ic_icons_remove else R.drawable.ic_icons_add - ) - } - - private fun createDivider(id: Int): ListItemData = - ListItemData.build("space_$id") { type = ListItemData.DIVIDER } - - private fun createMainItem(@StringRes text: Int): ListItemData = - ListItemData.build("header_$text") { - type = ListItemData.ACTION - textRes = text - } - - private fun createTextItem(@StringRes text: Int): ListItemData = - ListItemData.build("text_$text") { - type = ListItemData.PLAIN - textRes = text - action = ListItemData.ItemAction(text.toString()) - } - - private fun createProgressItem(): ListItemData = - ListItemData.build(identifier = "progress") { type = ListItemData.PROGRESS } - - private fun createSwitchItem(@StringRes text: Int, checked: Boolean): ListItemData = - ListItemData.build(identifier = "switch_$text") { - type = ListItemData.ACTION - textRes = text - action = ListItemData.ItemAction(text.toString()) - widget = WidgetState.SwitchState(checked) - } } |
