diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index de97b26fbf..d8c1bb6c49 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -14,50 +14,6 @@ env: -Porg.gradle.jvmargs=-Xmx4g -Porg.gradle.parallel=false jobs: - # Build Android Tests [Matrix SDK] - build-android-test-matrix-sdk: - name: Matrix SDK - Build Android Tests - runs-on: macos-latest - # No concurrency required, runs every time on a schedule. - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v2 - with: - distribution: 'adopt' - java-version: 11 - - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Build Android Tests for matrix-sdk-android - run: ./gradlew clean matrix-sdk-android:assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace - - # Build Android Tests [Matrix APP] - build-android-test-app: - name: App - Build Android Tests - runs-on: macos-latest - # No concurrency required, runs every time on a schedule. - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v2 - with: - distribution: 'adopt' - java-version: 11 - - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Build Android Tests for vector - run: ./gradlew clean vector:assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace - # Run Android Tests integration-tests: name: Matrix SDK - Running Integration Tests @@ -367,9 +323,6 @@ jobs: needs: - integration-tests - ui-tests -# - unit-tests - - build-android-test-matrix-sdk - - build-android-test-app - sonarqube if: always() && github.event_name != 'workflow_dispatch' # No concurrency required, runs every time on a schedule. diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d739afcd30..587bf14488 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,6 +12,30 @@ env: -Porg.gradle.parallel=false jobs: + # Build Android Tests + build-android-tests: + name: Build Android Tests + runs-on: ubuntu-latest + concurrency: + group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('build-android-tests-{0}', github.ref) }} + cancel-in-progress: true + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: 11 + - uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Build Android Tests + run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace + unit-tests: name: Run Unit Tests runs-on: ubuntu-latest @@ -41,3 +65,20 @@ jobs: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository ) with: files: ./**/build/test-results/**/*.xml + +# Notify the channel about runs against develop or main that have failures, as PRs should have caught these first. + notify: + runs-on: ubuntu-latest + needs: + - unit-tests + - build-android-tests + if: ${{ (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/main' ) && failure() }} + steps: + - uses: michaelkaye/matrix-hookshot-action@v0.3.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + matrix_access_token: ${{ secrets.ELEMENT_ANDROID_NOTIFICATION_ACCESS_TOKEN }} + matrix_room_id: ${{ secrets.ELEMENT_ANDROID_INTERNAL_ROOM_ID }} + text_template: "Build is broken for ${{ github.ref }}: {{#each job_statuses }}{{#with this }}{{#if completed }}{{name}} {{conclusion}} at {{completed_at}}, {{/if}}{{/with}}{{/each}}" + html_template: "Build is broken for ${{ github.ref }}: {{#each job_statuses }}{{#with this }}{{#if completed }}
{{icon conclusion }} {{name}} {{conclusion}} at {{completed_at}} [details]{{/if}}{{/with}}{{/each}}" + diff --git a/.idea/dictionaries/bmarty.xml b/.idea/dictionaries/bmarty.xml index ed572b573f..85290e72df 100644 --- a/.idea/dictionaries/bmarty.xml +++ b/.idea/dictionaries/bmarty.xml @@ -11,6 +11,7 @@ emoji emojis fdroid + ganfra gplay hmac homeserver @@ -18,6 +19,7 @@ ktlint linkified linkify + manu megolm msisdn msisdns diff --git a/changelog.d/4860.bugfix b/changelog.d/4860.bugfix new file mode 100644 index 0000000000..32049face4 --- /dev/null +++ b/changelog.d/4860.bugfix @@ -0,0 +1 @@ +Add colors for shield vector drawable \ No newline at end of file diff --git a/changelog.d/5443.misc b/changelog.d/5443.misc new file mode 100644 index 0000000000..f9fd715403 --- /dev/null +++ b/changelog.d/5443.misc @@ -0,0 +1 @@ +Adds stable room hierarchy endpoint with a fallback to the unstable one diff --git a/library/ui-styles/src/main/res/values/colors.xml b/library/ui-styles/src/main/res/values/colors.xml index 1b214cfc59..75b03a7d2e 100644 --- a/library/ui-styles/src/main/res/values/colors.xml +++ b/library/ui-styles/src/main/res/values/colors.xml @@ -126,4 +126,10 @@ @color/palette_prune @color/palette_prune + + + #0DBD8B + #17191C + #FF4B55 + diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 4a5b45c4f9..2b2c38e22a 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -166,7 +166,7 @@ dependencies { implementation libs.apache.commonsImaging // Phone number https://github.com/google/libphonenumber - implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.44' + implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.45' testImplementation libs.tests.junit testImplementation 'org.robolectric:robolectric:4.7.3' @@ -174,7 +174,7 @@ dependencies { // Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281 testImplementation libs.mockk.mockk testImplementation libs.tests.kluent - implementation libs.jetbrains.coroutinesAndroid + testImplementation libs.jetbrains.coroutinesTest // Plant Timber tree for test testImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1' // Transitively required for mocking realm as monarchy doesn't expose Rx diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt index 767334dfbd..41ec69cdc5 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt @@ -41,6 +41,7 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.SessionTestParams +import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.common.TestMatrixCallback import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo @@ -99,7 +100,6 @@ class E2eeSanityTests : InstrumentedTest { ensureMembersHaveJoined(aliceSession, otherAccounts, e2eRoomID) Log.v("#E2E TEST", "All users have joined the room") - Log.v("#E2E TEST", "Alice is sending the message") val text = "This is my message" @@ -172,7 +172,7 @@ class E2eeSanityTests : InstrumentedTest { } timelineEvent != null && timelineEvent.root.getClearType() == EventType.MESSAGE && - secondMessage.equals(timelineEvent.root.getClearContent().toModel()?.body) + secondMessage == timelineEvent.root.getClearContent().toModel()?.body } } } @@ -186,11 +186,11 @@ class E2eeSanityTests : InstrumentedTest { } /** - * Quick test for basic keybackup + * Quick test for basic key backup * 1. Create e2e between Alice and Bob * 2. Alice sends 3 messages, using 3 different sessions * 3. Ensure bob can decrypt - * 4. Create backup for bob and uplaod keys + * 4. Create backup for bob and upload keys * * 5. Sign out alice and bob to ensure no gossiping will happen * @@ -206,14 +206,14 @@ class E2eeSanityTests : InstrumentedTest { val bobSession = cryptoTestData.secondSession!! val e2eRoomID = cryptoTestData.roomId - Log.v("#E2E TEST", "Create and start keybackup for bob ...") - val keysBackupService = bobSession.cryptoService().keysBackupService() + Log.v("#E2E TEST", "Create and start key backup for bob ...") + val bobKeysBackupService = bobSession.cryptoService().keysBackupService() val keyBackupPassword = "FooBarBaz" val megolmBackupCreationInfo = testHelper.doSync { - keysBackupService.prepareKeysBackupVersion(keyBackupPassword, null, it) + bobKeysBackupService.prepareKeysBackupVersion(keyBackupPassword, null, it) } val version = testHelper.doSync { - keysBackupService.createKeysBackupVersion(megolmBackupCreationInfo, it) + bobKeysBackupService.createKeysBackupVersion(megolmBackupCreationInfo, it) } Log.v("#E2E TEST", "... Key backup started and enabled for bob") // Bob session should now have @@ -249,12 +249,12 @@ class E2eeSanityTests : InstrumentedTest { Log.v("#E2E TEST", "Force key backup for Bob...") testHelper.waitWithLatch { latch -> - keysBackupService.backupAllGroupSessions( + bobKeysBackupService.backupAllGroupSessions( null, TestMatrixCallback(latch, true) ) } - Log.v("#E2E TEST", "... Keybackup done for Bob") + Log.v("#E2E TEST", "... Key backup done for Bob") // Now lets logout both alice and bob to ensure that we won't have any gossiping @@ -397,7 +397,7 @@ class E2eeSanityTests : InstrumentedTest { } /** - * Test that if a better key is forwared (lower index, it is then used) + * Test that if a better key is forwarded (lower index, it is then used) */ @Test fun testForwardBetterKey() { @@ -525,15 +525,16 @@ class E2eeSanityTests : InstrumentedTest { private fun sendMessageInRoom(aliceRoomPOV: Room, text: String): String? { aliceRoomPOV.sendTextMessage(text) var sentEventId: String? = null - testHelper.waitWithLatch(4 * 60_000) { + testHelper.waitWithLatch(4 * TestConstants.timeOutMillis) { latch -> val timeline = aliceRoomPOV.createTimeline(null, TimelineSettings(60)) timeline.start() - testHelper.retryPeriodicallyWithLatch(it) { + testHelper.retryPeriodicallyWithLatch(latch) { val decryptedMsg = timeline.getSnapshot() .filter { it.root.getClearType() == EventType.MESSAGE } - .also { - Log.v("#E2E TEST", "Timeline snapshot is ${it.map { "${it.root.type}|${it.root.sendState}" }.joinToString(",", "[", "]")}") + .also { list -> + val message = list.joinToString(",", "[", "]") { "${it.root.type}|${it.root.sendState}" } + Log.v("#E2E TEST", "Timeline snapshot is $message") } .filter { it.root.sendState == SendState.SYNCED } .firstOrNull { it.root.getClearContent().toModel()?.body?.startsWith(text) == true } @@ -547,8 +548,8 @@ class E2eeSanityTests : InstrumentedTest { } private fun ensureMembersHaveJoined(aliceSession: Session, otherAccounts: List, e2eRoomID: String) { - testHelper.waitWithLatch { - testHelper.retryPeriodicallyWithLatch(it) { + testHelper.waitWithLatch { latch -> + testHelper.retryPeriodicallyWithLatch(latch) { otherAccounts.map { aliceSession.getRoomMember(it.myUserId, e2eRoomID)?.membership }.all { @@ -559,8 +560,8 @@ class E2eeSanityTests : InstrumentedTest { } private fun waitForAndAcceptInviteInRoom(otherSession: Session, e2eRoomID: String) { - testHelper.waitWithLatch { - testHelper.retryPeriodicallyWithLatch(it) { + testHelper.waitWithLatch { latch -> + testHelper.retryPeriodicallyWithLatch(latch) { val roomSummary = otherSession.getRoomSummary(e2eRoomID) (roomSummary != null && roomSummary.membership == Membership.INVITE).also { if (it) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt index 1ab1042129..5aec7db66c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt @@ -21,6 +21,7 @@ internal object NetworkConstants { private const val URI_API_PREFIX_PATH = "_matrix/client" const val URI_API_PREFIX_PATH_ = "$URI_API_PREFIX_PATH/" const val URI_API_PREFIX_PATH_R0 = "$URI_API_PREFIX_PATH/r0/" + const val URI_API_PREFIX_PATH_V1 = "$URI_API_PREFIX_PATH/v1/" const val URI_API_PREFIX_PATH_UNSTABLE = "$URI_API_PREFIX_PATH/unstable/" // Media diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt index c18055e089..e764ab551a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt @@ -113,71 +113,108 @@ internal class DefaultSpaceService @Inject constructor( return peekSpaceTask.execute(PeekSpaceTask.Params(spaceId)) } - override suspend fun querySpaceChildren(spaceId: String, - suggestedOnly: Boolean?, - limit: Int?, - from: String?, - knownStateList: List?): SpaceHierarchyData { - return resolveSpaceInfoTask.execute( - ResolveSpaceInfoTask.Params( - spaceId = spaceId, limit = limit, maxDepth = 1, from = from, suggestedOnly = suggestedOnly - ) - ).let { response -> - val spaceDesc = response.rooms?.firstOrNull { it.roomId == spaceId } - val root = RoomSummary( - roomId = spaceDesc?.roomId ?: spaceId, - roomType = spaceDesc?.roomType, - name = spaceDesc?.name ?: "", - displayName = spaceDesc?.name ?: "", - topic = spaceDesc?.topic ?: "", - joinedMembersCount = spaceDesc?.numJoinedMembers, - avatarUrl = spaceDesc?.avatarUrl ?: "", - encryptionEventTs = null, - typingUsers = emptyList(), - isEncrypted = false, - flattenParentIds = emptyList(), - canonicalAlias = spaceDesc?.canonicalAlias, - joinRules = RoomJoinRules.PUBLIC.takeIf { spaceDesc?.worldReadable == true } - ) - val children = response.rooms - ?.filter { it.roomId != spaceId } - ?.flatMap { childSummary -> - (spaceDesc?.childrenState ?: knownStateList) - ?.filter { it.stateKey == childSummary.roomId && it.type == EventType.STATE_SPACE_CHILD } - ?.mapNotNull { childStateEv -> - // create a child entry for everytime this room is the child of a space - // beware that a room could appear then twice in this list - childStateEv.content.toModel()?.let { childStateEvContent -> - SpaceChildInfo( - childRoomId = childSummary.roomId, - isKnown = true, - roomType = childSummary.roomType, - name = childSummary.name, - topic = childSummary.topic, - avatarUrl = childSummary.avatarUrl, - order = childStateEvContent.order, -// autoJoin = childStateEvContent.autoJoin ?: false, - viaServers = childStateEvContent.via.orEmpty(), - activeMemberCount = childSummary.numJoinedMembers, - parentRoomId = childStateEv.roomId, - suggested = childStateEvContent.suggested, - canonicalAlias = childSummary.canonicalAlias, - aliases = childSummary.aliases, - worldReadable = childSummary.worldReadable - ) - } - }.orEmpty() - } - .orEmpty() - SpaceHierarchyData( - rootSummary = root, - children = children, - childrenState = spaceDesc?.childrenState.orEmpty(), - nextToken = response.nextBatch - ) - } + override suspend fun querySpaceChildren( + spaceId: String, + suggestedOnly: Boolean?, + limit: Int?, + from: String?, + knownStateList: List? + ): SpaceHierarchyData { + val spacesResponse = getSpacesResponse(spaceId, suggestedOnly, limit, from) + val spaceRootResponse = spacesResponse.getRoot(spaceId) + val spaceRoot = spaceRootResponse?.toRoomSummary() ?: createBlankRoomSummary(spaceId) + val spaceChildren = spacesResponse.rooms.mapSpaceChildren(spaceId, spaceRootResponse, knownStateList) + + return SpaceHierarchyData( + rootSummary = spaceRoot, + children = spaceChildren, + childrenState = spaceRootResponse?.childrenState.orEmpty(), + nextToken = spacesResponse.nextBatch + ) } + private suspend fun getSpacesResponse(spaceId: String, suggestedOnly: Boolean?, limit: Int?, from: String?) = + resolveSpaceInfoTask.execute( + ResolveSpaceInfoTask.Params(spaceId = spaceId, limit = limit, maxDepth = 1, from = from, suggestedOnly = suggestedOnly) + ) + + private fun SpacesResponse.getRoot(spaceId: String) = rooms?.firstOrNull { it.roomId == spaceId } + + private fun SpaceChildSummaryResponse.toRoomSummary() = RoomSummary( + roomId = roomId, + roomType = roomType, + name = name ?: "", + displayName = name ?: "", + topic = topic ?: "", + joinedMembersCount = numJoinedMembers, + avatarUrl = avatarUrl ?: "", + encryptionEventTs = null, + typingUsers = emptyList(), + isEncrypted = false, + flattenParentIds = emptyList(), + canonicalAlias = canonicalAlias, + joinRules = RoomJoinRules.PUBLIC.takeIf { isWorldReadable } + ) + + private fun createBlankRoomSummary(spaceId: String) = RoomSummary( + roomId = spaceId, + joinedMembersCount = null, + encryptionEventTs = null, + typingUsers = emptyList(), + isEncrypted = false, + flattenParentIds = emptyList(), + canonicalAlias = null, + joinRules = null + ) + + private fun List?.mapSpaceChildren( + spaceId: String, + spaceRootResponse: SpaceChildSummaryResponse?, + knownStateList: List?, + ) = this?.filterIdIsNot(spaceId) + ?.toSpaceChildInfoList(spaceId, spaceRootResponse, knownStateList) + .orEmpty() + + private fun List.filterIdIsNot(spaceId: String) = filter { it.roomId != spaceId } + + private fun List.toSpaceChildInfoList( + spaceId: String, + rootRoomResponse: SpaceChildSummaryResponse?, + knownStateList: List?, + ) = flatMap { spaceChildSummary -> + (rootRoomResponse?.childrenState ?: knownStateList) + ?.filter { it.isChildOf(spaceChildSummary) } + ?.mapNotNull { childStateEvent -> childStateEvent.toSpaceChildInfo(spaceId, spaceChildSummary) } + .orEmpty() + } + + private fun Event.isChildOf(space: SpaceChildSummaryResponse) = stateKey == space.roomId && type == EventType.STATE_SPACE_CHILD + + private fun Event.toSpaceChildInfo(spaceId: String, summary: SpaceChildSummaryResponse) = content.toModel()?.let { content -> + createSpaceChildInfo(spaceId, summary, content) + } + + private fun createSpaceChildInfo( + spaceId: String, + summary: SpaceChildSummaryResponse, + content: SpaceChildContent + ) = SpaceChildInfo( + childRoomId = summary.roomId, + isKnown = true, + roomType = summary.roomType, + name = summary.name, + topic = summary.topic, + avatarUrl = summary.avatarUrl, + order = content.order, + viaServers = content.via.orEmpty(), + activeMemberCount = summary.numJoinedMembers, + parentRoomId = spaceId, + suggested = content.suggested, + canonicalAlias = summary.canonicalAlias, + aliases = summary.aliases, + worldReadable = summary.isWorldReadable + ) + override suspend fun joinSpace(spaceIdOrAlias: String, reason: String?, viaServers: List): JoinSpaceResult { @@ -192,10 +229,6 @@ internal class DefaultSpaceService @Inject constructor( leaveRoomTask.execute(LeaveRoomTask.Params(spaceId, reason)) } -// override fun getSpaceParentsOfRoom(roomId: String): List { -// return spaceSummaryDataSource.getParentsOfRoom(roomId) -// } - override suspend fun setSpaceParent(childRoomId: String, parentSpaceId: String, canonical: Boolean, viaServers: List) { // Should we perform some validation here?, // and if client want to bypass, it could use sendStateEvent directly? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/ResolveSpaceInfoTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/ResolveSpaceInfoTask.kt index 2a396d6ee7..d59ca06c2c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/ResolveSpaceInfoTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/ResolveSpaceInfoTask.kt @@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.space import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task +import retrofit2.HttpException import javax.inject.Inject internal interface ResolveSpaceInfoTask : Task { @@ -28,7 +29,6 @@ internal interface ResolveSpaceInfoTask : Task(500, "".toResponseBody())) + } +} diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeSpaceApi.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeSpaceApi.kt new file mode 100644 index 0000000000..d4fc986791 --- /dev/null +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeSpaceApi.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2021 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.test.fakes + +import io.mockk.coEvery +import io.mockk.mockk +import org.matrix.android.sdk.internal.session.space.SpaceApi +import org.matrix.android.sdk.internal.session.space.SpacesResponse +import org.matrix.android.sdk.test.fixtures.ResolveSpaceInfoTaskParamsFixture + +internal class FakeSpaceApi { + + val instance: SpaceApi = mockk() + val params = ResolveSpaceInfoTaskParamsFixture.aResolveSpaceInfoTaskParams() + + fun givenStableEndpointReturns(response: SpacesResponse) { + coEvery { instance.getSpaceHierarchy(params.spaceId, params.suggestedOnly, params.limit, params.maxDepth, params.from) } returns response + } + + fun givenStableEndpointThrows(throwable: Throwable) { + coEvery { instance.getSpaceHierarchy(params.spaceId, params.suggestedOnly, params.limit, params.maxDepth, params.from) } throws throwable + } + + fun givenUnstableEndpointReturns(response: SpacesResponse) { + coEvery { instance.getSpaceHierarchyUnstable(params.spaceId, params.suggestedOnly, params.limit, params.maxDepth, params.from) } returns response + } +} diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/ResolveSpaceInfoTaskParamsFixture.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/ResolveSpaceInfoTaskParamsFixture.kt new file mode 100644 index 0000000000..28f8c3637d --- /dev/null +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/ResolveSpaceInfoTaskParamsFixture.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2021 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.test.fixtures + +import org.matrix.android.sdk.internal.session.space.ResolveSpaceInfoTask + +internal object ResolveSpaceInfoTaskParamsFixture { + fun aResolveSpaceInfoTaskParams( + spaceId: String = "", + limit: Int? = null, + maxDepth: Int? = null, + from: String? = null, + suggestedOnly: Boolean? = null, + ) = ResolveSpaceInfoTask.Params( + spaceId, + limit, + maxDepth, + from, + suggestedOnly, + ) +} diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/SpacesResponseFixture.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/SpacesResponseFixture.kt new file mode 100644 index 0000000000..0a08331114 --- /dev/null +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/SpacesResponseFixture.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2021 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.test.fixtures + +import org.matrix.android.sdk.internal.session.space.SpaceChildSummaryResponse +import org.matrix.android.sdk.internal.session.space.SpacesResponse + +internal object SpacesResponseFixture { + fun aSpacesResponse( + nextBatch: String? = null, + rooms: List? = null, + ) = SpacesResponse( + nextBatch, + rooms, + ) +} diff --git a/vector/build.gradle b/vector/build.gradle index 438e8f2003..2b37c12323 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -367,7 +367,7 @@ dependencies { implementation 'com.facebook.stetho:stetho:1.6.0' // Phone number https://github.com/google/libphonenumber - implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.44' + implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.45' // FlowBinding implementation libs.github.flowBinding diff --git a/vector/src/main/res/drawable/ic_shield_black.xml b/vector/src/main/res/drawable/ic_shield_black.xml index 8ab70d981b..ddde3442b7 100644 --- a/vector/src/main/res/drawable/ic_shield_black.xml +++ b/vector/src/main/res/drawable/ic_shield_black.xml @@ -6,6 +6,6 @@ diff --git a/vector/src/main/res/drawable/ic_shield_black_no_border.xml b/vector/src/main/res/drawable/ic_shield_black_no_border.xml index 1e322c77c3..f9fa5de9f6 100644 --- a/vector/src/main/res/drawable/ic_shield_black_no_border.xml +++ b/vector/src/main/res/drawable/ic_shield_black_no_border.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/vector/src/main/res/drawable/ic_shield_custom.xml b/vector/src/main/res/drawable/ic_shield_custom.xml index ca58f028d9..aa6cbabad3 100644 --- a/vector/src/main/res/drawable/ic_shield_custom.xml +++ b/vector/src/main/res/drawable/ic_shield_custom.xml @@ -4,7 +4,7 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/vector/src/main/res/drawable/ic_shield_trusted.xml b/vector/src/main/res/drawable/ic_shield_trusted.xml index cac0cfcaf6..c122446a3c 100644 --- a/vector/src/main/res/drawable/ic_shield_trusted.xml +++ b/vector/src/main/res/drawable/ic_shield_trusted.xml @@ -6,7 +6,7 @@ + android:fillColor="@color/shield_color_trust"/> diff --git a/vector/src/main/res/drawable/ic_shield_warning.xml b/vector/src/main/res/drawable/ic_shield_warning.xml index ace7d7dbae..237f2aa5fd 100644 --- a/vector/src/main/res/drawable/ic_shield_warning.xml +++ b/vector/src/main/res/drawable/ic_shield_warning.xml @@ -6,7 +6,7 @@ + android:fillColor="@color/shield_color_warning"/>