Skip to content

Commit

Permalink
Merge pull request #1692 from OneSignal/user-model/notification-unit-…
Browse files Browse the repository at this point in the history
…tests

[User Model] Notifications Unit Tests
  • Loading branch information
brismithers authored and jinliu9508 committed Jan 31, 2024
2 parents 79e4ad5 + bc093be commit 055d798
Show file tree
Hide file tree
Showing 114 changed files with 1,857 additions and 21,613 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ internal class NotificationReceivedEvent(
var effectiveNotification: Notification? = notification

override fun complete(notification: INotification?) {
effectiveNotification = notification as Notification
effectiveNotification = notification as Notification?
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.onesignal.notifications.internal.generation.impl

import android.content.Context
import com.onesignal.common.AndroidUtils
import com.onesignal.common.safeString
import com.onesignal.core.internal.application.IApplicationService
import com.onesignal.core.internal.config.ConfigModelStore
import com.onesignal.core.internal.time.ITime
Expand All @@ -15,7 +16,6 @@ import com.onesignal.notifications.internal.display.INotificationDisplayer
import com.onesignal.notifications.internal.generation.INotificationGenerationProcessor
import com.onesignal.notifications.internal.lifecycle.INotificationLifecycleService
import com.onesignal.notifications.internal.summary.INotificationSummaryManager
import com.onesignal.session.internal.session.ISessionService
import kotlinx.coroutines.delay
import kotlinx.coroutines.withTimeout
import org.json.JSONException
Expand All @@ -32,7 +32,6 @@ internal class NotificationGenerationProcessor(
private val _dataController: INotificationRepository,
private val _notificationSummaryManager: INotificationSummaryManager,
private val _lifecycleService: INotificationLifecycleService,
private val _sessionService: ISessionService,
private val _time: ITime
) : INotificationGenerationProcessor {

Expand Down Expand Up @@ -229,7 +228,7 @@ internal class NotificationGenerationProcessor(

_dataController.createNotification(
customJSON.optString("i"),
jsonPayload.optString("grp"),
jsonPayload.safeString("grp"),
collapseKey,
notificationJob.isNotificationToDisplay, // When notification was displayed, count any notifications with duplicated android notification ids as dismissed.
opened,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ internal class PushTokenManager(
// runtime error
if (pushToken == null &&
(
pushTokenStatus == SubscriptionStatus.SUBSCRIBED ||
pushTokenStatus == SubscriptionStatus.NO_PERMISSION ||
pushStatusRuntimeError(pushTokenStatus)
)
) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* Code taken from https://github.com/kotest/kotest-extensions-robolectric with no changes.
*
* LICENSE: https://github.com/kotest/kotest-extensions-robolectric/blob/master/LICENSE
*/
package com.onesignal.notifications.extensions

import org.junit.runners.model.FrameworkMethod
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.robolectric.internal.bytecode.InstrumentationConfiguration
import org.robolectric.pluginapi.config.ConfigurationStrategy
import org.robolectric.plugins.ConfigConfigurer
import java.lang.reflect.Method

internal class ContainedRobolectricRunner(
private val config: Config?
) : RobolectricTestRunner(PlaceholderTest::class.java, injector) {
private val placeHolderMethod: FrameworkMethod = children[0]
val sdkEnvironment = getSandbox(placeHolderMethod).also {
configureSandbox(it, placeHolderMethod)
}
private val bootStrapMethod = sdkEnvironment.bootstrappedClass<Any>(testClass.javaClass)
.getMethod(PlaceholderTest::bootStrapMethod.name)

fun containedBefore() {
Thread.currentThread().contextClassLoader = sdkEnvironment.robolectricClassLoader
super.beforeTest(sdkEnvironment, placeHolderMethod, bootStrapMethod)
}

fun containedAfter() {
super.afterTest(placeHolderMethod, bootStrapMethod)
super.finallyAfterTest(placeHolderMethod)
Thread.currentThread().contextClassLoader = ContainedRobolectricRunner::class.java.classLoader
}

override fun createClassLoaderConfig(method: FrameworkMethod?): InstrumentationConfiguration {
return InstrumentationConfiguration.Builder(super.createClassLoaderConfig(method))
.doNotAcquirePackage("io.kotest")
.build()
}

override fun getConfig(method: Method?): Config {
val defaultConfiguration = injector.getInstance(ConfigurationStrategy::class.java)
.getConfig(testClass.javaClass, method)

if (config != null) {
val configConfigurer = injector.getInstance(ConfigConfigurer::class.java)
return configConfigurer.merge(defaultConfiguration[Config::class.java], config)
}

return super.getConfig(method)
}

class PlaceholderTest {
@org.junit.Test
fun testPlaceholder() {
}

fun bootStrapMethod() {
}
}

companion object {
private val injector = defaultInjector().build()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* Code taken from https://github.com/kotest/kotest-extensions-robolectric with a
* fix in the intercept method.
*
* LICENSE: https://github.com/kotest/kotest-extensions-robolectric/blob/master/LICENSE
*/
package com.onesignal.notifications.extensions

import android.app.Application
import io.kotest.core.extensions.ConstructorExtension
import io.kotest.core.extensions.TestCaseExtension
import io.kotest.core.spec.AutoScan
import io.kotest.core.spec.Spec
import io.kotest.core.test.TestCase
import io.kotest.core.test.TestResult
import org.robolectric.annotation.Config
import kotlin.reflect.KClass
import kotlin.reflect.full.findAnnotation

/**
* We override TestCaseExtension to configure the Robolectric environment because TestCase intercept
* occurs on the same thread the test is run. This is unfortunate because it is run for every test,
* rather than every spec. But the SpecExtension intercept is run on a different thread.
*/
@AutoScan
internal class RobolectricExtension : ConstructorExtension, TestCaseExtension {
private fun Class<*>.getParentClass(): List<Class<*>> {
if (superclass == null) return listOf()
return listOf(superclass) + superclass.getParentClass()
}

private fun KClass<*>.getConfig(): Config {
val configAnnotations = listOf(this.java).plus(this.java.getParentClass())
.mapNotNull { it.kotlin.findAnnotation<Config>() }
.asSequence()

val configAnnotation = configAnnotations.firstOrNull()

if (configAnnotation != null) {
return Config.Builder(configAnnotation).build()
}

val robolectricTestAnnotations = listOf(this.java).plus(this.java.getParentClass())
.mapNotNull { it.kotlin.findAnnotation<RobolectricTest>() }
.asSequence()

val application: KClass<out Application>? = robolectricTestAnnotations
.firstOrNull { it.application != KotestDefaultApplication::class }?.application
val sdk: Int? = robolectricTestAnnotations.firstOrNull { it.sdk != -1 }?.takeUnless { it.sdk == -1 }?.sdk

return Config.Builder()
.also { builder ->
if (application != null) {
builder.setApplication(application.java)
}

if (sdk != null) {
builder.setSdk(sdk)
}
}.build()
}

override fun <T : Spec> instantiate(clazz: KClass<T>): Spec? {
clazz.findAnnotation<RobolectricTest>() ?: return null

return ContainedRobolectricRunner(clazz.getConfig())
.sdkEnvironment.bootstrappedClass<Spec>(clazz.java).newInstance()
}

override suspend fun intercept(
testCase: TestCase,
execute: suspend (TestCase) -> TestResult
): TestResult {
// FIXED: Updated code based on https://github.com/kotest/kotest/issues/2717
val hasRobolectricAnnotation = testCase.spec::class.annotations.any { annotation ->
annotation.annotationClass.qualifiedName == RobolectricTest::class.qualifiedName
}

if (!hasRobolectricAnnotation) {
return execute(testCase)
}

val containedRobolectricRunner = ContainedRobolectricRunner(testCase.spec::class.getConfig())
containedRobolectricRunner.containedBefore()
val result = execute(testCase)
containedRobolectricRunner.containedAfter()
return result
}
}

internal class KotestDefaultApplication : Application()

annotation class RobolectricTest(
val application: KClass<out Application> = KotestDefaultApplication::class,
val sdk: Int = -1
)
Loading

0 comments on commit 055d798

Please sign in to comment.