mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-10-31 16:22:49 +00:00
Merge pull request #7584 from element-hq/feature/bma/fixSilentNotification
Ensure that noisy notifications are still noisy when the app has a PIN code.
This commit is contained in:
+2
-1
@@ -30,6 +30,7 @@ fun aNotificationData(
|
||||
senderIsNameAmbiguous: Boolean = false,
|
||||
roomDisplayName: String? = A_ROOM_NAME,
|
||||
roomJoinRule: JoinRule? = null,
|
||||
isNoisy: Boolean = false,
|
||||
): NotificationData {
|
||||
return NotificationData(
|
||||
sessionId = A_SESSION_ID,
|
||||
@@ -45,7 +46,7 @@ fun aNotificationData(
|
||||
isDm = false,
|
||||
isSpace = isSpace,
|
||||
isEncrypted = false,
|
||||
isNoisy = false,
|
||||
isNoisy = isNoisy,
|
||||
timestamp = timestamp,
|
||||
content = content,
|
||||
hasMention = hasMention,
|
||||
|
||||
+1
@@ -298,6 +298,7 @@ class DefaultNotifiableEventResolver(
|
||||
roomId = roomId,
|
||||
eventId = eventId,
|
||||
cause = "Unable to decrypt event content",
|
||||
noisy = isNoisy,
|
||||
)
|
||||
ResolvedPushEvent.Event(fallbackNotifiableEvent)
|
||||
}
|
||||
|
||||
+7
@@ -274,6 +274,12 @@ private fun NotifiableEvent.toFallbackNotifiableEvent(): FallbackNotifiableEvent
|
||||
is FallbackNotifiableEvent -> timestamp
|
||||
is NotifiableRingingCallEvent -> return null
|
||||
}
|
||||
val noisy = when (this) {
|
||||
is NotifiableMessageEvent -> noisy
|
||||
is InviteNotifiableEvent -> noisy
|
||||
is SimpleNotifiableEvent -> noisy
|
||||
is FallbackNotifiableEvent -> noisy
|
||||
}
|
||||
return FallbackNotifiableEvent(
|
||||
sessionId = sessionId,
|
||||
roomId = roomId,
|
||||
@@ -283,6 +289,7 @@ private fun NotifiableEvent.toFallbackNotifiableEvent(): FallbackNotifiableEvent
|
||||
canBeReplaced = false,
|
||||
isRedacted = false,
|
||||
isUpdated = false,
|
||||
noisy = noisy,
|
||||
timestamp = timestamp,
|
||||
cause = null,
|
||||
)
|
||||
|
||||
+2
@@ -24,6 +24,7 @@ class FallbackNotificationFactory(
|
||||
roomId: RoomId,
|
||||
eventId: EventId,
|
||||
cause: String?,
|
||||
noisy: Boolean,
|
||||
): FallbackNotifiableEvent = FallbackNotifiableEvent(
|
||||
sessionId = sessionId,
|
||||
roomId = roomId,
|
||||
@@ -32,6 +33,7 @@ class FallbackNotificationFactory(
|
||||
canBeReplaced = true,
|
||||
isRedacted = false,
|
||||
isUpdated = false,
|
||||
noisy = noisy,
|
||||
timestamp = clock.epochMillis(),
|
||||
description = "",
|
||||
cause = cause,
|
||||
|
||||
+1
@@ -170,6 +170,7 @@ class DefaultNotificationResultProcessor(
|
||||
roomId = RoomId(request.roomId),
|
||||
eventId = EventId(request.eventId),
|
||||
cause = exception.message,
|
||||
noisy = false,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
+1
-1
@@ -317,7 +317,7 @@ class DefaultNotificationCreator(
|
||||
val fallbackNotifiableEvent = fallbackNotifiableEvents.first()
|
||||
val channelId = notificationChannels.getChannelIdForMessage(
|
||||
sessionId = fallbackNotifiableEvent.sessionId,
|
||||
noisy = false,
|
||||
noisy = fallbackNotifiableEvents.any { it.noisy },
|
||||
)
|
||||
val existingCounter = existingNotification
|
||||
?.extras
|
||||
|
||||
+1
@@ -25,6 +25,7 @@ data class FallbackNotifiableEvent(
|
||||
override val canBeReplaced: Boolean,
|
||||
override val isRedacted: Boolean,
|
||||
override val isUpdated: Boolean,
|
||||
val noisy: Boolean,
|
||||
val timestamp: Long,
|
||||
val cause: String?,
|
||||
) : NotifiableEvent
|
||||
|
||||
+35
@@ -712,6 +712,41 @@ class DefaultNotifiableEventResolverTest : RobolectricTest() {
|
||||
canBeReplaced = true,
|
||||
isRedacted = false,
|
||||
isUpdated = false,
|
||||
noisy = false,
|
||||
timestamp = A_FAKE_TIMESTAMP,
|
||||
cause = "Unable to decrypt event content",
|
||||
)
|
||||
)
|
||||
assertThat(result.getEvent(request)).isEqualTo(Result.success(expectedResult))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `resolve RoomEncrypted noisy`() = runTest {
|
||||
val sut = createDefaultNotifiableEventResolver(
|
||||
notificationResult = Result.success(
|
||||
mapOf(
|
||||
AN_EVENT_ID to Result.success(
|
||||
aNotificationData(
|
||||
content = NotificationContent.MessageLike.RoomEncrypted,
|
||||
isNoisy = true,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
val request = aPushRequest(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID, "firebase")
|
||||
val result = sut.resolveEvents(A_SESSION_ID, listOf(request))
|
||||
val expectedResult = ResolvedPushEvent.Event(
|
||||
FallbackNotifiableEvent(
|
||||
sessionId = A_SESSION_ID,
|
||||
roomId = A_ROOM_ID,
|
||||
eventId = AN_EVENT_ID,
|
||||
editedEventId = null,
|
||||
description = "",
|
||||
canBeReplaced = true,
|
||||
isRedacted = false,
|
||||
isUpdated = false,
|
||||
noisy = true,
|
||||
timestamp = A_FAKE_TIMESTAMP,
|
||||
cause = "Unable to decrypt event content",
|
||||
)
|
||||
|
||||
+142
-1
@@ -15,28 +15,35 @@ import io.element.android.features.enterprise.api.EnterpriseService
|
||||
import io.element.android.features.enterprise.test.FakeEnterpriseService
|
||||
import io.element.android.features.lockscreen.api.LockScreenService
|
||||
import io.element.android.features.lockscreen.test.FakeLockScreenService
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID_2
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID_2
|
||||
import io.element.android.libraries.matrix.test.A_THREAD_ID
|
||||
import io.element.android.libraries.matrix.test.A_THREAD_ID_2
|
||||
import io.element.android.libraries.matrix.test.A_TIMESTAMP
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||
import io.element.android.libraries.matrix.ui.media.test.FakeImageLoaderHolder
|
||||
import io.element.android.libraries.push.api.notifications.NotificationIdProvider
|
||||
import io.element.android.libraries.push.impl.notifications.factories.NotificationAccountParams
|
||||
import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator
|
||||
import io.element.android.libraries.push.impl.notifications.factories.aNotificationAccountParams
|
||||
import io.element.android.libraries.push.impl.notifications.fake.FakeActiveNotificationsProvider
|
||||
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator
|
||||
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDisplayer
|
||||
import io.element.android.libraries.push.impl.notifications.fake.FakeRoomGroupMessageCreator
|
||||
import io.element.android.libraries.push.impl.notifications.fake.FakeSummaryGroupMessageCreator
|
||||
import io.element.android.libraries.push.impl.notifications.fixtures.A_NOTIFICATION
|
||||
import io.element.android.libraries.push.impl.notifications.fixtures.aFallbackNotifiableEvent
|
||||
import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent
|
||||
import io.element.android.libraries.push.impl.notifications.fixtures.aSimpleNotifiableEvent
|
||||
import io.element.android.libraries.push.impl.notifications.fixtures.anInviteNotifiableEvent
|
||||
import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent
|
||||
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
|
||||
@@ -48,6 +55,8 @@ import io.element.android.services.appnavstate.api.AppNavigationStateService
|
||||
import io.element.android.services.appnavstate.test.FakeAppNavigationStateService
|
||||
import io.element.android.services.appnavstate.test.aNavigationState
|
||||
import io.element.android.services.appnavstate.test.anAppNavigationState
|
||||
import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP
|
||||
import io.element.android.tests.testutils.lambda.LambdaThreeParamsRecorder
|
||||
import io.element.android.tests.testutils.lambda.any
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
@@ -472,6 +481,137 @@ class DefaultNotificationDrawerManagerTest {
|
||||
extraInvocationsForNotificationSummary = 1,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `when the app is locked, a noisy message event produces a noisy fallback notification`() = testAppLockedNotifiableEventReceived(
|
||||
notifiableEvent = aNotifiableMessageEvent(noisy = true),
|
||||
expectedFallbackEvent = anExpectedFallbackNotifiableEvent(noisy = true, timestamp = A_TIMESTAMP),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `when the app is locked, a silent message event produces a silent fallback notification`() = testAppLockedNotifiableEventReceived(
|
||||
notifiableEvent = aNotifiableMessageEvent(noisy = false),
|
||||
expectedFallbackEvent = anExpectedFallbackNotifiableEvent(noisy = false, timestamp = A_TIMESTAMP),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `when the app is locked, a noisy invite event produces a noisy fallback notification`() = testAppLockedNotifiableEventReceived(
|
||||
notifiableEvent = anInviteNotifiableEvent(noisy = true),
|
||||
expectedFallbackEvent = anExpectedFallbackNotifiableEvent(noisy = true, timestamp = 0),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `when the app is locked, a silent invite event produces a silent fallback notification`() = testAppLockedNotifiableEventReceived(
|
||||
notifiableEvent = anInviteNotifiableEvent(noisy = false),
|
||||
expectedFallbackEvent = anExpectedFallbackNotifiableEvent(noisy = false, timestamp = 0),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `when the app is locked, a noisy simple event produces a noisy fallback notification`() = testAppLockedNotifiableEventReceived(
|
||||
notifiableEvent = aSimpleNotifiableEvent(noisy = true),
|
||||
expectedFallbackEvent = anExpectedFallbackNotifiableEvent(noisy = true, timestamp = 0),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `when the app is locked, a silent simple event produces a silent fallback notification`() = testAppLockedNotifiableEventReceived(
|
||||
notifiableEvent = aSimpleNotifiableEvent(noisy = false),
|
||||
expectedFallbackEvent = anExpectedFallbackNotifiableEvent(noisy = false, timestamp = 0),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `when the app is locked, a noisy fallback event stays noisy`() = testAppLockedNotifiableEventReceived(
|
||||
notifiableEvent = aFallbackNotifiableEvent(noisy = true),
|
||||
expectedFallbackEvent = anExpectedFallbackNotifiableEvent(noisy = true, timestamp = A_FAKE_TIMESTAMP),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `when the app is locked, a silent fallback event stays silent`() = testAppLockedNotifiableEventReceived(
|
||||
notifiableEvent = aFallbackNotifiableEvent(noisy = false),
|
||||
expectedFallbackEvent = anExpectedFallbackNotifiableEvent(noisy = false, timestamp = A_FAKE_TIMESTAMP),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `when the app is locked, all the events are grouped into a single fallback notification`() = runTest {
|
||||
val createFallbackNotificationResult = aCreateFallbackNotificationRecorder()
|
||||
val sut = createAppLockedNotificationDrawerManager(createFallbackNotificationResult)
|
||||
sut.onNotifiableEventsReceived(
|
||||
listOf(
|
||||
aNotifiableMessageEvent(noisy = false),
|
||||
aNotifiableMessageEvent(eventId = AN_EVENT_ID_2, noisy = true),
|
||||
)
|
||||
)
|
||||
createFallbackNotificationResult.assertions()
|
||||
.isCalledOnce()
|
||||
.with(
|
||||
value(null),
|
||||
any(),
|
||||
value(
|
||||
listOf(
|
||||
anExpectedFallbackNotifiableEvent(noisy = false, timestamp = A_TIMESTAMP),
|
||||
anExpectedFallbackNotifiableEvent(eventId = AN_EVENT_ID_2, noisy = true, timestamp = A_TIMESTAMP),
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when the app is not locked, no fallback notification is created`() = runTest {
|
||||
val createFallbackNotificationResult = aCreateFallbackNotificationRecorder()
|
||||
val sut = createDefaultNotificationDrawerManager(
|
||||
appNavigationStateService = FakeAppNavigationStateService(
|
||||
initialAppNavigationState = anAppNavigationState(isInForeground = false),
|
||||
),
|
||||
notificationCreator = FakeNotificationCreator(
|
||||
createFallbackNotificationResult = createFallbackNotificationResult,
|
||||
),
|
||||
lockScreenService = FakeLockScreenService().apply { setIsPinSetup(false) },
|
||||
)
|
||||
sut.onNotifiableEventsReceived(listOf(aNotifiableMessageEvent(noisy = true)))
|
||||
createFallbackNotificationResult.assertions().isNeverCalled()
|
||||
}
|
||||
|
||||
/**
|
||||
* The content of the original event must be stripped, only the noisy flag, the ids and the timestamp are kept.
|
||||
*/
|
||||
private fun anExpectedFallbackNotifiableEvent(
|
||||
eventId: EventId = AN_EVENT_ID,
|
||||
noisy: Boolean,
|
||||
timestamp: Long,
|
||||
) = aFallbackNotifiableEvent(
|
||||
eventId = eventId,
|
||||
description = null,
|
||||
canBeReplaced = false,
|
||||
noisy = noisy,
|
||||
timestamp = timestamp,
|
||||
cause = null,
|
||||
)
|
||||
|
||||
private fun aCreateFallbackNotificationRecorder() =
|
||||
lambdaRecorder<Notification?, NotificationAccountParams, List<FallbackNotifiableEvent>, Notification> { _, _, _ -> A_NOTIFICATION }
|
||||
|
||||
private fun TestScope.createAppLockedNotificationDrawerManager(
|
||||
createFallbackNotificationResult: LambdaThreeParamsRecorder<Notification?, NotificationAccountParams, List<FallbackNotifiableEvent>, Notification>,
|
||||
) = createDefaultNotificationDrawerManager(
|
||||
appNavigationStateService = FakeAppNavigationStateService(
|
||||
initialAppNavigationState = anAppNavigationState(isInForeground = false),
|
||||
),
|
||||
notificationCreator = FakeNotificationCreator(
|
||||
createFallbackNotificationResult = createFallbackNotificationResult,
|
||||
),
|
||||
lockScreenService = FakeLockScreenService().apply { setIsPinSetup(true) },
|
||||
)
|
||||
|
||||
private fun testAppLockedNotifiableEventReceived(
|
||||
notifiableEvent: NotifiableEvent,
|
||||
expectedFallbackEvent: FallbackNotifiableEvent,
|
||||
) = runTest {
|
||||
val createFallbackNotificationResult = aCreateFallbackNotificationRecorder()
|
||||
val sut = createAppLockedNotificationDrawerManager(createFallbackNotificationResult)
|
||||
sut.onNotifiableEventsReceived(listOf(notifiableEvent))
|
||||
createFallbackNotificationResult.assertions()
|
||||
.isCalledOnce()
|
||||
.with(value(null), any(), value(listOf(expectedFallbackEvent)))
|
||||
}
|
||||
|
||||
private fun testOnNotifiableEventReceived(
|
||||
appNavigationState: AppNavigationState,
|
||||
notifiableEvents: List<NotifiableEvent>,
|
||||
@@ -503,6 +643,7 @@ class DefaultNotificationDrawerManagerTest {
|
||||
fun TestScope.createDefaultNotificationDrawerManager(
|
||||
notificationDisplayer: NotificationDisplayer = FakeNotificationDisplayer(),
|
||||
notificationRenderer: NotificationRenderer? = null,
|
||||
notificationCreator: NotificationCreator = FakeNotificationCreator(),
|
||||
appNavigationStateService: AppNavigationStateService = FakeAppNavigationStateService(),
|
||||
roomGroupMessageCreator: RoomGroupMessageCreator = FakeRoomGroupMessageCreator(),
|
||||
summaryGroupMessageCreator: SummaryGroupMessageCreator = FakeSummaryGroupMessageCreator(),
|
||||
@@ -519,7 +660,7 @@ fun TestScope.createDefaultNotificationDrawerManager(
|
||||
notificationRenderer = notificationRenderer ?: NotificationRenderer(
|
||||
notificationDisplayer = notificationDisplayer,
|
||||
notificationDataFactory = DefaultNotificationDataFactory(
|
||||
notificationCreator = FakeNotificationCreator(),
|
||||
notificationCreator = notificationCreator,
|
||||
roomGroupMessageCreator = roomGroupMessageCreator,
|
||||
summaryGroupMessageCreator = summaryGroupMessageCreator,
|
||||
activeNotificationsProvider = activeNotificationsProvider,
|
||||
|
||||
+36
@@ -267,6 +267,42 @@ class DefaultNotificationResultProcessorTest {
|
||||
assertThat(receivedFallbackEvent).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when an event cannot be resolved, the generated fallback event is silent`() = runTest {
|
||||
val onNotifiableEventsReceived = lambdaRecorder<List<NotifiableEvent>, Unit> {}
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val processor = createDefaultNotificationResultProcessor(
|
||||
mutableBatteryOptimizationStore = FakeMutableBatteryOptimizationStore(
|
||||
showBatteryOptimizationBannerResult = lambdaRecorder<Unit> {},
|
||||
),
|
||||
pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
),
|
||||
onNotifiableEventsReceived = onNotifiableEventsReceived,
|
||||
)
|
||||
|
||||
runningProcessor(processor) {
|
||||
emit(mapOf(aPushRequest() to Result.failure(NotificationResolverException.UnknownError("Unable to resolve event"))))
|
||||
}
|
||||
|
||||
advanceTimeBy(300.milliseconds)
|
||||
|
||||
onNotifiableEventsReceived.assertions()
|
||||
.isCalledOnce()
|
||||
.with(
|
||||
value(
|
||||
listOf(
|
||||
aFallbackNotifiableEvent(
|
||||
description = "",
|
||||
canBeReplaced = true,
|
||||
noisy = false,
|
||||
cause = "Unable to resolve event",
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun TestScope.runningProcessor(processor: NotificationResultProcessor, block: suspend NotificationResultProcessor.() -> Unit) {
|
||||
processor.start()
|
||||
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.impl.notifications
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
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_SESSION_ID
|
||||
import io.element.android.libraries.push.impl.notifications.fixtures.aFallbackNotifiableEvent
|
||||
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
|
||||
import org.junit.Test
|
||||
|
||||
class FallbackNotificationFactoryTest {
|
||||
@Test
|
||||
fun `create silent event`() {
|
||||
val sut = FallbackNotificationFactory(FakeSystemClock())
|
||||
val result = sut.create(
|
||||
sessionId = A_SESSION_ID,
|
||||
roomId = A_ROOM_ID,
|
||||
eventId = AN_EVENT_ID,
|
||||
cause = "A cause",
|
||||
noisy = false,
|
||||
)
|
||||
assertThat(result).isEqualTo(
|
||||
aFallbackNotifiableEvent(
|
||||
description = "",
|
||||
canBeReplaced = true,
|
||||
noisy = false,
|
||||
cause = "A cause",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `create noisy event`() {
|
||||
val sut = FallbackNotificationFactory(FakeSystemClock())
|
||||
val result = sut.create(
|
||||
sessionId = A_SESSION_ID,
|
||||
roomId = A_ROOM_ID,
|
||||
eventId = AN_EVENT_ID,
|
||||
cause = "A cause",
|
||||
noisy = true,
|
||||
)
|
||||
assertThat(result).isEqualTo(
|
||||
aFallbackNotifiableEvent(
|
||||
description = "",
|
||||
canBeReplaced = true,
|
||||
noisy = true,
|
||||
cause = "A cause",
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
+54
-1
@@ -18,6 +18,7 @@ import io.element.android.appconfig.NotificationConfig
|
||||
import io.element.android.features.enterprise.api.EnterpriseService
|
||||
import io.element.android.features.enterprise.test.FakeEnterpriseService
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
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.AN_EVENT_ID_2
|
||||
import io.element.android.libraries.matrix.test.A_COLOR_INT
|
||||
@@ -33,6 +34,7 @@ import io.element.android.libraries.push.impl.notifications.DefaultNotificationB
|
||||
import io.element.android.libraries.push.impl.notifications.NotificationActionIds
|
||||
import io.element.android.libraries.push.impl.notifications.RoomEventGroupInfo
|
||||
import io.element.android.libraries.push.impl.notifications.channels.DefaultNotificationChannels
|
||||
import io.element.android.libraries.push.impl.notifications.channels.FakeNotificationChannels
|
||||
import io.element.android.libraries.push.impl.notifications.channels.NotificationChannels
|
||||
import io.element.android.libraries.push.impl.notifications.factories.action.AcceptInvitationActionFactory
|
||||
import io.element.android.libraries.push.impl.notifications.factories.action.MarkAsReadActionFactory
|
||||
@@ -47,6 +49,8 @@ import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvid
|
||||
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||
import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP
|
||||
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import io.element.android.tests.testutils.robolectric.RobolectricTest
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
@@ -82,7 +86,10 @@ class DefaultNotificationCreatorTest : RobolectricTest() {
|
||||
|
||||
@Test
|
||||
fun `test createFallbackNotification`() {
|
||||
val sut = createNotificationCreator()
|
||||
val channelIdForMessage = lambdaRecorder<SessionId, Boolean, String> { _, _ -> A_CHANNEL_ID }
|
||||
val sut = createNotificationCreator(
|
||||
notificationChannels = FakeNotificationChannels(channelIdForMessage = channelIdForMessage),
|
||||
)
|
||||
val result = sut.createFallbackNotification(
|
||||
existingNotification = null,
|
||||
notificationAccountParams = aNotificationAccountParams(),
|
||||
@@ -93,6 +100,50 @@ class DefaultNotificationCreatorTest : RobolectricTest() {
|
||||
result.commonAssertions(
|
||||
expectedCategory = null,
|
||||
)
|
||||
assertThat(result.channelId).isEqualTo(A_CHANNEL_ID)
|
||||
// The notification must be posted on the silent channel.
|
||||
channelIdForMessage.assertions().isCalledOnce().with(value(A_SESSION_ID), value(false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test createFallbackNotification noisy`() {
|
||||
val channelIdForMessage = lambdaRecorder<SessionId, Boolean, String> { _, _ -> A_CHANNEL_ID }
|
||||
val sut = createNotificationCreator(
|
||||
notificationChannels = FakeNotificationChannels(channelIdForMessage = channelIdForMessage),
|
||||
)
|
||||
val result = sut.createFallbackNotification(
|
||||
existingNotification = null,
|
||||
notificationAccountParams = aNotificationAccountParams(),
|
||||
fallbackNotifiableEvents = listOf(
|
||||
aFallbackNotifiableEvent(noisy = true),
|
||||
)
|
||||
)
|
||||
result.commonAssertions(
|
||||
expectedCategory = null,
|
||||
)
|
||||
assertThat(result.channelId).isEqualTo(A_CHANNEL_ID)
|
||||
// The notification must be posted on the noisy channel.
|
||||
channelIdForMessage.assertions().isCalledOnce().with(value(A_SESSION_ID), value(true))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test createFallbackNotification is noisy when at least one event is noisy`() {
|
||||
val channelIdForMessage = lambdaRecorder<SessionId, Boolean, String> { _, _ -> A_CHANNEL_ID }
|
||||
val sut = createNotificationCreator(
|
||||
notificationChannels = FakeNotificationChannels(channelIdForMessage = channelIdForMessage),
|
||||
)
|
||||
val result = sut.createFallbackNotification(
|
||||
existingNotification = null,
|
||||
notificationAccountParams = aNotificationAccountParams(),
|
||||
fallbackNotifiableEvents = listOf(
|
||||
aFallbackNotifiableEvent(noisy = false),
|
||||
aFallbackNotifiableEvent(eventId = AN_EVENT_ID_2, noisy = true),
|
||||
)
|
||||
)
|
||||
result.commonAssertions(
|
||||
expectedCategory = null,
|
||||
)
|
||||
channelIdForMessage.assertions().isCalledOnce().with(value(A_SESSION_ID), value(true))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -389,6 +440,8 @@ class DefaultNotificationCreatorTest : RobolectricTest() {
|
||||
}
|
||||
}
|
||||
|
||||
private const val A_CHANNEL_ID = "aChannelId"
|
||||
|
||||
const val MARK_AS_READ_ACTION_TITLE = "MarkAsReadAction"
|
||||
const val QUICK_REPLY_ACTION_TITLE = "QuickReplyAction"
|
||||
const val ACCEPT_INVITATION_ACTION_TITLE = "AcceptInvitationAction"
|
||||
|
||||
+22
-11
@@ -39,13 +39,14 @@ fun aSimpleNotifiableEvent(
|
||||
type: String? = null,
|
||||
isRedacted: Boolean = false,
|
||||
canBeReplaced: Boolean = false,
|
||||
editedEventId: EventId? = null
|
||||
editedEventId: EventId? = null,
|
||||
noisy: Boolean = false,
|
||||
) = SimpleNotifiableEvent(
|
||||
sessionId = sessionId,
|
||||
roomId = roomId,
|
||||
eventId = eventId,
|
||||
editedEventId = editedEventId,
|
||||
noisy = false,
|
||||
noisy = noisy,
|
||||
title = "title",
|
||||
description = "description",
|
||||
type = type,
|
||||
@@ -59,14 +60,15 @@ fun anInviteNotifiableEvent(
|
||||
sessionId: SessionId = A_SESSION_ID,
|
||||
roomId: RoomId = A_ROOM_ID,
|
||||
eventId: EventId = AN_EVENT_ID,
|
||||
isRedacted: Boolean = false
|
||||
isRedacted: Boolean = false,
|
||||
noisy: Boolean = false,
|
||||
) = InviteNotifiableEvent(
|
||||
sessionId = sessionId,
|
||||
eventId = eventId,
|
||||
roomId = roomId,
|
||||
roomName = A_ROOM_NAME,
|
||||
editedEventId = null,
|
||||
noisy = false,
|
||||
noisy = noisy,
|
||||
title = "title",
|
||||
description = "description",
|
||||
type = null,
|
||||
@@ -89,11 +91,12 @@ fun aNotifiableMessageEvent(
|
||||
senderId: UserId = A_USER_ID_2,
|
||||
senderDisambiguatedDisplayName: String = A_USER_NAME_2,
|
||||
roomName: String? = A_ROOM_NAME,
|
||||
noisy: Boolean = false,
|
||||
) = NotifiableMessageEvent(
|
||||
sessionId = sessionId,
|
||||
eventId = eventId,
|
||||
editedEventId = null,
|
||||
noisy = false,
|
||||
noisy = noisy,
|
||||
timestamp = timestamp,
|
||||
senderDisambiguatedDisplayName = senderDisambiguatedDisplayName,
|
||||
senderId = senderId,
|
||||
@@ -149,15 +152,23 @@ fun aNotifiableCallEvent(
|
||||
|
||||
fun aFallbackNotifiableEvent(
|
||||
sessionId: SessionId = A_SESSION_ID,
|
||||
roomId: RoomId = A_ROOM_ID,
|
||||
eventId: EventId = AN_EVENT_ID,
|
||||
description: String? = "A fallback notification",
|
||||
canBeReplaced: Boolean = false,
|
||||
noisy: Boolean = false,
|
||||
timestamp: Long = A_FAKE_TIMESTAMP,
|
||||
cause: String? = "Unable to decrypt event",
|
||||
) = FallbackNotifiableEvent(
|
||||
sessionId = sessionId,
|
||||
roomId = A_ROOM_ID,
|
||||
eventId = AN_EVENT_ID,
|
||||
roomId = roomId,
|
||||
eventId = eventId,
|
||||
editedEventId = null,
|
||||
description = "A fallback notification",
|
||||
canBeReplaced = false,
|
||||
description = description,
|
||||
canBeReplaced = canBeReplaced,
|
||||
isRedacted = false,
|
||||
isUpdated = false,
|
||||
timestamp = A_FAKE_TIMESTAMP,
|
||||
cause = "Unable to decrypt event",
|
||||
noisy = noisy,
|
||||
timestamp = timestamp,
|
||||
cause = cause,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user