diff --git a/app/src/main/java/org/dhis2/usescases/login/LoginActivity.kt b/app/src/main/java/org/dhis2/usescases/login/LoginActivity.kt index a119649cfc..2caaa00e61 100644 --- a/app/src/main/java/org/dhis2/usescases/login/LoginActivity.kt +++ b/app/src/main/java/org/dhis2/usescases/login/LoginActivity.kt @@ -122,6 +122,7 @@ class LoginActivity : ActivityGlobalAbstract(), LoginContracts.View { override fun onDbImportFinished() { showLoginProgress(false) + blockLoginInfo() } companion object { diff --git a/app/src/main/java/org/dhis2/usescases/login/LoginModule.kt b/app/src/main/java/org/dhis2/usescases/login/LoginModule.kt index 39571c7b39..e5b14d772d 100644 --- a/app/src/main/java/org/dhis2/usescases/login/LoginModule.kt +++ b/app/src/main/java/org/dhis2/usescases/login/LoginModule.kt @@ -11,6 +11,7 @@ import org.dhis2.commons.prefs.PreferenceProvider import org.dhis2.commons.reporting.CrashReportController import org.dhis2.commons.resources.ResourceManager import org.dhis2.commons.schedulers.SchedulerProvider +import org.dhis2.commons.viewmodel.DispatcherProvider import org.dhis2.data.fingerprint.FingerPrintController import org.dhis2.data.server.UserManager import org.dhis2.usescases.login.auth.OpenIdProviders @@ -29,6 +30,7 @@ class LoginModule( preferenceProvider: PreferenceProvider, resourceManager: ResourceManager, schedulerProvider: SchedulerProvider, + dispatcherProvider: DispatcherProvider, fingerPrintController: FingerPrintController, analyticsHelper: AnalyticsHelper, crashReportController: CrashReportController, @@ -41,6 +43,7 @@ class LoginModule( preferenceProvider, resourceManager, schedulerProvider, + dispatcherProvider, fingerPrintController, analyticsHelper, crashReportController, diff --git a/app/src/main/java/org/dhis2/usescases/login/LoginViewModel.kt b/app/src/main/java/org/dhis2/usescases/login/LoginViewModel.kt index cba9074734..c138246a17 100644 --- a/app/src/main/java/org/dhis2/usescases/login/LoginViewModel.kt +++ b/app/src/main/java/org/dhis2/usescases/login/LoginViewModel.kt @@ -27,6 +27,7 @@ import org.dhis2.commons.prefs.SECURE_USER_NAME import org.dhis2.commons.reporting.CrashReportController import org.dhis2.commons.resources.ResourceManager import org.dhis2.commons.schedulers.SchedulerProvider +import org.dhis2.commons.viewmodel.DispatcherProvider import org.dhis2.data.fingerprint.FingerPrintController import org.dhis2.data.fingerprint.Type import org.dhis2.data.server.UserManager @@ -39,7 +40,6 @@ import org.dhis2.utils.analytics.DATA_STORE_ANALYTICS_PERMISSION_KEY import org.dhis2.utils.analytics.LOGIN import org.dhis2.utils.analytics.SERVER_QR_SCANNER import org.dhis2.utils.analytics.USER_PROPERTY_SERVER -import org.hisp.dhis.android.core.D2Manager import org.hisp.dhis.android.core.maintenance.D2Error import org.hisp.dhis.android.core.maintenance.D2ErrorCode import org.hisp.dhis.android.core.systeminfo.SystemInfo @@ -55,6 +55,7 @@ class LoginViewModel( private val preferenceProvider: PreferenceProvider, private val resourceManager: ResourceManager, private val schedulers: SchedulerProvider, + private val dispatchers: DispatcherProvider, private val fingerPrintController: FingerPrintController, private val analyticsHelper: AnalyticsHelper, private val crashReportController: CrashReportController, @@ -560,24 +561,26 @@ class LoginViewModel( } fun onImportDataBase(file: File) { - viewModelScope.launch { - val importResult = async { - D2Manager.getD2().maintenanceModule().databaseImportExport().importDatabase(file) - } - val importedMetadata = try { - importResult.await() - } catch (e: Exception) { - view.displayMessage(resourceManager.parseD2Error(e)) - Timber.e(e) - null - } - importedMetadata?.let { - setAccountInfo(it.serverUrl, it.username) - view.setUrl(it.serverUrl) - view.setUser(it.username) - displayManageAccount() + userManager?.let { + viewModelScope.launch { + val importResult = async(dispatchers.io()) { + it.d2.maintenanceModule().databaseImportExport().importDatabase(file) + } + val importedMetadata = try { + importResult.await() + } catch (e: Exception) { + view.displayMessage(resourceManager.parseD2Error(e)) + Timber.e(e) + null + } + importedMetadata?.let { + setAccountInfo(it.serverUrl, it.username) + view.setUrl(it.serverUrl) + view.setUser(it.username) + displayManageAccount() + } + view.onDbImportFinished() } - view.onDbImportFinished() } } } diff --git a/app/src/main/java/org/dhis2/usescases/login/LoginViewModelFactory.kt b/app/src/main/java/org/dhis2/usescases/login/LoginViewModelFactory.kt index 0f23f21294..cf1b998e88 100644 --- a/app/src/main/java/org/dhis2/usescases/login/LoginViewModelFactory.kt +++ b/app/src/main/java/org/dhis2/usescases/login/LoginViewModelFactory.kt @@ -7,6 +7,7 @@ import org.dhis2.commons.prefs.PreferenceProvider import org.dhis2.commons.reporting.CrashReportController import org.dhis2.commons.resources.ResourceManager import org.dhis2.commons.schedulers.SchedulerProvider +import org.dhis2.commons.viewmodel.DispatcherProvider import org.dhis2.data.fingerprint.FingerPrintController import org.dhis2.data.server.UserManager import org.dhis2.utils.analytics.AnalyticsHelper @@ -16,6 +17,7 @@ class LoginViewModelFactory( private val preferenceProvider: PreferenceProvider, private val resources: ResourceManager, private val schedulerProvider: SchedulerProvider, + private val dispatcherProvider: DispatcherProvider, private val fingerPrintController: FingerPrintController, private val analyticsHelper: AnalyticsHelper, private val crashReportController: CrashReportController, @@ -28,6 +30,7 @@ class LoginViewModelFactory( preferenceProvider, resources, schedulerProvider, + dispatcherProvider, fingerPrintController, analyticsHelper, crashReportController, diff --git a/app/src/test/java/org/dhis2/usescases/login/LoginViewModelTest.kt b/app/src/test/java/org/dhis2/usescases/login/LoginViewModelTest.kt index c71f384853..be94b64ffe 100644 --- a/app/src/test/java/org/dhis2/usescases/login/LoginViewModelTest.kt +++ b/app/src/test/java/org/dhis2/usescases/login/LoginViewModelTest.kt @@ -4,7 +4,11 @@ import androidx.arch.core.executor.testing.InstantTaskExecutorRule import io.reactivex.Completable import io.reactivex.Observable import io.reactivex.Single +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.setMain import org.dhis2.commons.Constants.PREFS_URLS import org.dhis2.commons.Constants.PREFS_USERS import org.dhis2.commons.Constants.USER_ASKED_CRASHLYTICS @@ -15,7 +19,9 @@ import org.dhis2.commons.prefs.SECURE_PASS import org.dhis2.commons.prefs.SECURE_SERVER_URL import org.dhis2.commons.prefs.SECURE_USER_NAME import org.dhis2.commons.reporting.CrashReportController +import org.dhis2.commons.resources.ResourceManager import org.dhis2.commons.schedulers.SchedulerProvider +import org.dhis2.commons.viewmodel.DispatcherProvider import org.dhis2.data.fingerprint.FingerPrintController import org.dhis2.data.fingerprint.FingerPrintResult import org.dhis2.data.fingerprint.Type @@ -28,11 +34,13 @@ import org.dhis2.utils.analytics.AnalyticsHelper import org.dhis2.utils.analytics.CLICK import org.dhis2.utils.analytics.LOGIN import org.dhis2.utils.analytics.SERVER_QR_SCANNER +import org.hisp.dhis.android.core.arch.db.access.DatabaseExportMetadata import org.hisp.dhis.android.core.systeminfo.SystemInfo import org.hisp.dhis.android.core.user.User import org.hisp.dhis.android.core.user.openid.IntentWithRequestCode import org.hisp.dhis.android.core.user.openid.OpenIDConnectConfig import org.junit.Assert.assertTrue +import org.junit.Before import org.junit.Rule import org.junit.Test import org.mockito.Mockito @@ -45,6 +53,8 @@ import org.mockito.kotlin.verify import org.mockito.kotlin.verifyNoMoreInteractions import org.mockito.kotlin.whenever import retrofit2.Response +import java.io.File + class LoginViewModelTest { @get:Rule @@ -66,12 +76,29 @@ class LoginViewModelTest { private val network: NetworkUtils = mock() private lateinit var loginViewModel: LoginViewModel private val openidconfig: OpenIDConnectConfig = mock() + private val resourceManager: ResourceManager = mock() + private val testingDispatcher = StandardTestDispatcher() + private val dispatcherProvider = object : DispatcherProvider { + override fun io(): CoroutineDispatcher { + return testingDispatcher + } + + override fun computation(): CoroutineDispatcher { + return testingDispatcher + } + + override fun ui(): CoroutineDispatcher { + return testingDispatcher + } + } private fun instantiateLoginViewModel() { loginViewModel = LoginViewModel( view, preferenceProvider, + resourceManager, schedulers, + dispatcherProvider, goldfinger, analyticsHelper, crashReportController, @@ -79,11 +106,14 @@ class LoginViewModelTest { userManager, ) } + private fun instantiateLoginViewModelWithNullUserManager() { loginViewModel = LoginViewModel( view, preferenceProvider, + resourceManager, schedulers, + dispatcherProvider, goldfinger, analyticsHelper, crashReportController, @@ -92,6 +122,12 @@ class LoginViewModelTest { ) } + @OptIn(ExperimentalCoroutinesApi::class) + @Before + fun setUp() { + Dispatchers.setMain(testingDispatcher) + } + @Test fun `Should go to MainActivity if user is already logged in`() { whenever(userManager.isUserLoggedIn) doReturn Observable.just(true) @@ -353,8 +389,8 @@ class LoginViewModelTest { fun `Should set server and username if user is logged`() { instantiateLoginViewModel() mockSystemInfo() - whenever(userManager.userName())doReturn Single.just("Username") - whenever(goldfinger.hasFingerPrint())doReturn true + whenever(userManager.userName()) doReturn Single.just("Username") + whenever(goldfinger.hasFingerPrint()) doReturn true whenever(preferenceProvider.contains(SECURE_SERVER_URL)) doReturn true loginViewModel.checkServerInfoAndShowBiometricButton() verify(view).setUrl("contextPath") @@ -389,12 +425,36 @@ class LoginViewModelTest { instantiateLoginViewModelWithNullUserManager() val openidconfig: OpenIDConnectConfig = mock() val it: IntentWithRequestCode = mock() - whenever(view.initLogin())doReturn userManager + whenever(view.initLogin()) doReturn userManager whenever(userManager.logIn(openidconfig)) doReturn Observable.just(it) instantiateLoginViewModelWithNullUserManager() loginViewModel.openIdLogin(openidconfig) verify(view).openOpenIDActivity(it) } + + @Test + fun `Should import database`() { + val mockedDatabase: File = mock() + + instantiateLoginViewModel() + whenever( + userManager.d2.maintenanceModule().databaseImportExport() + .importDatabase(mockedDatabase), + ) doReturn DatabaseExportMetadata( + 0, + "2024-01-01", + "serverUrl", + "userName", + false, + ) + + loginViewModel.onImportDataBase(mockedDatabase) + testingDispatcher.scheduler.advanceUntilIdle() + verify(view).setUrl("serverUrl") + verify(view).setUser("userName") + verify(view).onDbImportFinished() + } + private fun mockSystemInfo(isUserLoggedIn: Boolean = true) { whenever(userManager.isUserLoggedIn) doReturn Observable.just(isUserLoggedIn) if (isUserLoggedIn) {