@@ -33,6 +33,11 @@ abstract class BaseIntegrationTest {
3333 // URL handler tracking for tests
3434 private val urlHandlerCalled = AtomicBoolean (false )
3535 private val lastHandledUrl = AtomicReference <String ?>(null )
36+
37+ // Custom action handler tracking for tests
38+ private val customActionHandlerCalled = AtomicBoolean (false )
39+ private val lastHandledAction = AtomicReference < com.iterable.iterableapi.IterableAction ? > (null )
40+ private val lastHandledActionType = AtomicReference <String ?>(null )
3641
3742 @Before
3843 open fun setUp () {
@@ -41,6 +46,7 @@ abstract class BaseIntegrationTest {
4146
4247 // Reset tracking flags
4348 resetUrlHandlerTracking()
49+ resetCustomActionHandlerTracking()
4450
4551 // Set test mode flag to prevent MainActivity from initializing SDK
4652 // This ensures our test config (with test handlers) is the one used
@@ -71,17 +77,26 @@ abstract class BaseIntegrationTest {
7177 testUtils.setInAppMessageDisplayed(true )
7278 com.iterable.iterableapi.IterableInAppHandler .InAppResponse .SHOW
7379 }
74- .setCustomActionHandler { action, context ->
75- // Handle custom actions during tests
76- Log .d(" BaseIntegrationTest" , " Custom action triggered: $action " )
77- true
78- }
80+ .setCustomActionHandler(object : com.iterable.iterableapi.IterableCustomActionHandler {
81+ override fun handleIterableCustomAction (
82+ action : com.iterable.iterableapi.IterableAction ,
83+ actionContext : com.iterable.iterableapi.IterableActionContext
84+ ): Boolean {
85+ // Handle custom actions during tests
86+ val actionType = action.getType()
87+ Log .d(" BaseIntegrationTest" , " Custom action triggered: type=$actionType , action=$action , source=${actionContext.source} " )
88+ customActionHandlerCalled.set(true )
89+ lastHandledAction.set(action)
90+ lastHandledActionType.set(actionType)
91+ return false
92+ }
93+ })
7994 .setUrlHandler { url, context ->
8095 // Handle URLs during tests
8196 Log .d(" BaseIntegrationTest" , " URL handler triggered: $url " )
8297 urlHandlerCalled.set(true )
8398 lastHandledUrl.set(url.toString())
84- true
99+ false
85100 }
86101 .build()
87102
@@ -110,6 +125,21 @@ abstract class BaseIntegrationTest {
110125 }
111126 }
112127
128+ /* *
129+ * Check if notification permission is granted
130+ */
131+ protected fun hasNotificationPermission (): Boolean {
132+ return if (android.os.Build .VERSION .SDK_INT >= android.os.Build .VERSION_CODES .TIRAMISU ) {
133+ androidx.core.content.ContextCompat .checkSelfPermission(
134+ context,
135+ android.Manifest .permission.POST_NOTIFICATIONS
136+ ) == android.content.pm.PackageManager .PERMISSION_GRANTED
137+ } else {
138+ // For Android 12 and below, notifications are enabled by default
139+ androidx.core.app.NotificationManagerCompat .from(context).areNotificationsEnabled()
140+ }
141+ }
142+
113143 /* *
114144 * Wait for a condition to be true with timeout
115145 */
@@ -177,4 +207,36 @@ abstract class BaseIntegrationTest {
177207 urlHandlerCalled.get()
178208 }, timeoutSeconds)
179209 }
210+
211+ /* *
212+ * Reset custom action handler tracking
213+ */
214+ protected fun resetCustomActionHandlerTracking () {
215+ customActionHandlerCalled.set(false )
216+ lastHandledAction.set(null )
217+ lastHandledActionType.set(null )
218+ }
219+
220+ /* *
221+ * Get the last action handled by the custom action handler
222+ */
223+ protected fun getLastHandledAction (): com.iterable.iterableapi.IterableAction ? {
224+ return lastHandledAction.get()
225+ }
226+
227+ /* *
228+ * Get the last action type handled by the custom action handler
229+ */
230+ protected fun getLastHandledActionType (): String? {
231+ return lastHandledActionType.get()
232+ }
233+
234+ /* *
235+ * Wait for custom action handler to be called
236+ */
237+ protected fun waitForCustomActionHandler (timeoutSeconds : Long = TIMEOUT_SECONDS ): Boolean {
238+ return waitForCondition({
239+ customActionHandlerCalled.get()
240+ }, timeoutSeconds)
241+ }
180242}
0 commit comments