13487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su/*
23487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su * Copyright (C) 2008 The Android Open Source Project
33487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su *
43487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su * Licensed under the Apache License, Version 2.0 (the "License");
53487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su * you may not use this file except in compliance with the License.
63487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su * You may obtain a copy of the License at
73487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su *
83487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su *      http://www.apache.org/licenses/LICENSE-2.0
93487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su *
103487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su * Unless required by applicable law or agreed to in writing, software
113487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su * distributed under the License is distributed on an "AS IS" BASIS,
123487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su * See the License for the specific language governing permissions and
143487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su * limitations under the License.
153487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su */
163487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
173487313ff582d8a7ae2bf58e7379c4577522dd61Scott Supackage android.text.method.cts;
183487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
193487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport com.android.cts.stub.R;
203487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
213487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
223487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.app.Activity;
233487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.app.Instrumentation;
243487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.test.ActivityInstrumentationTestCase2;
253487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.text.Editable;
263487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.text.Selection;
273487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.text.Spannable;
283487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.text.SpannableString;
293487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.text.Spanned;
303487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.text.method.NumberKeyListener;
313487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.view.KeyEvent;
323487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.view.View;
333487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.widget.TextView;
343487313ff582d8a7ae2bf58e7379c4577522dd61Scott Suimport android.widget.TextView.BufferType;
353487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
36300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu
373487313ff582d8a7ae2bf58e7379c4577522dd61Scott Supublic class NumberKeyListenerTest extends
383487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        ActivityInstrumentationTestCase2<KeyListenerStubActivity> {
39300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu
403487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    private MockNumberKeyListener mNumberKeyListener;
413487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    private Activity mActivity;
423487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    private Instrumentation mInstrumentation;
433487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    private TextView mTextView;
443487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
453487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    public NumberKeyListenerTest(){
463487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        super("com.android.cts.stub", KeyListenerStubActivity.class);
473487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    }
483487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
493487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    @Override
503487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    protected void setUp() throws Exception {
513487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        super.setUp();
523487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        mActivity = getActivity();
533487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        mInstrumentation = getInstrumentation();
543487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        mTextView = (TextView) mActivity.findViewById(R.id.keylistener_textview);
553487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    }
563487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
573487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    /**
583487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * Check point:
593487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * 1. Filter "Android test", return "".
603487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * 2. Filter "12345", return null.
613487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * 3. Filter "", return null.
623487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * 4. Filter "12345 Android", return "12345".
633487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * 5. Filter Spanned("12345 Android"), return Spanned("12345") and copy spans.
643487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     */
653487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    public void testFilter() {
66300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        mNumberKeyListener = new MockNumberKeyListener(MockNumberKeyListener.DIGITS);
673487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        String source = "Android test";
683487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        SpannableString dest = new SpannableString("012345");
693487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals("", mNumberKeyListener.filter(source, 0, source.length(),
703487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su                dest, 0, dest.length()).toString());
713487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
723487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        source = "12345";
733487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        dest = new SpannableString("012345");
743487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertNull(mNumberKeyListener.filter(source, 0, source.length(), dest, 0, dest.length()));
753487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
763487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        source = "";
773487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        dest = new SpannableString("012345");
783487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertNull(mNumberKeyListener.filter(source, 0, source.length(), dest, 0, dest.length()));
793487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
803487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        source = "12345 Android";
813487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        dest = new SpannableString("012345 Android-test");
823487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals("12345", mNumberKeyListener.filter(source, 0, source.length(),
833487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su                dest, 0, dest.length()).toString());
843487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
853487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        Object what = new Object();
863487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        Spannable spannableSource = new SpannableString("12345 Android");
873487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        spannableSource.setSpan(what, 0, spannableSource.length(), Spanned.SPAN_POINT_POINT);
883487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        Spanned filtered = (Spanned) mNumberKeyListener.filter(spannableSource,
893487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su                0, spannableSource.length(), dest, 0, dest.length());
903487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals("12345", filtered.toString());
913487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals(Spanned.SPAN_POINT_POINT, filtered.getSpanFlags(what));
923487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals(0, filtered.getSpanStart(what));
933487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals("12345".length(), filtered.getSpanEnd(what));
943487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
953487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        try {
963487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            mNumberKeyListener.filter(null, 0, 1, dest, 0, dest.length());
973487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            fail("should throw NullPointerException.");
983487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        } catch (NullPointerException e) {
993487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        }
1003487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    }
1013487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1023487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    /**
1033487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * Check point:
1043487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * If one of the chars in the getAcceptedChars() can be generated by the keyCode of this
1053487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * key event, return the char; otherwise return '\0'.
1063487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     */
1073487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    public void testLookup() {
108300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        mNumberKeyListener = new MockNumberKeyListener(MockNumberKeyListener.DIGITS);
1093487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        KeyEvent event1 = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
1103487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        SpannableString str = new SpannableString("012345");
1113487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals('0', mNumberKeyListener.lookup(event1, str));
1123487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
113300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        mNumberKeyListener = new MockNumberKeyListener(MockNumberKeyListener.NOTHING);
114b540563eba88dee712c296c53cd8088bcc0368e7Brian Muramatsu        KeyEvent event2 = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A);
115b540563eba88dee712c296c53cd8088bcc0368e7Brian Muramatsu        str = new SpannableString("ABCD");
1163487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals('\0', mNumberKeyListener.lookup(event2, str));
1173487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1183487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        try {
1193487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            mNumberKeyListener.lookup(null, str);
1203487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            fail("should throw NullPointerException.");
1213487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        } catch (NullPointerException e) {
1223487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            // expected.
1233487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        }
1243487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    }
1253487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1263487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    public void testOk() {
127300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        mNumberKeyListener = new MockNumberKeyListener(MockNumberKeyListener.DIGITS);
1283487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1293487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertTrue(mNumberKeyListener.callOk(mNumberKeyListener.getAcceptedChars(), '3'));
1303487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertFalse(mNumberKeyListener.callOk(mNumberKeyListener.getAcceptedChars(), 'e'));
1313487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1323487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        try {
1333487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            mNumberKeyListener.callOk(null, 'm');
1343487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            fail("should throw NullPointerException.");
1353487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        } catch (NullPointerException e) {
1363487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        }
1373487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    }
1383487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1393487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    /**
1403487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * Check point:
1413487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * 1. Press '0' key, '0' will be added to the text.
1423487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * 2. Press an unaccepted key if it exists, it will not be added.
1433487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     * 3. remove NumberKeyListener and press '0' key, '0' will not be added.
1443487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su     */
1453487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    public void testPressKey() {
1463487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        final CharSequence text = "123456";
147300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        final MockNumberKeyListener numberKeyListener =
148300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu            new MockNumberKeyListener(MockNumberKeyListener.DIGITS);
1493487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1503487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        mActivity.runOnUiThread(new Runnable() {
1513487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            public void run() {
1523487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su                mTextView.setText(text, BufferType.EDITABLE);
1533487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su                mTextView.setKeyListener(numberKeyListener);
1543487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su                mTextView.requestFocus();
1553487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su                Selection.setSelection((Editable) mTextView.getText(), 0, 0);
1563487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            }
1573487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        });
1583487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        mInstrumentation.waitForIdleSync();
1593487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals("123456", mTextView.getText().toString());
1603487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        // press '0' key.
1613487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        sendKeys(KeyEvent.KEYCODE_0);
1623487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals("0123456", mTextView.getText().toString());
1633487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1643487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        // an unaccepted key if it exists.
165300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        int keyCode = TextMethodUtils.getUnacceptedKeyCode(MockNumberKeyListener.DIGITS);
1663487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        if (-1 != keyCode) {
1673487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            sendKeys(keyCode);
1683487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            // text of TextView will not be changed.
1693487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            assertEquals("0123456", mTextView.getText().toString());
1703487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        }
1713487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1723487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        mActivity.runOnUiThread(new Runnable() {
1733487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            public void run() {
1743487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su                mTextView.setKeyListener(null);
1753487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su                mTextView.requestFocus();
1763487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            }
1773487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        });
1783487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        mInstrumentation.waitForIdleSync();
1793487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        // press '0' key.
1803487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        sendKeys(KeyEvent.KEYCODE_0);
1813487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        assertEquals("0123456", mTextView.getText().toString());
1823487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    }
1833487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1843487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    private static class MockNumberKeyListener extends NumberKeyListener {
185300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu
186300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        static final char[] DIGITS =
187300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu                new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
188300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu
189300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        static final char[] NOTHING = new char[0];
190300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu
191300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        private final char[] mAcceptedChars;
192300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu
193300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        MockNumberKeyListener(char[] acceptedChars) {
194300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu            this.mAcceptedChars = acceptedChars;
195300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        }
1963487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
1973487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        @Override
1983487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        protected char[] getAcceptedChars() {
199300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu            return mAcceptedChars;
2003487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        }
2013487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
2023487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        @Override
2033487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        protected int lookup(KeyEvent event, Spannable content) {
2043487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            return super.lookup(event, content);
2053487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        }
2063487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
2073487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        public boolean callOk(char[] accept, char c) {
2083487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            return NumberKeyListener.ok(accept, c);
2093487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        }
2103487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su
2113487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        public int getInputType() {
2123487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su            return 0;
2133487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su        }
2143487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su    }
2153487313ff582d8a7ae2bf58e7379c4577522dd61Scott Su}
216