diff options
author | Maurice Lam <yukl@google.com> | 2018-03-05 15:59:43 -0800 |
---|---|---|
committer | Maurice Lam <yukl@google.com> | 2018-04-04 19:51:32 -0700 |
commit | 618a4449bb3e9be43586040ea2fb9a6371365ae7 (patch) | |
tree | 38bb10565cd00959f7cdc5649a30cf541407e4da /library/test/robotest | |
parent | 1643b5132fbbbc376279785a512d93adc7a46cd7 (diff) | |
download | setupwizard-618a4449bb3e9be43586040ea2fb9a6371365ae7.tar.gz |
Add touch feedback to links
- Clear selection after LinkSpan is clicked so that the highlight
effect will be cleared when the tap completes
- Set focusableInTouchMode to true and revealOnFocusHint to false
in RichTextView for N MR1 or above to allow the highlight effect
to be visible in touch mode.
Test: ./gradlew test connectedAndroidTest
Bug: 73350031
Change-Id: Ibb6f67102775802cdfebaa1529c09d936b4096cb
(cherry picked from commit bc1c7a159c14f8b8f532fec60681d34771cd7909)
Diffstat (limited to 'library/test/robotest')
-rw-r--r-- | library/test/robotest/src/com/android/setupwizardlib/span/LinkSpanTest.java | 32 | ||||
-rw-r--r-- | library/test/robotest/src/com/android/setupwizardlib/view/RichTextViewTest.java | 194 |
2 files changed, 223 insertions, 3 deletions
diff --git a/library/test/robotest/src/com/android/setupwizardlib/span/LinkSpanTest.java b/library/test/robotest/src/com/android/setupwizardlib/span/LinkSpanTest.java index fe72e03..3aafa7d 100644 --- a/library/test/robotest/src/com/android/setupwizardlib/span/LinkSpanTest.java +++ b/library/test/robotest/src/com/android/setupwizardlib/span/LinkSpanTest.java @@ -16,11 +16,16 @@ package com.android.setupwizardlib.span; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertSame; import static org.robolectric.RuntimeEnvironment.application; import android.content.Context; import android.content.ContextWrapper; +import android.text.Selection; +import android.text.SpannableStringBuilder; +import android.text.method.LinkMovementMethod; import android.widget.TextView; import com.android.setupwizardlib.robolectric.SuwLibRobolectricTestRunner; @@ -32,7 +37,7 @@ import org.junit.runner.RunWith; public class LinkSpanTest { @Test - public void testOnClick() { + public void onClick_shouldCallListenerOnContext() { final TestContext context = new TestContext(application); final TextView textView = new TextView(context); final LinkSpan linkSpan = new LinkSpan("test_id"); @@ -43,7 +48,7 @@ public class LinkSpanTest { } @Test - public void testNonImplementingContext() { + public void onClick_contextDoesNotImplementOnClickListener_shouldBeNoOp() { final TextView textView = new TextView(application); final LinkSpan linkSpan = new LinkSpan("test_id"); @@ -54,7 +59,7 @@ public class LinkSpanTest { } @Test - public void testWrappedListener() { + public void onClick_contextWrapsOnClickListener_shouldCallWrappedListener() { final TestContext context = new TestContext(application); final Context wrapperContext = new ContextWrapper(context); final TextView textView = new TextView(wrapperContext); @@ -65,6 +70,27 @@ public class LinkSpanTest { assertSame("Clicked LinkSpan should be passed to setup", linkSpan, context.clickedSpan); } + @Test + public void onClick_shouldClearSelection() { + final TestContext context = new TestContext(application); + final TextView textView = new TextView(context); + textView.setMovementMethod(LinkMovementMethod.getInstance()); + textView.setFocusable(true); + textView.setFocusableInTouchMode(true); + final LinkSpan linkSpan = new LinkSpan("test_id"); + + SpannableStringBuilder text = new SpannableStringBuilder("Lorem ipsum dolor sit"); + textView.setText(text); + text.setSpan(linkSpan, /* start= */ 0, /* end= */ 5, /* flags= */ 0); + // Simulate the touch effect set by TextView when touched. + Selection.setSelection(text, /* start= */ 0, /* end= */ 5); + + linkSpan.onClick(textView); + + assertThat(Selection.getSelectionStart(textView.getText())).isEqualTo(0); + assertThat(Selection.getSelectionEnd(textView.getText())).isEqualTo(0); + } + @SuppressWarnings("deprecation") private static class TestContext extends ContextWrapper implements LinkSpan.OnClickListener { diff --git a/library/test/robotest/src/com/android/setupwizardlib/view/RichTextViewTest.java b/library/test/robotest/src/com/android/setupwizardlib/view/RichTextViewTest.java new file mode 100644 index 0000000..2e28b48 --- /dev/null +++ b/library/test/robotest/src/com/android/setupwizardlib/view/RichTextViewTest.java @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2016 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 com.android.setupwizardlib.view; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.robolectric.RuntimeEnvironment.application; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.ContextWrapper; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.text.Annotation; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.TextAppearanceSpan; + +import com.android.setupwizardlib.robolectric.SuwLibRobolectricTestRunner; +import com.android.setupwizardlib.span.LinkSpan; +import com.android.setupwizardlib.span.LinkSpan.OnLinkClickListener; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import java.util.Arrays; + +@RunWith(SuwLibRobolectricTestRunner.class) +@Config(sdk = { Config.OLDEST_SDK, Config.NEWEST_SDK }) +public class RichTextViewTest { + + @Test + public void testLinkAnnotation() { + Annotation link = new Annotation("link", "foobar"); + SpannableStringBuilder ssb = new SpannableStringBuilder("Hello world"); + ssb.setSpan(link, 1, 2, 0 /* flags */); + + RichTextView textView = new RichTextView(application); + textView.setText(ssb); + + final CharSequence text = textView.getText(); + assertTrue("Text should be spanned", text instanceof Spanned); + + Object[] spans = ((Spanned) text).getSpans(0, text.length(), Annotation.class); + assertEquals("Annotation should be removed " + Arrays.toString(spans), 0, spans.length); + + spans = ((Spanned) text).getSpans(0, text.length(), LinkSpan.class); + assertEquals("There should be one span " + Arrays.toString(spans), 1, spans.length); + assertTrue("The span should be a LinkSpan", spans[0] instanceof LinkSpan); + assertEquals("The LinkSpan should have id \"foobar\"", + "foobar", ((LinkSpan) spans[0]).getId()); + } + + @Test + public void testOnLinkClickListener() { + Annotation link = new Annotation("link", "foobar"); + SpannableStringBuilder ssb = new SpannableStringBuilder("Hello world"); + ssb.setSpan(link, 1, 2, 0 /* flags */); + + RichTextView textView = new RichTextView(application); + textView.setText(ssb); + + OnLinkClickListener listener = mock(OnLinkClickListener.class); + textView.setOnLinkClickListener(listener); + + assertSame(listener, textView.getOnLinkClickListener()); + + CharSequence text = textView.getText(); + LinkSpan[] spans = ((Spanned) text).getSpans(0, text.length(), LinkSpan.class); + spans[0].onClick(textView); + + verify(listener).onLinkClick(eq(spans[0])); + } + + @Test + public void testLegacyContextOnClickListener() { + // Click listener implemented by context should still be invoked for compatibility. + Annotation link = new Annotation("link", "foobar"); + SpannableStringBuilder ssb = new SpannableStringBuilder("Hello world"); + ssb.setSpan(link, 1, 2, 0 /* flags */); + + TestContext context = spy(new TestContext(application)); + RichTextView textView = new RichTextView(context); + textView.setText(ssb); + + CharSequence text = textView.getText(); + LinkSpan[] spans = ((Spanned) text).getSpans(0, text.length(), LinkSpan.class); + spans[0].onClick(textView); + + verify(context).onClick(eq(spans[0])); + } + + @Test + public void testTextStyle() { + Annotation link = new Annotation("textAppearance", "foobar"); + SpannableStringBuilder ssb = new SpannableStringBuilder("Hello world"); + ssb.setSpan(link, 1, 2, 0 /* flags */); + + RichTextView textView = new RichTextView(application); + textView.setText(ssb); + + final CharSequence text = textView.getText(); + assertTrue("Text should be spanned", text instanceof Spanned); + + Object[] spans = ((Spanned) text).getSpans(0, text.length(), Annotation.class); + assertEquals("Annotation should be removed " + Arrays.toString(spans), 0, spans.length); + + spans = ((Spanned) text).getSpans(0, text.length(), TextAppearanceSpan.class); + assertEquals("There should be one span " + Arrays.toString(spans), 1, spans.length); + assertTrue("The span should be a TextAppearanceSpan", + spans[0] instanceof TextAppearanceSpan); + } + + @Test + public void testTextContainingLinksAreFocusable() { + Annotation testLink = new Annotation("link", "value"); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("Linked"); + spannableStringBuilder.setSpan(testLink, 0, 3, 0); + + RichTextView view = new RichTextView(application); + view.setText(spannableStringBuilder); + + assertTrue("TextView should be focusable since it contains spans", view.isFocusable()); + } + + + @SuppressLint("SetTextI18n") // It's OK. This is just a test. + @Test + public void testTextContainingNoLinksAreNotFocusable() { + RichTextView textView = new RichTextView(application); + textView.setText("Thou shall not be focusable!"); + + assertFalse("TextView should not be focusable since it does not contain any span", + textView.isFocusable()); + } + + + // Based on the text contents of the text view, the "focusable" property of the element + // should also be automatically changed. + @SuppressLint("SetTextI18n") // It's OK. This is just a test. + @Test + public void testRichTextViewFocusChangesWithTextChange() { + RichTextView textView = new RichTextView(application); + textView.setText("Thou shall not be focusable!"); + + assertFalse(textView.isFocusable()); + assertFalse(textView.isFocusableInTouchMode()); + + SpannableStringBuilder spannableStringBuilder = + new SpannableStringBuilder("I am focusable"); + spannableStringBuilder.setSpan(new Annotation("link", "focus:on_me"), 0, 1, 0); + textView.setText(spannableStringBuilder); + assertTrue(textView.isFocusable()); + if (VERSION.SDK_INT >= VERSION_CODES.N_MR1) { + assertTrue(textView.isFocusableInTouchMode()); + assertFalse(textView.getRevealOnFocusHint()); + } else { + assertFalse(textView.isFocusableInTouchMode()); + } + } + + public static class TestContext extends ContextWrapper implements LinkSpan.OnClickListener { + + public TestContext(Context base) { + super(base); + } + + @Override + public void onClick(LinkSpan span) { + // Ignore. Can be verified using Mockito + } + } +} |