google / Accessibility-Test-Framework-for-Android

Accessibility checks for automated Android testing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TextInputLayout / TextInputEditText fail accessibility scans

inktomi opened this issue · comments

Build: AI-203.6682.168.2031.7101492, 202101251652,

AI-203.6682.168.2031.7101492, JRE 11.0.8+10-b944.6842174x64 JetBrains s.r.o, OS Mac OS X(x86_64) v10.15.7, screens 5120.0x2880.0, 3384.0x6016.0, 3360.0x2100.0; Retina

AS: Arctic Fox | 2020.3.1 Canary 5; Kotlin plugin: 1.4.21-release-Studio4.2-1; Android Gradle Plugin: 7.0.0-alpha05; Gradle: 6.8; NDK: from local.properties: (not specified), latest from SDK: (not found); LLDB: LLDB 3.1 (revision: 3.1.4508709); CMake: from local.properties: (not specified), latest from SDK: (not found), from PATH: (not found)

TextInputLayout with a TextInputEditText inside it does not pass accessibility scans.

Create a sample project with the following:

app.gradle

  implementation 'com.google.android.material:material:1.2.1'
  androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0-alpha03'
  androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.4.0-alpha03'

ExampleInstrumentedTest

@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
    @Rule
    @JvmField
    var rule: ActivityScenarioRule<*> = ActivityScenarioRule(MainActivity::class.java)


    @Test
    fun justLoadHome() {
        AccessibilityChecks.enable()
        onView(withId(R.id.input_field)).perform(typeText("A - B - C"))
    }
}

MainActivity.kt

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val inputLayout = findViewById<TextInputLayout>(R.id.input_layout)
        inputLayout.hint = "A hint!"

        val inputField = findViewById<TextInputEditText>(R.id.input_field)
    }

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.textfield.TextInputLayout
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
        android:id="@+id/input_layout"
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:labelFor="@id/input_field"
        android:hint="A hint!"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">
        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/input_field"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Then, run the test. It will fail with an accessibility issue:

com.google.android.apps.common.testing.accessibility.framework.integrations.espresso.AccessibilityViewCheckException: There was 1 accessibility result:
TextInputEditText{id=2131230901, res-name=input_field, visibility=VISIBLE, width=300, height=54, has-focus=true, has-focusable=true, has-window-focus=false, is-clickable=true, is-enabled=true, is-focused=true, is-focusable=true, is-layout-requested=false, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@ca43d75, tag=null, root-is-layout-requested=false, has-input-connection=true, editor-info=[inputType=0x20001 imeOptions=0x40000006 privateImeOptions=null actionLabel=null actionId=0 initialSelStart=0 initialSelEnd=0 initialCapsMode=0x0 hintText=A hint! label=null packageName=null fieldId=0 fieldName=null extras=null ], x=0.0, y=0.0, text=, hint=A hint!, input-type=131073, ime-target=false, has-links=false}: This item may not have a label readable by screen readers. Reported by com.google.android.apps.common.testing.accessibility.framework.checks.SpeakableTextPresentCheck
at com.google.android.apps.common.testing.accessibility.framework.integrations.espresso.AccessibilityValidator.processResults(AccessibilityValidator.java:270)
at com.google.android.apps.common.testing.accessibility.framework.integrations.espresso.AccessibilityValidator.runAccessibilityChecks(AccessibilityValidator.java:228)
at com.google.android.apps.common.testing.accessibility.framework.integrations.espresso.AccessibilityValidator.checkAndReturnResults(AccessibilityValidator.java:87)
at androidx.test.espresso.accessibility.AccessibilityChecks$2.check(AccessibilityChecks.java:65)
at androidx.test.espresso.action.ViewActions$1.perform(ViewActions.java:3)
at androidx.test.espresso.ViewInteraction$SingleExecutionViewAction.perform(ViewInteraction.java:2)
at androidx.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:22)
at androidx.test.espresso.ViewInteraction.access$100(ViewInteraction.java:1)
at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:2)
at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:1)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Note that the hint is being set in code & in the layout, and the error even reports that it's set, but the SpeakableTextPresentCheck still fails. TalkBack will read the hint when this code is on screen.

In this use of TextInputLayout, the android:labelFor is not required. This is similar to the example on material.io.

The implementation of TextInputEditText will pick up the hint from the TextInputLayout automatically. In this particular construct, adding android:labelFor causes the hint to be ignored when testing accessibility on Espresso. Removing the attribute will eliminate the test failure.