Merge pull request #3450 from element-hq/feature/bma/improveCoverageMetrics

Improve code coverage metrics
This commit is contained in:
Benoit Marty
2024-09-19 10:02:55 +02:00
committed by GitHub
71 changed files with 2100 additions and 107 deletions

View File

@@ -21,7 +21,7 @@ class AppMigration05Test {
val sessionStore = InMemorySessionStore().apply {
updateData(
aSessionData(
sessionId = A_SESSION_ID,
sessionId = A_SESSION_ID.value,
sessionPath = "",
)
)
@@ -37,7 +37,7 @@ class AppMigration05Test {
val sessionStore = InMemorySessionStore().apply {
updateData(
aSessionData(
sessionId = A_SESSION_ID,
sessionId = A_SESSION_ID.value,
sessionPath = "/a/path/existing",
)
)

View File

@@ -21,7 +21,7 @@ class AppMigration06Test {
val sessionStore = InMemorySessionStore().apply {
updateData(
aSessionData(
sessionId = A_SESSION_ID,
sessionId = A_SESSION_ID.value,
sessionPath = "/a/path/to/a/session/AN_ID",
cachePath = "",
)
@@ -38,7 +38,7 @@ class AppMigration06Test {
val sessionStore = InMemorySessionStore().apply {
updateData(
aSessionData(
sessionId = A_SESSION_ID,
sessionId = A_SESSION_ID.value,
cachePath = "/a/path/existing",
)
)

View File

@@ -55,6 +55,7 @@ dependencies {
testImplementation(libs.test.mockk)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.sessionStorage.implMemory)
testImplementation(projects.libraries.sessionStorage.test)
testImplementation(projects.features.rageshake.test)
testImplementation(projects.tests.testutils)
testImplementation(projects.services.toolbox.test)

View File

@@ -17,9 +17,8 @@ import io.element.android.libraries.matrix.test.FakeSdkMetadata
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.network.useragent.DefaultUserAgentProvider
import io.element.android.libraries.sessionstorage.api.LoginType
import io.element.android.libraries.sessionstorage.api.SessionData
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
@@ -94,7 +93,7 @@ class DefaultBugReporterTest {
server.start()
val mockSessionStore = InMemorySessionStore().apply {
storeData(mockSessionData("@foo:eample.com", "ABCDEFGH"))
storeData(aSessionData(sessionId = "@foo:example.com", deviceId = "ABCDEFGH"))
}
val buildMeta = aBuildMeta()
@@ -143,7 +142,7 @@ class DefaultBugReporterTest {
assertThat(foundValues["can_contact"]).isEqualTo("true")
assertThat(foundValues["device_id"]).isEqualTo("ABCDEFGH")
assertThat(foundValues["sdk_sha"]).isEqualTo("123456789")
assertThat(foundValues["user_id"]).isEqualTo("@foo:eample.com")
assertThat(foundValues["user_id"]).isEqualTo("@foo:example.com")
assertThat(foundValues["text"]).isEqualTo("a bug occurred")
assertThat(foundValues["device_keys"]).isEqualTo("curve25519:CURVECURVECURVE, ed25519:EDKEYEDKEYEDKY")
@@ -163,7 +162,7 @@ class DefaultBugReporterTest {
server.start()
val mockSessionStore = InMemorySessionStore().apply {
storeData(mockSessionData("@foo:eample.com", "ABCDEFGH"))
storeData(aSessionData("@foo:example.com", "ABCDEFGH"))
}
val buildMeta = aBuildMeta()
@@ -267,21 +266,6 @@ class DefaultBugReporterTest {
return foundValues
}
private fun mockSessionData(userId: String, deviceId: String) = SessionData(
userId = userId,
deviceId = deviceId,
homeserverUrl = "example.com",
accessToken = "AA",
isTokenValid = true,
loginType = LoginType.DIRECT,
loginTimestamp = null,
oidcData = null,
refreshToken = null,
slidingSyncProxy = null,
passphrase = null,
sessionPath = "session",
cachePath = "cache",
)
@Test
fun `test sendBugReport error`() = runTest {
val server = MockWebServer()

View File

@@ -37,5 +37,6 @@ dependencies {
testImplementation(libs.test.turbine)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.sessionStorage.implMemory)
testImplementation(projects.libraries.sessionStorage.test)
testImplementation(projects.tests.testutils)
}

View File

@@ -8,7 +8,6 @@
package io.element.android.features.signedout.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.sessionstorage.api.LoginType
import io.element.android.libraries.sessionstorage.api.SessionData
@@ -20,18 +19,18 @@ open class SignedOutStateProvider : PreviewParameterProvider<SignedOutState> {
)
}
fun aSignedOutState() = SignedOutState(
private fun aSignedOutState() = SignedOutState(
appName = "AppName",
signedOutSession = aSessionData(),
eventSink = {},
)
fun aSessionData(
sessionId: SessionId = SessionId("@alice:server.org"),
private fun aSessionData(
sessionId: String = "@alice:server.org",
isTokenValid: Boolean = false,
): SessionData {
return SessionData(
userId = sessionId.value,
userId = sessionId,
deviceId = "aDeviceId",
accessToken = "anAccessToken",
refreshToken = "aRefreshToken",

View File

@@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.coroutines.test.runTest
import org.junit.Rule

View File

@@ -31,7 +31,7 @@ data class MatrixRoomInfo(
val isTombstoned: Boolean,
val isFavorite: Boolean,
val canonicalAlias: RoomAlias?,
val alternativeAliases: ImmutableList<String>,
val alternativeAliases: ImmutableList<RoomAlias>,
val currentUserMembership: CurrentUserMembership,
val inviter: RoomMember?,
val activeMembersCount: Long,
@@ -42,7 +42,7 @@ data class MatrixRoomInfo(
val notificationCount: Long,
val userDefinedNotificationMode: RoomNotificationMode?,
val hasRoomCall: Boolean,
val activeRoomCallParticipants: ImmutableList<String>,
val activeRoomCallParticipants: ImmutableList<UserId>,
val heroes: ImmutableList<MatrixUser>,
val pinnedEventIds: ImmutableList<EventId>,
val creator: UserId?,

View File

@@ -47,7 +47,10 @@ dependencies {
testImplementation(libs.test.truth)
testImplementation(libs.test.robolectric)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.sessionStorage.implMemory)
testImplementation(projects.libraries.sessionStorage.test)
testImplementation(projects.services.analytics.test)
testImplementation(projects.services.toolbox.test)
testImplementation(projects.tests.testutils)
testImplementation(libs.coroutines.test)
testImplementation(libs.test.turbine)

View File

@@ -10,9 +10,10 @@ package io.element.android.libraries.matrix.impl.analytics
import im.vector.app.features.analytics.plan.JoinedRoom
import io.element.android.libraries.matrix.api.room.MatrixRoom
private fun Long?.toAnalyticsRoomSize(): JoinedRoom.RoomSize {
private fun Long.toAnalyticsRoomSize(): JoinedRoom.RoomSize {
return when (this) {
null,
0L,
1L -> JoinedRoom.RoomSize.One
2L -> JoinedRoom.RoomSize.Two
in 3..10 -> JoinedRoom.RoomSize.ThreeToTen
in 11..100 -> JoinedRoom.RoomSize.ElevenToOneHundred

View File

@@ -8,14 +8,21 @@
package io.element.android.libraries.matrix.impl.auth
import io.element.android.libraries.matrix.api.auth.AuthenticationException
import org.matrix.rustcomponents.sdk.ClientBuildException as RustAuthenticationException
import org.matrix.rustcomponents.sdk.ClientBuildException
fun Throwable.mapAuthenticationException(): AuthenticationException {
val message = this.message ?: "Unknown error"
return when (this) {
is RustAuthenticationException.Generic -> AuthenticationException.Generic(message)
is RustAuthenticationException.InvalidServerName -> AuthenticationException.InvalidServerName(message)
is RustAuthenticationException.SlidingSyncVersion -> AuthenticationException.SlidingSyncVersion(message)
is ClientBuildException -> when (this) {
is ClientBuildException.Generic -> AuthenticationException.Generic(message)
is ClientBuildException.InvalidServerName -> AuthenticationException.InvalidServerName(message)
is ClientBuildException.SlidingSyncVersion -> AuthenticationException.SlidingSyncVersion(message)
is ClientBuildException.Sdk -> AuthenticationException.Generic(message)
is ClientBuildException.ServerUnreachable -> AuthenticationException.Generic(message)
is ClientBuildException.SlidingSync -> AuthenticationException.Generic(message)
is ClientBuildException.WellKnownDeserializationException -> AuthenticationException.Generic(message)
is ClientBuildException.WellKnownLookupFailed -> AuthenticationException.Generic(message)
}
else -> AuthenticationException.Generic(message)
}
}

View File

@@ -14,13 +14,17 @@ import org.matrix.rustcomponents.sdk.RecoveryException as RustRecoveryException
fun Throwable.mapRecoveryException(): RecoveryException {
return when (this) {
is RustRecoveryException.SecretStorage -> RecoveryException.SecretStorage(
message = errorMessage
)
is RustRecoveryException.BackupExistsOnServer -> RecoveryException.BackupExistsOnServer
is RustRecoveryException.Client -> RecoveryException.Client(
source.mapClientException()
)
is RustRecoveryException -> {
when (this) {
is RustRecoveryException.SecretStorage -> RecoveryException.SecretStorage(
message = errorMessage
)
is RustRecoveryException.BackupExistsOnServer -> RecoveryException.BackupExistsOnServer
is RustRecoveryException.Client -> RecoveryException.Client(
source.mapClientException()
)
}
}
else -> RecoveryException.Client(
ClientException.Other("Unknown error")
)

View File

@@ -12,7 +12,11 @@ import org.matrix.rustcomponents.sdk.ClientException as RustClientException
fun Throwable.mapClientException(): ClientException {
return when (this) {
is RustClientException.Generic -> ClientException.Generic(msg)
is RustClientException -> {
when (this) {
is RustClientException.Generic -> ClientException.Generic(msg)
}
}
else -> ClientException.Other(message ?: "Unknown error")
}
}

View File

@@ -39,7 +39,7 @@ class MatrixRoomInfoMapper {
isTombstoned = it.isTombstoned,
isFavorite = it.isFavourite,
canonicalAlias = it.canonicalAlias?.let(::RoomAlias),
alternativeAliases = it.alternativeAliases.toImmutableList(),
alternativeAliases = it.alternativeAliases.map(::RoomAlias).toImmutableList(),
currentUserMembership = it.membership.map(),
inviter = it.inviter?.let(RoomMemberMapper::map),
activeMembersCount = it.activeMembersCount.toLong(),
@@ -50,7 +50,7 @@ class MatrixRoomInfoMapper {
notificationCount = it.notificationCount.toLong(),
userDefinedNotificationMode = it.cachedUserDefinedNotificationMode?.map(),
hasRoomCall = it.hasRoomCall,
activeRoomCallParticipants = it.activeRoomCallParticipants.toImmutableList(),
activeRoomCallParticipants = it.activeRoomCallParticipants.map(::UserId).toImmutableList(),
heroes = it.elementHeroes().toImmutableList(),
pinnedEventIds = it.pinnedEventIds.map(::EventId).toImmutableList(),
)

View File

@@ -21,13 +21,17 @@ class RoomDescriptionMapper {
topic = roomDescription.topic,
avatarUrl = roomDescription.avatarUrl,
alias = roomDescription.alias?.let(::RoomAlias),
joinRule = when (roomDescription.joinRule) {
PublicRoomJoinRule.PUBLIC -> RoomDescription.JoinRule.PUBLIC
PublicRoomJoinRule.KNOCK -> RoomDescription.JoinRule.KNOCK
null -> RoomDescription.JoinRule.UNKNOWN
},
joinRule = roomDescription.joinRule.map(),
isWorldReadable = roomDescription.isWorldReadable,
numberOfMembers = roomDescription.joinedMembers.toLong(),
)
}
}
internal fun PublicRoomJoinRule?.map(): RoomDescription.JoinRule {
return when (this) {
PublicRoomJoinRule.PUBLIC -> RoomDescription.JoinRule.PUBLIC
PublicRoomJoinRule.KNOCK -> RoomDescription.JoinRule.KNOCK
null -> RoomDescription.JoinRule.UNKNOWN
}
}

View File

@@ -7,8 +7,11 @@
package io.element.android.libraries.matrix.impl.roomlist
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
@Suppress("unused")
@ExcludeFromCoverage
internal fun RoomListEntriesUpdate.describe(): String {
return when (this) {
is RoomListEntriesUpdate.Set -> {

View File

@@ -100,7 +100,8 @@ internal class MatrixTimelineDiffProcessor(
clear()
}
TimelineChange.TRUNCATE -> {
// Not supported
val index = diff.truncate() ?: return
subList(index.toInt(), size).clear()
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.analytics
import com.google.common.truth.Truth.assertThat
import im.vector.app.features.analytics.plan.JoinedRoom
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import org.junit.Test
class JoinedRoomExtKtTest {
@Test
fun `test room size mapping`() {
mapOf(
listOf(0L, 1L) to JoinedRoom.RoomSize.One,
listOf(2L, 2L) to JoinedRoom.RoomSize.Two,
listOf(3L, 10L) to JoinedRoom.RoomSize.ThreeToTen,
listOf(11L, 100L) to JoinedRoom.RoomSize.ElevenToOneHundred,
listOf(101L, 1000L) to JoinedRoom.RoomSize.OneHundredAndOneToAThousand,
listOf(1001L, 2000L) to JoinedRoom.RoomSize.MoreThanAThousand
).forEach { (joinedMemberCounts, expectedRoomSize) ->
joinedMemberCounts.forEach { joinedMemberCount ->
assertThat(aMatrixRoom(joinedMemberCount = joinedMemberCount).toAnalyticsJoinedRoom(null))
.isEqualTo(
JoinedRoom(
isDM = false,
isSpace = false,
roomSize = expectedRoomSize,
trigger = null
)
)
}
}
}
@Test
fun `test isDirect parameter mapping`() {
assertThat(aMatrixRoom(isDirect = true).toAnalyticsJoinedRoom(null))
.isEqualTo(
JoinedRoom(
isDM = true,
isSpace = false,
roomSize = JoinedRoom.RoomSize.One,
trigger = null
)
)
}
@Test
fun `test isSpace parameter mapping`() {
assertThat(aMatrixRoom(isSpace = true).toAnalyticsJoinedRoom(null))
.isEqualTo(
JoinedRoom(
isDM = false,
isSpace = true,
roomSize = JoinedRoom.RoomSize.One,
trigger = null
)
)
}
@Test
fun `test trigger parameter mapping`() {
assertThat(aMatrixRoom().toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite))
.isEqualTo(
JoinedRoom(
isDM = false,
isSpace = false,
roomSize = JoinedRoom.RoomSize.One,
trigger = JoinedRoom.Trigger.Invite
)
)
}
private fun aMatrixRoom(
isDirect: Boolean = false,
isSpace: Boolean = false,
joinedMemberCount: Long = 0
): MatrixRoom {
return FakeMatrixRoom(
isDirect = isDirect,
isSpace = isSpace,
joinedMemberCount = joinedMemberCount
)
}
}

View File

@@ -36,13 +36,24 @@ class AuthenticationExceptionMappingTest {
assertThat(ClientBuildException.InvalidServerName("Invalid server name").mapAuthenticationException())
.isException<AuthenticationException.InvalidServerName>("Invalid server name")
assertThat(ClientBuildException.Sdk("SDK issue").mapAuthenticationException())
.isException<AuthenticationException.Generic>("SDK issue")
assertThat(ClientBuildException.SlidingSyncVersion("Sliding sync not available").mapAuthenticationException())
.isException<AuthenticationException.SlidingSyncVersion>("Sliding sync not available")
}
@Test
fun `mapping other exceptions map to the Generic Kotlin`() {
assertThat(ClientBuildException.Sdk("SDK issue").mapAuthenticationException())
.isException<AuthenticationException.Generic>("SDK issue")
assertThat(ClientBuildException.ServerUnreachable("Server unreachable").mapAuthenticationException())
.isException<AuthenticationException.Generic>("Server unreachable")
assertThat(ClientBuildException.SlidingSync("Sliding Sync").mapAuthenticationException())
.isException<AuthenticationException.Generic>("Sliding Sync")
assertThat(ClientBuildException.WellKnownDeserializationException("WellKnown Deserialization").mapAuthenticationException())
.isException<AuthenticationException.Generic>("WellKnown Deserialization")
assertThat(ClientBuildException.WellKnownLookupFailed("WellKnown Lookup Failed").mapAuthenticationException())
.isException<AuthenticationException.Generic>("WellKnown Lookup Failed")
}
private inline fun <reified T> ThrowableSubject.isException(message: String) {
isInstanceOf(T::class.java)
hasMessageThat().isEqualTo(message)

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.auth.qrlogin
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeDecodeException
import io.element.android.libraries.matrix.api.auth.qrlogin.QrLoginException
import org.junit.Test
import org.matrix.rustcomponents.sdk.HumanQrLoginException as RustHumanQrLoginException
import org.matrix.rustcomponents.sdk.QrCodeDecodeException as RustQrCodeDecodeException
class QrErrorMapperTest {
@Test
fun `test map QrCodeDecodeException`() {
val result = QrErrorMapper.map(RustQrCodeDecodeException.Crypto("test"))
assertThat(result).isInstanceOf(QrCodeDecodeException.Crypto::class.java)
assertThat(result.message).isEqualTo("test")
}
@Test
fun `test map HumanQrLoginException`() {
assertThat(QrErrorMapper.map(RustHumanQrLoginException.Cancelled())).isEqualTo(QrLoginException.Cancelled)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.ConnectionInsecure())).isEqualTo(QrLoginException.ConnectionInsecure)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.Declined())).isEqualTo(QrLoginException.Declined)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.Expired())).isEqualTo(QrLoginException.Expired)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.OtherDeviceNotSignedIn())).isEqualTo(QrLoginException.OtherDeviceNotSignedIn)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.LinkingNotSupported())).isEqualTo(QrLoginException.LinkingNotSupported)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.Unknown())).isEqualTo(QrLoginException.Unknown)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.OidcMetadataInvalid())).isEqualTo(QrLoginException.OidcMetadataInvalid)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.SlidingSyncNotAvailable())).isEqualTo(QrLoginException.SlidingSyncNotAvailable)
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.auth.qrlogin
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep
import org.junit.Test
import org.matrix.rustcomponents.sdk.QrLoginProgress
class QrLoginProgressExtensionsKtTest {
@Test
fun `mapping QrLoginProgress should return expected result`() {
assertThat(QrLoginProgress.Starting.toStep())
.isEqualTo(QrCodeLoginStep.Starting)
assertThat(QrLoginProgress.EstablishingSecureChannel(1u, "01").toStep())
.isEqualTo(QrCodeLoginStep.EstablishingSecureChannel("01"))
assertThat(QrLoginProgress.WaitingForToken("userCode").toStep())
.isEqualTo(QrCodeLoginStep.WaitingForToken("userCode"))
assertThat(QrLoginProgress.Done.toStep())
.isEqualTo(QrCodeLoginStep.Finished)
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.core
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.ProgressCallback
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.matrix.rustcomponents.sdk.TransmissionProgress
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
class ProgressWatcherWrapperKtTest {
@Test
fun testToProgressWatcher() = runTest {
suspendCoroutine { continuation ->
val callback = object : ProgressCallback {
override fun onProgress(current: Long, total: Long) {
assertThat(current).isEqualTo(1)
assertThat(total).isEqualTo(2)
continuation.resume(Unit)
}
}
val result = callback.toProgressWatcher()
result.transmissionProgress(TransmissionProgress(1.toULong(), 2.toULong()))
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.di
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.core.meta.BuildType
import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations
import io.element.android.libraries.matrix.test.core.aBuildMeta
import org.junit.Test
class TracingMatrixModuleTest {
@Test
fun `providesTracingFilterConfiguration returns debug config for debug build`() {
assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.DEBUG)))
.isEqualTo(TracingFilterConfigurations.debug)
}
@Test
fun `providesTracingFilterConfiguration returns nightly config for nightly build`() {
assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.NIGHTLY)))
.isEqualTo(TracingFilterConfigurations.nightly)
}
@Test
fun `providesTracingFilterConfiguration returns release config for release build`() {
assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.RELEASE)))
.isEqualTo(TracingFilterConfigurations.release)
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.encryption
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.encryption.BackupState
import org.junit.Test
import org.matrix.rustcomponents.sdk.BackupState as RustBackupState
class BackupStateMapperTest {
@Test
fun `Ensure that mapping is correct`() {
val sut = BackupStateMapper()
assertThat(sut.map(RustBackupState.UNKNOWN)).isEqualTo(BackupState.UNKNOWN)
assertThat(sut.map(RustBackupState.CREATING)).isEqualTo(BackupState.CREATING)
assertThat(sut.map(RustBackupState.ENABLING)).isEqualTo(BackupState.ENABLING)
assertThat(sut.map(RustBackupState.RESUMING)).isEqualTo(BackupState.RESUMING)
assertThat(sut.map(RustBackupState.ENABLED)).isEqualTo(BackupState.ENABLED)
assertThat(sut.map(RustBackupState.DOWNLOADING)).isEqualTo(BackupState.DOWNLOADING)
assertThat(sut.map(RustBackupState.DISABLING)).isEqualTo(BackupState.DISABLING)
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.encryption
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
import org.junit.Test
import org.matrix.rustcomponents.sdk.BackupUploadState as RustBackupUploadState
class BackupUploadStateMapperTest {
@Test
fun `Ensure that mapping is correct`() {
val sut = BackupUploadStateMapper()
assertThat(sut.map(RustBackupUploadState.Waiting))
.isEqualTo(BackupUploadState.Waiting)
assertThat(sut.map(RustBackupUploadState.Error))
.isEqualTo(BackupUploadState.Error)
assertThat(sut.map(RustBackupUploadState.Done))
.isEqualTo(BackupUploadState.Done)
assertThat(sut.map(RustBackupUploadState.Uploading(1.toUInt(), 2.toUInt())))
.isEqualTo(BackupUploadState.Uploading(1, 2))
}
@Test
fun `Ensure that full uploading is mapper to Done`() {
val sut = BackupUploadStateMapper()
assertThat(sut.map(RustBackupUploadState.Uploading(2.toUInt(), 2.toUInt())))
.isEqualTo(BackupUploadState.Done)
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.encryption
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress
import org.junit.Test
import org.matrix.rustcomponents.sdk.EnableRecoveryProgress as RustEnableRecoveryProgress
class EnableRecoveryProgressMapperTest {
@Test
fun `Ensure that mapping is correct`() {
val sut = EnableRecoveryProgressMapper()
assertThat(sut.map(RustEnableRecoveryProgress.CreatingRecoveryKey))
.isEqualTo(EnableRecoveryProgress.CreatingRecoveryKey)
assertThat(sut.map(RustEnableRecoveryProgress.CreatingBackup))
.isEqualTo(EnableRecoveryProgress.CreatingBackup)
assertThat(sut.map(RustEnableRecoveryProgress.Starting))
.isEqualTo(EnableRecoveryProgress.Starting)
assertThat(sut.map(RustEnableRecoveryProgress.BackingUp(1.toUInt(), 2.toUInt())))
.isEqualTo(EnableRecoveryProgress.BackingUp(1, 2))
assertThat(sut.map(RustEnableRecoveryProgress.RoomKeyUploadError))
.isEqualTo(EnableRecoveryProgress.RoomKeyUploadError)
assertThat(sut.map(RustEnableRecoveryProgress.Done("recoveryKey")))
.isEqualTo(EnableRecoveryProgress.Done("recoveryKey"))
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.encryption
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.encryption.RecoveryState
import org.junit.Test
import org.matrix.rustcomponents.sdk.RecoveryState as RustRecoveryState
class RecoveryStateMapperTest {
@Test
fun `Ensure that mapping is correct`() {
val sut = RecoveryStateMapper()
assertThat(sut.map(RustRecoveryState.UNKNOWN)).isEqualTo(RecoveryState.UNKNOWN)
assertThat(sut.map(RustRecoveryState.ENABLED)).isEqualTo(RecoveryState.ENABLED)
assertThat(sut.map(RustRecoveryState.DISABLED)).isEqualTo(RecoveryState.DISABLED)
assertThat(sut.map(RustRecoveryState.INCOMPLETE)).isEqualTo(RecoveryState.INCOMPLETE)
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.factories
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
import io.element.android.libraries.matrix.test.A_ROOM_ID
import org.matrix.rustcomponents.sdk.PublicRoomJoinRule
import org.matrix.rustcomponents.sdk.RoomDescription
internal fun aRustRoomDescription(): RoomDescription {
return RoomDescription(
roomId = A_ROOM_ID.value,
name = "name",
topic = "topic",
alias = A_ROOM_ALIAS.value,
avatarUrl = "avatarUrl",
joinRule = PublicRoomJoinRule.PUBLIC,
isWorldReadable = true,
joinedMembers = 2u
)
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.factories
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.test.A_USER_ID
import org.matrix.rustcomponents.sdk.RoomHero
internal fun aRustRoomHero(
userId: UserId = A_USER_ID,
): RoomHero {
return RoomHero(
userId = userId.value,
displayName = "displayName",
avatarUrl = "avatarUrl",
)
}

View File

@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures
package io.element.android.libraries.matrix.impl.fixtures.factories
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.test.A_ROOM_ID
@@ -18,8 +18,8 @@ import org.matrix.rustcomponents.sdk.RoomNotificationMode
fun aRustRoomInfo(
id: String = A_ROOM_ID.value,
displayName: String = A_ROOM_NAME,
rawName: String = A_ROOM_NAME,
displayName: String? = A_ROOM_NAME,
rawName: String? = A_ROOM_NAME,
topic: String? = null,
avatarUrl: String? = null,
isDirect: Boolean = false,

View File

@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures
package io.element.android.libraries.matrix.impl.fixtures.factories
import io.element.android.libraries.matrix.api.core.UserId
import org.matrix.rustcomponents.sdk.MembershipState

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.factories
import org.matrix.rustcomponents.sdk.RoomPowerLevels
internal fun aRustRoomPowerLevels(
ban: Long,
invite: Long,
kick: Long,
redact: Long,
eventsDefault: Long,
stateDefault: Long,
usersDefault: Long,
roomName: Long,
roomAvatar: Long,
roomTopic: Long,
) = RoomPowerLevels(
ban = ban,
invite = invite,
kick = kick,
redact = redact,
eventsDefault = eventsDefault,
stateDefault = stateDefault,
usersDefault = usersDefault,
roomName = roomName,
roomAvatar = roomAvatar,
roomTopic = roomTopic,
)

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.factories
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
import io.element.android.libraries.matrix.test.A_ROOM_ID
import org.matrix.rustcomponents.sdk.RoomPreview
internal fun aRustRoomPreview(
canonicalAlias: String? = A_ROOM_ALIAS.value,
isJoined: Boolean = true,
isInvited: Boolean = true,
isPublic: Boolean = true,
canKnock: Boolean = true,
): RoomPreview {
return RoomPreview(
roomId = A_ROOM_ID.value,
canonicalAlias = canonicalAlias,
name = "name",
topic = "topic",
avatarUrl = "avatarUrl",
numJoinedMembers = 1u,
roomType = null,
isHistoryWorldReadable = true,
isJoined = isJoined,
isInvited = isInvited,
isPublic = isPublic,
canKnock = canKnock,
)
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.factories
import org.matrix.rustcomponents.sdk.SearchUsersResults
import org.matrix.rustcomponents.sdk.UserProfile
internal fun aRustSearchUsersResults(
results: List<UserProfile>,
limited: Boolean,
) = SearchUsersResults(
results = results,
limited = limited,
)

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.factories
import io.element.android.libraries.matrix.test.A_DEVICE_ID
import io.element.android.libraries.matrix.test.A_HOMESERVER_URL
import io.element.android.libraries.matrix.test.A_USER_ID
import org.matrix.rustcomponents.sdk.Session
import org.matrix.rustcomponents.sdk.SlidingSyncVersion
internal fun aRustSession(
proxy: SlidingSyncVersion = SlidingSyncVersion.None
): Session {
return Session(
accessToken = "accessToken",
refreshToken = "refreshToken",
userId = A_USER_ID.value,
deviceId = A_DEVICE_ID.value,
homeserverUrl = A_HOMESERVER_URL,
oidcData = null,
slidingSyncVersion = proxy,
)
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.factories
import io.element.android.libraries.matrix.test.A_USER_ID
import org.matrix.rustcomponents.sdk.UserProfile
fun aRustUserProfile(
userId: String = A_USER_ID.value,
displayName: String = "displayName",
avatarUrl: String = "avatarUrl",
) = UserProfile(
userId = userId,
displayName = displayName,
avatarUrl = avatarUrl,
)

View File

@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures
package io.element.android.libraries.matrix.impl.fixtures.fakes
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.test.A_ROOM_ID

View File

@@ -5,9 +5,10 @@
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures
package io.element.android.libraries.matrix.impl.fixtures.fakes
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo
import org.matrix.rustcomponents.sdk.EventTimelineItem
import org.matrix.rustcomponents.sdk.NoPointer
import org.matrix.rustcomponents.sdk.RoomInfo

View File

@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures
package io.element.android.libraries.matrix.impl.fixtures.fakes
import org.matrix.rustcomponents.sdk.NoPointer
import org.matrix.rustcomponents.sdk.RoomMember

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.fakes
import org.matrix.rustcomponents.sdk.InsertData
import org.matrix.rustcomponents.sdk.NoPointer
import org.matrix.rustcomponents.sdk.SetData
import org.matrix.rustcomponents.sdk.TimelineChange
import org.matrix.rustcomponents.sdk.TimelineDiff
import org.matrix.rustcomponents.sdk.TimelineItem
class FakeRustTimelineDiff(
private val change: TimelineChange,
private val item: TimelineItem? = FakeRustTimelineItem()
) : TimelineDiff(NoPointer) {
override fun change() = change
override fun append(): List<TimelineItem>? = item?.let { listOf(it) }
override fun insert(): InsertData? = item?.let { InsertData(1u, it) }
override fun pushBack(): TimelineItem? = item
override fun pushFront(): TimelineItem? = item
override fun remove(): UInt? = 1u
override fun reset(): List<TimelineItem>? = item?.let { listOf(it) }
override fun set(): SetData? = item?.let { SetData(1u, it) }
override fun truncate(): UInt? = 1u
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.fakes
import org.matrix.rustcomponents.sdk.EventTimelineItem
import org.matrix.rustcomponents.sdk.NoPointer
import org.matrix.rustcomponents.sdk.TimelineItem
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
class FakeRustTimelineItem : TimelineItem(NoPointer) {
override fun asEvent(): EventTimelineItem? = null
override fun asVirtual(): VirtualTimelineItem? = null
override fun fmtDebug(): String = "fmtDebug"
override fun uniqueId(): String = "uniqueId"
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.keys
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class DefaultPassphraseGeneratorTest {
@Test
fun `check that generated passphrase has the expected length`() {
val passphraseGenerator = DefaultPassphraseGenerator()
val passphrase = passphraseGenerator.generatePassphrase()
assertThat(passphrase!!.length).isEqualTo(342)
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.mapper
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSession
import io.element.android.libraries.matrix.impl.paths.SessionPaths
import io.element.android.libraries.matrix.test.A_DEVICE_ID
import io.element.android.libraries.matrix.test.A_HOMESERVER_URL
import io.element.android.libraries.matrix.test.A_HOMESERVER_URL_2
import io.element.android.libraries.matrix.test.A_SECRET
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.sessionstorage.api.LoginType
import org.junit.Test
import org.matrix.rustcomponents.sdk.SlidingSyncVersion
import java.io.File
class SessionKtTest {
@Test
fun `toSessionData compute the expected result`() {
val result = aRustSession().toSessionData(
isTokenValid = true,
loginType = LoginType.PASSWORD,
passphrase = A_SECRET,
sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")),
)
assertThat(result.userId).isEqualTo(A_USER_ID.value)
assertThat(result.deviceId).isEqualTo(A_DEVICE_ID.value)
assertThat(result.accessToken).isEqualTo("accessToken")
assertThat(result.refreshToken).isEqualTo("refreshToken")
assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL)
assertThat(result.isTokenValid).isTrue()
assertThat(result.oidcData).isNull()
assertThat(result.slidingSyncProxy).isNull()
assertThat(result.loginType).isEqualTo(LoginType.PASSWORD)
assertThat(result.loginTimestamp).isNotNull()
assertThat(result.passphrase).isEqualTo(A_SECRET)
assertThat(result.sessionPath).isEqualTo("/a/file")
assertThat(result.cachePath).isEqualTo("/a/cache")
}
@Test
fun `toSessionData can change the validity of the token`() {
val result = aRustSession().toSessionData(
isTokenValid = false,
loginType = LoginType.PASSWORD,
passphrase = A_SECRET,
sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")),
homeserverUrl = null,
)
assertThat(result.isTokenValid).isFalse()
}
@Test
fun `toSessionData can override the value of the homeserver url`() {
val result = aRustSession().toSessionData(
isTokenValid = true,
loginType = LoginType.PASSWORD,
passphrase = A_SECRET,
sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")),
homeserverUrl = A_HOMESERVER_URL_2,
)
assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL_2)
}
@Test
fun `toSessionData copy the sliding sync url if present`() {
val result = aRustSession(
proxy = SlidingSyncVersion.Proxy("proxyUrl")
).toSessionData(
isTokenValid = true,
loginType = LoginType.PASSWORD,
passphrase = A_SECRET,
sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")),
homeserverUrl = A_HOMESERVER_URL_2,
)
assertThat(result.slidingSyncProxy).isEqualTo("proxyUrl")
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2023, 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.poll
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.poll.PollKind
import org.junit.Test
import org.matrix.rustcomponents.sdk.PollKind as RustPollKind
class PollKindKtTest {
@Test
fun `map should return Disclosed when RustPollKind is Disclosed`() {
val pollKind = RustPollKind.DISCLOSED.map()
assertThat(pollKind).isEqualTo(PollKind.Disclosed)
}
@Test
fun `map should return Undisclosed when RustPollKind is Undisclosed`() {
val pollKind = RustPollKind.UNDISCLOSED.map()
assertThat(pollKind).isEqualTo(PollKind.Undisclosed)
}
@Test
fun `toInner should return DISCLOSED when PollKind is Disclosed`() {
val rustPollKind = PollKind.Disclosed.toInner()
assertThat(rustPollKind).isEqualTo(RustPollKind.DISCLOSED)
}
@Test
fun `toInner should return UNDISCLOSED when PollKind is Undisclosed`() {
val rustPollKind = PollKind.Undisclosed.toInner()
assertThat(rustPollKind).isEqualTo(RustPollKind.UNDISCLOSED)
}
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.room
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomHero
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomMember
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_3
import io.element.android.libraries.matrix.test.A_USER_ID_6
import io.element.android.libraries.matrix.test.room.aRoomMember
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.collections.immutable.toPersistentList
import org.junit.Test
import org.matrix.rustcomponents.sdk.Membership
import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode
class MatrixRoomInfoMapperTest {
@Test
fun `mapping of RustRoomInfo should map all the fields`() {
assertThat(
MatrixRoomInfoMapper().map(
aRustRoomInfo(
id = A_ROOM_ID.value,
displayName = "displayName",
rawName = "rawName",
topic = "topic",
avatarUrl = AN_AVATAR_URL,
isDirect = true,
isPublic = false,
isSpace = false,
isTombstoned = false,
isFavourite = false,
canonicalAlias = A_ROOM_ALIAS.value,
alternativeAliases = listOf(A_ROOM_ALIAS.value),
membership = Membership.JOINED,
inviter = aRustRoomMember(A_USER_ID),
heroes = listOf(aRustRoomHero()),
activeMembersCount = 2uL,
invitedMembersCount = 3uL,
joinedMembersCount = 4uL,
userPowerLevels = mapOf(A_USER_ID_6.value to 50L),
highlightCount = 10uL,
notificationCount = 11uL,
userDefinedNotificationMode = RustRoomNotificationMode.MUTE,
hasRoomCall = true,
activeRoomCallParticipants = listOf(A_USER_ID_3.value),
isMarkedUnread = false,
numUnreadMessages = 12uL,
numUnreadNotifications = 13uL,
numUnreadMentions = 14uL,
pinnedEventIds = listOf(AN_EVENT_ID.value),
roomCreator = A_USER_ID,
)
)
).isEqualTo(
MatrixRoomInfo(
id = A_ROOM_ID,
name = "displayName",
rawName = "rawName",
topic = "topic",
avatarUrl = AN_AVATAR_URL,
isDirect = true,
isPublic = false,
isSpace = false,
isTombstoned = false,
isFavorite = false,
canonicalAlias = A_ROOM_ALIAS,
alternativeAliases = listOf(A_ROOM_ALIAS).toImmutableList(),
currentUserMembership = CurrentUserMembership.JOINED,
inviter = aRoomMember(A_USER_ID),
activeMembersCount = 2L,
invitedMembersCount = 3L,
joinedMembersCount = 4L,
userPowerLevels = mapOf(A_USER_ID_6 to 50L).toImmutableMap(),
highlightCount = 10L,
notificationCount = 11L,
userDefinedNotificationMode = RoomNotificationMode.MUTE,
hasRoomCall = true,
activeRoomCallParticipants = listOf(A_USER_ID_3).toImmutableList(),
heroes = listOf(
MatrixUser(
userId = A_USER_ID,
displayName = "displayName",
avatarUrl = "avatarUrl",
)
).toImmutableList(),
pinnedEventIds = listOf(AN_EVENT_ID).toPersistentList(),
creator = A_USER_ID,
)
)
}
@Test
fun `mapping of RustRoomInfo with null members should map all the fields`() {
assertThat(
MatrixRoomInfoMapper().map(
aRustRoomInfo(
id = A_ROOM_ID.value,
displayName = null,
rawName = null,
topic = null,
avatarUrl = null,
isDirect = false,
isPublic = true,
isSpace = false,
isTombstoned = false,
isFavourite = true,
canonicalAlias = null,
alternativeAliases = emptyList(),
membership = Membership.INVITED,
inviter = null,
heroes = listOf(aRustRoomHero()),
activeMembersCount = 2uL,
invitedMembersCount = 3uL,
joinedMembersCount = 4uL,
userPowerLevels = emptyMap(),
highlightCount = 10uL,
notificationCount = 11uL,
userDefinedNotificationMode = null,
hasRoomCall = false,
activeRoomCallParticipants = emptyList(),
isMarkedUnread = true,
numUnreadMessages = 12uL,
numUnreadNotifications = 13uL,
numUnreadMentions = 14uL,
pinnedEventIds = emptyList(),
roomCreator = null,
)
)
).isEqualTo(
MatrixRoomInfo(
id = A_ROOM_ID,
name = null,
rawName = null,
topic = null,
avatarUrl = null,
isDirect = false,
isPublic = true,
isSpace = false,
isTombstoned = false,
isFavorite = true,
canonicalAlias = null,
alternativeAliases = emptyList<RoomAlias>().toPersistentList(),
currentUserMembership = CurrentUserMembership.INVITED,
inviter = null,
activeMembersCount = 2L,
invitedMembersCount = 3L,
joinedMembersCount = 4L,
userPowerLevels = emptyMap<UserId, Long>().toImmutableMap(),
highlightCount = 10L,
notificationCount = 11L,
userDefinedNotificationMode = null,
hasRoomCall = false,
activeRoomCallParticipants = emptyList<UserId>().toImmutableList(),
heroes = emptyList<MatrixUser>().toImmutableList(),
pinnedEventIds = emptyList<EventId>().toPersistentList(),
creator = null,
)
)
}
@Test
fun `mapping Membership`() {
assertThat(Membership.INVITED.map()).isEqualTo(CurrentUserMembership.INVITED)
assertThat(Membership.JOINED.map()).isEqualTo(CurrentUserMembership.JOINED)
assertThat(Membership.LEFT.map()).isEqualTo(CurrentUserMembership.LEFT)
}
@Test
fun `mapping RoomNotificationMode`() {
assertThat(RustRoomNotificationMode.ALL_MESSAGES.map()).isEqualTo(RoomNotificationMode.ALL_MESSAGES)
assertThat(RustRoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY.map()).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
assertThat(RustRoomNotificationMode.MUTE.map()).isEqualTo(RoomNotificationMode.MUTE)
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.room
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.MessageEventType
import org.junit.Test
import org.matrix.rustcomponents.sdk.MessageLikeEventType
class MessageEventTypeKtTest {
@Test
fun `map Rust type should result to correct Kotlin type`() {
assertThat(MessageLikeEventType.CALL_ANSWER.map()).isEqualTo(MessageEventType.CALL_ANSWER)
assertThat(MessageLikeEventType.CALL_INVITE.map()).isEqualTo(MessageEventType.CALL_INVITE)
assertThat(MessageLikeEventType.CALL_HANGUP.map()).isEqualTo(MessageEventType.CALL_HANGUP)
assertThat(MessageLikeEventType.CALL_CANDIDATES.map()).isEqualTo(MessageEventType.CALL_CANDIDATES)
assertThat(MessageLikeEventType.CALL_NOTIFY.map()).isEqualTo(MessageEventType.CALL_NOTIFY)
assertThat(MessageLikeEventType.KEY_VERIFICATION_READY.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_READY)
assertThat(MessageLikeEventType.KEY_VERIFICATION_START.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_START)
assertThat(MessageLikeEventType.KEY_VERIFICATION_CANCEL.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_CANCEL)
assertThat(MessageLikeEventType.KEY_VERIFICATION_ACCEPT.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_ACCEPT)
assertThat(MessageLikeEventType.KEY_VERIFICATION_KEY.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_KEY)
assertThat(MessageLikeEventType.KEY_VERIFICATION_MAC.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_MAC)
assertThat(MessageLikeEventType.KEY_VERIFICATION_DONE.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_DONE)
assertThat(MessageLikeEventType.REACTION.map()).isEqualTo(MessageEventType.REACTION)
assertThat(MessageLikeEventType.ROOM_ENCRYPTED.map()).isEqualTo(MessageEventType.ROOM_ENCRYPTED)
assertThat(MessageLikeEventType.ROOM_MESSAGE.map()).isEqualTo(MessageEventType.ROOM_MESSAGE)
assertThat(MessageLikeEventType.ROOM_REDACTION.map()).isEqualTo(MessageEventType.ROOM_REDACTION)
assertThat(MessageLikeEventType.STICKER.map()).isEqualTo(MessageEventType.STICKER)
assertThat(MessageLikeEventType.POLL_END.map()).isEqualTo(MessageEventType.POLL_END)
assertThat(MessageLikeEventType.POLL_RESPONSE.map()).isEqualTo(MessageEventType.POLL_RESPONSE)
assertThat(MessageLikeEventType.POLL_START.map()).isEqualTo(MessageEventType.POLL_START)
assertThat(MessageLikeEventType.UNSTABLE_POLL_END.map()).isEqualTo(MessageEventType.UNSTABLE_POLL_END)
assertThat(MessageLikeEventType.UNSTABLE_POLL_RESPONSE.map()).isEqualTo(MessageEventType.UNSTABLE_POLL_RESPONSE)
assertThat(MessageLikeEventType.UNSTABLE_POLL_START.map()).isEqualTo(MessageEventType.UNSTABLE_POLL_START)
}
@Test
fun `map Kotlin type should result to correct Rust type`() {
assertThat(MessageEventType.CALL_ANSWER.map()).isEqualTo(MessageLikeEventType.CALL_ANSWER)
assertThat(MessageEventType.CALL_INVITE.map()).isEqualTo(MessageLikeEventType.CALL_INVITE)
assertThat(MessageEventType.CALL_HANGUP.map()).isEqualTo(MessageLikeEventType.CALL_HANGUP)
assertThat(MessageEventType.CALL_CANDIDATES.map()).isEqualTo(MessageLikeEventType.CALL_CANDIDATES)
assertThat(MessageEventType.CALL_NOTIFY.map()).isEqualTo(MessageLikeEventType.CALL_NOTIFY)
assertThat(MessageEventType.KEY_VERIFICATION_READY.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_READY)
assertThat(MessageEventType.KEY_VERIFICATION_START.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_START)
assertThat(MessageEventType.KEY_VERIFICATION_CANCEL.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_CANCEL)
assertThat(MessageEventType.KEY_VERIFICATION_ACCEPT.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_ACCEPT)
assertThat(MessageEventType.KEY_VERIFICATION_KEY.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_KEY)
assertThat(MessageEventType.KEY_VERIFICATION_MAC.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_MAC)
assertThat(MessageEventType.KEY_VERIFICATION_DONE.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_DONE)
assertThat(MessageEventType.REACTION.map()).isEqualTo(MessageLikeEventType.REACTION)
assertThat(MessageEventType.ROOM_ENCRYPTED.map()).isEqualTo(MessageLikeEventType.ROOM_ENCRYPTED)
assertThat(MessageEventType.ROOM_MESSAGE.map()).isEqualTo(MessageLikeEventType.ROOM_MESSAGE)
assertThat(MessageEventType.ROOM_REDACTION.map()).isEqualTo(MessageLikeEventType.ROOM_REDACTION)
assertThat(MessageEventType.STICKER.map()).isEqualTo(MessageLikeEventType.STICKER)
assertThat(MessageEventType.POLL_END.map()).isEqualTo(MessageLikeEventType.POLL_END)
assertThat(MessageEventType.POLL_RESPONSE.map()).isEqualTo(MessageLikeEventType.POLL_RESPONSE)
assertThat(MessageEventType.POLL_START.map()).isEqualTo(MessageLikeEventType.POLL_START)
assertThat(MessageEventType.UNSTABLE_POLL_END.map()).isEqualTo(MessageLikeEventType.UNSTABLE_POLL_END)
assertThat(MessageEventType.UNSTABLE_POLL_RESPONSE.map()).isEqualTo(MessageLikeEventType.UNSTABLE_POLL_RESPONSE)
assertThat(MessageEventType.UNSTABLE_POLL_START.map()).isEqualTo(MessageLikeEventType.UNSTABLE_POLL_START)
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.room
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomHero
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo
import io.element.android.libraries.matrix.test.A_USER_ID
import org.junit.Test
class RoomInfoExtTest {
@Test
fun `get non empty element Heroes`() {
val result = aRustRoomInfo(
isDirect = true,
activeMembersCount = 2uL,
heroes = listOf(aRustRoomHero())
).elementHeroes()
assertThat(result).isEqualTo(
listOf(
MatrixUser(
userId = UserId(A_USER_ID.value),
displayName = "displayName",
avatarUrl = "avatarUrl",
)
)
)
}
@Test
fun `too many heroes and element Heroes is empty`() {
val result = aRustRoomInfo(
isDirect = true,
activeMembersCount = 2uL,
heroes = listOf(aRustRoomHero(), aRustRoomHero())
).elementHeroes()
assertThat(result).isEmpty()
}
@Test
fun `not direct and element Heroes is empty`() {
val result = aRustRoomInfo(
isDirect = false,
activeMembersCount = 2uL,
heroes = listOf(aRustRoomHero())
).elementHeroes()
assertThat(result).isEmpty()
}
@Test
fun `too many members and element Heroes is empty`() {
val result = aRustRoomInfo(
isDirect = true,
activeMembersCount = 3uL,
heroes = listOf(aRustRoomHero())
).elementHeroes()
assertThat(result).isEmpty()
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.room
import io.element.android.libraries.matrix.api.room.RoomType
import org.junit.Test
class RoomTypeKtTest {
@Test
fun toRoomType() {
assert(null.toRoomType() == RoomType.Room)
assert("m.space".toRoomType() == RoomType.Space)
assert("m.other".toRoomType() == RoomType.Other("m.other"))
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.room
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.StateEventType
import org.junit.Test
import org.matrix.rustcomponents.sdk.StateEventType as RustStateEventType
class StateEventTypeTest {
@Test
fun `mapping Rust type should work`() {
assertThat(RustStateEventType.CALL_MEMBER.map()).isEqualTo(StateEventType.CALL_MEMBER)
assertThat(RustStateEventType.POLICY_RULE_ROOM.map()).isEqualTo(StateEventType.POLICY_RULE_ROOM)
assertThat(RustStateEventType.POLICY_RULE_SERVER.map()).isEqualTo(StateEventType.POLICY_RULE_SERVER)
assertThat(RustStateEventType.POLICY_RULE_USER.map()).isEqualTo(StateEventType.POLICY_RULE_USER)
assertThat(RustStateEventType.ROOM_ALIASES.map()).isEqualTo(StateEventType.ROOM_ALIASES)
assertThat(RustStateEventType.ROOM_AVATAR.map()).isEqualTo(StateEventType.ROOM_AVATAR)
assertThat(RustStateEventType.ROOM_CANONICAL_ALIAS.map()).isEqualTo(StateEventType.ROOM_CANONICAL_ALIAS)
assertThat(RustStateEventType.ROOM_CREATE.map()).isEqualTo(StateEventType.ROOM_CREATE)
assertThat(RustStateEventType.ROOM_ENCRYPTION.map()).isEqualTo(StateEventType.ROOM_ENCRYPTION)
assertThat(RustStateEventType.ROOM_GUEST_ACCESS.map()).isEqualTo(StateEventType.ROOM_GUEST_ACCESS)
assertThat(RustStateEventType.ROOM_HISTORY_VISIBILITY.map()).isEqualTo(StateEventType.ROOM_HISTORY_VISIBILITY)
assertThat(RustStateEventType.ROOM_JOIN_RULES.map()).isEqualTo(StateEventType.ROOM_JOIN_RULES)
assertThat(RustStateEventType.ROOM_MEMBER_EVENT.map()).isEqualTo(StateEventType.ROOM_MEMBER_EVENT)
assertThat(RustStateEventType.ROOM_NAME.map()).isEqualTo(StateEventType.ROOM_NAME)
assertThat(RustStateEventType.ROOM_PINNED_EVENTS.map()).isEqualTo(StateEventType.ROOM_PINNED_EVENTS)
assertThat(RustStateEventType.ROOM_POWER_LEVELS.map()).isEqualTo(StateEventType.ROOM_POWER_LEVELS)
assertThat(RustStateEventType.ROOM_SERVER_ACL.map()).isEqualTo(StateEventType.ROOM_SERVER_ACL)
assertThat(RustStateEventType.ROOM_THIRD_PARTY_INVITE.map()).isEqualTo(StateEventType.ROOM_THIRD_PARTY_INVITE)
assertThat(RustStateEventType.ROOM_TOMBSTONE.map()).isEqualTo(StateEventType.ROOM_TOMBSTONE)
assertThat(RustStateEventType.ROOM_TOPIC.map()).isEqualTo(StateEventType.ROOM_TOPIC)
assertThat(RustStateEventType.SPACE_CHILD.map()).isEqualTo(StateEventType.SPACE_CHILD)
assertThat(RustStateEventType.SPACE_PARENT.map()).isEqualTo(StateEventType.SPACE_PARENT)
}
@Test
fun `mapping Kotlin type should work`() {
assertThat(StateEventType.CALL_MEMBER.map()).isEqualTo(RustStateEventType.CALL_MEMBER)
assertThat(StateEventType.POLICY_RULE_ROOM.map()).isEqualTo(RustStateEventType.POLICY_RULE_ROOM)
assertThat(StateEventType.POLICY_RULE_SERVER.map()).isEqualTo(RustStateEventType.POLICY_RULE_SERVER)
assertThat(StateEventType.POLICY_RULE_USER.map()).isEqualTo(RustStateEventType.POLICY_RULE_USER)
assertThat(StateEventType.ROOM_ALIASES.map()).isEqualTo(RustStateEventType.ROOM_ALIASES)
assertThat(StateEventType.ROOM_AVATAR.map()).isEqualTo(RustStateEventType.ROOM_AVATAR)
assertThat(StateEventType.ROOM_CANONICAL_ALIAS.map()).isEqualTo(RustStateEventType.ROOM_CANONICAL_ALIAS)
assertThat(StateEventType.ROOM_CREATE.map()).isEqualTo(RustStateEventType.ROOM_CREATE)
assertThat(StateEventType.ROOM_ENCRYPTION.map()).isEqualTo(RustStateEventType.ROOM_ENCRYPTION)
assertThat(StateEventType.ROOM_GUEST_ACCESS.map()).isEqualTo(RustStateEventType.ROOM_GUEST_ACCESS)
assertThat(StateEventType.ROOM_HISTORY_VISIBILITY.map()).isEqualTo(RustStateEventType.ROOM_HISTORY_VISIBILITY)
assertThat(StateEventType.ROOM_JOIN_RULES.map()).isEqualTo(RustStateEventType.ROOM_JOIN_RULES)
assertThat(StateEventType.ROOM_MEMBER_EVENT.map()).isEqualTo(RustStateEventType.ROOM_MEMBER_EVENT)
assertThat(StateEventType.ROOM_NAME.map()).isEqualTo(RustStateEventType.ROOM_NAME)
assertThat(StateEventType.ROOM_PINNED_EVENTS.map()).isEqualTo(RustStateEventType.ROOM_PINNED_EVENTS)
assertThat(StateEventType.ROOM_POWER_LEVELS.map()).isEqualTo(RustStateEventType.ROOM_POWER_LEVELS)
assertThat(StateEventType.ROOM_SERVER_ACL.map()).isEqualTo(RustStateEventType.ROOM_SERVER_ACL)
assertThat(StateEventType.ROOM_THIRD_PARTY_INVITE.map()).isEqualTo(RustStateEventType.ROOM_THIRD_PARTY_INVITE)
assertThat(StateEventType.ROOM_TOMBSTONE.map()).isEqualTo(RustStateEventType.ROOM_TOMBSTONE)
assertThat(StateEventType.ROOM_TOPIC.map()).isEqualTo(RustStateEventType.ROOM_TOPIC)
assertThat(StateEventType.SPACE_CHILD.map()).isEqualTo(RustStateEventType.SPACE_CHILD)
assertThat(StateEventType.SPACE_PARENT.map()).isEqualTo(RustStateEventType.SPACE_PARENT)
}
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.room.location
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.location.AssetType
import org.junit.Test
class AssetTypeKtTest {
@Test
fun toInner() {
assertThat(AssetType.SENDER.toInner()).isEqualTo(org.matrix.rustcomponents.sdk.AssetType.SENDER)
assertThat(AssetType.PIN.toInner()).isEqualTo(org.matrix.rustcomponents.sdk.AssetType.PIN)
}
}

View File

@@ -11,9 +11,9 @@ import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.roomMembers
import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoom
import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomMembersIterator
import io.element.android.libraries.matrix.impl.fixtures.aRustRoomMember
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomMember
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoom
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomMembersIterator
import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE
import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE_AND_SERVER
import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.SERVER

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.room.member
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import org.junit.Test
import uniffi.matrix_sdk.RoomMemberRole
import org.matrix.rustcomponents.sdk.MembershipState as RustMembershipState
class RoomMemberMapperTest {
@Test
fun mapRole() {
assertThat(RoomMemberMapper.mapRole(RoomMemberRole.USER)).isEqualTo(RoomMember.Role.USER)
assertThat(RoomMemberMapper.mapRole(RoomMemberRole.MODERATOR)).isEqualTo(RoomMember.Role.MODERATOR)
assertThat(RoomMemberMapper.mapRole(RoomMemberRole.ADMINISTRATOR)).isEqualTo(RoomMember.Role.ADMIN)
}
@Test
fun mapMembership() {
assertThat(RoomMemberMapper.mapMembership(RustMembershipState.BAN)).isEqualTo(RoomMembershipState.BAN)
assertThat(RoomMemberMapper.mapMembership(RustMembershipState.INVITE)).isEqualTo(RoomMembershipState.INVITE)
assertThat(RoomMemberMapper.mapMembership(RustMembershipState.JOIN)).isEqualTo(RoomMembershipState.JOIN)
assertThat(RoomMemberMapper.mapMembership(RustMembershipState.KNOCK)).isEqualTo(RoomMembershipState.KNOCK)
assertThat(RoomMemberMapper.mapMembership(RustMembershipState.LEAVE)).isEqualTo(RoomMembershipState.LEAVE)
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.room.powerlevels
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomPowerLevels
import org.junit.Test
class RoomPowerLevelsMapperTest {
@Test
fun `test that mapping of RoomPowerLevels is correct`() {
assertThat(
RoomPowerLevelsMapper.map(
aRustRoomPowerLevels(
ban = 1,
invite = 2,
kick = 3,
redact = 4,
eventsDefault = 5,
stateDefault = 6,
usersDefault = 7,
roomName = 8,
roomAvatar = 9,
roomTopic = 10,
)
)
).isEqualTo(
MatrixRoomPowerLevels(
ban = 1,
invite = 2,
kick = 3,
sendEvents = 5,
redactEvents = 4,
roomName = 8,
roomAvatar = 9,
roomTopic = 10,
)
)
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.room.preview
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.RoomType
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomPreview
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
import io.element.android.libraries.matrix.test.A_ROOM_ID
import org.junit.Test
class RoomPreviewMapperTest {
@Test
fun `map should map values 1`() {
assertThat(
RoomPreviewMapper.map(
aRustRoomPreview(
isJoined = false,
isInvited = false,
)
)
).isEqualTo(
RoomPreview(
roomId = A_ROOM_ID,
canonicalAlias = A_ROOM_ALIAS,
name = "name",
topic = "topic",
avatarUrl = "avatarUrl",
numberOfJoinedMembers = 1L,
roomType = RoomType.Room,
isHistoryWorldReadable = true,
isJoined = false,
isInvited = false,
isPublic = true,
canKnock = true,
)
)
}
@Test
fun `map should map values 2`() {
assertThat(
RoomPreviewMapper.map(
aRustRoomPreview(
canonicalAlias = null,
isPublic = false,
canKnock = false,
)
)
).isEqualTo(
RoomPreview(
roomId = A_ROOM_ID,
canonicalAlias = null,
name = "name",
topic = "topic",
avatarUrl = "avatarUrl",
numberOfJoinedMembers = 1L,
roomType = RoomType.Room,
isHistoryWorldReadable = true,
isJoined = true,
isInvited = true,
isPublic = false,
canKnock = false,
)
)
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.roomdirectory
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomDescription
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.roomdirectory.aRoomDescription
import org.junit.Test
import org.matrix.rustcomponents.sdk.PublicRoomJoinRule
class RoomDescriptionMapperTest {
@Test
fun map() {
assertThat(RoomDescriptionMapper().map(aRustRoomDescription())).isEqualTo(
aRoomDescription(
roomId = A_ROOM_ID,
name = "name",
topic = "topic",
alias = A_ROOM_ALIAS,
avatarUrl = "avatarUrl",
joinRule = RoomDescription.JoinRule.PUBLIC,
isWorldReadable = true,
joinedMembers = 2L
)
)
}
@Test
fun mapWithNullAlias() {
assertThat(RoomDescriptionMapper().map(aRustRoomDescription().copy(alias = null)).alias).isNull()
}
@Test
fun `map join rule`() {
assertThat(PublicRoomJoinRule.PUBLIC.map()).isEqualTo(RoomDescription.JoinRule.PUBLIC)
assertThat(PublicRoomJoinRule.KNOCK.map()).isEqualTo(RoomDescription.JoinRule.KNOCK)
assertThat(null.map()).isEqualTo(RoomDescription.JoinRule.UNKNOWN)
}
}

View File

@@ -10,9 +10,10 @@ package io.element.android.libraries.matrix.impl.roomlist
import com.google.common.truth.Truth.assertThat
import com.sun.jna.Pointer
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomListItem
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListItem
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_ROOM_ID_3
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
import kotlinx.coroutines.flow.MutableStateFlow
@@ -148,6 +149,18 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID)
}
@Test
fun `Reset removes all entries and add the provided ones`() = runTest {
summaries.value = listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(A_ROOM_ID_2))
val processor = createProcessor()
val index = 0
processor.postUpdate(listOf(RoomListEntriesUpdate.Reset(listOf(FakeRustRoomListItem(A_ROOM_ID_3)))))
assertThat(summaries.value.count()).isEqualTo(1)
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_3)
}
private fun TestScope.createProcessor() = RoomSummaryListProcessor(
summaries,
fakeRoomListService,

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.server
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.test.FakeMatrixClient
import org.junit.Test
class DefaultUserServerResolverTest {
@Test
fun resolve() {
// Given
val userServerResolver = DefaultUserServerResolver(FakeMatrixClient(
userIdServerNameLambda = { "dummy.org" }
))
// When
val result = userServerResolver.resolve()
// Then
assertThat(result).isEqualTo("dummy.org")
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.sync
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.sync.SyncState
import org.junit.Test
import org.matrix.rustcomponents.sdk.SyncServiceState
class AppStateMapperKtTest {
@Test
fun toSyncState() {
assertThat(SyncServiceState.IDLE.toSyncState()).isEqualTo(SyncState.Idle)
assertThat(SyncServiceState.RUNNING.toSyncState()).isEqualTo(SyncState.Running)
assertThat(SyncServiceState.TERMINATED.toSyncState()).isEqualTo(SyncState.Terminated)
assertThat(SyncServiceState.ERROR.toSyncState()).isEqualTo(SyncState.Error)
}
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.timeline
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustTimelineDiff
import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper
import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper
import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.matrix.rustcomponents.sdk.TimelineChange
class MatrixTimelineDiffProcessorTest {
private val timelineItems = MutableStateFlow<List<MatrixTimelineItem>>(emptyList())
private val anEvent = MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem())
private val anEvent2 = MatrixTimelineItem.Event(A_UNIQUE_ID_2, anEventTimelineItem())
@Test
fun `Append adds new entries at the end of the list`() = runTest {
timelineItems.value = listOf(anEvent)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.APPEND)))
assertThat(timelineItems.value.count()).isEqualTo(2)
assertThat(timelineItems.value).containsExactly(
anEvent,
MatrixTimelineItem.Other,
)
}
@Test
fun `PushBack adds a new entry at the end of the list`() = runTest {
timelineItems.value = listOf(anEvent)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.PUSH_BACK)))
assertThat(timelineItems.value.count()).isEqualTo(2)
assertThat(timelineItems.value).containsExactly(
anEvent,
MatrixTimelineItem.Other,
)
}
@Test
fun `PushFront inserts a new entry at the start of the list`() = runTest {
timelineItems.value = listOf(anEvent)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.PUSH_FRONT)))
assertThat(timelineItems.value.count()).isEqualTo(2)
assertThat(timelineItems.value).containsExactly(
MatrixTimelineItem.Other,
anEvent,
)
}
@Test
fun `Set replaces an entry at some index`() = runTest {
timelineItems.value = listOf(anEvent, anEvent2)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.SET)))
assertThat(timelineItems.value.count()).isEqualTo(2)
assertThat(timelineItems.value).containsExactly(
anEvent,
MatrixTimelineItem.Other
)
}
@Test
fun `Insert inserts a new entry at the provided index`() = runTest {
timelineItems.value = listOf(anEvent, anEvent2)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.INSERT)))
assertThat(timelineItems.value.count()).isEqualTo(3)
assertThat(timelineItems.value).containsExactly(
anEvent,
MatrixTimelineItem.Other,
anEvent2,
)
}
@Test
fun `Remove removes an entry at some index`() = runTest {
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.REMOVE)))
assertThat(timelineItems.value.count()).isEqualTo(2)
assertThat(timelineItems.value).containsExactly(
anEvent,
anEvent2,
)
}
@Test
fun `PopBack removes an entry at the end of the list`() = runTest {
timelineItems.value = listOf(anEvent, anEvent2)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.POP_BACK)))
assertThat(timelineItems.value.count()).isEqualTo(1)
assertThat(timelineItems.value).containsExactly(
anEvent,
)
}
@Test
fun `PopFront removes an entry at the start of the list`() = runTest {
timelineItems.value = listOf(anEvent, anEvent2)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.POP_FRONT)))
assertThat(timelineItems.value.count()).isEqualTo(1)
assertThat(timelineItems.value).containsExactly(
anEvent2,
)
}
@Test
fun `Clear removes all the entries`() = runTest {
timelineItems.value = listOf(anEvent, anEvent2)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.CLEAR)))
assertThat(timelineItems.value).isEmpty()
}
@Test
fun `Truncate removes all entries after the provided length`() = runTest {
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.TRUNCATE)))
assertThat(timelineItems.value.count()).isEqualTo(1)
assertThat(timelineItems.value).containsExactly(
anEvent,
)
}
@Test
fun `Reset removes all entries and add the provided ones`() = runTest {
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
val processor = createProcessor()
processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.RESET)))
assertThat(timelineItems.value.count()).isEqualTo(1)
assertThat(timelineItems.value).containsExactly(
MatrixTimelineItem.Other,
)
}
private fun TestScope.createProcessor(): MatrixTimelineDiffProcessor {
val timelineEventContentMapper = TimelineEventContentMapper()
val timelineItemMapper = MatrixTimelineItemMapper(
fetchDetailsForEvent = { _ -> Result.success(Unit) },
coroutineScope = this,
virtualTimelineItemMapper = VirtualTimelineItemMapper(),
eventTimelineItemMapper = EventTimelineItemMapper(
contentMapper = timelineEventContentMapper
)
)
return MatrixTimelineDiffProcessor(
timelineItems,
timelineItemFactory = timelineItemMapper,
)
}
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.timeline
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.timeline.ReceiptType
import org.junit.Test
import org.matrix.rustcomponents.sdk.ReceiptType as RustReceiptType
class ReceiptTypeMapperKtTest {
@Test
fun toRustReceiptType() {
assertThat(ReceiptType.READ.toRustReceiptType()).isEqualTo(RustReceiptType.READ)
assertThat(ReceiptType.READ_PRIVATE.toRustReceiptType()).isEqualTo(RustReceiptType.READ_PRIVATE)
assertThat(ReceiptType.FULLY_READ.toRustReceiptType()).isEqualTo(RustReceiptType.FULLY_READ)
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.timeline.postprocessor
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
import io.element.android.libraries.matrix.api.timeline.item.event.OtherState
import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.timeline.aMessageContent
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
internal val roomCreateEvent = MatrixTimelineItem.Event(
uniqueId = UniqueId("m.room.create"),
event = anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))
)
internal val roomCreatorJoinEvent = MatrixTimelineItem.Event(
uniqueId = UniqueId("m.room.member"),
event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))
)
internal val otherMemberJoinEvent = MatrixTimelineItem.Event(
uniqueId = UniqueId("m.room.member_other"),
event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED))
)
internal val messageEvent = MatrixTimelineItem.Event(
uniqueId = UniqueId("m.room.message"),
event = anEventTimelineItem(content = aMessageContent("hi"))
)
internal val messageEvent2 = MatrixTimelineItem.Event(
uniqueId = UniqueId("m.room.message2"),
event = anEventTimelineItem(content = aMessageContent("hello"))
)
internal val dayEvent = MatrixTimelineItem.Virtual(
uniqueId = UniqueId("day"),
virtual = VirtualTimelineItem.DayDivider(0),
)

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.timeline.postprocessor
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
import org.junit.Test
class LastForwardIndicatorsPostProcessorTest {
@Test
fun `LastForwardIndicatorsPostProcessor does not alter the items with mode not FOCUSED_ON_EVENT`() {
val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.LIVE)
val result = sut.process(listOf(messageEvent), true)
assertThat(result).containsExactly(messageEvent)
}
@Test
fun `LastForwardIndicatorsPostProcessor does not alter the items with mode FOCUSED_ON_EVENT but timeline not initialized`() {
val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT)
val result = sut.process(listOf(messageEvent), false)
assertThat(result).containsExactly(messageEvent)
}
@Test
fun `LastForwardIndicatorsPostProcessor add virtual items`() {
val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT)
val result = sut.process(listOf(messageEvent), true)
assertThat(result).containsExactly(
messageEvent,
MatrixTimelineItem.Virtual(
uniqueId = UniqueId("last_forward_indicator_${messageEvent.uniqueId}"),
virtual = VirtualTimelineItem.LastForwardIndicator
)
)
}
@Test
fun `LastForwardIndicatorsPostProcessor add virtual items on empty list`() {
val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT)
val result = sut.process(listOf(), true)
assertThat(result).containsExactly(
MatrixTimelineItem.Virtual(
uniqueId = UniqueId("last_forward_indicator_fake_id"),
virtual = VirtualTimelineItem.LastForwardIndicator
)
)
}
@Test
fun `LastForwardIndicatorsPostProcessor add virtual items but does not alter the list if called a second time`() {
val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT)
// Process a first time
sut.process(listOf(messageEvent), true)
// Process a second time with the same Event
val result = sut.process(listOf(messageEvent), true)
assertThat(result).containsExactly(
messageEvent,
MatrixTimelineItem.Virtual(
uniqueId = UniqueId("last_forward_indicator_${messageEvent.uniqueId}"),
virtual = VirtualTimelineItem.LastForwardIndicator
)
)
}
@Test
fun `LastForwardIndicatorsPostProcessor add virtual items each time it is called with new Events`() {
val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT)
// Process a first time
sut.process(listOf(dayEvent, messageEvent), true)
// Process a second time with the same Event
val result = sut.process(listOf(dayEvent, messageEvent, messageEvent2), true)
assertThat(result).containsExactly(
dayEvent,
messageEvent,
MatrixTimelineItem.Virtual(
uniqueId = UniqueId("last_forward_indicator_${messageEvent.uniqueId}"),
virtual = VirtualTimelineItem.LastForwardIndicator
),
messageEvent2,
MatrixTimelineItem.Virtual(
uniqueId = UniqueId("last_forward_indicator_${messageEvent2.uniqueId}"),
virtual = VirtualTimelineItem.LastForwardIndicator
)
)
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.timeline.postprocessor
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
import org.junit.Test
class LoadingIndicatorsPostProcessorTest {
@Test
fun `LoadingIndicatorsPostProcessor does not alter the items is the timeline is not initialized`() {
val sut = LoadingIndicatorsPostProcessor(FakeSystemClock())
val result = sut.process(
items = listOf(messageEvent, messageEvent2),
isTimelineInitialized = false,
hasMoreToLoadBackward = true,
hasMoreToLoadForward = true,
)
assertThat(result).containsExactly(messageEvent, messageEvent2)
}
@Test
fun `LoadingIndicatorsPostProcessor adds Loading indicator at the top of the list if hasMoreToLoadBackward is true`() {
val clock = FakeSystemClock()
val sut = LoadingIndicatorsPostProcessor(clock)
val result = sut.process(
items = listOf(messageEvent, messageEvent2),
isTimelineInitialized = true,
hasMoreToLoadBackward = true,
hasMoreToLoadForward = false,
)
assertThat(result).containsExactly(
MatrixTimelineItem.Virtual(
uniqueId = UniqueId("BackwardLoadingIndicator"),
virtual = VirtualTimelineItem.LoadingIndicator(
direction = Timeline.PaginationDirection.BACKWARDS,
timestamp = clock.epochMillis()
)
),
messageEvent,
messageEvent2,
)
}
@Test
fun `LoadingIndicatorsPostProcessor adds Loading indicator at the bottom of the list if hasMoreToLoadForward is true`() {
val clock = FakeSystemClock()
val sut = LoadingIndicatorsPostProcessor(clock)
val result = sut.process(
items = listOf(messageEvent, messageEvent2),
isTimelineInitialized = true,
hasMoreToLoadBackward = false,
hasMoreToLoadForward = true,
)
assertThat(result).containsExactly(
messageEvent,
messageEvent2,
MatrixTimelineItem.Virtual(
uniqueId = UniqueId("ForwardLoadingIndicator"),
virtual = VirtualTimelineItem.LoadingIndicator(
direction = Timeline.PaginationDirection.FORWARDS,
timestamp = clock.epochMillis()
)
),
)
}
@Test
fun `LoadingIndicatorsPostProcessor adds Loading indicator at the bottom and at the top of the list`() {
val clock = FakeSystemClock()
val sut = LoadingIndicatorsPostProcessor(clock)
val result = sut.process(
items = listOf(messageEvent, messageEvent2),
isTimelineInitialized = true,
hasMoreToLoadBackward = true,
hasMoreToLoadForward = true,
)
assertThat(result).containsExactly(
MatrixTimelineItem.Virtual(
uniqueId = UniqueId("BackwardLoadingIndicator"),
virtual = VirtualTimelineItem.LoadingIndicator(
direction = Timeline.PaginationDirection.BACKWARDS,
timestamp = clock.epochMillis()
)
),
messageEvent,
messageEvent2,
MatrixTimelineItem.Virtual(
uniqueId = UniqueId("ForwardLoadingIndicator"),
virtual = VirtualTimelineItem.LoadingIndicator(
direction = Timeline.PaginationDirection.FORWARDS,
timestamp = clock.epochMillis()
)
),
)
}
@Test
fun `LoadingIndicatorsPostProcessor only adds 1 Loading indicator if there is no items in the list`() {
val clock = FakeSystemClock()
val sut = LoadingIndicatorsPostProcessor(clock)
val result = sut.process(
items = listOf(),
isTimelineInitialized = true,
hasMoreToLoadBackward = true,
hasMoreToLoadForward = true,
)
assertThat(result).containsExactly(
MatrixTimelineItem.Virtual(
uniqueId = UniqueId("BackwardLoadingIndicator"),
virtual = VirtualTimelineItem.LoadingIndicator(
direction = Timeline.PaginationDirection.BACKWARDS,
timestamp = clock.epochMillis()
)
),
)
}
}

View File

@@ -8,37 +8,11 @@
package io.element.android.libraries.matrix.impl.timeline.postprocessor
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
import io.element.android.libraries.matrix.api.timeline.item.event.OtherState
import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.timeline.aMessageContent
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
import org.junit.Test
class RoomBeginningPostProcessorTest {
private val roomCreateEvent = MatrixTimelineItem.Event(
uniqueId = UniqueId("m.room.create"),
event = anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))
)
private val roomCreatorJoinEvent = MatrixTimelineItem.Event(
uniqueId = UniqueId("m.room.member"),
event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))
)
private val otherMemberJoinEvent = MatrixTimelineItem.Event(
uniqueId = UniqueId("m.room.member_other"),
event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED))
)
private val messageEvent = MatrixTimelineItem.Event(
uniqueId = UniqueId("m.room.message"),
event = anEventTimelineItem(content = aMessageContent("hi"))
)
@Test
fun `processor returns empty list when empty list is provided`() {
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.usersearch
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile
import io.element.android.libraries.matrix.test.A_USER_ID
import org.junit.Test
class UserProfileMapperTest {
@Test
fun map() {
assertThat(UserProfileMapper.map(aRustUserProfile(A_USER_ID.value, "displayName", "avatarUrl")))
.isEqualTo(MatrixUser(A_USER_ID, "displayName", "avatarUrl"))
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.usersearch
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSearchUsersResults
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile
import io.element.android.libraries.matrix.test.A_USER_ID
import kotlinx.collections.immutable.toImmutableList
import org.junit.Test
class UserSearchResultMapperTest {
@Test
fun `map limited list`() {
assertThat(
UserSearchResultMapper.map(
aRustSearchUsersResults(
results = listOf(aRustUserProfile(A_USER_ID.value, "displayName", "avatarUrl")),
limited = true,
)
)
)
.isEqualTo(
MatrixSearchUserResults(
results = listOf(MatrixUser(A_USER_ID, "displayName", "avatarUrl")).toImmutableList(),
limited = true,
)
)
}
@Test
fun `map not limited list`() {
assertThat(
UserSearchResultMapper.map(
aRustSearchUsersResults(
results = listOf(aRustUserProfile(A_USER_ID.value, "displayName", "avatarUrl")),
limited = false,
)
)
)
.isEqualTo(
MatrixSearchUserResults(
results = listOf(MatrixUser(A_USER_ID, "displayName", "avatarUrl")).toImmutableList(),
limited = false,
)
)
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.util
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import kotlinx.coroutines.test.runTest
import org.junit.Test
class SessionPathsProviderTest {
@Test
fun `if session is not found, provides returns null`() = runTest {
val sut = SessionPathsProvider(InMemorySessionStore())
val result = sut.provides(A_SESSION_ID)
assertThat(result).isNull()
}
@Test
fun `if session is found, provides returns the data`() = runTest {
val store = InMemorySessionStore()
val sut = SessionPathsProvider(store)
store.storeData(
aSessionData(
sessionPath = "/a/path/to/a/session",
cachePath = "/a/path/to/a/cache",
)
)
val result = sut.provides(A_SESSION_ID)!!
assertThat(result.fileDirectory.absolutePath).isEqualTo("/a/path/to/a/session")
assertThat(result.cacheDirectory.absolutePath).isEqualTo("/a/path/to/a/cache")
}
}

View File

@@ -520,7 +520,7 @@ fun aRoomInfo(
isTombstoned: Boolean = false,
isFavorite: Boolean = false,
canonicalAlias: RoomAlias? = null,
alternativeAliases: List<String> = emptyList(),
alternativeAliases: List<RoomAlias> = emptyList(),
currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED,
inviter: RoomMember? = null,
activeMembersCount: Long = 1,
@@ -531,7 +531,7 @@ fun aRoomInfo(
userDefinedNotificationMode: RoomNotificationMode? = null,
hasRoomCall: Boolean = false,
userPowerLevels: ImmutableMap<UserId, Long> = persistentMapOf(),
activeRoomCallParticipants: List<String> = emptyList(),
activeRoomCallParticipants: List<UserId> = emptyList(),
heroes: List<MatrixUser> = emptyList(),
pinnedEventIds: List<EventId> = emptyList(),
roomCreator: UserId? = null,

View File

@@ -51,9 +51,9 @@ class DefaultFirebaseNewTokenHandlerTest {
val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult)
val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler(
sessionStore = InMemoryMultiSessionsStore().apply {
storeData(aSessionData(A_USER_ID))
storeData(aSessionData(A_USER_ID_2))
storeData(aSessionData(A_USER_ID_3))
storeData(aSessionData(A_USER_ID.value))
storeData(aSessionData(A_USER_ID_2.value))
storeData(aSessionData(A_USER_ID_3.value))
},
matrixClientProvider = FakeMatrixClientProvider { sessionId ->
when (sessionId) {
@@ -90,7 +90,7 @@ class DefaultFirebaseNewTokenHandlerTest {
val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult)
val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler(
sessionStore = InMemoryMultiSessionsStore().apply {
storeData(aSessionData(A_USER_ID))
storeData(aSessionData(A_USER_ID.value))
},
matrixClientProvider = FakeMatrixClientProvider {
Result.failure(IllegalStateException())
@@ -114,7 +114,7 @@ class DefaultFirebaseNewTokenHandlerTest {
val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult)
val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler(
sessionStore = InMemoryMultiSessionsStore().apply {
storeData(aSessionData(A_USER_ID))
storeData(aSessionData(A_USER_ID.value))
},
matrixClientProvider = FakeMatrixClientProvider {
Result.success(aMatrixClient1)

View File

@@ -7,19 +7,19 @@
package io.element.android.libraries.sessionstorage.test
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.sessionstorage.api.LoginType
import io.element.android.libraries.sessionstorage.api.SessionData
fun aSessionData(
sessionId: SessionId = SessionId("@alice:server.org"),
sessionId: String = "@alice:server.org",
deviceId: String = "aDeviceId",
isTokenValid: Boolean = false,
sessionPath: String = "/a/path/to/a/session",
cachePath: String = "/a/path/to/a/cache",
): SessionData {
return SessionData(
userId = sessionId.value,
deviceId = "aDeviceId",
userId = sessionId,
deviceId = deviceId,
accessToken = "anAccessToken",
refreshToken = "aRefreshToken",
homeserverUrl = "aHomeserverUrl",

View File

@@ -68,11 +68,12 @@ class KonsistClassNameTest {
.withoutName(
"FakeFileSystem",
"FakeImageLoader",
"FakeRustRoom",
)
.assertTrue {
val interfaceName = it.name.replace("Fake", "")
it.name.startsWith("Fake") &&
val interfaceName = it.name
.replace("FakeRust", "")
.replace("Fake", "")
(it.name.startsWith("Fake") || it.name.startsWith("FakeRust")) &&
it.parents().any { parent -> parent.name.replace(".", "") == interfaceName }
}
}