Skip to content

Expose semantic testTags on chat-ui affordances#4

Merged
RomanLeshc merged 1 commit into
mainfrom
tf/testtags-chat-ui
May 11, 2026
Merged

Expose semantic testTags on chat-ui affordances#4
RomanLeshc merged 1 commit into
mainfrom
tf/testtags-chat-ui

Conversation

@phwizard
Copy link
Copy Markdown
Member

Summary

Adds Compose `Modifier.testTag(...)` markers to the chat-ui affordances that both Compose UI tests and Maestro E2E flows need to resolve at runtime. Today tests have to fall back to `contentDescription` / text matching, which breaks under localization, theming, and minor copy edits.

Tags added

Component Tag Element
`ChatInput` `chat_input` `OutlinedTextField` for user text
`ChatInput` `chat_send_button` FAB (active) AND disabled IconButton (empty field) — same tag on both states so tests can resolve the send affordance without knowing whether text is present
`ChatInput` `chat_attach_button` Attach IconButton (hidden in edit mode)
`MessageBubble` `chat_message_image` The `MediaMessage` subtree for media bubbles
`RoomListView` `rooms_list` The `LazyColumn` rendering rooms
`RoomListView` `room_row` Each clickable room `Surface`
`RoomListView` `rooms_search_input` The `SearchBar` `OutlinedTextField`
`RoomListView` `create_room_button` The "+" Add IconButton in the top app bar

Pattern

Each component declares its tag values in a small companion `*TestTags` object at the end of the file:

```kotlin
object ChatInputTestTags {
const val INPUT_FIELD = "chat_input"
const val SEND_BUTTON = "chat_send_button"
const val ATTACH_BUTTON = "chat_attach_button"
}
```

Source consumers import constants rather than re-typing magic strings, so:

  • Tags stay discoverable next to the composable they describe.
  • Renaming a tag is a one-place change.
  • Documents in one place that tests + Maestro flows depend on these values; don't change them casually.

Behavior

No behavior change. `testTag` is a `SemanticsModifier` — purely additive metadata only observable from accessibility / test frameworks. Render tree, layout, click handling unchanged.

Companion PRs

  • `ethora-sdk-android` PR #3 — existing Compose UI tests can update to `onNodeWithTag(...)` instead of `onNodeWithContentDescription(...)` once this lands.
  • `ethora-sample-android` PR #2 — the Maestro flows in `.maestro/flows/` already reference these exact id values (`id: "chat_input"`, `id: "chat_send_button"`, etc.) but as `optional: true` so they no-op today; once this lands those become required assertions and the flows actually exercise their full intent.

Test plan

  • `./gradlew :chat-ui:assembleDebug` succeeds.
  • No regressions in existing `./gradlew :ethora-component:test` suite.
  • Visual / behavior of `ChatInput`, `MessageBubble`, `RoomListView` unchanged on the sample app (manual smoke).
  • After the companion test PR is rebased on this, `./gradlew :chat-ui:connectedDebugAndroidTest` resolves the new `onNodeWithTag(...)` finders correctly.

Adds Compose Modifier.testTag(...) markers to the affordances that
both Compose UI tests (ethora-sdk-android/.../androidTest/) and
Maestro flows (ethora-sample-android/.maestro/flows/) need to
resolve at runtime. Without these, tests have to fall back to
contentDescription / text matching, which breaks under
localization, theming, and minor copy edits.

Tags added:

  ChatInput
    chat_input          OutlinedTextField for the user's text
    chat_send_button    FAB (active) and disabled IconButton (empty
                        field) — same tag on both states so tests
                        can resolve "the send affordance" without
                        knowing whether text is present
    chat_attach_button  attach IconButton (hidden in edit mode)

  MessageBubble
    chat_message_image  the MediaMessage subtree for media bubbles

  RoomListView
    rooms_list          the LazyColumn rendering the room list
    room_row            each clickable room Surface
    rooms_search_input  the SearchBar OutlinedTextField
    create_room_button  the "+" Add IconButton in the top app bar

Each component declares its tag values in a small companion
`*TestTags` object at the end of the file (ChatInputTestTags,
MessageBubbleTestTags, RoomListViewTestTags), so source consumers
import constants rather than re-typing magic strings. This:

  - keeps tags discoverable next to the composable they describe
  - makes a tag rename a one-place change (the constant)
  - documents in one place that tests + Maestro flows depend on
    these values, so don't change them casually

No behavior change. testTag is a SemanticsModifier — purely
additive metadata that's only observable from accessibility /
test frameworks. Render tree, layout, click handling unchanged.

Companion changes in:
  - ethora-sdk-android PR #3 (existing tests will be updated to
    use onNodeWithTag(...) instead of content-description anchors)
  - ethora-sample-android PR #2 (.maestro/flows/ already reference
    these exact id values via id: "chat_input" / "chat_send_button"
    etc., previously marked optional: true; once this lands those
    can become required assertions)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants