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