Mindy Pereira | 7cb970b | 2011-09-19 13:33:10 -0700 | [diff] [blame] | 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 | |
| 17 | package com.android.ex.chips; |
| 18 | |
Régis Décamps | 219cbfb | 2014-06-04 14:29:54 +0200 | [diff] [blame] | 19 | import android.annotation.TargetApi; |
| 20 | import android.content.ClipData; |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 21 | import android.content.Context; |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 22 | import android.graphics.Bitmap; |
| 23 | import android.graphics.drawable.BitmapDrawable; |
| 24 | import android.graphics.drawable.Drawable; |
Régis Décamps | 219cbfb | 2014-06-04 14:29:54 +0200 | [diff] [blame] | 25 | import android.net.Uri; |
Mindy Pereira | 7cb970b | 2011-09-19 13:33:10 -0700 | [diff] [blame] | 26 | import android.test.AndroidTestCase; |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 27 | import android.test.suitebuilder.annotation.SmallTest; |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 28 | import android.text.Editable; |
| 29 | import android.text.SpannableStringBuilder; |
| 30 | import android.text.util.Rfc822Tokenizer; |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 31 | import android.widget.TextView; |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 32 | |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 33 | import com.android.ex.chips.recipientchip.DrawableRecipientChip; |
Jin Cao | 6c2a016 | 2014-08-17 15:00:50 -0700 | [diff] [blame] | 34 | import com.android.ex.chips.recipientchip.ReplacementDrawableSpan; |
Scott Kennedy | 858e094 | 2013-10-10 11:50:01 -0700 | [diff] [blame] | 35 | import com.android.ex.chips.recipientchip.VisibleRecipientChip; |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 36 | |
Scott Kennedy | 983c99b | 2013-03-22 09:42:03 -0700 | [diff] [blame] | 37 | import java.util.regex.Pattern; |
| 38 | |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 39 | @SmallTest |
Mindy Pereira | 7cb970b | 2011-09-19 13:33:10 -0700 | [diff] [blame] | 40 | public class ChipsTest extends AndroidTestCase { |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 41 | private DrawableRecipientChip[] mMockRecips; |
Mindy Pereira | 7cb970b | 2011-09-19 13:33:10 -0700 | [diff] [blame] | 42 | |
Mindy Pereira | 8eb031e | 2011-09-20 15:42:32 -0700 | [diff] [blame] | 43 | private RecipientEntry[] mMockEntries; |
Mindy Pereira | 399bda8 | 2011-09-20 11:18:26 -0700 | [diff] [blame] | 44 | |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 45 | private Rfc822Tokenizer mTokenizer; |
| 46 | |
| 47 | private Editable mEditable; |
| 48 | |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 49 | class BaseMockRecipientEditTextView extends RecipientEditTextView { |
| 50 | |
| 51 | public BaseMockRecipientEditTextView(Context context) { |
| 52 | super(context, null); |
| 53 | mTokenizer = new Rfc822Tokenizer(); |
| 54 | setTokenizer(mTokenizer); |
| 55 | } |
| 56 | |
| 57 | @Override |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 58 | public DrawableRecipientChip[] getSortedRecipients() { |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 59 | return mMockRecips; |
| 60 | } |
| 61 | |
| 62 | @Override |
| 63 | public int getLineHeight() { |
| 64 | return 48; |
| 65 | } |
| 66 | |
| 67 | @Override |
| 68 | Drawable getChipBackground(RecipientEntry contact) { |
| 69 | return createChipBackground(); |
| 70 | } |
| 71 | |
| 72 | @Override |
| 73 | public int getViewWidth() { |
| 74 | return 100; |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | class MockRecipientEditTextView extends BaseMockRecipientEditTextView { |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 79 | |
| 80 | public MockRecipientEditTextView(Context context) { |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 81 | super(context); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 82 | mTokenizer = new Rfc822Tokenizer(); |
| 83 | setTokenizer(mTokenizer); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | @Override |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 87 | public DrawableRecipientChip[] getSortedRecipients() { |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 88 | return mMockRecips; |
| 89 | } |
| 90 | |
| 91 | @Override |
| 92 | public Editable getText() { |
| 93 | return mEditable; |
| 94 | } |
| 95 | |
| 96 | @Override |
| 97 | public Editable getSpannable() { |
| 98 | return mEditable; |
| 99 | } |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 100 | |
| 101 | @Override |
| 102 | public int getLineHeight() { |
| 103 | return 48; |
| 104 | } |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 105 | |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 106 | @Override |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 107 | Drawable getChipBackground(RecipientEntry contact) { |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 108 | return createChipBackground(); |
| 109 | } |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 110 | |
| 111 | @Override |
| 112 | public int length() { |
| 113 | return mEditable != null ? mEditable.length() : 0; |
| 114 | } |
| 115 | |
| 116 | @Override |
| 117 | public String toString() { |
| 118 | return mEditable != null ? mEditable.toString() : ""; |
| 119 | } |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 120 | |
| 121 | @Override |
| 122 | public int getViewWidth() { |
| 123 | return 100; |
| 124 | } |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 125 | } |
| 126 | |
Mindy Pereira | bdf58b6 | 2012-05-02 14:16:50 -0700 | [diff] [blame] | 127 | private class TestBaseRecipientAdapter extends BaseRecipientAdapter { |
Scott Kennedy | 983c99b | 2013-03-22 09:42:03 -0700 | [diff] [blame] | 128 | public TestBaseRecipientAdapter(final Context context) { |
Mindy Pereira | bdf58b6 | 2012-05-02 14:16:50 -0700 | [diff] [blame] | 129 | super(context); |
| 130 | } |
Scott Kennedy | 983c99b | 2013-03-22 09:42:03 -0700 | [diff] [blame] | 131 | |
| 132 | public TestBaseRecipientAdapter(final Context context, final int preferredMaxResultCount, |
| 133 | final int queryMode) { |
| 134 | super(context, preferredMaxResultCount, queryMode); |
| 135 | } |
Mindy Pereira | bdf58b6 | 2012-05-02 14:16:50 -0700 | [diff] [blame] | 136 | } |
| 137 | |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 138 | private MockRecipientEditTextView createViewForTesting() { |
| 139 | mEditable = new SpannableStringBuilder(); |
| 140 | MockRecipientEditTextView view = new MockRecipientEditTextView(getContext()); |
Mindy Pereira | bdf58b6 | 2012-05-02 14:16:50 -0700 | [diff] [blame] | 141 | view.setAdapter(new TestBaseRecipientAdapter(getContext())); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 142 | return view; |
| 143 | } |
| 144 | |
| 145 | public void testCreateDisplayText() { |
| 146 | RecipientEditTextView view = createViewForTesting(); |
| 147 | RecipientEntry entry = RecipientEntry.constructGeneratedEntry("User Name, Jr", |
Scott Kennedy | b1cddbb | 2013-03-06 10:38:07 -0800 | [diff] [blame] | 148 | "user@username.com", true); |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 149 | String testAddress = view.createAddressText(entry); |
| 150 | String testDisplay = view.createChipDisplayText(entry); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 151 | assertEquals("Expected a properly formatted RFC email address", |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 152 | "\"User Name, Jr\" <user@username.com>, ", testAddress); |
| 153 | assertEquals("Expected a displayable name", "User Name, Jr", testDisplay); |
| 154 | |
Scott Kennedy | b1cddbb | 2013-03-06 10:38:07 -0800 | [diff] [blame] | 155 | RecipientEntry alreadyFormatted = |
| 156 | RecipientEntry.constructFakeEntry("user@username.com, ", true); |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 157 | testAddress = view.createAddressText(alreadyFormatted); |
| 158 | testDisplay = view.createChipDisplayText(alreadyFormatted); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 159 | assertEquals("Expected a properly formatted RFC email address", "<user@username.com>, ", |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 160 | testAddress); |
| 161 | assertEquals("Expected a displayable name", "user@username.com", testDisplay); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 162 | |
| 163 | RecipientEntry alreadyFormattedNoSpace = RecipientEntry |
Scott Kennedy | b1cddbb | 2013-03-06 10:38:07 -0800 | [diff] [blame] | 164 | .constructFakeEntry("user@username.com,", true); |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 165 | testAddress = view.createAddressText(alreadyFormattedNoSpace); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 166 | assertEquals("Expected a properly formatted RFC email address", "<user@username.com>, ", |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 167 | testAddress); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 168 | |
| 169 | RecipientEntry alreadyNamed = RecipientEntry.constructGeneratedEntry("User Name", |
Scott Kennedy | b1cddbb | 2013-03-06 10:38:07 -0800 | [diff] [blame] | 170 | "\"User Name, Jr\" <user@username.com>", true); |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 171 | testAddress = view.createAddressText(alreadyNamed); |
| 172 | testDisplay = view.createChipDisplayText(alreadyNamed); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 173 | assertEquals( |
| 174 | "Expected address that used the name not the excess address name", |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 175 | "User Name <user@username.com>, ", testAddress); |
| 176 | assertEquals("Expected a displayable name", "User Name", testDisplay); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | public void testSanitizeBetween() { |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 180 | // First, add 2 chips and then make sure we remove |
| 181 | // the extra content between them correctly. |
Mindy Pereira | 8eb031e | 2011-09-20 15:42:32 -0700 | [diff] [blame] | 182 | populateMocks(2); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 183 | MockRecipientEditTextView view = createViewForTesting(); |
| 184 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 185 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 186 | String extra = "EXTRA"; |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 187 | mEditable = new SpannableStringBuilder(); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 188 | mEditable.append(first + extra + second); |
| 189 | int firstStart = mEditable.toString().indexOf(first); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 190 | int firstEnd = firstStart + first.trim().length(); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 191 | int secondStart = mEditable.toString().indexOf(second); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 192 | int secondEnd = secondStart + second.trim().length(); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 193 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], firstStart, firstEnd, 0); |
| 194 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], secondStart, secondEnd, 0); |
| 195 | view.sanitizeBetween(); |
| 196 | String editableString = mEditable.toString(); |
| 197 | assertEquals(editableString.indexOf(extra), -1); |
| 198 | assertEquals(editableString.indexOf(first), firstStart); |
| 199 | assertEquals(editableString.indexOf(second), secondStart - extra.length()); |
| 200 | assertEquals(editableString, (first + second)); |
| 201 | |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 202 | // Add 1 chip and make sure that we remove the extra stuff before it correctly. |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 203 | mEditable = new SpannableStringBuilder(); |
Mindy Pereira | 8eb031e | 2011-09-20 15:42:32 -0700 | [diff] [blame] | 204 | populateMocks(1); |
| 205 | mEditable.append(extra); |
Mindy Pereira | 01162ce | 2011-09-20 12:21:55 -0700 | [diff] [blame] | 206 | mEditable.append(first); |
| 207 | firstStart = mEditable.toString().indexOf(first); |
| 208 | firstEnd = firstStart + first.length(); |
| 209 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], firstStart, firstEnd, 0); |
| 210 | view.sanitizeBetween(); |
| 211 | assertEquals(mEditable.toString(), first); |
Mindy Pereira | 8eb031e | 2011-09-20 15:42:32 -0700 | [diff] [blame] | 212 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), firstStart |
| 213 | - extra.length()); |
| 214 | } |
| 215 | |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 216 | public void testSanitizeEnd() { |
| 217 | // First, add 2 chips and then make sure we remove |
| 218 | // the extra content between them correctly. |
| 219 | populateMocks(2); |
| 220 | MockRecipientEditTextView view = createViewForTesting(); |
| 221 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 222 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 223 | String extra = "EXTRA"; |
| 224 | mEditable = new SpannableStringBuilder(); |
| 225 | mEditable.append(first + second); |
| 226 | int firstStart = mEditable.toString().indexOf(first); |
| 227 | int firstEnd = firstStart + first.trim().length(); |
| 228 | int secondStart = mEditable.toString().indexOf(second); |
| 229 | int secondEnd = secondStart + second.trim().length(); |
| 230 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], firstStart, firstEnd, 0); |
| 231 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], secondStart, secondEnd, 0); |
| 232 | view.sanitizeEnd(); |
| 233 | String editableString = mEditable.toString(); |
| 234 | assertEquals(editableString.indexOf(extra), -1); |
| 235 | assertEquals(editableString.indexOf(first), firstStart); |
| 236 | assertEquals(editableString.indexOf(second), secondStart); |
| 237 | assertEquals(editableString, (first + second)); |
| 238 | mEditable.append(extra); |
| 239 | editableString = mEditable.toString(); |
| 240 | assertEquals(mEditable.toString(), (first + second + extra)); |
| 241 | view.sanitizeEnd(); |
| 242 | assertEquals(mEditable.toString(), (first + second)); |
| 243 | } |
| 244 | |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 245 | public void testMoreChipPlainText() { |
| 246 | MockRecipientEditTextView view = createViewForTesting(); |
| 247 | view.setMoreItem(createTestMoreItem()); |
| 248 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 249 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 250 | String third = (String) mTokenizer.terminateToken("THIRD"); |
| 251 | mEditable = new SpannableStringBuilder(); |
| 252 | mEditable.append(first+second+third); |
| 253 | int thirdStart = mEditable.toString().indexOf(third); |
| 254 | int thirdEnd = thirdStart + third.trim().length(); |
| 255 | view.createMoreChipPlainText(); |
Jin Cao | 6c2a016 | 2014-08-17 15:00:50 -0700 | [diff] [blame] | 256 | ReplacementDrawableSpan moreChip = view.getMoreChip(); |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 257 | assertEquals(mEditable.getSpanStart(moreChip), thirdStart); |
| 258 | assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd + 1); |
| 259 | } |
| 260 | |
| 261 | public void testCountTokens() { |
| 262 | MockRecipientEditTextView view = createViewForTesting(); |
| 263 | view.setMoreItem(createTestMoreItem()); |
| 264 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 265 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 266 | String third = (String) mTokenizer.terminateToken("THIRD"); |
Scott Kennedy | f7e202d | 2013-03-06 21:38:10 -0800 | [diff] [blame] | 267 | String fourth = "FOURTH,"; |
| 268 | String fifth = "FIFTH,"; |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 269 | mEditable = new SpannableStringBuilder(); |
| 270 | mEditable.append(first+second+third+fourth+fifth); |
| 271 | assertEquals(view.countTokens(mEditable), 5); |
| 272 | } |
| 273 | |
| 274 | public void testTooManyRecips() { |
| 275 | BaseMockRecipientEditTextView view = new BaseMockRecipientEditTextView(getContext()); |
| 276 | view.setMoreItem(createTestMoreItem()); |
| 277 | for (int i = 0; i < 100; i++) { |
| 278 | view.append(mTokenizer.terminateToken(i + "")); |
| 279 | } |
| 280 | assertEquals(view.countTokens(view.getText()), 100); |
| 281 | view.handlePendingChips(); |
| 282 | view.createMoreChip(); |
Jin Cao | 6c2a016 | 2014-08-17 15:00:50 -0700 | [diff] [blame] | 283 | ReplacementDrawableSpan moreChip = view.getMoreChip(); |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 284 | // We show 2 chips then place a more chip. |
| 285 | int secondStart = view.getText().toString().indexOf( |
| 286 | (String) mTokenizer.terminateToken(RecipientEditTextView.CHIP_LIMIT + "")); |
| 287 | assertEquals(view.getText().getSpanStart(moreChip), secondStart); |
| 288 | assertEquals(view.getText().getSpanEnd(moreChip), view.length()); |
| 289 | assertEquals(view.getSortedRecipients(), null); |
| 290 | } |
| 291 | |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 292 | public void testMoreChip() { |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 293 | // Add 3 chips: this is the trigger point at which the more chip will be created. |
| 294 | // Test that adding the chips and then creating and removing the more chip, as if |
| 295 | // the user were focusing/ removing focus from the chips field. |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 296 | populateMocks(3); |
| 297 | MockRecipientEditTextView view = createViewForTesting(); |
| 298 | view.setMoreItem(createTestMoreItem()); |
| 299 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 300 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 301 | String third = (String) mTokenizer.terminateToken("THIRD"); |
| 302 | mEditable = new SpannableStringBuilder(); |
| 303 | mEditable.append(first+second+third); |
| 304 | |
| 305 | int firstStart = mEditable.toString().indexOf(first); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 306 | int firstEnd = firstStart + first.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 307 | int secondStart = mEditable.toString().indexOf(second); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 308 | int secondEnd = secondStart + second.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 309 | int thirdStart = mEditable.toString().indexOf(third); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 310 | int thirdEnd = thirdStart + third.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 311 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 312 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 313 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 314 | |
| 315 | view.createMoreChip(); |
| 316 | assertEquals(mEditable.toString(), first+second+third); |
| 317 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); |
| 318 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); |
| 319 | // Find the more chip. |
Jin Cao | 6c2a016 | 2014-08-17 15:00:50 -0700 | [diff] [blame] | 320 | ReplacementDrawableSpan moreChip = view.getMoreChip(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 321 | assertEquals(mEditable.getSpanStart(moreChip), thirdStart); |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 322 | assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd + 1); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 323 | |
| 324 | view.removeMoreChip(); |
| 325 | assertEquals(mEditable.toString(), first+second+third); |
| 326 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); |
| 327 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); |
| 328 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); |
| 329 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart); |
| 330 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd); |
| 331 | moreChip = view.getMoreChip(); |
| 332 | assertEquals(mEditable.getSpanStart(moreChip), -1); |
| 333 | |
| 334 | // Rinse and repeat, just in case! |
| 335 | view.createMoreChip(); |
| 336 | assertEquals(mEditable.toString(), first+second+third); |
| 337 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); |
| 338 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); |
| 339 | // Find the more chip. |
| 340 | moreChip = view.getMoreChip(); |
| 341 | assertEquals(mEditable.getSpanStart(moreChip), thirdStart); |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 342 | assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd + 1); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 343 | |
| 344 | view.removeMoreChip(); |
| 345 | assertEquals(mEditable.toString(), first+second+third); |
| 346 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); |
| 347 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); |
| 348 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); |
| 349 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart); |
| 350 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd); |
| 351 | moreChip = view.getMoreChip(); |
| 352 | assertEquals(mEditable.getSpanStart(moreChip), -1); |
| 353 | } |
| 354 | |
| 355 | public void testMoreChipLotsOfUsers() { |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 356 | // Test adding and removing the more chip in the case where we have a lot of users. |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 357 | populateMocks(10); |
| 358 | MockRecipientEditTextView view = createViewForTesting(); |
| 359 | view.setMoreItem(createTestMoreItem()); |
| 360 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 361 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 362 | String third = (String) mTokenizer.terminateToken("THIRD"); |
| 363 | String fourth = (String) mTokenizer.terminateToken("FOURTH"); |
| 364 | String fifth = (String) mTokenizer.terminateToken("FIFTH"); |
| 365 | String sixth = (String) mTokenizer.terminateToken("SIXTH"); |
| 366 | String seventh = (String) mTokenizer.terminateToken("SEVENTH"); |
| 367 | String eigth = (String) mTokenizer.terminateToken("EIGHTH"); |
| 368 | String ninth = (String) mTokenizer.terminateToken("NINTH"); |
| 369 | String tenth = (String) mTokenizer.terminateToken("TENTH"); |
| 370 | mEditable = new SpannableStringBuilder(); |
| 371 | mEditable.append(first+second+third+fourth+fifth+sixth+seventh+eigth+ninth+tenth); |
| 372 | |
| 373 | int firstStart = mEditable.toString().indexOf(first); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 374 | int firstEnd = firstStart + first.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 375 | int secondStart = mEditable.toString().indexOf(second); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 376 | int secondEnd = secondStart + second.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 377 | int thirdStart = mEditable.toString().indexOf(third); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 378 | int thirdEnd = thirdStart + third.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 379 | int fourthStart = mEditable.toString().indexOf(fourth); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 380 | int fourthEnd = fourthStart + fourth.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 381 | int fifthStart = mEditable.toString().indexOf(fifth); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 382 | int fifthEnd = fifthStart + fifth.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 383 | int sixthStart = mEditable.toString().indexOf(sixth); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 384 | int sixthEnd = sixthStart + sixth.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 385 | int seventhStart = mEditable.toString().indexOf(seventh); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 386 | int seventhEnd = seventhStart + seventh.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 387 | int eighthStart = mEditable.toString().indexOf(eigth); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 388 | int eighthEnd = eighthStart + eigth.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 389 | int ninthStart = mEditable.toString().indexOf(ninth); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 390 | int ninthEnd = ninthStart + ninth.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 391 | int tenthStart = mEditable.toString().indexOf(tenth); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 392 | int tenthEnd = tenthStart + tenth.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 393 | mEditable.setSpan(mMockRecips[mMockRecips.length - 10], firstStart, firstEnd, 0); |
| 394 | mEditable.setSpan(mMockRecips[mMockRecips.length - 9], secondStart, secondEnd, 0); |
| 395 | mEditable.setSpan(mMockRecips[mMockRecips.length - 8], thirdStart, thirdEnd, 0); |
| 396 | mEditable.setSpan(mMockRecips[mMockRecips.length - 7], fourthStart, fourthEnd, 0); |
| 397 | mEditable.setSpan(mMockRecips[mMockRecips.length - 6], fifthStart, fifthEnd, 0); |
| 398 | mEditable.setSpan(mMockRecips[mMockRecips.length - 5], sixthStart, sixthEnd, 0); |
| 399 | mEditable.setSpan(mMockRecips[mMockRecips.length - 4], seventhStart, seventhEnd, 0); |
| 400 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], eighthStart, eighthEnd, 0); |
| 401 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], ninthStart, ninthEnd, 0); |
| 402 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], tenthStart, tenthEnd, 0); |
| 403 | |
| 404 | view.createMoreChip(); |
| 405 | assertEquals(mEditable.toString(), first + second + third + fourth + fifth + sixth |
| 406 | + seventh + eigth + ninth + tenth); |
| 407 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 10]), firstStart); |
| 408 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 9]), secondStart); |
| 409 | // Find the more chip. |
Jin Cao | 6c2a016 | 2014-08-17 15:00:50 -0700 | [diff] [blame] | 410 | ReplacementDrawableSpan moreChip = view.getMoreChip(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 411 | assertEquals(mEditable.getSpanStart(moreChip), thirdStart); |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 412 | assertEquals(mEditable.getSpanEnd(moreChip), tenthEnd + 1); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 413 | |
| 414 | view.removeMoreChip(); |
| 415 | assertEquals(mEditable.toString(), first + second + third + fourth + fifth + sixth |
| 416 | + seventh + eigth + ninth + tenth); |
| 417 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 10]), firstStart); |
| 418 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 9]), secondStart); |
| 419 | |
| 420 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 8]), thirdStart); |
| 421 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 7]), fourthStart); |
| 422 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 6]), fifthStart); |
| 423 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 5]), sixthStart); |
| 424 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), seventhStart); |
| 425 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), eighthStart); |
| 426 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), ninthStart); |
| 427 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), tenthStart); |
| 428 | moreChip = view.getMoreChip(); |
| 429 | assertEquals(mEditable.getSpanStart(moreChip), -1); |
| 430 | |
| 431 | } |
| 432 | |
| 433 | public void testMoreChipSpecialChars() { |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 434 | // Make sure the more chip correctly handles extra tokenizer characters in the middle |
| 435 | // of chip text. |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 436 | populateMocks(3); |
| 437 | MockRecipientEditTextView view = createViewForTesting(); |
| 438 | view.setMoreItem(createTestMoreItem()); |
| 439 | String first = (String) mTokenizer.terminateToken("FI,RST"); |
| 440 | String second = (String) mTokenizer.terminateToken("SE,COND"); |
| 441 | String third = (String) mTokenizer.terminateToken("THI,RD"); |
| 442 | mEditable = new SpannableStringBuilder(); |
| 443 | mEditable.append(first+second+third); |
| 444 | |
| 445 | int firstStart = mEditable.toString().indexOf(first); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 446 | int firstEnd = firstStart + first.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 447 | int secondStart = mEditable.toString().indexOf(second); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 448 | int secondEnd = secondStart + second.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 449 | int thirdStart = mEditable.toString().indexOf(third); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 450 | int thirdEnd = thirdStart + third.trim().length(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 451 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 452 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 453 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 454 | |
| 455 | view.createMoreChip(); |
| 456 | assertEquals(mEditable.toString(), first+second+third); |
| 457 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); |
| 458 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); |
| 459 | // Find the more chip. |
Jin Cao | 6c2a016 | 2014-08-17 15:00:50 -0700 | [diff] [blame] | 460 | ReplacementDrawableSpan moreChip = view.getMoreChip(); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 461 | assertEquals(mEditable.getSpanStart(moreChip), thirdStart); |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 462 | assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd + 1); |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 463 | |
| 464 | view.removeMoreChip(); |
| 465 | assertEquals(mEditable.toString(), first+second+third); |
| 466 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); |
| 467 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); |
| 468 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); |
| 469 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart); |
| 470 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd); |
| 471 | moreChip = view.getMoreChip(); |
| 472 | assertEquals(mEditable.getSpanStart(moreChip), -1); |
| 473 | } |
| 474 | |
Mindy Pereira | dfeb97f | 2011-09-23 10:50:47 -0700 | [diff] [blame] | 475 | public void testMoreChipDupes() { |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 476 | // Make sure the more chip is correctly added and removed when we have duplicate chips. |
Mindy Pereira | dfeb97f | 2011-09-23 10:50:47 -0700 | [diff] [blame] | 477 | populateMocks(4); |
| 478 | MockRecipientEditTextView view = createViewForTesting(); |
| 479 | view.setMoreItem(createTestMoreItem()); |
| 480 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 481 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 482 | String third = (String) mTokenizer.terminateToken("THIRD"); |
| 483 | mEditable = new SpannableStringBuilder(); |
| 484 | mEditable.append(first+second+third+third); |
| 485 | |
| 486 | int firstStart = mEditable.toString().indexOf(first); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 487 | int firstEnd = firstStart + first.trim().length(); |
Mindy Pereira | dfeb97f | 2011-09-23 10:50:47 -0700 | [diff] [blame] | 488 | int secondStart = mEditable.toString().indexOf(second); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 489 | int secondEnd = secondStart + second.trim().length(); |
Mindy Pereira | dfeb97f | 2011-09-23 10:50:47 -0700 | [diff] [blame] | 490 | int thirdStart = mEditable.toString().indexOf(third); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 491 | int thirdEnd = thirdStart + third.trim().length(); |
Mindy Pereira | dfeb97f | 2011-09-23 10:50:47 -0700 | [diff] [blame] | 492 | int thirdNextStart = mEditable.toString().indexOf(third, thirdEnd); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 493 | int thirdNextEnd = thirdNextStart + third.trim().length(); |
Mindy Pereira | dfeb97f | 2011-09-23 10:50:47 -0700 | [diff] [blame] | 494 | mEditable.setSpan(mMockRecips[mMockRecips.length - 4], firstStart, firstEnd, 0); |
| 495 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], secondStart, secondEnd, 0); |
| 496 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], thirdStart, thirdEnd, 0); |
| 497 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdNextStart, thirdNextEnd, 0); |
| 498 | |
| 499 | view.createMoreChip(); |
| 500 | assertEquals(mEditable.toString(), first+second+third+third); |
| 501 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), firstStart); |
| 502 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), secondStart); |
| 503 | // Find the more chip. |
Jin Cao | 6c2a016 | 2014-08-17 15:00:50 -0700 | [diff] [blame] | 504 | ReplacementDrawableSpan moreChip = view.getMoreChip(); |
Mindy Pereira | dfeb97f | 2011-09-23 10:50:47 -0700 | [diff] [blame] | 505 | assertEquals(mEditable.getSpanStart(moreChip), thirdStart); |
Mindy Pereira | f6519d2 | 2011-11-02 13:33:18 -0700 | [diff] [blame] | 506 | assertEquals(mEditable.getSpanEnd(moreChip), thirdNextEnd + 1); |
Mindy Pereira | dfeb97f | 2011-09-23 10:50:47 -0700 | [diff] [blame] | 507 | |
| 508 | view.removeMoreChip(); |
| 509 | assertEquals(mEditable.toString(), first+second+third+third); |
| 510 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), firstStart); |
| 511 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 4]), firstEnd); |
| 512 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), secondStart); |
| 513 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), thirdStart); |
| 514 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), thirdEnd); |
| 515 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdNextStart); |
| 516 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdNextEnd); |
| 517 | moreChip = view.getMoreChip(); |
| 518 | assertEquals(mEditable.getSpanStart(moreChip), -1); |
| 519 | } |
| 520 | |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 521 | public void testRemoveChip() { |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 522 | // Create 3 chips to start and test removing chips in various postions. |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 523 | populateMocks(3); |
| 524 | MockRecipientEditTextView view = createViewForTesting(); |
| 525 | view.setMoreItem(createTestMoreItem()); |
| 526 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 527 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 528 | String third = (String) mTokenizer.terminateToken("THIRD"); |
| 529 | mEditable = new SpannableStringBuilder(); |
| 530 | mEditable.append(first + second + third); |
| 531 | |
| 532 | int firstStart = mEditable.toString().indexOf(first); |
| 533 | int firstEnd = firstStart + first.length(); |
| 534 | int secondStart = mEditable.toString().indexOf(second); |
| 535 | int secondEnd = secondStart + second.length(); |
| 536 | int thirdStart = mEditable.toString().indexOf(third); |
| 537 | int thirdEnd = thirdStart + third.length(); |
| 538 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 539 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 540 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 541 | assertEquals(mEditable.toString(), first + second + third); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 542 | // Test removing the middle chip. |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 543 | view.removeChip(mMockRecips[mMockRecips.length - 2]); |
| 544 | assertEquals(mEditable.toString(), first + third); |
| 545 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); |
| 546 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); |
| 547 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), -1); |
| 548 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), -1); |
| 549 | int newThirdStart = mEditable.toString().indexOf(third); |
| 550 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), newThirdStart); |
| 551 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), newThirdStart |
| 552 | + third.length()); |
| 553 | |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 554 | // Test removing the first chip. |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 555 | populateMocks(3); |
| 556 | view = createViewForTesting(); |
| 557 | view.setMoreItem(createTestMoreItem()); |
| 558 | mEditable = new SpannableStringBuilder(); |
| 559 | mEditable.append(first + second + third); |
| 560 | |
| 561 | firstStart = mEditable.toString().indexOf(first); |
| 562 | firstEnd = firstStart + first.length(); |
| 563 | secondStart = mEditable.toString().indexOf(second); |
| 564 | secondEnd = secondStart + second.length(); |
| 565 | thirdStart = mEditable.toString().indexOf(third); |
| 566 | thirdEnd = thirdStart + third.length(); |
| 567 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 568 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 569 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 570 | assertEquals(mEditable.toString(), first + second + third); |
| 571 | view.removeChip(mMockRecips[mMockRecips.length - 3]); |
| 572 | assertEquals(mEditable.toString(), second + third); |
| 573 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), -1); |
| 574 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), -1); |
| 575 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), 0); |
| 576 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), second.length()); |
| 577 | newThirdStart = mEditable.toString().indexOf(third); |
| 578 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), newThirdStart); |
| 579 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), newThirdStart |
| 580 | + third.length()); |
| 581 | |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 582 | // Test removing the last chip. |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 583 | populateMocks(3); |
| 584 | view = createViewForTesting(); |
| 585 | view.setMoreItem(createTestMoreItem()); |
| 586 | mEditable = new SpannableStringBuilder(); |
| 587 | mEditable.append(first + second + third); |
| 588 | |
| 589 | firstStart = mEditable.toString().indexOf(first); |
| 590 | firstEnd = firstStart + first.length(); |
| 591 | secondStart = mEditable.toString().indexOf(second); |
| 592 | secondEnd = secondStart + second.length(); |
| 593 | thirdStart = mEditable.toString().indexOf(third); |
| 594 | thirdEnd = thirdStart + third.length(); |
| 595 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 596 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 597 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 598 | assertEquals(mEditable.toString(), first + second + third); |
| 599 | view.removeChip(mMockRecips[mMockRecips.length - 1]); |
| 600 | assertEquals(mEditable.toString(), first + second); |
| 601 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); |
| 602 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); |
| 603 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); |
| 604 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), secondEnd); |
| 605 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), -1); |
| 606 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), -1); |
| 607 | } |
| 608 | |
| 609 | public void testReplaceChip() { |
| 610 | populateMocks(3); |
| 611 | MockRecipientEditTextView view = createViewForTesting(); |
| 612 | view.setMoreItem(createTestMoreItem()); |
| 613 | view.setChipBackground(createChipBackground()); |
| 614 | view.setChipHeight(48); |
| 615 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 616 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 617 | String third = (String) mTokenizer.terminateToken("THIRD"); |
| 618 | mEditable = new SpannableStringBuilder(); |
| 619 | mEditable.append(first + second + third); |
| 620 | |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 621 | // Test replacing the first chip with a new chip. |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 622 | int firstStart = mEditable.toString().indexOf(first); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 623 | int firstEnd = firstStart + first.trim().length(); |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 624 | int secondStart = mEditable.toString().indexOf(second); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 625 | int secondEnd = secondStart + second.trim().length(); |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 626 | int thirdStart = mEditable.toString().indexOf(third); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 627 | int thirdEnd = thirdStart + third.trim().length(); |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 628 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 629 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 630 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 631 | assertEquals(mEditable.toString(), first + second + third); |
| 632 | view.replaceChip(mMockRecips[mMockRecips.length - 3], RecipientEntry |
Scott Kennedy | b1cddbb | 2013-03-06 10:38:07 -0800 | [diff] [blame] | 633 | .constructGeneratedEntry("replacement", "replacement@replacement.com", true)); |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 634 | assertEquals(mEditable.toString(), mTokenizer |
| 635 | .terminateToken("replacement <replacement@replacement.com>") |
| 636 | + second + third); |
| 637 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), -1); |
| 638 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), -1); |
| 639 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), mEditable |
| 640 | .toString().indexOf(second)); |
| 641 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), mEditable |
| 642 | .toString().indexOf(second) |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 643 | + second.trim().length()); |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 644 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), mEditable |
| 645 | .toString().indexOf(third)); |
| 646 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), mEditable |
| 647 | .toString().indexOf(third) |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 648 | + third.trim().length()); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 649 | DrawableRecipientChip[] spans = |
| 650 | mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class); |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 651 | assertEquals(spans.length, 3); |
| 652 | spans = mEditable |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 653 | .getSpans(0, mEditable.toString().indexOf(second) - 1, DrawableRecipientChip.class); |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 654 | assertEquals((String) spans[0].getDisplay(), "replacement"); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 655 | |
| 656 | |
| 657 | // Test replacing the middle chip with a new chip. |
| 658 | mEditable = new SpannableStringBuilder(); |
| 659 | mEditable.append(first + second + third); |
| 660 | firstStart = mEditable.toString().indexOf(first); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 661 | firstEnd = firstStart + first.trim().length(); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 662 | secondStart = mEditable.toString().indexOf(second); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 663 | secondEnd = secondStart + second.trim().length(); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 664 | thirdStart = mEditable.toString().indexOf(third); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 665 | thirdEnd = thirdStart + third.trim().length(); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 666 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 667 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 668 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 669 | assertEquals(mEditable.toString(), first + second + third); |
| 670 | view.replaceChip(mMockRecips[mMockRecips.length - 2], RecipientEntry |
Scott Kennedy | b1cddbb | 2013-03-06 10:38:07 -0800 | [diff] [blame] | 671 | .constructGeneratedEntry("replacement", "replacement@replacement.com", true)); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 672 | assertEquals(mEditable.toString(), first + mTokenizer |
| 673 | .terminateToken("replacement <replacement@replacement.com>") + third); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 674 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); |
| 675 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); |
| 676 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), -1); |
| 677 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), -1); |
| 678 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), mEditable |
| 679 | .toString().indexOf(third)); |
| 680 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), mEditable |
| 681 | .toString().indexOf(third) |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 682 | + third.trim().length()); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 683 | spans = mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 684 | assertEquals(spans.length, 3); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 685 | spans = mEditable.getSpans(firstEnd, mEditable.toString().indexOf(third) - 1, |
| 686 | DrawableRecipientChip.class); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 687 | assertEquals((String) spans[0].getDisplay(), "replacement"); |
| 688 | |
| 689 | |
| 690 | // Test replacing the last chip with a new chip. |
| 691 | mEditable = new SpannableStringBuilder(); |
| 692 | mEditable.append(first + second + third); |
| 693 | firstStart = mEditable.toString().indexOf(first); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 694 | firstEnd = firstStart + first.trim().length(); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 695 | secondStart = mEditable.toString().indexOf(second); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 696 | secondEnd = secondStart + second.trim().length(); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 697 | thirdStart = mEditable.toString().indexOf(third); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 698 | thirdEnd = thirdStart + third.trim().length(); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 699 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 700 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 701 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 702 | assertEquals(mEditable.toString(), first + second + third); |
| 703 | view.replaceChip(mMockRecips[mMockRecips.length - 1], RecipientEntry |
Scott Kennedy | b1cddbb | 2013-03-06 10:38:07 -0800 | [diff] [blame] | 704 | .constructGeneratedEntry("replacement", "replacement@replacement.com", true)); |
Mindy Pereira | 62397a5 | 2011-10-03 13:46:43 -0700 | [diff] [blame] | 705 | assertEquals(mEditable.toString(), first + second + mTokenizer |
| 706 | .terminateToken("replacement <replacement@replacement.com>")); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 707 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); |
| 708 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); |
| 709 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); |
| 710 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), secondEnd); |
| 711 | assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), -1); |
| 712 | assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), -1); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 713 | spans = mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 714 | assertEquals(spans.length, 3); |
| 715 | spans = mEditable |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 716 | .getSpans(secondEnd, mEditable.length(), DrawableRecipientChip.class); |
Mindy Pereira | fecc6f8 | 2011-09-27 10:05:05 -0700 | [diff] [blame] | 717 | assertEquals((String) spans[0].getDisplay(), "replacement"); |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 718 | } |
| 719 | |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 720 | public void testHandlePaste() { |
| 721 | // Start with an empty edit field. |
| 722 | // Add an address; the text should be left as is. |
| 723 | MockRecipientEditTextView view = createViewForTesting(); |
| 724 | view.setMoreItem(createTestMoreItem()); |
| 725 | view.setChipBackground(createChipBackground()); |
| 726 | view.setChipHeight(48); |
| 727 | mEditable = new SpannableStringBuilder(); |
| 728 | mEditable.append("user@user.com"); |
| 729 | view.setSelection(mEditable.length()); |
| 730 | view.handlePaste(); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 731 | assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, 0); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 732 | assertEquals(mEditable.toString(), "user@user.com"); |
| 733 | |
| 734 | // Test adding a single address to an empty chips field with a space at |
| 735 | // the end of it. The address should stay as text. |
| 736 | mEditable = new SpannableStringBuilder(); |
| 737 | String tokenizedUser = "user@user.com" + " "; |
| 738 | mEditable.append(tokenizedUser); |
| 739 | view.setSelection(mEditable.length()); |
| 740 | view.handlePaste(); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 741 | assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, 0); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 742 | assertEquals(mEditable.toString(), tokenizedUser); |
| 743 | |
| 744 | // Test adding a single address to an empty chips field with a semicolon at |
| 745 | // the end of it. The address should become a chip |
| 746 | mEditable = new SpannableStringBuilder(); |
| 747 | tokenizedUser = "user@user.com;"; |
| 748 | mEditable.append(tokenizedUser); |
| 749 | view.setSelection(mEditable.length()); |
| 750 | view.handlePaste(); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 751 | assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, 1); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 752 | |
| 753 | // Test adding 2 address to an empty chips field. The second to last |
| 754 | // address should become a chip and the last address should stay as |
| 755 | // text. |
| 756 | mEditable = new SpannableStringBuilder(); |
| 757 | mEditable.append("user1,user2@user.com"); |
| 758 | view.setSelection(mEditable.length()); |
| 759 | view.handlePaste(); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 760 | assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, 1); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 761 | assertEquals(mEditable.getSpans(0, mEditable.toString().indexOf("user2@user.com"), |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 762 | DrawableRecipientChip.class).length, 1); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 763 | assertEquals(mEditable.toString(), "<user1>, user2@user.com"); |
| 764 | |
| 765 | // Test adding a single address to the end of existing chips. The existing |
| 766 | // chips should remain, and the last address should stay as text. |
| 767 | populateMocks(3); |
| 768 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 769 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 770 | String third = (String) mTokenizer.terminateToken("THIRD"); |
| 771 | mEditable = new SpannableStringBuilder(); |
| 772 | mEditable.append(first + second + third); |
| 773 | view.setSelection(mEditable.length()); |
| 774 | int firstStart = mEditable.toString().indexOf(first); |
| 775 | int firstEnd = firstStart + first.trim().length(); |
| 776 | int secondStart = mEditable.toString().indexOf(second); |
| 777 | int secondEnd = secondStart + second.trim().length(); |
| 778 | int thirdStart = mEditable.toString().indexOf(third); |
| 779 | int thirdEnd = thirdStart + third.trim().length(); |
| 780 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 781 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 782 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 783 | |
| 784 | mEditable.append("user@user.com"); |
| 785 | view.setSelection(mEditable.length()); |
| 786 | view.handlePaste(); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 787 | assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 788 | mMockRecips.length); |
| 789 | assertEquals(mEditable.toString(), first + second + third + "user@user.com"); |
| 790 | |
| 791 | // Paste 2 addresses after existing chips. We expect the first address to be turned into |
| 792 | // a chip and the second to be left as text. |
| 793 | populateMocks(3); |
| 794 | mEditable = new SpannableStringBuilder(); |
| 795 | mEditable.append(first + second + third); |
| 796 | |
| 797 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 798 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 799 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 800 | |
| 801 | mEditable.append("user1, user2@user.com"); |
| 802 | view.setSelection(mEditable.length()); |
| 803 | view.handlePaste(); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 804 | assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 805 | mMockRecips.length + 1); |
| 806 | assertEquals(mEditable.getSpans(mEditable.toString().indexOf("<user1>"), mEditable |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 807 | .toString().indexOf("user2@user.com") - 1, DrawableRecipientChip.class).length, 1); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 808 | assertEquals(mEditable.getSpans(mEditable.toString().indexOf("user2@user.com"), mEditable |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 809 | .length(), DrawableRecipientChip.class).length, 0); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 810 | assertEquals(mEditable.toString(), first + second + third + "<user1>, user2@user.com"); |
| 811 | |
| 812 | // Paste 2 addresses after existing chips. We expect the first address to be turned into |
| 813 | // a chip and the second to be left as text. This removes the space seperator char between |
| 814 | // addresses. |
| 815 | populateMocks(3); |
| 816 | mEditable = new SpannableStringBuilder(); |
| 817 | mEditable.append(first + second + third); |
| 818 | |
| 819 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 820 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 821 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 822 | |
| 823 | mEditable.append("user1,user2@user.com"); |
| 824 | view.setSelection(mEditable.length()); |
| 825 | view.handlePaste(); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 826 | assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 827 | mMockRecips.length + 1); |
| 828 | assertEquals(mEditable.getSpans(mEditable.toString().indexOf("<user1>"), mEditable |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 829 | .toString().indexOf("user2@user.com") - 1, DrawableRecipientChip.class).length, 1); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 830 | assertEquals(mEditable.getSpans(mEditable.toString().indexOf("user2@user.com"), mEditable |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 831 | .length(), DrawableRecipientChip.class).length, 0); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 832 | assertEquals(mEditable.toString(), first + second + third + "<user1>, user2@user.com"); |
| 833 | |
| 834 | // Test a complete token pasted in at the end. It should be turned into a chip. |
| 835 | mEditable = new SpannableStringBuilder(); |
| 836 | mEditable.append("user1, user2@user.com,"); |
| 837 | view.setSelection(mEditable.length()); |
| 838 | view.handlePaste(); |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 839 | assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, 2); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 840 | assertEquals(mEditable.getSpans(mEditable.toString().indexOf("<user1>"), mEditable |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 841 | .toString().indexOf("user2@user.com") - 1, DrawableRecipientChip.class).length, 1); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 842 | assertEquals(mEditable.getSpans(mEditable.toString().indexOf("user2@user.com"), mEditable |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 843 | .length(), DrawableRecipientChip.class).length, 1); |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 844 | assertEquals(mEditable.toString(), "<user1>, <user2@user.com>, "); |
| 845 | } |
| 846 | |
Régis Décamps | 219cbfb | 2014-06-04 14:29:54 +0200 | [diff] [blame] | 847 | @TargetApi(16) |
| 848 | public void testHandlePasteClip() { |
| 849 | MockRecipientEditTextView view = createViewForTesting(); |
| 850 | |
| 851 | ClipData clipData = null; |
| 852 | mEditable = new SpannableStringBuilder(); |
| 853 | view.handlePasteClip(clipData); |
| 854 | assertEquals("", view.getText().toString()); |
| 855 | |
| 856 | clipData = ClipData.newPlainText("user label", "<foo@example.com>"); |
| 857 | mEditable = new SpannableStringBuilder(); |
| 858 | view.handlePasteClip(clipData); |
| 859 | assertEquals("<foo@example.com>", view.getText().toString()); |
| 860 | |
| 861 | clipData = ClipData.newHtmlText("user label", |
| 862 | "<bar@example.com>", "<a href=\"mailto:bar@example.com\">email</a>"); |
| 863 | mEditable = new SpannableStringBuilder(); |
| 864 | view.handlePasteClip(clipData); |
| 865 | assertEquals("<bar@example.com>", view.getText().toString()); |
| 866 | |
| 867 | ClipData.Item clipImageData = new ClipData.Item(Uri.parse("content://my/image")); |
| 868 | clipData = new ClipData("user label", new String[]{"image/jpeg"}, clipImageData); |
| 869 | mEditable = new SpannableStringBuilder(); |
| 870 | view.handlePasteClip(clipData); |
| 871 | assertEquals("", view.getText().toString() |
| 872 | ); |
| 873 | } |
| 874 | |
Mindy Pereira | 20c9d62 | 2011-10-12 13:18:04 -0700 | [diff] [blame] | 875 | public void testGetPastTerminators() { |
| 876 | MockRecipientEditTextView view = createViewForTesting(); |
| 877 | view.setMoreItem(createTestMoreItem()); |
| 878 | view.setChipBackground(createChipBackground()); |
| 879 | view.setChipHeight(48); |
| 880 | String test = "test"; |
| 881 | mEditable = new SpannableStringBuilder(); |
| 882 | mEditable.append(test); |
| 883 | assertEquals(view.movePastTerminators(mTokenizer.findTokenEnd(mEditable.toString(), 0)), |
| 884 | test.length()); |
| 885 | |
| 886 | test = "test,"; |
| 887 | mEditable = new SpannableStringBuilder(); |
| 888 | mEditable.append(test); |
| 889 | assertEquals(view.movePastTerminators(mTokenizer.findTokenEnd(mEditable.toString(), 0)), |
| 890 | test.length()); |
| 891 | |
| 892 | test = "test, "; |
| 893 | mEditable = new SpannableStringBuilder(); |
| 894 | mEditable.append(test); |
| 895 | assertEquals(view.movePastTerminators(mTokenizer.findTokenEnd(mEditable.toString(), 0)), |
| 896 | test.length()); |
| 897 | |
| 898 | test = "test;"; |
| 899 | mEditable = new SpannableStringBuilder(); |
| 900 | mEditable.append(test); |
| 901 | assertEquals(view.movePastTerminators(mTokenizer.findTokenEnd(mEditable.toString(), 0)), |
| 902 | test.length()); |
| 903 | |
| 904 | test = "test; "; |
| 905 | mEditable = new SpannableStringBuilder(); |
| 906 | mEditable.append(test); |
| 907 | assertEquals(view.movePastTerminators(mTokenizer.findTokenEnd(mEditable.toString(), 0)), |
| 908 | test.length()); |
| 909 | } |
| 910 | |
| 911 | public void testIsCompletedToken() { |
| 912 | MockRecipientEditTextView view = createViewForTesting(); |
| 913 | view.setMoreItem(createTestMoreItem()); |
| 914 | view.setChipBackground(createChipBackground()); |
| 915 | view.setChipHeight(48); |
| 916 | assertTrue(view.isCompletedToken("test;")); |
| 917 | assertTrue(view.isCompletedToken("test,")); |
| 918 | assertFalse(view.isCompletedToken("test")); |
| 919 | assertFalse(view.isCompletedToken("test ")); |
| 920 | } |
| 921 | |
Mindy Pereira | aca23c4 | 2011-10-13 16:22:09 -0700 | [diff] [blame] | 922 | public void testGetLastChip() { |
| 923 | populateMocks(3); |
| 924 | MockRecipientEditTextView view = createViewForTesting(); |
| 925 | view.setMoreItem(createTestMoreItem()); |
| 926 | view.setChipBackground(createChipBackground()); |
| 927 | view.setChipHeight(48); |
| 928 | String first = (String) mTokenizer.terminateToken("FIRST"); |
| 929 | String second = (String) mTokenizer.terminateToken("SECOND"); |
| 930 | String third = (String) mTokenizer.terminateToken("THIRD"); |
| 931 | mEditable = new SpannableStringBuilder(); |
| 932 | mEditable.append(first + second + third); |
| 933 | |
| 934 | // Test replacing the first chip with a new chip. |
| 935 | int firstStart = mEditable.toString().indexOf(first); |
| 936 | int firstEnd = firstStart + first.trim().length(); |
| 937 | int secondStart = mEditable.toString().indexOf(second); |
| 938 | int secondEnd = secondStart + second.trim().length(); |
| 939 | int thirdStart = mEditable.toString().indexOf(third); |
| 940 | int thirdEnd = thirdStart + third.trim().length(); |
| 941 | mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); |
| 942 | mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); |
| 943 | mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); |
| 944 | assertEquals(view.getLastChip(), mMockRecips[mMockRecips.length - 1]); |
| 945 | mEditable.append("extra"); |
| 946 | assertEquals(view.getLastChip(), mMockRecips[mMockRecips.length - 1]); |
| 947 | } |
| 948 | |
Mindy Pereira | 97cb259 | 2011-09-26 16:11:41 -0700 | [diff] [blame] | 949 | private Drawable createChipBackground() { |
| 950 | Bitmap drawable = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); |
| 951 | return new BitmapDrawable(getContext().getResources(), drawable); |
| 952 | } |
| 953 | |
Mindy Pereira | d719250 | 2011-09-22 08:04:45 -0700 | [diff] [blame] | 954 | private TextView createTestMoreItem() { |
| 955 | TextView view = new TextView(getContext()); |
| 956 | view.setText("<xliff:g id='count'>%1$s</xliff:g> more..."); |
| 957 | return view; |
| 958 | } |
| 959 | |
Mindy Pereira | 8eb031e | 2011-09-20 15:42:32 -0700 | [diff] [blame] | 960 | private void populateMocks(int size) { |
| 961 | mMockEntries = new RecipientEntry[size]; |
| 962 | for (int i = 0; i < size; i++) { |
| 963 | mMockEntries[i] = RecipientEntry.constructGeneratedEntry("user", |
Scott Kennedy | b1cddbb | 2013-03-06 10:38:07 -0800 | [diff] [blame] | 964 | "user@username.com", true); |
Mindy Pereira | 8eb031e | 2011-09-20 15:42:32 -0700 | [diff] [blame] | 965 | } |
Scott Kennedy | 194d427 | 2013-03-06 22:06:45 -0800 | [diff] [blame] | 966 | mMockRecips = new DrawableRecipientChip[size]; |
Mindy Pereira | 8eb031e | 2011-09-20 15:42:32 -0700 | [diff] [blame] | 967 | for (int i = 0; i < size; i++) { |
Scott Kennedy | f7e202d | 2013-03-06 21:38:10 -0800 | [diff] [blame] | 968 | mMockRecips[i] = new VisibleRecipientChip(null, mMockEntries[i]); |
Mindy Pereira | 8eb031e | 2011-09-20 15:42:32 -0700 | [diff] [blame] | 969 | } |
Mindy Pereira | 7cb970b | 2011-09-19 13:33:10 -0700 | [diff] [blame] | 970 | } |
Scott Kennedy | 20c8aa7 | 2013-03-06 22:23:59 -0800 | [diff] [blame] | 971 | |
| 972 | /** |
| 973 | * <p> |
| 974 | * Ensure the original text is always accurate, regardless of the type of email. The original |
| 975 | * text is used to determine where to display the chip span. If this test fails, it means some |
| 976 | * text that should be turned into one whole chip may behave unexpectedly. |
| 977 | * </p> |
| 978 | * <p> |
| 979 | * For example, a bug was seen where |
| 980 | * |
| 981 | * <pre> |
| 982 | * "Android User" <android@example.com> |
| 983 | * </pre> |
| 984 | * |
| 985 | * was converted to |
| 986 | * |
| 987 | * <pre> |
| 988 | * Android User [android@example.com] |
| 989 | * </pre> |
| 990 | * |
| 991 | * where text inside [] is a chip. |
| 992 | * </p> |
| 993 | */ |
| 994 | public void testCreateReplacementChipOriginalText() { |
| 995 | // Name in quotes + email address |
| 996 | testCreateReplacementChipOriginalText("\"Android User\" <android@example.com>,"); |
| 997 | // Name in quotes + email address without brackets |
| 998 | testCreateReplacementChipOriginalText("\"Android User\" android@example.com,"); |
| 999 | // Name in quotes |
| 1000 | testCreateReplacementChipOriginalText("\"Android User\","); |
| 1001 | // Name without quotes + email address |
| 1002 | testCreateReplacementChipOriginalText("Android User <android@example.com>,"); |
| 1003 | // Name without quotes |
| 1004 | testCreateReplacementChipOriginalText("Android User,"); |
| 1005 | // Email address |
| 1006 | testCreateReplacementChipOriginalText("<android@example.com>,"); |
| 1007 | // Email address without brackets |
| 1008 | testCreateReplacementChipOriginalText("android@example.com,"); |
| 1009 | } |
| 1010 | |
| 1011 | private void testCreateReplacementChipOriginalText(final String email) { |
| 1012 | // No trailing space |
| 1013 | attemptCreateReplacementChipOriginalText(email.trim()); |
| 1014 | // Trailing space |
| 1015 | attemptCreateReplacementChipOriginalText(email.trim() + " "); |
| 1016 | } |
| 1017 | |
| 1018 | private void attemptCreateReplacementChipOriginalText(final String email) { |
| 1019 | final RecipientEditTextView view = new RecipientEditTextView(getContext(), null); |
| 1020 | |
| 1021 | view.setText(email); |
| 1022 | view.mPendingChips.add(email); |
| 1023 | |
| 1024 | view.createReplacementChip(0, email.length(), view.getText(), true); |
| 1025 | // The "original text" should be the email without the comma or space(s) |
| 1026 | assertEquals(email.replaceAll(",\\s*$", ""), |
| 1027 | view.mTemporaryRecipients.get(0).getOriginalText().toString().trim()); |
| 1028 | } |
Scott Kennedy | 983c99b | 2013-03-22 09:42:03 -0700 | [diff] [blame] | 1029 | |
| 1030 | public void testCreateTokenizedEntryForPhone() { |
| 1031 | final String phonePattern = "[^\\d]*888[^\\d]*555[^\\d]*1234[^\\d]*"; |
| 1032 | final String phone1 = "8885551234"; |
| 1033 | final String phone2 = "888-555-1234"; |
| 1034 | final String phone3 = "(888) 555-1234"; |
| 1035 | |
| 1036 | final RecipientEditTextView view = new RecipientEditTextView(getContext(), null); |
| 1037 | final BaseRecipientAdapter adapter = new TestBaseRecipientAdapter(getContext(), 10, |
| 1038 | BaseRecipientAdapter.QUERY_TYPE_PHONE); |
| 1039 | view.setAdapter(adapter); |
| 1040 | |
| 1041 | final RecipientEntry entry1 = view.createTokenizedEntry(phone1); |
| 1042 | final String destination1 = entry1.getDestination(); |
| 1043 | assertTrue(phone1 + " failed with " + destination1, |
| 1044 | Pattern.matches(phonePattern, destination1)); |
| 1045 | |
| 1046 | final RecipientEntry entry2 = view.createTokenizedEntry(phone2); |
| 1047 | final String destination2 = entry2.getDestination(); |
| 1048 | assertTrue(phone2 + " failed with " + destination2, |
| 1049 | Pattern.matches(phonePattern, destination2)); |
| 1050 | |
| 1051 | final RecipientEntry entry3 = view.createTokenizedEntry(phone3); |
| 1052 | final String destination3 = entry3.getDestination(); |
| 1053 | assertTrue(phone3 + " failed with " + destination3, |
| 1054 | Pattern.matches(phonePattern, destination3)); |
| 1055 | } |
Mindy Pereira | 7cb970b | 2011-09-19 13:33:10 -0700 | [diff] [blame] | 1056 | } |