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