AI 145434: am: CL 145407 am: CL 145015 CTS: add test cases for LinkMovementMethod and HideReturnsTransformationMethod.
Original author: sus
Merged from: //branches/cupcake/...
Original author: android-build
Automated import of CL 145434
diff --git a/tests/tests/text/src/android/text/method/cts/HideReturnsTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/HideReturnsTransformationMethodTest.java
new file mode 100644
index 0000000..ffbff7f
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/HideReturnsTransformationMethodTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.method.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import android.text.method.HideReturnsTransformationMethod;
+
+import junit.framework.TestCase;
+
+/**
+ * Test {@link HideReturnsTransformationMethod}.
+ */
+@TestTargetClass(HideReturnsTransformationMethod.class)
+public class HideReturnsTransformationMethodTest extends TestCase {
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test constructor "
+ + "HideReturnsTransformationMethod#HideReturnsTransformationMethod().",
+ method = "HideReturnsTransformationMethod",
+ args = {}
+ )
+ public void testConstructor() {
+ new HideReturnsTransformationMethod();
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link HideReturnsTransformationMethod#getOriginal()}.",
+ method = "getOriginal",
+ args = {}
+ )
+ public void testGetOriginal() {
+ MyHideReturnsTranformationMethod method = new MyHideReturnsTranformationMethod();
+ TextMethodUtils.assertEquals(new char[] { '\r' }, method.getOriginal());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link HideReturnsTransformationMethod#getInstance()}.",
+ method = "getInstance",
+ args = {}
+ )
+ public void testGetInstance() {
+ HideReturnsTransformationMethod method0 = HideReturnsTransformationMethod.getInstance();
+ assertNotNull(method0);
+
+ HideReturnsTransformationMethod method1 = HideReturnsTransformationMethod.getInstance();
+ assertSame(method0, method1);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link HideReturnsTransformationMethod#getReplacement()}.",
+ method = "getReplacement",
+ args = {}
+ )
+ public void testGetReplacement() {
+ MyHideReturnsTranformationMethod method = new MyHideReturnsTranformationMethod();
+ TextMethodUtils.assertEquals(new char[] { '\uFEFF' }, method.getReplacement());
+ }
+
+ private static class MyHideReturnsTranformationMethod extends HideReturnsTransformationMethod {
+ @Override
+ protected char[] getOriginal() {
+ return super.getOriginal();
+ }
+
+ @Override
+ protected char[] getReplacement() {
+ return super.getReplacement();
+ }
+ }
+}
diff --git a/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
new file mode 100644
index 0000000..57c6d33
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
@@ -0,0 +1,679 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.method.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.text.method.MovementMethod;
+import android.text.style.ClickableSpan;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.TextView.BufferType;
+
+/**
+ * Test {@link LinkMovementMethod}. The class is an implementation of interface
+ * {@link MovementMethod}. The typical usage of {@link MovementMethod} is tested in
+ * {@link android.widget.cts.TextViewTest} and this test case is only focused on the
+ * implementation of the methods.
+ *
+ * @see android.widget.cts.TextViewTest
+ */
+@TestTargetClass(LinkMovementMethod.class)
+public class LinkMovementMethodTest extends
+ ActivityInstrumentationTestCase2<StubActivity> {
+ private static final String CONTENT = "clickable\nunclickable\nclickable";
+
+ private LinkMovementMethod mMethod;
+
+ private TextView mView;
+
+ private Spannable mSpannable;
+
+ private MockClickableSpan mClickable0;
+
+ private MockClickableSpan mClickable1;
+
+ public LinkMovementMethodTest() {
+ super("com.android.cts.stub", StubActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mMethod = new LinkMovementMethod();
+
+ // Set the content view with a text view which contains 3 lines,
+ mView = new TextView(getActivity());
+ mView.setText(CONTENT, BufferType.SPANNABLE);
+ getInstrumentation().runOnMainSync(new Runnable() {
+ public void run() {
+ getActivity().setContentView(mView);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ mSpannable = (Spannable) mView.getText();
+ // make first line clickable
+ mClickable0 = markClickable(0, CONTENT.indexOf('\n'));
+ // make last line clickable
+ mClickable1 = markClickable(CONTENT.lastIndexOf('\n'), CONTENT.length());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test constructor LinkMovementMethod#LinkMovementMethod().",
+ method = "LinkMovementMethod",
+ args = {}
+ )
+ public void testConstructor() {
+ new LinkMovementMethod();
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#getInstance()}. "
+ + "This is a method for creating singleton.",
+ method = "getInstance",
+ args = {}
+ )
+ public void testGetInstance() {
+ MovementMethod method0 = LinkMovementMethod.getInstance();
+ assertTrue(method0 instanceof LinkMovementMethod);
+
+ MovementMethod method1 = LinkMovementMethod.getInstance();
+ assertNotNull(method1);
+ assertSame(method0, method1);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#onTakeFocus(TextView, Spannable, int)}. "
+ + "The parameter textView is useless.",
+ method = "onTakeFocus",
+ args = {TextView.class, Spannable.class, int.class}
+ )
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+ + "should be added into javadoc of LinkMovementMethod#onTakeFocus(TextView, Spannable, "
+ + "int) when the params text is null")
+ public void testOnTakeFocus() {
+ LinkMovementMethod method = new LinkMovementMethod();
+ Spannable spannable = new SpannableString("test sequence");
+ Selection.setSelection(spannable, 0, spannable.length());
+
+ assertSelection(spannable, 0, spannable.length());
+ assertEquals(2, spannable.getSpans(0, spannable.length(), Object.class).length);
+ method.onTakeFocus(null, spannable, View.FOCUS_UP);
+ assertSelection(spannable, -1);
+ assertEquals(1, spannable.getSpans(0, spannable.length(), Object.class).length);
+ Object span = spannable.getSpans(0, spannable.length(), Object.class)[0];
+ assertEquals(0, spannable.getSpanStart(span));
+ assertEquals(0, spannable.getSpanEnd(span));
+ assertEquals(Spanned.SPAN_POINT_POINT, spannable.getSpanFlags(span));
+
+ // focus forwards
+ Selection.setSelection(spannable, 0, spannable.length());
+ assertSelection(spannable, 0, spannable.length());
+ assertEquals(3, spannable.getSpans(0, spannable.length(), Object.class).length);
+ method.onTakeFocus(null, spannable, View.FOCUS_RIGHT);
+ assertSelection(spannable, -1);
+ assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length);
+
+ // force adding span while focus backward
+ method.onTakeFocus(null, spannable, View.FOCUS_UP);
+ // param direction is unknown(0)
+ Selection.setSelection(spannable, 0, spannable.length());
+ assertSelection(spannable, 0, spannable.length());
+ assertEquals(3, spannable.getSpans(0, spannable.length(), Object.class).length);
+ method.onTakeFocus(null, spannable, 0);
+ assertSelection(spannable, -1);
+ assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length);
+
+ // null parameters
+ try {
+ method.onTakeFocus(new TextView(getActivity()), null, View.FOCUS_RIGHT);
+ fail("The method did not throw NullPointerException when param spannable is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#onKeyDown(TextView, Spannable, int, KeyEvent)}.",
+ method = "onKeyDown",
+ args = {TextView.class, Spannable.class, int.class, KeyEvent.class}
+ )
+ @UiThreadTest
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+ + "should be added into javadoc of LinkMovementMethod#onKeyDown(TextView, Spannable, "
+ + "int, KeyEvent) when the params widget, buffer or event is null")
+ public void testOnKeyDown() {
+ // no selection
+ assertSelection(mSpannable, -1);
+ mClickable0.reset();
+ mClickable1.reset();
+ assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_ENTER,
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)));
+ assertFalse(mClickable0.hasCalledOnClick());
+ assertFalse(mClickable1.hasCalledOnClick());
+
+ // select clickable0
+ Selection.setSelection(mSpannable, mSpannable.getSpanStart(mClickable0),
+ mSpannable.getSpanEnd(mClickable0));
+ mClickable0.reset();
+ mClickable1.reset();
+ assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)));
+ assertTrue(mClickable0.hasCalledOnClick());
+ assertFalse(mClickable1.hasCalledOnClick());
+
+ // select unclickable
+ Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0),
+ mSpannable.getSpanStart(mClickable1));
+ mClickable0.reset();
+ mClickable1.reset();
+ assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_ENTER,
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)));
+ assertFalse(mClickable0.hasCalledOnClick());
+ assertFalse(mClickable1.hasCalledOnClick());
+
+ // select all clickables(more than one)
+ Selection.selectAll(mSpannable);
+ mClickable0.reset();
+ mClickable1.reset();
+ assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)));
+ assertFalse(mClickable0.hasCalledOnClick());
+ assertFalse(mClickable1.hasCalledOnClick());
+
+ // part of selection is clickable
+ Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0),
+ mSpannable.getSpanEnd(mClickable1));
+ mClickable0.reset();
+ mClickable1.reset();
+ assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)));
+ assertFalse(mClickable0.hasCalledOnClick());
+ assertTrue(mClickable1.hasCalledOnClick());
+
+ // selection contains only clickable1 and repeat count of the event is not 0
+ Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0),
+ mSpannable.getSpanEnd(mClickable1));
+ long now = SystemClock.uptimeMillis();
+ KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_DPAD_CENTER, 1);
+
+ mClickable0.reset();
+ mClickable1.reset();
+ assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, event));
+ assertFalse(mClickable0.hasCalledOnClick());
+ assertFalse(mClickable1.hasCalledOnClick());
+
+ // null parameters
+ try {
+ mMethod.onKeyDown(null, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER));
+ fail("The method did not throw NullPointerException when param view is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ mMethod.onKeyDown(mView, null, KeyEvent.KEYCODE_DPAD_CENTER,
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER));
+ fail("The method did not throw NullPointerException when param spannable is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, null);
+ fail("The method did not throw NullPointerException when param keyEvent is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#onKeyUp(TextView, Spannable, int, KeyEvent)}. "
+ + "It always returns false, and all parameters are never read.",
+ method = "onKeyUp",
+ args = {TextView.class, Spannable.class, int.class, KeyEvent.class}
+ )
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. There is no "
+ + "document about the behaviour of this method.")
+ public void testOnKeyUp() {
+ LinkMovementMethod method = new LinkMovementMethod();
+ // always returns false
+ assertFalse(method.onKeyUp(null, null, 0, null));
+ assertFalse(method.onKeyUp(new TextView(getActivity()), null, 0, null));
+ assertFalse(method.onKeyUp(null, new SpannableString("blahblah"), 0, null));
+ assertFalse(method.onKeyUp(null, null, KeyEvent.KEYCODE_0,
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0)));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#onTouchEvent(TextView, Spannable, MotionEvent)} ",
+ method = "onTouchEvent",
+ args = {TextView.class, Spannable.class, MotionEvent.class}
+ )
+ @UiThreadTest
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+ + "should be added into javadoc of LinkMovementMethod#onTouchEvent(TextView, "
+ + "Spannable, MotionEvent) when the params widget, buffer or event is null")
+ public void testOnTouchEvent() {
+ assertSelection(mSpannable, -1);
+
+ // press on first line (Clickable)
+ assertTrue(pressOnLine(0));
+ assertSelectClickableLeftToRight(mSpannable, mClickable0);
+
+ // release on first line
+ assertFalse(mClickable0.hasCalledOnClick());
+ assertTrue(releaseOnLine(0));
+ assertTrue(mClickable0.hasCalledOnClick());
+
+ // press on second line (unclickable)
+ assertSelectClickableLeftToRight(mSpannable, mClickable0);
+ // just clear selection
+ pressOnLine(1);
+ assertSelection(mSpannable, -1);
+
+ // press on last line (Clickable)
+ assertTrue(pressOnLine(2));
+ assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+ // release on last line
+ assertFalse(mClickable1.hasCalledOnClick());
+ assertTrue(releaseOnLine(2));
+ assertTrue(mClickable1.hasCalledOnClick());
+
+ // release on second line (unclickable)
+ assertSelectClickableLeftToRight(mSpannable, mClickable1);
+ // just clear selection
+ releaseOnLine(1);
+ assertSelection(mSpannable, -1);
+
+ // null parameters
+ long now = SystemClock.uptimeMillis();
+ int y = (mView.getLayout().getLineTop(1) + mView.getLayout().getLineBottom(1)) / 2;
+ try {
+ mMethod.onTouchEvent(null, mSpannable,
+ MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 5, y, 0));
+ fail("The method did not throw NullPointerException when param view is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ mMethod.onTouchEvent(mView, null,
+ MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 5, y, 0));
+ fail("The method did not throw NullPointerException when param spannable is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ mMethod.onTouchEvent(mView, mSpannable, null);
+ fail("The method did not throw NullPointerException when param keyEvent is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#up(TextView, Spannable)}. It is protected. "
+ + "Use extended class to test.",
+ method = "up",
+ args = {TextView.class, Spannable.class}
+ )
+ @UiThreadTest
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+ + "should be added into javadoc of LinkMovementMethod#up(TextView, Spannable) "
+ + "when the params widget or buffer or is null")
+ public void testUp() {
+ final MyLinkMovementMethod method = new MyLinkMovementMethod();
+ assertSelection(mSpannable, -1);
+
+ assertTrue(method.up(mView, mSpannable));
+ assertSelectClickableRightToLeft(mSpannable, mClickable1);
+
+ assertTrue(method.up(mView, mSpannable));
+ assertSelectClickableRightToLeft(mSpannable, mClickable0);
+
+ assertFalse(method.up(mView, mSpannable));
+ assertSelectClickableRightToLeft(mSpannable, mClickable0);
+
+ // null parameters
+ try {
+ method.up(null, mSpannable);
+ fail("The method did not throw NullPointerException when param view is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ method.up(mView, null);
+ fail("The method did not throw NullPointerException when param spannable is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#down(TextView, Spannable)}. It is protected. "
+ + "Use extended class to test.",
+ method = "down",
+ args = {TextView.class, Spannable.class}
+ )
+ @UiThreadTest
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+ + "should be added into javadoc of LinkMovementMethod#down(TextView, Spannable) "
+ + "when the params widget or buffer or is null")
+ public void testDown() {
+ final MyLinkMovementMethod method = new MyLinkMovementMethod();
+ assertSelection(mSpannable, -1);
+
+ assertTrue(method.down(mView, mSpannable));
+ assertSelectClickableLeftToRight(mSpannable, mClickable0);
+
+ assertTrue(method.down(mView, mSpannable));
+ assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+ assertFalse(method.down(mView, mSpannable));
+ assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+ // null parameters
+ try {
+ method.down(null, mSpannable);
+ fail("The method did not throw NullPointerException when param view is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ method.down(mView, null);
+ fail("The method did not throw NullPointerException when param spannable is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#left(TextView, Spannable)}. It is protected. "
+ + "Use extended class to test.",
+ method = "left",
+ args = {TextView.class, Spannable.class}
+ )
+ @UiThreadTest
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+ + "should be added into javadoc of LinkMovementMethod#left(TextView, Spannable) "
+ + "when the params widget or buffer or is null")
+ public void testLeft() {
+ final MyLinkMovementMethod method = new MyLinkMovementMethod();
+ assertSelection(mSpannable, -1);
+
+ assertTrue(method.left(mView, mSpannable));
+ assertSelectClickableRightToLeft(mSpannable, mClickable1);
+
+ assertTrue(method.left(mView, mSpannable));
+ assertSelectClickableRightToLeft(mSpannable, mClickable0);
+
+ assertFalse(method.left(mView, mSpannable));
+ assertSelectClickableRightToLeft(mSpannable, mClickable0);
+
+ // null parameters
+ try {
+ method.left(null, mSpannable);
+ fail("The method did not throw NullPointerException when param view is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ method.left(mView, null);
+ fail("The method did not throw NullPointerException when param spannable is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#right(TextView, Spannable)}. It is protected. "
+ + "Use extended class to test.",
+ method = "right",
+ args = {TextView.class, Spannable.class}
+ )
+ @UiThreadTest
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+ + "should be added into javadoc of LinkMovementMethod#right(TextView, Spannable) "
+ + "when the params widget or buffer or is null")
+ public void testRight() {
+ final MyLinkMovementMethod method = new MyLinkMovementMethod();
+ assertSelection(mSpannable, -1);
+
+ assertTrue(method.right(mView, mSpannable));
+ assertSelectClickableLeftToRight(mSpannable, mClickable0);
+
+ assertTrue(method.right(mView, mSpannable));
+ assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+ assertFalse(method.right(mView, mSpannable));
+ assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+ // null parameters
+ try {
+ method.right(null, mSpannable);
+ fail("The method did not throw NullPointerException when param view is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ method.right(mView, null);
+ fail("The method did not throw NullPointerException when param spannable is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#up(TextView, Spannable)}.",
+ method = "up",
+ args = {TextView.class, Spannable.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#down(TextView, Spannable)}.",
+ method = "down",
+ args = {TextView.class, Spannable.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#right(TextView, Spannable)}.",
+ method = "left",
+ args = {TextView.class, Spannable.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#left(TextView, Spannable)}.",
+ method = "right",
+ args = {TextView.class, Spannable.class}
+ )
+ })
+ @UiThreadTest
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. There is no "
+ + "document about the behaviour of these methods when the spannable text is not "
+ + "clickcable.")
+ public void testMoveAroundUnclickable() {
+ final MyLinkMovementMethod method = new MyLinkMovementMethod();
+ mSpannable.removeSpan(mClickable0);
+ mSpannable.removeSpan(mClickable1);
+ assertSelection(mSpannable, -1);
+
+ assertFalse(method.up(mView, mSpannable));
+ assertSelection(mSpannable, -1);
+
+ assertFalse(method.down(mView, mSpannable));
+ assertSelection(mSpannable, -1);
+
+ assertFalse(method.left(mView, mSpannable));
+ assertSelection(mSpannable, -1);
+
+ assertFalse(method.right(mView, mSpannable));
+ assertSelection(mSpannable, -1);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test {@link LinkMovementMethod#initialize(TextView, Spannable)}.",
+ method = "initialize",
+ args = {TextView.class, Spannable.class}
+ )
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+ + "should be added into javadoc of LinkMovementMethod#initialize(TextView, Spannable) "
+ + "when the params text is null")
+ public void testInitialize() {
+ LinkMovementMethod method = new LinkMovementMethod();
+ Spannable spannable = new SpannableString("test sequence");
+ method.onTakeFocus(null, spannable, View.FOCUS_UP);
+ Selection.setSelection(spannable, 0, spannable.length());
+
+ assertSelection(spannable, 0, spannable.length());
+ assertEquals(3, spannable.getSpans(0, spannable.length(), Object.class).length);
+ method.initialize(null, spannable);
+ assertSelection(spannable, -1);
+ assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length);
+
+ try {
+ method.initialize(mView, null);
+ fail("The method did not throw NullPointerException when param spannable is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ private MockClickableSpan markClickable(final int start, final int end) {
+ final MockClickableSpan clickableSpan = new MockClickableSpan();
+ getInstrumentation().runOnMainSync(new Runnable() {
+ public void run() {
+ mSpannable.setSpan(clickableSpan, start, end, Spanned.SPAN_MARK_MARK);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+ return clickableSpan;
+ }
+
+ private boolean performMotionOnLine(int line, int action) {
+ int x = (mView.getLayout().getLineStart(line) + mView.getLayout().getLineEnd(line)) / 2;
+ int y = (mView.getLayout().getLineTop(line) + mView.getLayout().getLineBottom(line)) / 2;
+ long now = SystemClock.uptimeMillis();
+
+ return mMethod.onTouchEvent(mView, mSpannable,
+ MotionEvent.obtain(now, now, action, x, y, 0));
+ }
+
+ private boolean pressOnLine(int line) {
+ return performMotionOnLine(line, MotionEvent.ACTION_DOWN);
+ }
+
+ private boolean releaseOnLine(int line) {
+ return performMotionOnLine(line, MotionEvent.ACTION_UP);
+ }
+
+ private void assertSelection(Spannable spannable, int start, int end) {
+ assertEquals(start, Selection.getSelectionStart(spannable));
+ assertEquals(end, Selection.getSelectionEnd(spannable));
+ }
+
+ private void assertSelection(Spannable spannable, int position) {
+ assertSelection(spannable, position, position);
+ }
+
+ private void assertSelectClickableLeftToRight(Spannable spannable,
+ MockClickableSpan clickableSpan) {
+ assertSelection(spannable, spannable.getSpanStart(clickableSpan),
+ spannable.getSpanEnd(clickableSpan));
+ }
+
+ private void assertSelectClickableRightToLeft(Spannable spannable,
+ MockClickableSpan clickableSpan) {
+ assertSelection(spannable, spannable.getSpanEnd(clickableSpan),
+ spannable.getSpanStart(clickableSpan));
+ }
+
+ private static class MyLinkMovementMethod extends LinkMovementMethod {
+ @Override
+ protected boolean down(TextView widget, Spannable buffer) {
+ return super.down(widget, buffer);
+ }
+
+ @Override
+ protected boolean left(TextView widget, Spannable buffer) {
+ return super.left(widget, buffer);
+ }
+
+ @Override
+ protected boolean right(TextView widget, Spannable buffer) {
+ return super.right(widget, buffer);
+ }
+
+ @Override
+ protected boolean up(TextView widget, Spannable buffer) {
+ return super.up(widget, buffer);
+ }
+ }
+
+ private static class MockClickableSpan extends ClickableSpan {
+ private boolean mHasCalledOnClick;
+
+ @Override
+ public void onClick(View widget) {
+ mHasCalledOnClick = true;
+ }
+
+ public boolean hasCalledOnClick() {
+ return mHasCalledOnClick;
+ }
+
+ public void reset() {
+ mHasCalledOnClick = false;
+ }
+ }
+}