Skip to content

Commit 1610114

Browse files
committed
Add IAM basic test scaffolding and migrate build tests
1 parent d9c8110 commit 1610114

File tree

2 files changed

+310
-0
lines changed

2 files changed

+310
-0
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package com.onesignal.inAppMessages.internal
2+
3+
import com.onesignal.debug.LogLevel
4+
import com.onesignal.debug.internal.logging.Logging
5+
import com.onesignal.inAppMessages.internal.InAppMessagingHelpers.Companion.buildTestMessageWithRedisplay
6+
import io.kotest.core.spec.style.FunSpec
7+
import io.kotest.matchers.shouldBe
8+
import io.kotest.matchers.shouldNotBe
9+
import java.util.UUID
10+
11+
12+
class InAppMessagesTests : FunSpec({
13+
val IAM_CLICK_ID = "button_id_123"
14+
val LIMIT = 5
15+
val DELAY: Long = 60
16+
17+
// Define message at class level with lazy initialization
18+
val message: InAppMessagingHelpers.OSTestInAppMessageInternal by lazy {
19+
InAppMessagingHelpers.buildTestMessageWithSingleTrigger(
20+
Trigger.OSTriggerKind.SESSION_TIME,
21+
null,
22+
Trigger.OSTriggerOperator.GREATER_THAN_OR_EQUAL_TO.toString(),
23+
3
24+
)
25+
}
26+
27+
beforeAny {
28+
Logging.logLevel = LogLevel.NONE
29+
// TODO: add more from Player Model @BeforeClass in InAppMessagingUnitTests.java
30+
}
31+
32+
beforeTest {
33+
// TODO: add more from Player Model @BeforeTest in InAppMessagingUnitTests.java
34+
}
35+
36+
afterTest {
37+
// TODO: reset back to default: clear timers and clean up helpers
38+
}
39+
40+
test("testBuiltMessage") {
41+
// Given
42+
val messageId = message.messageId
43+
val variants = message.variants
44+
45+
// Then
46+
UUID.fromString(messageId) // Throws if invalid
47+
variants shouldNotBe null
48+
}
49+
50+
test("testBuiltMessageVariants") {
51+
message.variants["android"]?.get("es") shouldBe InAppMessagingHelpers.TEST_SPANISH_ANDROID_VARIANT_ID
52+
message.variants["android"]?.get("en") shouldBe InAppMessagingHelpers.TEST_ENGLISH_ANDROID_VARIANT_ID
53+
}
54+
55+
test("testBuiltMessageReDisplay") {
56+
// Given
57+
val message = buildTestMessageWithRedisplay(LIMIT, DELAY)
58+
59+
// Then
60+
message.redisplayStats.isRedisplayEnabled shouldBe true
61+
message.redisplayStats.displayLimit shouldBe LIMIT
62+
message.redisplayStats.displayDelay shouldBe DELAY
63+
message.redisplayStats.lastDisplayTime shouldBe -1
64+
message.redisplayStats.displayQuantity shouldBe 0
65+
66+
// When
67+
val messageWithoutDisplay: InAppMessagingHelpers.OSTestInAppMessageInternal =
68+
InAppMessagingHelpers.buildTestMessageWithSingleTrigger(
69+
Trigger.OSTriggerKind.SESSION_TIME,
70+
null,
71+
Trigger.OSTriggerOperator.GREATER_THAN_OR_EQUAL_TO.toString(),
72+
3
73+
)
74+
75+
// Then
76+
messageWithoutDisplay.redisplayStats.isRedisplayEnabled shouldBe false
77+
messageWithoutDisplay.redisplayStats.displayLimit shouldBe 1
78+
messageWithoutDisplay.redisplayStats.displayDelay shouldBe 0
79+
messageWithoutDisplay.redisplayStats.lastDisplayTime shouldBe -1
80+
messageWithoutDisplay.redisplayStats.displayQuantity shouldBe 0
81+
}
82+
83+
test("testBuiltMessageRedisplayLimit") {
84+
val message: InAppMessagingHelpers.OSTestInAppMessageInternal =
85+
buildTestMessageWithRedisplay(
86+
LIMIT,
87+
DELAY
88+
)
89+
for (i in 0 until LIMIT) {
90+
message.redisplayStats.shouldDisplayAgain() shouldBe true
91+
message.redisplayStats.incrementDisplayQuantity()
92+
}
93+
message.redisplayStats.incrementDisplayQuantity()
94+
message.redisplayStats.shouldDisplayAgain() shouldBe false
95+
}
96+
97+
98+
test("testBuiltMessageRedisplayDelay") {
99+
// TODO
100+
}
101+
102+
test("testBuiltMessageRedisplayCLickId") {
103+
val message: InAppMessagingHelpers.OSTestInAppMessageInternal =
104+
buildTestMessageWithRedisplay(
105+
LIMIT,
106+
DELAY
107+
)
108+
109+
message.clickedClickIds.isEmpty() shouldBe true
110+
message.isClickAvailable(IAM_CLICK_ID)
111+
112+
message.addClickId(IAM_CLICK_ID)
113+
message.clearClickIds()
114+
115+
message.clickedClickIds.isEmpty() shouldBe true
116+
117+
message.addClickId(IAM_CLICK_ID)
118+
message.addClickId(IAM_CLICK_ID)
119+
message.clickedClickIds.size shouldBe 1
120+
121+
message.isClickAvailable(IAM_CLICK_ID) shouldBe false
122+
123+
val messageWithoutDisplay2: InAppMessagingHelpers.OSTestInAppMessageInternal =
124+
InAppMessagingHelpers.buildTestMessageWithSingleTrigger(
125+
Trigger.OSTriggerKind.SESSION_TIME,
126+
null,
127+
Trigger.OSTriggerOperator.GREATER_THAN_OR_EQUAL_TO.toString(),
128+
3
129+
)
130+
131+
messageWithoutDisplay2.addClickId(IAM_CLICK_ID)
132+
messageWithoutDisplay2.isClickAvailable(IAM_CLICK_ID) shouldBe false
133+
}
134+
})
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package com.onesignal.inAppMessages.internal
2+
3+
import com.onesignal.core.internal.time.ITime
4+
import org.json.JSONArray
5+
import org.json.JSONObject
6+
import java.util.UUID
7+
8+
class InAppMessagingHelpers {
9+
companion object {
10+
const val TEST_SPANISH_ANDROID_VARIANT_ID = "d8cc-11e4-bed1-df8f05be55ba-a4b3gj7f"
11+
const val TEST_ENGLISH_ANDROID_VARIANT_ID = "11e4-bed1-df8f05be55ba-a4b3gj7f-d8cc"
12+
const val IAM_CLICK_ID = "12345678-1234-1234-1234-123456789012"
13+
const val IAM_PAGE_ID = "12345678-1234-ABCD-1234-123456789012"
14+
15+
// Most tests build a test message using only one trigger.
16+
// This convenience method makes it easy to build such a message
17+
internal fun buildTestMessageWithSingleTrigger(kind: Trigger.OSTriggerKind, key: String?, operator: String, value: Any): OSTestInAppMessageInternal {
18+
val triggersJson = basicTrigger(kind, key, operator, value)
19+
return buildTestMessage(triggersJson)
20+
}
21+
22+
private fun buildTestMessage(triggerJson: JSONArray?): OSTestInAppMessageInternal {
23+
return OSTestInAppMessageInternal(basicIAMJSONObject(triggerJson))
24+
}
25+
26+
private fun basicTrigger(
27+
kind: Trigger.OSTriggerKind,
28+
key: String?,
29+
operator: String,
30+
value: Any
31+
): JSONArray {
32+
val triggerJson: JSONObject = object : JSONObject() {
33+
init {
34+
put("id", UUID.randomUUID().toString())
35+
put("kind", kind.toString())
36+
put("property", key)
37+
put("operator", operator)
38+
put("value", value)
39+
}
40+
}
41+
42+
return wrap(wrap(triggerJson))
43+
}
44+
45+
private fun wrap(`object`: Any?): JSONArray {
46+
return object : JSONArray() {
47+
init {
48+
put(`object`)
49+
}
50+
}
51+
}
52+
53+
fun buildTestMessageWithRedisplay(limit: Int, delay: Long): OSTestInAppMessageInternal {
54+
return buildTestMessageWithMultipleDisplays(null, limit, delay)
55+
}
56+
57+
private fun buildTestMessageWithMultipleDisplays(
58+
triggerJson: JSONArray?,
59+
limit: Int,
60+
delay: Long
61+
): OSTestInAppMessageInternal {
62+
val json = basicIAMJSONObject(triggerJson)
63+
json.put("redisplay", object : JSONObject() {
64+
init {
65+
put("limit", limit)
66+
put("delay", delay) //in seconds
67+
}
68+
})
69+
70+
return OSTestInAppMessageInternal(json)
71+
}
72+
73+
private fun basicIAMJSONObject(triggerJson: JSONArray?): JSONObject {
74+
val jsonObject = JSONObject()
75+
jsonObject.put("id", UUID.randomUUID().toString())
76+
jsonObject.put("clickIds", JSONArray(listOf("clickId1", "clickId2", "clickId3")))
77+
// shouldn't hard-code?
78+
jsonObject.put("displayedInSession", true)
79+
jsonObject.put("variants", JSONObject().apply {
80+
put("android", JSONObject().apply {
81+
put("es", TEST_SPANISH_ANDROID_VARIANT_ID)
82+
put("en", TEST_ENGLISH_ANDROID_VARIANT_ID)
83+
})
84+
})
85+
jsonObject.put("max_display_time", 30)
86+
if (triggerJson != null) {
87+
jsonObject.put("triggers", triggerJson)
88+
} else {
89+
jsonObject.put("triggers", JSONArray())
90+
}
91+
jsonObject.put("actions", JSONArray().apply {
92+
put(buildTestActionJson())
93+
})
94+
95+
return jsonObject
96+
}
97+
98+
fun buildTestActionJson(): JSONObject {
99+
return object : JSONObject() {
100+
init {
101+
put("click_type", "button")
102+
put("id", IAM_CLICK_ID)
103+
put("name", "click_name")
104+
put("url", "https://www.onesignal.com")
105+
put("url_target", "webview")
106+
put("close", true)
107+
put("pageId", IAM_PAGE_ID)
108+
put("data", object : JSONObject() {
109+
init {
110+
put("test", "value")
111+
}
112+
})
113+
}
114+
}
115+
}
116+
}
117+
118+
class OSTestInAppMessageInternal(
119+
private val jsonObject: JSONObject
120+
) {
121+
private val inAppMessage: InAppMessage by lazy {
122+
initializeInAppMessage()
123+
}
124+
125+
private fun initializeInAppMessage(): InAppMessage {
126+
val time = object : ITime {
127+
override val currentTimeMillis: Long
128+
get() = System.currentTimeMillis()
129+
}
130+
131+
return InAppMessage(jsonObject, time)
132+
}
133+
134+
val messageId: String
135+
get() = inAppMessage.messageId
136+
137+
val variants: Map<String, Map<String, String>>
138+
get() = inAppMessage.variants
139+
140+
val clickedClickIds: MutableSet<String>
141+
get() = inAppMessage.clickedClickIds
142+
143+
var isDisplayedInSession: Boolean
144+
get() = inAppMessage.isDisplayedInSession
145+
set(value) {
146+
inAppMessage.isDisplayedInSession = value
147+
}
148+
149+
internal val redisplayStats: InAppMessageRedisplayStats
150+
get() = inAppMessage.redisplayStats
151+
152+
// Extract limit and delay from the JSON object
153+
private val redisplayLimit: Int
154+
get() = jsonObject.optJSONObject("redisplay")?.optInt("limit", -1) ?: -1
155+
156+
private val redisplayDelay: Long
157+
get() = jsonObject.optJSONObject("redisplay")?.optLong("delay", -1L) ?: -1L
158+
159+
fun isClickAvailable(clickId: String?): Boolean {
160+
return !clickedClickIds.contains(clickId)
161+
}
162+
163+
fun addClickId(clickId: String) {
164+
clickedClickIds.add(clickId)
165+
}
166+
167+
fun clearClickIds() {
168+
clickedClickIds.clear()
169+
}
170+
171+
override fun toString(): String {
172+
return "OSTestInAppMessageInternal(jsonObject=$jsonObject, redisplayLimit=$redisplayLimit, redisplayDelay=$redisplayDelay)"
173+
}
174+
}
175+
}
176+

0 commit comments

Comments
 (0)