/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.ex.chips; import android.content.Context; import android.test.AndroidTestCase; import android.text.Editable; import android.text.SpannableStringBuilder; import android.text.style.ImageSpan; import android.text.util.Rfc822Tokenizer; import android.widget.TextView; import com.android.ex.chips.RecipientEditTextView; import com.android.ex.chips.RecipientEntry; public class ChipsTest extends AndroidTestCase { private RecipientChip[] mMockRecips; private RecipientEntry[] mMockEntries; private Rfc822Tokenizer mTokenizer; private Editable mEditable; class MockRecipientEditTextView extends RecipientEditTextView { public MockRecipientEditTextView(Context context) { super(context, null); mTokenizer = new Rfc822Tokenizer(); setTokenizer(mTokenizer); } @Override public RecipientChip[] getSortedRecipients() { return mMockRecips; } @Override public Editable getText() { return mEditable; } @Override public Editable getSpannable() { return mEditable; } @Override public int getLineHeight() { return 48; } } private MockRecipientEditTextView createViewForTesting() { mEditable = new SpannableStringBuilder(); MockRecipientEditTextView view = new MockRecipientEditTextView(getContext()); return view; } public void testCreateDisplayText() { RecipientEditTextView view = createViewForTesting(); RecipientEntry entry = RecipientEntry.constructGeneratedEntry("User Name, Jr", "user@username.com"); String test = view.createDisplayText(entry); assertEquals("Expected a properly formatted RFC email address", "\"User Name, Jr\" , ", test); RecipientEntry alreadyFormatted = RecipientEntry.constructFakeEntry("user@username.com, "); test = view.createDisplayText(alreadyFormatted); assertEquals("Expected a properly formatted RFC email address", ", ", test); RecipientEntry alreadyFormattedNoSpace = RecipientEntry .constructFakeEntry("user@username.com,"); test = view.createDisplayText(alreadyFormattedNoSpace); assertEquals("Expected a properly formatted RFC email address", ", ", test); RecipientEntry alreadyNamed = RecipientEntry.constructGeneratedEntry("User Name", "\"User Name, Jr\" "); test = view.createDisplayText(alreadyNamed); assertEquals( "Expected address that used the name not the excess address name", "User Name , ", test); } public void testSanitizeBetween() { populateMocks(2); MockRecipientEditTextView view = createViewForTesting(); String first = (String) mTokenizer.terminateToken("FIRST"); String second = (String) mTokenizer.terminateToken("SECOND"); String extra = "EXTRA"; mEditable = new SpannableStringBuilder(); mEditable.append(first + extra + second); int firstStart = mEditable.toString().indexOf(first); int firstEnd = firstStart + first.trim().length(); int secondStart = mEditable.toString().indexOf(second); int secondEnd = secondStart + second.trim().length(); mEditable.setSpan(mMockRecips[mMockRecips.length - 2], firstStart, firstEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 1], secondStart, secondEnd, 0); view.sanitizeBetween(); String editableString = mEditable.toString(); assertEquals(editableString.indexOf(extra), -1); assertEquals(editableString.indexOf(first), firstStart); assertEquals(editableString.indexOf(second), secondStart - extra.length()); assertEquals(editableString, (first + second)); mEditable = new SpannableStringBuilder(); populateMocks(1); mEditable.append(extra); mEditable.append(first); firstStart = mEditable.toString().indexOf(first); firstEnd = firstStart + first.length(); mEditable.setSpan(mMockRecips[mMockRecips.length - 1], firstStart, firstEnd, 0); view.sanitizeBetween(); assertEquals(mEditable.toString(), first); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), firstStart - extra.length()); } public void testMoreChip() { populateMocks(3); MockRecipientEditTextView view = createViewForTesting(); view.setMoreItem(createTestMoreItem()); String first = (String) mTokenizer.terminateToken("FIRST"); String second = (String) mTokenizer.terminateToken("SECOND"); String third = (String) mTokenizer.terminateToken("THIRD"); mEditable = new SpannableStringBuilder(); mEditable.append(first+second+third); int firstStart = mEditable.toString().indexOf(first); int firstEnd = firstStart + first.trim().length(); int secondStart = mEditable.toString().indexOf(second); int secondEnd = secondStart + second.trim().length(); int thirdStart = mEditable.toString().indexOf(third); int thirdEnd = thirdStart + third.trim().length(); mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); view.createMoreChip(); assertEquals(mEditable.toString(), first+second+third); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); // Find the more chip. ImageSpan moreChip = view.getMoreChip(); assertEquals(mEditable.getSpanStart(moreChip), thirdStart); assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd); view.removeMoreChip(); assertEquals(mEditable.toString(), first+second+third); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart); assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd); moreChip = view.getMoreChip(); assertEquals(mEditable.getSpanStart(moreChip), -1); // Rinse and repeat, just in case! view.createMoreChip(); assertEquals(mEditable.toString(), first+second+third); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); // Find the more chip. moreChip = view.getMoreChip(); assertEquals(mEditable.getSpanStart(moreChip), thirdStart); assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd); view.removeMoreChip(); assertEquals(mEditable.toString(), first+second+third); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart); assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd); moreChip = view.getMoreChip(); assertEquals(mEditable.getSpanStart(moreChip), -1); } public void testMoreChipLotsOfUsers() { populateMocks(10); MockRecipientEditTextView view = createViewForTesting(); view.setMoreItem(createTestMoreItem()); String first = (String) mTokenizer.terminateToken("FIRST"); String second = (String) mTokenizer.terminateToken("SECOND"); String third = (String) mTokenizer.terminateToken("THIRD"); String fourth = (String) mTokenizer.terminateToken("FOURTH"); String fifth = (String) mTokenizer.terminateToken("FIFTH"); String sixth = (String) mTokenizer.terminateToken("SIXTH"); String seventh = (String) mTokenizer.terminateToken("SEVENTH"); String eigth = (String) mTokenizer.terminateToken("EIGHTH"); String ninth = (String) mTokenizer.terminateToken("NINTH"); String tenth = (String) mTokenizer.terminateToken("TENTH"); mEditable = new SpannableStringBuilder(); mEditable.append(first+second+third+fourth+fifth+sixth+seventh+eigth+ninth+tenth); int firstStart = mEditable.toString().indexOf(first); int firstEnd = firstStart + first.trim().length(); int secondStart = mEditable.toString().indexOf(second); int secondEnd = secondStart + second.trim().length(); int thirdStart = mEditable.toString().indexOf(third); int thirdEnd = thirdStart + third.trim().length(); int fourthStart = mEditable.toString().indexOf(fourth); int fourthEnd = fourthStart + fourth.trim().length(); int fifthStart = mEditable.toString().indexOf(fifth); int fifthEnd = fifthStart + fifth.trim().length(); int sixthStart = mEditable.toString().indexOf(sixth); int sixthEnd = sixthStart + sixth.trim().length(); int seventhStart = mEditable.toString().indexOf(seventh); int seventhEnd = seventhStart + seventh.trim().length(); int eighthStart = mEditable.toString().indexOf(eigth); int eighthEnd = eighthStart + eigth.trim().length(); int ninthStart = mEditable.toString().indexOf(ninth); int ninthEnd = ninthStart + ninth.trim().length(); int tenthStart = mEditable.toString().indexOf(tenth); int tenthEnd = tenthStart + tenth.trim().length(); mEditable.setSpan(mMockRecips[mMockRecips.length - 10], firstStart, firstEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 9], secondStart, secondEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 8], thirdStart, thirdEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 7], fourthStart, fourthEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 6], fifthStart, fifthEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 5], sixthStart, sixthEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 4], seventhStart, seventhEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 3], eighthStart, eighthEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 2], ninthStart, ninthEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 1], tenthStart, tenthEnd, 0); view.createMoreChip(); assertEquals(mEditable.toString(), first + second + third + fourth + fifth + sixth + seventh + eigth + ninth + tenth); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 10]), firstStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 9]), secondStart); // Find the more chip. ImageSpan moreChip = view.getMoreChip(); assertEquals(mEditable.getSpanStart(moreChip), thirdStart); assertEquals(mEditable.getSpanEnd(moreChip), tenthEnd); view.removeMoreChip(); assertEquals(mEditable.toString(), first + second + third + fourth + fifth + sixth + seventh + eigth + ninth + tenth); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 10]), firstStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 9]), secondStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 8]), thirdStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 7]), fourthStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 6]), fifthStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 5]), sixthStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), seventhStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), eighthStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), ninthStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), tenthStart); moreChip = view.getMoreChip(); assertEquals(mEditable.getSpanStart(moreChip), -1); } public void testMoreChipSpecialChars() { populateMocks(3); MockRecipientEditTextView view = createViewForTesting(); view.setMoreItem(createTestMoreItem()); String first = (String) mTokenizer.terminateToken("FI,RST"); String second = (String) mTokenizer.terminateToken("SE,COND"); String third = (String) mTokenizer.terminateToken("THI,RD"); mEditable = new SpannableStringBuilder(); mEditable.append(first+second+third); int firstStart = mEditable.toString().indexOf(first); int firstEnd = firstStart + first.trim().length(); int secondStart = mEditable.toString().indexOf(second); int secondEnd = secondStart + second.trim().length(); int thirdStart = mEditable.toString().indexOf(third); int thirdEnd = thirdStart + third.trim().length(); mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0); mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0); view.createMoreChip(); assertEquals(mEditable.toString(), first+second+third); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); // Find the more chip. ImageSpan moreChip = view.getMoreChip(); assertEquals(mEditable.getSpanStart(moreChip), thirdStart); assertEquals(mEditable.getSpanEnd(moreChip), thirdEnd); view.removeMoreChip(); assertEquals(mEditable.toString(), first+second+third); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart); assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 3]), firstEnd); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), secondStart); assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdStart); assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdEnd); moreChip = view.getMoreChip(); assertEquals(mEditable.getSpanStart(moreChip), -1); } private TextView createTestMoreItem() { TextView view = new TextView(getContext()); view.setText("%1$s more..."); return view; } private void populateMocks(int size) { mMockEntries = new RecipientEntry[size]; for (int i = 0; i < size; i++) { mMockEntries[i] = RecipientEntry.constructGeneratedEntry("user", "user@username.com"); } mMockRecips = new RecipientChip[size]; for (int i = 0; i < size; i++) { mMockRecips[i] = new RecipientChip(null, mMockEntries[i], i); } } }