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