flaky(android,ci): HomeScreenTest IME visibility wait times out in transcript-layout shards

Open Beginner friendly
#2,253 2 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 4 days

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
android, github-actions, kotlin

Research direction

Start with android/app/src/androidTest/kotlin/app/hapi/companion/feature/home/HomeScreenTest.kt and the transcript-layout job in .github/workflows/android.yml. Reproduce the timeout in the backDismissesKeyboardBeforeSearchAndImeSearchKeepsTheQuery test, then determine whether to replace the IME-visibility assertion with observable search state or make the emulator environment keyboard-aware. Verify the targeted test and the Android workflow no longer time out on the API 29 and API 36 matrix cells.

Written by the indexing model from the issue text.

Description

Summary

transcript-layout fails on HomeScreenTest.backDismissesKeyboardBeforeSearchAndImeSearchKeepsTheQuery for every PR that triggers the Android workflow. The failure is deterministic on the api-level: 29 cell and intermittent on the api-level: 36 cell, and it started with 1c861b2f0 (feat(android): redesign home toolbar search and filters, 2026-10-30), which landed directly on main and is the only commit that ever touched this test.

The PRs currently red on it do not touch HomeScreen at all. Because android.yml also triggers on shared/fixtures/**, unrelated PRs that only regenerate fixtures inherit the red check.

Failure

  • Job: transcript-layout (29) and transcript-layout (36)
  • Test: app.hapi.companion.feature.home.HomeScreenTest.backDismissesKeyboardBeforeSearchAndImeSearchKeepsTheQuery
  • Error:
androidx.compose.ui.test.ComposeTimeoutException: Condition still not satisfied after 10000 ms
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl.waitUntil(ComposeUiTest.android.kt:504)
emulator-5554 - 10 Tests 34/56 completed. (1 skipped) (0 failed)
app.hapi.companion.feature.home.HomeScreenTest > backDismissesKeyboardBeforeSearchAndImeSearchKeepsTheQuery[emulator-5554 - 10] FAILED
Tests on emulator-5554 - 10 failed: There was 1 failure(s).

It is the only failing test in the whole suite run; every other class (56 tests) passes.

Evidence

All runs below are on tips that contain no changes under android/app/src/main/kotlin/app/hapi/companion/feature/home/:

PR Run API 29 API 36
#1852 41222895376 fail fail
#1852 41218234554 fail pass
#1684 41222022753 fail pass
#2249 41182584545 fail pass
#2228 41004399629 fail pass

#2252, #2251, #2247, #2236 show no transcript-layout checks at all, because they do not touch android/** or shared/fixtures/** - so the gate only bites PRs that happen to touch those paths.

Root cause (hypothesis)

The test asserts soft-keyboard visibility, which the CI emulator does not reliably provide.

android/app/src/androidTest/kotlin/app/hapi/companion/feature/home/HomeScreenTest.kt:

@Volatile private var imeVisible = false            // :81

@Composable
private fun Content() {
    val showingKeyboard = WindowInsets.isImeVisible  // :99
    SideEffect { imeVisible = showingKeyboard }      // :100
    ...
}

compose.onNodeWithTag("home-search-input").performTextInput("Build")  // :200
compose.waitUntil(10_000) { imeVisible }                              // :201

Two independent reasons this can never become true on CI:

  1. performTextInput injects text into the semantics tree; it does not open the IME. There is no performClick() / requestFocus() + showSoftInput sequence before the wait, so isImeVisible may stay false even on a device with no hardware keyboard.
  2. The workflow never removes the emulator's hardware keyboard: .github/workflows/android.yml:62-67 only sets api-level, arch: x86_64 and disable-animations: true. With a hardware keyboard present Android keeps the soft IME hidden, so isImeVisible stays false and waitUntil burns the full 10 s.

This also explains the per-cell split: both matrix cells run the entire connectedDebugAndroidTest suite (android.yml:44-67), and the API 29 AVD reliably reports no IME while API 36 sometimes does.

Impact

  • Blocks any PR that touches android/** or shared/fixtures/** on a surface it does not own.
  • Currently visible on #1684, #1852, #2228, #2249.
  • Hides real Android regressions behind a permanently red shard.

Proposed fix

Any of these is test/CI-only and does not change product behavior:

  1. Preferred - stop asserting IME visibility. Assert the observable product state instead:
compose.onNodeWithTag("home-search-input").assertIsFocused().assertTextEquals("Build")
pressBack()
compose.waitUntil(10_000) { viewModel.uiState.value.searchQuery.isEmpty() }
compose.onNodeWithTag("home-search-input").assertDoesNotExist()
  1. Keep the IME intent but make it environment-aware. Explicitly open the keyboard (performClick() then compose.activity.window + showSoftInput) before waiting, and Assume/skip when LocalConfiguration.current.keyboard != Configuration.KEYBOARD_NOKEYS (hardware keyboard attached).
  2. Make the AVD match the assertion. Add emulator-options/profile with hw.keyboard=no so the soft IME is guaranteed, keeping all four imeVisible waits meaningful.

Option 1 plus a single @SdkSuppress-scoped IME test keeps both stability and intent.

Ask

  • Please stabilize this instrumented test (or gate it behind a hardware-keyboard check).
  • Until it is fixed, please do not treat this single red as a blocker for PRs that do not touch HomeScreen*.

Environment

  • CI: GitHub Actions, .github/workflows/android.yml job transcript-layout, matrix api-level: [29, 36], arch: x86_64, reactivecircus/android-emulator-runner@v2, disable-animations: true
  • Introduced by commit 1c861b2f0 on 2026-10-30; main has no later commit touching this test or HomeScreen.kt.
  • Not reproducible on the reporter's machine: the host only has Java 8 while the Gradle build requires JDK 17+, so all evidence above is CI-only.

Related

  • #1835 flaky(android,ci): InspectionReadersTest.toolBrowserStartsAtLatest display assert on API 36 - same class of issue.
  • #1868 flaky(ios,ci): SessionSplitPresentationTests sidebar width 420>360 on iPad app-build - open precedent.

AI Disclosure

Analysis and wording assisted by OpenAI Codex (GPT-5.6); every log reference above was read from the linked GitHub Actions runs.

Dominant language
TypeScript
Stars
5.3k
Forks
626
Avg merge
4d 14h
Merged PRs (30d)
102

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from tiann/hapi

All issues in tiann/hapi

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.