|
| 1 | +/* |
| 2 | + * Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | + * |
| 4 | + * This source code is licensed under the MIT license found in the |
| 5 | + * LICENSE file in the root directory of this source tree. |
| 6 | + */ |
| 7 | + |
| 8 | +package com.facebook.react.views.text |
| 9 | + |
| 10 | +import android.text.SpannableString |
| 11 | +import android.text.Spanned |
| 12 | +import android.text.style.ClickableSpan |
| 13 | +import android.view.View |
| 14 | +import androidx.core.view.AccessibilityDelegateCompat |
| 15 | +import androidx.core.view.ViewCompat |
| 16 | +import com.facebook.react.R |
| 17 | +import org.assertj.core.api.Assertions.assertThat |
| 18 | +import org.junit.Test |
| 19 | +import org.junit.runner.RunWith |
| 20 | +import org.robolectric.RobolectricTestRunner |
| 21 | +import org.robolectric.RuntimeEnvironment |
| 22 | + |
| 23 | +@RunWith(RobolectricTestRunner::class) |
| 24 | +class ReactTextViewAccessibilityDelegateTest { |
| 25 | + |
| 26 | + private val view = PreparedLayoutTextView(RuntimeEnvironment.getApplication()) |
| 27 | + |
| 28 | + @Test |
| 29 | + fun `the first update installs the text delegate`() { |
| 30 | + ReactTextViewAccessibilityDelegate.updateAccessibilityLinks(view, SpannableString("Hello")) |
| 31 | + |
| 32 | + assertThat(delegate()).isInstanceOf(ReactTextViewAccessibilityDelegate::class.java) |
| 33 | + assertThat(view.getTag(R.id.accessibility_links)).isNull() |
| 34 | + } |
| 35 | + |
| 36 | + @Test |
| 37 | + fun `updates without links keep the delegate`() { |
| 38 | + ReactTextViewAccessibilityDelegate.updateAccessibilityLinks(view, SpannableString("Hello")) |
| 39 | + val first = delegate() |
| 40 | + |
| 41 | + ReactTextViewAccessibilityDelegate.updateAccessibilityLinks(view, SpannableString("World")) |
| 42 | + |
| 43 | + assertThat(delegate()).isSameAs(first) |
| 44 | + } |
| 45 | + |
| 46 | + @Test |
| 47 | + fun `adding and removing links resets the delegate`() { |
| 48 | + ReactTextViewAccessibilityDelegate.updateAccessibilityLinks(view, SpannableString("Hello")) |
| 49 | + val plain = delegate() |
| 50 | + |
| 51 | + ReactTextViewAccessibilityDelegate.updateAccessibilityLinks(view, textWithLink()) |
| 52 | + val withLink = delegate() |
| 53 | + assertThat(withLink).isNotSameAs(plain) |
| 54 | + assertThat(view.getTag(R.id.accessibility_links)).isNotNull() |
| 55 | + |
| 56 | + ReactTextViewAccessibilityDelegate.updateAccessibilityLinks(view, SpannableString("Hello")) |
| 57 | + assertThat(delegate()).isNotSameAs(withLink) |
| 58 | + assertThat(view.getTag(R.id.accessibility_links)).isNull() |
| 59 | + } |
| 60 | + |
| 61 | + @Test |
| 62 | + fun `a view set back to auto is important for accessibility after an update`() { |
| 63 | + ReactTextViewAccessibilityDelegate.updateAccessibilityLinks(view, SpannableString("Hello")) |
| 64 | + view.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_AUTO |
| 65 | + |
| 66 | + ReactTextViewAccessibilityDelegate.updateAccessibilityLinks(view, SpannableString("World")) |
| 67 | + |
| 68 | + assertThat(view.importantForAccessibility).isEqualTo(View.IMPORTANT_FOR_ACCESSIBILITY_YES) |
| 69 | + } |
| 70 | + |
| 71 | + private fun delegate(): AccessibilityDelegateCompat? = ViewCompat.getAccessibilityDelegate(view) |
| 72 | + |
| 73 | + private fun textWithLink(): Spanned = |
| 74 | + SpannableString("Read the docs here").apply { |
| 75 | + setSpan( |
| 76 | + object : ClickableSpan() { |
| 77 | + override fun onClick(widget: View) = Unit |
| 78 | + }, |
| 79 | + 9, |
| 80 | + 13, |
| 81 | + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE, |
| 82 | + ) |
| 83 | + } |
| 84 | +} |
0 commit comments