• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  *      Copyright (C) 2012 Google Inc.
3  *      Licensed to The Android Open Source Project.
4  *
5  *      Licensed under the Apache License, Version 2.0 (the "License");
6  *      you may not use this file except in compliance with the License.
7  *      You may obtain a copy of the License at
8  *
9  *           http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *      Unless required by applicable law or agreed to in writing, software
12  *      distributed under the License is distributed on an "AS IS" BASIS,
13  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *      See the License for the specific language governing permissions and
15  *      limitations under the License.
16  *******************************************************************************/
17 
18 package com.android.mail.browse;
19 
20 import android.test.AndroidTestCase;
21 import android.test.suitebuilder.annotation.SmallTest;
22 import android.text.SpannableString;
23 
24 import com.android.mail.providers.Account;
25 import com.android.mail.providers.ConversationInfo;
26 import com.android.mail.providers.ParticipantInfo;
27 import com.android.mail.providers.UIProvider;
28 import com.google.common.collect.Lists;
29 
30 import org.json.JSONException;
31 import org.json.JSONObject;
32 
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.Map;
36 
37 @SmallTest
38 public class SendersFormattingTests extends AndroidTestCase {
39 
createConversationInfo()40     private static ConversationInfo createConversationInfo() {
41         return new ConversationInfo(0, 5, "snippet", "snippet", "snippet");
42     }
43 
testMeFromNullName()44     public void testMeFromNullName() {
45         final ConversationInfo conv = createConversationInfo();
46         conv.addParticipant(new ParticipantInfo(null, "something@somewhere.com", 0, false));
47         final ArrayList<SpannableString> strings = Lists.newArrayList();
48         assertEquals(0, strings.size());
49 
50         final Account account = createAccount();
51         SendersView.format(getContext(), conv, "", 100, strings, null, null, account, false, false);
52         assertEquals(1, strings.size());
53         assertEquals("me", strings.get(0).toString());
54     }
55 
testMeFromEmptyName()56     public void testMeFromEmptyName() {
57         final ConversationInfo conv = createConversationInfo();
58         conv.addParticipant(new ParticipantInfo("", "something@somewhere.com", 0, false));
59         final ArrayList<SpannableString> strings = Lists.newArrayList();
60         assertEquals(0, strings.size());
61 
62         final Account account = createAccount();
63         SendersView.format(getContext(), conv, "", 100, strings, null, null, account, false, false);
64         assertEquals(1, strings.size());
65         assertEquals("me", strings.get(0).toString());
66     }
67 
testMeFromDuplicateEmptyNames()68     public void testMeFromDuplicateEmptyNames() {
69         final ConversationInfo conv = createConversationInfo();
70         conv.addParticipant(new ParticipantInfo("", "something@somewhere.com", 0, false));
71         conv.addParticipant(new ParticipantInfo("", "something@somewhere.com", 0, false));
72         final ArrayList<SpannableString> strings = Lists.newArrayList();
73         assertEquals(0, strings.size());
74 
75         final Account account = createAccount();
76         SendersView.format(getContext(), conv, "", 100, strings, null, null, account, false, false);
77         assertEquals(2, strings.size());
78         assertNull(strings.get(0));
79         assertEquals("me", strings.get(1).toString());
80     }
81 
testDuplicates()82     public void testDuplicates() {
83         final ConversationInfo conv = createConversationInfo();
84         conv.addParticipant(new ParticipantInfo("Something", "something@somewhere.com", 0, false));
85         conv.addParticipant(new ParticipantInfo("Something", "something@somewhere.com", 0, false));
86 
87         final ArrayList<SpannableString> strings = Lists.newArrayList();
88         assertEquals(0, strings.size());
89 
90         final Account account = createAccount();
91         SendersView.format(getContext(), conv, "", 100, strings, null, null, account, false, false);
92         assertEquals(2, strings.size());
93         assertNull(strings.get(0));
94         assertEquals("Something", strings.get(1).toString());
95     }
96 
testSenderNameBadInput()97     public void testSenderNameBadInput() {
98         final ConversationInfo before = createConversationInfo();
99         before.addParticipant(new ParticipantInfo("****^****", null, 0, false));
100 
101         final byte[] serialized = before.toBlob();
102 
103         final ConversationInfo after = ConversationInfo.fromBlob(serialized);
104         assertEquals(1, after.participantInfos.size());
105         assertEquals(before.participantInfos.get(0).name, after.participantInfos.get(0).name);
106     }
107 
testConversationSnippetsBadInput()108     public void testConversationSnippetsBadInput() {
109         final String first = "*^*";
110         final String firstUnread = "*^*^*";
111         final String last = "*^*^*^*";
112 
113         final ConversationInfo before = new ConversationInfo(42, 49, first, firstUnread, last);
114         before.addParticipant(new ParticipantInfo("Foo Bar", "foo@bar.com", 0, false));
115         assertEquals(first, before.firstSnippet);
116         assertEquals(firstUnread, before.firstUnreadSnippet);
117         assertEquals(last, before.lastSnippet);
118 
119         final byte[] serialized = before.toBlob();
120 
121         final ConversationInfo after = ConversationInfo.fromBlob(serialized);
122         assertEquals(before.firstSnippet, after.firstSnippet);
123         assertEquals(before.firstUnreadSnippet, after.firstUnreadSnippet);
124         assertEquals(before.lastSnippet, after.lastSnippet);
125     }
126 
testSenderAvatarIsSenderOfFirstUnreadMessage()127     public void testSenderAvatarIsSenderOfFirstUnreadMessage() {
128         final ConversationInfo conv = createConversationInfo();
129         conv.addParticipant(new ParticipantInfo("a", "a@a.com", 0, true));
130         conv.addParticipant(new ParticipantInfo("b", "b@b.com", 0, false));
131         conv.addParticipant(new ParticipantInfo("c", "c@c.com", 0, false));
132 
133         final ArrayList<SpannableString> styledSenders = Lists.newArrayList();
134         final ArrayList<String> displayableSenderNames = Lists.newArrayList();
135         final ConversationItemViewModel.SenderAvatarModel senderAvatarModel =
136                 new ConversationItemViewModel.SenderAvatarModel();
137 
138         final Account account = createAccount();
139         SendersView.format(getContext(), conv, "", 100, styledSenders, displayableSenderNames,
140                 senderAvatarModel, account, false, false);
141 
142         // b is the first unread message with a valid email address
143         assertEquals("b@b.com", senderAvatarModel.getEmailAddress());
144         assertEquals("b", senderAvatarModel.getName());
145     }
146 
testSenderAvatarDoesNotChooseEmptyEmailAddress()147     public void testSenderAvatarDoesNotChooseEmptyEmailAddress() {
148         final ConversationInfo conv = createConversationInfo();
149         conv.addParticipant(new ParticipantInfo("a", "a@a.com", 0, true));
150         conv.addParticipant(new ParticipantInfo("b", "", 0, false));
151         conv.addParticipant(new ParticipantInfo("c", "c@c.com", 0, false));
152 
153         final ArrayList<SpannableString> styledSenders = Lists.newArrayList();
154         final ArrayList<String> displayableSenderNames = Lists.newArrayList();
155         final ConversationItemViewModel.SenderAvatarModel senderAvatarModel =
156                 new ConversationItemViewModel.SenderAvatarModel();
157 
158         final Account account = createAccount();
159         SendersView.format(getContext(), conv, "", 100, styledSenders, displayableSenderNames,
160                 senderAvatarModel, account, false, false);
161 
162         // b is unread but has an invalid email address so email address is set to the name
163         assertEquals("b", senderAvatarModel.getEmailAddress());
164         assertEquals("b", senderAvatarModel.getName());
165     }
166 
testSenderAvatarIsLastSenderIfAllMessagesAreRead()167     public void testSenderAvatarIsLastSenderIfAllMessagesAreRead() {
168         final ConversationInfo conv = createConversationInfo();
169         conv.addParticipant(new ParticipantInfo("a", "a@a.com", 0, true));
170         conv.addParticipant(new ParticipantInfo("b", "b@b.com", 0, true));
171         conv.addParticipant(new ParticipantInfo("c", "c@c.com", 0, true));
172 
173         final ArrayList<SpannableString> styledSenders = Lists.newArrayList();
174         final ArrayList<String> displayableSenderNames = Lists.newArrayList();
175         final ConversationItemViewModel.SenderAvatarModel senderAvatarModel =
176                 new ConversationItemViewModel.SenderAvatarModel();
177 
178         final Account account = createAccount();
179         SendersView.format(getContext(), conv, "", 100, styledSenders, displayableSenderNames,
180                 senderAvatarModel, account, false, false);
181 
182         // all are read, so c is chosen because it is the last sender
183         assertEquals("c@c.com", senderAvatarModel.getEmailAddress());
184         assertEquals("c", senderAvatarModel.getName());
185     }
186 
testSenderAvatarIsLastSenderWithValidEmailAddressIfAllMessagesAreRead()187     public void testSenderAvatarIsLastSenderWithValidEmailAddressIfAllMessagesAreRead() {
188         final ConversationInfo conv = createConversationInfo();
189         conv.addParticipant(new ParticipantInfo("a", "a@a.com", 0, true));
190         conv.addParticipant(new ParticipantInfo("b", "b@b.com", 0, true));
191         conv.addParticipant(new ParticipantInfo("c", "", 0, true));
192 
193         final ArrayList<SpannableString> styledSenders = Lists.newArrayList();
194         final ArrayList<String> displayableSenderNames = Lists.newArrayList();
195         final ConversationItemViewModel.SenderAvatarModel senderAvatarModel =
196                 new ConversationItemViewModel.SenderAvatarModel();
197 
198         final Account account = createAccount();
199         SendersView.format(getContext(), conv, "", 100, styledSenders, displayableSenderNames,
200                 senderAvatarModel, account, false, false);
201 
202         // all are read, c has an invalid email address, so email address is set to the name
203         assertEquals("c", senderAvatarModel.getEmailAddress());
204         assertEquals("c", senderAvatarModel.getName());
205     }
206 
testSenderAvatarIsLastSenderThatIsNotTheCurrentAccountIfAllMessagesAreRead()207     public void testSenderAvatarIsLastSenderThatIsNotTheCurrentAccountIfAllMessagesAreRead() {
208         final ConversationInfo conv = createConversationInfo();
209         conv.addParticipant(new ParticipantInfo("a", "a@a.com", 0, true));
210         conv.addParticipant(new ParticipantInfo("b", "b@b.com", 0, true));
211         // empty name indicates it is the current account
212         conv.addParticipant(new ParticipantInfo("", "c@c.com", 0, true));
213 
214         final ArrayList<SpannableString> styledSenders = Lists.newArrayList();
215         final ArrayList<String> displayableSenderNames = Lists.newArrayList();
216         final ConversationItemViewModel.SenderAvatarModel senderAvatarModel =
217                 new ConversationItemViewModel.SenderAvatarModel();
218 
219         final Account account = createAccount();
220         SendersView.format(getContext(), conv, "", 100, styledSenders, displayableSenderNames,
221                 senderAvatarModel, account, false, false);
222 
223         // c is the last sender, but it is the current account, so b is chosen instead
224         assertEquals("b@b.com", senderAvatarModel.getEmailAddress());
225         assertEquals("b", senderAvatarModel.getName());
226     }
227 
testSenderAvatarIsCurrentAccountIfAllSendersAreCurrentAccount()228     public void testSenderAvatarIsCurrentAccountIfAllSendersAreCurrentAccount() {
229         final ConversationInfo conv = createConversationInfo();
230         // empty name indicates it is the current account
231         conv.addParticipant(new ParticipantInfo("", "a@a.com", 0, true));
232 
233         final ArrayList<SpannableString> styledSenders = Lists.newArrayList();
234         final ArrayList<String> displayableSenderNames = Lists.newArrayList();
235         final ConversationItemViewModel.SenderAvatarModel senderAvatarModel =
236                 new ConversationItemViewModel.SenderAvatarModel();
237 
238         final Account account = createAccount();
239         SendersView.format(getContext(), conv, "", 100, styledSenders, displayableSenderNames,
240                 senderAvatarModel, account, false, false);
241 
242         // only one sender exists and it is the current account, so the current account is chosen
243         assertEquals("fflintstone@example.com", senderAvatarModel.getEmailAddress());
244         assertEquals("Fred Flintstone", senderAvatarModel.getName());
245     }
246 
247     /**
248      * Two senders in a thread should be kept distinct if they have unique email addresses, even if
249      * they happen to share the same name.
250      */
testSenderNamesWhenNamesMatchButEmailAddressesDiffer()251     public void testSenderNamesWhenNamesMatchButEmailAddressesDiffer() {
252         final ConversationInfo conv = createConversationInfo();
253         conv.addParticipant(new ParticipantInfo("Andrew", "aholmes@awesome.com", 0, true));
254         conv.addParticipant(new ParticipantInfo("Andrew", "ajohnson@wicked.com", 0, true));
255 
256         final ArrayList<SpannableString> styledSenders = Lists.newArrayList();
257         final ArrayList<String> displayableSenderNames = Lists.newArrayList();
258         final ConversationItemViewModel.SenderAvatarModel senderAvatarModel =
259                 new ConversationItemViewModel.SenderAvatarModel();
260 
261         final Account account = createAccount();
262         SendersView.format(getContext(), conv, "", 100, styledSenders, displayableSenderNames,
263                 senderAvatarModel, account, false, false);
264 
265         assertEquals(2, displayableSenderNames.size());
266         assertEquals("Andrew", displayableSenderNames.get(0));
267         assertEquals("Andrew", displayableSenderNames.get(1));
268     }
269 
createAccount()270     private static Account createAccount() {
271         try {
272             final Map<String, Object> map = new HashMap<>(2);
273             map.put(UIProvider.AccountColumns.NAME, "Fred Flintstone");
274             map.put(UIProvider.AccountColumns.ACCOUNT_MANAGER_NAME, "fflintstone@example.com");
275             map.put(UIProvider.AccountColumns.TYPE, "IMAP");
276             map.put(UIProvider.AccountColumns.PROVIDER_VERSION, 1);
277             map.put(UIProvider.AccountColumns.CAPABILITIES, 0);
278 
279             final JSONObject json = new JSONObject(map);
280 
281             return Account.builder().buildFrom(json);
282         } catch (JSONException je) {
283             throw new RuntimeException(je);
284         }
285     }
286 }