ChipsTest.java revision d71925073f008dccd8c4b65d5d66534e6451e64d
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.test.AndroidTestCase;
21import android.text.Editable;
22import android.text.SpannableStringBuilder;
23import android.text.style.ImageSpan;
24import android.text.util.Rfc822Tokenizer;
25import android.widget.TextView;
26
27import com.android.ex.chips.RecipientEditTextView;
28import com.android.ex.chips.RecipientEntry;
29
30
31public class ChipsTest extends AndroidTestCase {
32    private RecipientChip[] mMockRecips;
33
34    private RecipientEntry[] mMockEntries;
35
36    private Rfc822Tokenizer mTokenizer;
37
38    private Editable mEditable;
39
40    class MockRecipientEditTextView extends RecipientEditTextView {
41
42        public MockRecipientEditTextView(Context context) {
43            super(context, null);
44            mTokenizer = new Rfc822Tokenizer();
45            setTokenizer(mTokenizer);
46        }
47
48        @Override
49        public RecipientChip[] getSortedRecipients() {
50            return mMockRecips;
51        }
52
53        @Override
54        public Editable getText() {
55            return mEditable;
56        }
57
58        @Override
59        public Editable getSpannable() {
60            return mEditable;
61        }
62
63        @Override
64        public int getLineHeight() {
65            return 48;
66        }
67    }
68
69    private MockRecipientEditTextView createViewForTesting() {
70        mEditable = new SpannableStringBuilder();
71        MockRecipientEditTextView view = new MockRecipientEditTextView(getContext());
72        return view;
73    }
74
75    public void testCreateDisplayText() {
76        RecipientEditTextView view = createViewForTesting();
77        RecipientEntry entry = RecipientEntry.constructGeneratedEntry("User Name, Jr",
78                "user@username.com");
79        String test = view.createDisplayText(entry);
80        assertEquals("Expected a properly formatted RFC email address",
81                "\"User Name, Jr\" <user@username.com>, ", test);
82
83        RecipientEntry alreadyFormatted = RecipientEntry.constructFakeEntry("user@username.com, ");
84        test = view.createDisplayText(alreadyFormatted);
85        assertEquals("Expected a properly formatted RFC email address", "<user@username.com>, ",
86                test);
87
88        RecipientEntry alreadyFormattedNoSpace = RecipientEntry
89                .constructFakeEntry("user@username.com,");
90        test = view.createDisplayText(alreadyFormattedNoSpace);
91        assertEquals("Expected a properly formatted RFC email address", "<user@username.com>, ",
92                test);
93
94        RecipientEntry alreadyNamed = RecipientEntry.constructGeneratedEntry("User Name",
95                "\"User Name, Jr\" <user@username.com>");
96        test = view.createDisplayText(alreadyNamed);
97        assertEquals(
98                "Expected address that used the name not the excess address name",
99                "User Name <user@username.com>, ", test);
100    }
101
102    public void testSanitizeBetween() {
103        populateMocks(2);
104        MockRecipientEditTextView view = createViewForTesting();
105        String first = (String) mTokenizer.terminateToken("FIRST");
106        String second = (String) mTokenizer.terminateToken("SECOND");
107        String extra = "EXTRA";
108        mEditable = new SpannableStringBuilder();
109        mEditable.append(first + extra + second);
110        int firstStart = mEditable.toString().indexOf(first);
111        int firstEnd = firstStart + first.trim().length();
112        int secondStart = mEditable.toString().indexOf(second);
113        int secondEnd = secondStart + second.trim().length();
114        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], firstStart, firstEnd, 0);
115        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], secondStart, secondEnd, 0);
116        view.sanitizeBetween();
117        String editableString = mEditable.toString();
118        assertEquals(editableString.indexOf(extra), -1);
119        assertEquals(editableString.indexOf(first), firstStart);
120        assertEquals(editableString.indexOf(second), secondStart - extra.length());
121        assertEquals(editableString, (first + second));
122
123        mEditable = new SpannableStringBuilder();
124        populateMocks(1);
125        mEditable.append(extra);
126        mEditable.append(first);
127        firstStart = mEditable.toString().indexOf(first);
128        firstEnd = firstStart + first.length();
129        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], firstStart, firstEnd, 0);
130        view.sanitizeBetween();
131        assertEquals(mEditable.toString(), first);
132        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), firstStart
133                - extra.length());
134    }
135
136    public void testMoreChip() {
137        populateMocks(3);
138        MockRecipientEditTextView view = createViewForTesting();
139        view.setMoreItem(createTestMoreItem());
140        String first = (String) mTokenizer.terminateToken("FIRST");
141        String second = (String) mTokenizer.terminateToken("SECOND");
142        String third = (String) mTokenizer.terminateToken("THIRD");
143        mEditable = new SpannableStringBuilder();
144        mEditable.append(first+second+third);
145
146        int firstStart = mEditable.toString().indexOf(first);
147        int firstEnd = firstStart + first.trim().length();
148        int secondStart = mEditable.toString().indexOf(second);
149        int secondEnd = secondStart + second.trim().length();
150        int thirdStart = mEditable.toString().indexOf(third);
151        int thirdEnd = thirdStart + third.trim().length();
152        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
153        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
154        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
155
156        view.createMoreChip();
157        assertEquals(mEditable.toString(), first+second+third);
158        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
159        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
160        // Find the more chip.
161        ImageSpan moreChip = view.getMoreChip();
162        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
163        assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd);
164
165        view.removeMoreChip();
166        assertEquals(mEditable.toString(), first+second+third);
167        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
168        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd);
169        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
170        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart);
171        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd);
172        moreChip = view.getMoreChip();
173        assertEquals(mEditable.getSpanStart(moreChip), -1);
174
175        // Rinse and repeat, just in case!
176        view.createMoreChip();
177        assertEquals(mEditable.toString(), first+second+third);
178        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
179        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
180        // Find the more chip.
181        moreChip = view.getMoreChip();
182        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
183        assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd);
184
185        view.removeMoreChip();
186        assertEquals(mEditable.toString(), first+second+third);
187        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
188        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd);
189        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
190        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart);
191        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd);
192        moreChip = view.getMoreChip();
193        assertEquals(mEditable.getSpanStart(moreChip), -1);
194    }
195
196    public void testMoreChipLotsOfUsers() {
197        populateMocks(10);
198        MockRecipientEditTextView view = createViewForTesting();
199        view.setMoreItem(createTestMoreItem());
200        String first = (String) mTokenizer.terminateToken("FIRST");
201        String second = (String) mTokenizer.terminateToken("SECOND");
202        String third = (String) mTokenizer.terminateToken("THIRD");
203        String fourth = (String) mTokenizer.terminateToken("FOURTH");
204        String fifth = (String) mTokenizer.terminateToken("FIFTH");
205        String sixth = (String) mTokenizer.terminateToken("SIXTH");
206        String seventh = (String) mTokenizer.terminateToken("SEVENTH");
207        String eigth = (String) mTokenizer.terminateToken("EIGHTH");
208        String ninth = (String) mTokenizer.terminateToken("NINTH");
209        String tenth = (String) mTokenizer.terminateToken("TENTH");
210        mEditable = new SpannableStringBuilder();
211        mEditable.append(first+second+third+fourth+fifth+sixth+seventh+eigth+ninth+tenth);
212
213        int firstStart = mEditable.toString().indexOf(first);
214        int firstEnd = firstStart + first.trim().length();
215        int secondStart = mEditable.toString().indexOf(second);
216        int secondEnd = secondStart + second.trim().length();
217        int thirdStart = mEditable.toString().indexOf(third);
218        int thirdEnd = thirdStart + third.trim().length();
219        int fourthStart = mEditable.toString().indexOf(fourth);
220        int fourthEnd = fourthStart + fourth.trim().length();
221        int fifthStart = mEditable.toString().indexOf(fifth);
222        int fifthEnd = fifthStart + fifth.trim().length();
223        int sixthStart = mEditable.toString().indexOf(sixth);
224        int sixthEnd = sixthStart + sixth.trim().length();
225        int seventhStart = mEditable.toString().indexOf(seventh);
226        int seventhEnd = seventhStart + seventh.trim().length();
227        int eighthStart = mEditable.toString().indexOf(eigth);
228        int eighthEnd = eighthStart + eigth.trim().length();
229        int ninthStart = mEditable.toString().indexOf(ninth);
230        int ninthEnd = ninthStart + ninth.trim().length();
231        int tenthStart = mEditable.toString().indexOf(tenth);
232        int tenthEnd = tenthStart + tenth.trim().length();
233        mEditable.setSpan(mMockRecips[mMockRecips.length - 10], firstStart, firstEnd, 0);
234        mEditable.setSpan(mMockRecips[mMockRecips.length - 9], secondStart, secondEnd, 0);
235        mEditable.setSpan(mMockRecips[mMockRecips.length - 8], thirdStart, thirdEnd, 0);
236        mEditable.setSpan(mMockRecips[mMockRecips.length - 7], fourthStart, fourthEnd, 0);
237        mEditable.setSpan(mMockRecips[mMockRecips.length - 6], fifthStart, fifthEnd, 0);
238        mEditable.setSpan(mMockRecips[mMockRecips.length - 5], sixthStart, sixthEnd, 0);
239        mEditable.setSpan(mMockRecips[mMockRecips.length - 4], seventhStart, seventhEnd, 0);
240        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], eighthStart, eighthEnd, 0);
241        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], ninthStart, ninthEnd, 0);
242        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], tenthStart, tenthEnd, 0);
243
244        view.createMoreChip();
245        assertEquals(mEditable.toString(), first + second + third + fourth + fifth + sixth
246                + seventh + eigth + ninth + tenth);
247        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 10]), firstStart);
248        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 9]), secondStart);
249        // Find the more chip.
250        ImageSpan moreChip = view.getMoreChip();
251        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
252        assertEquals(mEditable.getSpanEnd(moreChip), tenthEnd);
253
254        view.removeMoreChip();
255        assertEquals(mEditable.toString(), first + second + third + fourth + fifth + sixth
256                + seventh + eigth + ninth + tenth);
257        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 10]), firstStart);
258        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 9]), secondStart);
259
260        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 8]), thirdStart);
261        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 7]), fourthStart);
262        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 6]), fifthStart);
263        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 5]), sixthStart);
264        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), seventhStart);
265        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), eighthStart);
266        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), ninthStart);
267        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), tenthStart);
268        moreChip = view.getMoreChip();
269        assertEquals(mEditable.getSpanStart(moreChip), -1);
270
271    }
272
273    public void testMoreChipSpecialChars() {
274        populateMocks(3);
275        MockRecipientEditTextView view = createViewForTesting();
276        view.setMoreItem(createTestMoreItem());
277        String first = (String) mTokenizer.terminateToken("FI,RST");
278        String second = (String) mTokenizer.terminateToken("SE,COND");
279        String third = (String) mTokenizer.terminateToken("THI,RD");
280        mEditable = new SpannableStringBuilder();
281        mEditable.append(first+second+third);
282
283        int firstStart = mEditable.toString().indexOf(first);
284        int firstEnd = firstStart + first.trim().length();
285        int secondStart = mEditable.toString().indexOf(second);
286        int secondEnd = secondStart + second.trim().length();
287        int thirdStart = mEditable.toString().indexOf(third);
288        int thirdEnd = thirdStart + third.trim().length();
289        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
290        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
291        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
292
293        view.createMoreChip();
294        assertEquals(mEditable.toString(), first+second+third);
295        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
296        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
297        // Find the more chip.
298        ImageSpan moreChip = view.getMoreChip();
299        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
300        assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd);
301
302        view.removeMoreChip();
303        assertEquals(mEditable.toString(), first+second+third);
304        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
305        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd);
306        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart);
307        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart);
308        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd);
309        moreChip = view.getMoreChip();
310        assertEquals(mEditable.getSpanStart(moreChip), -1);
311    }
312
313    private TextView createTestMoreItem() {
314        TextView view = new TextView(getContext());
315        view.setText("<xliff:g id='count'>%1$s</xliff:g> more...");
316        return view;
317    }
318
319    private void populateMocks(int size) {
320        mMockEntries = new RecipientEntry[size];
321        for (int i = 0; i < size; i++) {
322            mMockEntries[i] = RecipientEntry.constructGeneratedEntry("user",
323                    "user@username.com");
324        }
325        mMockRecips = new RecipientChip[size];
326        for (int i = 0; i < size; i++) {
327            mMockRecips[i] = new RecipientChip(null, mMockEntries[i], i);
328        }
329    }
330}
331