Skip to content

Android: a view with a content description and no text reads the same as a view showing that text #4530

Closed

Description

@vzkn

Purpose

On Android, a view that has a content description and no text is published exactly like a view whose text is that string. A caller cannot tell whether label is text on the screen, so a text check passes on an empty view.

Reproduction

Any view with a description and no text:

TextView saved = new TextView(this);
saved.setId(R.id.saved_task);
saved.setContentDescription("saved_task"); // no text yet

adb shell uiautomator dump reports it as text="" content-desc="saved_task".

agent-device get attrs 'id="dev.retest.bench.tasks:id/saved_task"' --json
# "node": {"type":"android.widget.TextView","label":"saved_task","identifier":"dev.retest.bench.tasks:id/saved_task", ...}
agent-device get text 'id="dev.retest.bench.tasks:id/saved_task"' --json
# "text": "saved_task"

When the app then sets the view's text to saved_task, the node is the same, field for field. snapshot --raw gives the same answer as the regular snapshot.

Cause

normalizeAndroidUiHierarchyNode in packages/platform-android/src/ui-hierarchy.ts labels a node with attrs.text || attrs.desc and publishes contentDescription only when it differs from the label (#2912). When the description is the label, nothing on the node says so. labelFacts in packages/provider-webdriver/src/webdriver-source.ts follows the same rule.

Required behavior

A node labelled by its content description can be told apart from a node labelled by its text. label and contentDescription keep their current values.

Proposed shape

Publish text when the view's text is not already the label, the rule contentDescription follows today. That is an empty string on a view with a description and no text, and no field anywhere else. text ?? label is then the text the view shows.

{"type":"android.widget.TextView","label":"saved_task","text":"","identifier":"dev.retest.bench.tasks:id/saved_task"}

Alternative: publish text on every view that has text. The rule is simpler, but it repeats the label on every text node.

Completion

  • A view with a description and no text, and a view whose text is that same string, produce different nodes in snapshot JSON, get attrs and find.
  • Nodes that are labelled by their text are unchanged.

iOS

Not affected. XCTest gives one label per element, so there is no second attribute to keep apart.

Environment

  • agent-device 0.21.38-nightly.20261113.167 (helper backend android-helper); same code on main at ddbfc85
  • Android 15 emulator (API 35, arm64), build-tools 35.0.0
  • macOS, Node 24.12.0

Found through a text assertion in Retest, which drives Android through agent-device. A pull request with the proposed shape follows.

Activity

  1. thymikee commented on Nov 14, 2026

    @thymikee
    Member

    Triage: bug; current Android normalization loses whether the label came from visible text or content description. #4531 covers the missing node provenance. Its review still needs to settle whether that alone satisfies the reported text assertion, since get text and text= are unchanged by that PR. No additional reproduction is needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions