Home | History | Annotate | Download | only in editor
      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 android.test.AndroidTestCase;
     20 import android.test.MoreAsserts;
     21 import android.test.suitebuilder.annotation.SmallTest;
     22 
     23 import com.android.contacts.model.account.AccountType;
     24 import com.android.contacts.model.account.AccountWithDataSet;
     25 import com.android.contacts.tests.mocks.MockAccountTypeManager;
     26 import com.google.common.collect.Sets;
     27 
     28 import java.util.Collection;
     29 import java.util.Set;
     30 
     31 /**
     32  * Test case for {@link ContactEditorUtils}.
     33  *
     34  * adb shell am instrument -w -e class com.android.contacts.editor.ContactEditorUtilsTest \
     35        com.android.contacts.tests/android.test.InstrumentationTestRunner
     36  */
     37 @SmallTest
     38 public class ContactEditorUtilsTest extends AndroidTestCase {
     39     private MockAccountTypeManager mAccountTypes;
     40     private ContactEditorUtils mTarget;
     41 
     42     private static final MockAccountType TYPE1 = new MockAccountType("type1", null, true);
     43     private static final MockAccountType TYPE2 = new MockAccountType("type2", null, true);
     44     private static final MockAccountType TYPE2EX = new MockAccountType("type2", "ext", true);
     45 
     46     // Only type 3 is "readonly".
     47     private static final MockAccountType TYPE3 = new MockAccountType("type3", null, false);
     48 
     49     private static final AccountWithDataSet ACCOUNT_1_A = new AccountWithDataSet(
     50             "a", TYPE1.accountType, TYPE1.dataSet);
     51     private static final AccountWithDataSet ACCOUNT_1_B = new AccountWithDataSet(
     52             "b", TYPE1.accountType, TYPE1.dataSet);
     53 
     54     private static final AccountWithDataSet ACCOUNT_2_A = new AccountWithDataSet(
     55             "a", TYPE2.accountType, TYPE2.dataSet);
     56     private static final AccountWithDataSet ACCOUNT_2EX_A = new AccountWithDataSet(
     57             "a", TYPE2EX.accountType, TYPE2EX.dataSet);
     58 
     59     private static final AccountWithDataSet ACCOUNT_3_C = new AccountWithDataSet(
     60             "c", TYPE3.accountType, TYPE3.dataSet);
     61 
     62     @Override
     63     protected void setUp() throws Exception {
     64         // Initialize with 0 types, 0 accounts.
     65         mAccountTypes = new MockAccountTypeManager(new AccountType[] {},
     66                 new AccountWithDataSet[] {});
     67         mTarget = new ContactEditorUtils(getContext(), mAccountTypes);
     68 
     69         // Clear the preferences.
     70         mTarget.cleanupForTest();
     71     }
     72 
     73     private void setAccountTypes(AccountType... types) {
     74         mAccountTypes.mTypes = types;
     75     }
     76 
     77     private void setAccounts(AccountWithDataSet... accounts) {
     78         mAccountTypes.mAccounts = accounts;
     79     }
     80 
     81     public void testGetWritableAccountTypeStrings() {
     82         String[] types;
     83 
     84         // 0 writable types
     85         setAccountTypes();
     86 
     87         types = mTarget.getWritableAccountTypeStrings();
     88         MoreAsserts.assertEquals(types, new String[0]);
     89 
     90         // 1 writable type
     91         setAccountTypes(TYPE1);
     92 
     93         types = mTarget.getWritableAccountTypeStrings();
     94         MoreAsserts.assertEquals(Sets.newHashSet(TYPE1.accountType), Sets.newHashSet(types));
     95 
     96         // 2 writable types
     97         setAccountTypes(TYPE1, TYPE2EX);
     98 
     99         types = mTarget.getWritableAccountTypeStrings();
    100         MoreAsserts.assertEquals(Sets.newHashSet(TYPE1.accountType, TYPE2EX.accountType),
    101                 Sets.newHashSet(types));
    102 
    103         // 3 writable types + 1 readonly type
    104         setAccountTypes(TYPE1, TYPE2, TYPE2EX, TYPE3);
    105 
    106         types = mTarget.getWritableAccountTypeStrings();
    107         MoreAsserts.assertEquals(
    108                 Sets.newHashSet(TYPE1.accountType, TYPE2.accountType, TYPE2EX.accountType),
    109                 Sets.newHashSet(types));
    110     }
    111 
    112     /**
    113      * Test for
    114      * - {@link ContactEditorUtils#saveDefaultAndAllAccounts}
    115      * - {@link ContactEditorUtils#getDefaultAccount}
    116      * - {@link ContactEditorUtils#getSavedAccounts()}
    117      */
    118     public void testSaveDefaultAndAllAccounts() {
    119         // Use these account types here.
    120         setAccountTypes(TYPE1, TYPE2);
    121 
    122         // If none has been saved, it should return an empty list.
    123         assertEquals(0, mTarget.getSavedAccounts().size());
    124 
    125         // Save 0 accounts.
    126         mAccountTypes.mAccounts = new AccountWithDataSet[]{};
    127         mTarget.saveDefaultAndAllAccounts(null);
    128         assertNull(mTarget.getDefaultAccount());
    129         MoreAsserts.assertEquals(
    130                 Sets.newHashSet(mAccountTypes.mAccounts),
    131                 toSet(mTarget.getSavedAccounts()));
    132 
    133         // 1 account
    134         mAccountTypes.mAccounts = new AccountWithDataSet[]{ACCOUNT_1_A};
    135         mTarget.saveDefaultAndAllAccounts(ACCOUNT_1_A);
    136         assertEquals(ACCOUNT_1_A, mTarget.getDefaultAccount());
    137         MoreAsserts.assertEquals(
    138                 Sets.newHashSet(mAccountTypes.mAccounts),
    139                 toSet(mTarget.getSavedAccounts()));
    140 
    141         // 2 accounts
    142         mAccountTypes.mAccounts = new AccountWithDataSet[]{ACCOUNT_1_A, ACCOUNT_1_B};
    143         mTarget.saveDefaultAndAllAccounts(ACCOUNT_1_B);
    144         assertEquals(ACCOUNT_1_B, mTarget.getDefaultAccount());
    145         MoreAsserts.assertEquals(
    146                 Sets.newHashSet(mAccountTypes.mAccounts),
    147                 toSet(mTarget.getSavedAccounts()));
    148 
    149         // 2 accounts, and save null as the default.  Even though there are accounts, the saved
    150         // account list should be empty in this case.
    151         mTarget.saveDefaultAndAllAccounts(null);
    152         assertNull(mTarget.getDefaultAccount());
    153         assertEquals(0, mTarget.getSavedAccounts().size());
    154     }
    155 
    156     public void testIsAccountValid() {
    157         // Use these account types here.
    158         setAccountTypes(TYPE1, TYPE2);
    159 
    160         // 0 accounts
    161         mAccountTypes.mAccounts = new AccountWithDataSet[]{};
    162         assertFalse(mTarget.isValidAccount(ACCOUNT_1_A));
    163         assertTrue(mTarget.isValidAccount(null)); // null is always valid
    164 
    165         // 2 accounts
    166         mAccountTypes.mAccounts = new AccountWithDataSet[]{ACCOUNT_1_A, ACCOUNT_2_A};
    167         assertTrue(mTarget.isValidAccount(ACCOUNT_1_A));
    168         assertTrue(mTarget.isValidAccount(ACCOUNT_2_A));
    169         assertFalse(mTarget.isValidAccount(ACCOUNT_2EX_A));
    170         assertTrue(mTarget.isValidAccount(null)); // null is always valid
    171     }
    172 
    173     /**
    174      * Tests for {@link ContactEditorUtils#shouldShowAccountChangedNotification()}, starting with
    175      * 0 accounts.
    176      */
    177     public void testShouldShowAccountChangedNotification_0Accounts() {
    178         // There's always at least one writable type...
    179         setAccountTypes(TYPE1);
    180 
    181         // First launch -- always true.
    182         assertTrue(mTarget.shouldShowAccountChangedNotification());
    183 
    184         // We show the notification here, and user clicked "add account"
    185         setAccounts(ACCOUNT_1_A);
    186 
    187         // Now we open the contact editor with the new account.
    188 
    189         // When closing the editor, we save the default account.
    190         mTarget.saveDefaultAndAllAccounts(ACCOUNT_1_A);
    191 
    192         // Next time the user creates a contact, we don't show the notification.
    193         assertFalse(mTarget.shouldShowAccountChangedNotification());
    194 
    195         // User added a new writable account, ACCOUNT_1_B.
    196         setAccounts(ACCOUNT_1_A, ACCOUNT_1_B);
    197 
    198         // Now we show the notification again.
    199         assertTrue(mTarget.shouldShowAccountChangedNotification());
    200 
    201         // User saved a new contact.  We update the account list and the default account.
    202         mTarget.saveDefaultAndAllAccounts(ACCOUNT_1_B);
    203 
    204         // User created another contact.  Now we don't show the notification.
    205         assertFalse(mTarget.shouldShowAccountChangedNotification());
    206 
    207         // User installed a new contact sync adapter...
    208 
    209         // Added a new account type: TYPE2, and the TYPE2EX extension.
    210         setAccountTypes(TYPE1, TYPE2, TYPE2EX);
    211         // Add new accounts: ACCOUNT_2_A, ACCOUNT_2EX_A.
    212         setAccounts(ACCOUNT_1_A, ACCOUNT_1_B, ACCOUNT_2_A, ACCOUNT_2EX_A);
    213 
    214         // New account means another notification.
    215         assertTrue(mTarget.shouldShowAccountChangedNotification());
    216 
    217         // User saves a new contact, with a different default account.
    218         mTarget.saveDefaultAndAllAccounts(ACCOUNT_2_A);
    219 
    220         // Next time user creates a contact, no notification.
    221         assertFalse(mTarget.shouldShowAccountChangedNotification());
    222 
    223         // Remove ACCOUNT_2EX_A.
    224         setAccountTypes(TYPE1, TYPE2, TYPE2EX);
    225         setAccounts(ACCOUNT_1_A, ACCOUNT_1_B, ACCOUNT_2_A);
    226 
    227         // ACCOUNT_2EX_A was not default, so no notification either.
    228         assertFalse(mTarget.shouldShowAccountChangedNotification());
    229 
    230         // Remove ACCOUNT_1_B, which is default.
    231         setAccountTypes(TYPE1, TYPE2, TYPE2EX);
    232         setAccounts(ACCOUNT_1_A, ACCOUNT_1_B);
    233 
    234         // Now we show the notification.
    235         assertTrue(mTarget.shouldShowAccountChangedNotification());
    236     }
    237 
    238     /**
    239      * Tests for {@link ContactEditorUtils#shouldShowAccountChangedNotification()}, starting with
    240      * 1 accounts.
    241      */
    242     public void testShouldShowAccountChangedNotification_1Account() {
    243         setAccountTypes(TYPE1, TYPE2);
    244         setAccounts(ACCOUNT_1_A);
    245 
    246         // First launch -- always true.
    247         assertTrue(mTarget.shouldShowAccountChangedNotification());
    248 
    249         // User saves a new contact.
    250         mTarget.saveDefaultAndAllAccounts(ACCOUNT_1_A);
    251 
    252         // Next time, no notification.
    253         assertFalse(mTarget.shouldShowAccountChangedNotification());
    254 
    255         // The rest is the same...
    256     }
    257 
    258     /**
    259      * Tests for {@link ContactEditorUtils#shouldShowAccountChangedNotification()}, starting with
    260      * 0 accounts, and the user selected "local only".
    261      */
    262     public void testShouldShowAccountChangedNotification_0Account_localOnly() {
    263         // There's always at least one writable type...
    264         setAccountTypes(TYPE1);
    265 
    266         // First launch -- always true.
    267         assertTrue(mTarget.shouldShowAccountChangedNotification());
    268 
    269         // We show the notification here, and user clicked "keep local" and saved an contact.
    270         mTarget.saveDefaultAndAllAccounts(null);
    271 
    272         // Now there are no accounts, and default account is null.
    273 
    274         // The user created another contact, but this we shouldn't show the notification.
    275         assertFalse(mTarget.shouldShowAccountChangedNotification());
    276     }
    277 
    278     public void testShouldShowAccountChangedNotification_sanity_check() {
    279         // Prepare 1 account and save it as the default.
    280         setAccountTypes(TYPE1);
    281         setAccounts(ACCOUNT_1_A);
    282 
    283         mTarget.saveDefaultAndAllAccounts(ACCOUNT_1_A);
    284 
    285         // Right after a save, the dialog shouldn't show up.
    286         assertFalse(mTarget.shouldShowAccountChangedNotification());
    287 
    288         // Remove the default account to emulate broken preferences.
    289         mTarget.removeDefaultAccountForTest();
    290         assertTrue(mTarget.shouldShowAccountChangedNotification());
    291     }
    292 
    293     private static <T> Set<T> toSet(Collection<T> collection) {
    294         Set<T> ret = Sets.newHashSet();
    295         ret.addAll(collection);
    296         return ret;
    297     }
    298 
    299     private static class MockAccountType extends AccountType {
    300         private boolean mAreContactsWritable;
    301 
    302         public MockAccountType(String accountType, String dataSet, boolean areContactsWritable) {
    303             this.accountType = accountType;
    304             this.dataSet = dataSet;
    305             mAreContactsWritable = areContactsWritable;
    306         }
    307 
    308         @Override
    309         public boolean areContactsWritable() {
    310             return mAreContactsWritable;
    311         }
    312 
    313         @Override
    314         public boolean isGroupMembershipEditable() {
    315             return true;
    316         }
    317     }
    318 }
    319