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.assertNull; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assert.fail; 24 25 import android.support.test.filters.MediumTest; 26 import android.support.test.runner.AndroidJUnit4; 27 import android.text.Selection; 28 import android.text.Spannable; 29 import android.text.SpannableString; 30 import android.text.Spanned; 31 import android.text.method.NumberKeyListener; 32 import android.view.KeyEvent; 33 import android.widget.TextView.BufferType; 34 35 import com.android.compatibility.common.util.CtsKeyEventUtil; 36 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 40 @MediumTest 41 @RunWith(AndroidJUnit4.class) 42 public class NumberKeyListenerTest extends KeyListenerTestCase { 43 private MockNumberKeyListener mMockNumberKeyListener; 44 45 /** 46 * Check point: 47 * 1. Filter "Android test", return "". 48 * 2. Filter "12345", return null. 49 * 3. Filter "", return null. 50 * 4. Filter "12345 Android", return "12345". 51 * 5. Filter Spanned("12345 Android"), return Spanned("12345") and copy spans. 52 */ 53 @Test 54 public void testFilter() { 55 mMockNumberKeyListener = new MockNumberKeyListener(MockNumberKeyListener.DIGITS); 56 String source = "Android test"; 57 SpannableString dest = new SpannableString("012345"); 58 assertEquals("", mMockNumberKeyListener.filter(source, 0, source.length(), 59 dest, 0, dest.length()).toString()); 60 61 source = "12345"; 62 dest = new SpannableString("012345"); 63 assertNull(mMockNumberKeyListener.filter(source, 0, source.length(), dest, 0, 64 dest.length())); 65 66 source = ""; 67 dest = new SpannableString("012345"); 68 assertNull(mMockNumberKeyListener.filter(source, 0, source.length(), dest, 0, 69 dest.length())); 70 71 source = "12345 Android"; 72 dest = new SpannableString("012345 Android-test"); 73 assertEquals("12345", mMockNumberKeyListener.filter(source, 0, source.length(), 74 dest, 0, dest.length()).toString()); 75 76 Object what = new Object(); 77 Spannable spannableSource = new SpannableString("12345 Android"); 78 spannableSource.setSpan(what, 0, spannableSource.length(), Spanned.SPAN_POINT_POINT); 79 Spanned filtered = (Spanned) mMockNumberKeyListener.filter(spannableSource, 80 0, spannableSource.length(), dest, 0, dest.length()); 81 assertEquals("12345", filtered.toString()); 82 assertEquals(Spanned.SPAN_POINT_POINT, filtered.getSpanFlags(what)); 83 assertEquals(0, filtered.getSpanStart(what)); 84 assertEquals("12345".length(), filtered.getSpanEnd(what)); 85 86 try { 87 mMockNumberKeyListener.filter(null, 0, 1, dest, 0, dest.length()); 88 fail("should throw NullPointerException."); 89 } catch (NullPointerException e) { 90 } 91 } 92 93 /** 94 * Check point: 95 * If one of the chars in the getAcceptedChars() can be generated by the keyCode of this 96 * key event, return the char; otherwise return '\0'. 97 */ 98 @Test 99 public void testLookup() { 100 mMockNumberKeyListener = new MockNumberKeyListener(MockNumberKeyListener.DIGITS); 101 KeyEvent event1 = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0); 102 SpannableString str = new SpannableString("012345"); 103 assertEquals('0', mMockNumberKeyListener.lookup(event1, str)); 104 105 mMockNumberKeyListener = new MockNumberKeyListener(MockNumberKeyListener.NOTHING); 106 KeyEvent event2 = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A); 107 str = new SpannableString("ABCD"); 108 assertEquals('\0', mMockNumberKeyListener.lookup(event2, str)); 109 110 try { 111 mMockNumberKeyListener.lookup(null, str); 112 fail("should throw NullPointerException."); 113 } catch (NullPointerException e) { 114 // expected. 115 } 116 } 117 118 @Test 119 public void testOk() { 120 mMockNumberKeyListener = new MockNumberKeyListener(MockNumberKeyListener.DIGITS); 121 122 assertTrue(mMockNumberKeyListener.callOk(mMockNumberKeyListener.getAcceptedChars(), '3')); 123 assertFalse(mMockNumberKeyListener.callOk(mMockNumberKeyListener.getAcceptedChars(), 'e')); 124 125 try { 126 mMockNumberKeyListener.callOk(null, 'm'); 127 fail("should throw NullPointerException."); 128 } catch (NullPointerException e) { 129 } 130 } 131 132 /** 133 * Check point: 134 * 1. Press '0' key, '0' will be added to the text. 135 * 2. Press an unaccepted key if it exists, it will not be added. 136 * 3. remove NumberKeyListener and press '0' key, '0' will not be added. 137 */ 138 @Test 139 public void testPressKey() { 140 final CharSequence text = "123456"; 141 final MockNumberKeyListener mockNumberKeyListener = 142 new MockNumberKeyListener(MockNumberKeyListener.DIGITS); 143 144 mActivity.runOnUiThread(() -> { 145 mTextView.setText(text, BufferType.EDITABLE); 146 mTextView.setKeyListener(mockNumberKeyListener); 147 mTextView.requestFocus(); 148 Selection.setSelection(mTextView.getText(), 0, 0); 149 }); 150 mInstrumentation.waitForIdleSync(); 151 assertEquals("123456", mTextView.getText().toString()); 152 // press '0' key. 153 CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_0); 154 assertEquals("0123456", mTextView.getText().toString()); 155 156 // an unaccepted key if it exists. 157 int keyCode = TextMethodUtils.getUnacceptedKeyCode(MockNumberKeyListener.DIGITS); 158 if (-1 != keyCode) { 159 CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, keyCode); 160 // text of TextView will not be changed. 161 assertEquals("0123456", mTextView.getText().toString()); 162 } 163 164 mActivity.runOnUiThread(() -> { 165 mTextView.setKeyListener(null); 166 mTextView.requestFocus(); 167 }); 168 mInstrumentation.waitForIdleSync(); 169 // press '0' key. 170 CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_0); 171 assertEquals("0123456", mTextView.getText().toString()); 172 } 173 174 /** 175 * A mocked {@link android.text.method.NumberKeyListener} for testing purposes. 176 * 177 * Allows {@link NumberKeyListenerTest} to call 178 * {@link android.text.method.NumberKeyListener#getAcceptedChars()}, 179 * {@link android.text.method.NumberKeyListener#lookup(KeyEvent, Spannable)}, and 180 * {@link android.text.method.NumberKeyListener@ok(char[], char)}. 181 */ 182 private static class MockNumberKeyListener extends NumberKeyListener { 183 static final char[] DIGITS = 184 new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; 185 186 static final char[] NOTHING = new char[0]; 187 188 private final char[] mAcceptedChars; 189 190 MockNumberKeyListener(char[] acceptedChars) { 191 this.mAcceptedChars = acceptedChars; 192 } 193 194 @Override 195 protected char[] getAcceptedChars() { 196 return mAcceptedChars; 197 } 198 199 @Override 200 protected int lookup(KeyEvent event, Spannable content) { 201 return super.lookup(event, content); 202 } 203 204 public boolean callOk(char[] accept, char c) { 205 return NumberKeyListener.ok(accept, c); 206 } 207 208 public int getInputType() { 209 return 0; 210 } 211 } 212 } 213