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