From f29d85cefa42cf5a8cfc73219d2804d93924f8c3 Mon Sep 17 00:00:00 2001 From: aurangzaibumer <35099184+aurangzaibumer@users.noreply.github.com> Date: Thu, 17 Oct 2024 22:30:43 +0500 Subject: [PATCH] Added Configurable Date Format For App (#3554) * added date format configurable and applied on sync time in navigation, setting screen and insight screen * Resolve CI build issue. Signed-off-by: Lentumunai-Mark * Run spotless fix Signed-off-by: Lentumunai-Mark * Resolve failing tests. Signed-off-by: Lentumunai-Mark * Add tests for uncovered functionality. Signed-off-by: Lentumunai-Mark --------- Signed-off-by: Lentumunai-Mark Co-authored-by: Lentumunai-Mark Co-authored-by: Benjamin Mwalimu --- .../app/ApplicationConfiguration.kt | 2 + .../util/extension/DateTimeExtension.kt | 61 +++++++++++++++++++ .../util/extension/DateTimeExtensionTest.kt | 22 +++++++ .../UserSettingInsightScreenTest.kt | 2 + .../configs/app/application_config.json | 3 +- .../quest/ui/main/AppMainViewModel.kt | 47 +++++++++++++- .../usersetting/UserInsightScreenFragment.kt | 3 +- .../ui/usersetting/UserSettingFragment.kt | 2 +- .../usersetting/UserSettingInsightScreen.kt | 7 ++- .../ui/usersetting/UserSettingViewModel.kt | 12 +++- .../quest/ui/main/AppMainActivityTest.kt | 5 +- .../quest/ui/main/AppMainViewModelTest.kt | 32 +++++++++- 12 files changed, 188 insertions(+), 10 deletions(-) diff --git a/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/app/ApplicationConfiguration.kt b/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/app/ApplicationConfiguration.kt index ce6ce3763f..27076b4a8f 100644 --- a/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/app/ApplicationConfiguration.kt +++ b/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/app/ApplicationConfiguration.kt @@ -21,6 +21,7 @@ import org.smartregister.fhircore.engine.configuration.ConfigType import org.smartregister.fhircore.engine.configuration.Configuration import org.smartregister.fhircore.engine.configuration.event.EventWorkflow import org.smartregister.fhircore.engine.domain.model.LauncherType +import org.smartregister.fhircore.engine.util.extension.DEFAULT_FORMAT_SDF_DD_MM_YYYY @Serializable data class ApplicationConfiguration( @@ -57,6 +58,7 @@ data class ApplicationConfiguration( id = null, ), val codingSystems: List = emptyList(), + var dateFormat: String = DEFAULT_FORMAT_SDF_DD_MM_YYYY, ) : Configuration() enum class SyncStrategy { diff --git a/android/engine/src/main/java/org/smartregister/fhircore/engine/util/extension/DateTimeExtension.kt b/android/engine/src/main/java/org/smartregister/fhircore/engine/util/extension/DateTimeExtension.kt index 9b05fd749f..567c848c79 100644 --- a/android/engine/src/main/java/org/smartregister/fhircore/engine/util/extension/DateTimeExtension.kt +++ b/android/engine/src/main/java/org/smartregister/fhircore/engine/util/extension/DateTimeExtension.kt @@ -29,6 +29,7 @@ import org.hl7.fhir.r4.model.DateTimeType import org.hl7.fhir.r4.model.DateType import org.ocpsoft.prettytime.PrettyTime import org.smartregister.fhircore.engine.R +import timber.log.Timber const val SDF_DD_MMM_YYYY = "dd-MMM-yyyy" const val SDF_YYYY_MM_DD = "yyyy-MM-dd" @@ -39,6 +40,9 @@ const val SDF_YYYY = "yyyy" const val SDF_D_MMM_YYYY_WITH_COMA = "d MMM, yyyy" const val SDFHH_MM = "HH:mm" const val SDF_E_MMM_DD_YYYY = "E, MMM dd yyyy" +const val DEFAULT_FORMAT_SDF_DD_MM_YYYY = "EEE, MMM dd - hh:mm a" +const val SDF_YYYY_MMM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss" +const val MMM_D_HH_MM_AA = "MMM d, hh:mm aa" fun yesterday(): Date = DateTimeType.now().apply { add(Calendar.DATE, -1) }.value @@ -149,3 +153,60 @@ fun calculateAge(date: Date, context: Context, localDateNow: LocalDate = LocalDa private fun Context.abbreviateString(resourceId: Int, content: Int) = if (content > 0) "$content${this.getString(resourceId).lowercase().abbreviate()} " else "" + +fun formatDate(timeMillis: Long, desireFormat: String): String { + return try { + // Try formatting with the provided format + val format = SimpleDateFormat(desireFormat, Locale.getDefault()) + val date = Date(timeMillis) + format.format(date) + } catch (e: Exception) { + // If formatting fails, fall back to the default format + val defaultFormat = SimpleDateFormat(DEFAULT_FORMAT_SDF_DD_MM_YYYY, Locale.getDefault()) + val date = Date(timeMillis) + defaultFormat.format(date) + } +} + +/** + * Reformats a given date string from its current format to a specified desired format. If the date + * string cannot be parsed in the provided current format, the method will return the original date + * string as a fallback. + * + * @param inputDateString The date string that needs to be reformatted. + * @param currentFormat The format in which the input date string is provided (e.g., "dd-MM-yyyy"). + * @param desiredFormat The format in which the output date string should be returned (default: + * "yyyy-MM-dd HH:mm:ss"). If no desired format is specified, it defaults to "yyyy-MM-dd + * HH:mm:ss". + * @return A string representing the date in the desired format if parsing succeeds, or the original + * input date string if parsing fails. + * + * Example usage: + * ``` + * val reformattedDate = reformatDate("08-10-2024 15:30", "dd-MM-yyyy HH:mm", "yyyy-MM-dd HH:mm:ss") + * println(reformattedDate) // Output: "2024-10-08 15:30:00" + * + * val invalidDate = reformatDate("InvalidDate", "dd-MM-yyyy", "yyyy-MM-dd") + * println(invalidDate) // Output: "InvalidDate" + * ``` + */ +fun reformatDate( + inputDateString: String, + currentFormat: String, + desiredFormat: String, +): String { + return try { + // Create a SimpleDateFormat with the current format of the input date + val inputDateFormat = SimpleDateFormat(currentFormat, Locale.getDefault()) + // Parse the input date string into a Date object + val date = inputDateFormat.parse(inputDateString) + // Create a SimpleDateFormat for the desired format + val outputDateFormat = SimpleDateFormat(desiredFormat, Locale.getDefault()) + // Format the date into the desired format and return the result + outputDateFormat.format(date ?: Date()) + } catch (e: Exception) { + // In case of any exception, return the original input date string + Timber.e(e) + inputDateString + } +} diff --git a/android/engine/src/test/java/org/smartregister/fhircore/engine/util/extension/DateTimeExtensionTest.kt b/android/engine/src/test/java/org/smartregister/fhircore/engine/util/extension/DateTimeExtensionTest.kt index a20342c18e..8b207c7464 100644 --- a/android/engine/src/test/java/org/smartregister/fhircore/engine/util/extension/DateTimeExtensionTest.kt +++ b/android/engine/src/test/java/org/smartregister/fhircore/engine/util/extension/DateTimeExtensionTest.kt @@ -137,4 +137,26 @@ class DateTimeExtensionTest : RobolectricTest() { fun isTodayWithDateYesterdayShouldReturnFalse() { assertFalse(yesterday().isToday()) } + + @Test + fun testReformatDateWithValidDate() { + val inputDateString = "2022-02-02" + val currentFormat = "yyyy-MM-dd" + val desiredFormat = "dd/MM/yyyy" + + val result = reformatDate(inputDateString, currentFormat, desiredFormat) + + assertEquals("02/02/2022", result) + } + + @Test + fun testReformatDateWithInvalidDateFormat() { + val inputDateString = "02/02/2022" + val currentFormat = "yyyy-MM-dd" + val desiredFormat = "dd/MM/yyyy" + + val result = reformatDate(inputDateString, currentFormat, desiredFormat) + + assertEquals(inputDateString, result) + } } 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 7e639d58da..b476d3c0d7 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 @@ -29,6 +29,7 @@ import org.junit.After 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.INSIGHT_UNSYNCED_DATA import org.smartregister.fhircore.quest.ui.usersetting.UserSettingInsightScreen @@ -118,6 +119,7 @@ class UserSettingInsightScreenTest { unsyncedResourcesFlow = unsyncedResourcesFlow, navController = rememberNavController(), onRefreshRequest = {}, + dateFormat = DEFAULT_FORMAT_SDF_DD_MM_YYYY, ) } this.activity = activity diff --git a/android/quest/src/main/assets/configs/app/application_config.json b/android/quest/src/main/assets/configs/app/application_config.json index cb7230ca1a..a4af956619 100644 --- a/android/quest/src/main/assets/configs/app/application_config.json +++ b/android/quest/src/main/assets/configs/app/application_config.json @@ -85,5 +85,6 @@ ], "logGpsLocation": [ "QUESTIONNAIRE" - ] + ], + "dateFormat": "MMM d, hh:mm aa" } diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModel.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModel.kt index 0a7fce88db..b8092861f7 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModel.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModel.kt @@ -74,8 +74,10 @@ import org.smartregister.fhircore.engine.util.SharedPreferencesHelper import org.smartregister.fhircore.engine.util.extension.countUnSyncedResources import org.smartregister.fhircore.engine.util.extension.extractLogicalIdUuid import org.smartregister.fhircore.engine.util.extension.fetchLanguages +import org.smartregister.fhircore.engine.util.extension.formatDate import org.smartregister.fhircore.engine.util.extension.getActivity import org.smartregister.fhircore.engine.util.extension.isDeviceOnline +import org.smartregister.fhircore.engine.util.extension.reformatDate import org.smartregister.fhircore.engine.util.extension.refresh import org.smartregister.fhircore.engine.util.extension.setAppLocale import org.smartregister.fhircore.engine.util.extension.showToast @@ -157,7 +159,7 @@ constructor( appTitle = applicationConfiguration.appTitle, currentLanguage = loadCurrentLanguage(), username = secureSharedPreference.retrieveSessionUsername() ?: "", - lastSyncTime = retrieveLastSyncTimestamp() ?: "", + lastSyncTime = getSyncTime(), languages = configurationRegistry.fetchLanguages(), navigationConfiguration = navigationConfiguration, registerCountMap = registerCountMap, @@ -166,6 +168,47 @@ constructor( countRegisterData() } + // todo - if we can move this method to somewhere else where it can be accessed easily on multiple + // view models + /** + * Retrieves the last sync time from shared preferences and returns it in a formatted way. This + * method handles both cases: + * 1. The time stored as a timestamp in milliseconds (preferred). + * 2. Backward compatibility where the time is stored in a formatted string. + * + * @return A formatted sync time string. + */ + fun getSyncTime(): String { + var result = "" + + // First, check if we have any previously stored sync time in SharedPreferences. + retrieveLastSyncTimestamp()?.let { storedDate -> + + // Try to treat the stored time as a timestamp (in milliseconds). + runCatching { + // Attempt to convert the stored date to Long (i.e., millis format) and format it. + result = + formatDate( + timeMillis = storedDate.toLong(), + desireFormat = applicationConfiguration.dateFormat, + ) + } + .onFailure { + // If conversion to Long fails, it's likely that the stored date is in a formatted string + // (backward compatibility). + // Reformat the stored date using the provided SYNC_TIMESTAMP_OUTPUT_FORMAT. + result = + reformatDate( + inputDateString = storedDate, + currentFormat = SYNC_TIMESTAMP_OUTPUT_FORMAT, + desiredFormat = applicationConfiguration.dateFormat, + ) + } + } + + // Return the result (either formatted time in millis or re-formatted backward-compatible date). + return result + } fun countRegisterData() { viewModelScope.launch { @@ -205,7 +248,7 @@ constructor( if (event.state is CurrentSyncJobStatus.Succeeded) { sharedPreferencesHelper.write( SharedPreferenceKey.LAST_SYNC_TIMESTAMP.name, - formatLastSyncTimestamp(event.state.timestamp), + event.state.timestamp.toInstant().toEpochMilli().toString(), ) retrieveAppMainUiState() viewModelScope.launch { retrieveAppMainUiState() } 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 c6100becda..8eac284142 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 @@ -53,10 +53,11 @@ class UserInsightScreenFragment : Fragment() { location = userSettingViewModel.practitionerLocation(), appVersionCode = userSettingViewModel.appVersionCode.toString(), appVersion = userSettingViewModel.appVersionName, - buildDate = userSettingViewModel.buildDate, + buildDate = userSettingViewModel.getBuildDate(), unsyncedResourcesFlow = userSettingViewModel.unsyncedResourcesMutableSharedFlow, navController = findNavController(), onRefreshRequest = { userSettingViewModel.fetchUnsyncedResources() }, + dateFormat = userSettingViewModel.getDateFormat(), ) } } diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingFragment.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingFragment.kt index bfd34b8a7b..ad7169aa85 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingFragment.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingFragment.kt @@ -101,7 +101,7 @@ class UserSettingFragment : Fragment(), OnSyncListener { userSettingViewModel.progressBarState.observeAsState(Pair(false, 0)).value, isDebugVariant = BuildConfig.DEBUG, mainNavController = findNavController(), - lastSyncTime = userSettingViewModel.retrieveLastSyncTimestamp(), + lastSyncTime = appMainViewModel.getSyncTime(), showProgressIndicatorFlow = userSettingViewModel.showProgressIndicatorFlow, dataMigrationVersion = userSettingViewModel.retrieveDataMigrationVersion(), enableManualSync = 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 8b854185aa..f6ed79d691 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 @@ -72,6 +72,8 @@ import kotlinx.coroutines.flow.MutableSharedFlow import org.smartregister.fhircore.engine.R import org.smartregister.fhircore.engine.ui.theme.DividerColor import org.smartregister.fhircore.engine.ui.theme.LoginDarkColor +import org.smartregister.fhircore.engine.util.extension.DEFAULT_FORMAT_SDF_DD_MM_YYYY +import org.smartregister.fhircore.engine.util.extension.formatDate const val USER_INSIGHT_TOP_APP_BAR = "userInsightToAppBar" const val INSIGHT_UNSYNCED_DATA = "insightUnsyncedData" @@ -93,6 +95,7 @@ fun UserSettingInsightScreen( unsyncedResourcesFlow: MutableSharedFlow>>, navController: NavController, onRefreshRequest: () -> Unit, + dateFormat: String = DEFAULT_FORMAT_SDF_DD_MM_YYYY, ) { val unsyncedResources = unsyncedResourcesFlow.collectAsState(initial = listOf()).value @@ -235,7 +238,8 @@ fun UserSettingInsightScreen( (if (Build.DEVICE.isNullOrEmpty()) "-" else Build.DEVICE), stringResource(R.string.os_version) to (if (Build.VERSION.BASE_OS.isNullOrEmpty()) "-" else Build.VERSION.BASE_OS), - stringResource(R.string.device_date) to (formatTimestamp(Build.TIME).ifEmpty { "-" }), + stringResource(R.string.device_date) to + (formatDate(Build.TIME, desireFormat = dateFormat).ifEmpty { "-" }), ) InsightInfoView( title = stringResource(id = R.string.device_info), @@ -365,6 +369,7 @@ fun UserSettingInsightScreenPreview() { unsyncedResourcesFlow = MutableSharedFlow(), navController = rememberNavController(), onRefreshRequest = {}, + dateFormat = DEFAULT_FORMAT_SDF_DD_MM_YYYY, ) } } diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingViewModel.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingViewModel.kt index 06538ffbac..8a5595fb2f 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingViewModel.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingViewModel.kt @@ -46,11 +46,13 @@ import org.smartregister.fhircore.engine.util.DispatcherProvider import org.smartregister.fhircore.engine.util.SecureSharedPreference import org.smartregister.fhircore.engine.util.SharedPreferenceKey import org.smartregister.fhircore.engine.util.SharedPreferencesHelper +import org.smartregister.fhircore.engine.util.extension.SDF_YYYY_MMM_DD_HH_MM_SS import org.smartregister.fhircore.engine.util.extension.countUnSyncedResources import org.smartregister.fhircore.engine.util.extension.fetchLanguages import org.smartregister.fhircore.engine.util.extension.getActivity import org.smartregister.fhircore.engine.util.extension.isDeviceOnline import org.smartregister.fhircore.engine.util.extension.launchActivityWithNoBackStackHistory +import org.smartregister.fhircore.engine.util.extension.reformatDate import org.smartregister.fhircore.engine.util.extension.refresh import org.smartregister.fhircore.engine.util.extension.setAppLocale import org.smartregister.fhircore.engine.util.extension.showToast @@ -89,7 +91,6 @@ constructor( val appVersionCode = BuildConfig.VERSION_CODE val appVersionName = BuildConfig.VERSION_NAME - val buildDate = BuildConfig.BUILD_DATE fun retrieveUsername(): String? = secureSharedPreference.retrieveSessionUsername() @@ -204,6 +205,15 @@ constructor( fun enabledDeviceToDeviceSync(): Boolean = applicationConfiguration.deviceToDeviceSync != null + fun getDateFormat() = applicationConfiguration.dateFormat + + fun getBuildDate() = + reformatDate( + inputDateString = BuildConfig.BUILD_DATE, + currentFormat = SDF_YYYY_MMM_DD_HH_MM_SS, + desiredFormat = applicationConfiguration.dateFormat, + ) + fun fetchUnsyncedResources() { viewModelScope.launch { withContext(dispatcherProvider.io()) { diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/main/AppMainActivityTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/main/AppMainActivityTest.kt index cde4637068..311c8d8146 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/main/AppMainActivityTest.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/main/AppMainActivityTest.kt @@ -124,14 +124,15 @@ class AppMainActivityTest : ActivityRobolectricTest() { } @Test - fun testOnSyncWithSyncStateSucceded() { + fun testOnSyncWithSyncStateSucceeded() { + // Arrange val viewModel = appMainActivity.appMainViewModel val stateSucceded = CurrentSyncJobStatus.Succeeded(OffsetDateTime.now()) appMainActivity.onSync(stateSucceded) Assert.assertEquals( viewModel.formatLastSyncTimestamp(timestamp = stateSucceded.timestamp), - viewModel.retrieveLastSyncTimestamp(), + viewModel.getSyncTime(), ) } diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModelTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModelTest.kt index b7d619b043..32fde4d404 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModelTest.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModelTest.kt @@ -71,13 +71,16 @@ import org.smartregister.fhircore.engine.util.DispatcherProvider import org.smartregister.fhircore.engine.util.SecureSharedPreference import org.smartregister.fhircore.engine.util.SharedPreferenceKey import org.smartregister.fhircore.engine.util.SharedPreferencesHelper +import org.smartregister.fhircore.engine.util.extension.formatDate import org.smartregister.fhircore.engine.util.extension.isDeviceOnline +import org.smartregister.fhircore.engine.util.extension.reformatDate import org.smartregister.fhircore.engine.util.extension.showToast import org.smartregister.fhircore.engine.util.test.HiltActivityForTest import org.smartregister.fhircore.quest.app.fakes.Faker import org.smartregister.fhircore.quest.navigation.MainNavigationScreen import org.smartregister.fhircore.quest.navigation.NavigationArg import org.smartregister.fhircore.quest.robolectric.RobolectricTest +import org.smartregister.fhircore.quest.ui.main.AppMainViewModel.Companion.SYNC_TIMESTAMP_OUTPUT_FORMAT import org.smartregister.fhircore.quest.ui.shared.models.QuestionnaireSubmission @HiltAndroidTest @@ -185,7 +188,7 @@ class AppMainViewModelTest : RobolectricTest() { ) Assert.assertEquals( appMainViewModel.formatLastSyncTimestamp(syncFinishedTimestamp), - sharedPreferencesHelper.read(SharedPreferenceKey.LAST_SYNC_TIMESTAMP.name, null), + appMainViewModel.getSyncTime(), ) coVerify { appMainViewModel.retrieveAppMainUiState() } } @@ -314,6 +317,33 @@ class AppMainViewModelTest : RobolectricTest() { } } + @Test + fun testGetSyncTimeWithMillisTimestamp() { + // Mocking a timestamp in milliseconds + val mockTimestamp = OffsetDateTime.now().toInstant().toEpochMilli().toString() + every { appMainViewModel.retrieveLastSyncTimestamp() } returns mockTimestamp + every { appMainViewModel.applicationConfiguration.dateFormat } returns "yyyy-MM-dd HH:mm:ss" + val syncTime = appMainViewModel.getSyncTime() + val expectedFormattedDate = + formatDate(mockTimestamp.toLong(), appMainViewModel.applicationConfiguration.dateFormat) + Assert.assertEquals(expectedFormattedDate, syncTime) + } + + @Test + fun testGetSyncTimeWithFormattedDate() { + val mockFormattedDate = "2023-10-10 10:10:10" + every { appMainViewModel.retrieveLastSyncTimestamp() } returns mockFormattedDate + every { appMainViewModel.applicationConfiguration.dateFormat } returns "yyyy-MM-dd" + val syncTime = appMainViewModel.getSyncTime() + val expectedReformattedDate = + reformatDate( + inputDateString = mockFormattedDate, + currentFormat = SYNC_TIMESTAMP_OUTPUT_FORMAT, + desiredFormat = appMainViewModel.applicationConfiguration.dateFormat, + ) + Assert.assertEquals(expectedReformattedDate, syncTime) + } + @Test @kotlinx.coroutines.ExperimentalCoroutinesApi fun testOnSubmitQuestionnaireShouldNeverUpdateTaskStatusWhenQuestionnaireTaskIdIsNull() =