ChipsTest.java revision b1cddbb70524197b68d99a6805a97d50eef4e353
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.ex.chips;
18
19import android.content.Context;
20import android.graphics.Bitmap;
21import android.graphics.drawable.BitmapDrawable;
22import android.graphics.drawable.Drawable;
23import android.test.AndroidTestCase;
24import android.test.suitebuilder.annotation.SmallTest;
25import android.text.Editable;
26import android.text.SpannableStringBuilder;
27import android.text.style.ImageSpan;
28import android.text.util.Rfc822Tokenizer;
29import android.widget.TextView;
30
31import com.android.ex.chips.RecipientEditTextView;
32import com.android.ex.chips.RecipientEntry;
33
34@SmallTest
35public class ChipsTest extends AndroidTestCase {
36    private RecipientChip[] mMockRecips;
37
38    private RecipientEntry[] mMockEntries;
39
40    private Rfc822Tokenizer mTokenizer;
41
42    private Editable mEditable;
43
44    class BaseMockRecipientEditTextView extends RecipientEditTextView {
45
46        public BaseMockRecipientEditTextView(Context context) {
47            super(context, null);
48            mTokenizer = new Rfc822Tokenizer();
49            setTokenizer(mTokenizer);
50        }
51
52        @Override
53        public RecipientChip[] getSortedRecipients() {
54            return mMockRecips;
55        }
56
57        @Override
58        public int getLineHeight() {
59            return 48;
60        }
61
62        @Override
63        Drawable getChipBackground(RecipientEntry contact) {
64            return createChipBackground();
65        }
66
67        @Override
68        public int getViewWidth() {
69            return 100;
70        }
71    }
72
73    class MockRecipientEditTextView extends BaseMockRecipientEditTextView {
74
75        public MockRecipientEditTextView(Context context) {
76            super(context);
77            mTokenizer = new Rfc822Tokenizer();
78            setTokenizer(mTokenizer);
79        }
80
81        @Override
82        public RecipientChip[] getSortedRecipients() {
83            return mMockRecips;
84        }
85
86        @Override
87        public Editable getText() {
88            return mEditable;
89        }
90
91        @Override
92        public Editable getSpannable() {
93            return mEditable;
94        }
95
96        @Override
97        public int getLineHeight() {
98            return 48;
99        }
100
101        @Override
102        Drawable getChipBackground(RecipientEntry contact) {
103            return createChipBackground();
104        }
105
106        @Override
107        public int length() {
108            return mEditable != null ? mEditable.length() : 0;
109        }
110
111        @Override
112        public String toString() {
113            return mEditable != null ? mEditable.toString() : "";
114        }
115
116        @Override
117        public int getViewWidth() {
118            return 100;
119        }
120    }
121
122    private class TestBaseRecipientAdapter extends BaseRecipientAdapter {
123        public TestBaseRecipientAdapter(Context context) {
124            super(context);
125        }
126    }
127
128    private MockRecipientEditTextView createViewForTesting() {
129        mEditable = new SpannableStringBuilder();
130        MockRecipientEditTextView view = new MockRecipientEditTextView(getContext());
131        view.setAdapter(new TestBaseRecipientAdapter(getContext()));
132        return view;
133    }
134
135    public void testCreateDisplayText() {
136        android.os.Debug.waitForDebugger();
137        RecipientEditTextView view = createViewForTesting();
138        RecipientEntry entry = RecipientEntry.constructGeneratedEntry("User Name, Jr",
139                "user@username.com", true);
140        String testAddress = view.createAddressText(entry);
141        String testDisplay = view.createChipDisplayText(entry);
142        assertEquals("Expected a properly formatted RFC email address",
143                "\"User Name, Jr\" <user@username.com>, ", testAddress);
144        assertEquals("Expected a displayable name", "User Name, Jr", testDisplay);
145
146
147        RecipientEntry alreadyFormatted =
148                RecipientEntry.constructFakeEntry("user@username.com, ", true);
149        testAddress = view.createAddressText(alreadyFormatted);
150        testDisplay = view.createChipDisplayText(alreadyFormatted);
151        assertEquals("Expected a properly formatted RFC email address", "<user@username.com>, ",
152                testAddress);
153        assertEquals("Expected a displayable name", "user@username.com", testDisplay);
154
155        RecipientEntry alreadyFormattedNoSpace = RecipientEntry
156                .constructFakeEntry("user@username.com,", true);
157        testAddress = view.createAddressText(alreadyFormattedNoSpace);
158        assertEquals("Expected a properly formatted RFC email address", "<user@username.com>, ",
159                testAddress);
160
161        RecipientEntry alreadyNamed = RecipientEntry.constructGeneratedEntry("User Name",
162                "\"User Name, Jr\" <user@username.com>", true);
163        testAddress = view.createAddressText(alreadyNamed);
164        testDisplay = view.createChipDisplayText(alreadyNamed);
165        assertEquals(
166                "Expected address that used the name not the excess address name",
167                "User Name <user@username.com>, ", testAddress);
168        assertEquals("Expected a displayable name", "User Name", testDisplay);
169    }
170
171    public void testSanitizeBetween() {
172        // First, add 2 chips and then make sure we remove
173        // the extra content between them correctly.
174        populateMocks(2);
175        MockRecipientEditTextView view = createViewForTesting();
176        String first = (String) mTokenizer.terminateToken("FIRST");
177        String second = (String) mTokenizer.terminateToken("SECOND");
178        String extra = "EXTRA";
179        mEditable = new SpannableStringBuilder();
180        mEditable.append(first + extra + second);
181        int firstStart = mEditable.toString().indexOf(first);
182        int firstEnd = firstStart + first.trim().length();
183        int secondStart = mEditable.toString().indexOf(second);
184        int secondEnd = secondStart + second.trim().length();
185        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], firstStart, firstEnd, 0);
186        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], secondStart, secondEnd, 0);
187        view.sanitizeBetween();
188        String editableString = mEditable.toString();
189        assertEquals(editableString.indexOf(extra), -1);
190        assertEquals(editableString.indexOf(first), firstStart);
191        assertEquals(editableString.indexOf(second), secondStart - extra.length());
192        assertEquals(editableString, (first + second));
193
194        // Add 1 chip and make sure that we remove the extra stuff before it correctly.
195        mEditable = new SpannableStringBuilder();
196        populateMocks(1);
197        mEditable.append(extra);
198        mEditable.append(first);
199        firstStart = mEditable.toString().indexOf(first);
200        firstEnd = firstStart + first.length();
201        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], firstStart, firstEnd, 0);
202        view.sanitizeBetween();
203        assertEquals(mEditable.toString(), first);
204        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), firstStart
205                - extra.length());
206    }
207
208    public void testSanitizeEnd() {
209        // First, add 2 chips and then make sure we remove
210        // the extra content between them correctly.
211        populateMocks(2);
212        MockRecipientEditTextView view = createViewForTesting();
213        String first = (String) mTokenizer.terminateToken("FIRST");
214        String second = (String) mTokenizer.terminateToken("SECOND");
215        String extra = "EXTRA";
216        mEditable = new SpannableStringBuilder();
217        mEditable.append(first + second);
218        int firstStart = mEditable.toString().indexOf(first);
219        int firstEnd = firstStart + first.trim().length();
220        int secondStart = mEditable.toString().indexOf(second);
221        int secondEnd = secondStart + second.trim().length();
222        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], firstStart, firstEnd, 0);
223        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], secondStart, secondEnd, 0);
224        view.sanitizeEnd();
225        String editableString = mEditable.toString();
226        assertEquals(editableString.indexOf(extra), -1);
227        assertEquals(editableString.indexOf(first), firstStart);
228        assertEquals(editableString.indexOf(second), secondStart);
229        assertEquals(editableString, (first + second));
230        mEditable.append(extra);
231        editableString = mEditable.toString();
232        assertEquals(mEditable.toString(), (first + second + extra));
233        view.sanitizeEnd();
234        assertEquals(mEditable.toString(), (first + second));
235    }
236
237    public void testMoreChipPlainText() {
238        MockRecipientEditTextView view = createViewForTesting();
239        view.setMoreItem(createTestMoreItem());
240        String first = (String) mTokenizer.terminateToken("FIRST");
241        String second = (String) mTokenizer.terminateToken("SECOND");
242        String third = (String) mTokenizer.terminateToken("THIRD");
243        mEditable = new SpannableStringBuilder();
244        mEditable.append(first+second+third);
245        int thirdStart = mEditable.toString().indexOf(third);
246        int thirdEnd = thirdStart + third.trim().length();
247        view.createMoreChipPlainText();
248        ImageSpan moreChip = view.getMoreChip();
249        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
250        assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd + 1);
251    }
252
253    public void testCountTokens() {
254        MockRecipientEditTextView view = createViewForTesting();
255        view.setMoreItem(createTestMoreItem());
256        String first = (String) mTokenizer.terminateToken("FIRST");
257        String second = (String) mTokenizer.terminateToken("SECOND");
258        String third = (String) mTokenizer.terminateToken("THIRD");
259        String fourth = (String) ("FOURTH,");
260        String fifth = (String) ("FIFTH,");
261        mEditable = new SpannableStringBuilder();
262        mEditable.append(first+second+third+fourth+fifth);
263        assertEquals(view.countTokens(mEditable), 5);
264    }
265
266    public void testTooManyRecips() {
267        BaseMockRecipientEditTextView view = new BaseMockRecipientEditTextView(getContext());
268        view.setMoreItem(createTestMoreItem());
269        for (int i = 0; i < 100; i++) {
270            view.append(mTokenizer.terminateToken(i + ""));
271        }
272        assertEquals(view.countTokens(view.getText()), 100);
273        view.handlePendingChips();
274        view.createMoreChip();
275        ImageSpan moreChip = view.getMoreChip();
276        // We show 2 chips then place a more chip.
277        int secondStart = view.getText().toString().indexOf(
278                (String) mTokenizer.terminateToken(RecipientEditTextView.CHIP_LIMIT + ""));
279        assertEquals(view.getText().getSpanStart(moreChip), secondStart);
280        assertEquals(view.getText().getSpanEnd(moreChip), view.length());
281        assertEquals(view.getSortedRecipients(), null);
282    }
283
284    public void testMoreChip() {
285        // Add 3 chips: this is the trigger point at which the more chip will be created.
286        // Test that adding the chips and then creating and removing the more chip, as if
287        // the user were focusing/ removing focus from the chips field.
288        populateMocks(3);
289        MockRecipientEditTextView view = createViewForTesting();
290        view.setMoreItem(createTestMoreItem());
291        String first = (String) mTokenizer.terminateToken("FIRST");
292        String second = (String) mTokenizer.terminateToken("SECOND");
293        String third = (String) mTokenizer.terminateToken("THIRD");
294        mEditable = new SpannableStringBuilder();
295        mEditable.append(first+second+third);
296
297        int firstStart = mEditable.toString().indexOf(first);
298        int firstEnd = firstStart + first.trim().length();
299        int secondStart = mEditable.toString().indexOf(second);
300        int secondEnd = secondStart + second.trim().length();
301        int thirdStart = mEditable.toString().indexOf(third);
302        int thirdEnd = thirdStart + third.trim().length();
303        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
304        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
305        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
306
307        view.createMoreChip();
308        assertEquals(mEditable.toString(), first+second+third);
309        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
310        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
311        // Find the more chip.
312        ImageSpan moreChip = view.getMoreChip();
313        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
314        assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd + 1);
315
316        view.removeMoreChip();
317        assertEquals(mEditable.toString(), first+second+third);
318        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
319        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd);
320        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
321        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart);
322        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd);
323        moreChip = view.getMoreChip();
324        assertEquals(mEditable.getSpanStart(moreChip), -1);
325
326        // Rinse and repeat, just in case!
327        view.createMoreChip();
328        assertEquals(mEditable.toString(), first+second+third);
329        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
330        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
331        // Find the more chip.
332        moreChip = view.getMoreChip();
333        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
334        assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd + 1);
335
336        view.removeMoreChip();
337        assertEquals(mEditable.toString(), first+second+third);
338        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
339        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd);
340        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
341        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart);
342        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd);
343        moreChip = view.getMoreChip();
344        assertEquals(mEditable.getSpanStart(moreChip), -1);
345    }
346
347    public void testMoreChipLotsOfUsers() {
348        // Test adding and removing the more chip in the case where we have a lot of users.
349        populateMocks(10);
350        MockRecipientEditTextView view = createViewForTesting();
351        view.setMoreItem(createTestMoreItem());
352        String first = (String) mTokenizer.terminateToken("FIRST");
353        String second = (String) mTokenizer.terminateToken("SECOND");
354        String third = (String) mTokenizer.terminateToken("THIRD");
355        String fourth = (String) mTokenizer.terminateToken("FOURTH");
356        String fifth = (String) mTokenizer.terminateToken("FIFTH");
357        String sixth = (String) mTokenizer.terminateToken("SIXTH");
358        String seventh = (String) mTokenizer.terminateToken("SEVENTH");
359        String eigth = (String) mTokenizer.terminateToken("EIGHTH");
360        String ninth = (String) mTokenizer.terminateToken("NINTH");
361        String tenth = (String) mTokenizer.terminateToken("TENTH");
362        mEditable = new SpannableStringBuilder();
363        mEditable.append(first+second+third+fourth+fifth+sixth+seventh+eigth+ninth+tenth);
364
365        int firstStart = mEditable.toString().indexOf(first);
366        int firstEnd = firstStart + first.trim().length();
367        int secondStart = mEditable.toString().indexOf(second);
368        int secondEnd = secondStart + second.trim().length();
369        int thirdStart = mEditable.toString().indexOf(third);
370        int thirdEnd = thirdStart + third.trim().length();
371        int fourthStart = mEditable.toString().indexOf(fourth);
372        int fourthEnd = fourthStart + fourth.trim().length();
373        int fifthStart = mEditable.toString().indexOf(fifth);
374        int fifthEnd = fifthStart + fifth.trim().length();
375        int sixthStart = mEditable.toString().indexOf(sixth);
376        int sixthEnd = sixthStart + sixth.trim().length();
377        int seventhStart = mEditable.toString().indexOf(seventh);
378        int seventhEnd = seventhStart + seventh.trim().length();
379        int eighthStart = mEditable.toString().indexOf(eigth);
380        int eighthEnd = eighthStart + eigth.trim().length();
381        int ninthStart = mEditable.toString().indexOf(ninth);
382        int ninthEnd = ninthStart + ninth.trim().length();
383        int tenthStart = mEditable.toString().indexOf(tenth);
384        int tenthEnd = tenthStart + tenth.trim().length();
385        mEditable.setSpan(mMockRecips[mMockRecips.length - 10], firstStart, firstEnd, 0);
386        mEditable.setSpan(mMockRecips[mMockRecips.length - 9], secondStart, secondEnd, 0);
387        mEditable.setSpan(mMockRecips[mMockRecips.length - 8], thirdStart, thirdEnd, 0);
388        mEditable.setSpan(mMockRecips[mMockRecips.length - 7], fourthStart, fourthEnd, 0);
389        mEditable.setSpan(mMockRecips[mMockRecips.length - 6], fifthStart, fifthEnd, 0);
390        mEditable.setSpan(mMockRecips[mMockRecips.length - 5], sixthStart, sixthEnd, 0);
391        mEditable.setSpan(mMockRecips[mMockRecips.length - 4], seventhStart, seventhEnd, 0);
392        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], eighthStart, eighthEnd, 0);
393        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], ninthStart, ninthEnd, 0);
394        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], tenthStart, tenthEnd, 0);
395
396        view.createMoreChip();
397        assertEquals(mEditable.toString(), first + second + third + fourth + fifth + sixth
398                + seventh + eigth + ninth + tenth);
399        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 10]), firstStart);
400        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 9]), secondStart);
401        // Find the more chip.
402        ImageSpan moreChip = view.getMoreChip();
403        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
404        assertEquals(mEditable.getSpanEnd(moreChip), tenthEnd + 1);
405
406        view.removeMoreChip();
407        assertEquals(mEditable.toString(), first + second + third + fourth + fifth + sixth
408                + seventh + eigth + ninth + tenth);
409        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 10]), firstStart);
410        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 9]), secondStart);
411
412        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 8]), thirdStart);
413        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 7]), fourthStart);
414        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 6]), fifthStart);
415        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 5]), sixthStart);
416        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), seventhStart);
417        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), eighthStart);
418        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), ninthStart);
419        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), tenthStart);
420        moreChip = view.getMoreChip();
421        assertEquals(mEditable.getSpanStart(moreChip), -1);
422
423    }
424
425    public void testMoreChipSpecialChars() {
426        // Make sure the more chip correctly handles extra tokenizer characters in the middle
427        // of chip text.
428        populateMocks(3);
429        MockRecipientEditTextView view = createViewForTesting();
430        view.setMoreItem(createTestMoreItem());
431        String first = (String) mTokenizer.terminateToken("FI,RST");
432        String second = (String) mTokenizer.terminateToken("SE,COND");
433        String third = (String) mTokenizer.terminateToken("THI,RD");
434        mEditable = new SpannableStringBuilder();
435        mEditable.append(first+second+third);
436
437        int firstStart = mEditable.toString().indexOf(first);
438        int firstEnd = firstStart + first.trim().length();
439        int secondStart = mEditable.toString().indexOf(second);
440        int secondEnd = secondStart + second.trim().length();
441        int thirdStart = mEditable.toString().indexOf(third);
442        int thirdEnd = thirdStart + third.trim().length();
443        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
444        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
445        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
446
447        view.createMoreChip();
448        assertEquals(mEditable.toString(), first+second+third);
449        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
450        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
451        // Find the more chip.
452        ImageSpan moreChip = view.getMoreChip();
453        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
454        assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd + 1);
455
456        view.removeMoreChip();
457        assertEquals(mEditable.toString(), first+second+third);
458        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
459        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd);
460        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
461        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart);
462        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd);
463        moreChip = view.getMoreChip();
464        assertEquals(mEditable.getSpanStart(moreChip), -1);
465    }
466
467    public void testMoreChipDupes() {
468        // Make sure the more chip is correctly added and removed when we have duplicate chips.
469        populateMocks(4);
470        MockRecipientEditTextView view = createViewForTesting();
471        view.setMoreItem(createTestMoreItem());
472        String first = (String) mTokenizer.terminateToken("FIRST");
473        String second = (String) mTokenizer.terminateToken("SECOND");
474        String third = (String) mTokenizer.terminateToken("THIRD");
475        mEditable = new SpannableStringBuilder();
476        mEditable.append(first+second+third+third);
477
478        int firstStart = mEditable.toString().indexOf(first);
479        int firstEnd = firstStart + first.trim().length();
480        int secondStart = mEditable.toString().indexOf(second);
481        int secondEnd = secondStart + second.trim().length();
482        int thirdStart = mEditable.toString().indexOf(third);
483        int thirdEnd = thirdStart + third.trim().length();
484        int thirdNextStart = mEditable.toString().indexOf(third, thirdEnd);
485        int thirdNextEnd = thirdNextStart + third.trim().length();
486        mEditable.setSpan(mMockRecips[mMockRecips.length - 4], firstStart, firstEnd, 0);
487        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], secondStart, secondEnd, 0);
488        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], thirdStart, thirdEnd, 0);
489        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdNextStart, thirdNextEnd, 0);
490
491        view.createMoreChip();
492        assertEquals(mEditable.toString(), first+second+third+third);
493        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), firstStart);
494        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), secondStart);
495        // Find the more chip.
496        ImageSpan moreChip = view.getMoreChip();
497        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
498        assertEquals(mEditable.getSpanEnd(moreChip), thirdNextEnd + 1);
499
500        view.removeMoreChip();
501        assertEquals(mEditable.toString(), first+second+third+third);
502        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), firstStart);
503        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 4]), firstEnd);
504        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), secondStart);
505        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), thirdStart);
506        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), thirdEnd);
507        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdNextStart);
508        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdNextEnd);
509        moreChip = view.getMoreChip();
510        assertEquals(mEditable.getSpanStart(moreChip), -1);
511    }
512
513    public void testRemoveChip() {
514        // Create 3 chips to start and test removing chips in various postions.
515        populateMocks(3);
516        MockRecipientEditTextView view = createViewForTesting();
517        view.setMoreItem(createTestMoreItem());
518        String first = (String) mTokenizer.terminateToken("FIRST");
519        String second = (String) mTokenizer.terminateToken("SECOND");
520        String third = (String) mTokenizer.terminateToken("THIRD");
521        mEditable = new SpannableStringBuilder();
522        mEditable.append(first + second + third);
523
524        int firstStart = mEditable.toString().indexOf(first);
525        int firstEnd = firstStart + first.length();
526        int secondStart = mEditable.toString().indexOf(second);
527        int secondEnd = secondStart + second.length();
528        int thirdStart = mEditable.toString().indexOf(third);
529        int thirdEnd = thirdStart + third.length();
530        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
531        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
532        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
533        assertEquals(mEditable.toString(), first + second + third);
534        // Test removing the middle chip.
535        view.removeChip(mMockRecips[mMockRecips.length - 2]);
536        assertEquals(mEditable.toString(), first + third);
537        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
538        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd);
539        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), -1);
540        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), -1);
541        int newThirdStart = mEditable.toString().indexOf(third);
542        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), newThirdStart);
543        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), newThirdStart
544                + third.length());
545
546        // Test removing the first chip.
547        populateMocks(3);
548        view = createViewForTesting();
549        view.setMoreItem(createTestMoreItem());
550        mEditable = new SpannableStringBuilder();
551        mEditable.append(first + second + third);
552
553        firstStart = mEditable.toString().indexOf(first);
554        firstEnd = firstStart + first.length();
555        secondStart = mEditable.toString().indexOf(second);
556        secondEnd = secondStart + second.length();
557        thirdStart = mEditable.toString().indexOf(third);
558        thirdEnd = thirdStart + third.length();
559        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
560        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
561        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
562        assertEquals(mEditable.toString(), first + second + third);
563        view.removeChip(mMockRecips[mMockRecips.length - 3]);
564        assertEquals(mEditable.toString(), second + third);
565        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), -1);
566        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), -1);
567        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), 0);
568        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), second.length());
569        newThirdStart = mEditable.toString().indexOf(third);
570        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), newThirdStart);
571        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), newThirdStart
572                + third.length());
573
574        // Test removing the last chip.
575        populateMocks(3);
576        view = createViewForTesting();
577        view.setMoreItem(createTestMoreItem());
578        mEditable = new SpannableStringBuilder();
579        mEditable.append(first + second + third);
580
581        firstStart = mEditable.toString().indexOf(first);
582        firstEnd = firstStart + first.length();
583        secondStart = mEditable.toString().indexOf(second);
584        secondEnd = secondStart + second.length();
585        thirdStart = mEditable.toString().indexOf(third);
586        thirdEnd = thirdStart + third.length();
587        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
588        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
589        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
590        assertEquals(mEditable.toString(), first + second + third);
591        view.removeChip(mMockRecips[mMockRecips.length - 1]);
592        assertEquals(mEditable.toString(), first + second);
593        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
594        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd);
595        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
596        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), secondEnd);
597        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), -1);
598        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), -1);
599    }
600
601    public void testReplaceChip() {
602        populateMocks(3);
603        MockRecipientEditTextView view = createViewForTesting();
604        view.setMoreItem(createTestMoreItem());
605        view.setChipBackground(createChipBackground());
606        view.setChipHeight(48);
607        String first = (String) mTokenizer.terminateToken("FIRST");
608        String second = (String) mTokenizer.terminateToken("SECOND");
609        String third = (String) mTokenizer.terminateToken("THIRD");
610        mEditable = new SpannableStringBuilder();
611        mEditable.append(first + second + third);
612
613        // Test replacing the first chip with a new chip.
614        int firstStart = mEditable.toString().indexOf(first);
615        int firstEnd = firstStart + first.trim().length();
616        int secondStart = mEditable.toString().indexOf(second);
617        int secondEnd = secondStart + second.trim().length();
618        int thirdStart = mEditable.toString().indexOf(third);
619        int thirdEnd = thirdStart + third.trim().length();
620        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
621        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
622        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
623        assertEquals(mEditable.toString(), first + second + third);
624        view.replaceChip(mMockRecips[mMockRecips.length - 3], RecipientEntry
625                .constructGeneratedEntry("replacement", "replacement@replacement.com", true));
626        assertEquals(mEditable.toString(), mTokenizer
627                .terminateToken("replacement <replacement@replacement.com>")
628                + second + third);
629        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), -1);
630        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), -1);
631        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), mEditable
632                .toString().indexOf(second));
633        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), mEditable
634                .toString().indexOf(second)
635                + second.trim().length());
636        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), mEditable
637                .toString().indexOf(third));
638        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), mEditable
639                .toString().indexOf(third)
640                + third.trim().length());
641        RecipientChip[] spans = mEditable.getSpans(0, mEditable.length(), RecipientChip.class);
642        assertEquals(spans.length, 3);
643        spans = mEditable
644                .getSpans(0, mEditable.toString().indexOf(second) - 1, RecipientChip.class);
645        assertEquals((String) spans[0].getDisplay(), "replacement");
646
647
648        // Test replacing the middle chip with a new chip.
649        mEditable = new SpannableStringBuilder();
650        mEditable.append(first + second + third);
651        firstStart = mEditable.toString().indexOf(first);
652        firstEnd = firstStart + first.trim().length();
653        secondStart = mEditable.toString().indexOf(second);
654        secondEnd = secondStart + second.trim().length();
655        thirdStart = mEditable.toString().indexOf(third);
656        thirdEnd = thirdStart + third.trim().length();
657        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
658        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
659        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
660        assertEquals(mEditable.toString(), first + second + third);
661        view.replaceChip(mMockRecips[mMockRecips.length - 2], RecipientEntry
662                .constructGeneratedEntry("replacement", "replacement@replacement.com", true));
663        assertEquals(mEditable.toString(), first + mTokenizer
664                .terminateToken("replacement <replacement@replacement.com>") + third);
665        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
666        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd);
667        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), -1);
668        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), -1);
669        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), mEditable
670                .toString().indexOf(third));
671        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), mEditable
672                .toString().indexOf(third)
673                + third.trim().length());
674        spans = mEditable.getSpans(0, mEditable.length(), RecipientChip.class);
675        assertEquals(spans.length, 3);
676        spans = mEditable
677                .getSpans(firstEnd, mEditable.toString().indexOf(third) - 1, RecipientChip.class);
678        assertEquals((String) spans[0].getDisplay(), "replacement");
679
680
681        // Test replacing the last chip with a new chip.
682        mEditable = new SpannableStringBuilder();
683        mEditable.append(first + second + third);
684        firstStart = mEditable.toString().indexOf(first);
685        firstEnd = firstStart + first.trim().length();
686        secondStart = mEditable.toString().indexOf(second);
687        secondEnd = secondStart + second.trim().length();
688        thirdStart = mEditable.toString().indexOf(third);
689        thirdEnd = thirdStart + third.trim().length();
690        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
691        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
692        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
693        assertEquals(mEditable.toString(), first + second + third);
694        view.replaceChip(mMockRecips[mMockRecips.length - 1], RecipientEntry
695                .constructGeneratedEntry("replacement", "replacement@replacement.com", true));
696        assertEquals(mEditable.toString(), first + second + mTokenizer
697                .terminateToken("replacement <replacement@replacement.com>"));
698        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
699        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd);
700        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
701        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), secondEnd);
702        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), -1);
703        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), -1);
704        spans = mEditable.getSpans(0, mEditable.length(), RecipientChip.class);
705        assertEquals(spans.length, 3);
706        spans = mEditable
707                .getSpans(secondEnd, mEditable.length(), RecipientChip.class);
708        assertEquals((String) spans[0].getDisplay(), "replacement");
709    }
710
711    public void testHandlePaste() {
712        // Start with an empty edit field.
713        // Add an address; the text should be left as is.
714        MockRecipientEditTextView view = createViewForTesting();
715        view.setMoreItem(createTestMoreItem());
716        view.setChipBackground(createChipBackground());
717        view.setChipHeight(48);
718        mEditable = new SpannableStringBuilder();
719        mEditable.append("user@user.com");
720        view.setSelection(mEditable.length());
721        view.handlePaste();
722        assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length, 0);
723        assertEquals(mEditable.toString(), "user@user.com");
724
725        // Test adding a single address to an empty chips field with a space at
726        // the end of it. The address should stay as text.
727        mEditable = new SpannableStringBuilder();
728        String tokenizedUser = "user@user.com" + " ";
729        mEditable.append(tokenizedUser);
730        view.setSelection(mEditable.length());
731        view.handlePaste();
732        assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length, 0);
733        assertEquals(mEditable.toString(), tokenizedUser);
734
735        // Test adding a single address to an empty chips field with a semicolon at
736        // the end of it. The address should become a chip
737        mEditable = new SpannableStringBuilder();
738        tokenizedUser = "user@user.com;";
739        mEditable.append(tokenizedUser);
740        view.setSelection(mEditable.length());
741        view.handlePaste();
742        assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length, 1);
743
744        // Test adding 2 address to an empty chips field. The second to last
745        // address should become a chip and the last address should stay as
746        // text.
747        mEditable = new SpannableStringBuilder();
748        mEditable.append("user1,user2@user.com");
749        view.setSelection(mEditable.length());
750        view.handlePaste();
751        assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length, 1);
752        assertEquals(mEditable.getSpans(0, mEditable.toString().indexOf("user2@user.com"),
753                RecipientChip.class).length, 1);
754        assertEquals(mEditable.toString(), "<user1>, user2@user.com");
755
756        // Test adding a single address to the end of existing chips. The existing
757        // chips should remain, and the last address should stay as text.
758        populateMocks(3);
759        String first = (String) mTokenizer.terminateToken("FIRST");
760        String second = (String) mTokenizer.terminateToken("SECOND");
761        String third = (String) mTokenizer.terminateToken("THIRD");
762        mEditable = new SpannableStringBuilder();
763        mEditable.append(first + second + third);
764        view.setSelection(mEditable.length());
765        int firstStart = mEditable.toString().indexOf(first);
766        int firstEnd = firstStart + first.trim().length();
767        int secondStart = mEditable.toString().indexOf(second);
768        int secondEnd = secondStart + second.trim().length();
769        int thirdStart = mEditable.toString().indexOf(third);
770        int thirdEnd = thirdStart + third.trim().length();
771        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
772        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
773        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
774
775        mEditable.append("user@user.com");
776        view.setSelection(mEditable.length());
777        view.handlePaste();
778        assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length,
779                mMockRecips.length);
780        assertEquals(mEditable.toString(), first + second + third + "user@user.com");
781
782        // Paste 2 addresses after existing chips. We expect the first address to be turned into
783        // a chip and the second to be left as text.
784        populateMocks(3);
785        mEditable = new SpannableStringBuilder();
786        mEditable.append(first + second + third);
787
788        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
789        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
790        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
791
792        mEditable.append("user1, user2@user.com");
793        view.setSelection(mEditable.length());
794        view.handlePaste();
795        assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length,
796                mMockRecips.length + 1);
797        assertEquals(mEditable.getSpans(mEditable.toString().indexOf("<user1>"), mEditable
798                .toString().indexOf("user2@user.com") - 1, RecipientChip.class).length, 1);
799        assertEquals(mEditable.getSpans(mEditable.toString().indexOf("user2@user.com"), mEditable
800                .length(), RecipientChip.class).length, 0);
801        assertEquals(mEditable.toString(), first + second + third + "<user1>, user2@user.com");
802
803        // Paste 2 addresses after existing chips. We expect the first address to be turned into
804        // a chip and the second to be left as text. This removes the space seperator char between
805        // addresses.
806        populateMocks(3);
807        mEditable = new SpannableStringBuilder();
808        mEditable.append(first + second + third);
809
810        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
811        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
812        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
813
814        mEditable.append("user1,user2@user.com");
815        view.setSelection(mEditable.length());
816        view.handlePaste();
817        assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length,
818                mMockRecips.length + 1);
819        assertEquals(mEditable.getSpans(mEditable.toString().indexOf("<user1>"), mEditable
820                .toString().indexOf("user2@user.com") - 1, RecipientChip.class).length, 1);
821        assertEquals(mEditable.getSpans(mEditable.toString().indexOf("user2@user.com"), mEditable
822                .length(), RecipientChip.class).length, 0);
823        assertEquals(mEditable.toString(), first + second + third + "<user1>, user2@user.com");
824
825        // Test a complete token pasted in at the end. It should be turned into a chip.
826        mEditable = new SpannableStringBuilder();
827        mEditable.append("user1, user2@user.com,");
828        view.setSelection(mEditable.length());
829        view.handlePaste();
830        assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length, 2);
831        assertEquals(mEditable.getSpans(mEditable.toString().indexOf("<user1>"), mEditable
832                .toString().indexOf("user2@user.com") - 1, RecipientChip.class).length, 1);
833        assertEquals(mEditable.getSpans(mEditable.toString().indexOf("user2@user.com"), mEditable
834                .length(), RecipientChip.class).length, 1);
835        assertEquals(mEditable.toString(), "<user1>, <user2@user.com>, ");
836    }
837
838    public void testGetPastTerminators() {
839        MockRecipientEditTextView view = createViewForTesting();
840        view.setMoreItem(createTestMoreItem());
841        view.setChipBackground(createChipBackground());
842        view.setChipHeight(48);
843        String test = "test";
844        mEditable = new SpannableStringBuilder();
845        mEditable.append(test);
846        assertEquals(view.movePastTerminators(mTokenizer.findTokenEnd(mEditable.toString(), 0)),
847                test.length());
848
849        test = "test,";
850        mEditable = new SpannableStringBuilder();
851        mEditable.append(test);
852        assertEquals(view.movePastTerminators(mTokenizer.findTokenEnd(mEditable.toString(), 0)),
853                test.length());
854
855        test = "test, ";
856        mEditable = new SpannableStringBuilder();
857        mEditable.append(test);
858        assertEquals(view.movePastTerminators(mTokenizer.findTokenEnd(mEditable.toString(), 0)),
859                test.length());
860
861        test = "test;";
862        mEditable = new SpannableStringBuilder();
863        mEditable.append(test);
864        assertEquals(view.movePastTerminators(mTokenizer.findTokenEnd(mEditable.toString(), 0)),
865                test.length());
866
867        test = "test; ";
868        mEditable = new SpannableStringBuilder();
869        mEditable.append(test);
870        assertEquals(view.movePastTerminators(mTokenizer.findTokenEnd(mEditable.toString(), 0)),
871                test.length());
872    }
873
874    public void testIsCompletedToken() {
875        MockRecipientEditTextView view = createViewForTesting();
876        view.setMoreItem(createTestMoreItem());
877        view.setChipBackground(createChipBackground());
878        view.setChipHeight(48);
879        assertTrue(view.isCompletedToken("test;"));
880        assertTrue(view.isCompletedToken("test,"));
881        assertFalse(view.isCompletedToken("test"));
882        assertFalse(view.isCompletedToken("test "));
883    }
884
885    public void testGetLastChip() {
886        populateMocks(3);
887        MockRecipientEditTextView view = createViewForTesting();
888        view.setMoreItem(createTestMoreItem());
889        view.setChipBackground(createChipBackground());
890        view.setChipHeight(48);
891        String first = (String) mTokenizer.terminateToken("FIRST");
892        String second = (String) mTokenizer.terminateToken("SECOND");
893        String third = (String) mTokenizer.terminateToken("THIRD");
894        mEditable = new SpannableStringBuilder();
895        mEditable.append(first + second + third);
896
897        // Test replacing the first chip with a new chip.
898        int firstStart = mEditable.toString().indexOf(first);
899        int firstEnd = firstStart + first.trim().length();
900        int secondStart = mEditable.toString().indexOf(second);
901        int secondEnd = secondStart + second.trim().length();
902        int thirdStart = mEditable.toString().indexOf(third);
903        int thirdEnd = thirdStart + third.trim().length();
904        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
905        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
906        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
907        assertEquals(view.getLastChip(), mMockRecips[mMockRecips.length - 1]);
908        mEditable.append("extra");
909        assertEquals(view.getLastChip(), mMockRecips[mMockRecips.length - 1]);
910    }
911
912    private Drawable createChipBackground() {
913        Bitmap drawable = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
914        return new BitmapDrawable(getContext().getResources(), drawable);
915    }
916
917    private TextView createTestMoreItem() {
918        TextView view = new TextView(getContext());
919        view.setText("<xliff:g id='count'>%1$s</xliff:g> more...");
920        return view;
921    }
922
923    private void populateMocks(int size) {
924        mMockEntries = new RecipientEntry[size];
925        for (int i = 0; i < size; i++) {
926            mMockEntries[i] = RecipientEntry.constructGeneratedEntry("user",
927                    "user@username.com", true);
928        }
929        mMockRecips = new RecipientChip[size];
930        for (int i = 0; i < size; i++) {
931            mMockRecips[i] = new VisibleRecipientChip(null, mMockEntries[i], i);
932        }
933    }
934}
935