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.bluetooth;
18 
19 import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.Mockito.mock;
25 import static org.mockito.Mockito.spy;
26 import static org.mockito.Mockito.verify;
27 
28 import android.app.PendingIntent;
29 import android.content.ContentResolver;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.net.Uri;
33 
34 import androidx.core.graphics.drawable.IconCompat;
35 import androidx.lifecycle.LiveData;
36 import androidx.preference.Preference;
37 import androidx.preference.PreferenceCategory;
38 import androidx.slice.Slice;
39 import androidx.slice.SliceViewManager;
40 import androidx.slice.builders.ListBuilder;
41 import androidx.slice.builders.ListBuilder.RowBuilder;
42 import androidx.slice.builders.SliceAction;
43 import androidx.test.annotation.UiThreadTest;
44 import androidx.test.core.app.ApplicationProvider;
45 import androidx.test.ext.junit.runners.AndroidJUnit4;
46 
47 import org.junit.Before;
48 import org.junit.Rule;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.mockito.ArgumentCaptor;
52 import org.mockito.Captor;
53 import org.mockito.Mock;
54 import org.mockito.junit.MockitoJUnit;
55 import org.mockito.junit.MockitoRule;
56 
57 @RunWith(AndroidJUnit4.class)
58 public class BlockingPrefWithSliceControllerTest {
59     private static final String KEY = "bt_device_slice_category";
60     private static final String TEST_URI_AUTHORITY = "com.android.settings";
61     private static final String TEST_EXTRA_INTENT = "EXTRA_INTENT";
62     private static final String TEST_EXTRA_PENDING_INTENT = "EXTRA_PENDING_INTENT";
63     private static final String TEST_INTENT_ACTION = "test";
64     private static final String TEST_PENDING_INTENT_ACTION = "test";
65     private static final String TEST_SLICE_TITLE = "Test Title";
66     private static final String TEST_SLICE_SUBTITLE = "Test Subtitle";
67     private static final String FAKE_ACTION = "fake_action";
68 
69     @Rule
70     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
71 
72     @Mock
73     private LiveData<Slice> mLiveData;
74     @Mock
75     private PreferenceCategory mPreferenceCategory;
76     @Captor
77     ArgumentCaptor<Preference> mPreferenceArgumentCaptor;
78 
79     private Context mContext;
80     private BlockingPrefWithSliceController mController;
81     private Uri mUri;
82 
83     @Before
setUp()84     public void setUp() {
85         mContext = spy(ApplicationProvider.getApplicationContext());
86         mController = spy(new BlockingPrefWithSliceController(mContext, KEY));
87         mController.mLiveData = mLiveData;
88         mController.mExtraIntent = TEST_EXTRA_INTENT;
89         mController.mExtraPendingIntent = TEST_EXTRA_PENDING_INTENT;
90         mController.mSliceIntentAction = TEST_INTENT_ACTION;
91         mController.mSlicePendingIntentAction = TEST_PENDING_INTENT_ACTION;
92         mController.mPreferenceCategory = mPreferenceCategory;
93         mUri = Uri.EMPTY;
94     }
95 
96     @Test
isAvailable_uriNull_returnFalse()97     public void isAvailable_uriNull_returnFalse() {
98         assertThat(mController.isAvailable()).isFalse();
99     }
100 
101     @Test
102     @UiThreadTest
isAvailable_uriNotNull_returnTrue()103     public void isAvailable_uriNotNull_returnTrue() {
104         mController.setSliceUri(mUri);
105 
106         assertThat(mController.isAvailable()).isTrue();
107     }
108 
109     @Test
onStart_registerObserver()110     public void onStart_registerObserver() {
111         mController.onStart();
112 
113         verify(mLiveData).observeForever(mController);
114     }
115 
116     @Test
onStop_unregisterObserver()117     public void onStop_unregisterObserver() {
118         mController.onStop();
119 
120         verify(mLiveData).removeObserver(mController);
121     }
122 
123     @Test
onChanged_nullSlice_updateSlice()124     public void onChanged_nullSlice_updateSlice() {
125         mController.onChanged(null);
126 
127         verify(mController).updatePreferenceFromSlice(null);
128     }
129 
130     @Test
onChanged_testSlice_updateSlice()131     public void onChanged_testSlice_updateSlice() {
132         mController.onChanged(buildTestSlice());
133 
134         verify(mController.mPreferenceCategory).addPreference(any());
135     }
136 
137     @Test
onChanged_sliceWithoutValidIntent_makePreferenceUnselectable()138     public void onChanged_sliceWithoutValidIntent_makePreferenceUnselectable() {
139         mController.onChanged(buildTestSlice());
140 
141         verify(mController.mPreferenceCategory).addPreference(mPreferenceArgumentCaptor.capture());
142         assertThat(mPreferenceArgumentCaptor.getValue().isSelectable()).isFalse();
143     }
144 
buildTestSlice()145     private Slice buildTestSlice() {
146         Uri uri =
147                 new Uri.Builder()
148                         .scheme(ContentResolver.SCHEME_CONTENT)
149                         .authority(TEST_URI_AUTHORITY)
150                         .build();
151         SliceViewManager.getInstance(mContext).pinSlice(uri);
152         ListBuilder listBuilder = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
153         IconCompat icon = mock(IconCompat.class);
154         listBuilder.addRow(
155                 new RowBuilder()
156                         .setTitleItem(icon, ICON_IMAGE)
157                         .setTitle(TEST_SLICE_TITLE)
158                         .setSubtitle(TEST_SLICE_SUBTITLE)
159                         .setPrimaryAction(
160                                 SliceAction.create(
161                                         PendingIntent.getActivity(
162                                                 mContext,
163                                                 /*requestCode= */ 0,
164                                                 new Intent(FAKE_ACTION),
165                                                 PendingIntent.FLAG_UPDATE_CURRENT
166                                                         | PendingIntent.FLAG_IMMUTABLE),
167                                         icon,
168                                         ICON_IMAGE,
169                                         "")));
170         return listBuilder.build();
171     }
172 }
173