fix(test): Check notification permission before requesting to fix flaky API 34 tests#5146
Closed
fix(test): Check notification permission before requesting to fix flaky API 34 tests#5146
Conversation
…fix flaky API 34 tests On API 34, Maestro's `permissions: all: allow` pre-grants POST_NOTIFICATIONS via `pm grant`. The ActivityResult callback from `requestPermissionLauncher` is not always reliably invoked when the permission is already granted, causing the notification to never be posted. This adds a checkSelfPermission guard so the notification is posted directly when already permitted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contributor
Semver Impact of This PR🟢 Patch (bug fixes) 📋 Changelog PreviewThis is how your changes will appear in the changelog. Bug Fixes 🐛
🤖 This preview updates automatically when you update the PR. |
adinauer
approved these changes
Mar 3, 2026
Contributor
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 91bb874 | 314.47 ms | 440.00 ms | 125.53 ms |
| dba088c | 333.98 ms | 381.16 ms | 47.18 ms |
| d15471f | 310.66 ms | 368.19 ms | 57.53 ms |
| bbc35bb | 298.53 ms | 372.17 ms | 73.64 ms |
| d15471f | 307.28 ms | 381.85 ms | 74.57 ms |
| ad8da22 | 362.98 ms | 453.94 ms | 90.96 ms |
| cf708bd | 408.35 ms | 458.98 ms | 50.63 ms |
| 96449e8 | 361.30 ms | 423.39 ms | 62.09 ms |
| 27d7cf8 | 309.43 ms | 364.27 ms | 54.85 ms |
| 91bb874 | 311.00 ms | 363.47 ms | 52.47 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 91bb874 | 1.58 MiB | 2.13 MiB | 559.07 KiB |
| dba088c | 1.58 MiB | 2.13 MiB | 558.99 KiB |
| d15471f | 1.58 MiB | 2.13 MiB | 559.54 KiB |
| bbc35bb | 1.58 MiB | 2.12 MiB | 553.01 KiB |
| d15471f | 1.58 MiB | 2.13 MiB | 559.54 KiB |
| ad8da22 | 1.58 MiB | 2.29 MiB | 719.83 KiB |
| cf708bd | 1.58 MiB | 2.11 MiB | 539.71 KiB |
| 96449e8 | 1.58 MiB | 2.11 MiB | 539.35 KiB |
| 27d7cf8 | 1.58 MiB | 2.12 MiB | 549.42 KiB |
| 91bb874 | 1.58 MiB | 2.13 MiB | 559.07 KiB |
Previous results on branch: rz/fix/flaky-notification-test-api34
Startup times
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| f1cc8c9 | 324.39 ms | 379.83 ms | 55.44 ms |
| b51e769 | 309.53 ms | 366.82 ms | 57.29 ms |
| 06b4d04 | 344.02 ms | 412.70 ms | 68.68 ms |
| 4a898ed | 314.14 ms | 358.00 ms | 43.86 ms |
| d326a0d | 311.04 ms | 365.46 ms | 54.42 ms |
| 65bdd9b | 365.50 ms | 428.45 ms | 62.95 ms |
| b6344f5 | 313.35 ms | 363.47 ms | 50.12 ms |
| be17dea | 345.68 ms | 407.27 ms | 61.59 ms |
| 25c258f | 293.67 ms | 393.28 ms | 99.61 ms |
| 0f654b6 | 312.67 ms | 350.31 ms | 37.64 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| f1cc8c9 | 1.58 MiB | 2.29 MiB | 722.92 KiB |
| b51e769 | 1.58 MiB | 2.29 MiB | 722.93 KiB |
| 06b4d04 | 1.58 MiB | 2.29 MiB | 722.92 KiB |
| 4a898ed | 1.58 MiB | 2.29 MiB | 722.92 KiB |
| d326a0d | 1.58 MiB | 2.29 MiB | 722.93 KiB |
| 65bdd9b | 1.58 MiB | 2.29 MiB | 722.97 KiB |
| b6344f5 | 1.58 MiB | 2.29 MiB | 722.93 KiB |
| be17dea | 1.58 MiB | 2.29 MiB | 722.91 KiB |
| 25c258f | 1.58 MiB | 2.29 MiB | 722.93 KiB |
| 0f654b6 | 1.58 MiB | 2.29 MiB | 722.91 KiB |
The Pixel Launcher can become unresponsive on CI emulators, showing a system dialog that blocks Maestro from interacting with the app under test. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
IMPORTANCE_DEFAULT notifications may be silently delivered on some emulators, causing the notification to not appear in the shade when Maestro swipes down to find it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use a shorter, faster swipe from the center-top (50%, 1%) to center (50%, 50%) with 1s duration instead of a slow full-screen swipe. Also increase retries from 3 to 5 to handle slower emulators. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three fixes for flaky notification tests on CI emulators: 1. Handle the POST_NOTIFICATIONS permission dialog explicitly in the Maestro flow, in case Maestro's `permissions: all: allow` doesn't grant it reliably. 2. Collapse the notification shade in onFlowStart to prevent cascade failures when a previous test left it open. 3. Add waitForAnimationToEnd inside the swipe retry loop to give the shade time to render. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tings The swipe from 50%,1% to 50%,50% was too long — it expanded straight to the quick settings panel, hiding the notification entries behind it. Use a shorter swipe (0% to 25%) to only open the notification shade where notification entries are visible. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n channel Two issues found from analyzing the accessibility hierarchy dump: 1. Repeated swipe-downs accumulated into full quick settings expansion, hiding the notification list. Fix: press home before each swipe retry to reset the shade state, so each attempt opens a fresh notification shade instead of expanding quick settings further. 2. adb install -r preserves app data including notification channels. The old IMPORTANCE_DEFAULT channel persists and Android ignores the code change to IMPORTANCE_HIGH. Fix: delete the channel before recreating it to ensure correct importance. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
IMPORTANCE_HIGH shows the notification as a heads-up banner at the top of the screen. When Maestro swipes down to open the notification shade, it instead dismisses the heads-up notification, causing it to disappear entirely. IMPORTANCE_DEFAULT puts the notification directly in the shade without a heads-up, so the swipe opens the shade as intended. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restore the original swipe values (90%,0% -> 90%,100%, 4s) that are proven to work on main, but keep the pressKey:home + waitForAnimationToEnd before each swipe to prevent quick settings accumulation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…otification shade The full-screen swipe (90%,0% -> 90%,100%) was expanding into quick settings on API 34 instead of showing the notification shade. Changed to a half-screen swipe (90%,0% -> 90%,50%) which is long enough to open the shade on API 36 but short enough to avoid quick settings on API 34. Also uses pressKey:back + pressKey:home to reliably collapse any open shade/quick settings before retrying, and increased retries from 3 to 5. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ition The notification shade was closing between the repeat loop's visibility check and the subsequent tapOn command. By moving the tapOn inside the loop (with optional: true) and changing the loop condition to check for the app's expected screen instead, we tap the notification immediately after the swipe while the shade is still open. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ve notifications am force-stop (used by Maestro's killApp) clears all notifications on API 33+, causing Test 4 (COLD start via notification) to always fail. Adds a "Kill Process" button that calls Process.killProcess() which kills the app process without clearing notifications. The Maestro test now taps this button instead of using killApp. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous approach of using Process.killProcess() without Finish Activity didn't work because the notification wasn't surviving process death on API 33+. Analysis of main branch (where all API levels pass) shows that the original flow works: Trigger Notification → Finish Activity → killApp → open shade → tap notification. Restores original swipe values (90%,0% → 90%,100%, 4000ms) and killApp which work on main. Keeps the runFlow for permission dialog handling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📜 Description
On API 34+, the notification button in the critical UI test app always launched the permission request dialog, even when permission was already granted. This caused flaky test behavior because the permission dialog would overlay the UI unexpectedly.
The fix adds a
ContextCompat.checkSelfPermissioncheck before launching the permission request. If the permission is already granted, it skips the request and directly posts the notification.💡 Motivation and Context
Critical UI tests on API 34 emulators were flaky because the notification permission request was being triggered even when the permission was already granted from a previous test run or interaction. This caused the permission dialog to appear unexpectedly, interfering with test assertions.
💚 How did you test it?
Ran the critical UI tests on an API 34 emulator and verified the notification flow works correctly both when permission is already granted and when it needs to be requested.
📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps
None