First Commit

This commit is contained in:
2025-12-18 16:28:50 +07:00
commit 8c3e4f491f
9974 changed files with 396488 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
plugins {
id("io.element.android-library")
}
android {
namespace = "io.element.android.libraries.push.test"
}
dependencies {
api(projects.libraries.push.api)
api(projects.libraries.pushproviders.api)
implementation(projects.libraries.designsystem)
implementation(projects.libraries.push.impl)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.matrixui)
implementation(projects.tests.testutils)
implementation(libs.androidx.core)
implementation(libs.coil.compose)
implementation(libs.coil.test)
implementation(libs.test.robolectric)
}
@@ -0,0 +1,18 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 2025 New Vector 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.test
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.push.api.GetCurrentPushProvider
class FakeGetCurrentPushProvider(
private val currentPushProvider: String?
) : GetCurrentPushProvider {
override suspend fun getCurrentPushProvider(sessionId: SessionId): String? = currentPushProvider
}
@@ -0,0 +1,112 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 2025 New Vector 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.test
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.push.api.PushService
import io.element.android.libraries.push.api.history.PushHistoryItem
import io.element.android.libraries.pushproviders.api.Distributor
import io.element.android.libraries.pushproviders.api.PushProvider
import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.simulateLongTask
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
class FakePushService(
private val testPushBlock: suspend (SessionId) -> Boolean = { true },
private val availablePushProviders: List<PushProvider> = emptyList(),
private val registerWithLambda: (MatrixClient, PushProvider, Distributor) -> Result<Unit> = { _, _, _ ->
Result.success(Unit)
},
private val currentPushProvider: (SessionId) -> PushProvider? = { availablePushProviders.firstOrNull() },
private val selectPushProviderLambda: suspend (SessionId, PushProvider) -> Unit = { _, _ -> lambdaError() },
private val setIgnoreRegistrationErrorLambda: (SessionId, Boolean) -> Unit = { _, _ -> lambdaError() },
private val resetPushHistoryResult: () -> Unit = { lambdaError() },
private val resetBatteryOptimizationStateResult: () -> Unit = { lambdaError() },
private val onServiceUnregisteredResult: (UserId) -> Unit = { lambdaError() },
private val ensurePusherIsRegisteredResult: () -> Result<Unit> = { lambdaError() },
) : PushService {
override suspend fun getCurrentPushProvider(sessionId: SessionId): PushProvider? {
return registeredPushProvider ?: currentPushProvider(sessionId)
}
override fun getAvailablePushProviders(): List<PushProvider> {
return availablePushProviders
}
private var registeredPushProvider: PushProvider? = null
override suspend fun registerWith(
matrixClient: MatrixClient,
pushProvider: PushProvider,
distributor: Distributor,
): Result<Unit> = simulateLongTask {
return registerWithLambda(matrixClient, pushProvider, distributor)
.also {
if (it.isSuccess) {
registeredPushProvider = pushProvider
}
}
}
override suspend fun ensurePusherIsRegistered(matrixClient: MatrixClient): Result<Unit> {
return ensurePusherIsRegisteredResult()
}
override suspend fun selectPushProvider(sessionId: SessionId, pushProvider: PushProvider) {
selectPushProviderLambda(sessionId, pushProvider)
}
private val ignoreRegistrationError = MutableStateFlow(false)
override fun ignoreRegistrationError(sessionId: SessionId): Flow<Boolean> {
return ignoreRegistrationError
}
override suspend fun setIgnoreRegistrationError(sessionId: SessionId, ignore: Boolean) {
ignoreRegistrationError.value = ignore
setIgnoreRegistrationErrorLambda(sessionId, ignore)
}
override suspend fun testPush(sessionId: SessionId): Boolean = simulateLongTask {
testPushBlock(sessionId)
}
private val pushHistoryItemsFlow = MutableStateFlow<List<PushHistoryItem>>(emptyList())
override fun getPushHistoryItemsFlow(): Flow<List<PushHistoryItem>> {
return pushHistoryItemsFlow
}
fun emitPushHistoryItems(items: List<PushHistoryItem>) {
pushHistoryItemsFlow.value = items
}
private val pushCounterFlow = MutableStateFlow(0)
override val pushCounter: Flow<Int> = pushCounterFlow
fun emitPushCounter(counter: Int) {
pushCounterFlow.value = counter
}
override suspend fun resetPushHistory() = simulateLongTask {
resetPushHistoryResult()
}
override suspend fun resetBatteryOptimizationState() {
resetBatteryOptimizationStateResult()
}
override suspend fun onServiceUnregistered(userId: UserId) {
onServiceUnregisteredResult(userId)
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 2025 New Vector 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.test
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.pushproviders.api.PusherSubscriber
import io.element.android.tests.testutils.lambda.lambdaError
class FakePusherSubscriber(
private val registerPusherResult: (MatrixClient, String, String) -> Result<Unit> = { _, _, _ -> lambdaError() },
private val unregisterPusherResult: (MatrixClient, String, String) -> Result<Unit> = { _, _, _ -> lambdaError() },
) : PusherSubscriber {
override suspend fun registerPusher(matrixClient: MatrixClient, pushKey: String, gateway: String): Result<Unit> {
return registerPusherResult(matrixClient, pushKey, gateway)
}
override suspend fun unregisterPusher(matrixClient: MatrixClient, pushKey: String, gateway: String): Result<Unit> {
return unregisterPusherResult(matrixClient, pushKey, gateway)
}
}
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 2025 New Vector 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.test.notifications
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.notification.NotificationData
import io.element.android.libraries.push.impl.notifications.CallNotificationEventResolver
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
import io.element.android.tests.testutils.lambda.lambdaError
class FakeCallNotificationEventResolver(
var resolveEventLambda: (sessionId: SessionId, notificationData: NotificationData, forceNotify: Boolean) -> Result<NotifiableEvent> = { _, _, _ ->
lambdaError()
},
) : CallNotificationEventResolver {
override suspend fun resolveEvent(sessionId: SessionId, notificationData: NotificationData, forceNotify: Boolean): Result<NotifiableEvent> {
return resolveEventLambda(sessionId, notificationData, forceNotify)
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-2025 New Vector 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.test.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.matrix.api.core.ThreadId
import io.element.android.libraries.push.api.notifications.NotificationCleaner
import io.element.android.tests.testutils.lambda.lambdaError
class FakeNotificationCleaner(
private val clearAllMessagesEventsLambda: (SessionId) -> Unit = { lambdaError() },
private val clearMessagesForRoomLambda: (SessionId, RoomId) -> Unit = { _, _ -> lambdaError() },
private val clearMessagesForThreadLambda: (SessionId, RoomId, ThreadId) -> Unit = { _, _, _ -> lambdaError() },
private val clearEventLambda: (SessionId, EventId) -> Unit = { _, _ -> lambdaError() },
private val clearMembershipNotificationForSessionLambda: (SessionId) -> Unit = { lambdaError() },
private val clearMembershipNotificationForRoomLambda: (SessionId, RoomId) -> Unit = { _, _ -> lambdaError() }
) : NotificationCleaner {
override fun clearAllMessagesEvents(sessionId: SessionId) {
clearAllMessagesEventsLambda(sessionId)
}
override fun clearMessagesForRoom(sessionId: SessionId, roomId: RoomId) {
clearMessagesForRoomLambda(sessionId, roomId)
}
override fun clearMessagesForThread(sessionId: SessionId, roomId: RoomId, threadId: ThreadId) {
clearMessagesForThreadLambda(sessionId, roomId, threadId)
}
override fun clearEvent(sessionId: SessionId, eventId: EventId) {
clearEventLambda(sessionId, eventId)
}
override fun clearMembershipNotificationForSession(sessionId: SessionId) {
clearMembershipNotificationForSessionLambda(sessionId)
}
override fun clearMembershipNotificationForRoom(sessionId: SessionId, roomId: RoomId) {
clearMembershipNotificationForRoomLambda(sessionId, roomId)
}
}
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2025 New Vector 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.test.notifications
import io.element.android.libraries.push.api.push.NotificationEventRequest
import io.element.android.libraries.push.impl.notifications.NotificationResolverQueue
import io.element.android.libraries.push.impl.notifications.model.ResolvedPushEvent
import kotlinx.coroutines.flow.MutableSharedFlow
class FakeNotificationResolverQueue(
private val processingLambda: suspend (NotificationEventRequest) -> Result<ResolvedPushEvent>,
) : NotificationResolverQueue {
override val results = MutableSharedFlow<Pair<List<NotificationEventRequest>, Map<NotificationEventRequest, Result<ResolvedPushEvent>>>>(replay = 1)
override suspend fun enqueue(request: NotificationEventRequest) {
results.emit(listOf(request) to mapOf(request to processingLambda(request)))
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 2025 New Vector 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.test.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.api.notifications.OnMissedCallNotificationHandler
class FakeOnMissedCallNotificationHandler(
var addMissedCallNotificationLambda: (SessionId, RoomId, EventId) -> Unit = { _, _, _ -> }
) : OnMissedCallNotificationHandler {
override suspend fun addMissedCallNotification(
sessionId: SessionId,
roomId: RoomId,
eventId: EventId,
) {
addMissedCallNotificationLambda(sessionId, roomId, eventId)
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2025 New Vector 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.test.notifications.conversations
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.push.api.notifications.conversations.NotificationConversationService
class FakeNotificationConversationService : NotificationConversationService {
override suspend fun onSendMessage(
sessionId: SessionId,
roomId: RoomId,
roomName: String,
roomIsDirect: Boolean,
roomAvatarUrl: String?,
) = Unit
override suspend fun onLeftRoom(sessionId: SessionId, roomId: RoomId) = Unit
override suspend fun onAvailableRoomsChanged(sessionId: SessionId, roomIds: Set<RoomId>) = Unit
}
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 2025 New Vector 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.test.notifications.push
import android.graphics.Bitmap
import androidx.core.graphics.drawable.IconCompat
import coil3.ImageLoader
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.push.api.notifications.NotificationBitmapLoader
class FakeNotificationBitmapLoader(
var getRoomBitmapResult: (AvatarData, ImageLoader, Long) -> Bitmap? = { _, _, _ -> null },
var getUserIconResult: (AvatarData, ImageLoader) -> IconCompat? = { _, _ -> null },
) : NotificationBitmapLoader {
override suspend fun getRoomBitmap(avatarData: AvatarData, imageLoader: ImageLoader, targetSize: Long): Bitmap? {
return getRoomBitmapResult(avatarData, imageLoader, targetSize)
}
override suspend fun getUserIcon(avatarData: AvatarData, imageLoader: ImageLoader): IconCompat? {
return getUserIconResult(avatarData, imageLoader)
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 2025 New Vector 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.test.test
import io.element.android.libraries.pushproviders.api.PushData
import io.element.android.libraries.pushproviders.api.PushHandler
import io.element.android.tests.testutils.lambda.lambdaError
class FakePushHandler(
private val handleResult: (PushData, String) -> Unit = { _, _ -> lambdaError() },
private val handleInvalidResult: (String, String) -> Unit = { _, _ -> lambdaError() },
) : PushHandler {
override suspend fun handle(pushData: PushData, providerInfo: String) {
handleResult(pushData, providerInfo)
}
override suspend fun handleInvalid(providerInfo: String, data: String) {
handleInvalidResult(providerInfo, data)
}
}