blob: a520f6c109cca01e32fb58d5efc0cf03b839d147 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.connectivity.WifiIcons
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel.Companion.viewModelForLocation
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@SmallTest
@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class WifiViewModelTest : SysuiTestCase() {
private lateinit var underTest: WifiViewModel
@Mock private lateinit var tableLogBuffer: TableLogBuffer
@Mock private lateinit var connectivityConstants: ConnectivityConstants
@Mock private lateinit var wifiConstants: WifiConstants
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
private lateinit var connectivityRepository: FakeConnectivityRepository
private lateinit var wifiRepository: FakeWifiRepository
private lateinit var interactor: WifiInteractor
private lateinit var airplaneModeViewModel: AirplaneModeViewModel
private val shouldShowSignalSpacerProviderFlow = MutableStateFlow(false)
private val testScope = TestScope()
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
airplaneModeRepository = FakeAirplaneModeRepository()
connectivityRepository = FakeConnectivityRepository()
wifiRepository = FakeWifiRepository()
wifiRepository.setIsWifiEnabled(true)
interactor =
WifiInteractorImpl(connectivityRepository, wifiRepository, testScope.backgroundScope)
airplaneModeViewModel =
AirplaneModeViewModelImpl(
AirplaneModeInteractor(
airplaneModeRepository,
connectivityRepository,
),
tableLogBuffer,
testScope.backgroundScope,
)
createAndSetViewModel()
}
// See [WifiViewModelIconParameterizedTest] for additional view model tests.
// Note on testing: [WifiViewModel] exposes 3 different instances of
// [LocationBasedWifiViewModel]. In practice, these 3 different instances will get the exact
// same data for icon, activity, etc. flows. So, most of these tests will test just one of the
// instances. There are also some tests that verify all 3 instances received the same data.
@Test
fun wifiIcon_allLocationViewModelsReceiveSameData() =
testScope.runTest {
val home = viewModelForLocation(underTest, StatusBarLocation.HOME)
val keyguard = viewModelForLocation(underTest, StatusBarLocation.KEYGUARD)
val qs = viewModelForLocation(underTest, StatusBarLocation.QS)
val latestHome by collectLastValue(home.wifiIcon)
val latestKeyguard by collectLastValue(keyguard.wifiIcon)
val latestQs by collectLastValue(qs.wifiIcon)
wifiRepository.setWifiNetwork(
WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 1)
)
assertThat(latestHome).isInstanceOf(WifiIcon.Visible::class.java)
assertThat(latestHome).isEqualTo(latestKeyguard)
assertThat(latestKeyguard).isEqualTo(latestQs)
}
@Test
fun wifiIcon_validHotspot_hotspotIconNotShown() =
testScope.runTest {
val latest by collectLastValue(underTest.wifiIcon)
// Even WHEN the network has a valid hotspot type
wifiRepository.setWifiNetwork(
WifiNetworkModel.Active(
NETWORK_ID,
isValidated = true,
level = 1,
hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.LAPTOP,
)
)
// THEN the hotspot icon is not used for the status bar icon, and the typical wifi icon
// is used instead
assertThat(latest).isInstanceOf(WifiIcon.Visible::class.java)
assertThat((latest as WifiIcon.Visible).res).isEqualTo(WifiIcons.WIFI_FULL_ICONS[1])
}
@Test
fun activity_showActivityConfigFalse_outputsFalse() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(false)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val activityIn by collectLastValue(underTest.isActivityInViewVisible)
val activityOut by collectLastValue(underTest.isActivityOutViewVisible)
val activityContainer by collectLastValue(underTest.isActivityContainerVisible)
// Verify that on launch, we receive false.
assertThat(activityIn).isFalse()
assertThat(activityOut).isFalse()
assertThat(activityContainer).isFalse()
}
@Test
fun activity_showActivityConfigFalse_noUpdatesReceived() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(false)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val activityIn by collectLastValue(underTest.isActivityInViewVisible)
val activityOut by collectLastValue(underTest.isActivityOutViewVisible)
val activityContainer by collectLastValue(underTest.isActivityContainerVisible)
// WHEN we update the repo to have activity
val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true)
wifiRepository.setWifiActivity(activity)
// THEN we didn't update to the new activity (because our config is false)
assertThat(activityIn).isFalse()
assertThat(activityOut).isFalse()
assertThat(activityContainer).isFalse()
}
@Test
fun activity_nullSsid_outputsFalse() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(
WifiNetworkModel.Active(NETWORK_ID, ssid = null, level = 1)
)
val activityIn by collectLastValue(underTest.isActivityInViewVisible)
val activityOut by collectLastValue(underTest.isActivityOutViewVisible)
val activityContainer by collectLastValue(underTest.isActivityContainerVisible)
// WHEN we update the repo to have activity
val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true)
wifiRepository.setWifiActivity(activity)
// THEN we still output false because our network's SSID is null
assertThat(activityIn).isFalse()
assertThat(activityOut).isFalse()
assertThat(activityContainer).isFalse()
}
@Test
fun activity_allLocationViewModelsReceiveSameData() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val home = viewModelForLocation(underTest, StatusBarLocation.HOME)
val keyguard = viewModelForLocation(underTest, StatusBarLocation.KEYGUARD)
val qs = viewModelForLocation(underTest, StatusBarLocation.QS)
val latestHome by collectLastValue(home.isActivityInViewVisible)
val latestKeyguard by collectLastValue(keyguard.isActivityInViewVisible)
val latestQs by collectLastValue(qs.isActivityInViewVisible)
val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true)
wifiRepository.setWifiActivity(activity)
assertThat(latestHome).isTrue()
assertThat(latestKeyguard).isTrue()
assertThat(latestQs).isTrue()
}
@Test
fun activityIn_hasActivityInTrue_outputsTrue() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val latest by collectLastValue(underTest.isActivityInViewVisible)
val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = false)
wifiRepository.setWifiActivity(activity)
assertThat(latest).isTrue()
}
@Test
fun activityIn_hasActivityInFalse_outputsFalse() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val latest by collectLastValue(underTest.isActivityInViewVisible)
val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = true)
wifiRepository.setWifiActivity(activity)
assertThat(latest).isFalse()
}
@Test
fun activityOut_hasActivityOutTrue_outputsTrue() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val latest by collectLastValue(underTest.isActivityOutViewVisible)
val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = true)
wifiRepository.setWifiActivity(activity)
assertThat(latest).isTrue()
}
@Test
fun activityOut_hasActivityOutFalse_outputsFalse() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val latest by collectLastValue(underTest.isActivityOutViewVisible)
val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = false)
wifiRepository.setWifiActivity(activity)
assertThat(latest).isFalse()
}
@Test
fun activityContainer_hasActivityInTrue_outputsTrue() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val latest by collectLastValue(underTest.isActivityContainerVisible)
val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = false)
wifiRepository.setWifiActivity(activity)
assertThat(latest).isTrue()
}
@Test
fun activityContainer_hasActivityOutTrue_outputsTrue() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val latest by collectLastValue(underTest.isActivityContainerVisible)
val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = true)
wifiRepository.setWifiActivity(activity)
assertThat(latest).isTrue()
}
@Test
fun activityContainer_inAndOutTrue_outputsTrue() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val latest by collectLastValue(underTest.isActivityContainerVisible)
val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true)
wifiRepository.setWifiActivity(activity)
assertThat(latest).isTrue()
}
@Test
fun activityContainer_inAndOutFalse_outputsFalse() =
testScope.runTest {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
val latest by collectLastValue(underTest.isActivityContainerVisible)
val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
wifiRepository.setWifiActivity(activity)
assertThat(latest).isFalse()
}
@Test
fun airplaneSpacer_notAirplaneMode_outputsFalse() =
testScope.runTest {
val latest by collectLastValue(underTest.isAirplaneSpacerVisible)
airplaneModeRepository.setIsAirplaneMode(false)
assertThat(latest).isFalse()
}
@Test
fun airplaneSpacer_airplaneForceHidden_outputsFalse() =
testScope.runTest {
val latest by collectLastValue(underTest.isAirplaneSpacerVisible)
airplaneModeRepository.setIsAirplaneMode(true)
connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.AIRPLANE))
assertThat(latest).isFalse()
}
@Test
fun airplaneSpacer_airplaneIconVisible_outputsTrue() =
testScope.runTest {
val latest by collectLastValue(underTest.isAirplaneSpacerVisible)
airplaneModeRepository.setIsAirplaneMode(true)
assertThat(latest).isTrue()
}
@Test
fun signalSpacer_firstSubNotShowingNetworkTypeIcon_outputsFalse() =
testScope.runTest {
val latest by collectLastValue(underTest.isSignalSpacerVisible)
shouldShowSignalSpacerProviderFlow.value = false
assertThat(latest).isFalse()
}
@Test
fun signalSpacer_firstSubIsShowingNetworkTypeIcon_outputsTrue() =
testScope.runTest {
val latest by collectLastValue(underTest.isSignalSpacerVisible)
shouldShowSignalSpacerProviderFlow.value = true
assertThat(latest).isTrue()
}
private fun createAndSetViewModel() {
// [WifiViewModel] creates its flows as soon as it's instantiated, and some of those flow
// creations rely on certain config values that we mock out in individual tests. This method
// allows tests to create the view model only after those configs are correctly set up.
underTest =
WifiViewModel(
airplaneModeViewModel,
{ shouldShowSignalSpacerProviderFlow },
connectivityConstants,
context,
tableLogBuffer,
interactor,
testScope.backgroundScope,
wifiConstants,
)
}
companion object {
private const val NETWORK_ID = 2
private val ACTIVE_VALID_WIFI_NETWORK =
WifiNetworkModel.Active(NETWORK_ID, ssid = "AB", level = 1)
}
}