From 1e87621e48c3e3d6114b38724528a828e89c3edf Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Thu, 29 Sep 2022 16:22:48 +0200 Subject: [PATCH 01/16] Adding changelog entry --- changelog.d/7257.wip | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/7257.wip diff --git a/changelog.d/7257.wip b/changelog.d/7257.wip new file mode 100644 index 0000000000..c6f9aefbd8 --- /dev/null +++ b/changelog.d/7257.wip @@ -0,0 +1 @@ +[Device Management] Save "matrix_client_information" events on login/registration From 9877e90df60732be239179295b2eee002b6a4151 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Thu, 29 Sep 2022 17:42:13 +0200 Subject: [PATCH 02/16] Adding use cases to get and set the extra matrix client Info --- .../DefaultSessionAccountDataService.kt | 3 +- .../accountdata/UpdateUserAccountDataTask.kt | 1 + .../extended/GetMatrixClientInfoUseCase.kt | 40 +++++++++++++++++ .../extended/MatrixClientInfoContent.kt | 43 ++++++++++++++++++ .../extended/SessionExtendedInfoConstants.kt | 20 +++++++++ .../extended/SetMatrixClientInfoUseCase.kt | 40 +++++++++++++++++ .../extended/UpdateMatrixClientInfoUseCase.kt | 44 +++++++++++++++++++ 7 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SessionExtendedInfoConstants.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt index df9dcfb903..c81dac0882 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt @@ -64,9 +64,10 @@ internal class DefaultSessionAccountDataService @Inject constructor( return roomAccountDataDataSource.getLiveAccountDataEvents(null, types) } + // TODO add unit tests override suspend fun updateUserAccountData(type: String, content: Content) { val params = UpdateUserAccountDataTask.AnyParams(type = type, any = content) - awaitCallback { callback -> + awaitCallback { callback -> updateUserAccountDataTask.configureWith(params) { this.retryCount = 5 // TODO Need to refactor retrying out into a helper method. this.callback = callback diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt index ff0e960f0f..9e42191a50 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt @@ -112,6 +112,7 @@ internal class DefaultUpdateUserAccountDataTask @Inject constructor( private val globalErrorReceiver: GlobalErrorReceiver ) : UpdateUserAccountDataTask { + // TODO add unit tests override suspend fun execute(params: UpdateUserAccountDataTask.Params) { return executeRequest(globalErrorReceiver) { accountDataApi.setAccountData(userId, params.type, params.getData()) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt new file mode 100644 index 0000000000..a41931ed4a --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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 im.vector.app.features.settings.devices.v2.details.extended + +import MATRIX_CLIENT_INFO_KEY_PREFIX +import im.vector.app.core.di.ActiveSessionHolder +import javax.inject.Inject + +/** + * This use case retrieves the current account data event containing extended client info. + */ +class GetMatrixClientInfoUseCase @Inject constructor( + private val activeSessionHolder: ActiveSessionHolder, +) { + + // TODO add unit tests + fun execute(): MatrixClientInfoContent? { + return activeSessionHolder + .getSafeActiveSession() + ?.let { session -> + val type = MATRIX_CLIENT_INFO_KEY_PREFIX + session.sessionParams.deviceId + val content = session.accountDataService().getUserAccountDataEvent(type)?.content + MatrixClientInfoContent.fromJson(content) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt new file mode 100644 index 0000000000..814f7ef5bb --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 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 im.vector.app.features.settings.devices.v2.details.extended + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import com.squareup.moshi.Moshi + +@JsonClass(generateAdapter = true) +data class MatrixClientInfoContent( + // app name + @Json(name = "name") + val name: String? = null, + // app version + @Json(name = "version") + val version: String? = null, + // app url (optional, applicable only for web) + @Json(name = "url") + val url: String? = null, +) { + companion object { + fun fromJson(obj: Any?): MatrixClientInfoContent? { + return Moshi.Builder() + .build() + .adapter(MatrixClientInfoContent::class.java) + .fromJsonValue(obj) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SessionExtendedInfoConstants.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SessionExtendedInfoConstants.kt new file mode 100644 index 0000000000..b87ebc1ffc --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SessionExtendedInfoConstants.kt @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022 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. + */ + +/** + * Prefix for th key account data event which holds client info. + */ +const val MATRIX_CLIENT_INFO_KEY_PREFIX = "io.element.matrix_client_information." diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt new file mode 100644 index 0000000000..1e3837bc17 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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 im.vector.app.features.settings.devices.v2.details.extended + +import MATRIX_CLIENT_INFO_KEY_PREFIX +import im.vector.app.core.di.ActiveSessionHolder +import org.matrix.android.sdk.api.session.events.model.toContent +import javax.inject.Inject + +/** + * This use case sets the account data event containing extended client info. + */ +class SetMatrixClientInfoUseCase @Inject constructor( + private val activeSessionHolder: ActiveSessionHolder, +) { + + // TODO add unit tests + suspend fun execute(clientInfo: MatrixClientInfoContent): Result = runCatching { + activeSessionHolder.getSafeActiveSession() + ?.let { session -> + val type = MATRIX_CLIENT_INFO_KEY_PREFIX + session.sessionParams.deviceId + session.accountDataService() + .updateUserAccountData(type, clientInfo.toContent()) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt new file mode 100644 index 0000000000..4058332127 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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 im.vector.app.features.settings.devices.v2.details.extended + +import im.vector.app.core.resources.AppNameProvider +import im.vector.app.core.resources.BuildMeta +import javax.inject.Inject + +/** + * This use case updates if needed the account data event containing extended client info. + */ +class UpdateMatrixClientInfoUseCase @Inject constructor( + private val appNameProvider: AppNameProvider, + private val buildMeta: BuildMeta, + private val getMatrixClientInfoUseCase: GetMatrixClientInfoUseCase, + private val setMatrixClientInfoUseCase: SetMatrixClientInfoUseCase, +) { + + // TODO add unit tests + suspend fun execute(): Result = runCatching { + val clientInfo = MatrixClientInfoContent( + name = appNameProvider.getAppName(), + version = buildMeta.versionName + ) + val storedClientInfo = getMatrixClientInfoUseCase.execute() + if (clientInfo != storedClientInfo) { + setMatrixClientInfoUseCase.execute(clientInfo) + } + } +} From ccc3ac628a844932aa4e643124cf8d4986d32aa4 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Fri, 30 Sep 2022 16:31:23 +0200 Subject: [PATCH 03/16] Adding unit tests for the get client info use case --- .../extended/GetMatrixClientInfoUseCase.kt | 11 +-- .../extended/MatrixClientInfoContent.kt | 11 +-- .../extended/SetMatrixClientInfoUseCase.kt | 9 ++- .../extended/UpdateMatrixClientInfoUseCase.kt | 6 +- .../GetMatrixClientInfoUseCaseTest.kt | 78 +++++++++++++++++++ .../im/vector/app/test/fakes/FakeSession.kt | 2 + .../fakes/FakeSessionAccountDataService.kt | 30 +++++++ 7 files changed, 128 insertions(+), 19 deletions(-) create mode 100644 vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCaseTest.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeSessionAccountDataService.kt diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt index a41931ed4a..c248340786 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt @@ -18,23 +18,24 @@ package im.vector.app.features.settings.devices.v2.details.extended import MATRIX_CLIENT_INFO_KEY_PREFIX import im.vector.app.core.di.ActiveSessionHolder +import org.matrix.android.sdk.api.session.events.model.toModel import javax.inject.Inject /** - * This use case retrieves the current account data event containing extended client info. + * This use case retrieves the current account data event containing extended client info + * for a given deviceId. */ class GetMatrixClientInfoUseCase @Inject constructor( private val activeSessionHolder: ActiveSessionHolder, ) { - // TODO add unit tests - fun execute(): MatrixClientInfoContent? { + fun execute(deviceId: String): MatrixClientInfoContent? { return activeSessionHolder .getSafeActiveSession() ?.let { session -> - val type = MATRIX_CLIENT_INFO_KEY_PREFIX + session.sessionParams.deviceId + val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId val content = session.accountDataService().getUserAccountDataEvent(type)?.content - MatrixClientInfoContent.fromJson(content) + content.toModel() } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt index 814f7ef5bb..a2b7191bb7 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt @@ -31,13 +31,4 @@ data class MatrixClientInfoContent( // app url (optional, applicable only for web) @Json(name = "url") val url: String? = null, -) { - companion object { - fun fromJson(obj: Any?): MatrixClientInfoContent? { - return Moshi.Builder() - .build() - .adapter(MatrixClientInfoContent::class.java) - .fromJsonValue(obj) - } - } -} +) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt index 1e3837bc17..43426de56c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt @@ -32,9 +32,12 @@ class SetMatrixClientInfoUseCase @Inject constructor( suspend fun execute(clientInfo: MatrixClientInfoContent): Result = runCatching { activeSessionHolder.getSafeActiveSession() ?.let { session -> - val type = MATRIX_CLIENT_INFO_KEY_PREFIX + session.sessionParams.deviceId - session.accountDataService() - .updateUserAccountData(type, clientInfo.toContent()) + val deviceId = session.sessionParams.deviceId + if (deviceId != null) { + val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId + session.accountDataService() + .updateUserAccountData(type, clientInfo.toContent()) + } } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt index 4058332127..ca953ce5d2 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt @@ -16,6 +16,7 @@ package im.vector.app.features.settings.devices.v2.details.extended +import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.AppNameProvider import im.vector.app.core.resources.BuildMeta import javax.inject.Inject @@ -24,19 +25,22 @@ import javax.inject.Inject * This use case updates if needed the account data event containing extended client info. */ class UpdateMatrixClientInfoUseCase @Inject constructor( + private val activeSessionHolder: ActiveSessionHolder, private val appNameProvider: AppNameProvider, private val buildMeta: BuildMeta, private val getMatrixClientInfoUseCase: GetMatrixClientInfoUseCase, private val setMatrixClientInfoUseCase: SetMatrixClientInfoUseCase, ) { + // TODO call the use case after signin + on app startup // TODO add unit tests suspend fun execute(): Result = runCatching { val clientInfo = MatrixClientInfoContent( name = appNameProvider.getAppName(), version = buildMeta.versionName ) - val storedClientInfo = getMatrixClientInfoUseCase.execute() + val sessionId = activeSessionHolder.getActiveSession().sessionParams.deviceId + val storedClientInfo = sessionId?.let { getMatrixClientInfoUseCase.execute(it) } if (clientInfo != storedClientInfo) { setMatrixClientInfoUseCase.execute(clientInfo) } diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCaseTest.kt new file mode 100644 index 0000000000..4a90f90c13 --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCaseTest.kt @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022 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 im.vector.app.features.settings.devices.v2.details.extended + +import MATRIX_CLIENT_INFO_KEY_PREFIX +import im.vector.app.test.fakes.FakeActiveSessionHolder +import org.amshove.kluent.shouldBe +import org.amshove.kluent.shouldBeEqualTo +import org.junit.Test + +private const val A_DEVICE_ID = "device-id" +private const val A_CLIENT_NAME = "client-name" +private const val A_CLIENT_VERSION = "client-version" +private const val A_CLIENT_URL = "client-url" + +class GetMatrixClientInfoUseCaseTest { + + private val fakeActiveSessionHolder = FakeActiveSessionHolder() + + private val getMatrixClientInfoUseCase = GetMatrixClientInfoUseCase( + activeSessionHolder = fakeActiveSessionHolder.instance + ) + + @Test + fun `given a device id and existing content when getting the info then result should contain that info`() { + // Given + givenClientInfoContent(A_DEVICE_ID) + val expectedClientInfo = MatrixClientInfoContent( + name = A_CLIENT_NAME, + version = A_CLIENT_VERSION, + url = A_CLIENT_URL, + ) + + // When + val result = getMatrixClientInfoUseCase.execute(A_DEVICE_ID) + + // Then + result shouldBeEqualTo expectedClientInfo + } + + @Test + fun `given no active session when getting the info then result should be null`() { + // Given + fakeActiveSessionHolder.givenGetSafeActiveSessionReturns(null) + + // When + val result = getMatrixClientInfoUseCase.execute(A_DEVICE_ID) + + // Then + result shouldBe null + } + + private fun givenClientInfoContent(deviceId: String) { + val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId + val content = mapOf( + Pair("name", A_CLIENT_NAME), + Pair("version", A_CLIENT_VERSION), + Pair("url", A_CLIENT_URL), + ) + fakeActiveSessionHolder.fakeSession + .fakeSessionAccountDataService + .givenGetUserAccountDataEventReturns(type, content) + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt index bf437c123b..29b634eb0c 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt @@ -43,6 +43,7 @@ class FakeSession( val fakeRoomService: FakeRoomService = FakeRoomService(), val fakePushersService: FakePushersService = FakePushersService(), private val fakeEventService: FakeEventService = FakeEventService(), + val fakeSessionAccountDataService: FakeSessionAccountDataService = FakeSessionAccountDataService(), ) : Session by mockk(relaxed = true) { init { @@ -60,6 +61,7 @@ class FakeSession( override fun roomService() = fakeRoomService override fun eventService() = fakeEventService override fun pushersService() = fakePushersService + override fun accountDataService() = fakeSessionAccountDataService fun givenVectorStore(vectorSessionStore: VectorSessionStore) { coEvery { diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSessionAccountDataService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSessionAccountDataService.kt new file mode 100644 index 0000000000..5b9c918b64 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSessionAccountDataService.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 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 im.vector.app.test.fakes + +import io.mockk.every +import io.mockk.mockk +import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent +import org.matrix.android.sdk.api.session.events.model.Content + +class FakeSessionAccountDataService : SessionAccountDataService by mockk() { + + fun givenGetUserAccountDataEventReturns(type: String, content: Content) { + every { getUserAccountDataEvent(type) } returns UserAccountDataEvent(type, content) + } +} From 7d00908f11fb9c25b19f869bbb4341c0b1c75457 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Fri, 30 Sep 2022 17:41:01 +0200 Subject: [PATCH 04/16] Adding unit tests for the set client info use case --- .../extended/SetMatrixClientInfoUseCase.kt | 7 +- .../extended/UpdateMatrixClientInfoUseCase.kt | 6 +- .../SetMatrixClientInfoUseCaseTest.kt | 109 ++++++++++++++++++ .../im/vector/app/test/fakes/FakeSession.kt | 2 +- .../fakes/FakeSessionAccountDataService.kt | 16 +++ 5 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt index 43426de56c..ccc73e896b 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt @@ -28,15 +28,16 @@ class SetMatrixClientInfoUseCase @Inject constructor( private val activeSessionHolder: ActiveSessionHolder, ) { - // TODO add unit tests suspend fun execute(clientInfo: MatrixClientInfoContent): Result = runCatching { activeSessionHolder.getSafeActiveSession() ?.let { session -> - val deviceId = session.sessionParams.deviceId - if (deviceId != null) { + val deviceId = session.sessionParams.deviceId.orEmpty() + if (deviceId.isNotEmpty()) { val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId session.accountDataService() .updateUserAccountData(type, clientInfo.toContent()) + } else { + throw IllegalStateException("device id is empty") } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt index ca953ce5d2..f19503dcc5 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt @@ -39,8 +39,10 @@ class UpdateMatrixClientInfoUseCase @Inject constructor( name = appNameProvider.getAppName(), version = buildMeta.versionName ) - val sessionId = activeSessionHolder.getActiveSession().sessionParams.deviceId - val storedClientInfo = sessionId?.let { getMatrixClientInfoUseCase.execute(it) } + val deviceId = activeSessionHolder.getActiveSession().sessionParams.deviceId.orEmpty() + val storedClientInfo = deviceId + .takeUnless { it.isEmpty() } + ?.let { getMatrixClientInfoUseCase.execute(it) } if (clientInfo != storedClientInfo) { setMatrixClientInfoUseCase.execute(clientInfo) } diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt new file mode 100644 index 0000000000..9e04d6984e --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2022 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 im.vector.app.features.settings.devices.v2.details.extended + +import MATRIX_CLIENT_INFO_KEY_PREFIX +import im.vector.app.test.fakes.FakeActiveSessionHolder +import kotlinx.coroutines.test.runTest +import org.amshove.kluent.shouldBe +import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldBeInstanceOf +import org.junit.Test +import org.matrix.android.sdk.api.session.events.model.toContent + +private const val A_DEVICE_ID = "device-id" + +class SetMatrixClientInfoUseCaseTest { + + private val fakeActiveSessionHolder = FakeActiveSessionHolder() + + private val setMatrixClientInfoUseCase = SetMatrixClientInfoUseCase( + activeSessionHolder = fakeActiveSessionHolder.instance + ) + + @Test + fun `given client info and no error when setting the info then account data is correctly updated`() = runTest { + // Given + val type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID + val clientInfo = givenClientInfo() + val content = clientInfo.toContent() + fakeActiveSessionHolder.fakeSession + .givenSessionId(A_DEVICE_ID) + fakeActiveSessionHolder.fakeSession + .fakeSessionAccountDataService + .givenUpdateUserAccountDataEventSucceeds() + + // When + val result = setMatrixClientInfoUseCase.execute(clientInfo) + + // Then + result.isSuccess shouldBe true + fakeActiveSessionHolder.fakeSession + .fakeSessionAccountDataService + .verifyUpdateUserAccountDataEventSucceeds(type, content) + } + + @Test + fun `given client info and error during update when setting the info then result is failure`() = runTest { + // Given + val type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID + val clientInfo = givenClientInfo() + val content = clientInfo.toContent() + fakeActiveSessionHolder.fakeSession + .givenSessionId(A_DEVICE_ID) + val error = Exception() + fakeActiveSessionHolder.fakeSession + .fakeSessionAccountDataService + .givenUpdateUserAccountDataEventFailsWithError(error) + + // When + val result = setMatrixClientInfoUseCase.execute(clientInfo) + + // Then + result.isFailure shouldBe true + result.exceptionOrNull() shouldBeEqualTo error + fakeActiveSessionHolder.fakeSession + .fakeSessionAccountDataService + .verifyUpdateUserAccountDataEventSucceeds(type, content) + } + + @Test + fun `given client info and null device id when setting the info then result is failure`() = runTest { + // Given + val type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID + val clientInfo = givenClientInfo() + val content = clientInfo.toContent() + fakeActiveSessionHolder.fakeSession + .givenSessionId(null) + + // When + val result = setMatrixClientInfoUseCase.execute(clientInfo) + + // Then + result.isFailure shouldBe true + result.exceptionOrNull() shouldBeInstanceOf IllegalStateException::class + fakeActiveSessionHolder.fakeSession + .fakeSessionAccountDataService + .verifyUpdateUserAccountDataEventSucceeds(type, content, inverse = true) + } + + private fun givenClientInfo() = MatrixClientInfoContent( + name = "name", + version = "version", + url = null, + ) +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt index 29b634eb0c..9fc876e666 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt @@ -82,7 +82,7 @@ class FakeSession( every { this@FakeSession.sessionParams } returns sessionParams } - fun givenSessionId(sessionId: String): SessionParams { + fun givenSessionId(sessionId: String?): SessionParams { val sessionParams = mockk() every { sessionParams.deviceId } returns sessionId givenSessionParams(sessionParams) diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSessionAccountDataService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSessionAccountDataService.kt index 5b9c918b64..34a0d8edb3 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeSessionAccountDataService.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSessionAccountDataService.kt @@ -16,8 +16,12 @@ package im.vector.app.test.fakes +import io.mockk.coEvery +import io.mockk.coVerify import io.mockk.every +import io.mockk.just import io.mockk.mockk +import io.mockk.runs import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.events.model.Content @@ -27,4 +31,16 @@ class FakeSessionAccountDataService : SessionAccountDataService by mockk() { fun givenGetUserAccountDataEventReturns(type: String, content: Content) { every { getUserAccountDataEvent(type) } returns UserAccountDataEvent(type, content) } + + fun givenUpdateUserAccountDataEventSucceeds() { + coEvery { updateUserAccountData(any(), any()) } just runs + } + + fun givenUpdateUserAccountDataEventFailsWithError(error: Exception) { + coEvery { updateUserAccountData(any(), any()) } throws error + } + + fun verifyUpdateUserAccountDataEventSucceeds(type: String, content: Content, inverse: Boolean = false) { + coVerify(inverse = inverse) { updateUserAccountData(type, content) } + } } From ce70ab8f0fde247da94873a6cd27aeacde2f2e52 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 3 Oct 2022 10:27:42 +0200 Subject: [PATCH 05/16] Adding unit tests for update client info use case --- .../v2/details/extended/NoDeviceIdError.kt | 19 +++ .../extended/SetMatrixClientInfoUseCase.kt | 2 +- .../extended/UpdateMatrixClientInfoUseCase.kt | 13 +- .../SetMatrixClientInfoUseCaseTest.kt | 2 +- .../UpdateMatrixClientInfoUseCaseTest.kt | 149 ++++++++++++++++++ 5 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/NoDeviceIdError.kt create mode 100644 vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCaseTest.kt diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/NoDeviceIdError.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/NoDeviceIdError.kt new file mode 100644 index 0000000000..c021a6703a --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/NoDeviceIdError.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 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 im.vector.app.features.settings.devices.v2.details.extended + +class NoDeviceIdError : IllegalStateException("device id is empty") diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt index ccc73e896b..b71e447ace 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt @@ -37,7 +37,7 @@ class SetMatrixClientInfoUseCase @Inject constructor( session.accountDataService() .updateUserAccountData(type, clientInfo.toContent()) } else { - throw IllegalStateException("device id is empty") + throw NoDeviceIdError() } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt index f19503dcc5..c2c75e0409 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt @@ -33,18 +33,19 @@ class UpdateMatrixClientInfoUseCase @Inject constructor( ) { // TODO call the use case after signin + on app startup - // TODO add unit tests suspend fun execute(): Result = runCatching { val clientInfo = MatrixClientInfoContent( name = appNameProvider.getAppName(), version = buildMeta.versionName ) val deviceId = activeSessionHolder.getActiveSession().sessionParams.deviceId.orEmpty() - val storedClientInfo = deviceId - .takeUnless { it.isEmpty() } - ?.let { getMatrixClientInfoUseCase.execute(it) } - if (clientInfo != storedClientInfo) { - setMatrixClientInfoUseCase.execute(clientInfo) + if (deviceId.isNotEmpty()) { + val storedClientInfo = getMatrixClientInfoUseCase.execute(deviceId) + if (clientInfo != storedClientInfo) { + setMatrixClientInfoUseCase.execute(clientInfo) + } + } else { + throw NoDeviceIdError() } } } diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt index 9e04d6984e..c7c8f562b1 100644 --- a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt @@ -95,7 +95,7 @@ class SetMatrixClientInfoUseCaseTest { // Then result.isFailure shouldBe true - result.exceptionOrNull() shouldBeInstanceOf IllegalStateException::class + result.exceptionOrNull() shouldBeInstanceOf NoDeviceIdError::class fakeActiveSessionHolder.fakeSession .fakeSessionAccountDataService .verifyUpdateUserAccountDataEventSucceeds(type, content, inverse = true) diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCaseTest.kt new file mode 100644 index 0000000000..2151b15d27 --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCaseTest.kt @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2022 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 im.vector.app.features.settings.devices.v2.details.extended + +import im.vector.app.core.resources.BuildMeta +import im.vector.app.test.fakes.FakeActiveSessionHolder +import im.vector.app.test.fakes.FakeAppNameProvider +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.test.runTest +import org.amshove.kluent.shouldBe +import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldBeInstanceOf +import org.junit.Test + +private const val AN_APP_NAME_1 = "app_name_1" +private const val AN_APP_NAME_2 = "app_name_2" +private const val A_VERSION_NAME_1 = "version_name_1" +private const val A_VERSION_NAME_2 = "version_name_2" +private const val A_SESSION_ID = "session-id" + +class UpdateMatrixClientInfoUseCaseTest { + + private val fakeActiveSessionHolder = FakeActiveSessionHolder() + private val fakeAppNameProvider = FakeAppNameProvider() + private val fakeBuildMeta = mockk() + private val getMatrixClientInfoUseCase = mockk() + private val setMatrixClientInfoUseCase = mockk() + + private val updateMatrixClientInfoUseCase = UpdateMatrixClientInfoUseCase( + activeSessionHolder = fakeActiveSessionHolder.instance, + appNameProvider = fakeAppNameProvider, + buildMeta = fakeBuildMeta, + getMatrixClientInfoUseCase = getMatrixClientInfoUseCase, + setMatrixClientInfoUseCase = setMatrixClientInfoUseCase, + ) + + @Test + fun `given current client info is different than the stored one when trying to update then new client info is set and result is success`() = runTest { + // Given + givenCurrentAppName(AN_APP_NAME_1) + givenCurrentVersionName(A_VERSION_NAME_1) + givenStoredClientInfo(AN_APP_NAME_2, A_VERSION_NAME_2) + givenSetClientInfoSucceeds() + val expectedClientInfoToSet = MatrixClientInfoContent( + name = AN_APP_NAME_1, + version = A_VERSION_NAME_1, + ) + + // When + val result = updateMatrixClientInfoUseCase.execute() + + // Then + result.isSuccess shouldBe true + coVerify { setMatrixClientInfoUseCase.execute(match { it == expectedClientInfoToSet }) } + } + + @Test + fun `given current client info is equal to the stored one when trying to update then nothing is done and result is success`() = runTest { + // Given + givenCurrentAppName(AN_APP_NAME_1) + givenCurrentVersionName(A_VERSION_NAME_1) + givenStoredClientInfo(AN_APP_NAME_1, A_VERSION_NAME_1) + + // When + val result = updateMatrixClientInfoUseCase.execute() + + // Then + result.isSuccess shouldBe true + coVerify(inverse = true) { setMatrixClientInfoUseCase.execute(any()) } + } + + @Test + fun `given error during setting new client info when trying to update then result is failure`() = runTest { + // Given + givenCurrentAppName(AN_APP_NAME_1) + givenCurrentVersionName(A_VERSION_NAME_1) + givenStoredClientInfo(AN_APP_NAME_2, A_VERSION_NAME_2) + val error = Exception() + givenSetClientInfoFailsWithError(error) + val expectedClientInfoToSet = MatrixClientInfoContent( + name = AN_APP_NAME_1, + version = A_VERSION_NAME_1, + ) + + // When + val result = updateMatrixClientInfoUseCase.execute() + + // Then + result.isFailure shouldBe true + result.exceptionOrNull() shouldBeEqualTo error + coVerify { setMatrixClientInfoUseCase.execute(match { it == expectedClientInfoToSet }) } + } + + @Test + fun `given no session id for current session when trying to update then result is failure`() = runTest { + // Given + givenCurrentAppName(AN_APP_NAME_1) + givenCurrentVersionName(A_VERSION_NAME_1) + fakeActiveSessionHolder.fakeSession.givenSessionId(null) + + // When + val result = updateMatrixClientInfoUseCase.execute() + + // Then + result.isFailure shouldBe true + result.exceptionOrNull() shouldBeInstanceOf NoDeviceIdError::class + } + + private fun givenCurrentAppName(appName: String) { + fakeAppNameProvider.givenAppName(appName) + } + + private fun givenCurrentVersionName(versionName: String) { + every { fakeBuildMeta.versionName } returns versionName + } + + private fun givenStoredClientInfo(appName: String, versionName: String) { + fakeActiveSessionHolder.fakeSession.givenSessionId(A_SESSION_ID) + every { getMatrixClientInfoUseCase.execute(A_SESSION_ID) } returns MatrixClientInfoContent( + name = appName, + version = versionName, + ) + } + + private fun givenSetClientInfoSucceeds() { + coEvery { setMatrixClientInfoUseCase.execute(any()) } returns Result.success(Unit) + } + + private fun givenSetClientInfoFailsWithError(error: Exception) { + coEvery { setMatrixClientInfoUseCase.execute(any()) } throws error + } +} From 1e6fb99e3c5895c621c860dc3086ff6134a10036 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 3 Oct 2022 14:49:37 +0200 Subject: [PATCH 06/16] Introducing a use case to configure and start a Session --- .../vector/app/core/di/ActiveSessionHolder.kt | 5 ++- .../im/vector/app/core/extensions/Session.kt | 11 ----- .../ConfigureAndStartSessionUseCase.kt | 44 +++++++++++++++++++ .../app/features/login/LoginViewModel.kt | 7 +-- .../onboarding/OnboardingViewModel.kt | 5 ++- .../onboarding/OnboardingViewModelTest.kt | 6 ++- .../im/vector/app/test/fakes/FakeSession.kt | 6 +-- 7 files changed, 62 insertions(+), 22 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt diff --git a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt index 3f0507305a..c7d621ac0a 100644 --- a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt +++ b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt @@ -19,10 +19,10 @@ package im.vector.app.core.di import android.content.Context import arrow.core.Option import im.vector.app.ActiveSessionDataSource -import im.vector.app.core.extensions.configureAndStart import im.vector.app.core.extensions.startSyncing import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.services.GuardServiceStarter +import im.vector.app.core.session.ConfigureAndStartSessionUseCase import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.crypto.keysrequest.KeyRequestHandler import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler @@ -50,6 +50,7 @@ class ActiveSessionHolder @Inject constructor( private val sessionInitializer: SessionInitializer, private val applicationContext: Context, private val authenticationService: AuthenticationService, + private val configureAndStartSessionUseCase: ConfigureAndStartSessionUseCase, ) { private var activeSessionReference: AtomicReference = AtomicReference() @@ -109,7 +110,7 @@ class ActiveSessionHolder @Inject constructor( } ?: sessionInitializer.tryInitialize(readCurrentSession = { activeSessionReference.get() }) { session -> setActiveSession(session) - session.configureAndStart(applicationContext, startSyncing = startSync) + configureAndStartSessionUseCase.execute(session, startSyncing = startSync) } } diff --git a/vector/src/main/java/im/vector/app/core/extensions/Session.kt b/vector/src/main/java/im/vector/app/core/extensions/Session.kt index cb1d46efce..9340722ce1 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Session.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Session.kt @@ -27,17 +27,6 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState import org.matrix.android.sdk.api.session.sync.FilterService import timber.log.Timber -fun Session.configureAndStart(context: Context, startSyncing: Boolean = true) { - Timber.i("Configure and start session for $myUserId. startSyncing: $startSyncing") - open() - filterService().setFilter(FilterService.FilterPreset.ElementFilter) - if (startSyncing) { - startSyncing(context) - } - pushersService().refreshPushers() - context.singletonEntryPoint().webRtcCallManager().checkForProtocolsSupportIfNeeded() -} - fun Session.startSyncing(context: Context) { val applicationContext = context.applicationContext if (!syncService().hasAlreadySynced()) { diff --git a/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt b/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt new file mode 100644 index 0000000000..3e47eb81a5 --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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 im.vector.app.core.session + +import android.content.Context +import dagger.hilt.android.qualifiers.ApplicationContext +import im.vector.app.core.extensions.startSyncing +import im.vector.app.features.call.webrtc.WebRtcCallManager +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.sync.FilterService +import timber.log.Timber +import javax.inject.Inject + +class ConfigureAndStartSessionUseCase @Inject constructor( + @ApplicationContext private val context: Context, + private val webRtcCallManager: WebRtcCallManager, +) { + + // TODO add unit tests + fun execute(session: Session, startSyncing: Boolean = true) { + Timber.i("Configure and start session for ${session.myUserId}. startSyncing: $startSyncing") + session.open() + session.filterService().setFilter(FilterService.FilterPreset.ElementFilter) + if (startSyncing) { + session.startSyncing(context) + } + session.pushersService().refreshPushers() + webRtcCallManager.checkForProtocolsSupportIfNeeded() + } +} diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt index 79d06a0864..b46f22c58f 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt @@ -30,9 +30,9 @@ import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory -import im.vector.app.core.extensions.configureAndStart import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider +import im.vector.app.core.session.ConfigureAndStartSessionUseCase import im.vector.app.core.utils.ensureTrailingSlash import kotlinx.coroutines.Job import kotlinx.coroutines.launch @@ -64,7 +64,8 @@ class LoginViewModel @AssistedInject constructor( private val homeServerConnectionConfigFactory: HomeServerConnectionConfigFactory, private val reAuthHelper: ReAuthHelper, private val stringProvider: StringProvider, - private val homeServerHistoryService: HomeServerHistoryService + private val homeServerHistoryService: HomeServerHistoryService, + private val configureAndStartSessionUseCase: ConfigureAndStartSessionUseCase, ) : VectorViewModel(initialState) { @AssistedFactory @@ -732,7 +733,7 @@ class LoginViewModel @AssistedInject constructor( activeSessionHolder.setActiveSession(session) authenticationService.reset() - session.configureAndStart(applicationContext) + configureAndStartSessionUseCase.execute(session) setState { copy( asyncLoginAction = Success(Unit) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 4f8a77f25d..9bb52fb1a5 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -26,13 +26,13 @@ import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.extensions.cancelCurrentOnSet -import im.vector.app.core.extensions.configureAndStart import im.vector.app.core.extensions.inferNoConnectivity import im.vector.app.core.extensions.isMatrixId import im.vector.app.core.extensions.toReducedUrl import im.vector.app.core.extensions.vectorStore import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider +import im.vector.app.core.session.ConfigureAndStartSessionUseCase import im.vector.app.core.utils.ensureProtocol import im.vector.app.core.utils.ensureTrailingSlash import im.vector.app.features.VectorFeatures @@ -91,6 +91,7 @@ class OnboardingViewModel @AssistedInject constructor( private val vectorOverrides: VectorOverrides, private val registrationActionHandler: RegistrationActionHandler, private val sdkIntProvider: BuildVersionSdkIntProvider, + private val configureAndStartSessionUseCase: ConfigureAndStartSessionUseCase, ) : VectorViewModel(initialState) { @AssistedFactory @@ -616,7 +617,7 @@ class OnboardingViewModel @AssistedInject constructor( activeSessionHolder.setActiveSession(session) authenticationService.reset() - session.configureAndStart(applicationContext) + configureAndStartSessionUseCase.execute(session) when (authenticationDescription) { is AuthenticationDescription.Register -> { diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index c3f6b86cb4..82adc70fe3 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -20,6 +20,7 @@ import android.net.Uri import android.os.Build import com.airbnb.mvrx.test.MavericksTestRule import im.vector.app.R +import im.vector.app.core.session.ConfigureAndStartSessionUseCase import im.vector.app.features.login.LoginConfig import im.vector.app.features.login.LoginMode import im.vector.app.features.login.ReAuthHelper @@ -50,6 +51,7 @@ import im.vector.app.test.fixtures.a401ServerError import im.vector.app.test.fixtures.aHomeServerCapabilities import im.vector.app.test.fixtures.anUnrecognisedCertificateError import im.vector.app.test.test +import io.mockk.mockk import kotlinx.coroutines.test.runTest import org.amshove.kluent.shouldBeEqualTo import org.junit.Before @@ -111,6 +113,7 @@ class OnboardingViewModelTest { private val fakeStartAuthenticationFlowUseCase = FakeStartAuthenticationFlowUseCase() private val fakeHomeServerHistoryService = FakeHomeServerHistoryService() private val fakeLoginWizard = FakeLoginWizard() + private val fakeConfigureAndStartSessionUseCase = mockk() private var initialState = OnboardingViewState() private lateinit var viewModel: OnboardingViewModel @@ -1093,6 +1096,7 @@ class OnboardingViewModelTest { FakeVectorOverrides(), fakeRegistrationActionHandler.instance, TestBuildVersionSdkIntProvider().also { it.value = Build.VERSION_CODES.O }, + fakeConfigureAndStartSessionUseCase, ).also { viewModel = it initialState = state @@ -1132,7 +1136,7 @@ class OnboardingViewModelTest { private fun givenInitialisesSession(session: Session) { fakeActiveSessionHolder.expectSetsActiveSession(session) fakeAuthenticationService.expectReset() - fakeSession.expectStartsSyncing() + fakeSession.expectStartsSyncing(fakeConfigureAndStartSessionUseCase) } private fun givenRegistrationResultFor(action: RegisterAction, result: RegistrationActionHandler.Result) { diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt index 9fc876e666..f4b17ea750 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt @@ -16,9 +16,9 @@ package im.vector.app.test.fakes -import im.vector.app.core.extensions.configureAndStart import im.vector.app.core.extensions.startSyncing import im.vector.app.core.extensions.vectorStore +import im.vector.app.core.session.ConfigureAndStartSessionUseCase import im.vector.app.features.session.VectorSessionStore import im.vector.app.test.testCoroutineDispatchers import io.mockk.coEvery @@ -71,9 +71,9 @@ class FakeSession( } } - fun expectStartsSyncing() { + fun expectStartsSyncing(configureAndStartSessionUseCase: ConfigureAndStartSessionUseCase) { coJustRun { - this@FakeSession.configureAndStart(any(), startSyncing = true) + configureAndStartSessionUseCase.execute(this@FakeSession, startSyncing = true) this@FakeSession.startSyncing(any()) } } From 0c6d49856c80e5467c3421ea8302baec09300e6f Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 3 Oct 2022 14:55:11 +0200 Subject: [PATCH 07/16] Moving matrix client info related component to core package --- .../session/clientinfo}/GetMatrixClientInfoUseCase.kt | 3 +-- .../session/clientinfo}/MatrixClientInfoContent.kt | 3 +-- .../extended => core/session/clientinfo}/NoDeviceIdError.kt | 2 +- .../session/clientinfo}/SessionExtendedInfoConstants.kt | 4 +++- .../session/clientinfo}/SetMatrixClientInfoUseCase.kt | 3 +-- .../session/clientinfo}/UpdateMatrixClientInfoUseCase.kt | 3 +-- .../session/clientinfo}/GetMatrixClientInfoUseCaseTest.kt | 3 +-- .../session/clientinfo}/SetMatrixClientInfoUseCaseTest.kt | 3 +-- .../session/clientinfo}/UpdateMatrixClientInfoUseCaseTest.kt | 2 +- 9 files changed, 11 insertions(+), 15 deletions(-) rename vector/src/main/java/im/vector/app/{features/settings/devices/v2/details/extended => core/session/clientinfo}/GetMatrixClientInfoUseCase.kt (93%) rename vector/src/main/java/im/vector/app/{features/settings/devices/v2/details/extended => core/session/clientinfo}/MatrixClientInfoContent.kt (91%) rename vector/src/main/java/im/vector/app/{features/settings/devices/v2/details/extended => core/session/clientinfo}/NoDeviceIdError.kt (90%) rename vector/src/main/java/im/vector/app/{features/settings/devices/v2/details/extended => core/session/clientinfo}/SessionExtendedInfoConstants.kt (86%) rename vector/src/main/java/im/vector/app/{features/settings/devices/v2/details/extended => core/session/clientinfo}/SetMatrixClientInfoUseCase.kt (93%) rename vector/src/main/java/im/vector/app/{features/settings/devices/v2/details/extended => core/session/clientinfo}/UpdateMatrixClientInfoUseCase.kt (93%) rename vector/src/test/java/im/vector/app/{features/settings/devices/v2/details/extended => core/session/clientinfo}/GetMatrixClientInfoUseCaseTest.kt (96%) rename vector/src/test/java/im/vector/app/{features/settings/devices/v2/details/extended => core/session/clientinfo}/SetMatrixClientInfoUseCaseTest.kt (97%) rename vector/src/test/java/im/vector/app/{features/settings/devices/v2/details/extended => core/session/clientinfo}/UpdateMatrixClientInfoUseCaseTest.kt (98%) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCase.kt similarity index 93% rename from vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt rename to vector/src/main/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCase.kt index c248340786..270457504c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCase.kt @@ -14,9 +14,8 @@ * limitations under the License. */ -package im.vector.app.features.settings.devices.v2.details.extended +package im.vector.app.core.session.clientinfo -import MATRIX_CLIENT_INFO_KEY_PREFIX import im.vector.app.core.di.ActiveSessionHolder import org.matrix.android.sdk.api.session.events.model.toModel import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/MatrixClientInfoContent.kt similarity index 91% rename from vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt rename to vector/src/main/java/im/vector/app/core/session/clientinfo/MatrixClientInfoContent.kt index a2b7191bb7..aacee6edef 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/MatrixClientInfoContent.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/MatrixClientInfoContent.kt @@ -14,11 +14,10 @@ * limitations under the License. */ -package im.vector.app.features.settings.devices.v2.details.extended +package im.vector.app.core.session.clientinfo import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import com.squareup.moshi.Moshi @JsonClass(generateAdapter = true) data class MatrixClientInfoContent( diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/NoDeviceIdError.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/NoDeviceIdError.kt similarity index 90% rename from vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/NoDeviceIdError.kt rename to vector/src/main/java/im/vector/app/core/session/clientinfo/NoDeviceIdError.kt index c021a6703a..c2b4445205 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/NoDeviceIdError.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/NoDeviceIdError.kt @@ -14,6 +14,6 @@ * limitations under the License. */ -package im.vector.app.features.settings.devices.v2.details.extended +package im.vector.app.core.session.clientinfo class NoDeviceIdError : IllegalStateException("device id is empty") diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SessionExtendedInfoConstants.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/SessionExtendedInfoConstants.kt similarity index 86% rename from vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SessionExtendedInfoConstants.kt rename to vector/src/main/java/im/vector/app/core/session/clientinfo/SessionExtendedInfoConstants.kt index b87ebc1ffc..80f69df1f8 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SessionExtendedInfoConstants.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/SessionExtendedInfoConstants.kt @@ -14,7 +14,9 @@ * limitations under the License. */ +package im.vector.app.core.session.clientinfo + /** - * Prefix for th key account data event which holds client info. + * Prefix for the key account data event which holds client info. */ const val MATRIX_CLIENT_INFO_KEY_PREFIX = "io.element.matrix_client_information." diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCase.kt similarity index 93% rename from vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt rename to vector/src/main/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCase.kt index b71e447ace..677d589dec 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCase.kt @@ -14,9 +14,8 @@ * limitations under the License. */ -package im.vector.app.features.settings.devices.v2.details.extended +package im.vector.app.core.session.clientinfo -import MATRIX_CLIENT_INFO_KEY_PREFIX import im.vector.app.core.di.ActiveSessionHolder import org.matrix.android.sdk.api.session.events.model.toContent import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt similarity index 93% rename from vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt rename to vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt index c2c75e0409..d4d35db4bb 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package im.vector.app.features.settings.devices.v2.details.extended +package im.vector.app.core.session.clientinfo import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.AppNameProvider @@ -32,7 +32,6 @@ class UpdateMatrixClientInfoUseCase @Inject constructor( private val setMatrixClientInfoUseCase: SetMatrixClientInfoUseCase, ) { - // TODO call the use case after signin + on app startup suspend fun execute(): Result = runCatching { val clientInfo = MatrixClientInfoContent( name = appNameProvider.getAppName(), diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt similarity index 96% rename from vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCaseTest.kt rename to vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt index 4a90f90c13..11af91c0f6 100644 --- a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/GetMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt @@ -14,9 +14,8 @@ * limitations under the License. */ -package im.vector.app.features.settings.devices.v2.details.extended +package im.vector.app.core.session.clientinfo -import MATRIX_CLIENT_INFO_KEY_PREFIX import im.vector.app.test.fakes.FakeActiveSessionHolder import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBeEqualTo diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCaseTest.kt similarity index 97% rename from vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt rename to vector/src/test/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCaseTest.kt index c7c8f562b1..f06b3a0951 100644 --- a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/SetMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCaseTest.kt @@ -14,9 +14,8 @@ * limitations under the License. */ -package im.vector.app.features.settings.devices.v2.details.extended +package im.vector.app.core.session.clientinfo -import MATRIX_CLIENT_INFO_KEY_PREFIX import im.vector.app.test.fakes.FakeActiveSessionHolder import kotlinx.coroutines.test.runTest import org.amshove.kluent.shouldBe diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt similarity index 98% rename from vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCaseTest.kt rename to vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt index 2151b15d27..4380d61520 100644 --- a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/extended/UpdateMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package im.vector.app.features.settings.devices.v2.details.extended +package im.vector.app.core.session.clientinfo import im.vector.app.core.resources.BuildMeta import im.vector.app.test.fakes.FakeActiveSessionHolder From c0e9d5124c9c9d32b217d51d32d0f494bba7adb5 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 3 Oct 2022 15:41:57 +0200 Subject: [PATCH 08/16] Update the Matrix client info when configuring the Session --- .../ConfigureAndStartSessionUseCase.kt | 3 ++ .../clientinfo/GetMatrixClientInfoUseCase.kt | 18 ++++------ .../clientinfo/SetMatrixClientInfoUseCase.kt | 27 ++++++-------- .../UpdateMatrixClientInfoUseCase.kt | 36 +++++++++++-------- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt b/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt index 3e47eb81a5..504ed830df 100644 --- a/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt @@ -19,6 +19,7 @@ package im.vector.app.core.session import android.content.Context import dagger.hilt.android.qualifiers.ApplicationContext import im.vector.app.core.extensions.startSyncing +import im.vector.app.core.session.clientinfo.UpdateMatrixClientInfoUseCase import im.vector.app.features.call.webrtc.WebRtcCallManager import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.sync.FilterService @@ -28,6 +29,7 @@ import javax.inject.Inject class ConfigureAndStartSessionUseCase @Inject constructor( @ApplicationContext private val context: Context, private val webRtcCallManager: WebRtcCallManager, + private val updateMatrixClientInfoUseCase: UpdateMatrixClientInfoUseCase, ) { // TODO add unit tests @@ -40,5 +42,6 @@ class ConfigureAndStartSessionUseCase @Inject constructor( } session.pushersService().refreshPushers() webRtcCallManager.checkForProtocolsSupportIfNeeded() + updateMatrixClientInfoUseCase.execute(session) } } diff --git a/vector/src/main/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCase.kt index 270457504c..18b731ea09 100644 --- a/vector/src/main/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCase.kt @@ -16,7 +16,7 @@ package im.vector.app.core.session.clientinfo -import im.vector.app.core.di.ActiveSessionHolder +import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.toModel import javax.inject.Inject @@ -24,17 +24,11 @@ import javax.inject.Inject * This use case retrieves the current account data event containing extended client info * for a given deviceId. */ -class GetMatrixClientInfoUseCase @Inject constructor( - private val activeSessionHolder: ActiveSessionHolder, -) { +class GetMatrixClientInfoUseCase @Inject constructor() { - fun execute(deviceId: String): MatrixClientInfoContent? { - return activeSessionHolder - .getSafeActiveSession() - ?.let { session -> - val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId - val content = session.accountDataService().getUserAccountDataEvent(type)?.content - content.toModel() - } + fun execute(session: Session, deviceId: String): MatrixClientInfoContent? { + val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId + val content = session.accountDataService().getUserAccountDataEvent(type)?.content + return content.toModel() } } diff --git a/vector/src/main/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCase.kt index 677d589dec..5ec428eed0 100644 --- a/vector/src/main/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCase.kt @@ -16,28 +16,23 @@ package im.vector.app.core.session.clientinfo -import im.vector.app.core.di.ActiveSessionHolder +import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.toContent import javax.inject.Inject /** * This use case sets the account data event containing extended client info. */ -class SetMatrixClientInfoUseCase @Inject constructor( - private val activeSessionHolder: ActiveSessionHolder, -) { +class SetMatrixClientInfoUseCase @Inject constructor() { - suspend fun execute(clientInfo: MatrixClientInfoContent): Result = runCatching { - activeSessionHolder.getSafeActiveSession() - ?.let { session -> - val deviceId = session.sessionParams.deviceId.orEmpty() - if (deviceId.isNotEmpty()) { - val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId - session.accountDataService() - .updateUserAccountData(type, clientInfo.toContent()) - } else { - throw NoDeviceIdError() - } - } + suspend fun execute(session: Session, clientInfo: MatrixClientInfoContent): Result = runCatching { + val deviceId = session.sessionParams.deviceId.orEmpty() + if (deviceId.isNotEmpty()) { + val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId + session.accountDataService() + .updateUserAccountData(type, clientInfo.toContent()) + } else { + throw NoDeviceIdError() + } } } diff --git a/vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt index d4d35db4bb..a5cd2bb948 100644 --- a/vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt @@ -16,35 +16,43 @@ package im.vector.app.core.session.clientinfo -import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.AppNameProvider import im.vector.app.core.resources.BuildMeta +import im.vector.app.features.session.coroutineScope +import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.session.Session +import timber.log.Timber import javax.inject.Inject /** * This use case updates if needed the account data event containing extended client info. */ class UpdateMatrixClientInfoUseCase @Inject constructor( - private val activeSessionHolder: ActiveSessionHolder, private val appNameProvider: AppNameProvider, private val buildMeta: BuildMeta, private val getMatrixClientInfoUseCase: GetMatrixClientInfoUseCase, private val setMatrixClientInfoUseCase: SetMatrixClientInfoUseCase, ) { - suspend fun execute(): Result = runCatching { - val clientInfo = MatrixClientInfoContent( - name = appNameProvider.getAppName(), - version = buildMeta.versionName - ) - val deviceId = activeSessionHolder.getActiveSession().sessionParams.deviceId.orEmpty() - if (deviceId.isNotEmpty()) { - val storedClientInfo = getMatrixClientInfoUseCase.execute(deviceId) - if (clientInfo != storedClientInfo) { - setMatrixClientInfoUseCase.execute(clientInfo) + fun execute(session: Session) { + session.coroutineScope.launch { + runCatching { + val clientInfo = MatrixClientInfoContent( + name = appNameProvider.getAppName(), + version = buildMeta.versionName + ) + val deviceId = session.sessionParams.deviceId.orEmpty() + if (deviceId.isNotEmpty()) { + val storedClientInfo = getMatrixClientInfoUseCase.execute(session, deviceId) + Timber.d("storedClientInfo=$storedClientInfo, current client info=$clientInfo") + if (clientInfo != storedClientInfo) { + Timber.d("client info need to be updated") + setMatrixClientInfoUseCase.execute(session, clientInfo) + } + } else { + throw NoDeviceIdError() + } } - } else { - throw NoDeviceIdError() } } } From 34e37ea6083581791088e3ae268fd5501467612e Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 3 Oct 2022 16:02:56 +0200 Subject: [PATCH 09/16] Updating unit tests --- .../GetMatrixClientInfoUseCaseTest.kt | 24 ++---- .../SetMatrixClientInfoUseCaseTest.kt | 30 ++++--- .../UpdateMatrixClientInfoUseCaseTest.kt | 82 ++++++++----------- 3 files changed, 53 insertions(+), 83 deletions(-) diff --git a/vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt index 11af91c0f6..800dedfb3a 100644 --- a/vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt @@ -16,7 +16,7 @@ package im.vector.app.core.session.clientinfo -import im.vector.app.test.fakes.FakeActiveSessionHolder +import im.vector.app.test.fakes.FakeSession import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBeEqualTo import org.junit.Test @@ -28,11 +28,9 @@ private const val A_CLIENT_URL = "client-url" class GetMatrixClientInfoUseCaseTest { - private val fakeActiveSessionHolder = FakeActiveSessionHolder() + private val fakeSession = FakeSession() - private val getMatrixClientInfoUseCase = GetMatrixClientInfoUseCase( - activeSessionHolder = fakeActiveSessionHolder.instance - ) + private val getMatrixClientInfoUseCase = GetMatrixClientInfoUseCase() @Test fun `given a device id and existing content when getting the info then result should contain that info`() { @@ -45,24 +43,12 @@ class GetMatrixClientInfoUseCaseTest { ) // When - val result = getMatrixClientInfoUseCase.execute(A_DEVICE_ID) + val result = getMatrixClientInfoUseCase.execute(fakeSession, A_DEVICE_ID) // Then result shouldBeEqualTo expectedClientInfo } - @Test - fun `given no active session when getting the info then result should be null`() { - // Given - fakeActiveSessionHolder.givenGetSafeActiveSessionReturns(null) - - // When - val result = getMatrixClientInfoUseCase.execute(A_DEVICE_ID) - - // Then - result shouldBe null - } - private fun givenClientInfoContent(deviceId: String) { val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId val content = mapOf( @@ -70,7 +56,7 @@ class GetMatrixClientInfoUseCaseTest { Pair("version", A_CLIENT_VERSION), Pair("url", A_CLIENT_URL), ) - fakeActiveSessionHolder.fakeSession + fakeSession .fakeSessionAccountDataService .givenGetUserAccountDataEventReturns(type, content) } diff --git a/vector/src/test/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCaseTest.kt index f06b3a0951..4345de45c4 100644 --- a/vector/src/test/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/SetMatrixClientInfoUseCaseTest.kt @@ -16,7 +16,7 @@ package im.vector.app.core.session.clientinfo -import im.vector.app.test.fakes.FakeActiveSessionHolder +import im.vector.app.test.fakes.FakeSession import kotlinx.coroutines.test.runTest import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBeEqualTo @@ -28,11 +28,9 @@ private const val A_DEVICE_ID = "device-id" class SetMatrixClientInfoUseCaseTest { - private val fakeActiveSessionHolder = FakeActiveSessionHolder() + private val fakeSession = FakeSession() - private val setMatrixClientInfoUseCase = SetMatrixClientInfoUseCase( - activeSessionHolder = fakeActiveSessionHolder.instance - ) + private val setMatrixClientInfoUseCase = SetMatrixClientInfoUseCase() @Test fun `given client info and no error when setting the info then account data is correctly updated`() = runTest { @@ -40,18 +38,18 @@ class SetMatrixClientInfoUseCaseTest { val type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID val clientInfo = givenClientInfo() val content = clientInfo.toContent() - fakeActiveSessionHolder.fakeSession + fakeSession .givenSessionId(A_DEVICE_ID) - fakeActiveSessionHolder.fakeSession + fakeSession .fakeSessionAccountDataService .givenUpdateUserAccountDataEventSucceeds() // When - val result = setMatrixClientInfoUseCase.execute(clientInfo) + val result = setMatrixClientInfoUseCase.execute(fakeSession, clientInfo) // Then result.isSuccess shouldBe true - fakeActiveSessionHolder.fakeSession + fakeSession .fakeSessionAccountDataService .verifyUpdateUserAccountDataEventSucceeds(type, content) } @@ -62,20 +60,20 @@ class SetMatrixClientInfoUseCaseTest { val type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID val clientInfo = givenClientInfo() val content = clientInfo.toContent() - fakeActiveSessionHolder.fakeSession + fakeSession .givenSessionId(A_DEVICE_ID) val error = Exception() - fakeActiveSessionHolder.fakeSession + fakeSession .fakeSessionAccountDataService .givenUpdateUserAccountDataEventFailsWithError(error) // When - val result = setMatrixClientInfoUseCase.execute(clientInfo) + val result = setMatrixClientInfoUseCase.execute(fakeSession, clientInfo) // Then result.isFailure shouldBe true result.exceptionOrNull() shouldBeEqualTo error - fakeActiveSessionHolder.fakeSession + fakeSession .fakeSessionAccountDataService .verifyUpdateUserAccountDataEventSucceeds(type, content) } @@ -86,16 +84,16 @@ class SetMatrixClientInfoUseCaseTest { val type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID val clientInfo = givenClientInfo() val content = clientInfo.toContent() - fakeActiveSessionHolder.fakeSession + fakeSession .givenSessionId(null) // When - val result = setMatrixClientInfoUseCase.execute(clientInfo) + val result = setMatrixClientInfoUseCase.execute(fakeSession, clientInfo) // Then result.isFailure shouldBe true result.exceptionOrNull() shouldBeInstanceOf NoDeviceIdError::class - fakeActiveSessionHolder.fakeSession + fakeSession .fakeSessionAccountDataService .verifyUpdateUserAccountDataEventSucceeds(type, content, inverse = true) } diff --git a/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt index 4380d61520..f31eaafb8c 100644 --- a/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt @@ -16,17 +16,23 @@ package im.vector.app.core.session.clientinfo +import android.os.SystemClock import im.vector.app.core.resources.BuildMeta -import im.vector.app.test.fakes.FakeActiveSessionHolder import im.vector.app.test.fakes.FakeAppNameProvider +import im.vector.app.test.fakes.FakeSession +import im.vector.app.test.testDispatcher import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.unmockkAll +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.runTest -import org.amshove.kluent.shouldBe -import org.amshove.kluent.shouldBeEqualTo -import org.amshove.kluent.shouldBeInstanceOf +import kotlinx.coroutines.test.setMain +import org.junit.After +import org.junit.Before import org.junit.Test private const val AN_APP_NAME_1 = "app_name_1" @@ -37,22 +43,31 @@ private const val A_SESSION_ID = "session-id" class UpdateMatrixClientInfoUseCaseTest { - private val fakeActiveSessionHolder = FakeActiveSessionHolder() + private val fakeSession = FakeSession() private val fakeAppNameProvider = FakeAppNameProvider() private val fakeBuildMeta = mockk() private val getMatrixClientInfoUseCase = mockk() private val setMatrixClientInfoUseCase = mockk() private val updateMatrixClientInfoUseCase = UpdateMatrixClientInfoUseCase( - activeSessionHolder = fakeActiveSessionHolder.instance, appNameProvider = fakeAppNameProvider, buildMeta = fakeBuildMeta, getMatrixClientInfoUseCase = getMatrixClientInfoUseCase, setMatrixClientInfoUseCase = setMatrixClientInfoUseCase, ) + @Before + fun setup() { + Dispatchers.setMain(testDispatcher) + } + + @After + fun tearDown() { + Dispatchers.resetMain() + } + @Test - fun `given current client info is different than the stored one when trying to update then new client info is set and result is success`() = runTest { + fun `given current client info is different than the stored one when trying to update then new client info is set`() = runTest { // Given givenCurrentAppName(AN_APP_NAME_1) givenCurrentVersionName(A_VERSION_NAME_1) @@ -64,63 +79,38 @@ class UpdateMatrixClientInfoUseCaseTest { ) // When - val result = updateMatrixClientInfoUseCase.execute() + updateMatrixClientInfoUseCase.execute(fakeSession) // Then - result.isSuccess shouldBe true - coVerify { setMatrixClientInfoUseCase.execute(match { it == expectedClientInfoToSet }) } + coVerify { setMatrixClientInfoUseCase.execute(fakeSession, match { it == expectedClientInfoToSet }) } } @Test - fun `given current client info is equal to the stored one when trying to update then nothing is done and result is success`() = runTest { + fun `given current client info is equal to the stored one when trying to update then nothing is done`() = runTest { // Given givenCurrentAppName(AN_APP_NAME_1) givenCurrentVersionName(A_VERSION_NAME_1) givenStoredClientInfo(AN_APP_NAME_1, A_VERSION_NAME_1) // When - val result = updateMatrixClientInfoUseCase.execute() + updateMatrixClientInfoUseCase.execute(fakeSession) // Then - result.isSuccess shouldBe true - coVerify(inverse = true) { setMatrixClientInfoUseCase.execute(any()) } + coVerify(inverse = true) { setMatrixClientInfoUseCase.execute(fakeSession, any()) } } @Test - fun `given error during setting new client info when trying to update then result is failure`() = runTest { + fun `given no session id for current session when trying to update then nothing is done`() = runTest { // Given givenCurrentAppName(AN_APP_NAME_1) givenCurrentVersionName(A_VERSION_NAME_1) - givenStoredClientInfo(AN_APP_NAME_2, A_VERSION_NAME_2) - val error = Exception() - givenSetClientInfoFailsWithError(error) - val expectedClientInfoToSet = MatrixClientInfoContent( - name = AN_APP_NAME_1, - version = A_VERSION_NAME_1, - ) + fakeSession.givenSessionId(null) // When - val result = updateMatrixClientInfoUseCase.execute() + updateMatrixClientInfoUseCase.execute(fakeSession) // Then - result.isFailure shouldBe true - result.exceptionOrNull() shouldBeEqualTo error - coVerify { setMatrixClientInfoUseCase.execute(match { it == expectedClientInfoToSet }) } - } - - @Test - fun `given no session id for current session when trying to update then result is failure`() = runTest { - // Given - givenCurrentAppName(AN_APP_NAME_1) - givenCurrentVersionName(A_VERSION_NAME_1) - fakeActiveSessionHolder.fakeSession.givenSessionId(null) - - // When - val result = updateMatrixClientInfoUseCase.execute() - - // Then - result.isFailure shouldBe true - result.exceptionOrNull() shouldBeInstanceOf NoDeviceIdError::class + coVerify(inverse = true) { setMatrixClientInfoUseCase.execute(fakeSession, any()) } } private fun givenCurrentAppName(appName: String) { @@ -132,18 +122,14 @@ class UpdateMatrixClientInfoUseCaseTest { } private fun givenStoredClientInfo(appName: String, versionName: String) { - fakeActiveSessionHolder.fakeSession.givenSessionId(A_SESSION_ID) - every { getMatrixClientInfoUseCase.execute(A_SESSION_ID) } returns MatrixClientInfoContent( + fakeSession.givenSessionId(A_SESSION_ID) + every { getMatrixClientInfoUseCase.execute(fakeSession, A_SESSION_ID) } returns MatrixClientInfoContent( name = appName, version = versionName, ) } private fun givenSetClientInfoSucceeds() { - coEvery { setMatrixClientInfoUseCase.execute(any()) } returns Result.success(Unit) - } - - private fun givenSetClientInfoFailsWithError(error: Exception) { - coEvery { setMatrixClientInfoUseCase.execute(any()) } throws error + coEvery { setMatrixClientInfoUseCase.execute(any(), any()) } returns Result.success(Unit) } } From e465969e5e6df99ba67e007168fdb716ca1a02cc Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 3 Oct 2022 16:44:20 +0200 Subject: [PATCH 10/16] Adding unit tests for ConfigureAndStartSessionUseCase --- .../ConfigureAndStartSessionUseCase.kt | 1 - .../ConfigureAndStartSessionUseCaseTest.kt | 102 ++++++++++++++++++ .../app/test/fakes/FakeFilterService.kt | 35 ++++++ .../im/vector/app/test/fakes/FakeSession.kt | 4 + .../app/test/fakes/FakeWebRtcCallManager.kt | 37 +++++++ 5 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 vector/src/test/java/im/vector/app/core/session/ConfigureAndStartSessionUseCaseTest.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeFilterService.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeWebRtcCallManager.kt diff --git a/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt b/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt index 504ed830df..be40fd907a 100644 --- a/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt @@ -32,7 +32,6 @@ class ConfigureAndStartSessionUseCase @Inject constructor( private val updateMatrixClientInfoUseCase: UpdateMatrixClientInfoUseCase, ) { - // TODO add unit tests fun execute(session: Session, startSyncing: Boolean = true) { Timber.i("Configure and start session for ${session.myUserId}. startSyncing: $startSyncing") session.open() diff --git a/vector/src/test/java/im/vector/app/core/session/ConfigureAndStartSessionUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/ConfigureAndStartSessionUseCaseTest.kt new file mode 100644 index 0000000000..1b070a97be --- /dev/null +++ b/vector/src/test/java/im/vector/app/core/session/ConfigureAndStartSessionUseCaseTest.kt @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2022 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 im.vector.app.core.session + +import im.vector.app.core.extensions.startSyncing +import im.vector.app.core.session.clientinfo.UpdateMatrixClientInfoUseCase +import im.vector.app.test.fakes.FakeContext +import im.vector.app.test.fakes.FakeSession +import im.vector.app.test.fakes.FakeWebRtcCallManager +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.runs +import io.mockk.unmockkAll +import io.mockk.verify +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.matrix.android.sdk.api.session.sync.FilterService + +class ConfigureAndStartSessionUseCaseTest { + + private val fakeContext = FakeContext() + private val fakeWebRtcCallManager = FakeWebRtcCallManager() + private val fakeUpdateMatrixClientInfoUseCase = mockk() + + private val configureAndStartSessionUseCase = ConfigureAndStartSessionUseCase( + context = fakeContext.instance, + webRtcCallManager = fakeWebRtcCallManager.instance, + updateMatrixClientInfoUseCase = fakeUpdateMatrixClientInfoUseCase, + ) + + @Before + fun setup() { + mockkStatic("im.vector.app.core.extensions.SessionKt") + } + + @After + fun tearDown() { + unmockkAll() + } + + @Test + fun `given a session and start sync needed when configuring and starting the session then it should be configured properly`() { + // Given + val fakeSession = givenASession() + fakeWebRtcCallManager.givenCheckForProtocolsSupportIfNeededSucceeds() + every { fakeUpdateMatrixClientInfoUseCase.execute(any()) } just runs + + // When + configureAndStartSessionUseCase.execute(fakeSession, startSyncing = true) + + // Then + verify { fakeSession.startSyncing(fakeContext.instance) } + fakeSession.fakeFilterService.verifySetFilter(FilterService.FilterPreset.ElementFilter) + fakeSession.fakePushersService.verifyRefreshPushers() + fakeWebRtcCallManager.verifyCheckForProtocolsSupportIfNeeded() + verify { fakeUpdateMatrixClientInfoUseCase.execute(fakeSession) } + } + + @Test + fun `given a session and no start sync needed when configuring and starting the session then it should be configured properly`() { + // Given + val fakeSession = givenASession() + fakeWebRtcCallManager.givenCheckForProtocolsSupportIfNeededSucceeds() + every { fakeUpdateMatrixClientInfoUseCase.execute(any()) } just runs + + // When + configureAndStartSessionUseCase.execute(fakeSession, startSyncing = false) + + // Then + verify(inverse = true) { fakeSession.startSyncing(fakeContext.instance) } + fakeSession.fakeFilterService.verifySetFilter(FilterService.FilterPreset.ElementFilter) + fakeSession.fakePushersService.verifyRefreshPushers() + fakeWebRtcCallManager.verifyCheckForProtocolsSupportIfNeeded() + verify { fakeUpdateMatrixClientInfoUseCase.execute(fakeSession) } + } + + private fun givenASession(): FakeSession { + val fakeSession = FakeSession() + every { fakeSession.open() } just runs + fakeSession.fakeFilterService.givenSetFilterSucceeds() + every { fakeSession.startSyncing(any()) } just runs + fakeSession.fakePushersService.givenRefreshPushersSucceeds() + return fakeSession + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeFilterService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeFilterService.kt new file mode 100644 index 0000000000..4332368127 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeFilterService.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 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 im.vector.app.test.fakes + +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.runs +import io.mockk.verify +import org.matrix.android.sdk.api.session.sync.FilterService + +class FakeFilterService : FilterService by mockk() { + + fun givenSetFilterSucceeds() { + every { setFilter(any()) } just runs + } + + fun verifySetFilter(filterPreset: FilterService.FilterPreset) { + verify { setFilter(filterPreset) } + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt index f4b17ea750..ef2104ed8a 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt @@ -44,6 +44,8 @@ class FakeSession( val fakePushersService: FakePushersService = FakePushersService(), private val fakeEventService: FakeEventService = FakeEventService(), val fakeSessionAccountDataService: FakeSessionAccountDataService = FakeSessionAccountDataService(), + val fakeFilterService: FakeFilterService = FakeFilterService(), + val fakePushersService: FakePushersService = FakePushersService(), ) : Session by mockk(relaxed = true) { init { @@ -62,6 +64,8 @@ class FakeSession( override fun eventService() = fakeEventService override fun pushersService() = fakePushersService override fun accountDataService() = fakeSessionAccountDataService + override fun filterService() = fakeFilterService + override fun pushersService() = fakePushersService fun givenVectorStore(vectorSessionStore: VectorSessionStore) { coEvery { diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeWebRtcCallManager.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeWebRtcCallManager.kt new file mode 100644 index 0000000000..b3664bafa1 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeWebRtcCallManager.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 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 im.vector.app.test.fakes + +import im.vector.app.features.call.webrtc.WebRtcCallManager +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.runs +import io.mockk.verify + +class FakeWebRtcCallManager { + + val instance = mockk() + + fun givenCheckForProtocolsSupportIfNeededSucceeds() { + every { instance.checkForProtocolsSupportIfNeeded() } just runs + } + + fun verifyCheckForProtocolsSupportIfNeeded() { + verify { instance.checkForProtocolsSupportIfNeeded() } + } +} From a762fc1d80aea08a95fc04dae316b86e51437861 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 3 Oct 2022 16:51:38 +0200 Subject: [PATCH 11/16] Removing unused imports --- vector/src/main/java/im/vector/app/core/extensions/Session.kt | 1 - .../core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt | 1 - .../session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt | 3 --- 3 files changed, 5 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/extensions/Session.kt b/vector/src/main/java/im/vector/app/core/extensions/Session.kt index 9340722ce1..4f2d387474 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Session.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Session.kt @@ -24,7 +24,6 @@ import im.vector.app.core.services.VectorSyncAndroidService import im.vector.app.features.session.VectorSessionStore import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState -import org.matrix.android.sdk.api.session.sync.FilterService import timber.log.Timber fun Session.startSyncing(context: Context) { diff --git a/vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt index 800dedfb3a..4be8218ab5 100644 --- a/vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/GetMatrixClientInfoUseCaseTest.kt @@ -17,7 +17,6 @@ package im.vector.app.core.session.clientinfo import im.vector.app.test.fakes.FakeSession -import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBeEqualTo import org.junit.Test diff --git a/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt index f31eaafb8c..79e6ea8639 100644 --- a/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt @@ -16,7 +16,6 @@ package im.vector.app.core.session.clientinfo -import android.os.SystemClock import im.vector.app.core.resources.BuildMeta import im.vector.app.test.fakes.FakeAppNameProvider import im.vector.app.test.fakes.FakeSession @@ -25,8 +24,6 @@ import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every import io.mockk.mockk -import io.mockk.mockkStatic -import io.mockk.unmockkAll import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.runTest From 5649933b0363aeef7c0ec65d516bc68e098b21c2 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 3 Oct 2022 17:06:42 +0200 Subject: [PATCH 12/16] Removing some TODOs --- .../session/user/accountdata/DefaultSessionAccountDataService.kt | 1 - .../session/user/accountdata/UpdateUserAccountDataTask.kt | 1 - 2 files changed, 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt index c81dac0882..c73446cf25 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt @@ -64,7 +64,6 @@ internal class DefaultSessionAccountDataService @Inject constructor( return roomAccountDataDataSource.getLiveAccountDataEvents(null, types) } - // TODO add unit tests override suspend fun updateUserAccountData(type: String, content: Content) { val params = UpdateUserAccountDataTask.AnyParams(type = type, any = content) awaitCallback { callback -> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt index 9e42191a50..ff0e960f0f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt @@ -112,7 +112,6 @@ internal class DefaultUpdateUserAccountDataTask @Inject constructor( private val globalErrorReceiver: GlobalErrorReceiver ) : UpdateUserAccountDataTask { - // TODO add unit tests override suspend fun execute(params: UpdateUserAccountDataTask.Params) { return executeRequest(globalErrorReceiver) { accountDataApi.setAccountData(userId, params.type, params.getData()) From 1475655f20c60dba22484ebfa094eddce1348688 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 3 Oct 2022 17:49:17 +0200 Subject: [PATCH 13/16] Fix unit tests failing by setting testDispatcher --- .../session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt index 79e6ea8639..b549c809b5 100644 --- a/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt @@ -64,7 +64,7 @@ class UpdateMatrixClientInfoUseCaseTest { } @Test - fun `given current client info is different than the stored one when trying to update then new client info is set`() = runTest { + fun `given current client info is different than the stored one when trying to update then new client info is set`() = runTest(testDispatcher) { // Given givenCurrentAppName(AN_APP_NAME_1) givenCurrentVersionName(A_VERSION_NAME_1) @@ -83,7 +83,7 @@ class UpdateMatrixClientInfoUseCaseTest { } @Test - fun `given current client info is equal to the stored one when trying to update then nothing is done`() = runTest { + fun `given current client info is equal to the stored one when trying to update then nothing is done`() = runTest(testDispatcher) { // Given givenCurrentAppName(AN_APP_NAME_1) givenCurrentVersionName(A_VERSION_NAME_1) @@ -97,7 +97,7 @@ class UpdateMatrixClientInfoUseCaseTest { } @Test - fun `given no session id for current session when trying to update then nothing is done`() = runTest { + fun `given no session id for current session when trying to update then nothing is done`() = runTest(testDispatcher) { // Given givenCurrentAppName(AN_APP_NAME_1) givenCurrentVersionName(A_VERSION_NAME_1) From 3adc5ca4305e535aa2b21f390d4c50e09962692d Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 5 Oct 2022 16:19:34 +0200 Subject: [PATCH 14/16] Using suspend modifier to make use case really testable --- .../vector/app/core/di/ActiveSessionHolder.kt | 4 +- .../ConfigureAndStartSessionUseCase.kt | 2 +- .../UpdateMatrixClientInfoUseCase.kt | 34 +++++------ .../ConfigureAndStartSessionUseCaseTest.kt | 15 +++-- .../UpdateMatrixClientInfoUseCaseTest.kt | 61 ++++++++++++------- 5 files changed, 66 insertions(+), 50 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt index c7d621ac0a..c74a945e61 100644 --- a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt +++ b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt @@ -110,7 +110,9 @@ class ActiveSessionHolder @Inject constructor( } ?: sessionInitializer.tryInitialize(readCurrentSession = { activeSessionReference.get() }) { session -> setActiveSession(session) - configureAndStartSessionUseCase.execute(session, startSyncing = startSync) + runBlocking { + configureAndStartSessionUseCase.execute(session, startSyncing = startSync) + } } } diff --git a/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt b/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt index be40fd907a..dfcb92af24 100644 --- a/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/ConfigureAndStartSessionUseCase.kt @@ -32,7 +32,7 @@ class ConfigureAndStartSessionUseCase @Inject constructor( private val updateMatrixClientInfoUseCase: UpdateMatrixClientInfoUseCase, ) { - fun execute(session: Session, startSyncing: Boolean = true) { + suspend fun execute(session: Session, startSyncing: Boolean = true) { Timber.i("Configure and start session for ${session.myUserId}. startSyncing: $startSyncing") session.open() session.filterService().setFilter(FilterService.FilterPreset.ElementFilter) diff --git a/vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt index a5cd2bb948..a46ca4eedb 100644 --- a/vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCase.kt @@ -18,8 +18,6 @@ package im.vector.app.core.session.clientinfo import im.vector.app.core.resources.AppNameProvider import im.vector.app.core.resources.BuildMeta -import im.vector.app.features.session.coroutineScope -import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session import timber.log.Timber import javax.inject.Inject @@ -34,25 +32,21 @@ class UpdateMatrixClientInfoUseCase @Inject constructor( private val setMatrixClientInfoUseCase: SetMatrixClientInfoUseCase, ) { - fun execute(session: Session) { - session.coroutineScope.launch { - runCatching { - val clientInfo = MatrixClientInfoContent( - name = appNameProvider.getAppName(), - version = buildMeta.versionName - ) - val deviceId = session.sessionParams.deviceId.orEmpty() - if (deviceId.isNotEmpty()) { - val storedClientInfo = getMatrixClientInfoUseCase.execute(session, deviceId) - Timber.d("storedClientInfo=$storedClientInfo, current client info=$clientInfo") - if (clientInfo != storedClientInfo) { - Timber.d("client info need to be updated") - setMatrixClientInfoUseCase.execute(session, clientInfo) - } - } else { - throw NoDeviceIdError() - } + suspend fun execute(session: Session) = runCatching { + val clientInfo = MatrixClientInfoContent( + name = appNameProvider.getAppName(), + version = buildMeta.versionName + ) + val deviceId = session.sessionParams.deviceId.orEmpty() + if (deviceId.isNotEmpty()) { + val storedClientInfo = getMatrixClientInfoUseCase.execute(session, deviceId) + Timber.d("storedClientInfo=$storedClientInfo, current client info=$clientInfo") + if (clientInfo != storedClientInfo) { + Timber.d("client info need to be updated") + return setMatrixClientInfoUseCase.execute(session, clientInfo) } + } else { + throw NoDeviceIdError() } } } diff --git a/vector/src/test/java/im/vector/app/core/session/ConfigureAndStartSessionUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/ConfigureAndStartSessionUseCaseTest.kt index 1b070a97be..b879806930 100644 --- a/vector/src/test/java/im/vector/app/core/session/ConfigureAndStartSessionUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/ConfigureAndStartSessionUseCaseTest.kt @@ -21,6 +21,8 @@ import im.vector.app.core.session.clientinfo.UpdateMatrixClientInfoUseCase import im.vector.app.test.fakes.FakeContext import im.vector.app.test.fakes.FakeSession import im.vector.app.test.fakes.FakeWebRtcCallManager +import io.mockk.coJustRun +import io.mockk.coVerify import io.mockk.every import io.mockk.just import io.mockk.mockk @@ -28,6 +30,7 @@ import io.mockk.mockkStatic import io.mockk.runs import io.mockk.unmockkAll import io.mockk.verify +import kotlinx.coroutines.test.runTest import org.junit.After import org.junit.Before import org.junit.Test @@ -56,11 +59,11 @@ class ConfigureAndStartSessionUseCaseTest { } @Test - fun `given a session and start sync needed when configuring and starting the session then it should be configured properly`() { + fun `given a session and start sync needed when configuring and starting the session then it should be configured properly`() = runTest { // Given val fakeSession = givenASession() fakeWebRtcCallManager.givenCheckForProtocolsSupportIfNeededSucceeds() - every { fakeUpdateMatrixClientInfoUseCase.execute(any()) } just runs + coJustRun { fakeUpdateMatrixClientInfoUseCase.execute(any()) } // When configureAndStartSessionUseCase.execute(fakeSession, startSyncing = true) @@ -70,15 +73,15 @@ class ConfigureAndStartSessionUseCaseTest { fakeSession.fakeFilterService.verifySetFilter(FilterService.FilterPreset.ElementFilter) fakeSession.fakePushersService.verifyRefreshPushers() fakeWebRtcCallManager.verifyCheckForProtocolsSupportIfNeeded() - verify { fakeUpdateMatrixClientInfoUseCase.execute(fakeSession) } + coVerify { fakeUpdateMatrixClientInfoUseCase.execute(fakeSession) } } @Test - fun `given a session and no start sync needed when configuring and starting the session then it should be configured properly`() { + fun `given a session and no start sync needed when configuring and starting the session then it should be configured properly`() = runTest { // Given val fakeSession = givenASession() fakeWebRtcCallManager.givenCheckForProtocolsSupportIfNeededSucceeds() - every { fakeUpdateMatrixClientInfoUseCase.execute(any()) } just runs + coJustRun { fakeUpdateMatrixClientInfoUseCase.execute(any()) } // When configureAndStartSessionUseCase.execute(fakeSession, startSyncing = false) @@ -88,7 +91,7 @@ class ConfigureAndStartSessionUseCaseTest { fakeSession.fakeFilterService.verifySetFilter(FilterService.FilterPreset.ElementFilter) fakeSession.fakePushersService.verifyRefreshPushers() fakeWebRtcCallManager.verifyCheckForProtocolsSupportIfNeeded() - verify { fakeUpdateMatrixClientInfoUseCase.execute(fakeSession) } + coVerify { fakeUpdateMatrixClientInfoUseCase.execute(fakeSession) } } private fun givenASession(): FakeSession { diff --git a/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt index b549c809b5..7f1727ff37 100644 --- a/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/UpdateMatrixClientInfoUseCaseTest.kt @@ -19,17 +19,14 @@ package im.vector.app.core.session.clientinfo import im.vector.app.core.resources.BuildMeta import im.vector.app.test.fakes.FakeAppNameProvider import im.vector.app.test.fakes.FakeSession -import im.vector.app.test.testDispatcher import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every import io.mockk.mockk -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.runTest -import kotlinx.coroutines.test.setMain -import org.junit.After -import org.junit.Before +import org.amshove.kluent.shouldBe +import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldBeInstanceOf import org.junit.Test private const val AN_APP_NAME_1 = "app_name_1" @@ -53,18 +50,8 @@ class UpdateMatrixClientInfoUseCaseTest { setMatrixClientInfoUseCase = setMatrixClientInfoUseCase, ) - @Before - fun setup() { - Dispatchers.setMain(testDispatcher) - } - - @After - fun tearDown() { - Dispatchers.resetMain() - } - @Test - fun `given current client info is different than the stored one when trying to update then new client info is set`() = runTest(testDispatcher) { + fun `given current client info is different than the stored one when trying to update then new client info is set`() = runTest { // Given givenCurrentAppName(AN_APP_NAME_1) givenCurrentVersionName(A_VERSION_NAME_1) @@ -76,37 +63,63 @@ class UpdateMatrixClientInfoUseCaseTest { ) // When - updateMatrixClientInfoUseCase.execute(fakeSession) + val result = updateMatrixClientInfoUseCase.execute(fakeSession) // Then + result.isSuccess shouldBe true coVerify { setMatrixClientInfoUseCase.execute(fakeSession, match { it == expectedClientInfoToSet }) } } @Test - fun `given current client info is equal to the stored one when trying to update then nothing is done`() = runTest(testDispatcher) { + fun `given error during set of new client info when trying to update then result is failure`() = runTest { + // Given + givenCurrentAppName(AN_APP_NAME_1) + givenCurrentVersionName(A_VERSION_NAME_1) + givenStoredClientInfo(AN_APP_NAME_2, A_VERSION_NAME_2) + val error = Exception() + givenSetClientInfoFails(error) + val expectedClientInfoToSet = MatrixClientInfoContent( + name = AN_APP_NAME_1, + version = A_VERSION_NAME_1, + ) + + // When + val result = updateMatrixClientInfoUseCase.execute(fakeSession) + + // Then + result.isFailure shouldBe true + result.exceptionOrNull() shouldBeEqualTo error + coVerify { setMatrixClientInfoUseCase.execute(fakeSession, match { it == expectedClientInfoToSet }) } + } + + @Test + fun `given current client info is equal to the stored one when trying to update then nothing is done`() = runTest { // Given givenCurrentAppName(AN_APP_NAME_1) givenCurrentVersionName(A_VERSION_NAME_1) givenStoredClientInfo(AN_APP_NAME_1, A_VERSION_NAME_1) // When - updateMatrixClientInfoUseCase.execute(fakeSession) + val result = updateMatrixClientInfoUseCase.execute(fakeSession) // Then + result.isSuccess shouldBe true coVerify(inverse = true) { setMatrixClientInfoUseCase.execute(fakeSession, any()) } } @Test - fun `given no session id for current session when trying to update then nothing is done`() = runTest(testDispatcher) { + fun `given no session id for current session when trying to update then nothing is done`() = runTest { // Given givenCurrentAppName(AN_APP_NAME_1) givenCurrentVersionName(A_VERSION_NAME_1) fakeSession.givenSessionId(null) // When - updateMatrixClientInfoUseCase.execute(fakeSession) + val result = updateMatrixClientInfoUseCase.execute(fakeSession) // Then + result.isFailure shouldBe true + result.exceptionOrNull() shouldBeInstanceOf NoDeviceIdError::class coVerify(inverse = true) { setMatrixClientInfoUseCase.execute(fakeSession, any()) } } @@ -129,4 +142,8 @@ class UpdateMatrixClientInfoUseCaseTest { private fun givenSetClientInfoSucceeds() { coEvery { setMatrixClientInfoUseCase.execute(any(), any()) } returns Result.success(Unit) } + + private fun givenSetClientInfoFails(error: Throwable) { + coEvery { setMatrixClientInfoUseCase.execute(any(), any()) } returns Result.failure(error) + } } From 4aca1dcb24788688aafaf6008d1c556a1a7b87e2 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 11 Oct 2022 14:28:03 +0200 Subject: [PATCH 15/16] Fix after rebase --- .../features/settings/devices/v2/list/SessionInfoView.kt | 1 + .../java/im/vector/app/test/fakes/FakePushersService.kt | 9 +++++++++ .../test/java/im/vector/app/test/fakes/FakeSession.kt | 2 -- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt index 6f6c5b24e2..5d558c517f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt @@ -184,6 +184,7 @@ class SessionInfoView @JvmOverloads constructor( } views.sessionInfoLastIPAddressTextView.setTextOrHide(deviceInfo.lastSeenIp?.takeIf { isLastSeenDetailsVisible }) + views.sessionInfoLastIPAddressTextView.text = "XX.XXX.XXX.XX" } private fun renderDetailsButton(isDetailsButtonVisible: Boolean) { diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakePushersService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakePushersService.kt index 60d50eab03..1a882b48c6 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakePushersService.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakePushersService.kt @@ -20,6 +20,7 @@ import androidx.lifecycle.liveData import io.mockk.Ordering import io.mockk.coVerify import io.mockk.every +import io.mockk.justRun import io.mockk.mockk import io.mockk.slot import io.mockk.verify @@ -45,4 +46,12 @@ class FakePushersService : PushersService by mockk(relaxed = true) { verify { enqueueAddHttpPusher(capture(httpPusherSlot)) } return httpPusherSlot.captured } + + fun givenRefreshPushersSucceeds() { + justRun { refreshPushers() } + } + + fun verifyRefreshPushers() { + verify { refreshPushers() } + } } diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt index ef2104ed8a..c40e4a8fc4 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt @@ -45,7 +45,6 @@ class FakeSession( private val fakeEventService: FakeEventService = FakeEventService(), val fakeSessionAccountDataService: FakeSessionAccountDataService = FakeSessionAccountDataService(), val fakeFilterService: FakeFilterService = FakeFilterService(), - val fakePushersService: FakePushersService = FakePushersService(), ) : Session by mockk(relaxed = true) { init { @@ -65,7 +64,6 @@ class FakeSession( override fun pushersService() = fakePushersService override fun accountDataService() = fakeSessionAccountDataService override fun filterService() = fakeFilterService - override fun pushersService() = fakePushersService fun givenVectorStore(vectorSessionStore: VectorSessionStore) { coEvery { From b9f7e9762d5e08d462c5008e36244ef449826328 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 11 Oct 2022 15:22:41 +0200 Subject: [PATCH 16/16] Removing code for tests --- .../app/features/settings/devices/v2/list/SessionInfoView.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt index 5d558c517f..6f6c5b24e2 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt @@ -184,7 +184,6 @@ class SessionInfoView @JvmOverloads constructor( } views.sessionInfoLastIPAddressTextView.setTextOrHide(deviceInfo.lastSeenIp?.takeIf { isLastSeenDetailsVisible }) - views.sessionInfoLastIPAddressTextView.text = "XX.XXX.XXX.XX" } private fun renderDetailsButton(isDetailsButtonVisible: Boolean) {