1 /*
2  * Copyright (C) 2023 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.settings.accessibility;
18 
19 import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
20 import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
21 import static com.android.settings.accessibility.FlashNotificationsUtil.DEFAULT_SCREEN_FLASH_COLOR;
22 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
23 
24 import static com.google.common.truth.Truth.assertThat;
25 
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.ArgumentMatchers.anyString;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.Mockito.when;
30 
31 import android.content.ContentResolver;
32 import android.content.Context;
33 import android.graphics.Color;
34 import android.provider.Settings;
35 
36 import androidx.fragment.app.Fragment;
37 import androidx.fragment.app.FragmentActivity;
38 import androidx.fragment.app.FragmentManager;
39 import androidx.preference.Preference;
40 import androidx.preference.PreferenceScreen;
41 
42 import com.android.settings.R;
43 
44 import org.junit.After;
45 import org.junit.Before;
46 import org.junit.Rule;
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 import org.mockito.Mock;
50 import org.mockito.MockitoAnnotations;
51 import org.mockito.junit.MockitoJUnit;
52 import org.mockito.junit.MockitoRule;
53 import org.robolectric.Robolectric;
54 import org.robolectric.RobolectricTestRunner;
55 import org.robolectric.annotation.Config;
56 import org.robolectric.annotation.Implementation;
57 import org.robolectric.annotation.Implements;
58 import org.robolectric.annotation.Resetter;
59 
60 import java.util.function.Consumer;
61 
62 @RunWith(RobolectricTestRunner.class)
63 @Config(shadows = {
64         ScreenFlashNotificationPreferenceControllerTest
65                 .ShadowScreenFlashNotificationColorDialogFragment.class,
66         ShadowFlashNotificationsUtils.class,
67         com.android.settings.testutils.shadow.ShadowFragment.class,
68 })
69 public class ScreenFlashNotificationPreferenceControllerTest {
70     private static final String PREFERENCE_KEY = "preference_key";
71     private static final String COLOR_DESCRIPTION_TEXT = "Colorful";
72 
73     @Rule
74     public MockitoRule mMockitoRule = MockitoJUnit.rule();
75 
76     @Mock
77     private PreferenceScreen mPreferenceScreen;
78     @Mock
79     private Preference mPreference;
80     @Mock
81     private Fragment mParentFragment;
82     @Mock
83     private FragmentManager mFragmentManager;
84     @Mock
85     private ScreenFlashNotificationColorDialogFragment mDialogFragment;
86 
87     private ScreenFlashNotificationPreferenceController mController;
88     private ContentResolver mContentResolver;
89 
90     @Before
setUp()91     public void setUp() {
92         MockitoAnnotations.initMocks(this);
93         FragmentActivity fragmentActivity = Robolectric.setupActivity(FragmentActivity.class);
94         Context context = fragmentActivity.getApplicationContext();
95         ShadowScreenFlashNotificationColorDialogFragment.setInstance(mDialogFragment);
96         ShadowFlashNotificationsUtils.setColorDescriptionText(COLOR_DESCRIPTION_TEXT);
97 
98         mContentResolver = context.getContentResolver();
99         mController = new ScreenFlashNotificationPreferenceController(context, PREFERENCE_KEY);
100         when(mPreferenceScreen.findPreference(PREFERENCE_KEY)).thenReturn(mPreference);
101         when(mPreference.getKey()).thenReturn(PREFERENCE_KEY);
102         mController.setParentFragment(mParentFragment);
103         when(mParentFragment.getParentFragmentManager()).thenReturn(mFragmentManager);
104     }
105 
106     @After
tearDown()107     public void tearDown() {
108         ShadowScreenFlashNotificationColorDialogFragment.reset();
109     }
110 
111     @Test
getAvailabilityStatus()112     public void getAvailabilityStatus() {
113         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
114     }
115 
116     @Test
isChecked_setOff_assertFalse()117     public void isChecked_setOff_assertFalse() {
118         Settings.System.putInt(mContentResolver, Settings.System.SCREEN_FLASH_NOTIFICATION, OFF);
119         assertThat(mController.isChecked()).isFalse();
120     }
121 
122     @Test
isChecked_setOn_assertTrue()123     public void isChecked_setOn_assertTrue() {
124         Settings.System.putInt(mContentResolver, Settings.System.SCREEN_FLASH_NOTIFICATION, ON);
125         assertThat(mController.isChecked()).isTrue();
126     }
127 
128     @Test
setChecked_whenTransparentColor_setTrue_assertNotTransparentColor()129     public void setChecked_whenTransparentColor_setTrue_assertNotTransparentColor() {
130         Settings.System.putInt(mContentResolver,
131                 Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, Color.TRANSPARENT);
132         mController.setChecked(true);
133         assertThat(Settings.System.getInt(mContentResolver,
134                 Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, 0)).isEqualTo(
135                 DEFAULT_SCREEN_FLASH_COLOR);
136     }
137 
138     @Test
setChecked_whenNotTransparent_setTrue_assertSameColor()139     public void setChecked_whenNotTransparent_setTrue_assertSameColor() {
140         Settings.System.putInt(mContentResolver,
141                 Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, 0x4D0000FF);
142         mController.setChecked(true);
143         assertThat(Settings.System.getInt(mContentResolver,
144                 Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, 0))
145                 .isEqualTo(0x4D0000FF);
146     }
147 
148     @Test
setChecked_setTrue_assertOn()149     public void setChecked_setTrue_assertOn() {
150         mController.setChecked(true);
151         assertThat(
152                 Settings.System.getInt(mContentResolver, Settings.System.SCREEN_FLASH_NOTIFICATION,
153                         OFF)).isEqualTo(ON);
154     }
155 
156     @Test
setChecked_setFalse_assertOff()157     public void setChecked_setFalse_assertOff() {
158         mController.setChecked(false);
159         assertThat(
160                 Settings.System.getInt(mContentResolver, Settings.System.SCREEN_FLASH_NOTIFICATION,
161                         OFF)).isEqualTo(OFF);
162     }
163 
164     @Test
getSliceHighlightMenuRes()165     public void getSliceHighlightMenuRes() {
166         assertThat(mController.getSliceHighlightMenuRes())
167                 .isEqualTo(R.string.menu_key_accessibility);
168     }
169 
170     @Test
getSummary()171     public void getSummary() {
172         assertThat(mController.getSummary()).isEqualTo(COLOR_DESCRIPTION_TEXT);
173     }
174 
175     @Test
displayPreference()176     public void displayPreference() {
177         mController.displayPreference(mPreferenceScreen);
178         verify(mPreference).setSummary(COLOR_DESCRIPTION_TEXT);
179     }
180 
181     @Test
handlePreferenceTreeClick()182     public void handlePreferenceTreeClick() {
183         mController.handlePreferenceTreeClick(mPreference);
184         verify(mDialogFragment).show(any(FragmentManager.class), anyString());
185     }
186 
187     /**
188      * Note: Actually, shadow of ScreenFlashNotificationColorDialogFragment will not be used.
189      * Instance that returned with {@link #getInstance} should be set with {@link #setInstance}
190      */
191     @Implements(ScreenFlashNotificationColorDialogFragment.class)
192     public static class ShadowScreenFlashNotificationColorDialogFragment {
193         static ScreenFlashNotificationColorDialogFragment sInstance = null;
194 
195         @Implementation
getInstance( int initialColor, Consumer<Integer> colorConsumer)196         protected static ScreenFlashNotificationColorDialogFragment getInstance(
197                 int initialColor, Consumer<Integer> colorConsumer) {
198             return sInstance;
199         }
200 
setInstance(ScreenFlashNotificationColorDialogFragment instance)201         public static void setInstance(ScreenFlashNotificationColorDialogFragment instance) {
202             sInstance = instance;
203         }
204 
205         @Resetter
reset()206         public static void reset() {
207             sInstance = null;
208         }
209     }
210 }
211