1 /** 2 * Copyright (c) 2012, Google Inc. 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.mail.compose; 18 19 import android.content.ContentResolver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.database.Cursor; 23 import android.database.MatrixCursor; 24 import android.net.Uri; 25 import android.test.ActivityInstrumentationTestCase2; 26 import android.test.suitebuilder.annotation.SmallTest; 27 import android.text.Html; 28 import android.text.TextUtils; 29 import android.text.util.Rfc822Tokenizer; 30 31 import com.android.mail.compose.ComposeActivity; 32 import com.android.mail.providers.Account; 33 import com.android.mail.providers.Attachment; 34 import com.android.mail.providers.MailAppProvider; 35 import com.android.mail.providers.Message; 36 import com.android.mail.providers.ReplyFromAccount; 37 import com.android.mail.providers.UIProvider; 38 import com.android.mail.utils.AccountUtils; 39 import com.android.mail.utils.LogUtils; 40 import com.android.mail.utils.MatrixCursorWithCachedColumns; 41 import com.android.mail.utils.Utils; 42 43 import org.json.JSONArray; 44 import org.json.JSONException; 45 46 import java.lang.Deprecated; 47 import java.lang.Throwable; 48 import java.util.Arrays; 49 import java.util.Date; 50 import java.util.HashSet; 51 52 @SmallTest 53 public class ComposeActivityTest extends ActivityInstrumentationTestCase2<ComposeActivity> { 54 // TODO: Remove usages of FromAddressSpinner#initialize and ComposeActivity#initReplyRecipients. 55 // The internal state of the activity instance may have the wrong mReplyFromAccount as 56 // this is set when handling the initial intent. Theses tests should 57 // instantiate the ComposeActivity with the correct reply all intent 58 59 // This varible shouldn't be used, as it may not match the state of the ComposeActivity 60 // TODO: remove usage of this variable 61 @Deprecated 62 private Account mAccount; 63 64 private static final Account[] EMPTY_ACCOUNT_LIST = new Account[0]; 65 66 public ComposeActivityTest() { 67 super(ComposeActivity.class); 68 } 69 70 private Message getRefMessage(ContentResolver resolver, Uri folderListUri) { 71 Cursor foldersCursor = resolver.query(folderListUri, 72 UIProvider.FOLDERS_PROJECTION, null, null, null); 73 Uri convUri = null; 74 if (foldersCursor != null) { 75 foldersCursor.moveToFirst(); 76 convUri = Uri.parse(foldersCursor 77 .getString(UIProvider.FOLDER_CONVERSATION_LIST_URI_COLUMN)); 78 foldersCursor.close(); 79 } 80 81 Cursor convCursor = resolver.query(convUri, 82 UIProvider.CONVERSATION_PROJECTION, null, null, null); 83 Uri messagesUri = null; 84 if (convCursor != null) { 85 convCursor.moveToFirst(); 86 messagesUri = Uri.parse(convCursor 87 .getString(UIProvider.CONVERSATION_MESSAGE_LIST_URI_COLUMN)); 88 convCursor.close(); 89 } 90 91 Cursor msgCursor = resolver.query(messagesUri, 92 UIProvider.MESSAGE_PROJECTION, null, null, null); 93 if (msgCursor != null) { 94 msgCursor.moveToFirst(); 95 } 96 return new Message(msgCursor); 97 } 98 99 100 private Message getRefMessage(ContentResolver resolver) { 101 return getRefMessage(resolver, mAccount.folderListUri); 102 } 103 104 public void setAccount(ComposeActivity activity, String accountName) { 105 // Get a mock account. 106 final Account account = getAccountForName(activity, accountName); 107 if (account != null) { 108 mAccount = account; 109 activity.setAccount(mAccount); 110 } 111 } 112 113 private Account[] getAccounts(Context context) { 114 return AccountUtils.getSyncingAccounts(context); 115 } 116 117 private Account getAccountForName(Context context, String accountName) { 118 Account[] results = getAccounts(context); 119 for (Account account : results) { 120 if (account.name.equals(accountName)) { 121 return account; 122 } 123 } 124 return null; 125 } 126 127 /** 128 * Test the cases where: The user's reply-to is one of their custom from's 129 * and they are replying all to a message where their custom from was a 130 * recipient. TODO: verify web behavior 131 */ 132 public void testRecipientsRefReplyAllCustomFromReplyTo() throws Throwable { 133 final ComposeActivity activity = getActivity(); 134 setAccount(activity, "account3 (at) mockuiprovider.com"); 135 final Message refMessage = getRefMessage(activity.getContentResolver()); 136 final String customFrom = "CUSTOMaccount3 (at) mockuiprovider.com"; 137 refMessage.setFrom("account3 (at) mockuiprovider.com"); 138 refMessage.setTo("someotheraccount1 (at) mockuiprovider.com, " 139 + "someotheraccount2 (at) mockuiprovider.com, someotheraccount3 (at) mockuiprovider.com, " 140 + customFrom); 141 refMessage.setReplyTo(customFrom); 142 activity.mFromSpinner = new FromAddressSpinner(activity); 143 ReplyFromAccount a = new ReplyFromAccount(mAccount, mAccount.uri, customFrom, 144 customFrom, customFrom, true, true); 145 JSONArray array = new JSONArray(); 146 array.put(a.serialize()); 147 mAccount.accountFromAddresses = array.toString(); 148 ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri, 149 mAccount.name, mAccount.name, customFrom, true, false); 150 activity.mFromSpinner.setCurrentAccount(currentAccount); 151 152 activity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL, 153 currentAccount.account, EMPTY_ACCOUNT_LIST, null); 154 runTestOnUiThread(new Runnable() { 155 @Override 156 public void run() { 157 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL); 158 String[] to = activity.getToAddresses(); 159 String[] cc = activity.getCcAddresses(); 160 String[] bcc = activity.getBccAddresses(); 161 String toAsString = TextUtils.join(",", to); 162 assertEquals(3, to.length); 163 assertFalse(toAsString.contains(customFrom)); 164 assertEquals(0, cc.length); 165 assertEquals(0, bcc.length); 166 } 167 }); 168 } 169 170 /** 171 * Test the cases where: The user sent a message to one of 172 * their custom froms and just replied to that message 173 */ 174 public void testRecipientsRefReplyAllOnlyAccount() throws Throwable { 175 final ComposeActivity activity = getActivity(); 176 setAccount(activity, "account3 (at) mockuiprovider.com"); 177 final Message refMessage = getRefMessage(activity.getContentResolver()); 178 refMessage.setFrom("account3 (at) mockuiprovider.com"); 179 refMessage.setTo("account3 (at) mockuiprovider.com"); 180 final Account account = mAccount; 181 activity.mFromSpinner = new FromAddressSpinner(activity); 182 ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri, 183 mAccount.name, mAccount.name, mAccount.name, true, false); 184 activity.mFromSpinner.setCurrentAccount(currentAccount); 185 186 activity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL, 187 currentAccount.account, EMPTY_ACCOUNT_LIST, null); 188 runTestOnUiThread(new Runnable() { 189 @Override 190 public void run() { 191 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL); 192 String[] to = activity.getToAddresses(); 193 String[] cc = activity.getCcAddresses(); 194 String[] bcc = activity.getBccAddresses(); 195 String toAsString = TextUtils.join(",", to); 196 assertEquals(1, to.length); 197 assertTrue(toAsString.contains(account.getEmailAddress())); 198 assertEquals(0, cc.length); 199 assertEquals(0, bcc.length); 200 } 201 }); 202 } 203 204 /** 205 * Test the cases where: The user sent a message to one of 206 * their custom froms and just replied to that message 207 */ 208 public void testRecipientsRefReplyAllOnlyCustomFrom() throws Throwable { 209 final ComposeActivity activity = getActivity(); 210 setAccount(activity, "account3 (at) mockuiprovider.com"); 211 final Message refMessage = getRefMessage(activity.getContentResolver()); 212 final String customFrom = "CUSTOMaccount3 (at) mockuiprovider.com"; 213 refMessage.setFrom("account3 (at) mockuiprovider.com"); 214 refMessage.setTo(customFrom); 215 activity.mFromSpinner = new FromAddressSpinner(activity); 216 ReplyFromAccount a = new ReplyFromAccount(mAccount, mAccount.uri, customFrom, 217 customFrom, customFrom, true, true); 218 JSONArray array = new JSONArray(); 219 array.put(a.serialize()); 220 mAccount.accountFromAddresses = array.toString(); 221 ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri, 222 mAccount.name, mAccount.name, customFrom, true, false); 223 activity.mFromSpinner.setCurrentAccount(currentAccount); 224 225 activity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL, 226 currentAccount.account, EMPTY_ACCOUNT_LIST, null); 227 runTestOnUiThread(new Runnable() { 228 @Override 229 public void run() { 230 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL); 231 String[] to = activity.getToAddresses(); 232 String[] cc = activity.getCcAddresses(); 233 String[] bcc = activity.getBccAddresses(); 234 String toAsString = TextUtils.join(",", to); 235 assertEquals(1, to.length); 236 assertTrue(toAsString.contains(customFrom)); 237 assertEquals(0, cc.length); 238 assertEquals(0, bcc.length); 239 } 240 }); 241 } 242 243 public void testReply() throws Throwable { 244 final ComposeActivity activity = getActivity(); 245 setAccount(activity, "account0 (at) mockuiprovider.com"); 246 final Message refMessage = getRefMessage(activity.getContentResolver()); 247 final String refMessageFromAccount = refMessage.getFrom(); 248 249 runTestOnUiThread(new Runnable() { 250 @Override 251 public void run() { 252 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY); 253 String[] to = activity.getToAddresses(); 254 String[] cc = activity.getCcAddresses(); 255 String[] bcc = activity.getBccAddresses(); 256 assertTrue(to.length == 1); 257 assertEquals(refMessageFromAccount, 258 Rfc822Tokenizer.tokenize(to[0])[0].getAddress()); 259 assertTrue(cc.length == 0); 260 assertTrue(bcc.length == 0); 261 } 262 }); 263 } 264 265 public void testReplyWithReplyTo() throws Throwable { 266 final ComposeActivity activity = getActivity(); 267 setAccount(activity, "account1 (at) mockuiprovider.com"); 268 final Message refMessage = getRefMessage(activity.getContentResolver()); 269 refMessage.setReplyTo("replytofromaccount1 (at) mock.com"); 270 final String refReplyToAccount = refMessage.getReplyTo(); 271 272 runTestOnUiThread(new Runnable() { 273 @Override 274 public void run() { 275 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY); 276 String[] to = activity.getToAddresses(); 277 String[] cc = activity.getCcAddresses(); 278 String[] bcc = activity.getBccAddresses(); 279 assertTrue(to.length == 1); 280 assertEquals(refReplyToAccount, 281 Rfc822Tokenizer.tokenize(to[0])[0].getAddress()); 282 assertTrue(cc.length == 0); 283 assertTrue(bcc.length == 0); 284 } 285 }); 286 } 287 288 /** 289 * Reply to a message you sent yourself to some recipients in the to field. 290 */ 291 public void testReplyToSelf() throws Throwable { 292 final ComposeActivity activity = getActivity(); 293 setAccount(activity, "account1 (at) mockuiprovider.com"); 294 final Message refMessage = getRefMessage(activity.getContentResolver()); 295 refMessage.setFrom("Account Test <account1 (at) mockuiprovider.com>"); 296 refMessage.setTo("test1 (at) gmail.com"); 297 runTestOnUiThread(new Runnable() { 298 @Override 299 public void run() { 300 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY); 301 String[] to = activity.getToAddresses(); 302 String[] cc = activity.getCcAddresses(); 303 String[] bcc = activity.getBccAddresses(); 304 assertTrue(to.length == 1); 305 String toAsString = TextUtils.join(",", to); 306 assertTrue(toAsString.contains("test1 (at) gmail.com")); 307 assertTrue(cc.length == 0); 308 assertTrue(bcc.length == 0); 309 } 310 }); 311 } 312 313 /** 314 * Reply-all to a message you sent. 315 */ 316 public void testReplyAllToSelf() throws Throwable { 317 final ComposeActivity activity = getActivity(); 318 setAccount(activity, "account1 (at) mockuiprovider.com"); 319 final Message refMessage = getRefMessage(activity.getContentResolver()); 320 refMessage.setFrom("Account Test <account1 (at) mockuiprovider.com>"); 321 refMessage.setTo("test1 (at) gmail.com, test2 (at) gmail.com"); 322 runTestOnUiThread(new Runnable() { 323 @Override 324 public void run() { 325 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL); 326 String[] to = activity.getToAddresses(); 327 String[] cc = activity.getCcAddresses(); 328 String[] bcc = activity.getBccAddresses(); 329 assertEquals(to.length, 2); 330 String toAsString = TextUtils.join(",", to); 331 assertTrue(toAsString.contains("test1 (at) gmail.com")); 332 assertTrue(toAsString.contains("test2 (at) gmail.com")); 333 assertTrue(cc.length == 0); 334 assertTrue(bcc.length == 0); 335 } 336 }); 337 } 338 339 /** 340 * Reply-all to a message you sent with some to and some CC recips. 341 */ 342 public void testReplyAllToSelfWithCc() throws Throwable { 343 final ComposeActivity activity = getActivity(); 344 setAccount(activity, "account1 (at) mockuiprovider.com"); 345 final Message refMessage = getRefMessage(activity.getContentResolver()); 346 refMessage.setFrom("Account Test <account1 (at) mockuiprovider.com>"); 347 refMessage.setTo("test1 (at) gmail.com, test2 (at) gmail.com"); 348 refMessage.setCc("testcc (at) gmail.com"); 349 runTestOnUiThread(new Runnable() { 350 @Override 351 public void run() { 352 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL); 353 String[] to = activity.getToAddresses(); 354 String[] cc = activity.getCcAddresses(); 355 String[] bcc = activity.getBccAddresses(); 356 assertEquals(to.length, 2); 357 String toAsString = TextUtils.join(",", to); 358 assertTrue(toAsString.contains("test1 (at) gmail.com")); 359 assertTrue(toAsString.contains("test2 (at) gmail.com")); 360 String ccAsString = TextUtils.join(",", cc); 361 assertTrue(ccAsString.contains("testcc (at) gmail.com")); 362 assertTrue(cc.length == 1); 363 assertTrue(bcc.length == 0); 364 } 365 }); 366 } 367 368 public void testReplyAll() throws Throwable { 369 final ComposeActivity activity = getActivity(); 370 setAccount(activity, "account0 (at) mockuiprovider.com"); 371 final Message refMessage = getRefMessage(activity.getContentResolver()); 372 final String[] refMessageTo = TextUtils.split(refMessage.getTo(), ","); 373 final String refMessageFromAccount = refMessage.getFrom(); 374 375 runTestOnUiThread(new Runnable() { 376 @Override 377 public void run() { 378 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL); 379 String[] to = activity.getToAddresses(); 380 String[] cc = activity.getCcAddresses(); 381 String[] bcc = activity.getBccAddresses(); 382 assertTrue(to.length == 1); 383 assertEquals(refMessageFromAccount, 384 Rfc822Tokenizer.tokenize(to[0])[0].getAddress()); 385 assertEquals(cc.length, refMessageTo.length); 386 assertTrue(bcc.length == 0); 387 } 388 }); 389 } 390 391 public void testReplyAllWithReplyTo() throws Throwable { 392 final ComposeActivity activity = getActivity(); 393 setAccount(activity, "account1 (at) mockuiprovider.com"); 394 final Message refMessage = getRefMessage(activity.getContentResolver()); 395 refMessage.setReplyTo("replytofromaccount1 (at) mock.com"); 396 final String[] refMessageTo = TextUtils.split(refMessage.getTo(), ","); 397 final String refReplyToAccount = refMessage.getReplyTo(); 398 399 runTestOnUiThread(new Runnable() { 400 @Override 401 public void run() { 402 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL); 403 String[] to = activity.getToAddresses(); 404 String[] cc = activity.getCcAddresses(); 405 String[] bcc = activity.getBccAddresses(); 406 assertTrue(to.length == 1); 407 assertEquals(refReplyToAccount, Rfc822Tokenizer.tokenize(to[0])[0].getAddress()); 408 assertEquals(cc.length, refMessageTo.length); 409 assertTrue(bcc.length == 0); 410 } 411 }); 412 } 413 414 private static Message getRefMessageWithCc(long messageId, boolean hasAttachments) { 415 MatrixCursor cursor = new MatrixCursorWithCachedColumns(UIProvider.MESSAGE_PROJECTION); 416 final String messageUri = "content://xxx/message/" + messageId; 417 Object[] messageValues = new Object[UIProvider.MESSAGE_PROJECTION.length]; 418 messageValues[UIProvider.MESSAGE_ID_COLUMN] = Long.valueOf(messageId); 419 messageValues[UIProvider.MESSAGE_URI_COLUMN] = messageUri; 420 messageValues[UIProvider.MESSAGE_SUBJECT_COLUMN] = "Message subject"; 421 messageValues[UIProvider.MESSAGE_SNIPPET_COLUMN] = "SNIPPET"; 422 String html = "<html><body><b><i>This is some html!!!</i></b></body></html>"; 423 messageValues[UIProvider.MESSAGE_BODY_HTML_COLUMN] = html; 424 messageValues[UIProvider.MESSAGE_BODY_TEXT_COLUMN] = Html.fromHtml(html); 425 messageValues[UIProvider.MESSAGE_HAS_ATTACHMENTS_COLUMN] = hasAttachments ? 1 : 0; 426 messageValues[UIProvider.MESSAGE_DATE_RECEIVED_MS_COLUMN] = new Date().getTime(); 427 messageValues[UIProvider.MESSAGE_ATTACHMENT_LIST_URI_COLUMN] = messageUri 428 + "/getAttachments"; 429 messageValues[UIProvider.MESSAGE_TO_COLUMN] = "account1 (at) mock.com, account2 (at) mock.com"; 430 messageValues[UIProvider.MESSAGE_FROM_COLUMN] = "fromaccount1 (at) mock.com"; 431 messageValues[UIProvider.MESSAGE_CC_COLUMN] = "accountcc1 (at) mock.com, accountcc2 (at) mock.com"; 432 cursor.addRow(messageValues); 433 cursor.moveToFirst(); 434 return new Message(cursor); 435 } 436 437 public void testReplyAllWithCc() throws Throwable { 438 final ComposeActivity activity = getActivity(); 439 setAccount(activity, "account1 (at) mockuiprovider.com"); 440 final Message refMessage = getRefMessageWithCc(0, false); 441 final String[] refMessageTo = TextUtils.split(refMessage.getTo(), ","); 442 final String[] refMessageCc = TextUtils.split(refMessage.getCc(), ","); 443 final String refMessageFromAccount = refMessage.getFrom(); 444 445 runTestOnUiThread(new Runnable() { 446 @Override 447 public void run() { 448 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL); 449 String[] to = activity.getToAddresses(); 450 String[] cc = activity.getCcAddresses(); 451 String[] bcc = activity.getBccAddresses(); 452 assertTrue(to.length == 1); 453 assertEquals(refMessageFromAccount, 454 Rfc822Tokenizer.tokenize(to[0])[0].getAddress()); 455 assertEquals(cc.length, refMessageTo.length + refMessageCc.length); 456 HashSet<String> ccMap = new HashSet<String>(); 457 for (String recip : cc) { 458 ccMap.add(Rfc822Tokenizer.tokenize(recip.trim())[0].getAddress()); 459 } 460 for (String toRecip : refMessageTo) { 461 assertTrue(ccMap.contains(toRecip.trim())); 462 } 463 for (String ccRecip : refMessageCc) { 464 assertTrue(ccMap.contains(ccRecip.trim())); 465 } 466 assertTrue(bcc.length == 0); 467 } 468 }); 469 } 470 471 public void testForward() throws Throwable { 472 final ComposeActivity activity = getActivity(); 473 setAccount(activity, "account0 (at) mockuiprovider.com"); 474 final Message refMessage = getRefMessage(activity.getContentResolver()); 475 476 runTestOnUiThread(new Runnable() { 477 @Override 478 public void run() { 479 activity.initReplyRecipients(refMessage, ComposeActivity.FORWARD); 480 String[] to = activity.getToAddresses(); 481 String[] cc = activity.getCcAddresses(); 482 String[] bcc = activity.getBccAddresses(); 483 assertEquals(to.length, 0); 484 assertEquals(cc.length, 0); 485 assertEquals(bcc.length, 0); 486 } 487 }); 488 } 489 490 public void testCompose() throws Throwable { 491 final ComposeActivity activity = getActivity(); 492 setAccount(activity, "account0 (at) mockuiprovider.com"); 493 final Message refMessage = getRefMessage(activity.getContentResolver()); 494 495 runTestOnUiThread(new Runnable() { 496 @Override 497 public void run() { 498 activity.initReplyRecipients(refMessage, ComposeActivity.COMPOSE); 499 String[] to = activity.getToAddresses(); 500 String[] cc = activity.getCcAddresses(); 501 String[] bcc = activity.getBccAddresses(); 502 assertEquals(to.length, 0); 503 assertEquals(cc.length, 0); 504 assertEquals(bcc.length, 0); 505 } 506 }); 507 } 508 509 /** 510 * Test the cases where: The user is replying to a message they sent 511 */ 512 public void testRecipientsRefMessageReplyToSelf() throws Throwable { 513 final ComposeActivity activity = getActivity(); 514 setAccount(activity, "account0 (at) mockuiprovider.com"); 515 final Message refMessage = getRefMessage(activity.getContentResolver()); 516 refMessage.setFrom("account0 (at) mockuiprovider.com"); 517 refMessage.setTo("someotheraccount (at) mockuiprovider.com"); 518 519 runTestOnUiThread(new Runnable() { 520 @Override 521 public void run() { 522 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY); 523 String[] to = activity.getToAddresses(); 524 String[] cc = activity.getCcAddresses(); 525 String[] bcc = activity.getBccAddresses(); 526 assertEquals(to.length, 1); 527 assertTrue(to[0].contains(refMessage.getTo())); 528 assertEquals(cc.length, 0); 529 assertEquals(bcc.length, 0); 530 } 531 }); 532 } 533 534 /** 535 * Test the cases where: 536 * The user is replying to a message sent from one of their custom froms 537 */ 538 public void testRecipientsRefMessageReplyToCustomFrom() throws Throwable { 539 final ComposeActivity activity = getActivity(); 540 setAccount(activity, "account1 (at) mockuiprovider.com"); 541 final Message refMessage = getRefMessage(activity.getContentResolver()); 542 refMessage.setFrom("CUSTOMaccount1 (at) mockuiprovider.com"); 543 refMessage.setTo("someotheraccount (at) mockuiprovider.com"); 544 activity.mFromSpinner = new FromAddressSpinner(activity); 545 ReplyFromAccount a = new ReplyFromAccount(mAccount, mAccount.uri, refMessage.getFrom(), 546 refMessage.getFrom(), refMessage.getFrom(), true, true); 547 JSONArray array = new JSONArray(); 548 array.put(a.serialize()); 549 mAccount.accountFromAddresses = array.toString(); 550 ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri, 551 mAccount.name, mAccount.name, mAccount.name, true, false); 552 activity.mFromSpinner.setCurrentAccount(currentAccount); 553 activity.mFromSpinner.initialize(ComposeActivity.REPLY, currentAccount.account, 554 EMPTY_ACCOUNT_LIST, null); 555 556 runTestOnUiThread(new Runnable() { 557 @Override 558 public void run() { 559 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY); 560 String[] to = activity.getToAddresses(); 561 String[] cc = activity.getCcAddresses(); 562 String[] bcc = activity.getBccAddresses(); 563 assertEquals(to.length, 1); 564 assertTrue(to[0].contains(refMessage.getTo())); 565 assertEquals(cc.length, 0); 566 assertEquals(bcc.length, 0); 567 } 568 }); 569 } 570 571 /** 572 * Test the cases where: 573 * The user is replying to a message sent from one of their custom froms 574 */ 575 public void testRecipientsRefMessageReplyAllCustomFrom() throws Throwable { 576 final ComposeActivity activity = getActivity(); 577 setAccount(activity, "account1 (at) mockuiprovider.com"); 578 final Message refMessage = getRefMessage(activity.getContentResolver()); 579 final String customFrom = "CUSTOMaccount1 (at) mockuiprovider.com"; 580 refMessage.setFrom("senderaccount (at) mockuiprovider.com"); 581 refMessage.setTo("someotheraccount (at) mockuiprovider.com, " 582 + "someotheraccount2 (at) mockuiprovider.com, someotheraccount4 (at) mockuiprovider.com, " 583 + customFrom); 584 activity.mFromSpinner = new FromAddressSpinner(activity); 585 ReplyFromAccount a = new ReplyFromAccount(mAccount, mAccount.uri, customFrom, 586 customFrom, customFrom, true, true); 587 JSONArray array = new JSONArray(); 588 array.put(a.serialize()); 589 mAccount.accountFromAddresses = array.toString(); 590 ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri, 591 mAccount.name, mAccount.name, mAccount.name, true, false); 592 activity.mFromSpinner.setCurrentAccount(currentAccount); 593 activity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL, 594 currentAccount.account, EMPTY_ACCOUNT_LIST, null); 595 runTestOnUiThread(new Runnable() { 596 @Override 597 public void run() { 598 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL); 599 String[] to = activity.getToAddresses(); 600 String[] cc = activity.getCcAddresses(); 601 String[] bcc = activity.getBccAddresses(); 602 String toAsString = TextUtils.join(",", to); 603 String ccAsString = TextUtils.join(",", cc); 604 String bccAsString = TextUtils.join(",", bcc); 605 assertEquals(to.length, 1); 606 assertFalse(toAsString.contains(customFrom)); 607 assertFalse(ccAsString.contains(customFrom)); 608 assertFalse(bccAsString.contains(customFrom)); 609 } 610 }); 611 } 612 613 /** 614 * Test the cases where: 615 * The user is replying to a message sent from one of their custom froms 616 */ 617 public void testRecipientsRefMessageReplyAllCustomFromThisAccount() throws Throwable { 618 final ComposeActivity activity = getActivity(); 619 setAccount(activity, "account1 (at) mockuiprovider.com"); 620 final Message refMessage = getRefMessage(activity.getContentResolver()); 621 final String customFrom = "CUSTOMaccount1 (at) mockuiprovider.com"; 622 refMessage.setFrom("account1 (at) mockuiprovider.com"); 623 refMessage.setTo("someotheraccount (at) mockuiprovider.com, " 624 + "someotheraccount2 (at) mockuiprovider.com, someotheraccount4 (at) mockuiprovider.com, " 625 + customFrom); 626 activity.mFromSpinner = new FromAddressSpinner(activity); 627 ReplyFromAccount a = new ReplyFromAccount(mAccount, mAccount.uri, customFrom, 628 customFrom, customFrom, true, true); 629 JSONArray array = new JSONArray(); 630 array.put(a.serialize()); 631 mAccount.accountFromAddresses = array.toString(); 632 ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri, 633 mAccount.name, mAccount.name, mAccount.name, true, false); 634 activity.mFromSpinner.setCurrentAccount(currentAccount); 635 activity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL, 636 currentAccount.account, EMPTY_ACCOUNT_LIST, null); 637 runTestOnUiThread(new Runnable() { 638 @Override 639 public void run() { 640 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL); 641 String[] to = activity.getToAddresses(); 642 String[] cc = activity.getCcAddresses(); 643 String[] bcc = activity.getBccAddresses(); 644 String toAsString = TextUtils.join(",", to); 645 String ccAsString = TextUtils.join(",", cc); 646 String bccAsString = TextUtils.join(",", bcc); 647 // Should have the same count as the original message. 648 assertEquals(to.length, 3); 649 assertFalse(toAsString.contains(customFrom)); 650 assertFalse(ccAsString.contains(customFrom)); 651 assertFalse(bccAsString.contains(customFrom)); 652 } 653 }); 654 } 655 656 // Test replying to a message in the first account in the list, and verify that 657 // the Compose Activity's from account for the reply is correct 658 public void testReplySendingAccount0() throws Throwable { 659 final Context context = getInstrumentation().getContext(); 660 // Get the test account 661 final Account currentAccount = getAccountForName(context, "account0 (at) mockuiprovider.com"); 662 663 // Get the message to be replied to 664 final Message refMessage = 665 getRefMessage(context.getContentResolver(), currentAccount.folderListUri); 666 667 // Create the reply intent 668 final Intent replyIntent = 669 ComposeActivity.updateActionIntent(currentAccount, refMessage.uri, 670 ComposeActivity.REPLY, new Intent()); 671 672 setActivityIntent(replyIntent); 673 674 final ComposeActivity activity = getActivity(); 675 final String refMessageFromAccount = refMessage.getFrom(); 676 677 runTestOnUiThread(new Runnable() { 678 @Override 679 public void run() { 680 String[] to = activity.getToAddresses(); 681 String[] cc = activity.getCcAddresses(); 682 String[] bcc = activity.getBccAddresses(); 683 Account fromAccount = activity.getFromAccount(); 684 assertEquals(1, to.length); 685 assertEquals(refMessageFromAccount, 686 Rfc822Tokenizer.tokenize(to[0])[0].getAddress()); 687 assertEquals(0, cc.length); 688 assertEquals(0, bcc.length); 689 assertEquals("account0 (at) mockuiprovider.com", fromAccount.getEmailAddress()); 690 } 691 }); 692 } 693 694 // Test replying to a message in the third account in the list, and verify that 695 // the Compose Activity's from account for the reply is correct 696 public void testReplySendingAccount1() throws Throwable { 697 final Context context = getInstrumentation().getContext(); 698 // Get the test account 699 final Account currentAccount = getAccountForName(context, "account2 (at) mockuiprovider.com"); 700 701 // Get the message to be replied to 702 final Message refMessage = 703 getRefMessage(context.getContentResolver(), currentAccount.folderListUri); 704 705 // Create the reply intent 706 final Intent replyIntent = 707 ComposeActivity.updateActionIntent(currentAccount, refMessage.uri, 708 ComposeActivity.REPLY, new Intent()); 709 710 setActivityIntent(replyIntent); 711 712 final ComposeActivity activity = getActivity(); 713 Account fromAccount = activity.getFromAccount(); 714 715 final String refMessageFromAccount = refMessage.getFrom(); 716 717 runTestOnUiThread(new Runnable() { 718 @Override 719 public void run() { 720 String[] to = activity.getToAddresses(); 721 String[] cc = activity.getCcAddresses(); 722 String[] bcc = activity.getBccAddresses(); 723 Account fromAccount = activity.getFromAccount(); 724 assertEquals(1, to.length); 725 assertEquals(refMessageFromAccount, 726 Rfc822Tokenizer.tokenize(to[0])[0].getAddress()); 727 assertEquals(0, cc.length); 728 assertEquals(0, bcc.length); 729 assertEquals("account2 (at) mockuiprovider.com", fromAccount.getEmailAddress()); 730 } 731 }); 732 } 733 734 // Test a mailto VIEW Intent, with an account specified in JSON format 735 public void testMailToAccountJSON() throws Throwable { 736 final Context context = getInstrumentation().getContext(); 737 // Get the test account 738 final Account currentAccount = getAccountForName(context, "account2 (at) mockuiprovider.com"); 739 740 // Create the mailto intent 741 final Intent mailtoIntent = 742 new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:test (at) localhost.com")); 743 mailtoIntent.putExtra(Utils.EXTRA_ACCOUNT, currentAccount.serialize()); 744 745 setActivityIntent(mailtoIntent); 746 747 final ComposeActivity activity = getActivity(); 748 Account fromAccount = activity.getFromAccount(); 749 750 runTestOnUiThread(new Runnable() { 751 @Override 752 public void run() { 753 String[] to = activity.getToAddresses(); 754 String[] cc = activity.getCcAddresses(); 755 String[] bcc = activity.getBccAddresses(); 756 Account fromAccount = activity.getFromAccount(); 757 assertEquals( 1, to.length); 758 assertEquals("test (at) localhost.com", 759 Rfc822Tokenizer.tokenize(to[0])[0].getAddress()); 760 assertEquals(0, cc.length); 761 assertEquals(0, bcc.length); 762 assertEquals("account2 (at) mockuiprovider.com", fromAccount.getEmailAddress()); 763 } 764 }); 765 } 766 767 // Test a COMPOSE Intent, with an account specified in parcel format 768 public void testMailToAccount() throws Throwable { 769 final Context context = getInstrumentation().getContext(); 770 // Get the test account 771 final Account currentAccount = getAccountForName(context, "account2 (at) mockuiprovider.com"); 772 773 // Create the mailto intent 774 Intent intent = new Intent(context, ComposeActivity.class); 775 intent.putExtra(ComposeActivity.EXTRA_FROM_EMAIL_TASK, true); 776 intent.putExtra(ComposeActivity.EXTRA_ACTION, ComposeActivity.COMPOSE); 777 intent.putExtra(Utils.EXTRA_ACCOUNT, currentAccount); 778 intent.putExtra(ComposeActivity.EXTRA_TO, "test (at) localhost.com"); 779 780 setActivityIntent(intent); 781 782 final ComposeActivity activity = getActivity(); 783 Account fromAccount = activity.getFromAccount(); 784 785 runTestOnUiThread(new Runnable() { 786 @Override 787 public void run() { 788 String[] to = activity.getToAddresses(); 789 String[] cc = activity.getCcAddresses(); 790 String[] bcc = activity.getBccAddresses(); 791 Account fromAccount = activity.getFromAccount(); 792 assertEquals( 1, to.length); 793 assertEquals("test (at) localhost.com", 794 Rfc822Tokenizer.tokenize(to[0])[0].getAddress()); 795 assertEquals(0, cc.length); 796 assertEquals(0, bcc.length); 797 assertEquals("account2 (at) mockuiprovider.com", fromAccount.getEmailAddress()); 798 } 799 }); 800 } 801 802 // Test a mailto VIEW Intent, with no account specified. The fromAccount should default to the 803 // last sent account. 804 public void testMailToAccountWithLastSentAccount() throws Throwable { 805 final Context context = getInstrumentation().getContext(); 806 807 // Set the last sent account to account0 808 final Account lastSentAccount = getAccountForName(context, "account1 (at) mockuiprovider.com"); 809 MailAppProvider appProvider = MailAppProvider.getInstance(); 810 appProvider.setLastSentFromAccount(lastSentAccount.uri.toString()); 811 812 // Create the mailto intent 813 final Intent mailtoIntent = 814 new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:test (at) localhost.com")); 815 816 setActivityIntent(mailtoIntent); 817 818 final ComposeActivity activity = getActivity(); 819 Account fromAccount = activity.getFromAccount(); 820 821 runTestOnUiThread(new Runnable() { 822 @Override 823 public void run() { 824 String[] to = activity.getToAddresses(); 825 String[] cc = activity.getCcAddresses(); 826 String[] bcc = activity.getBccAddresses(); 827 Account fromAccount = activity.getFromAccount(); 828 assertEquals( 1, to.length); 829 assertEquals("test (at) localhost.com", 830 Rfc822Tokenizer.tokenize(to[0])[0].getAddress()); 831 assertEquals(0, cc.length); 832 assertEquals(0, bcc.length); 833 assertEquals("account1 (at) mockuiprovider.com", fromAccount.getEmailAddress()); 834 } 835 }); 836 } 837 838 private static String createAttachmentsJson() { 839 Attachment attachment1 = new Attachment(); 840 attachment1.contentUri = Uri.parse("www.google.com"); 841 attachment1.setContentType("img/jpeg"); 842 attachment1.setName("attachment1"); 843 Attachment attachment2 = new Attachment(); 844 attachment2.contentUri = Uri.parse("www.google.com"); 845 attachment2.setContentType("img/jpeg"); 846 attachment2.setName("attachment2"); 847 JSONArray attachments = new JSONArray(); 848 try { 849 attachments.put(attachment1.toJSON()); 850 attachments.put(attachment2.toJSON()); 851 } catch (JSONException e) { 852 assertTrue(false); 853 } 854 return attachments.toString(); 855 } 856 857 // First test: switch reply to reply all to fwd, 1 to recipient, 1 cc recipient. 858 public void testChangeModes0() throws Throwable { 859 final ComposeActivity activity = getActivity(); 860 setAccount(activity, "account0 (at) mockuiprovider.com"); 861 final Message refMessage = getRefMessage(activity.getContentResolver()); 862 refMessage.setFrom("fromaccount (at) mockuiprovider.com"); 863 refMessage.setTo("account0 (at) mockuiprovider.com"); 864 refMessage.setCc("ccaccount (at) mockuiprovider.com"); 865 runTestOnUiThread(new Runnable() { 866 @Override 867 public void run() { 868 activity.mRefMessage = refMessage; 869 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY); 870 String[] to = activity.getToAddresses(); 871 String[] cc = activity.getCcAddresses(); 872 String[] bcc = activity.getBccAddresses(); 873 assertEquals(1, to.length); 874 assertTrue(to[0].contains(refMessage.getFrom())); 875 assertEquals(cc.length, 0); 876 assertEquals(bcc.length, 0); 877 activity.onNavigationItemSelected(1, ComposeActivity.REPLY_ALL); 878 assertEquals(activity.getToAddresses().length, 1); 879 assertTrue(activity.getToAddresses()[0].contains(refMessage.getFrom())); 880 assertEquals(activity.getCcAddresses().length, 1); 881 assertTrue(activity.getCcAddresses()[0].contains(refMessage.getCc())); 882 assertEquals(activity.getBccAddresses().length, 0); 883 activity.onNavigationItemSelected(2, ComposeActivity.FORWARD); 884 assertEquals(activity.getToAddresses().length, 0); 885 assertEquals(activity.getCcAddresses().length, 0); 886 assertEquals(activity.getBccAddresses().length, 0); 887 } 888 }); 889 } 890 891 // Switch reply to reply all to fwd, 2 to recipients, 1 cc recipient. 892 public void testChangeModes1() throws Throwable { 893 final ComposeActivity activity = getActivity(); 894 setAccount(activity, "account0 (at) mockuiprovider.com"); 895 final Message refMessage = getRefMessage(activity.getContentResolver()); 896 refMessage.setFrom("fromaccount (at) mockuiprovider.com"); 897 refMessage.setTo("account0 (at) mockuiprovider.com, toaccount0 (at) mockuiprovider.com"); 898 refMessage.setCc("ccaccount (at) mockuiprovider.com"); 899 runTestOnUiThread(new Runnable() { 900 @Override 901 public void run() { 902 activity.mRefMessage = refMessage; 903 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY); 904 String[] to = activity.getToAddresses(); 905 String[] cc = activity.getCcAddresses(); 906 String[] bcc = activity.getBccAddresses(); 907 assertEquals(to.length, 1); 908 assertTrue(to[0].contains(refMessage.getFrom())); 909 assertEquals(cc.length, 0); 910 assertEquals(bcc.length, 0); 911 activity.onNavigationItemSelected(1, ComposeActivity.REPLY_ALL); 912 assertEquals(activity.getToAddresses().length, 1); 913 assertTrue(activity.getToAddresses()[0].contains(refMessage.getFrom())); 914 assertEquals(activity.getCcAddresses().length, 2); 915 assertTrue(activity.getCcAddresses()[0].contains(refMessage.getCc()) 916 || activity.getCcAddresses()[1].contains(refMessage.getCc())); 917 assertTrue(activity.getCcAddresses()[0].contains("toaccount0 (at) mockuiprovider.com") 918 || activity.getCcAddresses()[1] 919 .contains("toaccount0 (at) mockuiprovider.com")); 920 assertEquals(activity.getBccAddresses().length, 0); 921 activity.onNavigationItemSelected(2, ComposeActivity.FORWARD); 922 assertEquals(activity.getToAddresses().length, 0); 923 assertEquals(activity.getCcAddresses().length, 0); 924 assertEquals(activity.getBccAddresses().length, 0); 925 } 926 }); 927 } 928 929 // Switch reply to reply all to fwd, 2 to recipients, 2 cc recipients. 930 public void testChangeModes2() throws Throwable { 931 final ComposeActivity activity = getActivity(); 932 setAccount(activity, "account0 (at) mockuiprovider.com"); 933 final Message refMessage = getRefMessage(activity.getContentResolver()); 934 refMessage.setFrom("fromaccount (at) mockuiprovider.com"); 935 refMessage.setTo("account0 (at) mockuiprovider.com, toaccount0 (at) mockuiprovider.com"); 936 refMessage.setCc("ccaccount (at) mockuiprovider.com, ccaccount2 (at) mockuiprovider.com"); 937 runTestOnUiThread(new Runnable() { 938 @Override 939 public void run() { 940 activity.mRefMessage = refMessage; 941 activity.initReplyRecipients(refMessage, ComposeActivity.REPLY); 942 String[] to = activity.getToAddresses(); 943 String[] cc = activity.getCcAddresses(); 944 String[] bcc = activity.getBccAddresses(); 945 assertEquals(to.length, 1); 946 assertTrue(to[0].contains(refMessage.getFrom())); 947 assertEquals(cc.length, 0); 948 assertEquals(bcc.length, 0); 949 activity.onNavigationItemSelected(1, ComposeActivity.REPLY_ALL); 950 assertEquals(activity.getToAddresses().length, 1); 951 assertTrue(activity.getToAddresses()[0].contains(refMessage.getFrom())); 952 assertEquals(activity.getCcAddresses().length, 3); 953 assertTrue(activity.getCcAddresses()[0].contains("ccaccount (at) mockuiprovider.com") 954 || activity.getCcAddresses()[1].contains("ccaccount (at) mockuiprovider.com") 955 || activity.getCcAddresses()[2].contains("ccaccount (at) mockuiprovider.com")); 956 assertTrue(activity.getCcAddresses()[0].contains("ccaccount2 (at) mockuiprovider.com") 957 || activity.getCcAddresses()[1].contains("ccaccount2 (at) mockuiprovider.com") 958 || activity.getCcAddresses()[2].contains("ccaccount2 (at) mockuiprovider.com")); 959 assertTrue(activity.getCcAddresses()[0].contains("toaccount0 (at) mockuiprovider.com") 960 || activity.getCcAddresses()[1].contains("toaccount0 (at) mockuiprovider.com") 961 || activity.getCcAddresses()[2].contains("toaccount0 (at) mockuiprovider.com")); 962 assertTrue(activity.getCcAddresses()[0].contains("toaccount0 (at) mockuiprovider.com") 963 || activity.getCcAddresses()[1] 964 .contains("toaccount0 (at) mockuiprovider.com") 965 || activity.getCcAddresses()[2] 966 .contains("toaccount0 (at) mockuiprovider.com")); 967 assertEquals(activity.getBccAddresses().length, 0); 968 activity.onNavigationItemSelected(2, ComposeActivity.FORWARD); 969 assertEquals(activity.getToAddresses().length, 0); 970 assertEquals(activity.getCcAddresses().length, 0); 971 assertEquals(activity.getBccAddresses().length, 0); 972 } 973 }); 974 } 975 976 // Switch reply to reply all to fwd, 2 attachments. 977 public void testChangeModes3() throws Throwable { 978 final ComposeActivity activity = getActivity(); 979 setAccount(activity, "account0 (at) mockuiprovider.com"); 980 final Message refMessage = getRefMessage(activity.getContentResolver()); 981 refMessage.hasAttachments = true; 982 refMessage.attachmentsJson = createAttachmentsJson(); 983 runTestOnUiThread(new Runnable() { 984 @Override 985 public void run() { 986 activity.mRefMessage = refMessage; 987 activity.initAttachments(refMessage); 988 assertEquals(activity.getAttachments().size(), 2); 989 activity.onNavigationItemSelected(1, ComposeActivity.REPLY); 990 assertEquals(activity.getAttachments().size(), 0); 991 activity.onNavigationItemSelected(1, ComposeActivity.REPLY_ALL); 992 assertEquals(activity.getAttachments().size(), 0); 993 activity.onNavigationItemSelected(2, ComposeActivity.FORWARD); 994 assertEquals(activity.getAttachments().size(), 2); 995 } 996 }); 997 } 998 } 999