diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea49da6400a..90c4b4bc622 100755 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -240,7 +240,7 @@ jobs: - name: Spotless check quest application run: ./gradlew -PlocalPropertiesFile=local.properties :quest:spotlessCheck --stacktrace :quest:ktlintCheck --stacktrace - working-directory: android + working-directory: android - name: Load AVD cache uses: actions/cache@v4 @@ -272,7 +272,11 @@ jobs: force-avd-creation: true emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true - script: ./gradlew clean -PlocalPropertiesFile=local.properties :quest:fhircoreJacocoReport --info -Pandroid.testInstrumentationRunnerArguments.notPackage=org.smartregister.fhircore.quest.performance + script: ./gradlew clean -PlocalPropertiesFile=local.properties :quest:connectedOpensrpDebugAndroidTest --stacktrace -Pandroid.testInstrumentationRunnerArguments.notPackage=org.smartregister.fhircore.quest.performance + + - name: Test UnitTest + run: ./gradlew clean -PlocalPropertiesFile=local.properties :quest:testOpensrpDebugUnitTest --stacktrace + working-directory: android - name: Run Quest module unit and instrumentation tests and generate aggregated coverage report (Disabled) if: false diff --git a/android/engine/src/main/res/values-es/strings.xml b/android/engine/src/main/res/values-es/strings.xml index 757d0475bb7..5ba9f19d9c2 100644 --- a/android/engine/src/main/res/values-es/strings.xml +++ b/android/engine/src/main/res/values-es/strings.xml @@ -55,6 +55,7 @@ Reintentar sincronización Sincronización en curso Cargando + Cargando… Mensaje de error al cerrar sesión: %1$s No se puede cerrar sesión: ya se ha cerrado sesión o el dispositivo está desconectado. No se pudo cargar la configuración. Inténtalo de nuevo más tarde diff --git a/android/engine/src/main/res/values-fr/strings.xml b/android/engine/src/main/res/values-fr/strings.xml index 5332ca15cda..c3ca7b188d6 100644 --- a/android/engine/src/main/res/values-fr/strings.xml +++ b/android/engine/src/main/res/values-fr/strings.xml @@ -55,6 +55,7 @@ Réessayer la synchronisation Synchronisation en cours Chargement + Chargement… Message d\'erreur de déconnexion %1$s Impossible de se déconnecter : Déjà déconnecté ou l\'appareil est hors ligne. Impossible de charger la configuration. Veuillez réessayer plus tard diff --git a/android/engine/src/main/res/values-in/strings.xml b/android/engine/src/main/res/values-in/strings.xml index 5933ffa823c..4200c79864d 100644 --- a/android/engine/src/main/res/values-in/strings.xml +++ b/android/engine/src/main/res/values-in/strings.xml @@ -52,6 +52,7 @@ Coba lagi sinkronisasi Sinkronisasi sedang berlangsung Memuat + Memuat… Pesan kesalahan logout: %1$s Tidak dapat logout: Sudah logout atau perangkat sedang offline. Tidak dapat memuat konfigurasi. Silakan coba lagi nanti diff --git a/android/engine/src/main/res/values-sw/strings.xml b/android/engine/src/main/res/values-sw/strings.xml index 0b80b4bf86c..becad88e545 100644 --- a/android/engine/src/main/res/values-sw/strings.xml +++ b/android/engine/src/main/res/values-sw/strings.xml @@ -45,6 +45,7 @@ Jaribu kusawazisha tena Kusawazisha inaendelea Inapakia + Inapakia… Hitilafu kounyesha fomu Hitilafu imetokea, haiwezi kuhifadhi fomu Badilisha picha diff --git a/android/engine/src/main/res/values/strings.xml b/android/engine/src/main/res/values/strings.xml index 7bc1d98de17..9003f2e8512 100644 --- a/android/engine/src/main/res/values/strings.xml +++ b/android/engine/src/main/res/values/strings.xml @@ -56,6 +56,7 @@ Retry sync Sync in progress Loading + Loading… Logout error message: %1$s Unable to logout: Already logged out or device is offline. Could not load configuration. Please try again later diff --git a/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/usersetting/UserSettingInsightScreenTest.kt b/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/usersetting/UserSettingInsightScreenTest.kt index b476d3c0d7d..b50e02d3123 100644 --- a/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/usersetting/UserSettingInsightScreenTest.kt +++ b/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/usersetting/UserSettingInsightScreenTest.kt @@ -18,6 +18,7 @@ package org.smartregister.fhircore.quest.integration.ui.usersetting import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.createEmptyComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText @@ -30,6 +31,7 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.smartregister.fhircore.engine.util.extension.DEFAULT_FORMAT_SDF_DD_MM_YYYY +import org.smartregister.fhircore.quest.ui.usersetting.CIRCULAR_PROGRESS_INDICATOR import org.smartregister.fhircore.quest.ui.usersetting.INSIGHT_UNSYNCED_DATA import org.smartregister.fhircore.quest.ui.usersetting.UserSettingInsightScreen @@ -100,8 +102,19 @@ class UserSettingInsightScreenTest { composeRule.onNodeWithTag(INSIGHT_UNSYNCED_DATA).assertDoesNotExist() } + @Test + fun testProgressIndicatorShowWhenFetchingTheData() { + val unsyncedResources = emptyList>() + initComposable( + unsyncedResourcesFlow = MutableStateFlow(unsyncedResources), + showProgressIndicator = true, + ) + composeRule.onNodeWithTag(CIRCULAR_PROGRESS_INDICATOR).assertExists().assertIsDisplayed() + } + private fun initComposable( unsyncedResourcesFlow: MutableSharedFlow>> = MutableSharedFlow(), + showProgressIndicator: Boolean = false, ) { scenario.onActivity { activity -> activity.setContent { @@ -118,6 +131,7 @@ class UserSettingInsightScreenTest { buildDate = "29 jan 2023", unsyncedResourcesFlow = unsyncedResourcesFlow, navController = rememberNavController(), + showProgressIndicator = showProgressIndicator, onRefreshRequest = {}, dateFormat = DEFAULT_FORMAT_SDF_DD_MM_YYYY, ) diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragment.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragment.kt index 8eac2841426..44636d522c8 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragment.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragment.kt @@ -21,6 +21,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.fragment.app.Fragment @@ -56,6 +57,8 @@ class UserInsightScreenFragment : Fragment() { buildDate = userSettingViewModel.getBuildDate(), unsyncedResourcesFlow = userSettingViewModel.unsyncedResourcesMutableSharedFlow, navController = findNavController(), + showProgressIndicator = + userSettingViewModel.showProgressIndicatorFlow.collectAsState().value, onRefreshRequest = { userSettingViewModel.fetchUnsyncedResources() }, dateFormat = userSettingViewModel.getDateFormat(), ) diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingInsightScreen.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingInsightScreen.kt index f6ed79d691b..de718ebb845 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingInsightScreen.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingInsightScreen.kt @@ -36,6 +36,7 @@ import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.Divider import androidx.compose.material.Icon import androidx.compose.material.IconButton @@ -77,6 +78,7 @@ import org.smartregister.fhircore.engine.util.extension.formatDate const val USER_INSIGHT_TOP_APP_BAR = "userInsightToAppBar" const val INSIGHT_UNSYNCED_DATA = "insightUnsyncedData" +const val CIRCULAR_PROGRESS_INDICATOR = "progressIndicator" @SuppressLint("UnusedMaterialScaffoldPaddingParameter") @Composable @@ -94,6 +96,7 @@ fun UserSettingInsightScreen( dividerColor: Color = DividerColor, unsyncedResourcesFlow: MutableSharedFlow>>, navController: NavController, + showProgressIndicator: Boolean = false, onRefreshRequest: () -> Unit, dateFormat: String = DEFAULT_FORMAT_SDF_DD_MM_YYYY, ) { @@ -123,7 +126,32 @@ fun UserSettingInsightScreen( horizontalAlignment = Alignment.Start, contentPadding = PaddingValues(vertical = 24.dp, horizontal = 16.dp), ) { - if (unsyncedResources.isNotEmpty()) { + if (showProgressIndicator) { + item { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth(), + ) { + Text( + text = stringResource(id = R.string.loading_ellipsis), + style = TextStyle(color = Color.Black, fontSize = 20.sp), + fontWeight = FontWeight.Bold, + ) + Spacer(modifier = Modifier.width(8.dp)) + CircularProgressIndicator( + modifier = + Modifier.testTag(CIRCULAR_PROGRESS_INDICATOR).size(24.dp).wrapContentWidth(), + strokeWidth = 1.6.dp, + ) + } + } + item { + Spacer(modifier = Modifier.height(16.dp)) + Divider(color = dividerColor) + Spacer(modifier = Modifier.height(24.dp)) + } + } else if (unsyncedResources.isNotEmpty()) { item { Text( text = stringResource(id = R.string.unsynced_resources), @@ -368,6 +396,7 @@ fun UserSettingInsightScreenPreview() { buildDate = "29 Jan 2023", unsyncedResourcesFlow = MutableSharedFlow(), navController = rememberNavController(), + showProgressIndicator = true, onRefreshRequest = {}, dateFormat = DEFAULT_FORMAT_SDF_DD_MM_YYYY, ) diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingScreen.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingScreen.kt index b141d041251..5b77487a839 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingScreen.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingScreen.kt @@ -93,7 +93,6 @@ import org.smartregister.fhircore.engine.ui.theme.LighterBlue import org.smartregister.fhircore.engine.ui.theme.LoginDarkColor import org.smartregister.fhircore.engine.util.annotation.PreviewWithBackgroundExcludeGenerated import org.smartregister.fhircore.engine.util.extension.appVersion -import org.smartregister.fhircore.quest.ui.pin.CIRCULAR_PROGRESS_INDICATOR const val RESET_DATABASE_DIALOG = "resetDatabaseDialog" const val USER_SETTING_ROW_LOGOUT = "userSettingRowLogout" diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/robolectric/RobolectricTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/robolectric/RobolectricTest.kt index 0698d2978b6..56902369030 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/robolectric/RobolectricTest.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/robolectric/RobolectricTest.kt @@ -49,6 +49,7 @@ import org.junit.Rule import org.junit.runner.RunWith import org.robolectric.Shadows import org.robolectric.annotation.Config +import org.robolectric.junit.rules.TimeoutRule import org.robolectric.util.ReflectionHelpers import org.smartregister.fhircore.engine.util.extension.SDF_YYYY_MM_DD import org.smartregister.fhircore.engine.util.extension.formatDate @@ -69,6 +70,8 @@ abstract class RobolectricTest { @get:Rule(order = 20) val fhirEngineProviderTestRule = FhirEngineProviderTestRule() + @get:Rule(order = 38) val globalTimeoutRule: TimeoutRule = TimeoutRule.seconds(900) // 15 minutes + /** Get the liveData value by observing but wait for 3 seconds if not ready then stop observing */ @Throws(InterruptedException::class) fun getLiveDataValue(liveData: LiveData): T? { diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragmentTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragmentTest.kt index 92e24359b63..820f1606810 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragmentTest.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragmentTest.kt @@ -16,124 +16,95 @@ package org.smartregister.fhircore.quest.ui.usersetting -import android.content.Context -import android.os.Bundle import android.view.View import androidx.core.view.isVisible +import androidx.fragment.app.commitNow +import androidx.navigation.Navigation import androidx.navigation.testing.TestNavHostController -import androidx.test.core.app.ApplicationProvider -import androidx.work.WorkManager import dagger.hilt.android.testing.BindValue import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest -import dagger.hilt.android.testing.HiltTestApplication import io.mockk.mockk -import io.mockk.spyk -import javax.inject.Inject import org.junit.Assert import org.junit.Before import org.junit.Rule import org.junit.Test +import org.robolectric.Robolectric import org.smartregister.fhircore.engine.R -import org.smartregister.fhircore.engine.configuration.app.ConfigService -import org.smartregister.fhircore.engine.data.remote.fhir.resource.FhirResourceDataSource -import org.smartregister.fhircore.engine.data.remote.fhir.resource.FhirResourceService -import org.smartregister.fhircore.engine.datastore.PreferenceDataStore -import org.smartregister.fhircore.engine.sync.SyncBroadcaster -import org.smartregister.fhircore.engine.util.DispatcherProvider -import org.smartregister.fhircore.engine.util.SecureSharedPreference -import org.smartregister.fhircore.engine.util.SharedPreferencesHelper -import org.smartregister.fhircore.quest.app.AppConfigService +import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry +import org.smartregister.fhircore.engine.util.test.HiltActivityForTest import org.smartregister.fhircore.quest.app.fakes.Faker -import org.smartregister.fhircore.quest.launchFragmentInHiltContainer import org.smartregister.fhircore.quest.robolectric.RobolectricTest -import org.smartregister.fhircore.quest.ui.login.AccountAuthenticator @HiltAndroidTest class UserInsightScreenFragmentTest : RobolectricTest() { @get:Rule(order = 0) var hiltRule = HiltAndroidRule(this) - @BindValue var configurationRegistry = Faker.buildTestConfigurationRegistry() + @BindValue + val configurationRegistry: ConfigurationRegistry = Faker.buildTestConfigurationRegistry() - @Inject lateinit var testDispatcherProvider: DispatcherProvider + @BindValue lateinit var userSettingViewModel: UserSettingViewModel - @Inject lateinit var workManager: WorkManager - - @Inject lateinit var preferenceDataStore: PreferenceDataStore - private val navController = TestNavHostController(ApplicationProvider.getApplicationContext()) - private val context = ApplicationProvider.getApplicationContext() - private val resourceService: FhirResourceService = mockk() - private val application: Context = ApplicationProvider.getApplicationContext() - private var sharedPreferencesHelper: SharedPreferencesHelper - private var configService: ConfigService - private var fhirResourceDataSource: FhirResourceDataSource - private lateinit var syncBroadcaster: SyncBroadcaster - private lateinit var userSettingViewModel: UserSettingViewModel - private lateinit var accountAuthenticator: AccountAuthenticator - private lateinit var secureSharedPreference: SecureSharedPreference - - init { - sharedPreferencesHelper = SharedPreferencesHelper(context = context, gson = mockk()) - configService = AppConfigService(context = context) - fhirResourceDataSource = spyk(FhirResourceDataSource(resourceService)) - } + private val activityController = Robolectric.buildActivity(HiltActivityForTest::class.java) @Before - @kotlinx.coroutines.ExperimentalCoroutinesApi fun setUp() { hiltRule.inject() - accountAuthenticator = mockk() - secureSharedPreference = mockk() - sharedPreferencesHelper = mockk() - syncBroadcaster = - SyncBroadcaster( - configurationRegistry, - fhirEngine = mockk(), - dispatcherProvider = testDispatcherProvider, - syncListenerManager = mockk(relaxed = true), - workManager = workManager, - context = application, - ) - userSettingViewModel = - UserSettingViewModel( - fhirEngine = mockk(), - syncBroadcaster = syncBroadcaster, - accountAuthenticator = accountAuthenticator, - secureSharedPreference = secureSharedPreference, - sharedPreferencesHelper = sharedPreferencesHelper, - preferenceDataStore = preferenceDataStore, - configurationRegistry = configurationRegistry, - workManager = mockk(relaxed = true), - dispatcherProvider = testDispatcherProvider, - ) + userSettingViewModel = mockk(relaxed = true) } @Test fun testUserSettingViewModelReturnsCorrectViewModelInstance() { - launchFragmentInHiltContainer( - Bundle(), - R.style.AppTheme, - navController, - ) { - Assert.assertNotNull(this) - Assert.assertNotNull((this as UserInsightScreenFragment).userSettingViewModel) - Assert.assertEquals(userSettingViewModel, userSettingViewModel) + activityController.create().resume() + val activity = activityController.get() + val navHostController = TestNavHostController(activity) + val fragment = + UserInsightScreenFragment().apply { + viewLifecycleOwnerLiveData.observeForever { + if (it != null) { + navHostController.setGraph( + org.smartregister.fhircore.quest.R.navigation.application_nav_graph, + ) + Navigation.setViewNavController(requireView(), navHostController) + } + } + } + activity.supportFragmentManager.run { + commitNow { + add(android.R.id.content, fragment, UserInsightScreenFragment::class.java.simpleName) + } + executePendingTransactions() } + Assert.assertEquals(userSettingViewModel, fragment.userSettingViewModel) } @Test - fun testUserSettinViewIsRenderedCorrectlyByOnCreateView() { - launchFragmentInHiltContainer( - Bundle(), - R.style.AppTheme, - navController, - ) { - this.view!!.findViewWithTag(USER_INSIGHT_TOP_APP_BAR)?.let { - Assert.assertTrue(it.isVisible) - Assert.assertTrue(it.isShown) + fun testUserInsightScreenViewIsRenderedCorrectlyByOnCreateView() { + activityController.create().resume() + val activity = activityController.get() + val navHostController = TestNavHostController(activity) + val fragment = + UserInsightScreenFragment().apply { + viewLifecycleOwnerLiveData.observeForever { + if (it != null) { + navHostController.setGraph( + org.smartregister.fhircore.quest.R.navigation.application_nav_graph, + ) + Navigation.setViewNavController(requireView(), navHostController) + } + } + } + activity.supportFragmentManager.run { + commitNow { + add(android.R.id.content, fragment, UserInsightScreenFragment::class.java.simpleName) } + executePendingTransactions() + } + fragment.view!!.findViewWithTag(USER_INSIGHT_TOP_APP_BAR)?.let { + Assert.assertTrue(it.isVisible) + Assert.assertTrue(it.isShown) } } } diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingFragmentTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingFragmentTest.kt index 6b7b2f415c8..d3f3a44f576 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingFragmentTest.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingFragmentTest.kt @@ -16,116 +16,90 @@ package org.smartregister.fhircore.quest.ui.usersetting -import android.content.Context -import android.os.Bundle import android.view.View import androidx.core.view.isVisible +import androidx.fragment.app.commitNow +import androidx.navigation.Navigation import androidx.navigation.testing.TestNavHostController -import androidx.test.core.app.ApplicationProvider -import androidx.work.WorkManager import dagger.hilt.android.testing.BindValue import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest -import dagger.hilt.android.testing.HiltTestApplication import io.mockk.mockk -import io.mockk.spyk -import javax.inject.Inject import org.junit.Assert import org.junit.Before import org.junit.Rule import org.junit.Test +import org.robolectric.Robolectric import org.smartregister.fhircore.engine.R -import org.smartregister.fhircore.engine.configuration.app.ConfigService -import org.smartregister.fhircore.engine.data.remote.fhir.resource.FhirResourceDataSource -import org.smartregister.fhircore.engine.data.remote.fhir.resource.FhirResourceService -import org.smartregister.fhircore.engine.datastore.PreferenceDataStore -import org.smartregister.fhircore.engine.sync.SyncBroadcaster -import org.smartregister.fhircore.engine.util.DispatcherProvider -import org.smartregister.fhircore.engine.util.SecureSharedPreference -import org.smartregister.fhircore.engine.util.SharedPreferencesHelper -import org.smartregister.fhircore.quest.app.AppConfigService +import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry +import org.smartregister.fhircore.engine.util.test.HiltActivityForTest import org.smartregister.fhircore.quest.app.fakes.Faker -import org.smartregister.fhircore.quest.launchFragmentInHiltContainer import org.smartregister.fhircore.quest.robolectric.RobolectricTest -import org.smartregister.fhircore.quest.ui.login.AccountAuthenticator @HiltAndroidTest class UserSettingFragmentTest : RobolectricTest() { @get:Rule(order = 0) var hiltRule = HiltAndroidRule(this) - @BindValue var configurationRegistry = Faker.buildTestConfigurationRegistry() + @BindValue + val configurationRegistry: ConfigurationRegistry = Faker.buildTestConfigurationRegistry() - @Inject lateinit var dispatcherProvider: DispatcherProvider + @BindValue lateinit var userSettingViewModel: UserSettingViewModel - @Inject lateinit var workManager: WorkManager - - private val navController = TestNavHostController(ApplicationProvider.getApplicationContext()) - private val context = ApplicationProvider.getApplicationContext() - private val resourceService: FhirResourceService = mockk() - private val application: Context = ApplicationProvider.getApplicationContext() - private var sharedPreferencesHelper: SharedPreferencesHelper - private var configService: ConfigService - private var fhirResourceDataSource: FhirResourceDataSource - private lateinit var syncBroadcaster: SyncBroadcaster - private lateinit var userSettingViewModel: UserSettingViewModel - private lateinit var accountAuthenticator: AccountAuthenticator - private lateinit var secureSharedPreference: SecureSharedPreference - private lateinit var preferenceDataStore: PreferenceDataStore - - init { - sharedPreferencesHelper = SharedPreferencesHelper(context = context, gson = mockk()) - configService = AppConfigService(context = context) - fhirResourceDataSource = spyk(FhirResourceDataSource(resourceService)) - } + private val activityController = Robolectric.buildActivity(HiltActivityForTest::class.java) @Before - @kotlinx.coroutines.ExperimentalCoroutinesApi fun setUp() { hiltRule.inject() - accountAuthenticator = mockk() - secureSharedPreference = mockk() - sharedPreferencesHelper = mockk() - preferenceDataStore = mockk() - syncBroadcaster = - SyncBroadcaster( - configurationRegistry, - fhirEngine = mockk(), - dispatcherProvider = dispatcherProvider, - syncListenerManager = mockk(relaxed = true), - workManager = workManager, - context = application, - ) - userSettingViewModel = - UserSettingViewModel( - fhirEngine = mockk(), - syncBroadcaster = syncBroadcaster, - accountAuthenticator = accountAuthenticator, - secureSharedPreference = secureSharedPreference, - sharedPreferencesHelper = sharedPreferencesHelper, - preferenceDataStore = preferenceDataStore, - configurationRegistry = configurationRegistry, - workManager = mockk(relaxed = true), - dispatcherProvider = dispatcherProvider, - ) + userSettingViewModel = mockk(relaxed = true) } @Test fun assertGetUserSettingViewModelReturnsCorrectViewModelInstance() { - launchFragmentInHiltContainer(Bundle(), R.style.AppTheme, navController) { - Assert.assertNotNull(this) - Assert.assertNotNull((this as UserSettingFragment).userSettingViewModel) - Assert.assertEquals(userSettingViewModel, userSettingViewModel) + activityController.create().resume() + val activity = activityController.get() + val navHostController = TestNavHostController(activity) + val fragment = + UserSettingFragment().apply { + viewLifecycleOwnerLiveData.observeForever { + if (it != null) { + navHostController.setGraph( + org.smartregister.fhircore.quest.R.navigation.application_nav_graph, + ) + Navigation.setViewNavController(requireView(), navHostController) + } + } + } + activity.supportFragmentManager.run { + commitNow { add(android.R.id.content, fragment, UserSettingFragment::class.java.simpleName) } + executePendingTransactions() } + Assert.assertEquals(userSettingViewModel, fragment.userSettingViewModel) } @Test fun testOnCreateViewRendersUserSettingFragmentCorrectly() { - launchFragmentInHiltContainer(Bundle(), R.style.AppTheme, navController) { - this.view!!.findViewWithTag(USER_SETTING_ROW_LOGOUT)?.let { - Assert.assertTrue(it.isVisible) - Assert.assertTrue(it.isShown) + activityController.create().resume() + val activity = activityController.get() + val navHostController = TestNavHostController(activity) + val fragment = + UserSettingFragment().apply { + viewLifecycleOwnerLiveData.observeForever { + if (it != null) { + navHostController.setGraph( + org.smartregister.fhircore.quest.R.navigation.application_nav_graph, + ) + Navigation.setViewNavController(requireView(), navHostController) + } + } } + activity.supportFragmentManager.run { + commitNow { add(android.R.id.content, fragment, UserSettingFragment::class.java.simpleName) } + executePendingTransactions() + } + fragment.view!!.findViewWithTag(USER_SETTING_ROW_LOGOUT)?.let { + Assert.assertTrue(it.isVisible) + Assert.assertTrue(it.isShown) } } }