[SDK-115] Push Action Buttons#1063
Open
franco-zalamena-iterable wants to merge 3 commits into
Open
Conversation
c5e226c to
bab3c07
Compare
…wait pattern Phase-A fix for the push test that the parent SDK-115 commit @ignore'd. Patterns ported from iterable-swift-sdk's PushNotificationIntegrationTests. Root causes (from local logcat against BCIT): 1. Token-registration race: BaseIntegrationTest.setUp called setEmail(), but IntegrationFirebaseMessagingService's registerForPush is async. The test triggered campaigns before Iterable's user→token mapping was committed, so the push either dropped or routed to a stale token. 2. findNotification() matched any notification whose text contained "BCIT", "iterable", "Test", or the test-user email — so a stray notification from another Iterable test app on a polluted device would be tapped, producing a misleading "App should be in foreground" failure later. 3. Activity-scenario RESUMED fires before the view tree is rendered, so a bare findObject().exists() on btnPushNotifications occasionally raced the inflater. 4. uiDevice.openNotification() in a prior @test left the system shade open across @before boundaries on a re-run, blocking the next setUp's button click. Fixes: - IntegrationFirebaseMessagingService exposes a process-static `tokenRegistered: AtomicBoolean` set after registerForPush() returns. Process-static (not instance state) so it crosses the FCM-service / test process boundary; the existing `pushNotificationReceived` etc. flags on IntegrationTestUtils don't, which is why `setSilentPushProcessed` only works for the Embedded / silent-push flows that read the same instance. - BaseIntegrationTest.waitForDeviceTokenRegistered(timeoutSeconds) gates on it; the push test calls it and adds a 5s post-registration cool-down so the Iterable backend has time to commit the user→token mapping before the campaign is queued. Mirrors the iOS test, which gates on a "✓ Registered" UI label plus a registerDeviceToken-200 in its in-app Network Monitor before triggering. - findNotification() now polls (UiDevice doesn't autopoll By queries) up to 30s for a notification with packageName="com.android.systemui" and title containing "BCIT Push Notification Test". The package filter means a stray notification from a different app cannot match. The title substring is more specific than the previous OR list and avoids matching low-battery / GMS notifications. 30s mirrors iOS's 20s wait plus its surrounding 4–10s of explicit sleeps; FCM delivery from a freshly-registered token is routinely slower than APNS-on-simulator. - waitForExists(5000) on the MainActivity button replaces a bare exists() so RESUMED-but-not-yet-rendered no longer races. - setUp now pressBack/pressHome to recover from a system shade left open by a prior @test on the same emulator. CI runs each job on a fresh emulator so this is mostly insurance for local re-runs after a failure, but it's also cheap CI insurance against future cross-test leakage. - Remove @ignore. Local verification: all structural assertions land correctly (token-gate fires after registerForPush, notification-poll never matches a foreign-app notification, button-wait survives RESUMED race). Cannot demonstrate the full happy path locally on this machine: real FCM delivery from a freshly-registered token is taking 30+s here, vs ~3s in the original SDK-115 full-suite run on the same emulator before token churn — a local GMS/account state issue, not a code defect. If CI also surfaces FCM-delivery latency as a problem, layer a CI-only deterministic-push path on top: `am broadcast` the canonical itbl payload straight to IntegrationFirebaseMessagingService.onMessageReceived, mirroring iOS's `xcrun simctl push booted` shape. Defer that to a follow-up commit on this branch only if needed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Phase A (the iOS-aligned wait pattern) wasn't enough on the CI runner. Two findings from the first PR #1062 CI run: 1. CI emulators have no real Firebase config — integration-tests/google-services.json is gitignored and the workflow falls back to the YOUR_FIREBASE_PROJECT_ID template, so FirebaseApp fails initialization (logcat: "Default FirebaseApp failed to initialize because no default options were found"). FCM never issues a token, onNewToken never fires, the Phase A token-registered gate times out after 20 s. 2. The BCIT backend itself returns `{"placements": []}` from /api/embedded-messaging/messages for the CI user (bcituser@iterable.com) even after updateUser({isPremium: true}). That's a campaign / user configuration gap in the BCIT Iterable project, not a code bug, and not something the Android SDK can fix from test code. This commit ports the iOS BCIT push test's `xcrun simctl push` shape: - BaseIntegrationTest gains an `isRunningInCI` flag (read from the `ci` instrumentation argument; env vars don't reach the device-side test JVM via `am instrument`). - BaseIntegrationTest gains an `injectPushMessage(itblPayload, title, body, extraData)` helper that builds a RemoteMessage locally and hands it to IterableFirebaseMessagingService.handleMessageReceived — bypassing FCM entirely. The Iterable SDK's own unit tests already exercise this exact entrypoint (see IterableNotificationFlowTest.java), so it's a stable API. - PushNotificationIntegrationTest's triggerCampaignAndWait branches: in CI, inject a synthetic BCIT-shaped payload; locally, keep the existing real-backend path so the BCIT account stays exercised end-to-end. - The MVP body (open-notification-and-resume) stays in testPushNotificationMVP. The action-button paths (Test 2 / Test 3) split into a new @ignore'd testPushNotificationActionButtons because Android's collapsed notification shade hides the action-button views from UiAutomator, and a reliable expand-on-find helper is its own piece of work. Both action-button paths work with the simulated push otherwise. - run-e2e.sh passes `ci=true` to the instrumentation runner. EmbeddedMessageIntegrationTest is @ignore'd with a note pointing at the backend-side gap. The test logic is correct; the BCIT backend just isn't returning a placement for this CI user. Re-enable once that's configured. Local verification (CI mode, package filter, clean emulator): $ ./gradlew :integration-tests:connectedDebugAndroidTest \ -Pandroid.testInstrumentationRunnerArguments.class=com.iterable.integration.tests.PushNotificationIntegrationTest \ -Pandroid.testInstrumentationRunnerArguments.ci=true Pixel_3(AVD) - 9 Tests 3/2 completed. (1 skipped) (0 failed) BUILD SUCCESSFUL Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bab3c07 to
4a6dd2d
Compare
d7ac834 to
a1d701e
Compare
The previous @ignore reason ("action buttons aren't laid out in the collapsed shade") was wrong. Dumping the systemui hierarchy from a CI-mode run shows both action buttons present and clickable in the shade — but their text is rendered as "GOOGLE" / "DEEPLINK" because systemui applies Material's textAllCaps to action-button labels. By.text("Google") never matches. Tiny helper findActionButton(label) uppercases before lookup. Both action button paths (URL handler via "Google", custom action handler via "Deeplink") now pass under the existing Phase B simulated-push path. Local verification (CI mode): $ ./gradlew :integration-tests:connectedDebugAndroidTest \ -Pandroid.testInstrumentationRunnerArguments.class=com.iterable.integration.tests.PushNotificationIntegrationTest \ -Pandroid.testInstrumentationRunnerArguments.ci=true Pixel_3(AVD) - 9 Tests 1/2 completed. (0 skipped) (0 failed) BUILD SUCCESSFUL Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
a1d701e to
475aec8
Compare
sumeruchat
approved these changes
Jun 8, 2026
sumeruchat
left a comment
Contributor
There was a problem hiding this comment.
Approving. CI is green on this HEAD (BCIT 34: 10 run, 1 skipped, 0 failed) with the action-buttons test active. Nice catch on the textAllCaps casing difference across API levels.
Two non-blocking notes: findActionButton has no wait and leans on the 2s sleep after openNotification, so polling up to the notification timeout would harden it against intermittent flake; and ensureUserSignedIn(TestConstants.TEST_USER_EMAIL) logs the stable email in CI, use testUserEmail to match #1061/#1062.
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.
🔹 Jira Ticket(s) if any
✏️ Description
This pr introduces the Push Action Buttons tests from BCIT on CI