FileDocCategorySizeDatePackage
TextViewWordLimitsTest.javaAPI DocAndroid 5.1 API10929Thu Mar 12 22:22:12 GMT 2015android.widget

TextViewWordLimitsTest

public class TextViewWordLimitsTest extends android.test.AndroidTestCase
TextViewPatchTest tests {@link TextView}'s definition of word. Finds and verifies word limits to be in strings containing different kinds of characters.

Fields Summary
TextView
mTv
Method
mGetWordLimits
Method
mSelectCurrentWord
Field
mContextMenuTriggeredByKey
Field
mSelectionControllerEnabled
Constructors Summary
Methods Summary
protected voidsetUp()
Sets up common fields used in all test cases.

throws
NoSuchFieldException
throws
SecurityException



                      
    
           
        mTv = new TextView(getContext());
        mTv.setInputType(InputType.TYPE_CLASS_TEXT);

        mGetWordLimits = mTv.getClass().getDeclaredMethod("getWordLimitsAt",
                new Class[] {int.class});
        mGetWordLimits.setAccessible(true);

        mSelectCurrentWord = mTv.getClass().getDeclaredMethod("selectCurrentWord", new Class[] {});
        mSelectCurrentWord.setAccessible(true);

        mContextMenuTriggeredByKey = mTv.getClass().getDeclaredField("mContextMenuTriggeredByKey");
        mContextMenuTriggeredByKey.setAccessible(true);
        mSelectionControllerEnabled = mTv.getClass().getDeclaredField("mSelectionControllerEnabled");
        mSelectionControllerEnabled.setAccessible(true);
    
public voidtestFinalSeparator()
Unicode classes included if combined with a letter.

        final String PUNCTUATION = "abc, def.";

        // Starting from the comma
        verifyWordLimits(PUNCTUATION, 3, 0, 3);
        verifyWordLimits(PUNCTUATION, 4, 0, 4);

        // Starting from the final period
        verifyWordLimits(PUNCTUATION, 8, 5, 8);
        verifyWordLimits(PUNCTUATION, 9, 5, 9);
    
public voidtestIncludedClasses()
Unicode classes included.

        final String LOWER          = "njlj";
        final String UPPER          = "NJLJ";
        final String TITLECASE      = "\u01C8\u01CB\u01F2"; // Lj Nj Dz
        final String OTHER          = "\u3042\u3044\u3046"; // Hiragana AIU
        final String MODIFIER       = "\u02C6\u02CA\u02CB"; // Circumflex Acute Grave

        // Each string contains a single valid word
        verifyWordLimits(LOWER, 1, 0, 4);
        verifyWordLimits(UPPER, 1, 0, 4);
        verifyWordLimits(TITLECASE, 1, 0, 3);
        verifyWordLimits(OTHER, 1, 0, 3);
        verifyWordLimits(MODIFIER, 1, 0, 3);
    
public voidtestLengths()
Corner cases for string length.

        final String ONE_TWO = "one two";
        final String EMPTY   = "";
        final String TOOLONG = "ThisWordIsTooLongToBeDefinedAsAWordInTheSenseUsedInTextView";

        // Select first word
        verifyWordLimits(ONE_TWO, 0, 0, 3);
        verifyWordLimits(ONE_TWO, 3, 0, 3);

        // Select last word
        verifyWordLimits(ONE_TWO, 4, 4, 7);
        verifyWordLimits(ONE_TWO, 7, 4, 7);

        // Empty string
        verifyWordLimits(EMPTY, 0, -1, -1);

        // Too long word
        verifyWordLimits(TOOLONG, 0, -1, -1);
    
public voidtestNotIncluded()
Unicode classes other than listed in testIncludedClasses and testPartlyIncluded act as word separators.

        // Selection of character classes excluded
        final String MARK_NONSPACING        = "a\u030A";       // a Combining ring above
        final String PUNCTUATION_OPEN_CLOSE = "(c)";           // Parenthesis
        final String PUNCTUATION_DASH       = "non-fiction";   // Hyphen
        final String PUNCTUATION_OTHER      = "b&b";           // Ampersand
        final String SYMBOL_OTHER           = "Android\u00AE"; // Registered
        final String SEPARATOR_SPACE        = "one two";       // Space

        // "a"
        verifyWordLimits(MARK_NONSPACING, 1, 0, 1);

        // "c"
        verifyWordLimits(PUNCTUATION_OPEN_CLOSE, 1, 1, 2);

        // "non-"
        verifyWordLimits(PUNCTUATION_DASH, 3, 0, 3);
        verifyWordLimits(PUNCTUATION_DASH, 4, 4, 11);

        // "b"
        verifyWordLimits(PUNCTUATION_OTHER, 0, 0, 1);
        verifyWordLimits(PUNCTUATION_OTHER, 1, 0, 1);
        verifyWordLimits(PUNCTUATION_OTHER, 2, 0, 3); // & is considered a punctuation sign.
        verifyWordLimits(PUNCTUATION_OTHER, 3, 2, 3);

        // "Android"
        verifyWordLimits(SYMBOL_OTHER, 7, 0, 7);
        verifyWordLimits(SYMBOL_OTHER, 8, -1, -1);

        // "one"
        verifyWordLimits(SEPARATOR_SPACE, 1, 0, 3);
    
public voidtestPartlyIncluded()
Unicode classes included if combined with a letter.

        final String NUMBER           = "123";
        final String NUMBER_LOWER     = "1st";
        final String APOSTROPHE       = "''";
        final String APOSTROPHE_LOWER = "'Android's'";

        // Pure decimal number is ignored
        verifyWordLimits(NUMBER, 1, -1, -1);

        // Number with letter is valid
        verifyWordLimits(NUMBER_LOWER, 1, 0, 3);

        // Stand apostrophes are ignore
        verifyWordLimits(APOSTROPHE, 1, -1, -1);

        // Apostrophes are accepted if they are a part of a word
        verifyWordLimits(APOSTROPHE_LOWER, 1, 0, 11);
    
public voidtestSelectCurrentWord()
Selection is used if present and valid word.

        SpannableString textLower       = new SpannableString("first second");
        SpannableString textOther       = new SpannableString("\u3042\3044\3046"); // Hiragana AIU
        SpannableString textDash        = new SpannableString("non-fiction");      // Hyphen
        SpannableString textPunctOther  = new SpannableString("b&b");              // Ampersand
        SpannableString textSymbolOther = new SpannableString("Android\u00AE");    // Registered

        // Valid selection - Letter, Lower
        verifySelectCurrentWord(textLower, 2, 5, 0, 5);

        // Adding the space spreads to the second word
        verifySelectCurrentWord(textLower, 2, 6, 0, 12);

        // Valid selection -- Letter, Other
        verifySelectCurrentWord(textOther, 1, 2, 0, 5);

        // Zero-width selection is interpreted as a cursor and the selection is ignored
        verifySelectCurrentWord(textLower, 2, 2, 0, 5);

        // Hyphen is part of selection
        verifySelectCurrentWord(textDash, 2, 5, 0, 11);

        // Ampersand part of selection or not
        verifySelectCurrentWord(textPunctOther, 1, 2, 0, 3);
        verifySelectCurrentWord(textPunctOther, 1, 3, 0, 3);

        // (R) part of the selection
        verifySelectCurrentWord(textSymbolOther, 2, 7, 0, 7);
        verifySelectCurrentWord(textSymbolOther, 2, 8, 0, 8);
    
public voidtestSurrogate()
Surrogate characters are treated as their code points.

        final String SURROGATE_LETTER   = "\uD800\uDC00\uD800\uDC01\uD800\uDC02"; // Linear B AEI
        final String SURROGATE_SYMBOL   = "\uD83D\uDE01\uD83D\uDE02\uD83D\uDE03"; // Three smileys

        // Letter Other is included even when coded as surrogate pairs
        verifyWordLimits(SURROGATE_LETTER, 0, 0, 6);
        verifyWordLimits(SURROGATE_LETTER, 1, 0, 6);
        verifyWordLimits(SURROGATE_LETTER, 2, 0, 6);
        verifyWordLimits(SURROGATE_LETTER, 3, 0, 6);
        verifyWordLimits(SURROGATE_LETTER, 4, 0, 6);
        verifyWordLimits(SURROGATE_LETTER, 5, 0, 6);
        verifyWordLimits(SURROGATE_LETTER, 6, 0, 6);

        // Not included classes are ignored even when coded as surrogate pairs
        verifyWordLimits(SURROGATE_SYMBOL, 0, -1, -1);
        verifyWordLimits(SURROGATE_SYMBOL, 1, -1, -1);
        verifyWordLimits(SURROGATE_SYMBOL, 2, -1, -1);
        verifyWordLimits(SURROGATE_SYMBOL, 3, -1, -1);
        verifyWordLimits(SURROGATE_SYMBOL, 4, -1, -1);
        verifyWordLimits(SURROGATE_SYMBOL, 5, -1, -1);
        verifyWordLimits(SURROGATE_SYMBOL, 6, -1, -1);
    
private voidverifySelectCurrentWord(android.text.Spannable text, int selectionStart, int selectionEnd, int correctStart, int correctEnd)

        mTv.setText(text, TextView.BufferType.SPANNABLE);

        Selection.setSelection((Spannable)mTv.getText(), selectionStart, selectionEnd);
        mContextMenuTriggeredByKey.setBoolean(mTv, true);
        mSelectionControllerEnabled.setBoolean(mTv, true);
        mSelectCurrentWord.invoke(mTv);

        assertEquals(correctStart, mTv.getSelectionStart());
        assertEquals(correctEnd, mTv.getSelectionEnd());
    
private voidverifyWordLimits(java.lang.String text, int pos, int correctStart, int correctEnd)
Calculate and verify word limits. Depends on the TextView implementation. Uses a private method and internal data representation.

param
text Text to select a word from
param
pos Position to expand word around
param
correctStart Correct start position for the word
param
correctEnd Correct end position for the word
throws
InvocationTargetException
throws
IllegalAccessException
throws
IllegalArgumentException
throws
InvocationTargetException
throws
IllegalAccessException

        mTv.setText(text, TextView.BufferType.SPANNABLE);

        long limits = (Long)mGetWordLimits.invoke(mTv, new Object[] {new Integer(pos)});
        int actualStart = (int)(limits >>> 32);
        int actualEnd = (int)(limits & 0x00000000FFFFFFFFL);
        assertEquals(correctStart, actualStart);
        assertEquals(correctEnd, actualEnd);