Skip to content

Commit 8f43866

Browse files
author
“Akshay
committed
[SDK-7]-BCIT Push Base
Activity created; utility function added in BaseIntegrationTest; Dedicated PushNotification Test file with one mvp function; Constants for new campaign id from Mobile SDK do not Delete project; An actvity for push modified
1 parent 42b4e11 commit 8f43866

File tree

5 files changed

+267
-21
lines changed

5 files changed

+267
-21
lines changed

integration-tests/src/androidTest/java/com/iterable/integration/tests/BaseIntegrationTest.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,18 @@ abstract class BaseIntegrationTest {
141141
testUtils.triggerCampaignViaAPI(campaignId, recipientEmail, dataFields, callback)
142142
}
143143

144+
/**
145+
* Trigger a push campaign via Iterable API
146+
*/
147+
protected fun triggerPushCampaignViaAPI(
148+
campaignId: Int,
149+
recipientEmail: String = TestConstants.TEST_USER_EMAIL,
150+
dataFields: Map<String, Any>? = null,
151+
callback: ((Boolean) -> Unit)? = null
152+
) {
153+
testUtils.triggerPushCampaignViaAPI(campaignId, recipientEmail, dataFields, callback)
154+
}
155+
144156

145157
/**
146158
* Reset URL handler tracking
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
package com.iterable.integration.tests
2+
3+
import android.content.Intent
4+
import android.util.Log
5+
import androidx.lifecycle.Lifecycle
6+
import androidx.test.core.app.ActivityScenario
7+
import androidx.test.ext.junit.runners.AndroidJUnit4
8+
import androidx.test.platform.app.InstrumentationRegistry
9+
import androidx.test.uiautomator.UiDevice
10+
import androidx.test.uiautomator.UiSelector
11+
import androidx.test.uiautomator.By
12+
import com.iterable.iterableapi.IterableApi
13+
import com.iterable.integration.tests.activities.PushNotificationTestActivity
14+
import org.awaitility.Awaitility
15+
import org.junit.After
16+
import org.junit.Assert
17+
import org.junit.Before
18+
import org.junit.Test
19+
import org.junit.runner.RunWith
20+
import java.util.concurrent.TimeUnit
21+
22+
@RunWith(AndroidJUnit4::class)
23+
class PushNotificationIntegrationTest : BaseIntegrationTest() {
24+
25+
companion object {
26+
private const val TAG = "PushNotificationIntegrationTest"
27+
private const val TEST_PUSH_CAMPAIGN_ID = TestConstants.TEST_PUSH_CAMPAIGN_ID
28+
}
29+
30+
private lateinit var uiDevice: UiDevice
31+
private lateinit var mainActivityScenario: ActivityScenario<MainActivity>
32+
33+
@Before
34+
override fun setUp() {
35+
Log.d(TAG, "🔧 Test setup starting...")
36+
37+
uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
38+
39+
// Call super.setUp() to initialize SDK with BaseIntegrationTest's config
40+
// This sets test mode flag and initializes SDK with test handlers (including urlHandler)
41+
super.setUp()
42+
43+
Log.d(TAG, "🔧 Base setup complete, SDK initialized with test handlers")
44+
45+
// Disable in-app auto display and clear existing messages BEFORE launching app
46+
// This prevents in-app messages from obscuring the push notification test screen
47+
Log.d(TAG, "🔧 Disabling in-app auto display and clearing existing messages...")
48+
IterableApi.getInstance().inAppManager.setAutoDisplayPaused(true)
49+
Log.d(TAG, "✅ In-app auto display paused")
50+
51+
// Clear all existing in-app messages
52+
IterableApi.getInstance().inAppManager.messages.forEach {
53+
Log.d(TAG, "Clearing existing in-app message: ${it.messageId}")
54+
IterableApi.getInstance().inAppManager.removeMessage(it)
55+
}
56+
Log.d(TAG, "✅ All in-app messages cleared")
57+
58+
Log.d(TAG, "🔧 MainActivity will skip initialization due to test mode flag")
59+
60+
// Now launch the app flow with custom handlers already configured
61+
launchAppAndNavigateToPushNotificationTesting()
62+
}
63+
64+
@After
65+
override fun tearDown() {
66+
super.tearDown()
67+
}
68+
69+
private fun launchAppAndNavigateToPushNotificationTesting() {
70+
// Step 1: Launch MainActivity (the home page)
71+
Log.d(TAG, "🔧 Step 1: Launching MainActivity...")
72+
val mainIntent = Intent(InstrumentationRegistry.getInstrumentation().targetContext, MainActivity::class.java)
73+
mainActivityScenario = ActivityScenario.launch(mainIntent)
74+
75+
// Wait for MainActivity to be ready
76+
Awaitility.await()
77+
.atMost(5, TimeUnit.SECONDS)
78+
.pollInterval(500, TimeUnit.MILLISECONDS)
79+
.until {
80+
val state = mainActivityScenario.state
81+
Log.d(TAG, "🔧 MainActivity state: $state")
82+
state == Lifecycle.State.RESUMED
83+
}
84+
85+
Log.d(TAG, "🔧 MainActivity is ready!")
86+
87+
// Step 2: Click the "Push Notifications" button to navigate to PushNotificationTestActivity
88+
Log.d(TAG, "🔧 Step 2: Clicking 'Push Notifications' button...")
89+
val pushButton = uiDevice.findObject(UiSelector().resourceId("com.iterable.integration.tests:id/btnPushNotifications"))
90+
if (pushButton.exists()) {
91+
pushButton.click()
92+
Log.d(TAG, "🔧 Clicked Push Notifications button successfully")
93+
} else {
94+
Log.e(TAG, "❌ Push Notifications button not found!")
95+
Assert.fail("Push Notifications button not found in MainActivity")
96+
}
97+
98+
// Step 3: Wait for PushNotificationTestActivity to load
99+
Log.d(TAG, "🔧 Step 3: Waiting for PushNotificationTestActivity to load...")
100+
Thread.sleep(2000) // Give time for navigation
101+
102+
Log.d(TAG, "🔧 App navigation complete: Now on PushNotificationTestActivity!")
103+
}
104+
105+
@Test
106+
fun testPushNotificationMVP() {
107+
// Step 1: Ensure user is signed in
108+
Log.d(TAG, "📧 Step 1: Ensuring user is signed in...")
109+
val userSignedIn = testUtils.ensureUserSignedIn(TestConstants.TEST_USER_EMAIL)
110+
Assert.assertTrue("User should be signed in", userSignedIn)
111+
Log.d(TAG, "✅ User signed in successfully: ${TestConstants.TEST_USER_EMAIL}")
112+
113+
// Step 2: Trigger push notification campaign via API
114+
Log.d(TAG, "🎯 Step 2: Triggering push notification campaign via API...")
115+
Log.d(TAG, "Campaign ID: $TEST_PUSH_CAMPAIGN_ID")
116+
Log.d(TAG, "User Email: ${TestConstants.TEST_USER_EMAIL}")
117+
118+
var campaignTriggered = false
119+
val latch = java.util.concurrent.CountDownLatch(1)
120+
121+
triggerPushCampaignViaAPI(TEST_PUSH_CAMPAIGN_ID, TestConstants.TEST_USER_EMAIL, null) { success ->
122+
campaignTriggered = success
123+
Log.d(TAG, "🎯 Push campaign trigger result: $success")
124+
if (!success) {
125+
val errorMessage = testUtils.getLastErrorMessage()
126+
Log.w(TAG, "⚠️ Push campaign trigger failed: $errorMessage")
127+
}
128+
latch.countDown()
129+
}
130+
131+
// Wait for API call to complete (up to 10 seconds for CI)
132+
val apiCallCompleted = latch.await(10, java.util.concurrent.TimeUnit.SECONDS)
133+
Log.d(TAG, "🎯 API call completed: $apiCallCompleted, success: $campaignTriggered")
134+
135+
if (!apiCallCompleted) {
136+
Log.e(TAG, "❌ API call did not complete in time")
137+
Assert.fail("Push campaign trigger API call did not complete in time")
138+
return
139+
}
140+
141+
if (!campaignTriggered) {
142+
val errorMessage = testUtils.getLastErrorMessage()
143+
Log.e(TAG, "❌ Push campaign trigger FAILED: $errorMessage")
144+
Log.e(TAG, "❌ Cannot proceed with test - no push notification will be available")
145+
Assert.fail("Push campaign trigger failed: $errorMessage. Check API key and campaign configuration.")
146+
return
147+
}
148+
149+
Log.d(TAG, "✅ Push campaign triggered successfully, waiting for notification...")
150+
151+
// Step 3: Wait for push notification to arrive (give time for FCM delivery)
152+
Log.d(TAG, "⏳ Step 3: Waiting for push notification to arrive...")
153+
Thread.sleep(5000) // Give time for FCM to deliver the notification
154+
155+
// Step 4: Open notification drawer and verify notification is present
156+
Log.d(TAG, "📱 Step 4: Opening notification drawer...")
157+
uiDevice.openNotification()
158+
Thread.sleep(2000) // Wait for notification drawer to open
159+
160+
// Step 5: Find and interact with the notification
161+
Log.d(TAG, "🔍 Step 5: Looking for push notification in notification drawer...")
162+
163+
// Try to find notification by text (common notification text patterns)
164+
var notificationFound = false
165+
var notification = uiDevice.findObject(By.textContains("Iterable"))
166+
?: uiDevice.findObject(By.textContains("iterable"))
167+
?: uiDevice.findObject(By.textContains("Test"))
168+
169+
if (notification == null) {
170+
// Try to find any notification that might be from our app
171+
val notifications = uiDevice.findObjects(By.res("com.android.systemui:id/notification_stack_scroller"))
172+
if (notifications.isNotEmpty()) {
173+
notification = notifications.first()
174+
notificationFound = true
175+
}
176+
} else {
177+
notificationFound = true
178+
}
179+
180+
if (!notificationFound || notification == null) {
181+
Log.e(TAG, "❌ Push notification not found in notification drawer")
182+
uiDevice.pressBack() // Close notification drawer
183+
Assert.fail("Push notification not found in notification drawer. Check FCM configuration and campaign setup.")
184+
return
185+
}
186+
187+
Log.d(TAG, "✅ Push notification found in notification drawer")
188+
189+
// Step 6: Click on the notification to open it
190+
Log.d(TAG, "🎯 Step 6: Clicking on push notification...")
191+
notification.click()
192+
Thread.sleep(2000) // Wait for app to open
193+
194+
// Step 7: Verify URL handler was called (if notification has action)
195+
Log.d(TAG, "🎯 Step 7: Verifying URL handler was called after notification click...")
196+
197+
val urlHandlerCalled = waitForUrlHandler(timeoutSeconds = 5)
198+
if (urlHandlerCalled) {
199+
// Step 8: Verify the correct URL was handled
200+
val handledUrl = getLastHandledUrl()
201+
Log.d(TAG, "🎯 URL handler received: $handledUrl")
202+
203+
Assert.assertNotNull("Handled URL should not be null", handledUrl)
204+
Log.d(TAG, "✅ URL handler was called with URL: $handledUrl")
205+
} else {
206+
Log.d(TAG, "ℹ️ URL handler was not called - notification may not have an action URL")
207+
// This is acceptable if the notification doesn't have a deep link action
208+
}
209+
210+
Log.d(TAG, "✅✅✅ Test completed successfully! All steps passed.")
211+
}
212+
}
213+

integration-tests/src/main/java/com/iterable/integration/tests/TestConstants.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ object TestConstants {
1212

1313
// Test campaign IDs - these should be configured in your Iterable project
1414
const val TEST_INAPP_CAMPAIGN_ID = 14332357
15-
const val TEST_PUSH_CAMPAIGN_ID = 14332358
15+
const val TEST_PUSH_CAMPAIGN_ID = 15671239
1616
const val TEST_EMBEDDED_CAMPAIGN_ID = 14332359
1717

1818
// Test placement IDs

integration-tests/src/main/java/com/iterable/integration/tests/activities/PushNotificationTestActivity.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.iterable.integration.tests.activities
22

33
import android.os.Bundle
44
import android.util.Log
5+
import android.widget.TextView
56
import androidx.appcompat.app.AppCompatActivity
67
import com.iterable.integration.tests.R
78

@@ -11,12 +12,23 @@ class PushNotificationTestActivity : AppCompatActivity() {
1112
private const val TAG = "PushNotificationTest"
1213
}
1314

15+
private lateinit var statusTextView: TextView
16+
1417
override fun onCreate(savedInstanceState: Bundle?) {
1518
super.onCreate(savedInstanceState)
1619
setContentView(R.layout.activity_push_notification_test)
1720

1821
Log.d(TAG, "Push Notification Test Activity started")
1922

20-
// TODO: Implement push notification test UI and logic
23+
initializeViews()
24+
updateStatus("Ready to test push notifications")
25+
}
26+
27+
private fun initializeViews() {
28+
statusTextView = findViewById(R.id.status_text)
29+
}
30+
31+
private fun updateStatus(status: String) {
32+
statusTextView.text = "Status: $status"
2133
}
2234
}
Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,34 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
34
android:layout_width="match_parent"
4-
android:layout_height="match_parent"
5-
android:orientation="vertical"
6-
android:padding="16dp"
7-
android:gravity="center">
5+
android:layout_height="match_parent">
86

9-
<TextView
10-
android:layout_width="wrap_content"
7+
<LinearLayout
8+
android:layout_width="match_parent"
119
android:layout_height="wrap_content"
12-
android:text="Push Notification Tests"
13-
android:textSize="24sp"
14-
android:textStyle="bold"
15-
android:layout_marginBottom="32dp"
16-
android:gravity="center" />
10+
android:orientation="vertical"
11+
android:padding="16dp">
1712

18-
<TextView
19-
android:layout_width="wrap_content"
20-
android:layout_height="wrap_content"
21-
android:text="Push notification tests will be implemented here"
22-
android:textSize="16sp"
23-
android:gravity="center" />
13+
<TextView
14+
android:layout_width="wrap_content"
15+
android:layout_height="wrap_content"
16+
android:text="Push Notification Tests"
17+
android:textSize="24sp"
18+
android:textStyle="bold"
19+
android:layout_marginBottom="16dp"
20+
android:gravity="center"
21+
android:layout_gravity="center" />
22+
23+
<TextView
24+
android:id="@+id/status_text"
25+
android:layout_width="match_parent"
26+
android:layout_height="wrap_content"
27+
android:text="Status: Ready"
28+
android:textSize="14sp"
29+
android:padding="8dp"
30+
android:background="#F0F0F0"
31+
android:layout_marginBottom="16dp" />
2432

25-
</LinearLayout>
33+
</LinearLayout>
34+
</ScrollView>

0 commit comments

Comments
 (0)