ChipsTest.java revision 878b7cea14b1f8583611a7df58a4406b3eca34b6
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 MockRecipientEditTextView extends RecipientEditTextView { 45 46 public MockRecipientEditTextView(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 Editable getText() { 59 return mEditable; 60 } 61 62 @Override 63 public Editable getSpannable() { 64 return mEditable; 65 } 66 67 @Override 68 public int getLineHeight() { 69 return 48; 70 } 71 72 public Drawable getChipBackground(RecipientEntry contact) { 73 return createChipBackground(); 74 } 75 } 76 77 private MockRecipientEditTextView createViewForTesting() { 78 mEditable = new SpannableStringBuilder(); 79 MockRecipientEditTextView view = new MockRecipientEditTextView(getContext()); 80 return view; 81 } 82 83 public void testCreateDisplayText() { 84 RecipientEditTextView view = createViewForTesting(); 85 RecipientEntry entry = RecipientEntry.constructGeneratedEntry("User Name, Jr", 86 "user@username.com"); 87 String test = view.createDisplayText(entry); 88 assertEquals("Expected a properly formatted RFC email address", 89 "\"User Name, Jr\" <user@username.com>, ", test); 90 91 RecipientEntry alreadyFormatted = RecipientEntry.constructFakeEntry("user@username.com, "); 92 test = view.createDisplayText(alreadyFormatted); 93 assertEquals("Expected a properly formatted RFC email address", "<user@username.com>, ", 94 test); 95 96 RecipientEntry alreadyFormattedNoSpace = RecipientEntry 97 .constructFakeEntry("user@username.com,"); 98 test = view.createDisplayText(alreadyFormattedNoSpace); 99 assertEquals("Expected a properly formatted RFC email address", "<user@username.com>, ", 100 test); 101 102 RecipientEntry alreadyNamed = RecipientEntry.constructGeneratedEntry("User Name", 103 "\"User Name, Jr\" <user@username.com>"); 104 test = view.createDisplayText(alreadyNamed); 105 assertEquals( 106 "Expected address that used the name not the excess address name", 107 "User Name <user@username.com>, ", test); 108 } 109 110 public void testSanitizeBetween() { 111 // First, add 2 chips and then make sure we remove 112 // the extra content between them correctly. 113 populateMocks(2); 114 MockRecipientEditTextView view = createViewForTesting(); 115 String first = (String) mTokenizer.terminateToken("FIRST"); 116 String second = (String) mTokenizer.terminateToken("SECOND"); 117 String extra = "EXTRA"; 118 mEditable = new SpannableStringBuilder(); 119 mEditable.append(first + extra + second); 120 int firstStart = mEditable.toString().indexOf(first); 121 int firstEnd = firstStart + first.length(); 122 int secondStart = mEditable.toString().indexOf(second); 123 int secondEnd = secondStart + second.length(); 124 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], firstStart, firstEnd, 0); 125 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], secondStart, secondEnd, 0); 126 view.sanitizeBetween(); 127 String editableString = mEditable.toString(); 128 assertEquals(editableString.indexOf(extra), -1); 129 assertEquals(editableString.indexOf(first), firstStart); 130 assertEquals(editableString.indexOf(second), secondStart - extra.length()); 131 assertEquals(editableString, (first + second)); 132 133 // Add 1 chip and make sure that we remove the extra stuff before it correctly. 134 mEditable = new SpannableStringBuilder(); 135 populateMocks(1); 136 mEditable.append(extra); 137 mEditable.append(first); 138 firstStart = mEditable.toString().indexOf(first); 139 firstEnd = firstStart + first.length(); 140 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], firstStart, firstEnd, 0); 141 view.sanitizeBetween(); 142 assertEquals(mEditable.toString(), first); 143 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), firstStart 144 - extra.length()); 145 } 146 147 public void testMoreChip() { 148 // Add 3 chips: this is the trigger point at which the more chip will be created. 149 // Test that adding the chips and then creating and removing the more chip, as if 150 // the user were focusing/ removing focus from the chips field. 151 populateMocks(3); 152 MockRecipientEditTextView view = createViewForTesting(); 153 view.setMoreItem(createTestMoreItem()); 154 String first = (String) mTokenizer.terminateToken("FIRST"); 155 String second = (String) mTokenizer.terminateToken("SECOND"); 156 String third = (String) mTokenizer.terminateToken("THIRD"); 157 mEditable = new SpannableStringBuilder(); 158 mEditable.append(first+second+third); 159 160 int firstStart = mEditable.toString().indexOf(first); 161 int firstEnd = firstStart + first.length(); 162 int secondStart = mEditable.toString().indexOf(second); 163 int secondEnd = secondStart + second.length(); 164 int thirdStart = mEditable.toString().indexOf(third); 165 int thirdEnd = thirdStart + third.length(); 166 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); 167 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); 168 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); 169 170 view.createMoreChip(); 171 assertEquals(mEditable.toString(), first+second+third); 172 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); 173 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); 174 // Find the more chip. 175 ImageSpan moreChip = view.getMoreChip(); 176 assertEquals(mEditable.getSpanStart(moreChip), thirdStart); 177 assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd); 178 179 view.removeMoreChip(); 180 assertEquals(mEditable.toString(), first+second+third); 181 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); 182 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); 183 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); 184 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart); 185 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd); 186 moreChip = view.getMoreChip(); 187 assertEquals(mEditable.getSpanStart(moreChip), -1); 188 189 // Rinse and repeat, just in case! 190 view.createMoreChip(); 191 assertEquals(mEditable.toString(), first+second+third); 192 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); 193 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); 194 // Find the more chip. 195 moreChip = view.getMoreChip(); 196 assertEquals(mEditable.getSpanStart(moreChip), thirdStart); 197 assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd); 198 199 view.removeMoreChip(); 200 assertEquals(mEditable.toString(), first+second+third); 201 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); 202 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); 203 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); 204 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart); 205 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd); 206 moreChip = view.getMoreChip(); 207 assertEquals(mEditable.getSpanStart(moreChip), -1); 208 } 209 210 public void testMoreChipLotsOfUsers() { 211 // Test adding and removing the more chip in the case where we have a lot of users. 212 populateMocks(10); 213 MockRecipientEditTextView view = createViewForTesting(); 214 view.setMoreItem(createTestMoreItem()); 215 String first = (String) mTokenizer.terminateToken("FIRST"); 216 String second = (String) mTokenizer.terminateToken("SECOND"); 217 String third = (String) mTokenizer.terminateToken("THIRD"); 218 String fourth = (String) mTokenizer.terminateToken("FOURTH"); 219 String fifth = (String) mTokenizer.terminateToken("FIFTH"); 220 String sixth = (String) mTokenizer.terminateToken("SIXTH"); 221 String seventh = (String) mTokenizer.terminateToken("SEVENTH"); 222 String eigth = (String) mTokenizer.terminateToken("EIGHTH"); 223 String ninth = (String) mTokenizer.terminateToken("NINTH"); 224 String tenth = (String) mTokenizer.terminateToken("TENTH"); 225 mEditable = new SpannableStringBuilder(); 226 mEditable.append(first+second+third+fourth+fifth+sixth+seventh+eigth+ninth+tenth); 227 228 int firstStart = mEditable.toString().indexOf(first); 229 int firstEnd = firstStart + first.length(); 230 int secondStart = mEditable.toString().indexOf(second); 231 int secondEnd = secondStart + second.length(); 232 int thirdStart = mEditable.toString().indexOf(third); 233 int thirdEnd = thirdStart + third.length(); 234 int fourthStart = mEditable.toString().indexOf(fourth); 235 int fourthEnd = fourthStart + fourth.length(); 236 int fifthStart = mEditable.toString().indexOf(fifth); 237 int fifthEnd = fifthStart + fifth.length(); 238 int sixthStart = mEditable.toString().indexOf(sixth); 239 int sixthEnd = sixthStart + sixth.length(); 240 int seventhStart = mEditable.toString().indexOf(seventh); 241 int seventhEnd = seventhStart + seventh.length(); 242 int eighthStart = mEditable.toString().indexOf(eigth); 243 int eighthEnd = eighthStart + eigth.length(); 244 int ninthStart = mEditable.toString().indexOf(ninth); 245 int ninthEnd = ninthStart + ninth.length(); 246 int tenthStart = mEditable.toString().indexOf(tenth); 247 int tenthEnd = tenthStart + tenth.length(); 248 mEditable.setSpan(mMockRecips[mMockRecips.length - 10], firstStart, firstEnd, 0); 249 mEditable.setSpan(mMockRecips[mMockRecips.length - 9], secondStart, secondEnd, 0); 250 mEditable.setSpan(mMockRecips[mMockRecips.length - 8], thirdStart, thirdEnd, 0); 251 mEditable.setSpan(mMockRecips[mMockRecips.length - 7], fourthStart, fourthEnd, 0); 252 mEditable.setSpan(mMockRecips[mMockRecips.length - 6], fifthStart, fifthEnd, 0); 253 mEditable.setSpan(mMockRecips[mMockRecips.length - 5], sixthStart, sixthEnd, 0); 254 mEditable.setSpan(mMockRecips[mMockRecips.length - 4], seventhStart, seventhEnd, 0); 255 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], eighthStart, eighthEnd, 0); 256 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], ninthStart, ninthEnd, 0); 257 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], tenthStart, tenthEnd, 0); 258 259 view.createMoreChip(); 260 assertEquals(mEditable.toString(), first + second + third + fourth + fifth + sixth 261 + seventh + eigth + ninth + tenth); 262 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 10]), firstStart); 263 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 9]), secondStart); 264 // Find the more chip. 265 ImageSpan moreChip = view.getMoreChip(); 266 assertEquals(mEditable.getSpanStart(moreChip), thirdStart); 267 assertEquals(mEditable.getSpanEnd(moreChip), tenthEnd); 268 269 view.removeMoreChip(); 270 assertEquals(mEditable.toString(), first + second + third + fourth + fifth + sixth 271 + seventh + eigth + ninth + tenth); 272 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 10]), firstStart); 273 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 9]), secondStart); 274 275 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 8]), thirdStart); 276 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 7]), fourthStart); 277 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 6]), fifthStart); 278 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 5]), sixthStart); 279 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), seventhStart); 280 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), eighthStart); 281 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), ninthStart); 282 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), tenthStart); 283 moreChip = view.getMoreChip(); 284 assertEquals(mEditable.getSpanStart(moreChip), -1); 285 286 } 287 288 public void testMoreChipSpecialChars() { 289 // Make sure the more chip correctly handles extra tokenizer characters in the middle 290 // of chip text. 291 populateMocks(3); 292 MockRecipientEditTextView view = createViewForTesting(); 293 view.setMoreItem(createTestMoreItem()); 294 String first = (String) mTokenizer.terminateToken("FI,RST"); 295 String second = (String) mTokenizer.terminateToken("SE,COND"); 296 String third = (String) mTokenizer.terminateToken("THI,RD"); 297 mEditable = new SpannableStringBuilder(); 298 mEditable.append(first+second+third); 299 300 int firstStart = mEditable.toString().indexOf(first); 301 int firstEnd = firstStart + first.length(); 302 int secondStart = mEditable.toString().indexOf(second); 303 int secondEnd = secondStart + second.length(); 304 int thirdStart = mEditable.toString().indexOf(third); 305 int thirdEnd = thirdStart + third.length(); 306 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); 307 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); 308 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); 309 310 view.createMoreChip(); 311 assertEquals(mEditable.toString(), first+second+third); 312 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); 313 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); 314 // Find the more chip. 315 ImageSpan moreChip = view.getMoreChip(); 316 assertEquals(mEditable.getSpanStart(moreChip), thirdStart); 317 assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd); 318 319 view.removeMoreChip(); 320 assertEquals(mEditable.toString(), first+second+third); 321 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); 322 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); 323 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); 324 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart); 325 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd); 326 moreChip = view.getMoreChip(); 327 assertEquals(mEditable.getSpanStart(moreChip), -1); 328 } 329 330 public void testMoreChipDupes() { 331 // Make sure the more chip is correctly added and removed when we have duplicate chips. 332 populateMocks(4); 333 MockRecipientEditTextView view = createViewForTesting(); 334 view.setMoreItem(createTestMoreItem()); 335 String first = (String) mTokenizer.terminateToken("FIRST"); 336 String second = (String) mTokenizer.terminateToken("SECOND"); 337 String third = (String) mTokenizer.terminateToken("THIRD"); 338 mEditable = new SpannableStringBuilder(); 339 mEditable.append(first+second+third+third); 340 341 int firstStart = mEditable.toString().indexOf(first); 342 int firstEnd = firstStart + first.length(); 343 int secondStart = mEditable.toString().indexOf(second); 344 int secondEnd = secondStart + second.length(); 345 int thirdStart = mEditable.toString().indexOf(third); 346 int thirdEnd = thirdStart + third.length(); 347 int thirdNextStart = mEditable.toString().indexOf(third, thirdEnd); 348 int thirdNextEnd = thirdNextStart + third.length(); 349 mEditable.setSpan(mMockRecips[mMockRecips.length - 4], firstStart, firstEnd, 0); 350 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], secondStart, secondEnd, 0); 351 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], thirdStart, thirdEnd, 0); 352 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdNextStart, thirdNextEnd, 0); 353 354 view.createMoreChip(); 355 assertEquals(mEditable.toString(), first+second+third+third); 356 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), firstStart); 357 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), secondStart); 358 // Find the more chip. 359 ImageSpan moreChip = view.getMoreChip(); 360 assertEquals(mEditable.getSpanStart(moreChip), thirdStart); 361 assertEquals(mEditable.getSpanEnd(moreChip), thirdNextEnd); 362 363 view.removeMoreChip(); 364 assertEquals(mEditable.toString(), first+second+third+third); 365 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), firstStart); 366 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 4]), firstEnd); 367 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), secondStart); 368 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), thirdStart); 369 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), thirdEnd); 370 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdNextStart); 371 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdNextEnd); 372 moreChip = view.getMoreChip(); 373 assertEquals(mEditable.getSpanStart(moreChip), -1); 374 } 375 376 public void testMatchesChip() { 377 // Test the logic for checking if we have found the chip 378 // that matches a particular offset in chips field. 379 populateMocks(3); 380 MockRecipientEditTextView view = createViewForTesting(); 381 view.setMoreItem(createTestMoreItem()); 382 String first = (String) mTokenizer.terminateToken("FIRST"); 383 String second = (String) mTokenizer.terminateToken("SECOND"); 384 String third = (String) mTokenizer.terminateToken("THIRD"); 385 mEditable = new SpannableStringBuilder(); 386 mEditable.append(first+second+third); 387 388 int firstStart = mEditable.toString().indexOf(first); 389 int firstEnd = firstStart + first.length(); 390 int secondStart = mEditable.toString().indexOf(second); 391 int secondEnd = secondStart + second.length(); 392 int thirdStart = mEditable.toString().indexOf(third); 393 int thirdEnd = thirdStart + third.length(); 394 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); 395 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); 396 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); 397 assertFalse(view.matchesChip(mMockRecips[mMockRecips.length - 3], -1)); 398 assertFalse(view.matchesChip(mMockRecips[mMockRecips.length - 1], mEditable.length() + 1)); 399 assertTrue(view.matchesChip(mMockRecips[mMockRecips.length - 3], firstStart)); 400 assertTrue(view.matchesChip(mMockRecips[mMockRecips.length - 3], firstEnd)); 401 assertTrue(view.matchesChip(mMockRecips[mMockRecips.length - 3], firstEnd - 1)); 402 } 403 404 public void testRemoveChip() { 405 // Create 3 chips to start and test removing chips in various postions. 406 populateMocks(3); 407 MockRecipientEditTextView view = createViewForTesting(); 408 view.setMoreItem(createTestMoreItem()); 409 String first = (String) mTokenizer.terminateToken("FIRST"); 410 String second = (String) mTokenizer.terminateToken("SECOND"); 411 String third = (String) mTokenizer.terminateToken("THIRD"); 412 mEditable = new SpannableStringBuilder(); 413 mEditable.append(first + second + third); 414 415 int firstStart = mEditable.toString().indexOf(first); 416 int firstEnd = firstStart + first.length(); 417 int secondStart = mEditable.toString().indexOf(second); 418 int secondEnd = secondStart + second.length(); 419 int thirdStart = mEditable.toString().indexOf(third); 420 int thirdEnd = thirdStart + third.length(); 421 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); 422 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); 423 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); 424 assertEquals(mEditable.toString(), first + second + third); 425 // Test removing the middle chip. 426 view.removeChip(mMockRecips[mMockRecips.length - 2]); 427 assertEquals(mEditable.toString(), first + third); 428 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); 429 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); 430 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), -1); 431 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), -1); 432 int newThirdStart = mEditable.toString().indexOf(third); 433 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), newThirdStart); 434 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), newThirdStart 435 + third.length()); 436 437 // Test removing the first chip. 438 populateMocks(3); 439 view = createViewForTesting(); 440 view.setMoreItem(createTestMoreItem()); 441 mEditable = new SpannableStringBuilder(); 442 mEditable.append(first + second + third); 443 444 firstStart = mEditable.toString().indexOf(first); 445 firstEnd = firstStart + first.length(); 446 secondStart = mEditable.toString().indexOf(second); 447 secondEnd = secondStart + second.length(); 448 thirdStart = mEditable.toString().indexOf(third); 449 thirdEnd = thirdStart + third.length(); 450 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); 451 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); 452 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); 453 assertEquals(mEditable.toString(), first + second + third); 454 view.removeChip(mMockRecips[mMockRecips.length - 3]); 455 assertEquals(mEditable.toString(), second + third); 456 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), -1); 457 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), -1); 458 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), 0); 459 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), second.length()); 460 newThirdStart = mEditable.toString().indexOf(third); 461 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), newThirdStart); 462 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), newThirdStart 463 + third.length()); 464 465 // Test removing the last chip. 466 populateMocks(3); 467 view = createViewForTesting(); 468 view.setMoreItem(createTestMoreItem()); 469 mEditable = new SpannableStringBuilder(); 470 mEditable.append(first + second + third); 471 472 firstStart = mEditable.toString().indexOf(first); 473 firstEnd = firstStart + first.length(); 474 secondStart = mEditable.toString().indexOf(second); 475 secondEnd = secondStart + second.length(); 476 thirdStart = mEditable.toString().indexOf(third); 477 thirdEnd = thirdStart + third.length(); 478 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); 479 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); 480 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); 481 assertEquals(mEditable.toString(), first + second + third); 482 view.removeChip(mMockRecips[mMockRecips.length - 1]); 483 assertEquals(mEditable.toString(), first + second); 484 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); 485 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); 486 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); 487 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), secondEnd); 488 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), -1); 489 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), -1); 490 } 491 492 public void testReplaceChip() { 493 populateMocks(3); 494 MockRecipientEditTextView view = createViewForTesting(); 495 view.setMoreItem(createTestMoreItem()); 496 view.setChipBackground(createChipBackground()); 497 view.setChipHeight(48); 498 String first = (String) mTokenizer.terminateToken("FIRST"); 499 String second = (String) mTokenizer.terminateToken("SECOND"); 500 String third = (String) mTokenizer.terminateToken("THIRD"); 501 mEditable = new SpannableStringBuilder(); 502 mEditable.append(first + second + third); 503 504 // Test replacing the first chip with a new chip. 505 int firstStart = mEditable.toString().indexOf(first); 506 int firstEnd = firstStart + first.length(); 507 int secondStart = mEditable.toString().indexOf(second); 508 int secondEnd = secondStart + second.length(); 509 int thirdStart = mEditable.toString().indexOf(third); 510 int thirdEnd = thirdStart + third.length(); 511 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); 512 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); 513 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); 514 assertEquals(mEditable.toString(), first + second + third); 515 view.replaceChip(mMockRecips[mMockRecips.length - 3], RecipientEntry 516 .constructGeneratedEntry("replacement", "replacement@replacement.com")); 517 assertEquals(mEditable.toString(), mTokenizer 518 .terminateToken("replacement <replacement@replacement.com>") 519 + second + third); 520 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), -1); 521 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), -1); 522 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), mEditable 523 .toString().indexOf(second)); 524 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), mEditable 525 .toString().indexOf(second) 526 + second.length()); 527 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), mEditable 528 .toString().indexOf(third)); 529 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), mEditable 530 .toString().indexOf(third) 531 + third.length()); 532 RecipientChip[] spans = mEditable.getSpans(0, mEditable.length(), RecipientChip.class); 533 assertEquals(spans.length, 3); 534 spans = mEditable 535 .getSpans(0, mEditable.toString().indexOf(second) - 1, RecipientChip.class); 536 assertEquals((String) spans[0].getDisplay(), "replacement"); 537 538 539 // Test replacing the middle chip with a new chip. 540 mEditable = new SpannableStringBuilder(); 541 mEditable.append(first + second + third); 542 firstStart = mEditable.toString().indexOf(first); 543 firstEnd = firstStart + first.length(); 544 secondStart = mEditable.toString().indexOf(second); 545 secondEnd = secondStart + second.length(); 546 thirdStart = mEditable.toString().indexOf(third); 547 thirdEnd = thirdStart + third.length(); 548 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); 549 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); 550 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); 551 assertEquals(mEditable.toString(), first + second + third); 552 view.replaceChip(mMockRecips[mMockRecips.length - 2], RecipientEntry 553 .constructGeneratedEntry("replacement", "replacement@replacement.com")); 554 assertEquals(mEditable.toString(), mTokenizer 555 .terminateToken("replacement <replacement@replacement.com>") 556 + second + third); 557 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); 558 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); 559 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), -1); 560 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), -1); 561 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), mEditable 562 .toString().indexOf(third)); 563 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), mEditable 564 .toString().indexOf(third) 565 + third.length()); 566 spans = mEditable.getSpans(0, mEditable.length(), RecipientChip.class); 567 assertEquals(spans.length, 3); 568 spans = mEditable 569 .getSpans(firstEnd, mEditable.toString().indexOf(third) - 1, RecipientChip.class); 570 assertEquals((String) spans[0].getDisplay(), "replacement"); 571 572 573 // Test replacing the last chip with a new chip. 574 mEditable = new SpannableStringBuilder(); 575 mEditable.append(first + second + third); 576 firstStart = mEditable.toString().indexOf(first); 577 firstEnd = firstStart + first.length(); 578 secondStart = mEditable.toString().indexOf(second); 579 secondEnd = secondStart + second.length(); 580 thirdStart = mEditable.toString().indexOf(third); 581 thirdEnd = thirdStart + third.length(); 582 mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); 583 mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); 584 mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); 585 assertEquals(mEditable.toString(), first + second + third); 586 view.replaceChip(mMockRecips[mMockRecips.length - 1], RecipientEntry 587 .constructGeneratedEntry("replacement", "replacement@replacement.com")); 588 assertEquals(mEditable.toString(), mTokenizer 589 .terminateToken("replacement <replacement@replacement.com>") 590 + second + third); 591 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); 592 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); 593 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); 594 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), secondEnd); 595 assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), -1); 596 assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), -1); 597 spans = mEditable.getSpans(0, mEditable.length(), RecipientChip.class); 598 assertEquals(spans.length, 3); 599 spans = mEditable 600 .getSpans(secondEnd, mEditable.length(), RecipientChip.class); 601 assertEquals((String) spans[0].getDisplay(), "replacement"); 602 } 603 604 private Drawable createChipBackground() { 605 Bitmap drawable = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); 606 return new BitmapDrawable(getContext().getResources(), drawable); 607 } 608 609 private TextView createTestMoreItem() { 610 TextView view = new TextView(getContext()); 611 view.setText("<xliff:g id='count'>%1$s</xliff:g> more..."); 612 return view; 613 } 614 615 private void populateMocks(int size) { 616 mMockEntries = new RecipientEntry[size]; 617 for (int i = 0; i < size; i++) { 618 mMockEntries[i] = RecipientEntry.constructGeneratedEntry("user", 619 "user@username.com"); 620 } 621 mMockRecips = new RecipientChip[size]; 622 for (int i = 0; i < size; i++) { 623 mMockRecips[i] = new RecipientChip(null, mMockEntries[i], i); 624 } 625 } 626} 627