From ae7c2257dfd822b64b9500191715940f74ec85cc Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 6 Oct 2023 11:37:26 +0200 Subject: [PATCH] Improve coverage in permalinks package (#1502) * Improve coverage in permalinks package --- libraries/matrix/api/build.gradle.kts | 2 + .../api/permalink/MatrixToConverterTests.kt | 58 ++++++ .../api/permalink/PermalinkBuilderTests.kt | 81 +++++++++ .../api/permalink/PermalinkParserTests.kt | 167 ++++++++++++++++++ .../android/tests/testutils/IsInDebug.kt | 22 +++ 5 files changed, 330 insertions(+) create mode 100644 libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/MatrixToConverterTests.kt create mode 100644 libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilderTests.kt create mode 100644 libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParserTests.kt create mode 100644 tests/testutils/src/main/kotlin/io/element/android/tests/testutils/IsInDebug.kt diff --git a/libraries/matrix/api/build.gradle.kts b/libraries/matrix/api/build.gradle.kts index 1ffe07eb6f..5a430f7db5 100644 --- a/libraries/matrix/api/build.gradle.kts +++ b/libraries/matrix/api/build.gradle.kts @@ -44,4 +44,6 @@ dependencies { testImplementation(libs.test.junit) testImplementation(libs.test.truth) + testImplementation(libs.test.robolectric) + testImplementation(projects.tests.testutils) } diff --git a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/MatrixToConverterTests.kt b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/MatrixToConverterTests.kt new file mode 100644 index 0000000000..ef0a586fba --- /dev/null +++ b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/MatrixToConverterTests.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.permalink + +import android.net.Uri +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class MatrixToConverterTests { + + @Test + fun `converting a matrix-to url does nothing`() { + val url = Uri.parse("https://matrix.to/#/#element-android:matrix.org") + assertThat(MatrixToConverter.convert(url)).isEqualTo(url) + } + + @Test + fun `converting a url with a supported room path returns a matrix-to url`() { + val url = Uri.parse("https://riot.im/develop/#/room/#element-android:matrix.org") + assertThat(MatrixToConverter.convert(url)).isEqualTo(Uri.parse("https://matrix.to/#/#element-android:matrix.org")) + } + + @Test + fun `converting a url with a supported user path returns a matrix-to url`() { + val url = Uri.parse("https://riot.im/develop/#/user/@test:matrix.org") + assertThat(MatrixToConverter.convert(url)).isEqualTo(Uri.parse("https://matrix.to/#/@test:matrix.org")) + } + + @Test + fun `converting a url with a supported group path returns a matrix-to url`() { + val url = Uri.parse("https://riot.im/develop/#/group/+group:matrix.org") + assertThat(MatrixToConverter.convert(url)).isEqualTo(Uri.parse("https://matrix.to/#/+group:matrix.org")) + } + + @Test + fun `converting an unsupported url returns null`() { + val url = Uri.parse("https://element.io/") + assertThat(MatrixToConverter.convert(url)).isNull() + } + +} diff --git a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilderTests.kt b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilderTests.kt new file mode 100644 index 0000000000..0a9a03cabb --- /dev/null +++ b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilderTests.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.permalink + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.tests.testutils.assertThrowsInDebug +import io.element.android.tests.testutils.isInDebug +import org.junit.Test + +class PermalinkBuilderTests { + + fun `building a permalink for an invalid user id throws when verifying the id`() { + assertThrowsInDebug { + val userId = UserId("some invalid user id") + PermalinkBuilder.permalinkForUser(userId) + } + } + + fun `building a permalink for an invalid room id throws when verifying the id`() { + assertThrowsInDebug { + val roomId = RoomId("some invalid room id") + PermalinkBuilder.permalinkForRoomId(roomId) + } + } + + @Test + fun `building a permalink for an invalid user id returns failure when not verifying the id`() { + if (!isInDebug()) { + val userId = UserId("some invalid user id") + assertThat(PermalinkBuilder.permalinkForUser(userId).isFailure).isTrue() + } + } + + @Test + fun `building a permalink for an invalid room id returns failure when not verifying the id`() { + if (!isInDebug()) { + val roomId = RoomId("some invalid room id") + assertThat(PermalinkBuilder.permalinkForRoomId(roomId).isFailure).isTrue() + } + } + + @Test + fun `building a permalink for an invalid room alias returns failure`() { + val roomAlias = "an invalid room alias" + assertThat(PermalinkBuilder.permalinkForRoomAlias(roomAlias).isFailure).isTrue() + } + + @Test + fun `building a permalink for a valid user id returns a matrix-to url`() { + val userId = UserId("@user:matrix.org") + assertThat(PermalinkBuilder.permalinkForUser(userId).getOrNull()).isEqualTo("https://matrix.to/#/@user:matrix.org") + } + + @Test + fun `building a permalink for a valid room id returns a matrix-to url`() { + val roomId = RoomId("!aBCdEFG1234:matrix.org") + assertThat(PermalinkBuilder.permalinkForRoomId(roomId).getOrNull()).isEqualTo("https://matrix.to/#/!aBCdEFG1234:matrix.org") + } + + @Test + fun `building a permalink for a valid room alias returns a matrix-to url`() { + val roomAlias = "#room:matrix.org" + assertThat(PermalinkBuilder.permalinkForRoomAlias(roomAlias).getOrNull()).isEqualTo("https://matrix.to/#/#room:matrix.org") + } +} diff --git a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParserTests.kt b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParserTests.kt new file mode 100644 index 0000000000..74797083c4 --- /dev/null +++ b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParserTests.kt @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.permalink + +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class PermalinkParserTests { + + @Test + fun `parsing an invalid url returns a fallback link`() { + val url = "https://element.io" + assertThat(PermalinkParser.parse(url)).isInstanceOf(PermalinkData.FallbackLink::class.java) + } + + @Test + fun `parsing an invalid url with the right path but no content returns a fallback link`() { + val url = "https://app.element.io/#/user" + assertThat(PermalinkParser.parse(url)).isInstanceOf(PermalinkData.FallbackLink::class.java) + } + + @Test + fun `parsing an invalid url with the right path but empty content returns a fallback link`() { + val url = "https://app.element.io/#/user/" + assertThat(PermalinkParser.parse(url)).isInstanceOf(PermalinkData.FallbackLink::class.java) + } + + @Test + fun `parsing an invalid url with the right path but invalid content returns a fallback link`() { + val url = "https://app.element.io/#/user/some%20user!" + assertThat(PermalinkParser.parse(url)).isInstanceOf(PermalinkData.FallbackLink::class.java) + } + + @Test + fun `parsing a valid user url returns a user link`() { + val url = "https://app.element.io/#/user/@test:matrix.org" + assertThat(PermalinkParser.parse(url)).isEqualTo( + PermalinkData.UserLink( + userId = "@test:matrix.org" + ) + ) + } + + @Test + fun `parsing a valid room id url returns a room link`() { + val url = "https://app.element.io/#/room/!aBCD1234:matrix.org" + assertThat(PermalinkParser.parse(url)).isEqualTo( + PermalinkData.RoomLink( + roomIdOrAlias = "!aBCD1234:matrix.org", + isRoomAlias = false, + eventId = null, + viaParameters = emptyList(), + ) + ) + } + + @Test + fun `parsing a valid room id with event id url returns a room link`() { + val url = "https://app.element.io/#/room/!aBCD1234:matrix.org/$1234567890abcdef:matrix.org" + assertThat(PermalinkParser.parse(url)).isEqualTo( + PermalinkData.RoomLink( + roomIdOrAlias = "!aBCD1234:matrix.org", + isRoomAlias = false, + eventId = "\$1234567890abcdef:matrix.org", + viaParameters = emptyList(), + ) + ) + } + + @Test + fun `parsing a valid room id with and invalid event id url returns a room link with no event id`() { + val url = "https://app.element.io/#/room/!aBCD1234:matrix.org/1234567890abcdef:matrix.org" + assertThat(PermalinkParser.parse(url)).isEqualTo( + PermalinkData.RoomLink( + roomIdOrAlias = "!aBCD1234:matrix.org", + isRoomAlias = false, + eventId = null, + viaParameters = emptyList(), + ) + ) + } + + @Test + fun `parsing a valid room id with event id and via parameters url returns a room link`() { + val url = "https://app.element.io/#/room/!aBCD1234:matrix.org/$1234567890abcdef:matrix.org?via=matrix.org&via=matrix.com" + assertThat(PermalinkParser.parse(url)).isEqualTo( + PermalinkData.RoomLink( + roomIdOrAlias = "!aBCD1234:matrix.org", + isRoomAlias = false, + eventId = "\$1234567890abcdef:matrix.org", + viaParameters = listOf("matrix.org", "matrix.com"), + ) + ) + } + + @Test + fun `parsing a valid room alias url returns a room link`() { + val url = "https://app.element.io/#/room/#element-android:matrix.org" + assertThat(PermalinkParser.parse(url)).isEqualTo( + PermalinkData.RoomLink( + roomIdOrAlias = "#element-android:matrix.org", + isRoomAlias = true, + eventId = null, + viaParameters = emptyList(), + ) + ) + } + + @Test + fun `parsing a url with an invalid signurl returns a fallback link`() { + // This url has no private key + val url = "https://app.element.io/#/room/%21aBCDEF12345%3Amatrix.org" + + "?email=testuser%40element.io" + + "&signurl=https%3A%2F%2Fvector.im%2F_matrix%2Fidentity%2Fapi%2Fv1%2Fsign-ed25519%3Ftoken%3Da_token" + + "&room_name=TestRoom" + + "&room_avatar_url=" + + "&inviter_name=User" + + "&guest_access_token=" + + "&guest_user_id=" + + "&room_type=" + assertThat(PermalinkParser.parse(url)).isInstanceOf(PermalinkData.FallbackLink::class.java) + } + + @Test + fun `parsing a url with signurl returns a room email invite link`() { + val url = "https://app.element.io/#/room/%21aBCDEF12345%3Amatrix.org" + + "?email=testuser%40element.io" + + "&signurl=https%3A%2F%2Fvector.im%2F_matrix%2Fidentity%2Fapi%2Fv1%2Fsign-ed25519%3Ftoken%3Da_token%26private_key%3Da_private_key" + + "&room_name=TestRoom" + + "&room_avatar_url=" + + "&inviter_name=User" + + "&guest_access_token=" + + "&guest_user_id=" + + "&room_type=" + assertThat(PermalinkParser.parse(url)).isEqualTo( + PermalinkData.RoomEmailInviteLink( + roomId = "!aBCDEF12345:matrix.org", + email = "testuser@element.io", + signUrl = "https://vector.im/_matrix/identity/api/v1/sign-ed25519?token=a_token&private_key=a_private_key", + roomName = "TestRoom", + roomAvatarUrl = "", + inviterName = "User", + identityServer = "vector.im", + token = "a_token", + privateKey = "a_private_key", + roomType = "", + ) + ) + } +} diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/IsInDebug.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/IsInDebug.kt new file mode 100644 index 0000000000..d2bef1c4c2 --- /dev/null +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/IsInDebug.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.tests.testutils + +/** + * Returns true if the app is in debug mode. + */ +fun isInDebug() = BuildConfig.DEBUG