1 /* 2 * Copyright (C) 2011 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.contacts.editor; 18 19 import static junit.framework.Assert.assertEquals; 20 import static junit.framework.Assert.assertFalse; 21 import static junit.framework.Assert.assertNull; 22 import static org.junit.Assert.assertTrue; 23 24 import android.support.test.InstrumentationRegistry; 25 import android.support.test.filters.SmallTest; 26 import android.support.test.runner.AndroidJUnit4; 27 28 import com.android.contacts.model.account.AccountType; 29 import com.android.contacts.model.account.AccountWithDataSet; 30 31 import org.junit.Before; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 35 import java.util.ArrayList; 36 import java.util.Arrays; 37 import java.util.Collections; 38 import java.util.List; 39 40 /** 41 * Test case for {@link ContactEditorUtils}. 42 * 43 * adb shell am instrument -w -e class com.android.contacts.editor.ContactEditorUtilsTest \ 44 com.android.contacts.tests/android.test.InstrumentationTestRunner 45 46 * <p>It may make sense to just delete or move these tests since the code under test just forwards 47 * calls to {@link com.android.contacts.preference.ContactsPreferences} and that logic is already 48 * covered by {@link com.android.contacts.preference.ContactsPreferencesTest} 49 * </p> 50 */ 51 @SmallTest 52 @RunWith(AndroidJUnit4.class) 53 public class ContactEditorUtilsTest { 54 private ContactEditorUtils mTarget; 55 56 private static final String TYPE1 = "type1"; 57 private static final String TYPE2 = "type2"; 58 private static final String TYPE2_EXT = "ext"; 59 60 private static final AccountWithDataSet ACCOUNT_1_A = new AccountWithDataSet("a", TYPE1, null); 61 private static final AccountWithDataSet ACCOUNT_1_B = new AccountWithDataSet("b", TYPE1, null); 62 63 private static final AccountWithDataSet ACCOUNT_2_A = new AccountWithDataSet("a", TYPE2, null); 64 private static final AccountWithDataSet ACCOUNT_2EX_A = new AccountWithDataSet( 65 "a", TYPE2, TYPE2_EXT); 66 67 @Before 68 public void setUp() throws Exception { 69 mTarget = ContactEditorUtils.create(InstrumentationRegistry.getTargetContext()); 70 71 // Clear the preferences. 72 mTarget.cleanupForTest(); 73 } 74 75 /** 76 * Test for 77 * - {@link ContactEditorUtils#saveDefaultAccount} 78 * - {@link ContactEditorUtils#getOnlyOrDefaultAccount} 79 */ 80 @Test 81 public void testSaveDefaultAccount() { 82 mTarget.saveDefaultAccount(null); 83 assertNull(mTarget.getOnlyOrDefaultAccount(Collections.<AccountWithDataSet>emptyList())); 84 85 mTarget.saveDefaultAccount(ACCOUNT_1_A); 86 assertEquals(ACCOUNT_1_A, mTarget.getOnlyOrDefaultAccount(Collections. 87 <AccountWithDataSet>emptyList())); 88 } 89 90 /** 91 * Tests for 92 * {@link ContactEditorUtils#shouldShowAccountChangedNotification(List<AccountWithDataSet>)}, 93 * starting with 0 accounts. 94 */ 95 @Test 96 public void testShouldShowAccountChangedNotification_0Accounts() { 97 List<AccountWithDataSet> currentAccounts = new ArrayList<>(); 98 assertTrue(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 99 100 // We show the notification here, and user clicked "add account" 101 currentAccounts.add(ACCOUNT_1_A); 102 103 // Now we open the contact editor with the new account. 104 105 // When closing the editor, we save the default account. 106 mTarget.saveDefaultAccount(ACCOUNT_1_A); 107 108 // Next time the user creates a contact, we don't show the notification. 109 assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 110 111 // User added a new writable account, ACCOUNT_1_B. 112 currentAccounts.add(ACCOUNT_1_B); 113 114 // Since default account is still ACCOUNT_1_A, we don't show the notification. 115 assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 116 117 // User saved a new contact. We update the account list and the default account. 118 mTarget.saveDefaultAccount(ACCOUNT_1_B); 119 120 // User created another contact. Now we don't show the notification. 121 assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 122 123 // User installed a new contact sync adapter... 124 125 // Add new accounts: ACCOUNT_2_A, ACCOUNT_2EX_A. 126 currentAccounts.add(ACCOUNT_2_A); 127 currentAccounts.add(ACCOUNT_2EX_A); 128 129 // New added account but default account is still not changed, so no notification. 130 assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 131 132 // User saves a new contact, with a different default account. 133 mTarget.saveDefaultAccount(ACCOUNT_2_A); 134 135 // Next time user creates a contact, no notification. 136 assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 137 138 // Remove ACCOUNT_2EX_A. 139 currentAccounts.remove(ACCOUNT_2EX_A); 140 141 // ACCOUNT_2EX_A was not default, so no notification either. 142 assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 143 144 // Remove ACCOUNT_2_A, which is default. 145 currentAccounts.remove(ACCOUNT_2_A); 146 147 // Now we show the notification. 148 assertTrue(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 149 150 // Do not save the default account, and add a new account now. 151 currentAccounts.add(ACCOUNT_2EX_A); 152 153 // No default account, so show notification. 154 assertTrue(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 155 } 156 157 /** 158 * Tests for 159 * {@link ContactEditorUtils#shouldShowAccountChangedNotification(List<AccountWithDataSet>)}, 160 * starting with 1 accounts. 161 */ 162 @Test 163 public void testShouldShowAccountChangedNotification_1Account() { 164 // Always returns false when 1 writable account. 165 assertFalse(mTarget.shouldShowAccountChangedNotification( 166 Collections.singletonList(ACCOUNT_1_A))); 167 168 // User saves a new contact. 169 mTarget.saveDefaultAccount(ACCOUNT_1_A); 170 171 // Next time, no notification. 172 assertFalse(mTarget.shouldShowAccountChangedNotification( 173 Collections.singletonList(ACCOUNT_1_A))); 174 175 // The rest is the same... 176 } 177 178 /** 179 * Tests for 180 * {@link ContactEditorUtils#shouldShowAccountChangedNotification(List<AccountWithDataSet>)}, 181 * starting with 0 accounts, and the user selected "local only". 182 */ 183 @Test 184 public void testShouldShowAccountChangedNotification_0Account_localOnly() { 185 // First launch -- always true. 186 assertTrue(mTarget.shouldShowAccountChangedNotification(Collections. 187 <AccountWithDataSet>emptyList())); 188 189 // We show the notification here, and user clicked "keep local" and saved an contact. 190 mTarget.saveDefaultAccount(AccountWithDataSet.getNullAccount()); 191 192 // Now there are no accounts, and default account is null. 193 194 // The user created another contact, but this we shouldn't show the notification. 195 assertFalse(mTarget.shouldShowAccountChangedNotification(Collections. 196 <AccountWithDataSet>emptyList())); 197 } 198 199 @Test 200 public void testShouldShowAccountChangedNotification_sanity_check() { 201 // Prepare 1 account and save it as the default. 202 mTarget.saveDefaultAccount(ACCOUNT_1_A); 203 204 // Right after a save, the dialog shouldn't show up. 205 assertFalse(mTarget.shouldShowAccountChangedNotification( 206 Collections.singletonList(ACCOUNT_1_A))); 207 208 // Remove the default account to emulate broken preferences. 209 mTarget.removeDefaultAccountForTest(); 210 211 // The dialog shouldn't show up. 212 // The logic is, if there's a writable account, we'll pick it as default 213 assertFalse(mTarget.shouldShowAccountChangedNotification( 214 Collections.singletonList(ACCOUNT_1_A))); 215 } 216 217 @Test 218 public void testShouldShowAccountChangedNotification_nullAccount() { 219 final List<AccountWithDataSet> currentAccounts = new ArrayList<>(); 220 final AccountWithDataSet nullAccount = AccountWithDataSet.getNullAccount(); 221 currentAccounts.add(nullAccount); 222 223 assertTrue(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 224 225 // User chooses to keep the "device" account as the default 226 mTarget.saveDefaultAccount(nullAccount); 227 228 // Right after a save, the dialog shouldn't show up. 229 assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts)); 230 } 231 232 private static class MockAccountType extends AccountType { 233 private boolean mAreContactsWritable; 234 235 public MockAccountType(String accountType, String dataSet, boolean areContactsWritable) { 236 this.accountType = accountType; 237 this.dataSet = dataSet; 238 mAreContactsWritable = areContactsWritable; 239 } 240 241 @Override 242 public boolean areContactsWritable() { 243 return mAreContactsWritable; 244 } 245 246 @Override 247 public boolean isGroupMembershipEditable() { 248 return true; 249 } 250 } 251 } 252