Add test on DefaultPushHandler
This commit is contained in:
parent
839242d7bc
commit
3866e49822
7 changed files with 411 additions and 41 deletions
|
|
@ -19,7 +19,9 @@ package io.element.android.libraries.push.impl.notifications
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
||||||
|
|
@ -67,6 +69,7 @@ interface NotifiableEventResolver {
|
||||||
suspend fun resolveEvent(sessionId: SessionId, roomId: RoomId, eventId: EventId): NotifiableEvent?
|
suspend fun resolveEvent(sessionId: SessionId, roomId: RoomId, eventId: EventId): NotifiableEvent?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
class DefaultNotifiableEventResolver @Inject constructor(
|
class DefaultNotifiableEventResolver @Inject constructor(
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val clock: SystemClock,
|
private val clock: SystemClock,
|
||||||
|
|
|
||||||
|
|
@ -16,27 +16,19 @@
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.push
|
package io.element.android.libraries.push.impl.push
|
||||||
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
import io.element.android.libraries.core.meta.BuildMeta
|
import io.element.android.libraries.core.meta.BuildMeta
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||||
import io.element.android.libraries.push.impl.notifications.DefaultNotificationDrawerManager
|
|
||||||
import io.element.android.libraries.push.impl.notifications.NotifiableEventResolver
|
import io.element.android.libraries.push.impl.notifications.NotifiableEventResolver
|
||||||
import io.element.android.libraries.push.impl.store.DefaultPushDataStore
|
|
||||||
import io.element.android.libraries.push.impl.test.DefaultTestPush
|
import io.element.android.libraries.push.impl.test.DefaultTestPush
|
||||||
import io.element.android.libraries.push.impl.troubleshoot.DiagnosticPushHandler
|
import io.element.android.libraries.push.impl.troubleshoot.DiagnosticPushHandler
|
||||||
import io.element.android.libraries.pushproviders.api.PushData
|
import io.element.android.libraries.pushproviders.api.PushData
|
||||||
import io.element.android.libraries.pushproviders.api.PushHandler
|
import io.element.android.libraries.pushproviders.api.PushHandler
|
||||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.SupervisorJob
|
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -44,23 +36,15 @@ private val loggerTag = LoggerTag("PushHandler", LoggerTag.PushLoggerTag)
|
||||||
|
|
||||||
@ContributesBinding(AppScope::class)
|
@ContributesBinding(AppScope::class)
|
||||||
class DefaultPushHandler @Inject constructor(
|
class DefaultPushHandler @Inject constructor(
|
||||||
private val defaultNotificationDrawerManager: DefaultNotificationDrawerManager,
|
private val onNotifiableEventReceived: OnNotifiableEventReceived,
|
||||||
private val notifiableEventResolver: NotifiableEventResolver,
|
private val notifiableEventResolver: NotifiableEventResolver,
|
||||||
private val defaultPushDataStore: DefaultPushDataStore,
|
private val incrementPushDataStore: IncrementPushDataStore,
|
||||||
private val userPushStoreFactory: UserPushStoreFactory,
|
private val userPushStoreFactory: UserPushStoreFactory,
|
||||||
private val pushClientSecret: PushClientSecret,
|
private val pushClientSecret: PushClientSecret,
|
||||||
// private val actionIds: NotificationActionIds,
|
|
||||||
private val buildMeta: BuildMeta,
|
private val buildMeta: BuildMeta,
|
||||||
private val matrixAuthenticationService: MatrixAuthenticationService,
|
private val matrixAuthenticationService: MatrixAuthenticationService,
|
||||||
private val diagnosticPushHandler: DiagnosticPushHandler,
|
private val diagnosticPushHandler: DiagnosticPushHandler,
|
||||||
) : PushHandler {
|
) : PushHandler {
|
||||||
private val coroutineScope = CoroutineScope(SupervisorJob())
|
|
||||||
|
|
||||||
// UI handler
|
|
||||||
private val uiHandler by lazy {
|
|
||||||
Handler(Looper.getMainLooper())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when message is received.
|
* Called when message is received.
|
||||||
*
|
*
|
||||||
|
|
@ -68,21 +52,15 @@ class DefaultPushHandler @Inject constructor(
|
||||||
*/
|
*/
|
||||||
override suspend fun handle(pushData: PushData) {
|
override suspend fun handle(pushData: PushData) {
|
||||||
Timber.tag(loggerTag.value).d("## handling pushData: ${pushData.roomId}/${pushData.eventId}")
|
Timber.tag(loggerTag.value).d("## handling pushData: ${pushData.roomId}/${pushData.eventId}")
|
||||||
|
|
||||||
if (buildMeta.lowPrivacyLoggingEnabled) {
|
if (buildMeta.lowPrivacyLoggingEnabled) {
|
||||||
Timber.tag(loggerTag.value).d("## pushData: $pushData")
|
Timber.tag(loggerTag.value).d("## pushData: $pushData")
|
||||||
}
|
}
|
||||||
|
incrementPushDataStore.incrementPushCounter()
|
||||||
defaultPushDataStore.incrementPushCounter()
|
|
||||||
|
|
||||||
// Diagnostic Push
|
// Diagnostic Push
|
||||||
if (pushData.eventId == DefaultTestPush.TEST_EVENT_ID) {
|
if (pushData.eventId == DefaultTestPush.TEST_EVENT_ID) {
|
||||||
diagnosticPushHandler.handlePush()
|
diagnosticPushHandler.handlePush()
|
||||||
return
|
} else {
|
||||||
}
|
handleInternal(pushData)
|
||||||
|
|
||||||
uiHandler.post {
|
|
||||||
coroutineScope.launch(Dispatchers.IO) { handleInternal(pushData) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,7 +76,6 @@ class DefaultPushHandler @Inject constructor(
|
||||||
} else {
|
} else {
|
||||||
Timber.tag(loggerTag.value).d("## handleInternal()")
|
Timber.tag(loggerTag.value).d("## handleInternal()")
|
||||||
}
|
}
|
||||||
|
|
||||||
val clientSecret = pushData.clientSecret
|
val clientSecret = pushData.clientSecret
|
||||||
// clientSecret should not be null. If this happens, restore default session
|
// clientSecret should not be null. If this happens, restore default session
|
||||||
val userId = clientSecret
|
val userId = clientSecret
|
||||||
|
|
@ -109,27 +86,22 @@ class DefaultPushHandler @Inject constructor(
|
||||||
?: run {
|
?: run {
|
||||||
matrixAuthenticationService.getLatestSessionId()
|
matrixAuthenticationService.getLatestSessionId()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
Timber.w("Unable to get a session")
|
Timber.w("Unable to get a session")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val notifiableEvent = notifiableEventResolver.resolveEvent(userId, pushData.roomId, pushData.eventId)
|
|
||||||
|
|
||||||
if (notifiableEvent == null) {
|
|
||||||
Timber.w("Unable to get a notification data")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val userPushStore = userPushStoreFactory.getOrCreate(userId)
|
val userPushStore = userPushStoreFactory.getOrCreate(userId)
|
||||||
if (!userPushStore.getNotificationEnabledForDevice().first()) {
|
if (userPushStore.getNotificationEnabledForDevice().first()) {
|
||||||
|
val notifiableEvent = notifiableEventResolver.resolveEvent(userId, pushData.roomId, pushData.eventId)
|
||||||
|
if (notifiableEvent == null) {
|
||||||
|
Timber.w("Unable to get a notification data")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
onNotifiableEventReceived.onNotifiableEventReceived(notifiableEvent)
|
||||||
|
} else {
|
||||||
// TODO We need to check if this is an incoming call
|
// TODO We need to check if this is an incoming call
|
||||||
Timber.tag(loggerTag.value).i("Notification are disabled for this device, ignore push.")
|
Timber.tag(loggerTag.value).i("Notification are disabled for this device, ignore push.")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultNotificationDrawerManager.onNotifiableEventReceived(notifiableEvent)
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.tag(loggerTag.value).e(e, "## handleInternal() failed")
|
Timber.tag(loggerTag.value).e(e, "## handleInternal() failed")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.impl.push
|
||||||
|
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.libraries.push.impl.store.DefaultPushDataStore
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
interface IncrementPushDataStore {
|
||||||
|
suspend fun incrementPushCounter()
|
||||||
|
}
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
|
class DefaultIncrementPushDataStore @Inject constructor(
|
||||||
|
private val defaultPushDataStore: DefaultPushDataStore
|
||||||
|
) : IncrementPushDataStore {
|
||||||
|
override suspend fun incrementPushCounter() {
|
||||||
|
defaultPushDataStore.incrementPushCounter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.impl.push
|
||||||
|
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.libraries.push.impl.notifications.DefaultNotificationDrawerManager
|
||||||
|
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
interface OnNotifiableEventReceived {
|
||||||
|
fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
|
class DefaultOnNotifiableEventReceived @Inject constructor(
|
||||||
|
private val defaultNotificationDrawerManager: DefaultNotificationDrawerManager,
|
||||||
|
) : OnNotifiableEventReceived {
|
||||||
|
override fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent) {
|
||||||
|
defaultNotificationDrawerManager.onNotifiableEventReceived(notifiableEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.impl.notifications
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
|
||||||
|
|
||||||
|
class FakeNotifiableEventResolver(
|
||||||
|
private val notifiableEventResult: (SessionId, RoomId, EventId) -> NotifiableEvent? = { _, _, _ -> TODO() }
|
||||||
|
) : NotifiableEventResolver {
|
||||||
|
override suspend fun resolveEvent(sessionId: SessionId, roomId: RoomId, eventId: EventId): NotifiableEvent? {
|
||||||
|
return notifiableEventResult(sessionId, roomId, eventId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,267 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.impl.push
|
||||||
|
|
||||||
|
import app.cash.turbine.test
|
||||||
|
import io.element.android.libraries.core.meta.BuildMeta
|
||||||
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||||
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||||
|
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||||
|
import io.element.android.libraries.matrix.test.A_SECRET
|
||||||
|
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||||
|
import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService
|
||||||
|
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||||
|
import io.element.android.libraries.push.impl.notifications.FakeNotifiableEventResolver
|
||||||
|
import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent
|
||||||
|
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
|
||||||
|
import io.element.android.libraries.push.impl.test.DefaultTestPush
|
||||||
|
import io.element.android.libraries.push.impl.troubleshoot.DiagnosticPushHandler
|
||||||
|
import io.element.android.libraries.pushproviders.api.PushData
|
||||||
|
import io.element.android.libraries.pushstore.api.UserPushStore
|
||||||
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||||
|
import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStore
|
||||||
|
import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStoreFactory
|
||||||
|
import io.element.android.libraries.pushstore.test.userpushstore.clientsecret.FakePushClientSecret
|
||||||
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
|
import io.element.android.tests.testutils.lambda.value
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class DefaultPushHandlerTest {
|
||||||
|
@Test
|
||||||
|
fun `when classical PushData is received, the notification drawer is informed`() = runTest {
|
||||||
|
val aNotifiableMessageEvent = aNotifiableMessageEvent()
|
||||||
|
val notifiableEventResult =
|
||||||
|
lambdaRecorder<SessionId, RoomId, EventId, NotifiableEvent> { _, _, _ -> aNotifiableMessageEvent }
|
||||||
|
val onNotifiableEventReceived = lambdaRecorder<NotifiableEvent, Unit> {}
|
||||||
|
val incrementPushCounterResult = lambdaRecorder<Unit> {}
|
||||||
|
val aPushData = PushData(
|
||||||
|
eventId = AN_EVENT_ID,
|
||||||
|
roomId = A_ROOM_ID,
|
||||||
|
unread = 0,
|
||||||
|
clientSecret = A_SECRET,
|
||||||
|
)
|
||||||
|
val defaultPushHandler = createDefaultPushHandler(
|
||||||
|
onNotifiableEventReceived = onNotifiableEventReceived,
|
||||||
|
notifiableEventResult = notifiableEventResult,
|
||||||
|
pushClientSecret = FakePushClientSecret(
|
||||||
|
getUserIdFromSecretResult = { A_USER_ID }
|
||||||
|
),
|
||||||
|
incrementPushCounterResult = incrementPushCounterResult
|
||||||
|
)
|
||||||
|
defaultPushHandler.handle(aPushData)
|
||||||
|
incrementPushCounterResult.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
notifiableEventResult.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(value(A_USER_ID), value(A_ROOM_ID), value(AN_EVENT_ID))
|
||||||
|
onNotifiableEventReceived.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(value(aNotifiableMessageEvent))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when classical PushData is received, but notifications are disabled, nothing happen`() =
|
||||||
|
runTest {
|
||||||
|
val aNotifiableMessageEvent = aNotifiableMessageEvent()
|
||||||
|
val notifiableEventResult =
|
||||||
|
lambdaRecorder<SessionId, RoomId, EventId, NotifiableEvent> { _, _, _ -> aNotifiableMessageEvent }
|
||||||
|
val onNotifiableEventReceived = lambdaRecorder<NotifiableEvent, Unit> {}
|
||||||
|
val incrementPushCounterResult = lambdaRecorder<Unit> {}
|
||||||
|
val aPushData = PushData(
|
||||||
|
eventId = AN_EVENT_ID,
|
||||||
|
roomId = A_ROOM_ID,
|
||||||
|
unread = 0,
|
||||||
|
clientSecret = A_SECRET,
|
||||||
|
)
|
||||||
|
val defaultPushHandler = createDefaultPushHandler(
|
||||||
|
onNotifiableEventReceived = onNotifiableEventReceived,
|
||||||
|
notifiableEventResult = notifiableEventResult,
|
||||||
|
pushClientSecret = FakePushClientSecret(
|
||||||
|
getUserIdFromSecretResult = { A_USER_ID }
|
||||||
|
),
|
||||||
|
userPushStore = FakeUserPushStore().apply {
|
||||||
|
setNotificationEnabledForDevice(false)
|
||||||
|
},
|
||||||
|
incrementPushCounterResult = incrementPushCounterResult
|
||||||
|
)
|
||||||
|
defaultPushHandler.handle(aPushData)
|
||||||
|
incrementPushCounterResult.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
notifiableEventResult.assertions()
|
||||||
|
.isNeverCalled()
|
||||||
|
onNotifiableEventReceived.assertions()
|
||||||
|
.isNeverCalled()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when PushData is received, but client secret is not known, fallback the latest session`() =
|
||||||
|
runTest {
|
||||||
|
val aNotifiableMessageEvent = aNotifiableMessageEvent()
|
||||||
|
val notifiableEventResult =
|
||||||
|
lambdaRecorder<SessionId, RoomId, EventId, NotifiableEvent> { _, _, _ -> aNotifiableMessageEvent }
|
||||||
|
val onNotifiableEventReceived = lambdaRecorder<NotifiableEvent, Unit> {}
|
||||||
|
val incrementPushCounterResult = lambdaRecorder<Unit> {}
|
||||||
|
val aPushData = PushData(
|
||||||
|
eventId = AN_EVENT_ID,
|
||||||
|
roomId = A_ROOM_ID,
|
||||||
|
unread = 0,
|
||||||
|
clientSecret = A_SECRET,
|
||||||
|
)
|
||||||
|
val defaultPushHandler = createDefaultPushHandler(
|
||||||
|
onNotifiableEventReceived = onNotifiableEventReceived,
|
||||||
|
notifiableEventResult = notifiableEventResult,
|
||||||
|
pushClientSecret = FakePushClientSecret(
|
||||||
|
getUserIdFromSecretResult = { null }
|
||||||
|
),
|
||||||
|
matrixAuthenticationService = FakeAuthenticationService().apply {
|
||||||
|
getLatestSessionIdLambda = { A_USER_ID }
|
||||||
|
},
|
||||||
|
incrementPushCounterResult = incrementPushCounterResult
|
||||||
|
)
|
||||||
|
defaultPushHandler.handle(aPushData)
|
||||||
|
incrementPushCounterResult.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
notifiableEventResult.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(value(A_USER_ID), value(A_ROOM_ID), value(AN_EVENT_ID))
|
||||||
|
onNotifiableEventReceived.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(value(aNotifiableMessageEvent))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when PushData is received, but client secret is not known, and there is no latest session, nothing happen`() =
|
||||||
|
runTest {
|
||||||
|
val aNotifiableMessageEvent = aNotifiableMessageEvent()
|
||||||
|
val notifiableEventResult =
|
||||||
|
lambdaRecorder<SessionId, RoomId, EventId, NotifiableEvent> { _, _, _ -> aNotifiableMessageEvent }
|
||||||
|
val onNotifiableEventReceived = lambdaRecorder<NotifiableEvent, Unit> {}
|
||||||
|
val incrementPushCounterResult = lambdaRecorder<Unit> {}
|
||||||
|
val aPushData = PushData(
|
||||||
|
eventId = AN_EVENT_ID,
|
||||||
|
roomId = A_ROOM_ID,
|
||||||
|
unread = 0,
|
||||||
|
clientSecret = A_SECRET,
|
||||||
|
)
|
||||||
|
val defaultPushHandler = createDefaultPushHandler(
|
||||||
|
onNotifiableEventReceived = onNotifiableEventReceived,
|
||||||
|
notifiableEventResult = notifiableEventResult,
|
||||||
|
pushClientSecret = FakePushClientSecret(
|
||||||
|
getUserIdFromSecretResult = { null }
|
||||||
|
),
|
||||||
|
matrixAuthenticationService = FakeAuthenticationService().apply {
|
||||||
|
getLatestSessionIdLambda = { null }
|
||||||
|
},
|
||||||
|
incrementPushCounterResult = incrementPushCounterResult
|
||||||
|
)
|
||||||
|
defaultPushHandler.handle(aPushData)
|
||||||
|
incrementPushCounterResult.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
notifiableEventResult.assertions()
|
||||||
|
.isNeverCalled()
|
||||||
|
onNotifiableEventReceived.assertions()
|
||||||
|
.isNeverCalled()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when classical PushData is received, but not able to resolve the event, nothing happen`() =
|
||||||
|
runTest {
|
||||||
|
val notifiableEventResult =
|
||||||
|
lambdaRecorder<SessionId, RoomId, EventId, NotifiableEvent?> { _, _, _ -> null }
|
||||||
|
val onNotifiableEventReceived = lambdaRecorder<NotifiableEvent, Unit> {}
|
||||||
|
val incrementPushCounterResult = lambdaRecorder<Unit> {}
|
||||||
|
val aPushData = PushData(
|
||||||
|
eventId = AN_EVENT_ID,
|
||||||
|
roomId = A_ROOM_ID,
|
||||||
|
unread = 0,
|
||||||
|
clientSecret = A_SECRET,
|
||||||
|
)
|
||||||
|
val defaultPushHandler = createDefaultPushHandler(
|
||||||
|
onNotifiableEventReceived = onNotifiableEventReceived,
|
||||||
|
notifiableEventResult = notifiableEventResult,
|
||||||
|
buildMeta = aBuildMeta(
|
||||||
|
// Also test `lowPrivacyLoggingEnabled = false` here
|
||||||
|
lowPrivacyLoggingEnabled = false
|
||||||
|
),
|
||||||
|
pushClientSecret = FakePushClientSecret(
|
||||||
|
getUserIdFromSecretResult = { A_USER_ID }
|
||||||
|
),
|
||||||
|
incrementPushCounterResult = incrementPushCounterResult
|
||||||
|
)
|
||||||
|
defaultPushHandler.handle(aPushData)
|
||||||
|
incrementPushCounterResult.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
notifiableEventResult.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(value(A_USER_ID), value(A_ROOM_ID), value(AN_EVENT_ID))
|
||||||
|
onNotifiableEventReceived.assertions()
|
||||||
|
.isNeverCalled()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when diagnostic PushData is received, the diagnostic push handler is informed `() =
|
||||||
|
runTest {
|
||||||
|
val aPushData = PushData(
|
||||||
|
eventId = DefaultTestPush.TEST_EVENT_ID,
|
||||||
|
roomId = A_ROOM_ID,
|
||||||
|
unread = 0,
|
||||||
|
clientSecret = A_SECRET,
|
||||||
|
)
|
||||||
|
val diagnosticPushHandler = DiagnosticPushHandler()
|
||||||
|
val defaultPushHandler = createDefaultPushHandler(
|
||||||
|
diagnosticPushHandler = diagnosticPushHandler,
|
||||||
|
incrementPushCounterResult = { }
|
||||||
|
)
|
||||||
|
diagnosticPushHandler.state.test {
|
||||||
|
defaultPushHandler.handle(aPushData)
|
||||||
|
awaitItem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createDefaultPushHandler(
|
||||||
|
onNotifiableEventReceived: (NotifiableEvent) -> Unit = { TODO() },
|
||||||
|
notifiableEventResult: (SessionId, RoomId, EventId) -> NotifiableEvent? = { _, _, _ -> TODO() },
|
||||||
|
incrementPushCounterResult: () -> Unit = { TODO() },
|
||||||
|
userPushStore: UserPushStore = FakeUserPushStore(),
|
||||||
|
pushClientSecret: PushClientSecret = FakePushClientSecret(),
|
||||||
|
buildMeta: BuildMeta = aBuildMeta(),
|
||||||
|
matrixAuthenticationService: MatrixAuthenticationService = FakeAuthenticationService(),
|
||||||
|
diagnosticPushHandler: DiagnosticPushHandler = DiagnosticPushHandler(),
|
||||||
|
): DefaultPushHandler {
|
||||||
|
return DefaultPushHandler(
|
||||||
|
onNotifiableEventReceived = FakeOnNotifiableEventReceived(onNotifiableEventReceived),
|
||||||
|
notifiableEventResolver = FakeNotifiableEventResolver(notifiableEventResult),
|
||||||
|
incrementPushDataStore = object : IncrementPushDataStore {
|
||||||
|
override suspend fun incrementPushCounter() {
|
||||||
|
incrementPushCounterResult()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
userPushStoreFactory = FakeUserPushStoreFactory(userPushStore),
|
||||||
|
pushClientSecret = pushClientSecret,
|
||||||
|
buildMeta = buildMeta,
|
||||||
|
matrixAuthenticationService = matrixAuthenticationService,
|
||||||
|
diagnosticPushHandler = diagnosticPushHandler,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.impl.push
|
||||||
|
|
||||||
|
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
|
||||||
|
|
||||||
|
class FakeOnNotifiableEventReceived(
|
||||||
|
private val onNotifiableEventReceivedResult: (NotifiableEvent) -> Unit,
|
||||||
|
) : OnNotifiableEventReceived {
|
||||||
|
override fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent) {
|
||||||
|
onNotifiableEventReceivedResult(notifiableEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue