Repository navigation
[SDK-792] fix(ios): reject showMessage for an empty or unknown message id - #920
joaodordio wants to merge 4 commits into
Conversation
… compiles against native 3.10.1 The published iterableapi 3.10.1 AAR is compiled with Kotlin 1.9 without jvm-default, so onEmbeddedMessagingSyncSucceeded and onEmbeddedMessagingSyncFailed are abstract to Java implementers. RNIterableAPIModuleImpl did not override them, so the module failed javac. Add no-op overrides that match the native defaults.
Iterable.inAppManager.showMessage called IterableInAppManager.showMessage on the React Native native-modules thread. Since native Android 3.9.0, a host activity that is not a FragmentActivity takes the Dialog path, whose LifecycleRegistry.addObserver call throws IllegalStateException off the main thread and kills the process. - Post the native call with UiThreadUtil.runOnUiThread, matching setAutoDisplayPaused and the native iOS SDK. - Reject when the message id is missing instead of passing null into native (NPE). - Resolve null when the message is dismissed without a URL instead of NPE on toString. - Fix the empty messageId check, which used reference equality. Adds the first JVM unit tests for the Android bridge (Robolectric + Mockito, versions mirrored from iterable-android-sdk) and excludes them from the npm package.
…ge id The iOS bridge logged and returned without settling the promise. Reject with the same messages as the Android bridge.
|
Coverage Impact This PR will not change total coverage. 🚦 See full report on Qlty Cloud »🛟 Help
|
1 new issue
|
| test('showMessage_messageNotInNativeQueue_rejects', async () => { | ||
| // GIVEN an in-app message that is no longer in the native queue | ||
| const message: IterableInAppMessage = IterableInAppMessage.fromDict({ | ||
| messageId: 'message1', | ||
| campaignId: 1234, | ||
| trigger: { type: IterableInAppTriggerType.immediate }, | ||
| }); | ||
| const error = new Error('Could not find message with id: message1'); | ||
|
|
||
| // WHEN the native module rejects the call | ||
| MockRNIterableAPI.showMessage.mockRejectedValueOnce(error); | ||
|
|
||
| // THEN Iterable.inAppManager.showMessage rejects with the native error | ||
| await expect( | ||
| Iterable.inAppManager?.showMessage(message, true) | ||
| ).rejects.toBe(error); | ||
| }); |
There was a problem hiding this comment.
Jest test does not lock either reject message
What the spec says: SDK-792 asks for those two reject strings on iOS, and for Jest coverage in the mock layer if applicable. The strings themselves live in ReactIterableAPI.showMessage (~L387–397), which this test never calls.
Why it conflicts: The test passes for any rejection, including a wrong message or a revert of the Swift change. It does not check the empty-id string. That is allowed by “if applicable” — the mock cannot see the native queue — so this is not a missed acceptance criterion. The test name overclaims what it pins.
Suggested action: Either rename it so it only claims “a native rejection is propagated,” or add a mock-layer case whose expected message is messageId is null or empty. Do not treat this Jest file as proof of the iOS strings; those are in the Swift guards, matched to Android ~L290–296.

📝 Summary
Reject
showMessageon iOS for an empty or unknown message id, matching the Android bridge after #918.🎟️ Jira Ticket: SDK-792
📖 Description
ReactIterableAPI.showMessageloggedITBErrorand returned without calling the resolver or rejecter when the message id was not in the native queue, so the JS promise never settled. An empty id was not checked at all.It now rejects with the same code and messages as Android (
messageId is null or empty,Could not find message with id: <id>), using the samerejecterpattern asgetHtmlInAppContentin this file.Stacked on #918. Branch is cut from #918 so the CHANGELOG lands under the same
## 3.2.1section. The diff shrinks to three files once #918 merges.🧪 How to test?
yarn test(addsshowMessage_messageNotInNativeQueue_rejects, which pins the JS side of the contract)xcodebuild ... -sdk iphonesimulator build, BUILD SUCCEEDED)Iterable.inAppManager.showMessagewith a message that was consumed elsewhere, expect a rejection instead of a hanging promise🧾 Changelog
Added under
## 3.2.1.📚 Docs PR if applicable
Covered by SDK-793.