diff --git a/changelog.d/7344.feature b/changelog.d/7344.feature new file mode 100644 index 0000000000..a6deb4a23a --- /dev/null +++ b/changelog.d/7344.feature @@ -0,0 +1 @@ +[Device management] Add lab flag for matrix client info account data event diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index c164b0a519..77f16efff8 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -3340,6 +3340,8 @@ Other users in direct messages and rooms that you join are able to view a full list of your sessions.\n\nThis provides them with confidence that they are really speaking to you, but it also means they can see the session name you enter here. Enable new session manager Have greater visibility and control over all your sessions. + Enable client info recording + Record the client name, version, and url to recognise sessions more easily in session manager. %s\nis looking a little empty. diff --git a/vector-config/src/main/res/values/config-settings.xml b/vector-config/src/main/res/values/config-settings.xml index 9c7eee5c0c..7b7aac8156 100755 --- a/vector-config/src/main/res/values/config-settings.xml +++ b/vector-config/src/main/res/values/config-settings.xml @@ -42,6 +42,9 @@ false true false + true + false + true true false true diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt index 38b62e1511..d2afdb65e8 100644 --- a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt @@ -100,6 +100,7 @@ import im.vector.app.features.settings.devtools.KeyRequestViewModel import im.vector.app.features.settings.font.FontScaleSettingViewModel import im.vector.app.features.settings.homeserver.HomeserverSettingsViewModel import im.vector.app.features.settings.ignored.IgnoredUsersViewModel +import im.vector.app.features.settings.labs.VectorSettingsLabsViewModel import im.vector.app.features.settings.legals.LegalsViewModel import im.vector.app.features.settings.locale.LocalePickerViewModel import im.vector.app.features.settings.push.PushGatewaysViewModel @@ -665,4 +666,9 @@ interface MavericksViewModelModule { @IntoMap @MavericksViewModelKey(SessionLearnMoreViewModel::class) fun sessionLearnMoreViewModelFactory(factory: SessionLearnMoreViewModel.Factory): MavericksAssistedViewModelFactory<*, *> + + @Binds + @IntoMap + @MavericksViewModelKey(VectorSettingsLabsViewModel::class) + fun vectorSettingsLabsViewModelFactory(factory: VectorSettingsLabsViewModel.Factory): MavericksAssistedViewModelFactory<*, *> } 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 dfcb92af24..a5e1fe68bd 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 @@ -21,6 +21,7 @@ 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 im.vector.app.features.settings.VectorPreferences import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.sync.FilterService import timber.log.Timber @@ -30,6 +31,7 @@ class ConfigureAndStartSessionUseCase @Inject constructor( @ApplicationContext private val context: Context, private val webRtcCallManager: WebRtcCallManager, private val updateMatrixClientInfoUseCase: UpdateMatrixClientInfoUseCase, + private val vectorPreferences: VectorPreferences, ) { suspend fun execute(session: Session, startSyncing: Boolean = true) { @@ -41,6 +43,8 @@ class ConfigureAndStartSessionUseCase @Inject constructor( } session.pushersService().refreshPushers() webRtcCallManager.checkForProtocolsSupportIfNeeded() - updateMatrixClientInfoUseCase.execute(session) + if (vectorPreferences.isClientInfoRecordingEnabled()) { + updateMatrixClientInfoUseCase.execute(session) + } } } diff --git a/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteMatrixClientInfoUseCase.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteMatrixClientInfoUseCase.kt new file mode 100644 index 0000000000..bab3af9af5 --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteMatrixClientInfoUseCase.kt @@ -0,0 +1,41 @@ +/* + * 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.clientinfo + +import im.vector.app.core.di.ActiveSessionHolder +import timber.log.Timber +import javax.inject.Inject + +/** + * This use case delete the account data event containing extended client info. + */ +class DeleteMatrixClientInfoUseCase @Inject constructor( + private val activeSessionHolder: ActiveSessionHolder, + private val setMatrixClientInfoUseCase: SetMatrixClientInfoUseCase, +) { + + suspend fun execute(): Result = runCatching { + Timber.d("deleting recorded client info") + val session = activeSessionHolder.getActiveSession() + val emptyClientInfo = MatrixClientInfoContent( + name = "", + version = "", + url = "", + ) + return setMatrixClientInfoUseCase.execute(session, emptyClientInfo) + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index aaf328e9c7..89fcda142a 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -73,6 +73,7 @@ class VectorPreferences @Inject constructor( const val SETTINGS_LABS_DEFERRED_DM_KEY = "SETTINGS_LABS_DEFERRED_DM_KEY" const val SETTINGS_LABS_RICH_TEXT_EDITOR_KEY = "SETTINGS_LABS_RICH_TEXT_EDITOR_KEY" const val SETTINGS_LABS_NEW_SESSION_MANAGER_KEY = "SETTINGS_LABS_NEW_SESSION_MANAGER_KEY" + const val SETTINGS_LABS_CLIENT_INFO_RECORDING_KEY = "SETTINGS_LABS_CLIENT_INFO_RECORDING_KEY" const val SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY" const val SETTINGS_CRYPTOGRAPHY_DIVIDER_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_DIVIDER_PREFERENCE_KEY" const val SETTINGS_CRYPTOGRAPHY_MANAGE_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_MANAGE_PREFERENCE_KEY" @@ -1188,6 +1189,13 @@ class VectorPreferences @Inject constructor( return defaultPrefs.getBoolean(SETTINGS_LABS_NEW_SESSION_MANAGER_KEY, getDefault(R.bool.settings_labs_new_session_manager_default)) } + /** + * Indicates whether or not client info recording is enabled. + */ + fun isClientInfoRecordingEnabled(): Boolean { + return defaultPrefs.getBoolean(SETTINGS_LABS_CLIENT_INFO_RECORDING_KEY, getDefault(R.bool.settings_labs_client_info_recording_default)) + } + fun showLiveSenderInfo(): Boolean { return defaultPrefs.getBoolean(SETTINGS_TIMELINE_SHOW_LIVE_SENDER_INFO, getDefault(R.bool.settings_timeline_show_live_sender_info_default)) } diff --git a/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsAction.kt b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsAction.kt new file mode 100644 index 0000000000..db48c3400b --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsAction.kt @@ -0,0 +1,24 @@ +/* + * 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.labs + +import im.vector.app.core.platform.VectorViewModelAction + +sealed class VectorSettingsLabsAction : VectorViewModelAction { + object UpdateClientInfo : VectorSettingsLabsAction() + object DeleteRecordedClientInfo : VectorSettingsLabsAction() +} diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt similarity index 85% rename from vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt rename to vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt index 18bc35f72a..6c31e32567 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019 New Vector Ltd + * Copyright (c) 2019 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. @@ -14,13 +14,15 @@ * limitations under the License. */ -package im.vector.app.features.settings +package im.vector.app.features.settings.labs import android.os.Bundle import android.text.method.LinkMovementMethod import android.widget.TextView import androidx.preference.Preference +import androidx.preference.Preference.OnPreferenceChangeListener import androidx.preference.SwitchPreference +import com.airbnb.mvrx.fragmentViewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R @@ -30,6 +32,8 @@ import im.vector.app.features.MainActivityArgs import im.vector.app.features.VectorFeatures import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.home.room.threads.ThreadsManager +import im.vector.app.features.settings.VectorPreferences +import im.vector.app.features.settings.VectorSettingsBaseFragment import org.matrix.android.sdk.api.settings.LightweightSettingsStorage import javax.inject.Inject @@ -37,6 +41,8 @@ import javax.inject.Inject class VectorSettingsLabsFragment : VectorSettingsBaseFragment() { + private val viewModel: VectorSettingsLabsViewModel by fragmentViewModel() + @Inject lateinit var vectorPreferences: VectorPreferences @Inject lateinit var lightweightSettingsStorage: LightweightSettingsStorage @Inject lateinit var threadsManager: ThreadsManager @@ -85,6 +91,7 @@ class VectorSettingsLabsFragment : } configureUnreadNotificationsAsTabPreference() + configureEnableClientInfoRecordingPreference() } private fun configureUnreadNotificationsAsTabPreference() { @@ -140,4 +147,16 @@ class VectorSettingsLabsFragment : private fun onNewLayoutPreferenceClicked() { configureUnreadNotificationsAsTabPreference() } + + private fun configureEnableClientInfoRecordingPreference() { + findPreference(VectorPreferences.SETTINGS_LABS_CLIENT_INFO_RECORDING_KEY)?.onPreferenceChangeListener = + OnPreferenceChangeListener { _, newValue -> + when (newValue as? Boolean) { + false -> viewModel.handle(VectorSettingsLabsAction.DeleteRecordedClientInfo) + true -> viewModel.handle(VectorSettingsLabsAction.UpdateClientInfo) + else -> Unit + } + true + } + } } diff --git a/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsViewModel.kt new file mode 100644 index 0000000000..38686b06be --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsViewModel.kt @@ -0,0 +1,67 @@ +/* + * 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.labs + +import com.airbnb.mvrx.MavericksViewModelFactory +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +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.platform.EmptyViewEvents +import im.vector.app.core.platform.VectorViewModel +import im.vector.app.core.session.clientinfo.DeleteMatrixClientInfoUseCase +import im.vector.app.core.session.clientinfo.UpdateMatrixClientInfoUseCase +import kotlinx.coroutines.launch + +class VectorSettingsLabsViewModel @AssistedInject constructor( + @Assisted initialState: VectorSettingsLabsViewState, + private val activeSessionHolder: ActiveSessionHolder, + private val updateMatrixClientInfoUseCase: UpdateMatrixClientInfoUseCase, + private val deleteMatrixClientInfoUseCase: DeleteMatrixClientInfoUseCase, +) : VectorViewModel(initialState) { + + @AssistedFactory + interface Factory : MavericksAssistedViewModelFactory { + override fun create(initialState: VectorSettingsLabsViewState): VectorSettingsLabsViewModel + } + + companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() + + override fun handle(action: VectorSettingsLabsAction) { + when (action) { + VectorSettingsLabsAction.UpdateClientInfo -> handleUpdateClientInfo() + VectorSettingsLabsAction.DeleteRecordedClientInfo -> handleDeleteRecordedClientInfo() + } + } + + private fun handleUpdateClientInfo() { + viewModelScope.launch { + activeSessionHolder.getSafeActiveSession() + ?.let { session -> + updateMatrixClientInfoUseCase.execute(session) + } + } + } + + private fun handleDeleteRecordedClientInfo() { + viewModelScope.launch { + deleteMatrixClientInfoUseCase.execute() + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsViewState.kt b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsViewState.kt new file mode 100644 index 0000000000..c246d30994 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsViewState.kt @@ -0,0 +1,21 @@ +/* + * 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.labs + +import com.airbnb.mvrx.MavericksState + +class VectorSettingsLabsViewState : MavericksState diff --git a/vector/src/main/res/xml/vector_settings_labs.xml b/vector/src/main/res/xml/vector_settings_labs.xml index 51c78d278a..5b519bdd91 100644 --- a/vector/src/main/res/xml/vector_settings_labs.xml +++ b/vector/src/main/res/xml/vector_settings_labs.xml @@ -107,6 +107,14 @@ android:defaultValue="@bool/settings_labs_new_session_manager_default" android:key="SETTINGS_LABS_NEW_SESSION_MANAGER_KEY" android:summary="@string/labs_enable_session_manager_summary" - android:title="@string/labs_enable_session_manager_title" /> + android:title="@string/labs_enable_session_manager_title" + app:isPreferenceVisible="@bool/settings_labs_new_session_manager_visible" /> + + diff --git a/vector/src/main/res/xml/vector_settings_root.xml b/vector/src/main/res/xml/vector_settings_root.xml index 02dc36bf39..ffa8688cbd 100644 --- a/vector/src/main/res/xml/vector_settings_root.xml +++ b/vector/src/main/res/xml/vector_settings_root.xml @@ -35,7 +35,7 @@ () + private val fakeVectorPreferences = FakeVectorPreferences() private val configureAndStartSessionUseCase = ConfigureAndStartSessionUseCase( context = fakeContext.instance, webRtcCallManager = fakeWebRtcCallManager.instance, updateMatrixClientInfoUseCase = fakeUpdateMatrixClientInfoUseCase, + vectorPreferences = fakeVectorPreferences.instance, ) @Before @@ -59,11 +62,12 @@ class ConfigureAndStartSessionUseCaseTest { } @Test - fun `given a session and start sync needed when configuring and starting the session then it should be configured properly`() = runTest { + fun `given start sync needed and client info recording enabled when execute then it should be configured properly`() = runTest { // Given val fakeSession = givenASession() fakeWebRtcCallManager.givenCheckForProtocolsSupportIfNeededSucceeds() coJustRun { fakeUpdateMatrixClientInfoUseCase.execute(any()) } + fakeVectorPreferences.givenIsClientInfoRecordingEnabled(isEnabled = true) // When configureAndStartSessionUseCase.execute(fakeSession, startSyncing = true) @@ -77,11 +81,31 @@ class ConfigureAndStartSessionUseCaseTest { } @Test - fun `given a session and no start sync needed when configuring and starting the session then it should be configured properly`() = runTest { + fun `given start sync needed and client info recording disabled when execute then it should be configured properly`() = runTest { // Given val fakeSession = givenASession() fakeWebRtcCallManager.givenCheckForProtocolsSupportIfNeededSucceeds() coJustRun { fakeUpdateMatrixClientInfoUseCase.execute(any()) } + fakeVectorPreferences.givenIsClientInfoRecordingEnabled(isEnabled = false) + + // When + configureAndStartSessionUseCase.execute(fakeSession, startSyncing = true) + + // Then + verify { fakeSession.startSyncing(fakeContext.instance) } + fakeSession.fakeFilterService.verifySetFilter(FilterService.FilterPreset.ElementFilter) + fakeSession.fakePushersService.verifyRefreshPushers() + fakeWebRtcCallManager.verifyCheckForProtocolsSupportIfNeeded() + coVerify(inverse = true) { fakeUpdateMatrixClientInfoUseCase.execute(fakeSession) } + } + + @Test + fun `given a session and no start sync needed when execute then it should be configured properly`() = runTest { + // Given + val fakeSession = givenASession() + fakeWebRtcCallManager.givenCheckForProtocolsSupportIfNeededSucceeds() + coJustRun { fakeUpdateMatrixClientInfoUseCase.execute(any()) } + fakeVectorPreferences.givenIsClientInfoRecordingEnabled(isEnabled = true) // When configureAndStartSessionUseCase.execute(fakeSession, startSyncing = false) diff --git a/vector/src/test/java/im/vector/app/core/session/clientinfo/DeleteMatrixClientInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/session/clientinfo/DeleteMatrixClientInfoUseCaseTest.kt new file mode 100644 index 0000000000..c89bd73979 --- /dev/null +++ b/vector/src/test/java/im/vector/app/core/session/clientinfo/DeleteMatrixClientInfoUseCaseTest.kt @@ -0,0 +1,82 @@ +/* + * 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.clientinfo + +import im.vector.app.test.fakes.FakeActiveSessionHolder +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.mockk +import kotlinx.coroutines.test.runTest +import org.amshove.kluent.shouldBe +import org.amshove.kluent.shouldBeEqualTo +import org.junit.Test + +class DeleteMatrixClientInfoUseCaseTest { + + private val fakeActiveSessionHolder = FakeActiveSessionHolder() + private val fakeSetMatrixClientInfoUseCase = mockk() + + private val deleteMatrixClientInfoUseCase = DeleteMatrixClientInfoUseCase( + activeSessionHolder = fakeActiveSessionHolder.instance, + setMatrixClientInfoUseCase = fakeSetMatrixClientInfoUseCase + ) + + @Test + fun `given current session when calling use case then empty client info is set and result is success`() = runTest { + // Given + givenSetMatrixClientInfoSucceeds() + val expectedClientInfoToBeSet = MatrixClientInfoContent( + name = "", + version = "", + url = "", + ) + + // When + val result = deleteMatrixClientInfoUseCase.execute() + + // Then + result.isSuccess shouldBe true + coVerify { + fakeSetMatrixClientInfoUseCase.execute( + fakeActiveSessionHolder.fakeSession, + expectedClientInfoToBeSet + ) + } + } + + @Test + fun `given current session and error during the process when calling use case then result is failure`() = runTest { + // Given + val error = Exception() + givenSetMatrixClientInfoFails(error) + + // When + val result = deleteMatrixClientInfoUseCase.execute() + + // Then + result.isFailure shouldBe true + result.exceptionOrNull() shouldBeEqualTo error + } + + private fun givenSetMatrixClientInfoSucceeds() { + coEvery { fakeSetMatrixClientInfoUseCase.execute(any(), any()) } returns Result.success(Unit) + } + + private fun givenSetMatrixClientInfoFails(error: Exception) { + coEvery { fakeSetMatrixClientInfoUseCase.execute(any(), any()) } returns Result.failure(error) + } +} diff --git a/vector/src/test/java/im/vector/app/features/settings/labs/VectorSettingsLabsViewModelTest.kt b/vector/src/test/java/im/vector/app/features/settings/labs/VectorSettingsLabsViewModelTest.kt new file mode 100644 index 0000000000..b3a4648263 --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/settings/labs/VectorSettingsLabsViewModelTest.kt @@ -0,0 +1,86 @@ +/* + * 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.labs + +import com.airbnb.mvrx.test.MavericksTestRule +import im.vector.app.core.session.clientinfo.DeleteMatrixClientInfoUseCase +import im.vector.app.core.session.clientinfo.UpdateMatrixClientInfoUseCase +import im.vector.app.test.fakes.FakeActiveSessionHolder +import im.vector.app.test.test +import im.vector.app.test.testDispatcher +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.mockk +import org.junit.Rule +import org.junit.Test + +class VectorSettingsLabsViewModelTest { + + @get:Rule + val mavericksTestRule = MavericksTestRule(testDispatcher = testDispatcher) + + private val fakeActiveSessionHolder = FakeActiveSessionHolder() + private val fakeUpdateMatrixClientInfoUseCase = mockk() + private val fakeDeleteMatrixClientInfoUseCase = mockk() + + private fun createViewModel(): VectorSettingsLabsViewModel { + return VectorSettingsLabsViewModel( + initialState = VectorSettingsLabsViewState(), + activeSessionHolder = fakeActiveSessionHolder.instance, + updateMatrixClientInfoUseCase = fakeUpdateMatrixClientInfoUseCase, + deleteMatrixClientInfoUseCase = fakeDeleteMatrixClientInfoUseCase, + ) + } + + @Test + fun `given update client info action when handling this action then update client info use case is called`() { + // Given + givenUpdateClientInfoSucceeds() + + // When + val viewModel = createViewModel() + val viewModelTest = viewModel.test() + viewModel.handle(VectorSettingsLabsAction.UpdateClientInfo) + + // Then + viewModelTest.finish() + coVerify { fakeUpdateMatrixClientInfoUseCase.execute(fakeActiveSessionHolder.fakeSession) } + } + + @Test + fun `given delete client info action when handling this action then delete client info use case is called`() { + // Given + givenDeleteClientInfoSucceeds() + + // When + val viewModel = createViewModel() + val viewModelTest = viewModel.test() + viewModel.handle(VectorSettingsLabsAction.DeleteRecordedClientInfo) + + // Then + viewModelTest.finish() + coVerify { fakeDeleteMatrixClientInfoUseCase.execute() } + } + + private fun givenUpdateClientInfoSucceeds() { + coEvery { fakeUpdateMatrixClientInfoUseCase.execute(any()) } returns Result.success(Unit) + } + + private fun givenDeleteClientInfoSucceeds() { + coEvery { fakeDeleteMatrixClientInfoUseCase.execute() } returns Result.success(Unit) + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeVectorPreferences.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeVectorPreferences.kt index bc761d9016..8b0630c24f 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeVectorPreferences.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeVectorPreferences.kt @@ -36,4 +36,8 @@ class FakeVectorPreferences { fun verifySetSpaceBackstack(value: List, inverse: Boolean = false) { verify(inverse = inverse) { instance.setSpaceBackstack(value) } } + + fun givenIsClientInfoRecordingEnabled(isEnabled: Boolean) { + every { instance.isClientInfoRecordingEnabled() } returns isEnabled + } }