[SDK-115] BCIT push test on CI#1062
Open
franco-zalamena-iterable wants to merge 2 commits into
Open
Conversation
franco-zalamena-iterable
added a commit
that referenced
this pull request
Jun 2, 2026
…ger BCIT The `branches:` key under `pull_request:` filters by the PR's *target* branch, not its head — so PRs targeting long-lived integration branches (e.g. the followup #1062 targeting SDK-115-bcit-ci) silently skipped this workflow. Path filters still gate which PRs actually fire it; only PRs that touch integration-tests / iterableapi(-ui) / the workflow / the run-e2e.sh script will trigger. Push trigger keeps `branches: [master]` so we don't double-run on every feature branch's push events alongside its PR run. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
c51ba9c to
911f442
Compare
franco-zalamena-iterable
added a commit
that referenced
this pull request
Jun 2, 2026
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>
911f442 to
c5e226c
Compare
c5e226c to
bab3c07
Compare
3 tasks
…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
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 uses the pr #1061 as a base, we are adding push notifiction testing from BCIT on this branch