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.assertNotNull; 21 import static org.junit.Assert.assertNotSame; 22 import static org.junit.Assert.assertSame; 23 import static org.junit.Assert.fail; 24 import static org.mockito.Matchers.any; 25 import static org.mockito.Matchers.anyInt; 26 import static org.mockito.Mockito.atLeastOnce; 27 import static org.mockito.Mockito.never; 28 import static org.mockito.Mockito.spy; 29 import static org.mockito.Mockito.verify; 30 31 import android.support.test.filters.LargeTest; 32 import android.support.test.runner.AndroidJUnit4; 33 import android.text.InputType; 34 import android.text.Selection; 35 import android.text.Spannable; 36 import android.text.SpannableStringBuilder; 37 import android.text.method.MultiTapKeyListener; 38 import android.text.method.TextKeyListener.Capitalize; 39 import android.view.KeyEvent; 40 import android.widget.TextView.BufferType; 41 42 import org.junit.After; 43 import org.junit.Before; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 47 import java.io.IOException; 48 49 @LargeTest 50 @RunWith(AndroidJUnit4.class) 51 public class MultiTapKeyListenerTest extends KeyListenerTestCase { 52 /** 53 * time out of MultiTapKeyListener. longer than 2000ms in case the system is sluggish. 54 */ 55 private static final long TIME_OUT = 3000; 56 57 @Before 58 public void setup() throws IOException { 59 super.setup(); 60 enableAutoCapSettings(); 61 } 62 63 @After 64 public void tearDown() throws IOException { 65 resetAutoCapSettings(); 66 } 67 68 @Test 69 public void testConstructor() { 70 new MultiTapKeyListener(Capitalize.NONE, true); 71 72 new MultiTapKeyListener(Capitalize.WORDS, false); 73 74 new MultiTapKeyListener(null, false); 75 } 76 77 @Test 78 public void testOnSpanAdded() throws Throwable { 79 final MultiTapKeyListener mockMultiTapKeyListener 80 = spy(new MultiTapKeyListener(Capitalize.CHARACTERS, true)); 81 final Spannable text = new SpannableStringBuilder("123456"); 82 83 verify(mockMultiTapKeyListener, never()).onSpanAdded(any(), any(), anyInt(), anyInt()); 84 mActivityRule.runOnUiThread(() -> { 85 mTextView.setKeyListener(mockMultiTapKeyListener); 86 mTextView.setText(text, BufferType.EDITABLE); 87 }); 88 mInstrumentation.waitForIdleSync(); 89 90 verify(mockMultiTapKeyListener, atLeastOnce()).onSpanAdded( 91 any(), any(), anyInt(), anyInt()); 92 } 93 94 @Test 95 public void testOnSpanChanged() { 96 final MultiTapKeyListener multiTapKeyListener 97 = MultiTapKeyListener.getInstance(true, Capitalize.CHARACTERS); 98 final Spannable text = new SpannableStringBuilder("123456"); 99 multiTapKeyListener.onSpanChanged(text, Selection.SELECTION_END, 0, 0, 0, 0); 100 101 try { 102 multiTapKeyListener.onSpanChanged(null, Selection.SELECTION_END, 0, 0, 0, 0); 103 fail("should throw NullPointerException."); 104 } catch (NullPointerException e) { 105 // expected. 106 } 107 } 108 109 @Test 110 public void testOnKeyDown_capitalizeNone() throws Throwable { 111 MultiTapKeyListener keyListener = MultiTapKeyListener.getInstance(false, Capitalize.NONE); 112 113 prepareEmptyTextView(); 114 115 callOnKeyDown(keyListener, KeyEvent.KEYCODE_4, 2); 116 assertEquals("h", mTextView.getText().toString()); 117 118 callOnKeyDown(keyListener, KeyEvent.KEYCODE_3, 2); 119 assertEquals("he", mTextView.getText().toString()); 120 121 callOnKeyDown(keyListener, KeyEvent.KEYCODE_5, 3); 122 assertEquals("hel", mTextView.getText().toString()); 123 124 callOnKeyDown(keyListener, KeyEvent.KEYCODE_5, 3); 125 assertEquals("hell", mTextView.getText().toString()); 126 127 callOnKeyDown(keyListener, KeyEvent.KEYCODE_6, 3); 128 assertEquals("hello", mTextView.getText().toString()); 129 } 130 131 @Test 132 public void testOnKeyDown_capitalizeCharacters() throws Throwable { 133 MultiTapKeyListener keyListener = MultiTapKeyListener.getInstance(false, 134 Capitalize.CHARACTERS); 135 136 prepareEmptyTextView(); 137 138 callOnKeyDown(keyListener, KeyEvent.KEYCODE_4, 2); 139 assertEquals("H", mTextView.getText().toString()); 140 141 callOnKeyDown(keyListener, KeyEvent.KEYCODE_3, 2); 142 assertEquals("HE", mTextView.getText().toString()); 143 144 callOnKeyDown(keyListener, KeyEvent.KEYCODE_5, 3); 145 assertEquals("HEL", mTextView.getText().toString()); 146 147 callOnKeyDown(keyListener, KeyEvent.KEYCODE_5, 3); 148 assertEquals("HELL", mTextView.getText().toString()); 149 150 callOnKeyDown(keyListener, KeyEvent.KEYCODE_6, 3); 151 assertEquals("HELLO", mTextView.getText().toString()); 152 } 153 154 @Test 155 public void testOnKeyDown_capitalizeSentences() throws Throwable { 156 MultiTapKeyListener keyListener = MultiTapKeyListener.getInstance(false, 157 Capitalize.SENTENCES); 158 159 prepareEmptyTextView(); 160 161 callOnKeyDown(keyListener, KeyEvent.KEYCODE_4, 2); 162 assertEquals("H", mTextView.getText().toString()); 163 164 callOnKeyDown(keyListener, KeyEvent.KEYCODE_4, 3); 165 assertEquals("Hi", mTextView.getText().toString()); 166 167 callOnKeyDown(keyListener, KeyEvent.KEYCODE_1, 1); 168 assertEquals("Hi.", mTextView.getText().toString()); 169 170 addSpace(); 171 172 callOnKeyDown(keyListener, KeyEvent.KEYCODE_2, 2); 173 assertEquals("Hi. B", mTextView.getText().toString()); 174 175 callOnKeyDown(keyListener, KeyEvent.KEYCODE_9, 3); 176 assertEquals("Hi. By", mTextView.getText().toString()); 177 178 callOnKeyDown(keyListener, KeyEvent.KEYCODE_3, 2); 179 assertEquals("Hi. Bye", mTextView.getText().toString()); 180 } 181 182 @Test 183 public void testOnKeyDown_capitalizeWords() throws Throwable { 184 MultiTapKeyListener keyListener = MultiTapKeyListener.getInstance(false, 185 Capitalize.WORDS); 186 187 prepareEmptyTextView(); 188 189 callOnKeyDown(keyListener, KeyEvent.KEYCODE_4, 2); 190 assertEquals("H", mTextView.getText().toString()); 191 192 callOnKeyDown(keyListener, KeyEvent.KEYCODE_4, 3); 193 assertEquals("Hi", mTextView.getText().toString()); 194 195 addSpace(); 196 197 callOnKeyDown(keyListener, KeyEvent.KEYCODE_2, 2); 198 assertEquals("Hi B", mTextView.getText().toString()); 199 200 callOnKeyDown(keyListener, KeyEvent.KEYCODE_9, 3); 201 assertEquals("Hi By", mTextView.getText().toString()); 202 203 callOnKeyDown(keyListener, KeyEvent.KEYCODE_3, 2); 204 assertEquals("Hi Bye", mTextView.getText().toString()); 205 } 206 207 private void prepareEmptyTextView() throws Throwable { 208 mActivityRule.runOnUiThread(() -> { 209 mTextView.setText("", BufferType.EDITABLE); 210 Selection.setSelection(mTextView.getEditableText(), 0, 0); 211 }); 212 mInstrumentation.waitForIdleSync(); 213 assertEquals("", mTextView.getText().toString()); 214 } 215 216 private void callOnKeyDown(final MultiTapKeyListener keyListener, final int keyCode, 217 final int numTimes) throws Throwable { 218 mActivityRule.runOnUiThread(() -> { 219 for (int i = 0; i < numTimes; i++) { 220 keyListener.onKeyDown(mTextView, mTextView.getEditableText(), keyCode, 221 new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); 222 } 223 }); 224 mInstrumentation.waitForIdleSync(); 225 226 // Wait a bit in order to distinguish this character and the next one. 227 try { 228 Thread.sleep(TIME_OUT); 229 } catch (InterruptedException e) { 230 fail("thrown unexpected InterruptedException when sleep."); 231 } 232 } 233 234 private void addSpace() throws Throwable { 235 mActivityRule.runOnUiThread(() -> mTextView.append(" ")); 236 mInstrumentation.waitForIdleSync(); 237 } 238 239 @Test 240 public void testGetInstance() { 241 MultiTapKeyListener listener1 = MultiTapKeyListener.getInstance(false, Capitalize.NONE); 242 MultiTapKeyListener listener2 = MultiTapKeyListener.getInstance(false, Capitalize.NONE); 243 MultiTapKeyListener listener3 = MultiTapKeyListener.getInstance(false, Capitalize.WORDS); 244 MultiTapKeyListener listener4 = MultiTapKeyListener.getInstance(true, Capitalize.NONE); 245 246 assertNotNull(listener1); 247 assertNotNull(listener2); 248 assertSame(listener1, listener2); 249 250 assertNotSame(listener1, listener3); 251 assertNotSame(listener4, listener3); 252 assertNotSame(listener4, listener1); 253 } 254 255 @Test 256 public void testOnSpanRemoved() { 257 MultiTapKeyListener multiTapKeyListener = 258 new MultiTapKeyListener(Capitalize.CHARACTERS, true); 259 final Spannable text = new SpannableStringBuilder("123456"); 260 multiTapKeyListener.onSpanRemoved(text, new Object(), 0, 0); 261 } 262 263 @Test 264 public void testGetInputType() { 265 MultiTapKeyListener listener = MultiTapKeyListener.getInstance(false, Capitalize.NONE); 266 int expected = InputType.TYPE_CLASS_TEXT; 267 assertEquals(expected, listener.getInputType()); 268 269 listener = MultiTapKeyListener.getInstance(true, Capitalize.CHARACTERS); 270 expected = InputType.TYPE_CLASS_TEXT 271 | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS 272 | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT; 273 assertEquals(expected, listener.getInputType()); 274 } 275 } 276