1 /* 2 * Copyright (C) 2008 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 android.text.method.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNotSame; 23 import static org.junit.Assert.assertSame; 24 import static org.junit.Assert.assertTrue; 25 import static org.junit.Assert.fail; 26 import static org.mockito.Mockito.any; 27 import static org.mockito.Mockito.anyInt; 28 import static org.mockito.Mockito.atLeastOnce; 29 import static org.mockito.Mockito.never; 30 import static org.mockito.Mockito.spy; 31 import static org.mockito.Mockito.verify; 32 33 import android.os.SystemClock; 34 import android.support.test.filters.MediumTest; 35 import android.support.test.runner.AndroidJUnit4; 36 import android.test.UiThreadTest; 37 import android.text.Editable; 38 import android.text.InputType; 39 import android.text.Selection; 40 import android.text.Spannable; 41 import android.text.SpannableStringBuilder; 42 import android.text.method.TextKeyListener; 43 import android.text.method.TextKeyListener.Capitalize; 44 import android.view.KeyCharacterMap; 45 import android.view.KeyEvent; 46 import android.widget.TextView.BufferType; 47 48 import com.android.compatibility.common.util.CtsKeyEventUtil; 49 50 import org.junit.Test; 51 import org.junit.runner.RunWith; 52 53 @MediumTest 54 @RunWith(AndroidJUnit4.class) 55 public class TextKeyListenerTest extends KeyListenerTestCase { 56 /** 57 * time out of MultiTapKeyListener. longer than 2000ms in case the system is sluggish. 58 */ 59 private static final long TIME_OUT = 3000; 60 61 @Test 62 public void testConstructor() { 63 new TextKeyListener(Capitalize.NONE, true); 64 65 new TextKeyListener(null, true); 66 } 67 68 @Test 69 public void testShouldCap() { 70 String str = "hello world! man"; 71 72 // Index of the characters(start with 0): 73 // 'h' = 0; 'w' = 6; 'm' = 13; 'a' = 14 74 assertFalse(TextKeyListener.shouldCap(Capitalize.NONE, str, 0)); 75 assertTrue(TextKeyListener.shouldCap(Capitalize.SENTENCES, str, 0)); 76 assertTrue(TextKeyListener.shouldCap(Capitalize.WORDS, str, 0)); 77 assertTrue(TextKeyListener.shouldCap(Capitalize.CHARACTERS, str, 0)); 78 79 assertFalse(TextKeyListener.shouldCap(Capitalize.NONE, str, 6)); 80 assertFalse(TextKeyListener.shouldCap(Capitalize.SENTENCES, str, 6)); 81 assertTrue(TextKeyListener.shouldCap(Capitalize.WORDS, str, 6)); 82 assertTrue(TextKeyListener.shouldCap(Capitalize.CHARACTERS, str, 6)); 83 84 assertFalse(TextKeyListener.shouldCap(Capitalize.NONE, str, 13)); 85 assertTrue(TextKeyListener.shouldCap(Capitalize.SENTENCES, str, 13)); 86 assertTrue(TextKeyListener.shouldCap(Capitalize.WORDS, str, 13)); 87 assertTrue(TextKeyListener.shouldCap(Capitalize.CHARACTERS, str, 13)); 88 89 assertFalse(TextKeyListener.shouldCap(Capitalize.NONE, str, 14)); 90 assertFalse(TextKeyListener.shouldCap(Capitalize.SENTENCES, str, 14)); 91 assertFalse(TextKeyListener.shouldCap(Capitalize.WORDS, str, 14)); 92 assertTrue(TextKeyListener.shouldCap(Capitalize.CHARACTERS, str, 14)); 93 } 94 95 @Test(expected=NullPointerException.class) 96 public void testShouldCapNull() { 97 TextKeyListener.shouldCap(Capitalize.WORDS, null, 16); 98 } 99 100 @Test 101 public void testOnSpanAdded() throws Throwable { 102 final TextKeyListener mockTextKeyListener = spy( 103 new TextKeyListener(Capitalize.CHARACTERS, true)); 104 final Spannable text = new SpannableStringBuilder("123456"); 105 106 verify(mockTextKeyListener, never()).onSpanAdded(any(), any(), anyInt(), anyInt()); 107 mActivityRule.runOnUiThread(() -> { 108 mTextView.setKeyListener(mockTextKeyListener); 109 mTextView.setText(text, BufferType.EDITABLE); 110 }); 111 mInstrumentation.waitForIdleSync(); 112 verify(mockTextKeyListener, atLeastOnce()).onSpanAdded(any(), any(), anyInt(), anyInt()); 113 114 mockTextKeyListener.release(); 115 } 116 117 @Test 118 public void testGetInstance1() { 119 TextKeyListener listener1 = TextKeyListener.getInstance(true, Capitalize.WORDS); 120 TextKeyListener listener2 = TextKeyListener.getInstance(true, Capitalize.WORDS); 121 TextKeyListener listener3 = TextKeyListener.getInstance(false, Capitalize.WORDS); 122 TextKeyListener listener4 = TextKeyListener.getInstance(true, Capitalize.CHARACTERS); 123 124 assertNotNull(listener1); 125 assertNotNull(listener2); 126 assertSame(listener1, listener2); 127 128 assertNotSame(listener1, listener3); 129 assertNotSame(listener1, listener4); 130 assertNotSame(listener4, listener3); 131 132 listener1.release(); 133 listener2.release(); 134 listener3.release(); 135 listener4.release(); 136 } 137 138 @Test 139 public void testGetInstance2() { 140 TextKeyListener listener1 = TextKeyListener.getInstance(); 141 TextKeyListener listener2 = TextKeyListener.getInstance(); 142 143 assertNotNull(listener1); 144 assertNotNull(listener2); 145 assertSame(listener1, listener2); 146 147 listener1.release(); 148 listener2.release(); 149 } 150 151 @Test 152 public void testOnSpanChanged() { 153 TextKeyListener textKeyListener = TextKeyListener.getInstance(); 154 final Spannable text = new SpannableStringBuilder("123456"); 155 textKeyListener.onSpanChanged(text, Selection.SELECTION_END, 0, 0, 0, 0); 156 157 textKeyListener.release(); 158 } 159 160 @Test(expected=NullPointerException.class) 161 public void testOnSpanChangedNull() { 162 TextKeyListener textKeyListener = TextKeyListener.getInstance(); 163 textKeyListener.onSpanChanged(null, Selection.SELECTION_END, 0, 0, 0, 0); 164 } 165 166 @UiThreadTest 167 @Test 168 public void testClear() { 169 CharSequence text = "123456"; 170 mTextView.setText(text, BufferType.EDITABLE); 171 172 Editable content = mTextView.getText(); 173 assertEquals(text, content.toString()); 174 175 TextKeyListener.clear(content); 176 assertEquals("", content.toString()); 177 } 178 179 @Test 180 public void testOnSpanRemoved() { 181 TextKeyListener textKeyListener = new TextKeyListener(Capitalize.CHARACTERS, true); 182 final Spannable text = new SpannableStringBuilder("123456"); 183 textKeyListener.onSpanRemoved(text, new Object(), 0, 0); 184 185 textKeyListener.release(); 186 } 187 188 /** 189 * Wait for TIME_OUT, or listener will accept key event as multi tap rather than a new key. 190 */ 191 private void waitForListenerTimeout() { 192 try { 193 Thread.sleep(TIME_OUT); 194 } catch (InterruptedException e) { 195 fail("thrown unexpected InterruptedException when sleep."); 196 } 197 } 198 199 /** 200 * Check point: 201 * 1. press KEYCODE_4 once. if it's ALPHA key board, text will be "4", if it's 202 * NUMERIC key board, text will be "g", else text will be "". 203 */ 204 @Test 205 public void testPressKey() throws Throwable { 206 final TextKeyListener textKeyListener 207 = TextKeyListener.getInstance(false, Capitalize.NONE); 208 209 mActivityRule.runOnUiThread(() -> { 210 mTextView.setText("", BufferType.EDITABLE); 211 Selection.setSelection(mTextView.getText(), 0, 0); 212 mTextView.setKeyListener(textKeyListener); 213 mTextView.requestFocus(); 214 }); 215 mInstrumentation.waitForIdleSync(); 216 assertEquals("", mTextView.getText().toString()); 217 218 CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_4); 219 waitForListenerTimeout(); 220 String text = mTextView.getText().toString(); 221 int keyType = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD).getKeyboardType(); 222 if (KeyCharacterMap.ALPHA == keyType 223 || KeyCharacterMap.FULL == keyType) { 224 assertEquals("4", text); 225 } else if (KeyCharacterMap.NUMERIC == keyType) { 226 assertEquals("g", text); 227 } else { 228 assertEquals("", text); 229 } 230 231 textKeyListener.release(); 232 } 233 234 @Test 235 public void testOnKeyOther() throws Throwable { 236 final String text = "abcd"; 237 final TextKeyListener textKeyListener 238 = TextKeyListener.getInstance(false, Capitalize.NONE); 239 240 mActivityRule.runOnUiThread(() -> { 241 mTextView.setText("", BufferType.EDITABLE); 242 Selection.setSelection(mTextView.getText(), 0, 0); 243 mTextView.setKeyListener(textKeyListener); 244 }); 245 mInstrumentation.waitForIdleSync(); 246 assertEquals("", mTextView.getText().toString()); 247 248 // test ACTION_MULTIPLE KEYCODE_UNKNOWN key event. 249 KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(), text, 250 1, KeyEvent.FLAG_WOKE_HERE); 251 CtsKeyEventUtil.sendKey(mInstrumentation, mTextView, event); 252 mInstrumentation.waitForIdleSync(); 253 // the text of TextView is never changed, onKeyOther never works. 254 // assertEquals(text, mTextView.getText().toString()); issue 1731439 255 256 textKeyListener.release(); 257 } 258 259 @Test 260 public void testGetInputType() { 261 TextKeyListener listener = TextKeyListener.getInstance(false, Capitalize.NONE); 262 int expected = InputType.TYPE_CLASS_TEXT; 263 assertEquals(expected, listener.getInputType()); 264 265 listener = TextKeyListener.getInstance(false, Capitalize.CHARACTERS); 266 expected = InputType.TYPE_CLASS_TEXT 267 | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS; 268 assertEquals(expected, listener.getInputType()); 269 270 listener.release(); 271 } 272 } 273