diff --git a/app/src/main/java/com/x8bit/bitwarden/BitwardenApplication.kt b/app/src/main/java/com/x8bit/bitwarden/BitwardenApplication.kt index b26f2f4f99..a3e3913a15 100644 --- a/app/src/main/java/com/x8bit/bitwarden/BitwardenApplication.kt +++ b/app/src/main/java/com/x8bit/bitwarden/BitwardenApplication.kt @@ -6,6 +6,7 @@ import com.x8bit.bitwarden.data.auth.manager.AuthRequestNotificationManager import com.x8bit.bitwarden.data.platform.manager.LogsManager import com.x8bit.bitwarden.data.platform.manager.event.OrganizationEventManager import com.x8bit.bitwarden.data.platform.manager.network.NetworkConfigManager +import com.x8bit.bitwarden.data.platform.manager.network.NetworkConnectionManager import com.x8bit.bitwarden.data.platform.manager.restriction.RestrictionManager import dagger.hilt.android.HiltAndroidApp import javax.inject.Inject @@ -21,6 +22,9 @@ class BitwardenApplication : Application() { @Inject lateinit var logsManager: LogsManager + @Inject + lateinit var networkConnectionManager: NetworkConnectionManager + @Inject lateinit var networkConfigManager: NetworkConfigManager diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt index c54efe738a..0953a993b7 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt @@ -259,8 +259,10 @@ object PlatformManagerModule { @Singleton fun provideNetworkConnectionManager( application: Application, + dispatcherManager: DispatcherManager, ): NetworkConnectionManager = NetworkConnectionManagerImpl( context = application.applicationContext, + dispatcherManager = dispatcherManager, ) @Provides diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/NetworkConnection.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/NetworkConnection.kt new file mode 100644 index 0000000000..e05f52f0fc --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/NetworkConnection.kt @@ -0,0 +1,28 @@ +package com.x8bit.bitwarden.data.platform.manager.model + +/** + * A representation of the current network connection. + */ +sealed class NetworkConnection { + /** + * Currently not connected to the internet. + */ + data object None : NetworkConnection() + + /** + * Currently connected to the internet via WiFi with a signal [strength] indication. + */ + data class Wifi( + val strength: NetworkSignalStrength, + ) : NetworkConnection() + + /** + * Currently connected to the internet via cellular connection. + */ + data object Cellular : NetworkConnection() + + /** + * Currently connected to the internet via an unknown connection. + */ + data object Other : NetworkConnection() +} diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/NetworkSignalStrength.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/NetworkSignalStrength.kt new file mode 100644 index 0000000000..983cde4ebf --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/NetworkSignalStrength.kt @@ -0,0 +1,13 @@ +package com.x8bit.bitwarden.data.platform.manager.model + +/** + * An indicator of the signal strength for a network connection. + */ +enum class NetworkSignalStrength { + EXCELLENT, + GOOD, + FAIR, + WEAK, + NONE, + UNKNOWN, +} diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManager.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManager.kt index 8ae26a5829..e2f38a28cc 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManager.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManager.kt @@ -1,5 +1,8 @@ package com.x8bit.bitwarden.data.platform.manager.network +import com.x8bit.bitwarden.data.platform.manager.model.NetworkConnection +import kotlinx.coroutines.flow.StateFlow + /** * Manager to detect and handle changes to network connectivity. */ @@ -9,4 +12,21 @@ interface NetworkConnectionManager { * available. */ val isNetworkConnected: Boolean + + /** + * Emits `true` when the application has a network connection and access to the Internet is + * available. + */ + val isNetworkConnectedFlow: StateFlow + + /** + * Returns the current network connection. + */ + val networkConnection: NetworkConnection + + /** + * Emits the current [NetworkConnection] indicating what type of network the app is currently + * using to connect to the internet. + */ + val networkConnectionFlow: StateFlow } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManagerImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManagerImpl.kt index 638688ee15..7fd48bb763 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManagerImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManagerImpl.kt @@ -2,21 +2,153 @@ package com.x8bit.bitwarden.data.platform.manager.network import android.content.Context import android.net.ConnectivityManager +import android.net.LinkProperties +import android.net.Network import android.net.NetworkCapabilities +import android.net.NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED +import android.net.NetworkRequest +import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow +import com.bitwarden.data.manager.DispatcherManager +import com.x8bit.bitwarden.data.platform.manager.model.NetworkConnection +import com.x8bit.bitwarden.data.platform.manager.model.NetworkSignalStrength +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn /** * Primary implementation of [NetworkConnectionManager]. */ class NetworkConnectionManagerImpl( context: Context, + dispatcherManager: DispatcherManager, ) : NetworkConnectionManager { + private val unconfinedScope = CoroutineScope(context = dispatcherManager.unconfined) + private val networkChangeCallback = ConnectionChangeCallback() + private val connectivityManager: ConnectivityManager = context .applicationContext .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + init { + connectivityManager.registerNetworkCallback( + NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .build(), + networkChangeCallback, + ) + } + override val isNetworkConnected: Boolean get() = connectivityManager .getNetworkCapabilities(connectivityManager.activeNetwork) ?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) ?: false + + override val isNetworkConnectedFlow: StateFlow = + networkChangeCallback + .connectionChangeFlow + .map { isNetworkConnected } + .distinctUntilChanged() + .stateIn( + scope = unconfinedScope, + started = SharingStarted.Eagerly, + initialValue = isNetworkConnected, + ) + + override val networkConnection: NetworkConnection + get() = connectivityManager + .getNetworkCapabilities(connectivityManager.activeNetwork) + .networkConnection + + override val networkConnectionFlow: StateFlow = networkChangeCallback + .connectionChangeFlow + .map { _ -> networkConnection } + .distinctUntilChanged() + .stateIn( + scope = unconfinedScope, + started = SharingStarted.Eagerly, + initialValue = networkConnection, + ) + + /** + * A callback used to monitor the connection of a [Network]. + */ + private class ConnectionChangeCallback : ConnectivityManager.NetworkCallback() { + private val mutableConnectionState: MutableSharedFlow = bufferedMutableSharedFlow() + + /** + * A [StateFlow] that emits when the connection state to a network changes. + */ + val connectionChangeFlow: SharedFlow = mutableConnectionState.asSharedFlow() + + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities, + ) { + super.onCapabilitiesChanged(network, networkCapabilities) + mutableConnectionState.tryEmit(Unit) + } + + override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) { + super.onLinkPropertiesChanged(network, linkProperties) + mutableConnectionState.tryEmit(Unit) + } + + override fun onAvailable(network: Network) { + super.onAvailable(network) + mutableConnectionState.tryEmit(Unit) + } + + override fun onLost(network: Network) { + super.onLost(network) + mutableConnectionState.tryEmit(Unit) + } + } } + +/** + * Converts the [NetworkCapabilities] to a [NetworkConnection]. + */ +private val NetworkCapabilities?.networkConnection: NetworkConnection + get() = this + ?.let { + if (it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + NetworkConnection.Wifi(it.networkStrength) + } else if (it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + NetworkConnection.Cellular + } else { + NetworkConnection.Other + } + } + ?: NetworkConnection.None + +/** + * Converts an integer value to an enum signal strength based on the RSSI standard. + * + * * -50 dBm: Excellent signal + * * -60 to -75 dBm: Good signal + * * -76 to -90 dBm: Fair signal + * * -91 to -110 dBm: Weak signal + * * -110 dBm and below: No signal + */ +@Suppress("MagicNumber") +private val NetworkCapabilities.networkStrength: NetworkSignalStrength + get() { + val strength = this.signalStrength + return when { + (strength <= SIGNAL_STRENGTH_UNSPECIFIED) -> NetworkSignalStrength.UNKNOWN + (strength <= -110) -> NetworkSignalStrength.NONE + (strength <= -91) -> NetworkSignalStrength.WEAK + (strength <= -76) -> NetworkSignalStrength.FAIR + (strength <= -60) -> NetworkSignalStrength.GOOD + else -> NetworkSignalStrength.EXCELLENT + } + } diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManagerTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManagerTest.kt index c566bd136e..8e14dd2b9f 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManagerTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/network/NetworkConnectionManagerTest.kt @@ -4,20 +4,67 @@ import android.content.Context import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities +import android.net.NetworkRequest +import app.cash.turbine.test +import com.bitwarden.data.datasource.disk.base.FakeDispatcherManager +import com.x8bit.bitwarden.data.platform.manager.model.NetworkConnection +import com.x8bit.bitwarden.data.platform.manager.model.NetworkSignalStrength import io.mockk.every +import io.mockk.just import io.mockk.mockk -import org.junit.Test -import org.junit.jupiter.api.Assertions +import io.mockk.mockkConstructor +import io.mockk.runs +import io.mockk.slot +import io.mockk.unmockkConstructor +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertFalse +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test class NetworkConnectionManagerTest { + private val networkCallback = slot() + private val connectivityManager = mockk { + every { + registerNetworkCallback(any(), capture(networkCallback)) + } just runs + every { activeNetwork } returns null + every { getNetworkCapabilities(any()) } returns null + } + private val context = mockk { + every { applicationContext } returns this + every { getSystemService(Context.CONNECTIVITY_SERVICE) } returns connectivityManager + } + private val fakeDispatcherManager = FakeDispatcherManager() + + private lateinit var networkConnectionManager: NetworkConnectionManagerImpl + + @BeforeEach + fun setup() { + mockkConstructor(NetworkRequest.Builder::class) + val builder = mockk { + every { addTransportType(any()) } returns this + every { build() } returns mockk() + } + every { anyConstructed().addCapability(any()) } returns builder + networkConnectionManager = NetworkConnectionManagerImpl( + context = context, + dispatcherManager = fakeDispatcherManager, + ) + } + + @AfterEach + fun tearDown() { + unmockkConstructor(NetworkRequest.Builder::class) + } + @Test fun `isNetworkConnected should return false if no active network`() { - val connectivityManager: ConnectivityManager = mockk { - every { activeNetwork } returns null - every { getNetworkCapabilities(any()) } returns null - } - val networkConnectionManager = createNetworkConnectionManager(connectivityManager) - Assertions.assertFalse(networkConnectionManager.isNetworkConnected) + every { connectivityManager.activeNetwork } returns null + every { connectivityManager.getNetworkCapabilities(any()) } returns null + assertFalse(networkConnectionManager.isNetworkConnected) } @Test @@ -26,12 +73,9 @@ class NetworkConnectionManagerTest { val networkCapabilities: NetworkCapabilities = mockk { every { hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) } returns false } - val connectivityManager: ConnectivityManager = mockk { - every { activeNetwork } returns network - every { getNetworkCapabilities(network) } returns networkCapabilities - } - val networkConnectionManager = createNetworkConnectionManager(connectivityManager) - Assertions.assertFalse(networkConnectionManager.isNetworkConnected) + every { connectivityManager.activeNetwork } returns network + every { connectivityManager.getNetworkCapabilities(network) } returns networkCapabilities + assertFalse(networkConnectionManager.isNetworkConnected) } @Test @@ -40,24 +84,164 @@ class NetworkConnectionManagerTest { val networkCapabilities: NetworkCapabilities = mockk { every { hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) } returns true } - val connectivityManager: ConnectivityManager = mockk { - every { activeNetwork } returns network - every { getNetworkCapabilities(network) } returns networkCapabilities - } - val networkConnectionManager = createNetworkConnectionManager(connectivityManager) - Assertions.assertTrue(networkConnectionManager.isNetworkConnected) + every { connectivityManager.activeNetwork } returns network + every { connectivityManager.getNetworkCapabilities(network) } returns networkCapabilities + assertTrue(networkConnectionManager.isNetworkConnected) } - private fun createNetworkConnectionManager( - connectivityManager: ConnectivityManager, - ): NetworkConnectionManager { - val appContext: Context = mockk { - every { getSystemService(Context.CONNECTIVITY_SERVICE) } returns connectivityManager - } - val context: Context = mockk { - every { applicationContext } returns appContext + @Test + fun `isNetworkConnectedFlow should emit changes to the network state`() = runTest { + val network = mockk() + val capabilities = mockk { + every { signalStrength } returns -75 + every { hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) } returns true + every { hasTransport(NetworkCapabilities.TRANSPORT_WIFI) } returns false + every { hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) } returns true } + every { connectivityManager.activeNetwork } returns network - return NetworkConnectionManagerImpl(context) + networkConnectionManager + .isNetworkConnectedFlow + .test { + assertFalse(awaitItem()) + + every { connectivityManager.getNetworkCapabilities(network) } returns capabilities + networkCallback.captured.onLost(mockk()) + assertTrue(awaitItem()) + + every { + capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + } returns false + networkCallback.captured.onLinkPropertiesChanged(mockk(), mockk()) + assertFalse(awaitItem()) + } + } + + @Test + fun `networkConnection should return None if no active network`() { + every { connectivityManager.activeNetwork } returns null + every { connectivityManager.getNetworkCapabilities(any()) } returns null + assertEquals(NetworkConnection.None, networkConnectionManager.networkConnection) + } + + @Test + fun `networkConnection should return none Wifi if active network has wifi transport`() { + val network = mockk() + val capabilities = mockk { + every { hasTransport(NetworkCapabilities.TRANSPORT_WIFI) } returns true + every { signalStrength } returns -120 + } + every { connectivityManager.activeNetwork } returns network + every { connectivityManager.getNetworkCapabilities(network) } returns capabilities + assertEquals( + NetworkConnection.Wifi(strength = NetworkSignalStrength.NONE), + networkConnectionManager.networkConnection, + ) + } + + @Test + fun `networkConnection should return weak Wifi if active network has wifi transport`() { + val network = mockk() + val capabilities = mockk { + every { hasTransport(NetworkCapabilities.TRANSPORT_WIFI) } returns true + every { signalStrength } returns -100 + } + every { connectivityManager.activeNetwork } returns network + every { connectivityManager.getNetworkCapabilities(network) } returns capabilities + assertEquals( + NetworkConnection.Wifi(strength = NetworkSignalStrength.WEAK), + networkConnectionManager.networkConnection, + ) + } + + @Test + fun `networkConnection should return fair Wifi if active network has wifi transport`() { + val network = mockk() + val capabilities = mockk { + every { hasTransport(NetworkCapabilities.TRANSPORT_WIFI) } returns true + every { signalStrength } returns -90 + } + every { connectivityManager.activeNetwork } returns network + every { connectivityManager.getNetworkCapabilities(network) } returns capabilities + assertEquals( + NetworkConnection.Wifi(strength = NetworkSignalStrength.FAIR), + networkConnectionManager.networkConnection, + ) + } + + @Test + fun `networkConnection should return good Wifi if active network has wifi transport`() { + val network = mockk() + val capabilities = mockk { + every { hasTransport(NetworkCapabilities.TRANSPORT_WIFI) } returns true + every { signalStrength } returns -75 + } + every { connectivityManager.activeNetwork } returns network + every { connectivityManager.getNetworkCapabilities(network) } returns capabilities + assertEquals( + NetworkConnection.Wifi(strength = NetworkSignalStrength.GOOD), + networkConnectionManager.networkConnection, + ) + } + + @Test + fun `networkConnection should return excellent Wifi if active network has wifi transport`() { + val network = mockk() + val capabilities = mockk { + every { hasTransport(NetworkCapabilities.TRANSPORT_WIFI) } returns true + every { signalStrength } returns -50 + } + every { connectivityManager.activeNetwork } returns network + every { connectivityManager.getNetworkCapabilities(network) } returns capabilities + assertEquals( + NetworkConnection.Wifi(strength = NetworkSignalStrength.EXCELLENT), + networkConnectionManager.networkConnection, + ) + } + + @Test + fun `networkConnection should return Cellular if active network has cellular transport`() { + val network = mockk() + val capabilities = mockk { + every { hasTransport(NetworkCapabilities.TRANSPORT_WIFI) } returns false + every { hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) } returns true + } + every { connectivityManager.activeNetwork } returns network + every { connectivityManager.getNetworkCapabilities(network) } returns capabilities + assertEquals(NetworkConnection.Cellular, networkConnectionManager.networkConnection) + } + + @Test + fun `networkConnectionFlow should emit changes to the network state`() = runTest { + val network = mockk() + val capabilities = mockk { + every { signalStrength } returns -75 + every { hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) } returns true + every { hasTransport(NetworkCapabilities.TRANSPORT_WIFI) } returns false + every { hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) } returns true + } + every { connectivityManager.activeNetwork } returns network + + networkConnectionManager + .networkConnectionFlow + .test { + assertEquals(NetworkConnection.None, awaitItem()) + + every { connectivityManager.getNetworkCapabilities(network) } returns capabilities + networkCallback.captured.onCapabilitiesChanged(mockk(), mockk()) + assertEquals(NetworkConnection.Cellular, awaitItem()) + + every { + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) + } returns true + every { + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) + } returns false + networkCallback.captured.onAvailable(mockk()) + assertEquals( + NetworkConnection.Wifi(strength = NetworkSignalStrength.GOOD), + awaitItem(), + ) + } } } diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/util/FakeNetworkConnectionManager.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/util/FakeNetworkConnectionManager.kt index 8be0a4cd04..03db51ff06 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/util/FakeNetworkConnectionManager.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/util/FakeNetworkConnectionManager.kt @@ -1,7 +1,37 @@ package com.x8bit.bitwarden.data.platform.manager.util +import com.x8bit.bitwarden.data.platform.manager.model.NetworkConnection import com.x8bit.bitwarden.data.platform.manager.network.NetworkConnectionManager +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow class FakeNetworkConnectionManager( - override val isNetworkConnected: Boolean, -) : NetworkConnectionManager + isNetworkConnected: Boolean, + networkConnection: NetworkConnection, +) : NetworkConnectionManager { + private val mutableIsNetworkConnectedStateFlow = MutableStateFlow(isNetworkConnected) + private val mutableNetworkConnectionStateFlow = MutableStateFlow(networkConnection) + + var fakeIsNetworkConnected: Boolean + get() = mutableIsNetworkConnectedStateFlow.value + set(value) { + mutableIsNetworkConnectedStateFlow.value = value + } + + var fakeNetworkConnection: NetworkConnection + get() = mutableNetworkConnectionStateFlow.value + set(value) { + mutableNetworkConnectionStateFlow.value = value + } + + override val isNetworkConnected: Boolean get() = fakeIsNetworkConnected + + override val isNetworkConnectedFlow: StateFlow = + mutableIsNetworkConnectedStateFlow.asStateFlow() + + override val networkConnection: NetworkConnection get() = fakeNetworkConnection + + override val networkConnectionFlow: StateFlow = + mutableNetworkConnectionStateFlow.asStateFlow() +} diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnViewModelTest.kt index 59d11140b4..4aa72c2586 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnViewModelTest.kt @@ -18,6 +18,7 @@ import com.x8bit.bitwarden.data.auth.repository.util.generateUriForCaptcha import com.x8bit.bitwarden.data.auth.repository.util.generateUriForSso import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager import com.x8bit.bitwarden.data.platform.manager.model.FlagKey +import com.x8bit.bitwarden.data.platform.manager.model.NetworkConnection import com.x8bit.bitwarden.data.platform.manager.util.FakeNetworkConnectionManager import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository import com.x8bit.bitwarden.data.platform.repository.util.FakeEnvironmentRepository @@ -1186,7 +1187,10 @@ class EnterpriseSignOnViewModelTest : BaseViewModelTest() { environmentRepository = environmentRepository, featureFlagManager = featureFlagManager, generatorRepository = generatorRepository, - networkConnectionManager = FakeNetworkConnectionManager(isNetworkConnected), + networkConnectionManager = FakeNetworkConnectionManager( + isNetworkConnected = isNetworkConnected, + networkConnection = NetworkConnection.Cellular, + ), savedStateHandle = savedStateHandle, ) .also {