1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel 18 19 import android.app.Flags 20 import android.app.NotificationManager.Policy 21 import android.platform.test.annotations.DisableFlags 22 import android.platform.test.annotations.EnableFlags 23 import android.platform.test.flag.junit.FlagsParameterization 24 import android.provider.Settings 25 import android.service.notification.ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST 26 import androidx.test.filters.SmallTest 27 import com.android.settingslib.notification.data.repository.updateNotificationPolicy 28 import com.android.settingslib.notification.modes.TestModeBuilder 29 import com.android.systemui.SysuiTestCase 30 import com.android.systemui.coroutines.collectLastValue 31 import com.android.systemui.flags.andSceneContainer 32 import com.android.systemui.kosmos.testScope 33 import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRepository 34 import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository 35 import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix 36 import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor 37 import com.android.systemui.statusbar.policy.data.repository.zenModeRepository 38 import com.android.systemui.testKosmos 39 import com.google.common.truth.Truth.assertThat 40 import kotlinx.coroutines.ExperimentalCoroutinesApi 41 import kotlinx.coroutines.test.runCurrent 42 import kotlinx.coroutines.test.runTest 43 import org.junit.Test 44 import org.junit.runner.RunWith 45 import platform.test.runner.parameterized.ParameterizedAndroidJunit4 46 import platform.test.runner.parameterized.Parameters 47 48 @OptIn(ExperimentalCoroutinesApi::class) 49 @RunWith(ParameterizedAndroidJunit4::class) 50 @SmallTest 51 @EnableFlags(FooterViewRefactor.FLAG_NAME) 52 class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { 53 private val kosmos = testKosmos() 54 private val testScope = kosmos.testScope 55 private val zenModeRepository = kosmos.zenModeRepository 56 private val activeNotificationListRepository = kosmos.activeNotificationListRepository 57 private val fakeSecureSettingsRepository = kosmos.fakeSecureSettingsRepository 58 59 private val underTest = kosmos.emptyShadeViewModel 60 61 companion object { 62 @JvmStatic 63 @Parameters(name = "{0}") getParamsnull64 fun getParams(): List<FlagsParameterization> { 65 return FlagsParameterization.allCombinationsOf().andSceneContainer() 66 } 67 } 68 69 init { 70 mSetFlagsRule.setFlagsParameterization(flags) 71 } 72 73 @Test areNotificationsHiddenInShade_truenull74 fun areNotificationsHiddenInShade_true() = 75 testScope.runTest { 76 val hidden by collectLastValue(underTest.areNotificationsHiddenInShade) 77 78 zenModeRepository.updateNotificationPolicy( 79 suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST 80 ) 81 zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) 82 runCurrent() 83 84 assertThat(hidden).isTrue() 85 } 86 87 @Test areNotificationsHiddenInShade_falsenull88 fun areNotificationsHiddenInShade_false() = 89 testScope.runTest { 90 val hidden by collectLastValue(underTest.areNotificationsHiddenInShade) 91 92 zenModeRepository.updateNotificationPolicy( 93 suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST 94 ) 95 zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_OFF) 96 runCurrent() 97 98 assertThat(hidden).isFalse() 99 } 100 101 @Test hasFilteredOutSeenNotifications_truenull102 fun hasFilteredOutSeenNotifications_true() = 103 testScope.runTest { 104 val hasFilteredNotifs by collectLastValue(underTest.hasFilteredOutSeenNotifications) 105 106 activeNotificationListRepository.hasFilteredOutSeenNotifications.value = true 107 runCurrent() 108 109 assertThat(hasFilteredNotifs).isTrue() 110 } 111 112 @Test hasFilteredOutSeenNotifications_falsenull113 fun hasFilteredOutSeenNotifications_false() = 114 testScope.runTest { 115 val hasFilteredNotifs by collectLastValue(underTest.hasFilteredOutSeenNotifications) 116 117 activeNotificationListRepository.hasFilteredOutSeenNotifications.value = false 118 runCurrent() 119 120 assertThat(hasFilteredNotifs).isFalse() 121 } 122 123 @Test 124 @EnableFlags(ModesEmptyShadeFix.FLAG_NAME) 125 @DisableFlags(Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API) text_changesWhenNotifsHiddenInShadenull126 fun text_changesWhenNotifsHiddenInShade() = 127 testScope.runTest { 128 val text by collectLastValue(underTest.text) 129 130 zenModeRepository.updateNotificationPolicy( 131 suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST 132 ) 133 zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_OFF) 134 runCurrent() 135 136 assertThat(text).isEqualTo("No notifications") 137 138 zenModeRepository.updateNotificationPolicy( 139 suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST 140 ) 141 zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) 142 runCurrent() 143 144 assertThat(text).isEqualTo("Notifications paused by Do Not Disturb") 145 } 146 147 @Test 148 @EnableFlags(ModesEmptyShadeFix.FLAG_NAME, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API) text_reflectsModesHidingNotificationsnull149 fun text_reflectsModesHidingNotifications() = 150 testScope.runTest { 151 val text by collectLastValue(underTest.text) 152 153 assertThat(text).isEqualTo("No notifications") 154 155 zenModeRepository.addMode( 156 TestModeBuilder() 157 .setId("Do not disturb") 158 .setName("Do not disturb") 159 .setActive(true) 160 .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false) 161 .build() 162 ) 163 runCurrent() 164 assertThat(text).isEqualTo("Notifications paused by Do not disturb") 165 166 zenModeRepository.addMode( 167 TestModeBuilder() 168 .setId("Work") 169 .setName("Work") 170 .setActive(true) 171 .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false) 172 .build() 173 ) 174 runCurrent() 175 assertThat(text).isEqualTo("Notifications paused by Do not disturb and one other mode") 176 177 zenModeRepository.addMode( 178 TestModeBuilder() 179 .setId("Gym") 180 .setName("Gym") 181 .setActive(true) 182 .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false) 183 .build() 184 ) 185 runCurrent() 186 assertThat(text).isEqualTo("Notifications paused by Do not disturb and 2 other modes") 187 188 zenModeRepository.deactivateMode("Do not disturb") 189 zenModeRepository.deactivateMode("Work") 190 runCurrent() 191 assertThat(text).isEqualTo("Notifications paused by Gym") 192 } 193 194 @Test 195 @EnableFlags(ModesEmptyShadeFix.FLAG_NAME) footer_isVisibleWhenSeenNotifsAreFilteredOutnull196 fun footer_isVisibleWhenSeenNotifsAreFilteredOut() = 197 testScope.runTest { 198 val footerVisible by collectLastValue(underTest.footer.isVisible) 199 200 activeNotificationListRepository.hasFilteredOutSeenNotifications.value = false 201 runCurrent() 202 203 assertThat(footerVisible).isFalse() 204 205 activeNotificationListRepository.hasFilteredOutSeenNotifications.value = true 206 runCurrent() 207 208 assertThat(footerVisible).isTrue() 209 } 210 211 @Test 212 @EnableFlags(ModesEmptyShadeFix.FLAG_NAME, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API) onClick_whenHistoryDisabled_leadsToSettingsPagenull213 fun onClick_whenHistoryDisabled_leadsToSettingsPage() = 214 testScope.runTest { 215 val onClick by collectLastValue(underTest.onClick) 216 runCurrent() 217 218 fakeSecureSettingsRepository.setInt(Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0) 219 220 assertThat(onClick?.targetIntent?.action) 221 .isEqualTo(Settings.ACTION_NOTIFICATION_SETTINGS) 222 assertThat(onClick?.backStack).isEmpty() 223 } 224 225 @Test 226 @EnableFlags(ModesEmptyShadeFix.FLAG_NAME, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API) onClick_whenHistoryEnabled_leadsToHistoryPagenull227 fun onClick_whenHistoryEnabled_leadsToHistoryPage() = 228 testScope.runTest { 229 val onClick by collectLastValue(underTest.onClick) 230 runCurrent() 231 232 fakeSecureSettingsRepository.setInt(Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 1) 233 234 assertThat(onClick?.targetIntent?.action) 235 .isEqualTo(Settings.ACTION_NOTIFICATION_HISTORY) 236 assertThat(onClick?.backStack?.map { it.action }) 237 .containsExactly(Settings.ACTION_NOTIFICATION_SETTINGS) 238 } 239 240 @Test 241 @EnableFlags(ModesEmptyShadeFix.FLAG_NAME, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API) onClick_whenOneModeHidingNotifications_leadsToModeSettingsnull242 fun onClick_whenOneModeHidingNotifications_leadsToModeSettings() = 243 testScope.runTest { 244 val onClick by collectLastValue(underTest.onClick) 245 runCurrent() 246 247 zenModeRepository.addMode( 248 TestModeBuilder() 249 .setId("ID") 250 .setActive(true) 251 .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false) 252 .build() 253 ) 254 runCurrent() 255 256 assertThat(onClick?.targetIntent?.action) 257 .isEqualTo(Settings.ACTION_AUTOMATIC_ZEN_RULE_SETTINGS) 258 assertThat( 259 onClick?.targetIntent?.extras?.getString(Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID) 260 ) 261 .isEqualTo("ID") 262 assertThat(onClick?.backStack?.map { it.action }) 263 .containsExactly(Settings.ACTION_ZEN_MODE_SETTINGS) 264 } 265 266 @Test 267 @EnableFlags(ModesEmptyShadeFix.FLAG_NAME, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API) onClick_whenMultipleModesHidingNotifications_leadsToGeneralModesSettingsnull268 fun onClick_whenMultipleModesHidingNotifications_leadsToGeneralModesSettings() = 269 testScope.runTest { 270 val onClick by collectLastValue(underTest.onClick) 271 runCurrent() 272 273 zenModeRepository.addMode( 274 TestModeBuilder() 275 .setActive(true) 276 .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false) 277 .build() 278 ) 279 zenModeRepository.addMode( 280 TestModeBuilder() 281 .setActive(true) 282 .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false) 283 .build() 284 ) 285 runCurrent() 286 287 assertThat(onClick?.targetIntent?.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS) 288 assertThat(onClick?.backStack).isEmpty() 289 } 290 } 291