19f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su/* 29f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * Copyright (C) 2008 The Android Open Source Project 39f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * 49f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * Licensed under the Apache License, Version 2.0 (the "License"); 59f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * you may not use this file except in compliance with the License. 69f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * You may obtain a copy of the License at 79f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * 89f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * http://www.apache.org/licenses/LICENSE-2.0 99f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * 109f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * Unless required by applicable law or agreed to in writing, software 119f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * distributed under the License is distributed on an "AS IS" BASIS, 129f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * See the License for the specific language governing permissions and 149f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * limitations under the License. 159f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su */ 169f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 179f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Supackage android.text.method.cts; 189f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 199f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 209f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.os.SystemClock; 219f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.test.ActivityInstrumentationTestCase2; 229f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.test.UiThreadTest; 239f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.text.Selection; 249f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.text.Spannable; 259f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.text.SpannableString; 269f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.text.Spanned; 279f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.text.method.LinkMovementMethod; 289f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.text.method.MovementMethod; 299f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.text.style.ClickableSpan; 309f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.view.KeyEvent; 319f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.view.MotionEvent; 329f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.view.View; 339f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.widget.TextView; 349f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Suimport android.widget.TextView.BufferType; 359f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 369f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su/** 379f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * Test {@link LinkMovementMethod}. The class is an implementation of interface 389f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * {@link MovementMethod}. The typical usage of {@link MovementMethod} is tested in 399f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * {@link android.widget.cts.TextViewTest} and this test case is only focused on the 409f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * implementation of the methods. 419f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * 429f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su * @see android.widget.cts.TextViewTest 439f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su */ 449f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Supublic class LinkMovementMethodTest extends 459f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su ActivityInstrumentationTestCase2<StubActivity> { 469f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private static final String CONTENT = "clickable\nunclickable\nclickable"; 479f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 489f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private LinkMovementMethod mMethod; 499f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 509f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private TextView mView; 519f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 529f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private Spannable mSpannable; 539f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 549f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private MockClickableSpan mClickable0; 559f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 569f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private MockClickableSpan mClickable1; 579f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 589f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public LinkMovementMethodTest() { 599f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su super("com.android.cts.stub", StubActivity.class); 609f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 619f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 629f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @Override 639f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su protected void setUp() throws Exception { 649f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su super.setUp(); 659f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mMethod = new LinkMovementMethod(); 669f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 679f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // Set the content view with a text view which contains 3 lines, 689f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mView = new TextView(getActivity()); 699f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mView.setText(CONTENT, BufferType.SPANNABLE); 709f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su getInstrumentation().runOnMainSync(new Runnable() { 719f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void run() { 729f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su getActivity().setContentView(mView); 739f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 749f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su }); 759f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su getInstrumentation().waitForIdleSync(); 769f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 779f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mSpannable = (Spannable) mView.getText(); 789f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // make first line clickable 799f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable0 = markClickable(0, CONTENT.indexOf('\n')); 809f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // make last line clickable 819f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable1 = markClickable(CONTENT.lastIndexOf('\n'), CONTENT.length()); 829f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 839f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 849f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testConstructor() { 859f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su new LinkMovementMethod(); 869f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 879f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 889f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testGetInstance() { 899f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su MovementMethod method0 = LinkMovementMethod.getInstance(); 909f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(method0 instanceof LinkMovementMethod); 919f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 929f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su MovementMethod method1 = LinkMovementMethod.getInstance(); 939f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertNotNull(method1); 949f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSame(method0, method1); 959f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 969f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 979f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testOnTakeFocus() { 989f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su LinkMovementMethod method = new LinkMovementMethod(); 999f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Spannable spannable = new SpannableString("test sequence"); 1009f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Selection.setSelection(spannable, 0, spannable.length()); 1019f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1029f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, 0, spannable.length()); 103c59fe85a7cd516caf51deea78daee810a0b4cf90Rasmus Tengblad assertTrue("Expected at least 2 spans", 2 <= spannable.getSpans(0, spannable.length(), Object.class).length); 1049f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.onTakeFocus(null, spannable, View.FOCUS_UP); 1059f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, -1); 1069f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertEquals(1, spannable.getSpans(0, spannable.length(), Object.class).length); 1079f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Object span = spannable.getSpans(0, spannable.length(), Object.class)[0]; 1089f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertEquals(0, spannable.getSpanStart(span)); 1099f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertEquals(0, spannable.getSpanEnd(span)); 1109f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertEquals(Spanned.SPAN_POINT_POINT, spannable.getSpanFlags(span)); 1119f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1129f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // focus forwards 1139f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Selection.setSelection(spannable, 0, spannable.length()); 1149f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, 0, spannable.length()); 115c59fe85a7cd516caf51deea78daee810a0b4cf90Rasmus Tengblad assertTrue("Expected at least 3 spans", 3 <= spannable.getSpans(0, spannable.length(), Object.class).length); 1169f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.onTakeFocus(null, spannable, View.FOCUS_RIGHT); 1179f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, -1); 1189f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length); 1199f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1209f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // force adding span while focus backward 1219f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.onTakeFocus(null, spannable, View.FOCUS_UP); 1229f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // param direction is unknown(0) 1239f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Selection.setSelection(spannable, 0, spannable.length()); 1249f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, 0, spannable.length()); 125c59fe85a7cd516caf51deea78daee810a0b4cf90Rasmus Tengblad assertTrue("Expected at least 3 spans", 3 <= spannable.getSpans(0, spannable.length(), Object.class).length); 1269f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.onTakeFocus(null, spannable, 0); 1279f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, -1); 1289f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length); 1299f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1309f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // null parameters 1319f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 1329f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.onTakeFocus(new TextView(getActivity()), null, View.FOCUS_RIGHT); 1339f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param spannable is null."); 1349f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 1359f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 1369f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 1379f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 1389f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1399f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @UiThreadTest 1409f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testOnKeyDown() { 1419f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // no selection 1429f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 1439f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable0.reset(); 1449f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable1.reset(); 1459f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_ENTER, 1469f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER))); 1479f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable0.hasCalledOnClick()); 1489f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable1.hasCalledOnClick()); 1499f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1509f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // select clickable0 1519f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Selection.setSelection(mSpannable, mSpannable.getSpanStart(mClickable0), 1529f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mSpannable.getSpanEnd(mClickable0)); 1539f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable0.reset(); 1549f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable1.reset(); 1559f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, 1569f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER))); 1579f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(mClickable0.hasCalledOnClick()); 1589f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable1.hasCalledOnClick()); 1599f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1609f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // select unclickable 1619f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0), 1629f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mSpannable.getSpanStart(mClickable1)); 1639f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable0.reset(); 1649f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable1.reset(); 1659f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_ENTER, 1669f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER))); 1679f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable0.hasCalledOnClick()); 1689f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable1.hasCalledOnClick()); 1699f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1709f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // select all clickables(more than one) 1719f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Selection.selectAll(mSpannable); 1729f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable0.reset(); 1739f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable1.reset(); 1749f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, 1759f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER))); 1769f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable0.hasCalledOnClick()); 1779f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable1.hasCalledOnClick()); 1789f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1799f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // part of selection is clickable 1809f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0), 1819f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mSpannable.getSpanEnd(mClickable1)); 1829f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable0.reset(); 1839f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable1.reset(); 1849f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, 1859f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER))); 1869f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable0.hasCalledOnClick()); 1879f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(mClickable1.hasCalledOnClick()); 1889f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1899f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // selection contains only clickable1 and repeat count of the event is not 0 1909f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0), 1919f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mSpannable.getSpanEnd(mClickable1)); 1929f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su long now = SystemClock.uptimeMillis(); 1939f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, 1949f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su KeyEvent.KEYCODE_DPAD_CENTER, 1); 1959f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 1969f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable0.reset(); 1979f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mClickable1.reset(); 1989f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, event)); 1999f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable0.hasCalledOnClick()); 2009f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable1.hasCalledOnClick()); 2019f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2029f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // null parameters 2039f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 2049f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mMethod.onKeyDown(null, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, 2059f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)); 2069f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param view is null."); 2079f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 2089f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 2099f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 2109f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2119f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 2129f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mMethod.onKeyDown(mView, null, KeyEvent.KEYCODE_DPAD_CENTER, 2139f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)); 2149f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param spannable is null."); 2159f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 2169f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 2179f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 2189f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2199f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 2209f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, null); 2219f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param keyEvent is null."); 2229f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 2239f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 2249f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 2259f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 2269f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2279f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testOnKeyUp() { 2289f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su LinkMovementMethod method = new LinkMovementMethod(); 2299f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // always returns false 2309f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.onKeyUp(null, null, 0, null)); 2319f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.onKeyUp(new TextView(getActivity()), null, 0, null)); 2329f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.onKeyUp(null, new SpannableString("blahblah"), 0, null)); 2339f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.onKeyUp(null, null, KeyEvent.KEYCODE_0, 2349f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0))); 2359f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 2369f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2379f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @UiThreadTest 2389f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testOnTouchEvent() { 2399f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 2409f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2419f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // press on first line (Clickable) 2429f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(pressOnLine(0)); 2439f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableLeftToRight(mSpannable, mClickable0); 2449f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2459f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // release on first line 2469f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable0.hasCalledOnClick()); 2479f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(releaseOnLine(0)); 2489f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(mClickable0.hasCalledOnClick()); 2499f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2509f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // press on second line (unclickable) 2519f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableLeftToRight(mSpannable, mClickable0); 2529f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // just clear selection 2539f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su pressOnLine(1); 2549f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 2559f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2569f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // press on last line (Clickable) 2579f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(pressOnLine(2)); 2589f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableLeftToRight(mSpannable, mClickable1); 2599f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2609f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // release on last line 2619f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(mClickable1.hasCalledOnClick()); 2629f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(releaseOnLine(2)); 2639f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(mClickable1.hasCalledOnClick()); 2649f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2659f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // release on second line (unclickable) 2669f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableLeftToRight(mSpannable, mClickable1); 2679f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // just clear selection 2689f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su releaseOnLine(1); 2699f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 2709f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2719f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // null parameters 2729f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su long now = SystemClock.uptimeMillis(); 2739f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su int y = (mView.getLayout().getLineTop(1) + mView.getLayout().getLineBottom(1)) / 2; 2749f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 2759f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mMethod.onTouchEvent(null, mSpannable, 2769f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 5, y, 0)); 2779f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param view is null."); 2789f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 2799f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 2809f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 2819f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2829f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 2839f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mMethod.onTouchEvent(mView, null, 2849f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 5, y, 0)); 2859f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param spannable is null."); 2869f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 2879f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 2889f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 2899f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2909f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 2919f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mMethod.onTouchEvent(mView, mSpannable, null); 2929f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param keyEvent is null."); 2939f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 2949f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 2959f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 2969f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 2979f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 2989f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @UiThreadTest 2999f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testUp() { 3009f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su final MyLinkMovementMethod method = new MyLinkMovementMethod(); 3019f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 3029f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3039f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(method.up(mView, mSpannable)); 3049f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableRightToLeft(mSpannable, mClickable1); 3059f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3069f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(method.up(mView, mSpannable)); 3079f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableRightToLeft(mSpannable, mClickable0); 3089f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3099f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.up(mView, mSpannable)); 3109f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableRightToLeft(mSpannable, mClickable0); 3119f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3129f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // null parameters 3139f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 3149f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.up(null, mSpannable); 3159f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param view is null."); 3169f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 3179f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 3189f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 3199f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3209f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 3219f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.up(mView, null); 3229f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param spannable is null."); 3239f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 3249f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 3259f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 3269f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 3279f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3289f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @UiThreadTest 3299f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testDown() { 3309f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su final MyLinkMovementMethod method = new MyLinkMovementMethod(); 3319f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 3329f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3339f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(method.down(mView, mSpannable)); 3349f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableLeftToRight(mSpannable, mClickable0); 3359f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3369f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(method.down(mView, mSpannable)); 3379f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableLeftToRight(mSpannable, mClickable1); 3389f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3399f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.down(mView, mSpannable)); 3409f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableLeftToRight(mSpannable, mClickable1); 3419f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3429f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // null parameters 3439f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 3449f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.down(null, mSpannable); 3459f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param view is null."); 3469f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 3479f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 3489f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 3499f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3509f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 3519f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.down(mView, null); 3529f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param spannable is null."); 3539f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 3549f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 3559f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 3569f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 3579f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3589f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @UiThreadTest 3599f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testLeft() { 3609f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su final MyLinkMovementMethod method = new MyLinkMovementMethod(); 3619f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 3629f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3639f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(method.left(mView, mSpannable)); 3649f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableRightToLeft(mSpannable, mClickable1); 3659f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3669f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(method.left(mView, mSpannable)); 3679f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableRightToLeft(mSpannable, mClickable0); 3689f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3699f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.left(mView, mSpannable)); 3709f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableRightToLeft(mSpannable, mClickable0); 3719f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3729f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // null parameters 3739f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 3749f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.left(null, mSpannable); 3759f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param view is null."); 3769f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 3779f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 3789f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 3799f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3809f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 3819f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.left(mView, null); 3829f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param spannable is null."); 3839f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 3849f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 3859f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 3869f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 3879f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3889f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @UiThreadTest 3899f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testRight() { 3909f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su final MyLinkMovementMethod method = new MyLinkMovementMethod(); 3919f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 3929f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3939f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(method.right(mView, mSpannable)); 3949f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableLeftToRight(mSpannable, mClickable0); 3959f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3969f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertTrue(method.right(mView, mSpannable)); 3979f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableLeftToRight(mSpannable, mClickable1); 3989f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 3999f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.right(mView, mSpannable)); 4009f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelectClickableLeftToRight(mSpannable, mClickable1); 4019f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4029f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // null parameters 4039f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 4049f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.right(null, mSpannable); 4059f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param view is null."); 4069f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 4079f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 4089f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4099f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4109f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 4119f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.right(mView, null); 4129f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param spannable is null."); 4139f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 4149f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 4159f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4169f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4179f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4189f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @UiThreadTest 4199f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testMoveAroundUnclickable() { 4209f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su final MyLinkMovementMethod method = new MyLinkMovementMethod(); 4219f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mSpannable.removeSpan(mClickable0); 4229f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mSpannable.removeSpan(mClickable1); 4239f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 4249f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4259f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.up(mView, mSpannable)); 4269f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 4279f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4289f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.down(mView, mSpannable)); 4299f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 4309f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4319f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.left(mView, mSpannable)); 4329f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 4339f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4349f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertFalse(method.right(mView, mSpannable)); 4359f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(mSpannable, -1); 4369f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4379f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4389f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void testInitialize() { 4399f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su LinkMovementMethod method = new LinkMovementMethod(); 4409f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Spannable spannable = new SpannableString("test sequence"); 4419f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.onTakeFocus(null, spannable, View.FOCUS_UP); 4429f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su Selection.setSelection(spannable, 0, spannable.length()); 4439f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4449f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, 0, spannable.length()); 445c59fe85a7cd516caf51deea78daee810a0b4cf90Rasmus Tengblad assertTrue("Expected at least 3 spans", 3 <= spannable.getSpans(0, spannable.length(), Object.class).length); 4469f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.initialize(null, spannable); 4479f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, -1); 4489f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length); 4499f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4509f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su try { 4519f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su method.initialize(mView, null); 4529f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su fail("The method did not throw NullPointerException when param spannable is null."); 4539f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } catch (NullPointerException e) { 4549f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su // expected 4559f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4569f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4579f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4589f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private MockClickableSpan markClickable(final int start, final int end) { 4599f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su final MockClickableSpan clickableSpan = new MockClickableSpan(); 4609f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su getInstrumentation().runOnMainSync(new Runnable() { 4619f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void run() { 4629f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mSpannable.setSpan(clickableSpan, start, end, Spanned.SPAN_MARK_MARK); 4639f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4649f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su }); 4659f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su getInstrumentation().waitForIdleSync(); 4669f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su return clickableSpan; 4679f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4689f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4699f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private boolean performMotionOnLine(int line, int action) { 4709f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su int x = (mView.getLayout().getLineStart(line) + mView.getLayout().getLineEnd(line)) / 2; 4719f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su int y = (mView.getLayout().getLineTop(line) + mView.getLayout().getLineBottom(line)) / 2; 4729f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su long now = SystemClock.uptimeMillis(); 4739f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4749f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su return mMethod.onTouchEvent(mView, mSpannable, 4759f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su MotionEvent.obtain(now, now, action, x, y, 0)); 4769f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4779f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4789f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private boolean pressOnLine(int line) { 4799f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su return performMotionOnLine(line, MotionEvent.ACTION_DOWN); 4809f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4819f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4829f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private boolean releaseOnLine(int line) { 4839f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su return performMotionOnLine(line, MotionEvent.ACTION_UP); 4849f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4859f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4869f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private void assertSelection(Spannable spannable, int start, int end) { 4879f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertEquals(start, Selection.getSelectionStart(spannable)); 4889f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertEquals(end, Selection.getSelectionEnd(spannable)); 4899f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4909f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4919f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private void assertSelection(Spannable spannable, int position) { 4929f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, position, position); 4939f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 4949f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 4959f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private void assertSelectClickableLeftToRight(Spannable spannable, 4969f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su MockClickableSpan clickableSpan) { 4979f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, spannable.getSpanStart(clickableSpan), 4989f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su spannable.getSpanEnd(clickableSpan)); 4999f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5009f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 5019f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private void assertSelectClickableRightToLeft(Spannable spannable, 5029f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su MockClickableSpan clickableSpan) { 5039f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su assertSelection(spannable, spannable.getSpanEnd(clickableSpan), 5049f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su spannable.getSpanStart(clickableSpan)); 5059f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5069f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 5079f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private static class MyLinkMovementMethod extends LinkMovementMethod { 5089f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @Override 5099f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su protected boolean down(TextView widget, Spannable buffer) { 5109f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su return super.down(widget, buffer); 5119f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5129f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 5139f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @Override 5149f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su protected boolean left(TextView widget, Spannable buffer) { 5159f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su return super.left(widget, buffer); 5169f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5179f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 5189f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @Override 5199f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su protected boolean right(TextView widget, Spannable buffer) { 5209f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su return super.right(widget, buffer); 5219f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5229f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 5239f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @Override 5249f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su protected boolean up(TextView widget, Spannable buffer) { 5259f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su return super.up(widget, buffer); 5269f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5279f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5289f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 5299f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private static class MockClickableSpan extends ClickableSpan { 5309f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su private boolean mHasCalledOnClick; 5319f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 5329f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su @Override 5339f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void onClick(View widget) { 5349f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mHasCalledOnClick = true; 5359f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5369f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 5379f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public boolean hasCalledOnClick() { 5389f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su return mHasCalledOnClick; 5399f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5409f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su 5419f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su public void reset() { 5429f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su mHasCalledOnClick = false; 5439f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5449f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su } 5459f4ffc968cc16769cdb7dd8a47301240a0f5d3fcScott Su} 546