Merge pull request #245 from ouchadam/tech/push-tests
Tech/Push registration tests
This commit is contained in:
commit
ab330c94d9
|
@ -6,7 +6,11 @@ import kotlinx.coroutines.test.runTest
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
fun runExpectTest(testBody: suspend ExpectTestScope.() -> Unit) {
|
fun runExpectTest(testBody: suspend ExpectTestScope.() -> Unit) {
|
||||||
runTest { testBody(ExpectTest(coroutineContext)) }
|
runTest {
|
||||||
|
val expectTest = ExpectTest(coroutineContext)
|
||||||
|
testBody(expectTest)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExpectTest(override val coroutineContext: CoroutineContext) : ExpectTestScope {
|
class ExpectTest(override val coroutineContext: CoroutineContext) : ExpectTestScope {
|
||||||
|
@ -24,6 +28,11 @@ class ExpectTest(override val coroutineContext: CoroutineContext) : ExpectTestSc
|
||||||
expects.add(times to { block(this@expectUnit) })
|
expects.add(times to { block(this@expectUnit) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun <T> T.expect(times: Int, block: suspend MockKMatcherScope.(T) -> Unit) {
|
||||||
|
coJustRun { block(this@expect) }
|
||||||
|
expects.add(times to { block(this@expect) })
|
||||||
|
}
|
||||||
|
|
||||||
override fun <T> T.captureExpects(block: suspend MockKMatcherScope.(T) -> Unit) {
|
override fun <T> T.captureExpects(block: suspend MockKMatcherScope.(T) -> Unit) {
|
||||||
groups.add { block(this@captureExpects) }
|
groups.add { block(this@captureExpects) }
|
||||||
}
|
}
|
||||||
|
@ -34,5 +43,6 @@ private fun Any.ignore() = Unit
|
||||||
interface ExpectTestScope : CoroutineScope {
|
interface ExpectTestScope : CoroutineScope {
|
||||||
fun verifyExpects()
|
fun verifyExpects()
|
||||||
fun <T> T.expectUnit(times: Int = 1, block: suspend MockKMatcherScope.(T) -> Unit)
|
fun <T> T.expectUnit(times: Int = 1, block: suspend MockKMatcherScope.(T) -> Unit)
|
||||||
|
fun <T> T.expect(times: Int = 1, block: suspend MockKMatcherScope.(T) -> Unit)
|
||||||
fun <T> T.captureExpects(block: suspend MockKMatcherScope.(T) -> Unit)
|
fun <T> T.captureExpects(block: suspend MockKMatcherScope.(T) -> Unit)
|
||||||
}
|
}
|
|
@ -10,4 +10,9 @@ dependencies {
|
||||||
|
|
||||||
implementation Dependencies.mavenCentral.kotlinSerializationJson
|
implementation Dependencies.mavenCentral.kotlinSerializationJson
|
||||||
implementation Dependencies.jitPack.unifiedPush
|
implementation Dependencies.jitPack.unifiedPush
|
||||||
|
|
||||||
|
kotlinTest(it)
|
||||||
|
androidImportFixturesWorkaround(project, project(":core"))
|
||||||
|
androidImportFixturesWorkaround(project, project(":matrix:common"))
|
||||||
|
androidImportFixturesWorkaround(project, project(":domains:android:stub"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import app.dapk.st.core.extensions.unsafeLazy
|
||||||
import app.dapk.st.domain.push.PushTokenRegistrarPreferences
|
import app.dapk.st.domain.push.PushTokenRegistrarPreferences
|
||||||
import app.dapk.st.firebase.messaging.Messaging
|
import app.dapk.st.firebase.messaging.Messaging
|
||||||
import app.dapk.st.push.messaging.MessagingPushTokenRegistrar
|
import app.dapk.st.push.messaging.MessagingPushTokenRegistrar
|
||||||
|
import app.dapk.st.push.unifiedpush.UnifiedPushImpl
|
||||||
import app.dapk.st.push.unifiedpush.UnifiedPushRegistrar
|
import app.dapk.st.push.unifiedpush.UnifiedPushRegistrar
|
||||||
|
|
||||||
class PushModule(
|
class PushModule(
|
||||||
|
@ -21,15 +22,15 @@ class PushModule(
|
||||||
) : ProvidableModule {
|
) : ProvidableModule {
|
||||||
|
|
||||||
private val registrars by unsafeLazy {
|
private val registrars by unsafeLazy {
|
||||||
|
val unifiedPush = UnifiedPushImpl(context)
|
||||||
PushTokenRegistrars(
|
PushTokenRegistrars(
|
||||||
context,
|
|
||||||
MessagingPushTokenRegistrar(
|
MessagingPushTokenRegistrar(
|
||||||
errorTracker,
|
errorTracker,
|
||||||
pushHandler,
|
pushHandler,
|
||||||
messaging,
|
messaging,
|
||||||
),
|
),
|
||||||
UnifiedPushRegistrar(context),
|
UnifiedPushRegistrar(context, unifiedPush),
|
||||||
PushTokenRegistrarPreferences(preferences)
|
PushTokenRegistrarPreferences(preferences),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,30 @@
|
||||||
package app.dapk.st.push
|
package app.dapk.st.push
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import app.dapk.st.domain.push.PushTokenRegistrarPreferences
|
import app.dapk.st.domain.push.PushTokenRegistrarPreferences
|
||||||
import app.dapk.st.push.messaging.MessagingPushTokenRegistrar
|
import app.dapk.st.push.messaging.MessagingPushTokenRegistrar
|
||||||
import app.dapk.st.push.unifiedpush.UnifiedPushRegistrar
|
import app.dapk.st.push.unifiedpush.UnifiedPushRegistrar
|
||||||
import org.unifiedpush.android.connector.UnifiedPush
|
|
||||||
|
|
||||||
private val FIREBASE_OPTION = Registrar("Google - Firebase (FCM)")
|
private val FIREBASE_OPTION = Registrar("Google - Firebase (FCM)")
|
||||||
private val NONE = Registrar("None")
|
private val NONE = Registrar("None")
|
||||||
|
|
||||||
class PushTokenRegistrars(
|
class PushTokenRegistrars(
|
||||||
private val context: Context,
|
|
||||||
private val messagingPushTokenRegistrar: MessagingPushTokenRegistrar,
|
private val messagingPushTokenRegistrar: MessagingPushTokenRegistrar,
|
||||||
private val unifiedPushRegistrar: UnifiedPushRegistrar,
|
private val unifiedPushRegistrar: UnifiedPushRegistrar,
|
||||||
private val pushTokenStore: PushTokenRegistrarPreferences,
|
private val pushTokenStore: PushTokenRegistrarPreferences,
|
||||||
|
private val state: SelectionState = SelectionState(selection = null),
|
||||||
) : PushTokenRegistrar {
|
) : PushTokenRegistrar {
|
||||||
|
|
||||||
private var selection: Registrar? = null
|
|
||||||
|
|
||||||
fun options(): List<Registrar> {
|
fun options(): List<Registrar> {
|
||||||
val messagingOption = when (messagingPushTokenRegistrar.isAvailable()) {
|
val messagingOption = when (messagingPushTokenRegistrar.isAvailable()) {
|
||||||
true -> FIREBASE_OPTION
|
true -> FIREBASE_OPTION
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
return listOfNotNull(NONE, messagingOption) + UnifiedPush.getDistributors(context).map { Registrar(it) }
|
return listOfNotNull(NONE, messagingOption) + unifiedPushRegistrar.getDistributors()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun currentSelection() = selection ?: (pushTokenStore.currentSelection()?.let { Registrar(it) } ?: defaultSelection()).also { selection = it }
|
suspend fun currentSelection() = state.selection ?: (readStoredSelection() ?: defaultSelection()).also { state.selection = it }
|
||||||
|
|
||||||
|
private suspend fun readStoredSelection() = pushTokenStore.currentSelection()?.let { Registrar(it) }?.takeIf { options().contains(it) }
|
||||||
|
|
||||||
private fun defaultSelection() = when (messagingPushTokenRegistrar.isAvailable()) {
|
private fun defaultSelection() = when (messagingPushTokenRegistrar.isAvailable()) {
|
||||||
true -> FIREBASE_OPTION
|
true -> FIREBASE_OPTION
|
||||||
|
@ -34,7 +32,7 @@ class PushTokenRegistrars(
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun makeSelection(option: Registrar) {
|
suspend fun makeSelection(option: Registrar) {
|
||||||
selection = option
|
state.selection = option
|
||||||
pushTokenStore.store(option.id)
|
pushTokenStore.store(option.id)
|
||||||
when (option) {
|
when (option) {
|
||||||
NONE -> {
|
NONE -> {
|
||||||
|
@ -66,7 +64,7 @@ class PushTokenRegistrars(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unregister() {
|
override fun unregister() {
|
||||||
when (selection) {
|
when (state.selection) {
|
||||||
FIREBASE_OPTION -> messagingPushTokenRegistrar.unregister()
|
FIREBASE_OPTION -> messagingPushTokenRegistrar.unregister()
|
||||||
NONE -> {
|
NONE -> {
|
||||||
runCatching {
|
runCatching {
|
||||||
|
@ -86,4 +84,6 @@ class PushTokenRegistrars(
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class Registrar(val id: String)
|
value class Registrar(val id: String)
|
||||||
|
|
||||||
|
data class SelectionState(var selection: Registrar?)
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package app.dapk.st.push.unifiedpush
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.unifiedpush.android.connector.UnifiedPush
|
||||||
|
|
||||||
|
interface UnifiedPush {
|
||||||
|
fun saveDistributor(distributor: String)
|
||||||
|
fun getDistributor(): String
|
||||||
|
fun getDistributors(): List<String>
|
||||||
|
fun registerApp()
|
||||||
|
fun unregisterApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class UnifiedPushImpl(private val context: Context) : app.dapk.st.push.unifiedpush.UnifiedPush {
|
||||||
|
override fun saveDistributor(distributor: String) = UnifiedPush.saveDistributor(context, distributor)
|
||||||
|
override fun getDistributor(): String = UnifiedPush.getDistributor(context)
|
||||||
|
override fun getDistributors(): List<String> = UnifiedPush.getDistributors(context)
|
||||||
|
override fun registerApp() = UnifiedPush.registerApp(context)
|
||||||
|
override fun unregisterApp() = UnifiedPush.unregisterApp(context)
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package app.dapk.st.push.unifiedpush
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import app.dapk.st.core.AppLogTag
|
||||||
|
import app.dapk.st.core.log
|
||||||
|
import app.dapk.st.core.module
|
||||||
|
import app.dapk.st.matrix.common.EventId
|
||||||
|
import app.dapk.st.matrix.common.RoomId
|
||||||
|
import app.dapk.st.push.PushModule
|
||||||
|
import app.dapk.st.push.PushTokenPayload
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
private const val FALLBACK_UNIFIED_PUSH_GATEWAY = "https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify"
|
||||||
|
private val json = Json { ignoreUnknownKeys = true }
|
||||||
|
|
||||||
|
class UnifiedPushMessageDelegate(
|
||||||
|
private val scope: CoroutineScope = CoroutineScope(SupervisorJob()),
|
||||||
|
private val pushModuleProvider: (Context) -> PushModule = { it.module() },
|
||||||
|
private val endpointReader: suspend (URL) -> String = {
|
||||||
|
runCatching { it.openStream().use { String(it.readBytes()) } }.getOrNull() ?: ""
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun onMessage(context: Context, message: ByteArray) {
|
||||||
|
log(AppLogTag.PUSH, "UnifiedPush onMessage, $message")
|
||||||
|
val module = pushModuleProvider(context)
|
||||||
|
val handler = module.pushHandler()
|
||||||
|
scope.launch {
|
||||||
|
withContext(module.dispatcher().io) {
|
||||||
|
val payload = json.decodeFromString(UnifiedPushMessagePayload.serializer(), String(message))
|
||||||
|
handler.onMessageReceived(payload.notification.eventId?.let { EventId(it) }, payload.notification.roomId?.let { RoomId(it) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onNewEndpoint(context: Context, endpoint: String) {
|
||||||
|
log(AppLogTag.PUSH, "UnifiedPush onNewEndpoint $endpoint")
|
||||||
|
val module = pushModuleProvider(context)
|
||||||
|
val handler = module.pushHandler()
|
||||||
|
scope.launch {
|
||||||
|
withContext(module.dispatcher().io) {
|
||||||
|
val matrixEndpoint = URL(endpoint).let { URL("${it.protocol}://${it.host}/_matrix/push/v1/notify") }
|
||||||
|
val content = endpointReader(matrixEndpoint)
|
||||||
|
val gatewayUrl = when {
|
||||||
|
content.contains("\"gateway\":\"matrix\"") -> matrixEndpoint.toString()
|
||||||
|
else -> FALLBACK_UNIFIED_PUSH_GATEWAY
|
||||||
|
}
|
||||||
|
handler.onNewToken(PushTokenPayload(token = endpoint, gatewayUrl = gatewayUrl))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
private data class UnifiedPushMessagePayload(
|
||||||
|
@SerialName("notification") val notification: Notification,
|
||||||
|
) {
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Notification(
|
||||||
|
@SerialName("event_id") val eventId: String? = null,
|
||||||
|
@SerialName("room_id") val roomId: String? = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,56 +3,19 @@ package app.dapk.st.push.unifiedpush
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import app.dapk.st.core.AppLogTag
|
import app.dapk.st.core.AppLogTag
|
||||||
import app.dapk.st.core.log
|
import app.dapk.st.core.log
|
||||||
import app.dapk.st.core.module
|
|
||||||
import app.dapk.st.matrix.common.EventId
|
|
||||||
import app.dapk.st.matrix.common.RoomId
|
|
||||||
import app.dapk.st.push.PushModule
|
|
||||||
import app.dapk.st.push.PushTokenPayload
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.SupervisorJob
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import org.unifiedpush.android.connector.MessagingReceiver
|
import org.unifiedpush.android.connector.MessagingReceiver
|
||||||
import java.net.URL
|
|
||||||
|
|
||||||
private val json = Json { ignoreUnknownKeys = true }
|
|
||||||
|
|
||||||
private const val FALLBACK_UNIFIED_PUSH_GATEWAY = "https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify"
|
|
||||||
|
|
||||||
class UnifiedPushMessageReceiver : MessagingReceiver() {
|
class UnifiedPushMessageReceiver : MessagingReceiver() {
|
||||||
|
|
||||||
private val scope = CoroutineScope(SupervisorJob())
|
private val delegate = UnifiedPushMessageDelegate()
|
||||||
|
|
||||||
override fun onMessage(context: Context, message: ByteArray, instance: String) {
|
override fun onMessage(context: Context, message: ByteArray, instance: String) {
|
||||||
log(AppLogTag.PUSH, "UnifiedPush onMessage, $message")
|
delegate.onMessage(context, message)
|
||||||
val module = context.module<PushModule>()
|
|
||||||
val handler = module.pushHandler()
|
|
||||||
scope.launch {
|
|
||||||
withContext(module.dispatcher().io) {
|
|
||||||
val payload = json.decodeFromString(UnifiedPushMessagePayload.serializer(), String(message))
|
|
||||||
handler.onMessageReceived(payload.notification.eventId?.let { EventId(it) }, payload.notification.roomId?.let { RoomId(it) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) {
|
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) {
|
||||||
log(AppLogTag.PUSH, "UnifiedPush onNewEndpoint $endpoint")
|
delegate.onNewEndpoint(context, endpoint)
|
||||||
val module = context.module<PushModule>()
|
|
||||||
val handler = module.pushHandler()
|
|
||||||
scope.launch {
|
|
||||||
withContext(module.dispatcher().io) {
|
|
||||||
val matrixEndpoint = URL(endpoint).let { URL("${it.protocol}://${it.host}/_matrix/push/v1/notify") }
|
|
||||||
val content = runCatching { matrixEndpoint.openStream().use { String(it.readBytes()) } }.getOrNull() ?: ""
|
|
||||||
val gatewayUrl = when {
|
|
||||||
content.contains("\"gateway\":\"matrix\"") -> matrixEndpoint.toString()
|
|
||||||
else -> FALLBACK_UNIFIED_PUSH_GATEWAY
|
|
||||||
}
|
|
||||||
handler.onNewToken(PushTokenPayload(token = endpoint, gatewayUrl = gatewayUrl))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRegistrationFailed(context: Context, instance: String) {
|
override fun onRegistrationFailed(context: Context, instance: String) {
|
||||||
|
@ -63,15 +26,4 @@ class UnifiedPushMessageReceiver : MessagingReceiver() {
|
||||||
log(AppLogTag.PUSH, "UnifiedPush onUnregistered")
|
log(AppLogTag.PUSH, "UnifiedPush onUnregistered")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
}
|
||||||
private data class UnifiedPushMessagePayload(
|
|
||||||
@SerialName("notification") val notification: Notification,
|
|
||||||
) {
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Notification(
|
|
||||||
@SerialName("event_id") val eventId: String? = null,
|
|
||||||
@SerialName("room_id") val roomId: String? = null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,38 +7,41 @@ import app.dapk.st.core.AppLogTag
|
||||||
import app.dapk.st.core.log
|
import app.dapk.st.core.log
|
||||||
import app.dapk.st.push.PushTokenRegistrar
|
import app.dapk.st.push.PushTokenRegistrar
|
||||||
import app.dapk.st.push.Registrar
|
import app.dapk.st.push.Registrar
|
||||||
import org.unifiedpush.android.connector.UnifiedPush
|
|
||||||
|
|
||||||
class UnifiedPushRegistrar(
|
class UnifiedPushRegistrar(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
|
private val unifiedPush: UnifiedPush,
|
||||||
|
private val componentFactory: (Context) -> ComponentName = { ComponentName(it, UnifiedPushMessageReceiver::class.java) }
|
||||||
) : PushTokenRegistrar {
|
) : PushTokenRegistrar {
|
||||||
|
|
||||||
|
fun getDistributors() = unifiedPush.getDistributors().map { Registrar(it) }
|
||||||
|
|
||||||
fun registerSelection(registrar: Registrar) {
|
fun registerSelection(registrar: Registrar) {
|
||||||
log(AppLogTag.PUSH, "UnifiedPush - register: $registrar")
|
log(AppLogTag.PUSH, "UnifiedPush - register: $registrar")
|
||||||
UnifiedPush.saveDistributor(context, registrar.id)
|
unifiedPush.saveDistributor(registrar.id)
|
||||||
registerApp()
|
registerApp()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun registerCurrentToken() {
|
override suspend fun registerCurrentToken() {
|
||||||
log(AppLogTag.PUSH, "UnifiedPush - register current token")
|
log(AppLogTag.PUSH, "UnifiedPush - register current token")
|
||||||
if (UnifiedPush.getDistributor(context).isNotEmpty()) {
|
if (unifiedPush.getDistributor().isNotEmpty()) {
|
||||||
registerApp()
|
registerApp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerApp() {
|
private fun registerApp() {
|
||||||
context.packageManager.setComponentEnabledSetting(
|
context.packageManager.setComponentEnabledSetting(
|
||||||
ComponentName(context, UnifiedPushMessageReceiver::class.java),
|
componentFactory(context),
|
||||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||||
PackageManager.DONT_KILL_APP,
|
PackageManager.DONT_KILL_APP,
|
||||||
)
|
)
|
||||||
UnifiedPush.registerApp(context)
|
unifiedPush.registerApp()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unregister() {
|
override fun unregister() {
|
||||||
UnifiedPush.unregisterApp(context)
|
unifiedPush.unregisterApp()
|
||||||
context.packageManager.setComponentEnabledSetting(
|
context.packageManager.setComponentEnabledSetting(
|
||||||
ComponentName(context, UnifiedPushMessageReceiver::class.java),
|
componentFactory(context),
|
||||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||||
PackageManager.DONT_KILL_APP,
|
PackageManager.DONT_KILL_APP,
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
package app.dapk.st.push
|
||||||
|
|
||||||
|
import app.dapk.st.domain.push.PushTokenRegistrarPreferences
|
||||||
|
import app.dapk.st.push.messaging.MessagingPushTokenRegistrar
|
||||||
|
import app.dapk.st.push.unifiedpush.UnifiedPushRegistrar
|
||||||
|
import io.mockk.*
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
import test.delegateReturn
|
||||||
|
import test.runExpectTest
|
||||||
|
|
||||||
|
private val UNIFIED_PUSH = Registrar("unified-push option")
|
||||||
|
private val NONE = Registrar("None")
|
||||||
|
private val FIREBASE = Registrar("Google - Firebase (FCM)")
|
||||||
|
private val UNIFIED_PUSH_DISTRIBUTORS = listOf(UNIFIED_PUSH)
|
||||||
|
|
||||||
|
class PushTokenRegistrarsTest {
|
||||||
|
|
||||||
|
private val fakeMessagingPushRegistrar = FakeMessagingPushRegistrar()
|
||||||
|
private val fakeUnifiedPushRegistrar = FakeUnifiedPushRegistrar()
|
||||||
|
private val fakePushTokenRegistrarPreferences = FakePushTokenRegistrarPreferences()
|
||||||
|
private val selectionState = SelectionState(selection = null)
|
||||||
|
|
||||||
|
private val registrars = PushTokenRegistrars(
|
||||||
|
fakeMessagingPushRegistrar.instance,
|
||||||
|
fakeUnifiedPushRegistrar.instance,
|
||||||
|
fakePushTokenRegistrarPreferences.instance,
|
||||||
|
selectionState,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given messaging is available, when reading options, then returns firebase and unified push`() {
|
||||||
|
fakeMessagingPushRegistrar.givenIsAvailable().returns(true)
|
||||||
|
fakeUnifiedPushRegistrar.givenDistributors().returns(UNIFIED_PUSH_DISTRIBUTORS)
|
||||||
|
|
||||||
|
val result = registrars.options()
|
||||||
|
|
||||||
|
result shouldBeEqualTo listOf(Registrar("None"), FIREBASE) + UNIFIED_PUSH_DISTRIBUTORS
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given messaging is not available, when reading options, then returns unified push`() {
|
||||||
|
fakeMessagingPushRegistrar.givenIsAvailable().returns(false)
|
||||||
|
fakeUnifiedPushRegistrar.givenDistributors().returns(UNIFIED_PUSH_DISTRIBUTORS)
|
||||||
|
|
||||||
|
val result = registrars.options()
|
||||||
|
|
||||||
|
result shouldBeEqualTo listOf(Registrar("None")) + UNIFIED_PUSH_DISTRIBUTORS
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given no saved selection and messaging is not available, when reading default selection, then returns none`() = runTest {
|
||||||
|
fakePushTokenRegistrarPreferences.givenCurrentSelection().returns(null)
|
||||||
|
fakeMessagingPushRegistrar.givenIsAvailable().returns(false)
|
||||||
|
|
||||||
|
val result = registrars.currentSelection()
|
||||||
|
|
||||||
|
result shouldBeEqualTo NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given no saved selection and messaging is available, when reading default selection, then returns firebase`() = runTest {
|
||||||
|
fakePushTokenRegistrarPreferences.givenCurrentSelection().returns(null)
|
||||||
|
fakeMessagingPushRegistrar.givenIsAvailable().returns(true)
|
||||||
|
|
||||||
|
val result = registrars.currentSelection()
|
||||||
|
|
||||||
|
result shouldBeEqualTo FIREBASE
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given saved selection and is a option, when reading default selection, then returns selection`() = runTest {
|
||||||
|
fakeUnifiedPushRegistrar.givenDistributors().returns(UNIFIED_PUSH_DISTRIBUTORS)
|
||||||
|
fakePushTokenRegistrarPreferences.givenCurrentSelection().returns(FIREBASE.id)
|
||||||
|
fakeMessagingPushRegistrar.givenIsAvailable().returns(true)
|
||||||
|
|
||||||
|
val result = registrars.currentSelection()
|
||||||
|
|
||||||
|
result shouldBeEqualTo FIREBASE
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given saved selection and is not an option, when reading default selection, then returns next default`() = runTest {
|
||||||
|
fakeUnifiedPushRegistrar.givenDistributors().returns(UNIFIED_PUSH_DISTRIBUTORS)
|
||||||
|
fakePushTokenRegistrarPreferences.givenCurrentSelection().returns(FIREBASE.id)
|
||||||
|
fakeMessagingPushRegistrar.givenIsAvailable().returns(false)
|
||||||
|
|
||||||
|
val result = registrars.currentSelection()
|
||||||
|
|
||||||
|
result shouldBeEqualTo NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when selecting none, then stores and unregisters`() = runExpectTest {
|
||||||
|
fakePushTokenRegistrarPreferences.instance.expect { it.store(NONE.id) }
|
||||||
|
fakeMessagingPushRegistrar.instance.expect { it.unregister() }
|
||||||
|
fakeUnifiedPushRegistrar.instance.expect { it.unregister() }
|
||||||
|
|
||||||
|
registrars.makeSelection(NONE)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when selecting firebase, then stores and unregisters unifiedpush`() = runExpectTest {
|
||||||
|
fakePushTokenRegistrarPreferences.instance.expect { it.store(FIREBASE.id) }
|
||||||
|
fakeMessagingPushRegistrar.instance.expect { it.registerCurrentToken() }
|
||||||
|
fakeUnifiedPushRegistrar.instance.expect { it.unregister() }
|
||||||
|
|
||||||
|
registrars.makeSelection(FIREBASE)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when selecting unified push, then stores and unregisters firebase`() = runExpectTest {
|
||||||
|
fakePushTokenRegistrarPreferences.instance.expect { it.store(UNIFIED_PUSH.id) }
|
||||||
|
fakeMessagingPushRegistrar.instance.expect { it.unregister() }
|
||||||
|
fakeUnifiedPushRegistrar.instance.expect { it.registerSelection(UNIFIED_PUSH) }
|
||||||
|
|
||||||
|
registrars.makeSelection(UNIFIED_PUSH)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given unified push selected, when registering current token, then delegates`() = runExpectTest {
|
||||||
|
selectionState.selection = UNIFIED_PUSH
|
||||||
|
fakeUnifiedPushRegistrar.instance.expect { it.registerCurrentToken() }
|
||||||
|
|
||||||
|
registrars.registerCurrentToken()
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given firebase selected, when registering current token, then delegates`() = runExpectTest {
|
||||||
|
selectionState.selection = FIREBASE
|
||||||
|
fakeMessagingPushRegistrar.instance.expect { it.registerCurrentToken() }
|
||||||
|
|
||||||
|
registrars.registerCurrentToken()
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given none selected, when registering current token, then does nothing`() = runExpectTest {
|
||||||
|
selectionState.selection = NONE
|
||||||
|
|
||||||
|
registrars.registerCurrentToken()
|
||||||
|
|
||||||
|
verify { fakeMessagingPushRegistrar.instance wasNot Called }
|
||||||
|
verify { fakeUnifiedPushRegistrar.instance wasNot Called }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given unified push selected, when unregistering, then delegates`() = runExpectTest {
|
||||||
|
selectionState.selection = UNIFIED_PUSH
|
||||||
|
fakeUnifiedPushRegistrar.instance.expect { it.unregister() }
|
||||||
|
|
||||||
|
registrars.unregister()
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given firebase selected, when unregistering, then delegates`() = runExpectTest {
|
||||||
|
selectionState.selection = FIREBASE
|
||||||
|
fakeMessagingPushRegistrar.instance.expect { it.unregister() }
|
||||||
|
|
||||||
|
registrars.unregister()
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given none selected, when unregistering, then unregisters all`() = runExpectTest {
|
||||||
|
selectionState.selection = NONE
|
||||||
|
fakeUnifiedPushRegistrar.instance.expect { it.unregister() }
|
||||||
|
fakeMessagingPushRegistrar.instance.expect { it.unregister() }
|
||||||
|
|
||||||
|
registrars.unregister()
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeMessagingPushRegistrar {
|
||||||
|
val instance = mockk<MessagingPushTokenRegistrar>()
|
||||||
|
|
||||||
|
fun givenIsAvailable() = every { instance.isAvailable() }.delegateReturn()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeUnifiedPushRegistrar {
|
||||||
|
val instance = mockk<UnifiedPushRegistrar>()
|
||||||
|
|
||||||
|
fun givenDistributors() = every { instance.getDistributors() }.delegateReturn()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakePushTokenRegistrarPreferences {
|
||||||
|
val instance = mockk<PushTokenRegistrarPreferences>()
|
||||||
|
|
||||||
|
fun givenCurrentSelection() = coEvery { instance.currentSelection() }.delegateReturn()
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package app.dapk.st.push.messaging
|
||||||
|
|
||||||
|
import app.dapk.st.firebase.messaging.Messaging
|
||||||
|
import app.dapk.st.push.PushTokenPayload
|
||||||
|
import app.dapk.st.push.unifiedpush.FakePushHandler
|
||||||
|
import fake.FakeErrorTracker
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
import test.delegateReturn
|
||||||
|
import test.runExpectTest
|
||||||
|
|
||||||
|
private const val A_TOKEN = "a-token"
|
||||||
|
private const val SYGNAL_GATEWAY = "https://sygnal.dapk.app/_matrix/push/v1/notify"
|
||||||
|
private val AN_ERROR = RuntimeException()
|
||||||
|
|
||||||
|
class MessagingPushTokenRegistrarTest {
|
||||||
|
|
||||||
|
private val fakePushHandler = FakePushHandler()
|
||||||
|
private val fakeErrorTracker = FakeErrorTracker()
|
||||||
|
private val fakeMessaging = FakeMessaging()
|
||||||
|
|
||||||
|
private val registrar = MessagingPushTokenRegistrar(
|
||||||
|
fakeErrorTracker,
|
||||||
|
fakePushHandler,
|
||||||
|
fakeMessaging.instance,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when checking isAvailable, then delegates`() = runExpectTest {
|
||||||
|
fakeMessaging.givenIsAvailable().returns(true)
|
||||||
|
|
||||||
|
val result = registrar.isAvailable()
|
||||||
|
|
||||||
|
result shouldBeEqualTo true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when registering current token, then enables and forwards current token to handler`() = runExpectTest {
|
||||||
|
fakeMessaging.instance.expect { it.enable() }
|
||||||
|
fakePushHandler.expect { it.onNewToken(PushTokenPayload(A_TOKEN, SYGNAL_GATEWAY)) }
|
||||||
|
fakeMessaging.givenToken().returns(A_TOKEN)
|
||||||
|
|
||||||
|
registrar.registerCurrentToken()
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given fails to register, when registering current token, then tracks error`() = runExpectTest {
|
||||||
|
fakeMessaging.instance.expect { it.enable() }
|
||||||
|
fakeMessaging.givenToken().throws(AN_ERROR)
|
||||||
|
fakeErrorTracker.expect { it.track(AN_ERROR) }
|
||||||
|
|
||||||
|
registrar.registerCurrentToken()
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when unregistering, then deletes token and disables`() = runExpectTest {
|
||||||
|
fakeMessaging.instance.expect { it.deleteToken() }
|
||||||
|
fakeMessaging.instance.expect { it.disable() }
|
||||||
|
|
||||||
|
registrar.unregister()
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeMessaging {
|
||||||
|
val instance = mockk<Messaging>()
|
||||||
|
|
||||||
|
fun givenIsAvailable() = every { instance.isAvailable() }.delegateReturn()
|
||||||
|
fun givenToken() = coEvery { instance.token() }.delegateReturn()
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package app.dapk.st.push.messaging
|
||||||
|
|
||||||
|
import app.dapk.st.push.PushTokenPayload
|
||||||
|
import app.dapk.st.push.unifiedpush.FakePushHandler
|
||||||
|
import fixture.aRoomId
|
||||||
|
import fixture.anEventId
|
||||||
|
import org.junit.Test
|
||||||
|
import test.runExpectTest
|
||||||
|
|
||||||
|
private const val A_TOKEN = "a-push-token"
|
||||||
|
private const val SYGNAL_GATEWAY = "https://sygnal.dapk.app/_matrix/push/v1/notify"
|
||||||
|
private val A_ROOM_ID = aRoomId()
|
||||||
|
private val AN_EVENT_ID = anEventId()
|
||||||
|
|
||||||
|
class MessagingServiceAdapterTest {
|
||||||
|
|
||||||
|
private val fakePushHandler = FakePushHandler()
|
||||||
|
|
||||||
|
private val messagingServiceAdapter = MessagingServiceAdapter(fakePushHandler)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `onNewToken, then delegates to push handler`() = runExpectTest {
|
||||||
|
fakePushHandler.expect {
|
||||||
|
it.onNewToken(PushTokenPayload(token = A_TOKEN, gatewayUrl = SYGNAL_GATEWAY))
|
||||||
|
}
|
||||||
|
messagingServiceAdapter.onNewToken(A_TOKEN)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `onMessageReceived, then delegates to push handler`() = runExpectTest {
|
||||||
|
fakePushHandler.expect {
|
||||||
|
it.onMessageReceived(AN_EVENT_ID, A_ROOM_ID)
|
||||||
|
}
|
||||||
|
messagingServiceAdapter.onMessageReceived(AN_EVENT_ID, A_ROOM_ID)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package app.dapk.st.push.unifiedpush
|
||||||
|
|
||||||
|
import app.dapk.st.push.PushHandler
|
||||||
|
import io.mockk.mockk
|
||||||
|
|
||||||
|
class FakePushHandler : PushHandler by mockk()
|
|
@ -0,0 +1,95 @@
|
||||||
|
package app.dapk.st.push.unifiedpush
|
||||||
|
|
||||||
|
import app.dapk.st.matrix.common.EventId
|
||||||
|
import app.dapk.st.matrix.common.RoomId
|
||||||
|
import app.dapk.st.push.PushModule
|
||||||
|
import app.dapk.st.push.PushTokenPayload
|
||||||
|
import fake.FakeContext
|
||||||
|
import fixture.CoroutineDispatchersFixture.aCoroutineDispatchers
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||||
|
import org.junit.Test
|
||||||
|
import test.delegateReturn
|
||||||
|
import test.runExpectTest
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
private val A_CONTEXT = FakeContext()
|
||||||
|
private const val A_ROOM_ID = "a room id"
|
||||||
|
private const val AN_EVENT_ID = "an event id"
|
||||||
|
private const val AN_ENDPOINT_HOST = "https://aendpointurl.com"
|
||||||
|
private const val AN_ENDPOINT = "$AN_ENDPOINT_HOST/with/path"
|
||||||
|
private const val A_GATEWAY_URL = "$AN_ENDPOINT_HOST/_matrix/push/v1/notify"
|
||||||
|
private const val FALLBACK_GATEWAY_URL = "https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify"
|
||||||
|
|
||||||
|
class UnifiedPushMessageDelegateTest {
|
||||||
|
|
||||||
|
private val fakePushHandler = FakePushHandler()
|
||||||
|
private val fakeEndpointReader = FakeEndpointReader()
|
||||||
|
private val fakePushModule = FakePushModule().also {
|
||||||
|
it.givenPushHandler().returns(fakePushHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val unifiedPushReceiver = UnifiedPushMessageDelegate(
|
||||||
|
CoroutineScope(UnconfinedTestDispatcher()),
|
||||||
|
pushModuleProvider = { _ -> fakePushModule.instance },
|
||||||
|
endpointReader = fakeEndpointReader,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `parses incoming message payloads`() = runExpectTest {
|
||||||
|
fakePushHandler.expect { it.onMessageReceived(EventId(AN_EVENT_ID), RoomId(A_ROOM_ID)) }
|
||||||
|
val messageBytes = createMessage(A_ROOM_ID, AN_EVENT_ID)
|
||||||
|
|
||||||
|
unifiedPushReceiver.onMessage(A_CONTEXT.instance, messageBytes)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given endpoint is a gateway, then uses original endpoint url`() = runExpectTest {
|
||||||
|
fakeEndpointReader.given(A_GATEWAY_URL).returns("""{"unifiedpush":{"gateway":"matrix"}}""")
|
||||||
|
fakePushHandler.expect { it.onNewToken(PushTokenPayload(token = AN_ENDPOINT, gatewayUrl = A_GATEWAY_URL)) }
|
||||||
|
|
||||||
|
unifiedPushReceiver.onNewEndpoint(A_CONTEXT.instance, AN_ENDPOINT)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given endpoint is not a gateway, then uses fallback endpoint url`() = runExpectTest {
|
||||||
|
fakeEndpointReader.given(A_GATEWAY_URL).returns("")
|
||||||
|
fakePushHandler.expect { it.onNewToken(PushTokenPayload(token = AN_ENDPOINT, gatewayUrl = FALLBACK_GATEWAY_URL)) }
|
||||||
|
|
||||||
|
unifiedPushReceiver.onNewEndpoint(A_CONTEXT.instance, AN_ENDPOINT)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createMessage(roomId: String, eventId: String) = """
|
||||||
|
{
|
||||||
|
"notification": {
|
||||||
|
"room_id": "$roomId",
|
||||||
|
"event_id": "$eventId"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent().toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakePushModule {
|
||||||
|
val instance = mockk<PushModule>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
every { instance.dispatcher() }.returns(aCoroutineDispatchers())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun givenPushHandler() = every { instance.pushHandler() }.delegateReturn()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeEndpointReader : suspend (URL) -> String by mockk() {
|
||||||
|
|
||||||
|
fun given(url: String) = coEvery { this@FakeEndpointReader.invoke(URL(url)) }.delegateReturn()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package app.dapk.st.push.unifiedpush
|
||||||
|
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import app.dapk.st.push.Registrar
|
||||||
|
import fake.FakeContext
|
||||||
|
import fake.FakePackageManager
|
||||||
|
import io.mockk.Called
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
import test.delegateReturn
|
||||||
|
import test.runExpectTest
|
||||||
|
|
||||||
|
private val A_COMPONENT_NAME = FakeComponentName()
|
||||||
|
private val A_REGISTRAR_SELECTION = Registrar("a-registrar")
|
||||||
|
private const val A_SAVED_DISTRIBUTOR = "a distributor"
|
||||||
|
|
||||||
|
class UnifiedPushRegistrarTest {
|
||||||
|
|
||||||
|
private val fakePackageManager = FakePackageManager()
|
||||||
|
private val fakeContext = FakeContext().also {
|
||||||
|
it.givenPackageManager().returns(fakePackageManager.instance)
|
||||||
|
}
|
||||||
|
private val fakeUnifiedPush = FakeUnifiedPush()
|
||||||
|
private val fakeComponentFactory = { _: Context -> A_COMPONENT_NAME.instance }
|
||||||
|
|
||||||
|
private val registrar = UnifiedPushRegistrar(fakeContext.instance, fakeUnifiedPush, fakeComponentFactory)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when unregistering, then updates unified push and disables component`() = runExpectTest {
|
||||||
|
fakeUnifiedPush.expect { it.unregisterApp() }
|
||||||
|
fakePackageManager.instance.expect {
|
||||||
|
it.setComponentEnabledSetting(A_COMPONENT_NAME.instance, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
|
||||||
|
}
|
||||||
|
|
||||||
|
registrar.unregister()
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when registering selection, then updates unified push and enables component`() = runExpectTest {
|
||||||
|
fakeUnifiedPush.expect { it.registerApp() }
|
||||||
|
fakeUnifiedPush.expect { it.saveDistributor(A_REGISTRAR_SELECTION.id) }
|
||||||
|
fakePackageManager.instance.expect {
|
||||||
|
it.setComponentEnabledSetting(A_COMPONENT_NAME.instance, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
|
||||||
|
}
|
||||||
|
|
||||||
|
registrar.registerSelection(A_REGISTRAR_SELECTION)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given saved distributor, when registering current token, then updates unified push and enables component`() = runExpectTest {
|
||||||
|
fakeUnifiedPush.givenDistributor().returns(A_SAVED_DISTRIBUTOR)
|
||||||
|
fakeUnifiedPush.expect { it.registerApp() }
|
||||||
|
fakePackageManager.instance.expect {
|
||||||
|
it.setComponentEnabledSetting(A_COMPONENT_NAME.instance, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
|
||||||
|
}
|
||||||
|
|
||||||
|
registrar.registerCurrentToken()
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given no distributor, when registering current token, then does nothing`() = runExpectTest {
|
||||||
|
fakeUnifiedPush.givenDistributor().returns("")
|
||||||
|
|
||||||
|
registrar.registerCurrentToken()
|
||||||
|
|
||||||
|
verify(exactly = 0) { fakeUnifiedPush.registerApp() }
|
||||||
|
verify { fakePackageManager.instance wasNot Called }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given distributors, then returns them as Registrars`() {
|
||||||
|
fakeUnifiedPush.givenDistributors().returns(listOf("a", "b"))
|
||||||
|
|
||||||
|
val result = registrar.getDistributors()
|
||||||
|
|
||||||
|
result shouldBeEqualTo listOf(Registrar("a"), Registrar("b"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FakeUnifiedPush : UnifiedPush by mockk() {
|
||||||
|
fun givenDistributor() = every { getDistributor() }.delegateReturn()
|
||||||
|
fun givenDistributors() = every { getDistributors() }.delegateReturn()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeComponentName {
|
||||||
|
val instance = mockk<ComponentName>()
|
||||||
|
}
|
|
@ -1,8 +1,16 @@
|
||||||
package fake
|
package fake
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
|
import test.delegateReturn
|
||||||
|
|
||||||
class FakeContext {
|
class FakeContext {
|
||||||
val instance = mockk<Context>()
|
val instance = mockk<Context>()
|
||||||
|
fun givenPackageManager() = every { instance.packageManager }.delegateReturn()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakePackageManager {
|
||||||
|
val instance = mockk<PackageManager>()
|
||||||
}
|
}
|
|
@ -15,7 +15,6 @@ import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import test.delegateReturn
|
import test.delegateReturn
|
||||||
import test.expect
|
|
||||||
import test.runExpectTest
|
import test.runExpectTest
|
||||||
|
|
||||||
private const val SUMMARY_ID = 101
|
private const val SUMMARY_ID = 101
|
||||||
|
@ -45,12 +44,13 @@ class NotificationRendererTest {
|
||||||
@Test
|
@Test
|
||||||
fun `given removed rooms when rendering then cancels notifications with cancelled room ids`() = runExpectTest {
|
fun `given removed rooms when rendering then cancels notifications with cancelled room ids`() = runExpectTest {
|
||||||
val removedRooms = setOf(aRoomId("id-1"), aRoomId("id-2"))
|
val removedRooms = setOf(aRoomId("id-1"), aRoomId("id-2"))
|
||||||
fakeNotificationFactory.instance.expect { it.mapToNotifications(NotificationState(emptyMap(), removedRooms, emptySet(), emptySet())) }
|
val state = aNotificationState(removedRooms = removedRooms)
|
||||||
fakeNotificationManager.instance.expectUnit {
|
fakeNotificationFactory.givenNotifications(state).returns(aNotifications())
|
||||||
removedRooms.forEach { removedRoom -> it.cancel(removedRoom.value, ROOM_MESSAGE_ID) }
|
fakeNotificationManager.instance.expectUnit { removedRooms.forEach { removedRoom -> it.cancel(removedRoom.value, ROOM_MESSAGE_ID) } }
|
||||||
}
|
fakeNotificationManager.instance.expectUnit { it.cancel(SUMMARY_ID) }
|
||||||
|
|
||||||
|
notificationRenderer.render(state)
|
||||||
|
|
||||||
notificationRenderer.render(NotificationState(emptyMap(), removedRooms, emptySet(), emptySet()))
|
|
||||||
verifyExpects()
|
verifyExpects()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ def excludes = [
|
||||||
'**/*Activity*',
|
'**/*Activity*',
|
||||||
'**/*AndroidService*',
|
'**/*AndroidService*',
|
||||||
'**/*Application*',
|
'**/*Application*',
|
||||||
|
'**/*Receiver*',
|
||||||
|
|
||||||
// Generated
|
// Generated
|
||||||
'**/*serializer*',
|
'**/*serializer*',
|
||||||
|
|
Loading…
Reference in New Issue