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