diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fa1d83b2..9a82ae61a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Fixes - Fixed `Iterable.trackPushOpenWithCampaignId` on Android so the `appAlreadyRunning` argument is forwarded to the native SDK instead of always being sent as `false`. +- `Iterable.inAppManager.showMessage` now rejects on iOS when the message id is empty or no longer in the native queue, matching Android. Previously the promise never settled. ### Updates diff --git a/ios/RNIterableAPI/ReactIterableAPI.swift b/ios/RNIterableAPI/ReactIterableAPI.swift index 958f15691..3a9185774 100644 --- a/ios/RNIterableAPI/ReactIterableAPI.swift +++ b/ios/RNIterableAPI/ReactIterableAPI.swift @@ -410,8 +410,16 @@ import React rejecter: RCTPromiseRejectBlock ) { ITBInfo() + guard !messageId.isEmpty else { + ITBError("messageId is null or empty") + rejecter("", "messageId is null or empty", NSError(domain: "", code: 0, userInfo: nil)) + return + } guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else { ITBError("Could not find message with id: \(messageId)") + rejecter( + "", "Could not find message with id: \(messageId)", + NSError(domain: "", code: 0, userInfo: nil)) return } IterableAPI.inAppManager.show(message: message, consume: consume) { (url) in diff --git a/src/__tests__/IterableInApp.test.ts b/src/__tests__/IterableInApp.test.ts index ca48934da..98dbf238e 100644 --- a/src/__tests__/IterableInApp.test.ts +++ b/src/__tests__/IterableInApp.test.ts @@ -328,6 +328,25 @@ describe('Iterable In App', () => { }); }); + test('showMessage_nativeRejects_propagatesRejectionToJs', async () => { + // JS contract only: the native rejection itself is implemented in the iOS and Android bridges + // 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); + }); + test('removeMessage_params_methodCalledWithParams', () => { // GIVEN an in-app message const messageDict = {