From af506c73f40bebe2f604f98929f40da90f5d9e65 Mon Sep 17 00:00:00 2001 From: Damian Kaczmarek Date: Fri, 4 Oct 2024 09:15:50 +0200 Subject: [PATCH 1/5] feat: Add debug button send FCM token --- .../com/wire/android/di/CoreLogicModule.kt | 5 + .../wire/android/ui/debug/DebugDataOptions.kt | 56 ++++- .../ui/debug/DebugDataOptionsViewModel.kt | 46 +++- .../com/wire/android/ui/debug/DebugScreen.kt | 29 ++- .../com/wire/android/ui/debug/LogOptions.kt | 9 +- .../kotlin/com/wire/android/util/FileUtil.kt | 3 +- app/src/main/res/values/strings.xml | 16 +- .../services/WireFirebaseMessagingService.kt | 6 +- .../debug/DebugDataOptionsViewModelTest.kt | 226 ++++++++++++++++++ 9 files changed, 372 insertions(+), 24 deletions(-) create mode 100644 app/src/test/kotlin/com/wire/android/ui/settings/debug/DebugDataOptionsViewModelTest.kt diff --git a/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt b/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt index 4bdac6acfcb..0b32e3d76f0 100644 --- a/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt +++ b/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt @@ -487,4 +487,9 @@ class UseCaseModule { @Provides fun provideBreakSessionUseCase(@KaliumCoreLogic coreLogic: CoreLogic, @CurrentAccount currentAccount: UserId): BreakSessionUseCase = coreLogic.getSessionScope(currentAccount).debug.breakSession + + @ViewModelScoped + @Provides + fun provideSendFCMTokenToAPIUseCase(@KaliumCoreLogic coreLogic: CoreLogic, @CurrentAccount currentAccount: UserId) = + coreLogic.getSessionScope(currentAccount).debug.sendFCMTokenToServer } diff --git a/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptions.kt b/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptions.kt index b2cb4792faf..106ab474818 100644 --- a/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptions.kt +++ b/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptions.kt @@ -26,6 +26,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import com.wire.android.BuildConfig import com.wire.android.R import com.wire.android.di.hiltViewModelScoped @@ -38,9 +39,12 @@ import com.wire.android.ui.common.WireDialogButtonType import com.wire.android.ui.common.WireSwitch import com.wire.android.ui.common.button.WirePrimaryButton import com.wire.android.ui.common.dimensions +import com.wire.android.ui.common.snackbar.LocalSnackbarHostState +import com.wire.android.ui.common.snackbar.collectAndShowSnackbar import com.wire.android.ui.e2eiEnrollment.GetE2EICertificateUI import com.wire.android.ui.home.conversationslist.common.FolderHeader import com.wire.android.ui.home.settings.SettingsItem +import com.wire.android.ui.theme.WireTheme import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireDimensions import com.wire.android.ui.theme.wireTypography @@ -59,6 +63,7 @@ fun DebugDataOptions( hiltViewModelScoped(DebugDataOptions), onManualMigrationPressed: (currentAccount: UserId) -> Unit ) { + LocalSnackbarHostState.current.collectAndShowSnackbar(snackbarFlow = viewModel.infoMessage) DebugDataOptionsContent( state = viewModel.state(), appVersion = appVersion, @@ -73,6 +78,7 @@ fun DebugDataOptions( handleE2EIEnrollmentResult = viewModel::handleE2EIEnrollmentResult, dismissCertificateDialog = viewModel::dismissCertificateDialog, checkCrlRevocationList = viewModel::checkCrlRevocationList, + onResendFCMToken = viewModel::forceSendFCMToken ) } @@ -92,8 +98,10 @@ fun DebugDataOptionsContent( handleE2EIEnrollmentResult: (Either) -> Unit, dismissCertificateDialog: () -> Unit, checkCrlRevocationList: () -> Unit, + onResendFCMToken: () -> Unit, + modifier: Modifier = Modifier, ) { - Column { + Column(modifier = modifier) { FolderHeader(stringResource(R.string.label_debug_data)) @@ -194,7 +202,8 @@ fun DebugDataOptionsContent( onDisableEventProcessingChange = onDisableEventProcessingChange, onRestartSlowSyncForRecovery = onRestartSlowSyncForRecovery, onForceUpdateApiVersions = onForceUpdateApiVersions, - checkCrlRevocationList = checkCrlRevocationList + checkCrlRevocationList = checkCrlRevocationList, + onResendFCMToken = onResendFCMToken, ) } @@ -357,13 +366,30 @@ private fun EnableEncryptedProteusStorageSwitch( //endregion //region Debug Tools + +@Preview +@Composable +private fun DebugToolsOptionsPreview() { + WireTheme { + DebugToolsOptions( + isEventProcessingEnabled = true, + onDisableEventProcessingChange = {}, + onRestartSlowSyncForRecovery = {}, + onForceUpdateApiVersions = {}, + checkCrlRevocationList = {}, + onResendFCMToken = {}, + ) + } +} + @Composable private fun DebugToolsOptions( isEventProcessingEnabled: Boolean, onDisableEventProcessingChange: (Boolean) -> Unit, onRestartSlowSyncForRecovery: () -> Unit, onForceUpdateApiVersions: () -> Unit, - checkCrlRevocationList: () -> Unit + checkCrlRevocationList: () -> Unit, + onResendFCMToken: () -> Unit, ) { FolderHeader(stringResource(R.string.label_debug_tools_title)) Column { @@ -434,6 +460,27 @@ private fun DebugToolsOptions( ) } ) + + RowItemTemplate( + modifier = Modifier.wrapContentWidth(), + title = { + Text( + style = MaterialTheme.wireTypography.body01, + color = MaterialTheme.wireColorScheme.onBackground, + text = stringResource(R.string.debug_settings_register_fcm_push_token), + modifier = Modifier.padding(start = dimensions().spacing8x) + ) + }, + actions = { + WirePrimaryButton( + minSize = MaterialTheme.wireDimensions.buttonMediumMinSize, + minClickableSize = MaterialTheme.wireDimensions.buttonMinClickableSize, + onClick = onResendFCMToken, + text = stringResource(R.string.debug_settings_force_api_versioning_update_button_text), + fillMaxWidth = false + ) + } + ) } } @@ -469,7 +516,7 @@ private fun DisableEventProcessingSwitch( @PreviewMultipleThemes @Composable -fun PreviewOtherDebugOptions() { +fun PreviewOtherDebugOptions() = WireTheme { DebugDataOptionsContent( appVersion = "1.0.0", buildVariant = "debug", @@ -492,5 +539,6 @@ fun PreviewOtherDebugOptions() { handleE2EIEnrollmentResult = {}, dismissCertificateDialog = {}, checkCrlRevocationList = {}, + onResendFCMToken = {} ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptionsViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptionsViewModel.kt index e6c4a667b01..b23e0d65238 100644 --- a/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptionsViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptionsViewModel.kt @@ -28,8 +28,10 @@ import com.wire.android.di.CurrentAccount import com.wire.android.di.ScopedArgs import com.wire.android.di.ViewModelScopedPreview import com.wire.android.migration.failure.UserMigrationStatus +import com.wire.android.util.dispatchers.DispatcherProvider import com.wire.android.util.getDeviceIdString import com.wire.android.util.getGitBuildId +import com.wire.android.util.ui.UIText import com.wire.kalium.logic.CoreFailure import com.wire.kalium.logic.E2EIFailure import com.wire.kalium.logic.data.user.UserId @@ -38,20 +40,26 @@ import com.wire.kalium.logic.feature.e2ei.CheckCrlRevocationListUseCase import com.wire.kalium.logic.feature.e2ei.usecase.E2EIEnrollmentResult import com.wire.kalium.logic.feature.keypackage.MLSKeyPackageCountResult import com.wire.kalium.logic.feature.keypackage.MLSKeyPackageCountUseCase +import com.wire.kalium.logic.feature.notificationToken.SendFCMTokenError +import com.wire.kalium.logic.feature.notificationToken.SendFCMTokenUseCase import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.functional.fold import com.wire.kalium.logic.sync.periodic.UpdateApiVersionsScheduler import com.wire.kalium.logic.sync.slow.RestartSlowSyncProcessForRecoveryUseCase import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import kotlinx.serialization.Serializable import javax.inject.Inject @ViewModelScopedPreview interface DebugDataOptionsViewModel { - + val infoMessage: SharedFlow get() = MutableSharedFlow() fun state(): DebugDataOptionsState = DebugDataOptionsState() fun currentAccount(): UserId = UserId("value", "domain") fun checkCrlRevocationList() {} @@ -62,6 +70,7 @@ interface DebugDataOptionsViewModel { fun dismissCertificateDialog() {} fun forceUpdateApiVersions() {} fun disableEventProcessing(disabled: Boolean) {} + fun forceSendFCMToken() {} } @Suppress("LongParameterList", "TooManyFunctions") @@ -75,13 +84,18 @@ class DebugDataOptionsViewModelImpl private val mlsKeyPackageCount: MLSKeyPackageCountUseCase, private val restartSlowSyncProcessForRecovery: RestartSlowSyncProcessForRecoveryUseCase, private val checkCrlRevocationList: CheckCrlRevocationListUseCase, - private val getCurrentAnalyticsTrackingIdentifier: GetCurrentAnalyticsTrackingIdentifierUseCase + private val getCurrentAnalyticsTrackingIdentifier: GetCurrentAnalyticsTrackingIdentifierUseCase, + private val sendFCMToken: SendFCMTokenUseCase, + private val dispatcherProvider: DispatcherProvider, ) : ViewModel(), DebugDataOptionsViewModel { var state by mutableStateOf( DebugDataOptionsState() ) + private val _infoMessage = MutableSharedFlow() + override val infoMessage = _infoMessage.asSharedFlow() + init { observeEncryptedProteusStorageState() observeMlsMetadata() @@ -181,6 +195,34 @@ class DebugDataOptionsViewModelImpl } } + override fun forceSendFCMToken() { + viewModelScope.launch { + withContext(dispatcherProvider.io()) { + val result = sendFCMToken() + result.fold( + { + when (it.status) { + SendFCMTokenError.Reason.CANT_GET_CLIENT_ID -> { + _infoMessage.emit(UIText.DynamicString("Can't get client ID, error: ${it.error}")) + } + + SendFCMTokenError.Reason.CANT_GET_NOTIFICATION_TOKEN -> { + _infoMessage.emit(UIText.DynamicString("Can't get notification token, error: ${it.error}")) + } + + SendFCMTokenError.Reason.CANT_REGISTER_TOKEN -> { + _infoMessage.emit(UIText.DynamicString("Can't register token, error: ${it.error}")) + } + } + }, + { + _infoMessage.emit(UIText.DynamicString("Token registered")) + } + ) + } + } + } + //region Private private fun observeEncryptedProteusStorageState() { viewModelScope.launch { diff --git a/app/src/main/kotlin/com/wire/android/ui/debug/DebugScreen.kt b/app/src/main/kotlin/com/wire/android/ui/debug/DebugScreen.kt index 5fa57d82b8a..83da82c533d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/debug/DebugScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/debug/DebugScreen.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import com.ramcosta.composedestinations.annotation.RootNavGraph import com.wire.android.BuildConfig @@ -42,12 +43,13 @@ import com.wire.android.R import com.wire.android.navigation.BackStackMode import com.wire.android.navigation.NavigationCommand import com.wire.android.navigation.Navigator +import com.wire.android.navigation.WireDestination import com.wire.android.ui.common.dimensions import com.wire.android.ui.common.scaffold.WireScaffold -import com.wire.android.navigation.WireDestination import com.wire.android.ui.common.topappbar.NavigationIconType import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar import com.wire.android.ui.destinations.MigrationScreenDestination +import com.wire.android.ui.theme.WireTheme import com.wire.android.util.getMimeType import com.wire.android.util.getUrisOfFilesInDirectory import com.wire.android.util.multipleFileSharingIntent @@ -61,7 +63,12 @@ fun DebugScreen(navigator: Navigator, userDebugViewModel: UserDebugViewModel = h UserDebugContent( onNavigationPressed = navigator::navigateBack, onManualMigrationPressed = { - navigator.navigate(NavigationCommand(MigrationScreenDestination(it), BackStackMode.CLEAR_WHOLE)) + navigator.navigate( + NavigationCommand( + MigrationScreenDestination(it), + BackStackMode.CLEAR_WHOLE + ) + ) }, state = userDebugViewModel.state, onLoggingEnabledChange = userDebugViewModel::setLoggingEnabledState, @@ -146,7 +153,8 @@ data class DebugContentState( fun shareLogs() { val dir = File(logPath).parentFile - val fileUris = context.getUrisOfFilesInDirectory(dir) + val fileUris = + if (dir != null && dir.exists()) context.getUrisOfFilesInDirectory(dir) else arrayListOf() val intent = context.multipleFileSharingIntent(fileUris) // The first log file is simply text, not compressed. Get its mime type separately // and set it as the mime type for the intent. @@ -157,3 +165,18 @@ data class DebugContentState( context.startActivity(intent) } } + +@Preview(heightDp = 1400) +@Composable +internal fun PreviewUserDebugContent() = WireTheme { + UserDebugContent( + state = UserDebugState( + isLoggingEnabled = true, + logPath = "/data/user/0/com.wire.android/files/logs" + ), + onNavigationPressed = {}, + onManualMigrationPressed = {}, + onLoggingEnabledChange = {}, + onDeleteLogs = {} + ) +} diff --git a/app/src/main/kotlin/com/wire/android/ui/debug/LogOptions.kt b/app/src/main/kotlin/com/wire/android/ui/debug/LogOptions.kt index b722ca048c8..7a3fe1e89f0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/debug/LogOptions.kt +++ b/app/src/main/kotlin/com/wire/android/ui/debug/LogOptions.kt @@ -50,9 +50,10 @@ fun LogOptions( isLoggingEnabled: Boolean, onLoggingEnabledChange: (Boolean) -> Unit, onDeleteLogs: () -> Unit, - onShareLogs: () -> Unit + onShareLogs: () -> Unit, + modifier: Modifier = Modifier, ) { - Column { + Column(modifier = modifier) { FolderHeader(stringResource(R.string.label_logs_option_title)) EnableLoggingSwitch( isEnabled = isLoggingEnabled, @@ -82,9 +83,9 @@ fun LogOptions( @Composable private fun EnableLoggingSwitch( - isEnabled: Boolean = false, onCheckedChange: ((Boolean) -> Unit)?, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + isEnabled: Boolean = false ) { SurfaceBackgroundWrapper { Column(Modifier.padding(dimensions().spacing16x)) { diff --git a/app/src/main/kotlin/com/wire/android/util/FileUtil.kt b/app/src/main/kotlin/com/wire/android/util/FileUtil.kt index 468504c0849..0eb6c8c44fa 100644 --- a/app/src/main/kotlin/com/wire/android/util/FileUtil.kt +++ b/app/src/main/kotlin/com/wire/android/util/FileUtil.kt @@ -383,10 +383,9 @@ fun isText(mimeType: String?): Boolean { return mimeType != null && mimeType.startsWith("text/") } -@Suppress("MagicNumber") fun Context.getDeviceIdString(): String? { - if (Build.VERSION.SDK_INT >= 26) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { return Settings.Secure.getString(this.contentResolver, Settings.Secure.ANDROID_ID) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b20e3344f83..a8caa35f21d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -219,13 +219,7 @@ Wire Website Copyright © Wire Swiss GmbH - Debug Settings - API VERSIONING - E2EI Manual Enrollment - Force API versioning update - ⚠️ Break Session Dependencies: - Update Support Back up & Restore Conversations Search conversations @@ -1482,4 +1476,14 @@ In group conversations, the group admin can overwrite this setting. Bad Fair Excellent + + + + Register FCM push token + Debug Settings + API VERSIONING + E2EI Manual Enrollment + Force API versioning update + ⚠️ Break Session + Update diff --git a/app/src/nonfree/kotlin/com/wire/android/services/WireFirebaseMessagingService.kt b/app/src/nonfree/kotlin/com/wire/android/services/WireFirebaseMessagingService.kt index d929185e174..750107f4798 100644 --- a/app/src/nonfree/kotlin/com/wire/android/services/WireFirebaseMessagingService.kt +++ b/app/src/nonfree/kotlin/com/wire/android/services/WireFirebaseMessagingService.kt @@ -105,11 +105,11 @@ class WireFirebaseMessagingService : FirebaseMessagingService() { return userIdValue } - override fun onNewToken(p0: String) { - super.onNewToken(p0) + override fun onNewToken(token: String) { + super.onNewToken(token) scope.launch { coreLogic.globalScope { - saveNotificationToken(p0, "GCM", BuildConfig.FIREBASE_PUSH_SENDER_ID) + saveNotificationToken(token, "GCM", BuildConfig.FIREBASE_PUSH_SENDER_ID) }.let { result -> when (result) { is Result.Failure.Generic -> diff --git a/app/src/test/kotlin/com/wire/android/ui/settings/debug/DebugDataOptionsViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/settings/debug/DebugDataOptionsViewModelTest.kt new file mode 100644 index 00000000000..f4476ca976c --- /dev/null +++ b/app/src/test/kotlin/com/wire/android/ui/settings/debug/DebugDataOptionsViewModelTest.kt @@ -0,0 +1,226 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.wire.android.ui.settings.debug + +import android.content.Context +import app.cash.turbine.test +import com.wire.android.config.CoroutineTestExtension +import com.wire.android.config.ScopedArgsTestExtension +import com.wire.android.config.TestDispatcherProvider +import com.wire.android.datastore.GlobalDataStore +import com.wire.android.framework.TestUser +import com.wire.android.migration.failure.UserMigrationStatus +import com.wire.android.ui.debug.DebugDataOptionsViewModelImpl +import com.wire.android.util.getDeviceIdString +import com.wire.android.util.getGitBuildId +import com.wire.android.util.ui.UIText +import com.wire.kalium.logic.data.conversation.ClientId +import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.feature.analytics.GetCurrentAnalyticsTrackingIdentifierUseCase +import com.wire.kalium.logic.feature.e2ei.CheckCrlRevocationListUseCase +import com.wire.kalium.logic.feature.keypackage.MLSKeyPackageCountResult +import com.wire.kalium.logic.feature.keypackage.MLSKeyPackageCountUseCase +import com.wire.kalium.logic.feature.notificationToken.SendFCMTokenError +import com.wire.kalium.logic.feature.notificationToken.SendFCMTokenUseCase +import com.wire.kalium.logic.functional.Either +import com.wire.kalium.logic.sync.periodic.UpdateApiVersionsScheduler +import com.wire.kalium.logic.sync.slow.RestartSlowSyncProcessForRecoveryUseCase +import io.mockk.MockKAnnotations +import io.mockk.coEvery +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.mockkStatic +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.setMain +import org.amshove.kluent.internal.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(ScopedArgsTestExtension::class) +@ExtendWith(CoroutineTestExtension::class) +class DebugDataOptionsViewModelTest { + + @Test + fun `given token sending token will succeed, when sending FCM token, then info message should emmit success message`() = runTest { + // given + val (_, viewModel) = DebugDataOptionsHiltArrangement() + .withSendFCMTokenSuccess() + .arrange() + + viewModel.infoMessage.test { + // when + viewModel.forceSendFCMToken() + + // then + val result = awaitItem() + assertEquals(UIText.DynamicString("Token registered"), result) + } + } + + @Test + fun `given there is not client ID, when sending FCM token,info message should emit error message`() = runTest { + // given + val (_, viewModel) = DebugDataOptionsHiltArrangement() + .withSendFCMTokenClientIdFailure() + .arrange() + + viewModel.infoMessage.test { + // when + viewModel.forceSendFCMToken() + + // then + val result = awaitItem() + assertEquals(UIText.DynamicString("Can't get client ID, error: error message"), result) + } + } + + @Test + fun `given there is not notification token, when sending FCM token,info message should emit error message`() = runTest { + // given + val (_, viewModel) = DebugDataOptionsHiltArrangement() + .withSendFCMTokenNotificationTokenFailure() + .arrange() + + viewModel.infoMessage.test { + // when + viewModel.forceSendFCMToken() + + // then + val result = awaitItem() + assertEquals(UIText.DynamicString("Can't get notification token, error: error message"), result) + } + } + + @Test + fun `given that there is API failure, when sending FCM token,info message should emit error message`() = runTest { + // given + val (_, viewModel) = DebugDataOptionsHiltArrangement() + .withSendFCMTokenClientRepositoryRegisterTokenFailure() + .arrange() + + viewModel.infoMessage.test { + // when + viewModel.forceSendFCMToken() + + // then + val result = awaitItem() + assertEquals(UIText.DynamicString("Can't register token, error: error message"), result) + } + } +} + +internal class DebugDataOptionsHiltArrangement { + + @MockK(relaxed = true) + lateinit var context: Context + + private val currentAccount: UserId = TestUser.SELF_USER_ID + + @MockK + lateinit var globalDataStore: GlobalDataStore + + @MockK + lateinit var updateApiVersions: UpdateApiVersionsScheduler + + @MockK + lateinit var mlsKeyPackageCount: MLSKeyPackageCountUseCase + + @MockK + lateinit var restartSlowSyncProcessForRecovery: RestartSlowSyncProcessForRecoveryUseCase + + @MockK + lateinit var checkCrlRevocationList: CheckCrlRevocationListUseCase + + @MockK + lateinit var getCurrentAnalyticsTrackingIdentifier: GetCurrentAnalyticsTrackingIdentifierUseCase + + @MockK + lateinit var sendFCMToken: SendFCMTokenUseCase + + private val viewModel by lazy { + DebugDataOptionsViewModelImpl( + context = context, + currentAccount = currentAccount, + globalDataStore = globalDataStore, + updateApiVersions = updateApiVersions, + mlsKeyPackageCount = mlsKeyPackageCount, + restartSlowSyncProcessForRecovery = restartSlowSyncProcessForRecovery, + checkCrlRevocationList = checkCrlRevocationList, + getCurrentAnalyticsTrackingIdentifier = getCurrentAnalyticsTrackingIdentifier, + sendFCMToken = sendFCMToken, + dispatcherProvider = TestDispatcherProvider(), + ) + } + + init { + MockKAnnotations.init(this, relaxUnitFun = true) + Dispatchers.setMain(UnconfinedTestDispatcher()) + + every { + globalDataStore.isEncryptedProteusStorageEnabled() + } returns flowOf(true) + coEvery { + mlsKeyPackageCount() + } returns MLSKeyPackageCountResult.Success(ClientId("clientId"), 1, false) + coEvery { + getCurrentAnalyticsTrackingIdentifier() + } returns "trackingId" + mockkStatic("com.wire.android.util.FileUtilKt") + every { + context.getDeviceIdString() + } returns "deviceId" + every { + context.getGitBuildId() + } returns "gitBuildId" + coEvery { + globalDataStore.getUserMigrationStatus(TestUser.SELF_USER_ID.value) + } returns flowOf(UserMigrationStatus.NoNeed) + } + + fun arrange() = this to viewModel + + fun withSendFCMTokenSuccess() = apply { + coEvery { + sendFCMToken() + } returns Either.Right(Unit) + } + + suspend fun withSendFCMTokenClientIdFailure() = apply { + coEvery { + sendFCMToken() + } returns Either.Left(SendFCMTokenError(SendFCMTokenError.Reason.CANT_GET_CLIENT_ID, "error message")) + } + + suspend fun withSendFCMTokenNotificationTokenFailure() = apply { + coEvery { + sendFCMToken() + } returns Either.Left(SendFCMTokenError(SendFCMTokenError.Reason.CANT_GET_NOTIFICATION_TOKEN, "error message")) + } + + suspend fun withSendFCMTokenClientRepositoryRegisterTokenFailure() = apply { + coEvery { + sendFCMToken() + } returns Either.Left(SendFCMTokenError(SendFCMTokenError.Reason.CANT_REGISTER_TOKEN, "error message")) + } +} From 0fd62cc4c0ba87f5ddff299b6c7c239d6849da9c Mon Sep 17 00:00:00 2001 From: Damian Kaczmarek Date: Fri, 4 Oct 2024 12:57:13 +0200 Subject: [PATCH 2/5] checkout to kalium branch --- kalium | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kalium b/kalium index 873cf34ed0b..abb5bf005c7 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit 873cf34ed0bf9a69af53ba9f9122006357ee2c78 +Subproject commit abb5bf005c73ae280db590976e8c5d8ac54ae119 From d570f8bb614eb131cadb56e678fec6c9dba71ba2 Mon Sep 17 00:00:00 2001 From: Damian Kaczmarek Date: Mon, 7 Oct 2024 09:09:42 +0200 Subject: [PATCH 3/5] CR - only in private build --- .../wire/android/ui/debug/DebugDataOptions.kt | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptions.kt b/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptions.kt index 106ab474818..756669e1442 100644 --- a/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptions.kt +++ b/app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptions.kt @@ -461,26 +461,28 @@ private fun DebugToolsOptions( } ) - RowItemTemplate( - modifier = Modifier.wrapContentWidth(), - title = { - Text( - style = MaterialTheme.wireTypography.body01, - color = MaterialTheme.wireColorScheme.onBackground, - text = stringResource(R.string.debug_settings_register_fcm_push_token), - modifier = Modifier.padding(start = dimensions().spacing8x) - ) - }, - actions = { - WirePrimaryButton( - minSize = MaterialTheme.wireDimensions.buttonMediumMinSize, - minClickableSize = MaterialTheme.wireDimensions.buttonMinClickableSize, - onClick = onResendFCMToken, - text = stringResource(R.string.debug_settings_force_api_versioning_update_button_text), - fillMaxWidth = false - ) - } - ) + if (BuildConfig.PRIVATE_BUILD) { + RowItemTemplate( + modifier = Modifier.wrapContentWidth(), + title = { + Text( + style = MaterialTheme.wireTypography.body01, + color = MaterialTheme.wireColorScheme.onBackground, + text = stringResource(R.string.debug_settings_register_fcm_push_token), + modifier = Modifier.padding(start = dimensions().spacing8x) + ) + }, + actions = { + WirePrimaryButton( + minSize = MaterialTheme.wireDimensions.buttonMediumMinSize, + minClickableSize = MaterialTheme.wireDimensions.buttonMinClickableSize, + onClick = onResendFCMToken, + text = stringResource(R.string.debug_settings_force_api_versioning_update_button_text), + fillMaxWidth = false + ) + } + ) + } } } From 6973fc36b122432ec7b08242e77b730e284d3606 Mon Sep 17 00:00:00 2001 From: Damian Kaczmarek Date: Tue, 8 Oct 2024 11:59:37 +0200 Subject: [PATCH 4/5] checkout kalium develop --- kalium | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kalium b/kalium index abb5bf005c7..75b92ab865e 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit abb5bf005c73ae280db590976e8c5d8ac54ae119 +Subproject commit 75b92ab865e75c4dbefe42feef662b85ac040dd4 From 773d9f3dfbc4dea254f3285aceb13bdaf17789c4 Mon Sep 17 00:00:00 2001 From: Damian Kaczmarek Date: Thu, 10 Oct 2024 10:39:11 +0200 Subject: [PATCH 5/5] test restart