Repository navigation
[SDK-789] fix(android): show in-app messages on the main thread and compile against native 3.10.1 #918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SDK-789] fix(android): show in-app messages on the main thread and compile against native 3.10.1 #918
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| package com.iterable.iterableapi; | ||
|
|
||
| import static org.junit.Assert.assertNull; | ||
| import static org.junit.Assert.assertSame; | ||
| import static org.mockito.ArgumentMatchers.any; | ||
| import static org.mockito.ArgumentMatchers.anyBoolean; | ||
| import static org.mockito.ArgumentMatchers.eq; | ||
| import static org.mockito.ArgumentMatchers.isNull; | ||
| import static org.mockito.Mockito.doAnswer; | ||
| import static org.mockito.Mockito.mock; | ||
| import static org.mockito.Mockito.never; | ||
| import static org.mockito.Mockito.verify; | ||
| import static org.mockito.Mockito.when; | ||
| import static org.robolectric.Shadows.shadowOf; | ||
|
|
||
| import android.net.Uri; | ||
| import android.os.Looper; | ||
|
|
||
| import com.facebook.react.bridge.Promise; | ||
| import com.facebook.react.bridge.ReactApplicationContext; | ||
| import com.iterable.reactnative.RNIterableAPIModuleImpl; | ||
|
|
||
| import org.junit.After; | ||
| import org.junit.Before; | ||
| import org.junit.Test; | ||
| import org.junit.runner.RunWith; | ||
| import org.robolectric.RobolectricTestRunner; | ||
| import org.robolectric.annotation.Config; | ||
|
|
||
| import java.util.concurrent.atomic.AtomicReference; | ||
|
|
||
| @RunWith(RobolectricTestRunner.class) | ||
| @Config(sdk = 34) | ||
| public class RNIterableAPIModuleImplShowMessageTest { | ||
|
|
||
| private static final String MESSAGE_ID = "message-id"; | ||
|
|
||
| private IterableApi originalApi; | ||
| private IterableInAppManager inAppManager; | ||
| private IterableInAppMessage message; | ||
| private Promise promise; | ||
| private RNIterableAPIModuleImpl module; | ||
|
|
||
| @Before | ||
| public void setUp() { | ||
| originalApi = IterableApi.sharedInstance; | ||
| IterableApi api = mock(IterableApi.class); | ||
| inAppManager = mock(IterableInAppManager.class); | ||
| message = mock(IterableInAppMessage.class); | ||
| promise = mock(Promise.class); | ||
| when(api.getInAppManager()).thenReturn(inAppManager); | ||
| when(inAppManager.getMessageById(MESSAGE_ID)).thenReturn(message); | ||
| IterableApi.sharedInstance = api; | ||
| module = new RNIterableAPIModuleImpl(mock(ReactApplicationContext.class)); | ||
| } | ||
|
|
||
| @After | ||
| public void tearDown() { | ||
| IterableApi.sharedInstance = originalApi; | ||
| } | ||
|
|
||
| @Test | ||
| public void showMessageFromBridgeThreadDisplaysOnMainThread() throws InterruptedException { | ||
| final AtomicReference<Thread> displayThread = new AtomicReference<>(); | ||
| doAnswer(invocation -> { | ||
| displayThread.set(Thread.currentThread()); | ||
| return null; | ||
| }).when(inAppManager).showMessage(eq(message), eq(true), any(IterableHelper.IterableUrlCallback.class)); | ||
|
|
||
| Thread bridgeThread = new Thread(() -> module.showMessage(MESSAGE_ID, true, promise)); | ||
| bridgeThread.start(); | ||
| bridgeThread.join(); | ||
|
|
||
| assertNull(displayThread.get()); | ||
|
|
||
| shadowOf(Looper.getMainLooper()).idle(); | ||
|
|
||
| assertSame(Looper.getMainLooper().getThread(), displayThread.get()); | ||
| } | ||
|
Comment on lines
+63
to
+79
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What the spec says: SDK-789 is that hop. SDK-790 requires :iterable_react-native-sdk:testDebugUnitTest on pull requests to master. This PRβs GitHub Unit tests job is Jest and succeeded. ci.yml did not run. Why it conflicts: The automated proof of the crash fix is the local Gradle command in the PR body. A later change can remove the hop and the checks that actually ran on #918 stay green. SDK-790 is the ticket that closes that gap; the test itself is the right check for this bridge. Suggested action: Land SDK-790 so this suite runs on master pull requests before 3.2.1 is published. #918 does not need a CI change of its own. |
||
|
|
||
| @Test | ||
| public void showMessageRejectsWhenMessageIsMissing() { | ||
| module.showMessage("missing", true, promise); | ||
| shadowOf(Looper.getMainLooper()).idle(); | ||
|
|
||
| verify(promise).reject("", "Could not find message with id: missing"); | ||
| verify(inAppManager, never()).showMessage(any(IterableInAppMessage.class), anyBoolean(), any(IterableHelper.IterableUrlCallback.class)); | ||
| } | ||
|
|
||
| @Test | ||
| public void showMessageRejectsWhenMessageIdIsEmpty() { | ||
| module.showMessage(new String(""), true, promise); | ||
| shadowOf(Looper.getMainLooper()).idle(); | ||
|
|
||
| verify(promise).reject("", "messageId is null or empty"); | ||
| verify(inAppManager, never()).showMessage(any(IterableInAppMessage.class), anyBoolean(), any(IterableHelper.IterableUrlCallback.class)); | ||
| } | ||
|
|
||
| @Test | ||
| public void showMessageResolvesClickedUrl() { | ||
| stubClickWith(Uri.parse("https://iterable.com")); | ||
|
|
||
| module.showMessage(MESSAGE_ID, false, promise); | ||
| shadowOf(Looper.getMainLooper()).idle(); | ||
|
|
||
| verify(promise).resolve("https://iterable.com"); | ||
| } | ||
|
|
||
| @Test | ||
| public void showMessageResolvesNullWhenClosedWithoutUrl() { | ||
| stubClickWith(null); | ||
|
|
||
| module.showMessage(MESSAGE_ID, false, promise); | ||
| shadowOf(Looper.getMainLooper()).idle(); | ||
|
|
||
| verify(promise).resolve(isNull()); | ||
| } | ||
|
|
||
| private void stubClickWith(final Uri url) { | ||
| doAnswer(invocation -> { | ||
| IterableHelper.IterableUrlCallback callback = invocation.getArgument(2); | ||
| callback.execute(url); | ||
| return null; | ||
| }).when(inAppManager).showMessage(eq(message), eq(false), any(IterableHelper.IterableUrlCallback.class)); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function with high complexity (count = 6): showMessage [qlty:function-complexity]