summaryrefslogtreecommitdiffhomepage
path: root/android/app/src
diff options
context:
space:
mode:
authorJonatan Rhodin <jonatan.rhodin@mullvad.net>2023-05-19 08:16:51 +0200
committerAlbin <albin@mullvad.net>2023-05-23 16:27:32 +0200
commit6d8b81e305489bafed9e84a7c297e4f71ac3e9dc (patch)
tree20ff409083afbee7e3b23c366d6094fd6f589358 /android/app/src
parent3470c85de0a361ee340b510bc779318c5ac95860 (diff)
downloadmullvadvpn-6d8b81e305489bafed9e84a7c297e4f71ac3e9dc.tar.xz
mullvadvpn-6d8b81e305489bafed9e84a7c297e4f71ac3e9dc.zip
Remove scopes in koin and use global scope everywhere
Diffstat (limited to 'android/app/src')
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreenTest.kt25
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt16
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SplitTunnelingFragment.kt22
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt16
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/ApplicationImageView.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModel.kt60
-rw-r--r--android/app/src/main/res/values/dimensions.xml1
-rw-r--r--android/app/src/main/res/values/styles.xml15
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/di/UiModuleTest.kt45
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt25
12 files changed, 91 insertions, 151 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 087c4b72a7..e7fa052d5f 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
@@ -11,28 +11,21 @@ import io.mockk.verify
import net.mullvad.mullvadvpn.applist.AppData
import net.mullvad.mullvadvpn.applist.ApplicationsIconManager
import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState
-import net.mullvad.mullvadvpn.di.APPS_SCOPE
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.koin.core.context.loadKoinModules
import org.koin.core.context.unloadKoinModules
-import org.koin.core.qualifier.named
-import org.koin.core.scope.Scope
import org.koin.dsl.module
-import org.koin.java.KoinJavaComponent.getKoin
class SplitTunnelingScreenTest {
@get:Rule val composeTestRule = createComposeRule()
- private lateinit var scope: Scope
private val testModule = module {
- scope(named(APPS_SCOPE)) {
- scoped {
- mockk<ApplicationsIconManager>().apply {
- every { getAppIcon(any()) } returns mockk(relaxed = true)
- }
+ single {
+ mockk<ApplicationsIconManager>().apply {
+ every { getAppIcon(any()) } returns mockk(relaxed = true)
}
}
}
@@ -41,12 +34,10 @@ class SplitTunnelingScreenTest {
fun setup() {
MockKAnnotations.init(this)
loadKoinModules(testModule)
- scope = getKoin().getOrCreateScope(APPS_SCOPE, named(APPS_SCOPE))
}
@After
fun tearDown() {
- scope.close()
unloadKoinModules(testModule)
unmockkAll()
}
@@ -76,7 +67,7 @@ class SplitTunnelingScreenTest {
composeTestRule.setContent {
SplitTunnelingScreen(
uiState =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = listOf(excludedApp),
includedApps = listOf(includedApp),
showSystemApps = false
@@ -104,7 +95,7 @@ class SplitTunnelingScreenTest {
composeTestRule.setContent {
SplitTunnelingScreen(
uiState =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = emptyList(),
includedApps = listOf(includedApp),
showSystemApps = false
@@ -135,7 +126,7 @@ class SplitTunnelingScreenTest {
composeTestRule.setContent {
SplitTunnelingScreen(
uiState =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = listOf(excludedApp),
includedApps = listOf(includedApp),
showSystemApps = false
@@ -162,7 +153,7 @@ class SplitTunnelingScreenTest {
composeTestRule.setContent {
SplitTunnelingScreen(
uiState =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = listOf(excludedApp),
includedApps = listOf(includedApp),
showSystemApps = false
@@ -189,7 +180,7 @@ class SplitTunnelingScreenTest {
composeTestRule.setContent {
SplitTunnelingScreen(
uiState =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = listOf(excludedApp),
includedApps = listOf(includedApp),
showSystemApps = false
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt
index 8c5a295308..5fc222bf0a 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt
@@ -98,7 +98,7 @@ fun SplitTunnelingScreen(
title = stringResource(id = R.string.split_tunneling),
progress = progress,
modifier = scaffoldModifier,
- backTitle = stringResource(id = R.string.settings_vpn)
+ backTitle = stringResource(id = R.string.settings)
)
},
) {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
index 26703d98ec..f0fcc4fa65 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
@@ -45,16 +45,12 @@ val uiModule = module {
single<PackageManager> { androidContext().packageManager }
single<String>(named(SELF_PACKAGE_NAME)) { androidContext().packageName }
- scope(named(APPS_SCOPE)) {
- viewModel { SplitTunnelingViewModel(get(), get(), Dispatchers.Default) }
- scoped { ApplicationsIconManager(get()) } onClose { it?.dispose() }
- scoped { ApplicationsProvider(get(), get(named(SELF_PACKAGE_NAME))) }
- }
+ viewModel { SplitTunnelingViewModel(get(), get(), Dispatchers.Default) }
+ single { ApplicationsIconManager(get()) } onClose { it?.dispose() }
+ single { ApplicationsProvider(get(), get(named(SELF_PACKAGE_NAME))) }
- scope(named(SERVICE_CONNECTION_SCOPE)) {
- scoped<SplitTunneling> { (messenger: Messenger, dispatcher: EventDispatcher) ->
- SplitTunneling(messenger, dispatcher)
- }
+ single { (messenger: Messenger, dispatcher: EventDispatcher) ->
+ SplitTunneling(messenger, dispatcher)
}
single { ServiceConnectionManager(androidContext()) }
@@ -97,7 +93,5 @@ val uiModule = module {
}
}
-const val APPS_SCOPE = "APPS_SCOPE"
-const val SERVICE_CONNECTION_SCOPE = "SERVICE_CONNECTION_SCOPE"
const val SELF_PACKAGE_NAME = "SELF_PACKAGE_NAME"
const val APP_PREFERENCES_NAME = "net.mullvad.mullvadvpn.app_preferences"
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SplitTunnelingFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SplitTunnelingFragment.kt
index 910588e580..9a920d7324 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SplitTunnelingFragment.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SplitTunnelingFragment.kt
@@ -9,24 +9,11 @@ import androidx.compose.ui.platform.ComposeView
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.screen.SplitTunnelingScreen
import net.mullvad.mullvadvpn.compose.theme.AppTheme
-import net.mullvad.mullvadvpn.di.APPS_SCOPE
-import net.mullvad.mullvadvpn.di.SERVICE_CONNECTION_SCOPE
import net.mullvad.mullvadvpn.viewmodel.SplitTunnelingViewModel
-import org.koin.android.ext.android.getKoin
-import org.koin.androidx.viewmodel.ViewModelOwner
-import org.koin.androidx.viewmodel.scope.viewModel
-import org.koin.core.qualifier.named
-import org.koin.core.scope.Scope
+import org.koin.androidx.viewmodel.ext.android.viewModel
class SplitTunnelingFragment : BaseFragment() {
- private val scope: Scope =
- getKoin().getOrCreateScope(APPS_SCOPE, named(APPS_SCOPE)).also { appsScope ->
- getKoin().getScopeOrNull(SERVICE_CONNECTION_SCOPE)?.let { serviceConnectionScope ->
- appsScope.linkTo(serviceConnectionScope)
- }
- }
- private val viewModel by
- scope.viewModel<SplitTunnelingViewModel>(owner = { ViewModelOwner.from(this, this) })
+ private val viewModel: SplitTunnelingViewModel by viewModel()
override fun onCreateView(
inflater: LayoutInflater,
@@ -48,9 +35,4 @@ class SplitTunnelingFragment : BaseFragment() {
}
}
}
-
- override fun onDestroy() {
- scope.close()
- super.onDestroy()
- }
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt
index a58db46ff7..7f895618fb 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt
@@ -4,15 +4,12 @@ import android.os.Looper
import android.os.Messenger
import android.os.RemoteException
import android.util.Log
-import net.mullvad.mullvadvpn.di.SERVICE_CONNECTION_SCOPE
import net.mullvad.mullvadvpn.ipc.DispatchingHandler
import net.mullvad.mullvadvpn.ipc.Event
import net.mullvad.mullvadvpn.ipc.Request
import org.koin.core.component.KoinApiExtension
-import org.koin.core.parameter.parametersOf
-import org.koin.core.qualifier.named
-import org.koin.core.scope.KoinScopeComponent
-import org.koin.core.scope.get
+import org.koin.core.component.KoinComponent
+import org.koin.core.component.get
// Container of classes that communicate with the service through an active connection
//
@@ -23,13 +20,10 @@ class ServiceConnectionContainer(
val connection: Messenger,
onServiceReady: (ServiceConnectionContainer) -> Unit,
onVpnPermissionRequest: () -> Unit
-) : KoinScopeComponent {
+) : KoinComponent {
private val dispatcher =
DispatchingHandler(Looper.getMainLooper()) { message -> Event.fromMessage(message) }
- override val scope =
- getKoin().getOrCreateScope(SERVICE_CONNECTION_SCOPE, named(SERVICE_CONNECTION_SCOPE), this)
-
val accountDataSource = ServiceConnectionAccountDataSource(connection, dispatcher)
val authTokenCache = AuthTokenCache(connection, dispatcher)
val connectionProxy = ConnectionProxy(connection, dispatcher)
@@ -37,8 +31,7 @@ class ServiceConnectionContainer(
val locationInfoCache = LocationInfoCache(dispatcher)
val settingsListener = SettingsListener(connection, dispatcher)
- // NOTE: `org.koin.core.scope.get` must be used here rather than `org.koin.core.component.get`.
- val splitTunneling = get<SplitTunneling>(parameters = { parametersOf(connection, dispatcher) })
+ val splitTunneling = SplitTunneling(connection, dispatcher)
val voucherRedeemer = VoucherRedeemer(connection, dispatcher)
val vpnPermission = VpnPermission(connection, dispatcher)
@@ -61,7 +54,6 @@ class ServiceConnectionContainer(
fun onDestroy() {
unregisterListener()
- closeScope()
dispatcher.onDestroy()
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt
index 1de160ffe8..f7be833792 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt
@@ -22,3 +22,6 @@ fun ServiceConnectionManager.relayListListener() =
fun ServiceConnectionManager.settingsListener() =
this.connectionState.value.readyContainer()?.settingsListener
+
+fun ServiceConnectionManager.splitTunneling() =
+ this.connectionState.value.readyContainer()?.splitTunneling
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/ApplicationImageView.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/ApplicationImageView.kt
index 8c840357e0..519fefb180 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/ApplicationImageView.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/ApplicationImageView.kt
@@ -15,25 +15,23 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.applist.ApplicationsIconManager
-import net.mullvad.mullvadvpn.di.APPS_SCOPE
-import org.koin.core.scope.inject
-import org.koin.core.scope.KoinScopeComponent
-import org.koin.core.scope.Scope
+import org.koin.core.component.KoinApiExtension
+import org.koin.core.component.KoinComponent
+import org.koin.core.component.inject
+@OptIn(KoinApiExtension::class)
class ApplicationImageView
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = R.attr.applicationListItemViewStyle,
-) : AppCompatImageView(context, attrs, defStyleAttr), KoinScopeComponent {
+) : AppCompatImageView(context, attrs, defStyleAttr), KoinComponent {
private val viewScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
private val iconManager: ApplicationsIconManager by inject()
private var updateImageJob: Job? = null
- override val scope: Scope = getKoin().getScope(APPS_SCOPE)
-
var packageName: String = ""
set(value) {
field = value
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModel.kt
index 38803cfc21..a1376eabb4 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModel.kt
@@ -5,36 +5,60 @@ import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.applist.AppData
import net.mullvad.mullvadvpn.applist.ApplicationsProvider
import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState
+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.SplitTunneling
+import net.mullvad.mullvadvpn.ui.serviceconnection.splitTunneling
class SplitTunnelingViewModel(
private val appsProvider: ApplicationsProvider,
- private val splitTunneling: SplitTunneling,
+ private val serviceConnectionManager: ServiceConnectionManager,
private val dispatcher: CoroutineDispatcher
) : ViewModel() {
private val allApps = MutableStateFlow<List<AppData>?>(null)
private val showSystemApps = MutableStateFlow(false)
+ private val _shared: SharedFlow<ServiceConnectionContainer> =
+ serviceConnectionManager.connectionState
+ .flatMapLatest { state ->
+ if (state is ServiceConnectionState.ConnectedReady) {
+ flowOf(state.container)
+ } else {
+ emptyFlow()
+ }
+ }
+ .shareIn(viewModelScope, SharingStarted.WhileSubscribed())
+
private val vmState =
- combine(splitTunneling.excludedAppsCallbackFlow(), allApps, showSystemApps) {
- excludedApps,
- allApps,
- showSystemApps ->
- SplitTunnelingViewModelState(
- excludedApps = excludedApps,
- allApps = allApps,
- showSystemApps = showSystemApps
- )
+ _shared
+ .flatMapLatest { serviceConnection ->
+ combine(
+ serviceConnection.splitTunneling.excludedAppsCallbackFlow(),
+ allApps,
+ showSystemApps
+ ) { excludedApps, allApps, showSystemApps ->
+ SplitTunnelingViewModelState(
+ excludedApps = excludedApps,
+ allApps = allApps,
+ showSystemApps = showSystemApps
+ )
+ }
}
.stateIn(
viewModelScope,
@@ -53,22 +77,28 @@ class SplitTunnelingViewModel(
init {
viewModelScope.launch(dispatcher) {
- if (!splitTunneling.enabled) splitTunneling.enabled = true
+ if (serviceConnectionManager.splitTunneling()?.enabled == false) {
+ serviceConnectionManager.splitTunneling()?.enabled = true
+ }
fetchApps()
}
}
override fun onCleared() {
- splitTunneling.persist()
+ serviceConnectionManager.splitTunneling()?.persist()
super.onCleared()
}
-
+
fun onIncludeAppClick(packageName: String) {
- viewModelScope.launch(dispatcher) { splitTunneling.includeApp(packageName) }
+ viewModelScope.launch(dispatcher) {
+ serviceConnectionManager.splitTunneling()?.includeApp(packageName)
+ }
}
fun onExcludeAppClick(packageName: String) {
- viewModelScope.launch(dispatcher) { splitTunneling.excludeApp(packageName) }
+ viewModelScope.launch(dispatcher) {
+ serviceConnectionManager.splitTunneling()?.excludeApp(packageName)
+ }
}
fun onShowSystemAppsClicked(show: Boolean) {
diff --git a/android/app/src/main/res/values/dimensions.xml b/android/app/src/main/res/values/dimensions.xml
index 76fa24032d..d6bab1dade 100644
--- a/android/app/src/main/res/values/dimensions.xml
+++ b/android/app/src/main/res/values/dimensions.xml
@@ -39,7 +39,6 @@
<dimen name="half_vertical_space">10dp</dimen>
<dimen name="button_separation">18dp</dimen>
<dimen name="screen_vertical_margin">22dp</dimen>
- <dimen name="app_list_item_icon_size">35dp</dimen>
<dimen name="progress_size">60dp</dimen>
<dimen name="icon_size">24dp</dimen>
<dimen name="widget_padding">16dp</dimen>
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
index 9a808e9c3b..dab9229592 100644
--- a/android/app/src/main/res/values/styles.xml
+++ b/android/app/src/main/res/values/styles.xml
@@ -56,10 +56,6 @@
<item name="android:textColor">@color/white</item>
<item name="android:textSize">@dimen/text_medium_plus</item>
</style>
- <style name="TextAppearance.Mullvad.Title2">
- <item name="android:textColor">@color/white</item>
- <item name="android:textSize">@dimen/text_medium</item>
- </style>
<style name="TextAppearance.Mullvad.Small">
<item name="android:textColor">@color/white60</item>
<item name="android:textSize">@dimen/text_small</item>
@@ -90,17 +86,6 @@
<item name="android:clickable">false</item>
<item name="android:focusable">false</item>
</style>
- <style name="TextAppearance.Mullvad.CollapsingToolbar">
- <item name="android:textColor">@color/white</item>
- </style>
- <style name="TextAppearance.Mullvad.CollapsingToolbar.Expanded">
- <item name="android:textSize">30sp</item>
- <item name="android:textStyle">bold</item>
- </style>
- <style name="TextAppearance.Mullvad.CollapsingToolbar.Collapsed">
- <item name="android:textSize">20sp</item>
- <item name="android:textStyle">bold</item>
- </style>
<!-- Switch Style -->
<style name="AppTheme.Switch">
<item name="android:layout_width">@dimen/switch_width</item>
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/di/UiModuleTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/di/UiModuleTest.kt
deleted file mode 100644
index 01b1807d42..0000000000
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/di/UiModuleTest.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package net.mullvad.mullvadvpn.di
-
-import android.os.Messenger
-import io.mockk.mockk
-import io.mockk.unmockkAll
-import kotlin.test.assertEquals
-import net.mullvad.mullvadvpn.ipc.Event
-import net.mullvad.mullvadvpn.ipc.MessageDispatcher
-import net.mullvad.mullvadvpn.ui.serviceconnection.SplitTunneling
-import org.junit.After
-import org.junit.Rule
-import org.junit.Test
-import org.koin.core.parameter.parametersOf
-import org.koin.core.qualifier.named
-import org.koin.core.scope.Scope
-import org.koin.test.KoinTest
-import org.koin.test.KoinTestRule
-
-class UiModuleTest : KoinTest {
-
- @get:Rule val koinTestRule = KoinTestRule.create { modules(uiModule) }
-
- @After
- fun tearDown() {
- unmockkAll()
- }
-
- @Test
- fun test_scope_linking() {
- val appsScope: Scope = getKoin().createScope(APPS_SCOPE, named(APPS_SCOPE))
- val serviceConnectionScope =
- getKoin().createScope(SERVICE_CONNECTION_SCOPE, named(SERVICE_CONNECTION_SCOPE))
-
- appsScope.linkTo(serviceConnectionScope)
-
- val mockedMessenger = mockk<Messenger>()
- val mockedEventMessageHandler = mockk<MessageDispatcher<Event>>(relaxed = true)
- val serviceConnectionSplitTunneling =
- serviceConnectionScope.get<SplitTunneling>(
- parameters = { parametersOf(mockedMessenger, mockedEventMessageHandler) }
- )
-
- assertEquals(appsScope.get<SplitTunneling>(), serviceConnectionSplitTunneling)
- }
-}
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 bc31165ebe..2b5a7f261c 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
@@ -14,11 +14,15 @@ 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.TestCoroutineRule
import net.mullvad.mullvadvpn.applist.AppData
import net.mullvad.mullvadvpn.applist.ApplicationsProvider
import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState
+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.SplitTunneling
import org.junit.After
import org.junit.Before
@@ -32,6 +36,8 @@ class SplitTunnelingViewModelTest {
@get:Rule val timeout = Timeout(3000L, TimeUnit.MILLISECONDS)
private val mockedApplicationsProvider = mockk<ApplicationsProvider>()
private val mockedSplitTunneling = mockk<SplitTunneling>()
+ private val mockedServiceConnectionManager = mockk<ServiceConnectionManager>()
+ private val mockedServiceConnectionContainer = mockk<ServiceConnectionContainer>()
private lateinit var testSubject: SplitTunnelingViewModel
@Before
@@ -67,7 +73,7 @@ class SplitTunnelingViewModelTest {
}
initTestSubject(emptyList())
val expectedState =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = emptyList(),
includedApps = emptyList(),
showSystemApps = false
@@ -88,7 +94,7 @@ class SplitTunnelingViewModelTest {
initTestSubject(listOf(appExcluded, appNotExcluded))
val expectedState =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = listOf(appExcluded),
includedApps = listOf(appNotExcluded),
showSystemApps = false
@@ -119,13 +125,13 @@ class SplitTunnelingViewModelTest {
initTestSubject(listOf(app))
val expectedStateBeforeAction =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = listOf(app),
includedApps = emptyList(),
showSystemApps = false
)
val expectedStateAfterAction =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = emptyList(),
includedApps = listOf(app),
showSystemApps = false
@@ -160,14 +166,14 @@ class SplitTunnelingViewModelTest {
initTestSubject(listOf(app))
val expectedStateBeforeAction =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = emptyList(),
includedApps = listOf(app),
showSystemApps = false
)
val expectedStateAfterAction =
- SplitTunnelingUiState.Data(
+ SplitTunnelingUiState.ShowAppList(
excludedApps = listOf(app),
includedApps = emptyList(),
showSystemApps = false
@@ -189,10 +195,15 @@ class SplitTunnelingViewModelTest {
private fun initTestSubject(appList: List<AppData>) {
every { mockedApplicationsProvider.getAppsList() } returns appList
+ every { mockedServiceConnectionManager.connectionState } returns
+ MutableStateFlow(
+ ServiceConnectionState.ConnectedReady(mockedServiceConnectionContainer)
+ )
+ every { mockedServiceConnectionContainer.splitTunneling } returns mockedSplitTunneling
testSubject =
SplitTunnelingViewModel(
mockedApplicationsProvider,
- mockedSplitTunneling,
+ mockedServiceConnectionManager,
testCoroutineRule.testDispatcher
)
}