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