blob: 9e0fe783619b09e2f944afe8dd265f61e98a1614 [file] [log] [blame]
Roshan Agrawald5f8a232018-11-08 19:44:24 -08001/*
2 * Copyright (C) 2018 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
17package com.android.car.settings.accounts;
18
19import static com.google.common.truth.Truth.assertThat;
20
21import static org.mockito.ArgumentMatchers.any;
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080022import static org.mockito.ArgumentMatchers.eq;
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080023import static org.mockito.Mockito.verify;
Roshan Agrawald5f8a232018-11-08 19:44:24 -080024import static org.robolectric.RuntimeEnvironment.application;
25
26import android.accounts.Account;
27import android.content.ContentResolver;
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080028import android.content.Context;
Roshan Agrawald5f8a232018-11-08 19:44:24 -080029import android.content.SyncAdapterType;
30import android.content.SyncInfo;
31import android.content.SyncStatusInfo;
32import android.content.pm.PackageInfo;
Roshan Agrawald5f8a232018-11-08 19:44:24 -080033import android.content.pm.ProviderInfo;
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080034import android.os.Bundle;
Roshan Agrawald5f8a232018-11-08 19:44:24 -080035import android.os.UserHandle;
36
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080037import androidx.lifecycle.Lifecycle;
Roshan Agrawald5f8a232018-11-08 19:44:24 -080038import androidx.preference.Preference;
Roshan Agrawald5f8a232018-11-08 19:44:24 -080039
40import com.android.car.settings.CarSettingsRobolectricTestRunner;
41import com.android.car.settings.R;
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080042import com.android.car.settings.common.LogicalPreferenceGroup;
43import com.android.car.settings.common.PreferenceControllerTestHelper;
44import com.android.car.settings.testutils.ShadowAccountManager;
Roshan Agrawald5f8a232018-11-08 19:44:24 -080045import com.android.car.settings.testutils.ShadowApplicationPackageManager;
46import com.android.car.settings.testutils.ShadowContentResolver;
47
48import org.junit.After;
49import org.junit.Before;
50import org.junit.Test;
51import org.junit.runner.RunWith;
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080052import org.mockito.Mock;
Roshan Agrawald5f8a232018-11-08 19:44:24 -080053import org.mockito.MockitoAnnotations;
54import org.robolectric.Shadows;
55import org.robolectric.annotation.Config;
56import org.robolectric.shadow.api.Shadow;
57
58import java.util.ArrayList;
59import java.util.Date;
60import java.util.List;
61
62/**
63 * Unit test for {@link AccountSyncDetailsPreferenceController}.
64 */
65@RunWith(CarSettingsRobolectricTestRunner.class)
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080066@Config(shadows = {ShadowContentResolver.class, ShadowApplicationPackageManager.class,
67 ShadowAccountManager.class})
Roshan Agrawald5f8a232018-11-08 19:44:24 -080068public class AccountSyncDetailsPreferenceControllerTest {
Roshan Agrawald5f8a232018-11-08 19:44:24 -080069 private static final int SYNCABLE = 1;
70 private static final int NOT_SYNCABLE = 0;
71
72 private static final int USER_ID = 3;
73 private static final int NOT_USER_ID = 5;
74
75 private static final String AUTHORITY = "authority";
76 private static final String ACCOUNT_TYPE = "com.acct1";
77 private static final String DIFFERENT_ACCOUNT_TYPE = "com.acct2";
78
79 private final Account mAccount = new Account("acct1", ACCOUNT_TYPE);
80 private final UserHandle mUserHandle = new UserHandle(USER_ID);
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080081 @Mock
82 ShadowContentResolver.SyncListener mMockSyncListener;
83 private Context mContext;
Roshan Agrawald5f8a232018-11-08 19:44:24 -080084 private AccountSyncDetailsPreferenceController mController;
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080085 private LogicalPreferenceGroup mPreferenceGroup;
Roshan Agrawald5f8a232018-11-08 19:44:24 -080086
87 @Before
88 public void setUp() {
89 MockitoAnnotations.initMocks(this);
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080090 mContext = application;
91 ShadowContentResolver.setSyncListener(mMockSyncListener);
Roshan Agrawald5f8a232018-11-08 19:44:24 -080092
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080093 PreferenceControllerTestHelper<AccountSyncDetailsPreferenceController> helper =
94 new PreferenceControllerTestHelper<>(mContext,
95 AccountSyncDetailsPreferenceController.class);
96 mController = helper.getController();
Roshan Agrawald5f8a232018-11-08 19:44:24 -080097 mController.setAccount(mAccount);
98 mController.setUserHandle(mUserHandle);
Roshan Agrawala6b4ec82018-11-20 15:33:37 -080099
100 mPreferenceGroup = new LogicalPreferenceGroup(mContext);
101 helper.setPreference(mPreferenceGroup);
102
103 helper.markState(Lifecycle.State.STARTED);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800104 }
105
106 @After
107 public void tearDown() {
108 ShadowContentResolver.reset();
109 }
110
111 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800112 public void refreshUi_syncAdapterDoesNotHaveSameAccountType_shouldNotBeShown() {
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800113 // Adds a sync adapter type that is visible but does not have the right account type.
114 SyncAdapterType syncAdapterType = new SyncAdapterType(AUTHORITY,
115 DIFFERENT_ACCOUNT_TYPE, /* userVisible */ true, /* supportsUploading */ true);
116 SyncAdapterType[] syncAdapters = {syncAdapterType};
117 ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
118
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800119 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800120
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800121 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800122 }
123
124 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800125 public void refreshUi_syncAdapterIsNotVisible_shouldNotBeShown() {
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800126 // Adds a sync adapter type that has the right account type but is not visible.
127 SyncAdapterType syncAdapterType = new SyncAdapterType(AUTHORITY,
128 ACCOUNT_TYPE, /* userVisible */ false, /* supportsUploading */ true);
129 SyncAdapterType[] syncAdapters = {syncAdapterType};
130 ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
131
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800132 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800133
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800134 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800135 }
136
137 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800138 public void refreshUi_syncAdapterIsNotSyncable_shouldNotBeShown() {
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800139 // Adds a sync adapter type that has the right account type and is visible.
140 SyncAdapterType syncAdapterType = new SyncAdapterType(AUTHORITY,
141 ACCOUNT_TYPE, /* userVisible */ true, /* supportsUploading */ true);
142 SyncAdapterType[] syncAdapters = {syncAdapterType};
143 ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
144 // Sets that the sync adapter to not syncable.
145 ShadowContentResolver.setIsSyncable(mAccount, AUTHORITY, /* syncable= */ NOT_SYNCABLE);
146
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800147 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800148
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800149 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800150 }
151
152 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800153 public void refreshUi_syncAdapterDoesNotHaveProviderInfo_shouldNotBeShown() {
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800154 // Adds a sync adapter type that has the right account type and is visible.
155 SyncAdapterType syncAdapterType = new SyncAdapterType(AUTHORITY,
156 ACCOUNT_TYPE, /* userVisible */ true, /* supportsUploading */ true);
157 SyncAdapterType[] syncAdapters = {syncAdapterType};
158 ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
159 // Sets that the sync adapter to syncable.
160 ShadowContentResolver.setIsSyncable(mAccount, AUTHORITY, /* syncable= */ SYNCABLE);
161
162 // However, no provider info is set for the sync adapter, so it shouldn't be visible.
163
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800164 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800165
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800166 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800167 }
168
169 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800170 public void refreshUi_providerInfoDoesNotHaveLabel_shouldNotBeShown() {
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800171 // Adds a sync adapter type that has the right account type and is visible.
172 SyncAdapterType syncAdapterType = new SyncAdapterType(AUTHORITY,
173 ACCOUNT_TYPE, /* userVisible */ true, /* supportsUploading */ true);
174 SyncAdapterType[] syncAdapters = {syncAdapterType};
175 ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
176 // Sets that the sync adapter to syncable.
177 ShadowContentResolver.setIsSyncable(mAccount, AUTHORITY, /* syncable= */ SYNCABLE);
178 // Sets provider info for the sync adapter but it does not have a label.
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800179 ProviderInfo info = new ProviderInfo();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800180 info.authority = AUTHORITY;
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800181 info.name = "";
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800182
183 ProviderInfo[] providers = {info};
184 PackageInfo packageInfo = new PackageInfo();
185 packageInfo.packageName = AUTHORITY;
186 packageInfo.providers = providers;
187 getShadowApplicationManager().addPackage(packageInfo);
188
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800189 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800190
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800191 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800192 }
193
194 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800195 public void refreshUi_providerLabelShouldBeSet() {
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800196 // Adds a sync adapter type that has the right account type and is visible.
197 SyncAdapterType syncAdapterType = new SyncAdapterType(AUTHORITY,
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800198 ACCOUNT_TYPE, /* userVisible */ true, /* supportsUploading */ true);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800199 SyncAdapterType[] syncAdapters = {syncAdapterType};
200 ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
201 // Sets that the sync adapter to syncable.
202 ShadowContentResolver.setIsSyncable(mAccount, AUTHORITY, /* syncable= */ SYNCABLE);
203 // Sets provider info for the sync adapter with a label.
James Lemieux56770fd2018-12-14 15:31:51 -0800204 ProviderInfo info = new ProviderInfo();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800205 info.authority = AUTHORITY;
James Lemieux56770fd2018-12-14 15:31:51 -0800206 info.name = "label";
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800207
208 ProviderInfo[] providers = {info};
209 PackageInfo packageInfo = new PackageInfo();
210 packageInfo.packageName = AUTHORITY;
211 packageInfo.providers = providers;
212 getShadowApplicationManager().addPackage(packageInfo);
213
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800214 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800215
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800216 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
217 Preference pref = mPreferenceGroup.getPreference(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800218 assertThat(pref.getTitle()).isEqualTo("label");
219 }
220
221 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800222 public void refreshUi_masterSyncOff_syncDisabled_shouldNotBeChecked() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800223 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800224 // Turns off master sync and automatic sync for the adapter.
225 ContentResolver.setMasterSyncAutomaticallyAsUser(/* sync= */ true, USER_ID);
226 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ false,
227 USER_ID);
228
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800229 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800230
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800231 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
232 SyncPreference pref = (SyncPreference) mPreferenceGroup.getPreference(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800233 assertThat(pref.isChecked()).isFalse();
234 }
235
236 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800237 public void refreshUi_masterSyncOn_syncDisabled_shouldBeChecked() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800238 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800239 // Turns on master sync and turns off automatic sync for the adapter.
240 ContentResolver.setMasterSyncAutomaticallyAsUser(/* sync= */ false, USER_ID);
241 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ false,
242 USER_ID);
243
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800244 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800245
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800246 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
247 SyncPreference pref = (SyncPreference) mPreferenceGroup.getPreference(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800248 assertThat(pref.isChecked()).isTrue();
249 }
250
251 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800252 public void refreshUi_masterSyncOff_syncEnabled_shouldBeChecked() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800253 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800254 // Turns off master sync and turns on automatic sync for the adapter.
255 ContentResolver.setMasterSyncAutomaticallyAsUser(/* sync= */ true, USER_ID);
256 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ true,
257 USER_ID);
258
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800259 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800260
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800261 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
262 SyncPreference pref = (SyncPreference) mPreferenceGroup.getPreference(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800263 assertThat(pref.isChecked()).isTrue();
264 }
265
266 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800267 public void refreshUi_syncDisabled_summaryShouldBeSet() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800268 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800269 // Turns off automatic sync for the the sync adapter.
270 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ false,
271 mUserHandle.getIdentifier());
272
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800273 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800274
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800275 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
276 Preference pref = mPreferenceGroup.getPreference(0);
277 assertThat(pref.getSummary()).isEqualTo(mContext.getString(R.string.sync_disabled));
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800278 }
279
280 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800281 public void refreshUi_syncEnabled_activelySyncing_summaryShouldBeSet() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800282 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800283 // Turns on automatic sync for the the sync adapter.
284 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ true,
285 mUserHandle.getIdentifier());
286 // Adds the sync adapter to the list of currently syncing adapters.
287 SyncInfo syncInfo = new SyncInfo(/* authorityId= */ 0, mAccount, AUTHORITY, /* startTime= */
288 0);
289 List<SyncInfo> syncs = new ArrayList<>();
290 syncs.add(syncInfo);
291 ShadowContentResolver.setCurrentSyncs(syncs);
292
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800293 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800294
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800295 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
296 Preference pref = mPreferenceGroup.getPreference(0);
297 assertThat(pref.getSummary()).isEqualTo(mContext.getString(R.string.sync_in_progress));
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800298 }
299
300 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800301 public void refreshUi_syncEnabled_syncHasHappened_summaryShouldBeSet() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800302 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800303 // Turns on automatic sync for the the sync adapter.
304 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ true,
305 mUserHandle.getIdentifier());
306 // Sets the sync adapter's last successful sync time.
307 SyncStatusInfo status = new SyncStatusInfo(0);
308 status.setLastSuccess(0, 83091);
309 ShadowContentResolver.setSyncStatus(mAccount, AUTHORITY, status);
310
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800311 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800312
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800313 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
314 Preference pref = mPreferenceGroup.getPreference(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800315
316 String expectedTimeString = mController.formatSyncDate(new Date(83091));
317 assertThat(pref.getSummary()).isEqualTo(
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800318 mContext.getString(R.string.last_synced, expectedTimeString));
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800319 }
320
321 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800322 public void refreshUi_activelySyncing_notInitialSync_shouldHaveActiveSyncIcon() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800323 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800324 // Adds the sync adapter to the list of currently syncing adapters.
325 SyncInfo syncInfo = new SyncInfo(/* authorityId= */ 0, mAccount, AUTHORITY, /* startTime= */
326 0);
327 List<SyncInfo> syncs = new ArrayList<>();
328 syncs.add(syncInfo);
329 ShadowContentResolver.setCurrentSyncs(syncs);
330 // Sets the sync adapter's initializing state to false (i.e. it's not performing an
331 // initial sync).
332 SyncStatusInfo status = new SyncStatusInfo(0);
333 status.initialize = false;
334 ShadowContentResolver.setSyncStatus(mAccount, AUTHORITY, status);
335
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800336 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800337
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800338 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
339 Preference pref = mPreferenceGroup.getPreference(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800340
341 assertThat(Shadows.shadowOf(pref.getIcon()).getCreatedFromResId()).isEqualTo(
Roshan Agrawal24d2d3b2018-12-28 15:45:00 -0800342 R.drawable.ic_sync_anim);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800343 }
344
345 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800346 public void refreshUi_syncPending_notInitialSync_shouldHaveActiveSyncIcon() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800347 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800348 // Sets the sync adapter's initializing state to false (i.e. it's not performing an
349 // initial sync).
350 // Also sets the the sync status to pending
351 SyncStatusInfo status = new SyncStatusInfo(0);
352 status.initialize = false;
353 status.pending = true;
354 ShadowContentResolver.setSyncStatus(mAccount, AUTHORITY, status);
355
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800356 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800357
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800358 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
359 Preference pref = mPreferenceGroup.getPreference(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800360
361 assertThat(Shadows.shadowOf(pref.getIcon()).getCreatedFromResId()).isEqualTo(
Roshan Agrawal24d2d3b2018-12-28 15:45:00 -0800362 R.drawable.ic_sync);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800363 }
364
365 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800366 public void refreshUi_syncFailed_shouldHaveProblemSyncIcon() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800367 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800368 // Turns on automatic sync for the the sync adapter.
369 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ true,
370 mUserHandle.getIdentifier());
371 // Sets the sync adapter's last failure time and message so it appears to have failed
372 // previously.
373 SyncStatusInfo status = new SyncStatusInfo(0);
374 status.lastFailureTime = 10;
375 status.lastFailureMesg = "too-many-deletions";
376 ShadowContentResolver.setSyncStatus(mAccount, AUTHORITY, status);
377
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800378 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800379
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800380 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
381 Preference pref = mPreferenceGroup.getPreference(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800382
383 assertThat(Shadows.shadowOf(pref.getIcon()).getCreatedFromResId()).isEqualTo(
384 R.drawable.ic_sync_problem);
385 }
386
387 @Test
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800388 public void refreshUi_noSyncStatus_shouldHaveNoIcon() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800389 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800390
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800391 mController.refreshUi();
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800392
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800393 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
394 Preference pref = mPreferenceGroup.getPreference(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800395
396 assertThat(pref.getIcon()).isNull();
397 assertThat(pref.isIconSpaceReserved()).isTrue();
398 }
399
400 @Test
401 public void onAccountsUpdate_correctUserId_shouldForceUpdatePreferences() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800402 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800403
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800404 mController.refreshUi();
405 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800406
407 ShadowContentResolver.reset();
408 mController.onAccountsUpdate(mUserHandle);
409
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800410 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800411 }
412
413 @Test
414 public void onAccountsUpdate_incorrectUserId_shouldNotForceUpdatePreferences() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800415 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800416
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800417 mController.refreshUi();
418 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800419
420 ShadowContentResolver.reset();
421 mController.onAccountsUpdate(new UserHandle(NOT_USER_ID));
422
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800423 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
424 }
425
426 @Test
427 public void onSyncPreferenceClicked_preferenceUnchecked_shouldSetSyncAutomaticallyOff() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800428 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800429
430 // Turns off one time sync and turns on automatic sync for the adapter so the preference is
431 // checked.
432 ContentResolver.setMasterSyncAutomaticallyAsUser(/* sync= */ true, USER_ID);
433 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ true,
434 USER_ID);
435
436 mController.refreshUi();
437 SyncPreference pref = (SyncPreference) mPreferenceGroup.getPreference(0);
438 pref.performClick();
439
440 assertThat(ContentResolver.getSyncAutomaticallyAsUser(mAccount, AUTHORITY,
441 USER_ID)).isFalse();
442 }
443
444 @Test
445 public void onSyncPreferenceClicked_preferenceUnchecked_shouldCancelSync() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800446 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800447
448 // Turns off one time sync and turns on automatic sync for the adapter so the preference is
449 // checked.
450 ContentResolver.setMasterSyncAutomaticallyAsUser(/* sync= */ true, USER_ID);
451 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ true,
452 USER_ID);
453
454 mController.refreshUi();
455 SyncPreference pref = (SyncPreference) mPreferenceGroup.getPreference(0);
456 pref.performClick();
457
458 verify(mMockSyncListener).onSyncCanceled(eq(mAccount), eq(AUTHORITY), eq(USER_ID));
459 }
460
461 @Test
462 public void onSyncPreferenceClicked_preferenceChecked_shouldSetSyncAutomaticallyOn() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800463 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800464
465 // Turns off one time sync and automatic sync for the adapter so the preference is
466 // unchecked.
467 ContentResolver.setMasterSyncAutomaticallyAsUser(/* sync= */ true, USER_ID);
468 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ false,
469 USER_ID);
470
471 mController.refreshUi();
472 SyncPreference pref = (SyncPreference) mPreferenceGroup.getPreference(0);
473 pref.performClick();
474
475 assertThat(ContentResolver.getSyncAutomaticallyAsUser(mAccount, AUTHORITY,
476 USER_ID)).isTrue();
477 }
478
479 @Test
480 public void onSyncPreferenceClicked_preferenceChecked_masterSyncOff_shouldRequestSync() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800481 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800482
483 // Turns off master sync and automatic sync for the adapter so the preference is unchecked.
484 ContentResolver.setMasterSyncAutomaticallyAsUser(/* sync= */ false, USER_ID);
485 ContentResolver.setSyncAutomaticallyAsUser(mAccount, AUTHORITY, /* sync= */ false,
486 USER_ID);
487
488 mController.refreshUi();
489 SyncPreference pref = (SyncPreference) mPreferenceGroup.getPreference(0);
490
491 // Sets master sync off
492 ContentResolver.setMasterSyncAutomaticallyAsUser(/* sync= */ false, USER_ID);
493 pref.performClick();
494
495 verify(mMockSyncListener).onSyncRequested(eq(mAccount), eq(AUTHORITY), eq(USER_ID),
496 any(Bundle.class));
497 }
498
499 @Test
500 public void onSyncPreferenceClicked_oneTimeSyncOn_shouldRequestSync() {
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800501 setUpVisibleSyncAdapters(AUTHORITY);
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800502
503 // Turns on one time sync mode
504 ContentResolver.setMasterSyncAutomaticallyAsUser(/* sync= */ false, USER_ID);
505
506 mController.refreshUi();
507 SyncPreference pref = (SyncPreference) mPreferenceGroup.getPreference(0);
508 pref.performClick();
509
510 verify(mMockSyncListener).onSyncRequested(eq(mAccount), eq(AUTHORITY), eq(USER_ID),
511 any(Bundle.class));
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800512 }
513
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800514 private void setUpVisibleSyncAdapters(String... authorities) {
515 SyncAdapterType[] syncAdapters = new SyncAdapterType[authorities.length];
516 for (int i = 0; i < authorities.length; i++) {
517 String authority = authorities[i];
518 // Adds a sync adapter type that has the right account type and is visible.
519 SyncAdapterType syncAdapterType = new SyncAdapterType(authority,
520 ACCOUNT_TYPE, /* userVisible */ true, /* supportsUploading */ true);
521 syncAdapters[i] = syncAdapterType;
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800522
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800523 // Sets that the sync adapter is syncable.
524 ShadowContentResolver.setIsSyncable(mAccount, authority, /* syncable= */ SYNCABLE);
525
526 // Sets provider info with a label for the sync adapter.
527 ProviderInfo info = new ProviderInfo();
Roshan Agrawalf731b0f2019-01-02 16:09:40 -0800528 info.authority = authority;
Roshan Agrawalba4742e2018-12-10 15:34:12 -0800529 info.name = "label";
530 ProviderInfo[] providers = {info};
531
532 PackageInfo packageInfo = new PackageInfo();
533 packageInfo.packageName = authority;
534 packageInfo.providers = providers;
535 getShadowApplicationManager().addPackage(packageInfo);
536 }
537 ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800538 }
539
540 private ShadowApplicationPackageManager getShadowApplicationManager() {
Roshan Agrawala6b4ec82018-11-20 15:33:37 -0800541 return Shadow.extract(mContext.getPackageManager());
Roshan Agrawald5f8a232018-11-08 19:44:24 -0800542 }
543}