Skip to content

Commit 8bf8651

Browse files
committed
[User Model] Notifications Unit Tests
* Added various unit tests for notifications module * removed high level unittest module from solution
1 parent 78383da commit 8bf8651

File tree

117 files changed

+1857
-24509
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+1857
-24509
lines changed

OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/NotificationReceivedEvent.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ internal class NotificationReceivedEvent(
1010
var effectiveNotification: Notification? = notification
1111

1212
override fun complete(notification: INotification?) {
13-
effectiveNotification = notification as Notification
13+
effectiveNotification = notification as Notification?
1414
}
1515
}

OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/generation/impl/NotificationGenerationProcessor.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.onesignal.notifications.internal.generation.impl
22

33
import android.content.Context
44
import com.onesignal.common.AndroidUtils
5+
import com.onesignal.common.safeString
56
import com.onesignal.core.internal.application.IApplicationService
67
import com.onesignal.core.internal.config.ConfigModelStore
78
import com.onesignal.core.internal.time.ITime
@@ -15,7 +16,6 @@ import com.onesignal.notifications.internal.display.INotificationDisplayer
1516
import com.onesignal.notifications.internal.generation.INotificationGenerationProcessor
1617
import com.onesignal.notifications.internal.lifecycle.INotificationLifecycleService
1718
import com.onesignal.notifications.internal.summary.INotificationSummaryManager
18-
import com.onesignal.session.internal.session.ISessionService
1919
import kotlinx.coroutines.delay
2020
import kotlinx.coroutines.withTimeout
2121
import org.json.JSONException
@@ -32,7 +32,6 @@ internal class NotificationGenerationProcessor(
3232
private val _dataController: INotificationRepository,
3333
private val _notificationSummaryManager: INotificationSummaryManager,
3434
private val _lifecycleService: INotificationLifecycleService,
35-
private val _sessionService: ISessionService,
3635
private val _time: ITime
3736
) : INotificationGenerationProcessor {
3837

@@ -229,7 +228,7 @@ internal class NotificationGenerationProcessor(
229228

230229
_dataController.createNotification(
231230
customJSON.optString("i"),
232-
jsonPayload.optString("grp"),
231+
jsonPayload.safeString("grp"),
233232
collapseKey,
234233
notificationJob.isNotificationToDisplay, // When notification was displayed, count any notifications with duplicated android notification ids as dismissed.
235234
opened,

OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/pushtoken/PushTokenManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ internal class PushTokenManager(
3737
// runtime error
3838
if (pushToken == null &&
3939
(
40-
pushTokenStatus == SubscriptionStatus.SUBSCRIBED ||
40+
pushTokenStatus == SubscriptionStatus.NO_PERMISSION ||
4141
pushStatusRuntimeError(pushTokenStatus)
4242
)
4343
) {

OneSignalSDK/onesignal/notifications/src/test/java/com/onesignal/notifications/ExampleUnitTest.kt

Lines changed: 0 additions & 16 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Code taken from https://github.com/kotest/kotest-extensions-robolectric with no changes.
3+
*
4+
* LICENSE: https://github.com/kotest/kotest-extensions-robolectric/blob/master/LICENSE
5+
*/
6+
package com.onesignal.notifications.extensions
7+
8+
import org.junit.runners.model.FrameworkMethod
9+
import org.robolectric.RobolectricTestRunner
10+
import org.robolectric.annotation.Config
11+
import org.robolectric.internal.bytecode.InstrumentationConfiguration
12+
import org.robolectric.pluginapi.config.ConfigurationStrategy
13+
import org.robolectric.plugins.ConfigConfigurer
14+
import java.lang.reflect.Method
15+
16+
internal class ContainedRobolectricRunner(
17+
private val config: Config?
18+
) : RobolectricTestRunner(PlaceholderTest::class.java, injector) {
19+
private val placeHolderMethod: FrameworkMethod = children[0]
20+
val sdkEnvironment = getSandbox(placeHolderMethod).also {
21+
configureSandbox(it, placeHolderMethod)
22+
}
23+
private val bootStrapMethod = sdkEnvironment.bootstrappedClass<Any>(testClass.javaClass)
24+
.getMethod(PlaceholderTest::bootStrapMethod.name)
25+
26+
fun containedBefore() {
27+
Thread.currentThread().contextClassLoader = sdkEnvironment.robolectricClassLoader
28+
super.beforeTest(sdkEnvironment, placeHolderMethod, bootStrapMethod)
29+
}
30+
31+
fun containedAfter() {
32+
super.afterTest(placeHolderMethod, bootStrapMethod)
33+
super.finallyAfterTest(placeHolderMethod)
34+
Thread.currentThread().contextClassLoader = ContainedRobolectricRunner::class.java.classLoader
35+
}
36+
37+
override fun createClassLoaderConfig(method: FrameworkMethod?): InstrumentationConfiguration {
38+
return InstrumentationConfiguration.Builder(super.createClassLoaderConfig(method))
39+
.doNotAcquirePackage("io.kotest")
40+
.build()
41+
}
42+
43+
override fun getConfig(method: Method?): Config {
44+
val defaultConfiguration = injector.getInstance(ConfigurationStrategy::class.java)
45+
.getConfig(testClass.javaClass, method)
46+
47+
if (config != null) {
48+
val configConfigurer = injector.getInstance(ConfigConfigurer::class.java)
49+
return configConfigurer.merge(defaultConfiguration[Config::class.java], config)
50+
}
51+
52+
return super.getConfig(method)
53+
}
54+
55+
class PlaceholderTest {
56+
@org.junit.Test
57+
fun testPlaceholder() {
58+
}
59+
60+
fun bootStrapMethod() {
61+
}
62+
}
63+
64+
companion object {
65+
private val injector = defaultInjector().build()
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* Code taken from https://github.com/kotest/kotest-extensions-robolectric with a
3+
* fix in the intercept method.
4+
*
5+
* LICENSE: https://github.com/kotest/kotest-extensions-robolectric/blob/master/LICENSE
6+
*/
7+
package com.onesignal.notifications.extensions
8+
9+
import android.app.Application
10+
import io.kotest.core.extensions.ConstructorExtension
11+
import io.kotest.core.extensions.TestCaseExtension
12+
import io.kotest.core.spec.AutoScan
13+
import io.kotest.core.spec.Spec
14+
import io.kotest.core.test.TestCase
15+
import io.kotest.core.test.TestResult
16+
import org.robolectric.annotation.Config
17+
import kotlin.reflect.KClass
18+
import kotlin.reflect.full.findAnnotation
19+
20+
/**
21+
* We override TestCaseExtension to configure the Robolectric environment because TestCase intercept
22+
* occurs on the same thread the test is run. This is unfortunate because it is run for every test,
23+
* rather than every spec. But the SpecExtension intercept is run on a different thread.
24+
*/
25+
@AutoScan
26+
internal class RobolectricExtension : ConstructorExtension, TestCaseExtension {
27+
private fun Class<*>.getParentClass(): List<Class<*>> {
28+
if (superclass == null) return listOf()
29+
return listOf(superclass) + superclass.getParentClass()
30+
}
31+
32+
private fun KClass<*>.getConfig(): Config {
33+
val configAnnotations = listOf(this.java).plus(this.java.getParentClass())
34+
.mapNotNull { it.kotlin.findAnnotation<Config>() }
35+
.asSequence()
36+
37+
val configAnnotation = configAnnotations.firstOrNull()
38+
39+
if (configAnnotation != null) {
40+
return Config.Builder(configAnnotation).build()
41+
}
42+
43+
val robolectricTestAnnotations = listOf(this.java).plus(this.java.getParentClass())
44+
.mapNotNull { it.kotlin.findAnnotation<RobolectricTest>() }
45+
.asSequence()
46+
47+
val application: KClass<out Application>? = robolectricTestAnnotations
48+
.firstOrNull { it.application != KotestDefaultApplication::class }?.application
49+
val sdk: Int? = robolectricTestAnnotations.firstOrNull { it.sdk != -1 }?.takeUnless { it.sdk == -1 }?.sdk
50+
51+
return Config.Builder()
52+
.also { builder ->
53+
if (application != null) {
54+
builder.setApplication(application.java)
55+
}
56+
57+
if (sdk != null) {
58+
builder.setSdk(sdk)
59+
}
60+
}.build()
61+
}
62+
63+
override fun <T : Spec> instantiate(clazz: KClass<T>): Spec? {
64+
clazz.findAnnotation<RobolectricTest>() ?: return null
65+
66+
return ContainedRobolectricRunner(clazz.getConfig())
67+
.sdkEnvironment.bootstrappedClass<Spec>(clazz.java).newInstance()
68+
}
69+
70+
override suspend fun intercept(
71+
testCase: TestCase,
72+
execute: suspend (TestCase) -> TestResult
73+
): TestResult {
74+
// FIXED: Updated code based on https://github.com/kotest/kotest/issues/2717
75+
val hasRobolectricAnnotation = testCase.spec::class.annotations.any { annotation ->
76+
annotation.annotationClass.qualifiedName == RobolectricTest::class.qualifiedName
77+
}
78+
79+
if (!hasRobolectricAnnotation) {
80+
return execute(testCase)
81+
}
82+
83+
val containedRobolectricRunner = ContainedRobolectricRunner(testCase.spec::class.getConfig())
84+
containedRobolectricRunner.containedBefore()
85+
val result = execute(testCase)
86+
containedRobolectricRunner.containedAfter()
87+
return result
88+
}
89+
}
90+
91+
internal class KotestDefaultApplication : Application()
92+
93+
annotation class RobolectricTest(
94+
val application: KClass<out Application> = KotestDefaultApplication::class,
95+
val sdk: Int = -1
96+
)

0 commit comments

Comments
 (0)