From 4e13dd29faafc98de69b8e4d7d8c5d670d8c2d5d Mon Sep 17 00:00:00 2001 From: Kolya Opahle Date: Thu, 12 Nov 2020 14:04:14 +0100 Subject: [PATCH 1/4] 1. Replaced redundant uiStateState during test result fetch with a NetworkRequestWrapper that is able to represent multiple states. This allows for better request state handling throughout the app 2. Completely removed the SubmissionViewModel 3. Failure to fetch the test should now always display the invalid test card on the home screen Signed-off-by: Kolya Opahle --- .../ui/TestRiskLevelCalculationFragment.kt | 7 +- ...iskLevelCalculationFragmentCWAViewModel.kt | 6 + .../fragment_test_risk_level_calculation.xml | 6 +- .../storage/SubmissionRepository.kt | 34 ++--- .../ui/main/home/SubmissionCardState.kt | 130 ++++++++++------ .../main/home/SubmissionCardsStateProvider.kt | 6 +- .../SubmissionTestResultFragment.kt | 11 +- .../SubmissionTestResultViewModel.kt | 25 ++-- .../testresult/TestResultUIState.kt | 5 +- .../ui/viewmodel/SubmissionViewModel.kt | 12 -- .../util/NetworkRequestWrapper.kt | 30 ++++ .../formatter/FormatterSubmissionHelper.kt | 139 ++++++++++-------- .../fragment_submission_symptom_calendar.xml | 4 - .../fragment_submission_symptom_intro.xml | 4 - .../fragment_submission_test_result.xml | 4 +- ...de_submission_symptom_length_selection.xml | 4 - .../res/layout/include_test_result_card.xml | 2 +- 17 files changed, 241 insertions(+), 188 deletions(-) delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt index 0867b6e6bfc..f9834cdc792 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt @@ -15,7 +15,6 @@ import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange import de.rki.coronawarnapp.sharing.ExposureSharingService import de.rki.coronawarnapp.test.menu.ui.TestMenuItem import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel -import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.viewBindingLazy @@ -39,7 +38,6 @@ class TestRiskLevelCalculationFragment : Fragment(R.layout.fragment_test_risk_le ) private val settingsViewModel: SettingsViewModel by activityViewModels() - private val submissionViewModel: SubmissionViewModel by activityViewModels() private val binding: FragmentTestRiskLevelCalculationBinding by viewBindingLazy() @@ -51,7 +49,10 @@ class TestRiskLevelCalculationFragment : Fragment(R.layout.fragment_test_risk_le } binding.settingsViewModel = settingsViewModel - binding.submissionViewModel = submissionViewModel + + vm.showRiskStatusCard.observe2(this) { + binding.showRiskStatusCard = it + } binding.buttonRetrieveDiagnosisKeys.setOnClickListener { vm.retrieveDiagnosisKeys() } binding.buttonProvideKeyViaQr.setOnClickListener { vm.scanLocalQRCodeAndProvide() } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt index d0a85e7f0f7..d33900aa8a1 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt @@ -23,11 +23,13 @@ import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange import de.rki.coronawarnapp.storage.AppDatabase import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.RiskLevelRepository +import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.task.TaskController import de.rki.coronawarnapp.task.common.DefaultTaskRequest import de.rki.coronawarnapp.task.submitBlocking import de.rki.coronawarnapp.ui.tracing.card.TracingCardStateProvider import de.rki.coronawarnapp.util.KeyFileHelper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.di.AppInjector @@ -36,6 +38,7 @@ import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.sample import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -65,6 +68,9 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( val riskLevelResetEvent = SingleLiveEvent() val apiKeysProvidedEvent = SingleLiveEvent() val riskScoreState = MutableLiveData(RiskScoreState()) + val showRiskStatusCard = SubmissionRepository.deviceUIStateFlow.map { + it.withSuccess(false) { true } + }.asLiveData(dispatcherProvider.Default) val tracingCardState = tracingCardStateProvider.state .sample(150L) diff --git a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml index 9e29d88d479..a58a1ff4308 100644 --- a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml +++ b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml @@ -11,8 +11,8 @@ + name="showRiskStatusCard" + type="Boolean" /> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt index b601e6d7747..62ae3efc8d0 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt @@ -1,16 +1,13 @@ package de.rki.coronawarnapp.storage -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.asLiveData import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.service.submission.SubmissionService -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState -import de.rki.coronawarnapp.util.Event +import de.rki.coronawarnapp.util.NetworkRequestWrapper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.di.AppInjector import de.rki.coronawarnapp.util.formatter.TestResult import de.rki.coronawarnapp.worker.BackgroundWorkScheduler @@ -26,15 +23,12 @@ object SubmissionRepository { AppInjector.component.appScope } - val uiStateStateFlowInternal = MutableStateFlow(ApiRequestState.IDLE) - val uiStateStateFlow: Flow = uiStateStateFlowInternal - val uiStateState: LiveData = uiStateStateFlow.asLiveData() - private val testResultReceivedDateFlowInternal = MutableStateFlow(Date()) val testResultReceivedDateFlow: Flow = testResultReceivedDateFlowInternal - private val deviceUIStateFlowInternal = MutableStateFlow(DeviceUIState.UNPAIRED) - val deviceUIStateFlow: Flow = deviceUIStateFlowInternal + private val deviceUIStateFlowInternal = + MutableStateFlow>(NetworkRequestWrapper.RequestIdle) + val deviceUIStateFlow: Flow> = deviceUIStateFlowInternal private val testResultFlow = MutableStateFlow(null) @@ -80,37 +74,33 @@ object SubmissionRepository { LocalData.teletan(teletan) } - private val uiStateErrorInternal = MutableLiveData>(null) - val uiStateError: LiveData> = uiStateErrorInternal - // TODO this should be more UI agnostic fun refreshDeviceUIState(refreshTestResult: Boolean = true) { var refresh = refreshTestResult - deviceUIStateFlowInternal.value.let { + deviceUIStateFlowInternal.value.withSuccess { if (it != DeviceUIState.PAIRED_NO_RESULT && it != DeviceUIState.UNPAIRED) { refresh = false Timber.d("refreshDeviceUIState: Change refresh, state ${it.name} doesn't require refresh") } } - uiStateStateFlowInternal.value = ApiRequestState.STARTED + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestStarted + appScope.launch { try { refreshUIState(refresh) - uiStateStateFlowInternal.value = ApiRequestState.SUCCESS } catch (err: CwaWebException) { - uiStateErrorInternal.postValue(Event(err)) - uiStateStateFlowInternal.value = ApiRequestState.FAILED + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestFailed(err) } catch (err: Exception) { + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestFailed(err) err.report(ExceptionCategory.INTERNAL) } } } fun reset() { - uiStateStateFlowInternal.value = ApiRequestState.IDLE - deviceUIStateFlowInternal.value = DeviceUIState.UNPAIRED + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestIdle } // TODO this should be more UI agnostic @@ -132,6 +122,6 @@ object SubmissionRepository { } } } - deviceUIStateFlowInternal.value = uiState + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestSuccessful(uiState) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt index 6592ad0bae0..4cd1b51e030 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt @@ -3,7 +3,6 @@ package de.rki.coronawarnapp.ui.main.home import android.content.Context import android.graphics.drawable.Drawable import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_ERROR import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_NEGATIVE @@ -12,72 +11,109 @@ import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE_TELETAN import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_REDEEMED import de.rki.coronawarnapp.util.DeviceUIState.SUBMITTED_FINAL +import de.rki.coronawarnapp.util.NetworkRequestWrapper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess data class SubmissionCardState( - val deviceUiState: DeviceUIState, + val deviceUiState: NetworkRequestWrapper, val isDeviceRegistered: Boolean, - val uiStateState: ApiRequestState ) { - fun isRiskCardVisible(): Boolean = deviceUiState != PAIRED_POSITIVE && - deviceUiState != PAIRED_POSITIVE_TELETAN && - deviceUiState != SUBMITTED_FINAL + fun isRiskCardVisible(): Boolean = + deviceUiState.withSuccess(true) { + when (it) { + PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN, SUBMITTED_FINAL -> false + else -> true + } + } fun isUnregisteredCardVisible(): Boolean = !isDeviceRegistered fun isFetchingCardVisible(): Boolean = - isDeviceRegistered && (uiStateState == ApiRequestState.STARTED || uiStateState == ApiRequestState.FAILED) + isDeviceRegistered && deviceUiState is NetworkRequestWrapper.RequestStarted fun isFailedCardVisible(): Boolean = - isDeviceRegistered && uiStateState == ApiRequestState.SUCCESS && deviceUiState == PAIRED_REDEEMED + isDeviceRegistered && when (deviceUiState) { + is NetworkRequestWrapper.RequestFailed -> true + is NetworkRequestWrapper.RequestSuccessful -> deviceUiState.data == PAIRED_REDEEMED + else -> false + } - fun isPositiveSubmissionCardVisible(): Boolean = uiStateState == ApiRequestState.SUCCESS && - (deviceUiState == PAIRED_POSITIVE || - deviceUiState == PAIRED_POSITIVE_TELETAN) + fun isPositiveSubmissionCardVisible(): Boolean = + deviceUiState.withSuccess(false) { + when (it) { + PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN -> true + else -> false + } + } fun isSubmissionDoneCardVisible(): Boolean = - uiStateState == ApiRequestState.SUCCESS && deviceUiState == SUBMITTED_FINAL + when (deviceUiState) { + is NetworkRequestWrapper.RequestSuccessful -> deviceUiState.data == SUBMITTED_FINAL + else -> false + } fun isContentCardVisible(): Boolean = - uiStateState == ApiRequestState.SUCCESS && (deviceUiState == PAIRED_ERROR || - deviceUiState == PAIRED_NEGATIVE || - deviceUiState == PAIRED_NO_RESULT) + deviceUiState.withSuccess(false) { + when (it) { + PAIRED_ERROR, PAIRED_NEGATIVE, PAIRED_NO_RESULT -> true + else -> false + } + } - fun getContentCardTitleText(c: Context): String = when (deviceUiState) { - PAIRED_ERROR, PAIRED_REDEEMED, PAIRED_NEGATIVE -> R.string.submission_status_card_title_available - PAIRED_NO_RESULT -> R.string.submission_status_card_title_pending - else -> R.string.submission_status_card_title_pending - }.let { c.getString(it) } + fun getContentCardTitleText(c: Context): String = + deviceUiState.withSuccess(R.string.submission_status_card_title_pending) { + when (it) { + PAIRED_ERROR, PAIRED_REDEEMED, PAIRED_NEGATIVE -> R.string.submission_status_card_title_available + PAIRED_NO_RESULT -> R.string.submission_status_card_title_pending + else -> R.string.submission_status_card_title_pending + } + }.let { c.getString(it) } - fun getContentCardSubTitleText(c: Context): String = when (deviceUiState) { - PAIRED_NEGATIVE -> R.string.submission_status_card_subtitle_negative - PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_subtitle_invalid - else -> null - }?.let { c.getString(it) } ?: "" + fun getContentCardSubTitleText(c: Context): String = + deviceUiState.withSuccess(null) { + when (it) { + PAIRED_NEGATIVE -> R.string.submission_status_card_subtitle_negative + PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_subtitle_invalid + else -> null + } + }?.let { c.getString(it) } ?: "" - fun getContentCardSubTitleTextColor(c: Context): Int = when (deviceUiState) { - PAIRED_NEGATIVE -> R.color.colorTextSemanticGreen - PAIRED_ERROR, PAIRED_REDEEMED -> R.color.colorTextSemanticNeutral - else -> R.color.colorTextPrimary1 - }.let { c.getColor(it) } + fun getContentCardSubTitleTextColor(c: Context): Int = + deviceUiState.withSuccess(R.color.colorTextPrimary1) { + when (it) { + PAIRED_NEGATIVE -> R.color.colorTextSemanticGreen + PAIRED_ERROR, PAIRED_REDEEMED -> R.color.colorTextSemanticNeutral + else -> R.color.colorTextPrimary1 + } + }.let { c.getColor(it) } - fun isContentCardStatusTextVisible(): Boolean = when (deviceUiState) { - PAIRED_NEGATIVE, PAIRED_REDEEMED, PAIRED_ERROR -> true - else -> false - } + fun isContentCardStatusTextVisible(): Boolean = + deviceUiState.withSuccess(false) { + when (it) { + PAIRED_NEGATIVE, PAIRED_REDEEMED, PAIRED_ERROR -> true + else -> false + } + } - fun getContentCardBodyText(c: Context): String = when (deviceUiState) { - PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_body_invalid - PAIRED_NEGATIVE -> R.string.submission_status_card_body_negative - PAIRED_NO_RESULT -> R.string.submission_status_card_body_pending - else -> R.string.submission_status_card_body_pending - }.let { c.getString(it) } + fun getContentCardBodyText(c: Context): String = + deviceUiState.withSuccess(R.string.submission_status_card_body_pending) { + when (it) { + PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_body_invalid + PAIRED_NEGATIVE -> R.string.submission_status_card_body_negative + PAIRED_NO_RESULT -> R.string.submission_status_card_body_pending + else -> R.string.submission_status_card_body_pending + } + }.let { c.getString(it) } - fun getContentCardIcon(c: Context): Drawable? = when (deviceUiState) { - PAIRED_NO_RESULT -> R.drawable.ic_main_illustration_pending - PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN -> R.drawable.ic_main_illustration_pending - PAIRED_NEGATIVE -> R.drawable.ic_main_illustration_negative - PAIRED_ERROR, PAIRED_REDEEMED -> R.drawable.ic_main_illustration_invalid - else -> R.drawable.ic_main_illustration_invalid - }.let { c.getDrawable(it) } + fun getContentCardIcon(c: Context): Drawable? = + deviceUiState.withSuccess(R.drawable.ic_main_illustration_invalid) { + when (it) { + PAIRED_NO_RESULT -> R.drawable.ic_main_illustration_pending + PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN -> R.drawable.ic_main_illustration_pending + PAIRED_NEGATIVE -> R.drawable.ic_main_illustration_negative + PAIRED_ERROR, PAIRED_REDEEMED -> R.drawable.ic_main_illustration_invalid + else -> R.drawable.ic_main_illustration_invalid + } + }.let { c.getDrawable(it) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt index 087c1e1f72a..d70c19dad9a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt @@ -3,8 +3,6 @@ package de.rki.coronawarnapp.ui.main.home import dagger.Reusable import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.SubmissionRepository -import de.rki.coronawarnapp.ui.submission.ApiRequestState -import de.rki.coronawarnapp.util.DeviceUIState import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.onCompletion @@ -18,11 +16,9 @@ class SubmissionCardsStateProvider @Inject constructor() { val state: Flow = combine( SubmissionRepository.deviceUIStateFlow, - SubmissionRepository.uiStateStateFlow ) { args -> SubmissionCardState( - deviceUiState = args[0] as DeviceUIState, - uiStateState = args[1] as ApiRequestState, + deviceUiState = args[0], isDeviceRegistered = LocalData.registrationToken() != null ) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt index a1d42d3961c..0de5f0efad2 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt @@ -15,8 +15,8 @@ import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withFailure import de.rki.coronawarnapp.util.di.AutoInject -import de.rki.coronawarnapp.util.observeEvent import de.rki.coronawarnapp.util.ui.doNavigate import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.viewBindingLazy @@ -79,6 +79,11 @@ class SubmissionTestResultFragment : Fragment(R.layout.fragment_submission_test_ viewModel.uiState.observe2(this) { binding.uiState = it + it.deviceUiState.withFailure { + if (it is CwaWebException) { + DialogHelper.showDialog(buildErrorDialog(it)) + } + } } // registers callback when the os level back is pressed @@ -99,10 +104,6 @@ class SubmissionTestResultFragment : Fragment(R.layout.fragment_submission_test_ DialogHelper.showDialog(tracingRequiredDialog) } - viewModel.uiStateError.observeEvent(viewLifecycleOwner) { - DialogHelper.showDialog(buildErrorDialog(it)) - } - viewModel.showRedeemedTokenWarning.observe2(this) { val dialog = DialogHelper.DialogInstance( requireActivity(), diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt index 97586ba507f..370ecbf2928 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt @@ -3,7 +3,6 @@ package de.rki.coronawarnapp.ui.submission.testresult import androidx.lifecycle.LiveData import androidx.lifecycle.asLiveData import com.squareup.inject.assisted.AssistedInject -import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.nearby.ENFClient import de.rki.coronawarnapp.notification.TestResultNotificationService import de.rki.coronawarnapp.service.submission.SubmissionService @@ -12,7 +11,7 @@ import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.submission.Symptoms import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents import de.rki.coronawarnapp.util.DeviceUIState -import de.rki.coronawarnapp.util.Event +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel @@ -37,20 +36,22 @@ class SubmissionTestResultViewModel @AssistedInject constructor( private val tokenErrorMutex = Mutex() val uiState: LiveData = combineTransform( - SubmissionRepository.uiStateStateFlow, SubmissionRepository.deviceUIStateFlow, SubmissionRepository.testResultReceivedDateFlow - ) { apiRequestState, deviceUiState, resultDate -> + ) { deviceUiState, resultDate -> tokenErrorMutex.withLock { - if (!wasRedeemedTokenErrorShown && deviceUiState == DeviceUIState.PAIRED_REDEEMED) { - wasRedeemedTokenErrorShown = true - showRedeemedTokenWarning.postValue(Unit) + if (!wasRedeemedTokenErrorShown) { + deviceUiState.withSuccess { + if (it == DeviceUIState.PAIRED_REDEEMED) { + wasRedeemedTokenErrorShown = true + showRedeemedTokenWarning.postValue(Unit) + } + } } } TestResultUIState( - apiRequestState = apiRequestState, deviceUiState = deviceUiState, testResultReceivedDate = resultDate ).let { emit(it) } @@ -58,11 +59,13 @@ class SubmissionTestResultViewModel @AssistedInject constructor( suspend fun observeTestResultToSchedulePositiveTestResultReminder() = SubmissionRepository.deviceUIStateFlow - .first { it == DeviceUIState.PAIRED_POSITIVE || it == DeviceUIState.PAIRED_POSITIVE_TELETAN } + .first { request -> + request.withSuccess(false) { + it == DeviceUIState.PAIRED_POSITIVE || it == DeviceUIState.PAIRED_POSITIVE_TELETAN + } + } .also { testResultNotificationService.schedulePositiveTestResultReminder() } - val uiStateError: LiveData> = SubmissionRepository.uiStateError - fun onBackPressed() { routeToScreen.postValue(SubmissionNavigationEvents.NavigateToMainActivity) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt index b1909eb805d..a34a02cad13 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt @@ -1,11 +1,10 @@ package de.rki.coronawarnapp.ui.submission.testresult -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import java.util.Date data class TestResultUIState( - val apiRequestState: ApiRequestState, - val deviceUiState: DeviceUIState, + val deviceUiState: NetworkRequestWrapper, val testResultReceivedDate: Date? ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt deleted file mode 100644 index 6b668e6c420..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt +++ /dev/null @@ -1,12 +0,0 @@ -package de.rki.coronawarnapp.ui.viewmodel - -import androidx.lifecycle.LiveData -import androidx.lifecycle.asLiveData -import de.rki.coronawarnapp.storage.SubmissionRepository -import de.rki.coronawarnapp.util.DeviceUIState -import de.rki.coronawarnapp.util.viewmodel.CWAViewModel - -class SubmissionViewModel : CWAViewModel() { - - val deviceUiState: LiveData = SubmissionRepository.deviceUIStateFlow.asLiveData() -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt new file mode 100644 index 00000000000..47d1c57e48a --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt @@ -0,0 +1,30 @@ +package de.rki.coronawarnapp.util + +sealed class NetworkRequestWrapper { + object RequestIdle : NetworkRequestWrapper() + object RequestStarted : NetworkRequestWrapper() + data class RequestSuccessful(val data: T) : NetworkRequestWrapper() + data class RequestFailed(val error: U) : NetworkRequestWrapper() + + companion object { + fun NetworkRequestWrapper?.withSuccess(without: W, block: (data: T) -> W): W { + return if (this is RequestSuccessful) { + block(this.data) + } else { + without + } + } + + fun NetworkRequestWrapper?.withSuccess(block: (data: T) -> Unit) { + if (this is RequestSuccessful) { + block(this.data) + } + } + + fun NetworkRequestWrapper?.withFailure(block: (error: U) -> Unit) { + if (this is RequestFailed) { + block(this.error) + } + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt index 156f8efee02..e573e202356 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt @@ -8,11 +8,13 @@ import android.text.Spannable import android.text.SpannableString import android.text.SpannableStringBuilder import android.text.style.ForegroundColorSpan +import android.view.View import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.R import de.rki.coronawarnapp.submission.Symptoms -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.TimeAndDateExtensions.toUIFormat import java.util.Date import java.util.Locale @@ -49,33 +51,37 @@ fun isEnableSymptomCalendarButtonByState(currentState: Symptoms.StartOf?): Boole return currentState != null } -fun formatTestResultSpinnerVisible(uiStateState: ApiRequestState?): Int = - formatVisibility(uiStateState != ApiRequestState.SUCCESS) - -fun formatTestResultVisible(uiStateState: ApiRequestState?): Int = - formatVisibility(uiStateState == ApiRequestState.SUCCESS) - -fun formatTestResultStatusText(uiState: DeviceUIState?): String { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NEGATIVE -> appContext.getString(R.string.test_result_card_status_negative) - DeviceUIState.PAIRED_POSITIVE, - DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getString(R.string.test_result_card_status_positive) - else -> appContext.getString(R.string.test_result_card_status_invalid) +fun formatTestResultSpinnerVisible(uiState: NetworkRequestWrapper?): Int = + uiState.withSuccess(View.VISIBLE) { + View.GONE } -} -fun formatTestResultStatusColor(uiState: DeviceUIState?): Int { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NEGATIVE -> appContext.getColor(R.color.colorTextSemanticGreen) - DeviceUIState.PAIRED_POSITIVE, - DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getColor(R.color.colorTextSemanticRed) - else -> appContext.getColor(R.color.colorTextSemanticRed) +fun formatTestResultVisible(uiState: NetworkRequestWrapper?): Int = + uiState.withSuccess(View.GONE) { + View.VISIBLE } -} -fun formatTestResult(uiState: DeviceUIState?): Spannable { +fun formatTestResultStatusText(uiState: NetworkRequestWrapper?): String = + uiState.withSuccess(R.string.test_result_card_status_invalid) { + when (it) { + DeviceUIState.PAIRED_NEGATIVE -> R.string.test_result_card_status_negative + DeviceUIState.PAIRED_POSITIVE, + DeviceUIState.PAIRED_POSITIVE_TELETAN -> R.string.test_result_card_status_positive + else -> R.string.test_result_card_status_invalid + } + }.let { CoronaWarnApplication.getAppContext().getString(it) } + +fun formatTestResultStatusColor(uiState: NetworkRequestWrapper?): Int = + uiState.withSuccess(R.color.colorTextSemanticRed) { + when (it) { + DeviceUIState.PAIRED_NEGATIVE -> R.color.colorTextSemanticGreen + DeviceUIState.PAIRED_POSITIVE, + DeviceUIState.PAIRED_POSITIVE_TELETAN -> R.color.colorTextSemanticRed + else -> R.color.colorTextSemanticRed + } + }.let { CoronaWarnApplication.getAppContext().getColor(it) } + +fun formatTestResult(uiState: NetworkRequestWrapper?): Spannable { val appContext = CoronaWarnApplication.getAppContext() return SpannableStringBuilder() .append(appContext.getString(R.string.test_result_card_virus_name_text)) @@ -87,33 +93,36 @@ fun formatTestResult(uiState: DeviceUIState?): Spannable { ) } -fun formatTestResultCardContent(uiState: DeviceUIState?): Spannable { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NO_RESULT -> - SpannableString(appContext.getString(R.string.test_result_card_status_pending)) - DeviceUIState.PAIRED_ERROR, - DeviceUIState.PAIRED_REDEEMED -> - SpannableString(appContext.getString(R.string.test_result_card_status_invalid)) - - DeviceUIState.PAIRED_POSITIVE, - DeviceUIState.PAIRED_POSITIVE_TELETAN, - DeviceUIState.PAIRED_NEGATIVE -> formatTestResult(uiState) - else -> SpannableString("") +fun formatTestResultCardContent(uiState: NetworkRequestWrapper?): Spannable { + return uiState.withSuccess(SpannableString("")) { + val appContext = CoronaWarnApplication.getAppContext() + when (it) { + DeviceUIState.PAIRED_NO_RESULT -> + SpannableString(appContext.getString(R.string.test_result_card_status_pending)) + DeviceUIState.PAIRED_ERROR, + DeviceUIState.PAIRED_REDEEMED -> + SpannableString(appContext.getString(R.string.test_result_card_status_invalid)) + + DeviceUIState.PAIRED_POSITIVE, + DeviceUIState.PAIRED_POSITIVE_TELETAN, + DeviceUIState.PAIRED_NEGATIVE -> formatTestResult(uiState) + else -> SpannableString("") + } } } -fun formatTestStatusIcon(uiState: DeviceUIState?): Drawable? { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NO_RESULT -> appContext.getDrawable(R.drawable.ic_test_result_illustration_pending) - DeviceUIState.PAIRED_POSITIVE_TELETAN, - DeviceUIState.PAIRED_POSITIVE -> appContext.getDrawable(R.drawable.ic_test_result_illustration_positive) - DeviceUIState.PAIRED_NEGATIVE -> appContext.getDrawable(R.drawable.ic_test_result_illustration_negative) - DeviceUIState.PAIRED_ERROR, - DeviceUIState.PAIRED_REDEEMED -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid) - else -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid) - } +fun formatTestStatusIcon(uiState: NetworkRequestWrapper?): Drawable? { + return uiState.withSuccess(R.drawable.ic_test_result_illustration_invalid) { + when (it) { + DeviceUIState.PAIRED_NO_RESULT -> R.drawable.ic_test_result_illustration_pending + DeviceUIState.PAIRED_POSITIVE_TELETAN, + DeviceUIState.PAIRED_POSITIVE -> R.drawable.ic_test_result_illustration_positive + DeviceUIState.PAIRED_NEGATIVE -> R.drawable.ic_test_result_illustration_negative + DeviceUIState.PAIRED_ERROR, + DeviceUIState.PAIRED_REDEEMED -> R.drawable.ic_test_result_illustration_invalid + else -> R.drawable.ic_test_result_illustration_invalid + } + }.let { CoronaWarnApplication.getAppContext().getDrawable(it) } } fun formatTestResultRegisteredAtText(registeredAt: Date?): String { @@ -122,24 +131,30 @@ fun formatTestResultRegisteredAtText(registeredAt: Date?): String { .format(registeredAt?.toUIFormat(appContext)) } -fun formatTestResultPendingStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_NO_RESULT) +fun formatTestResultPendingStepsVisible(uiState: NetworkRequestWrapper?): Int = + uiState.withSuccess(View.GONE) { formatVisibility(it == DeviceUIState.PAIRED_NO_RESULT) } -fun formatTestResultNegativeStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_NEGATIVE) +fun formatTestResultNegativeStepsVisible(uiState: NetworkRequestWrapper?): Int = + uiState.withSuccess(View.GONE) { formatVisibility(it == DeviceUIState.PAIRED_NEGATIVE) } -fun formatTestResultPositiveStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_POSITIVE || uiState == DeviceUIState.PAIRED_POSITIVE_TELETAN) +fun formatTestResultPositiveStepsVisible(uiState: NetworkRequestWrapper?): Int = + uiState.withSuccess(View.GONE) { + formatVisibility(it == DeviceUIState.PAIRED_POSITIVE || it == DeviceUIState.PAIRED_POSITIVE_TELETAN) + } -fun formatTestResultInvalidStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_ERROR || uiState == DeviceUIState.PAIRED_REDEEMED) +fun formatTestResultInvalidStepsVisible(uiState: NetworkRequestWrapper?): Int = + uiState.withSuccess(View.GONE) { + formatVisibility(it == DeviceUIState.PAIRED_ERROR || it == DeviceUIState.PAIRED_REDEEMED) + } -fun formatShowRiskStatusCard(deviceUiState: DeviceUIState?): Int = - formatVisibility( - deviceUiState != DeviceUIState.PAIRED_POSITIVE && - deviceUiState != DeviceUIState.PAIRED_POSITIVE_TELETAN && - deviceUiState != DeviceUIState.SUBMITTED_FINAL - ) +fun formatShowRiskStatusCard(uiState: NetworkRequestWrapper?): Int = + uiState.withSuccess(View.GONE) { + formatVisibility( + it != DeviceUIState.PAIRED_POSITIVE && + it != DeviceUIState.PAIRED_POSITIVE_TELETAN && + it != DeviceUIState.SUBMITTED_FINAL + ) + } fun formatCountryIsoTagToLocalizedName(isoTag: String?): String { val country = if (isoTag != null) Locale("", isoTag).displayCountry else "" diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml index a34166dd59d..ecf73ebc437 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml @@ -9,10 +9,6 @@ - - - - - - + type="de.rki.coronawarnapp.util.NetworkRequestWrapper<de.rki.coronawarnapp.util.DeviceUIState,java.lang.Throwable>" /> Date: Thu, 12 Nov 2020 14:29:11 +0100 Subject: [PATCH 2/4] Keep displaying fetching card on server errors as this usually does not indicate any problems with the test itself Signed-off-by: Kolya Opahle --- .../java/de/rki/coronawarnapp/http/HttpErrorParser.kt | 3 +++ .../coronawarnapp/ui/main/home/SubmissionCardState.kt | 11 ++++++++--- .../ui/main/home/SubmissionCardsStateProvider.kt | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt index bc347abb919..1061abc7e16 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt @@ -26,6 +26,7 @@ import de.rki.coronawarnapp.exception.http.UnauthorizedException import de.rki.coronawarnapp.exception.http.UnsupportedMediaTypeException import okhttp3.Interceptor import okhttp3.Response +import java.net.SocketTimeoutException import java.net.UnknownHostException import javax.net.ssl.HttpsURLConnection @@ -66,6 +67,8 @@ class HttpErrorParser : Interceptor { throw CwaWebException(code) } } + } catch (err: SocketTimeoutException) { + throw NetworkConnectTimeoutException() } catch (err: UnknownHostException) { throw CwaUnknownHostException() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt index 4cd1b51e030..517a077b37f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt @@ -3,6 +3,7 @@ package de.rki.coronawarnapp.ui.main.home import android.content.Context import android.graphics.drawable.Drawable import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.exception.http.CwaServerError import de.rki.coronawarnapp.util.DeviceUIState import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_ERROR import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_NEGATIVE @@ -16,7 +17,7 @@ import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess data class SubmissionCardState( val deviceUiState: NetworkRequestWrapper, - val isDeviceRegistered: Boolean, + val isDeviceRegistered: Boolean ) { fun isRiskCardVisible(): Boolean = @@ -30,11 +31,15 @@ data class SubmissionCardState( fun isUnregisteredCardVisible(): Boolean = !isDeviceRegistered fun isFetchingCardVisible(): Boolean = - isDeviceRegistered && deviceUiState is NetworkRequestWrapper.RequestStarted + isDeviceRegistered && when (deviceUiState) { + is NetworkRequestWrapper.RequestFailed -> deviceUiState.error is CwaServerError + is NetworkRequestWrapper.RequestStarted -> true + else -> false + } fun isFailedCardVisible(): Boolean = isDeviceRegistered && when (deviceUiState) { - is NetworkRequestWrapper.RequestFailed -> true + is NetworkRequestWrapper.RequestFailed -> deviceUiState.error !is CwaServerError is NetworkRequestWrapper.RequestSuccessful -> deviceUiState.data == PAIRED_REDEEMED else -> false } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt index d70c19dad9a..9fc9fa97657 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt @@ -15,7 +15,7 @@ import javax.inject.Inject class SubmissionCardsStateProvider @Inject constructor() { val state: Flow = combine( - SubmissionRepository.deviceUIStateFlow, + SubmissionRepository.deviceUIStateFlow ) { args -> SubmissionCardState( deviceUiState = args[0], From 0cfaa6f441baf4f778cb4c5fc0cb05e70117b8c4 Mon Sep 17 00:00:00 2001 From: Kolya Opahle Date: Thu, 12 Nov 2020 15:49:30 +0100 Subject: [PATCH 3/4] Fixing unit tests (mostly just syntax, one test case changed due to new card) Signed-off-by: Kolya Opahle --- .../main/home/HomeFragmentViewModelTest.kt | 6 +- .../main/home/SubmissionCardStateTest.kt | 21 +- .../home/SubmissionCardsStateProviderTest.kt | 11 +- .../FormatterSubmissionHelperTest.kt | 197 ++++++++++-------- 4 files changed, 134 insertions(+), 101 deletions(-) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt index 44a4980d782..c636f8180f5 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt @@ -9,12 +9,12 @@ import de.rki.coronawarnapp.ui.main.home.HomeFragmentViewModel import de.rki.coronawarnapp.ui.main.home.SubmissionCardState import de.rki.coronawarnapp.ui.main.home.SubmissionCardsStateProvider import de.rki.coronawarnapp.ui.main.home.TracingHeaderState -import de.rki.coronawarnapp.ui.submission.ApiRequestState.SUCCESS import de.rki.coronawarnapp.ui.tracing.card.TracingCardState import de.rki.coronawarnapp.ui.tracing.card.TracingCardStateProvider import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE_TELETAN +import de.rki.coronawarnapp.util.NetworkRequestWrapper import de.rki.coronawarnapp.util.security.EncryptionErrorResetTool import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations @@ -128,7 +128,7 @@ class HomeFragmentViewModelTest : BaseTest() { @Test fun `positive test result notification is triggered on positive QR code result`() { - val state = SubmissionCardState(PAIRED_POSITIVE, true, SUCCESS) + val state = SubmissionCardState(NetworkRequestWrapper.RequestSuccessful(PAIRED_POSITIVE), true) every { submissionCardsStateProvider.state } returns flowOf(state) every { testResultNotificationService.schedulePositiveTestResultReminder() } returns Unit @@ -142,7 +142,7 @@ class HomeFragmentViewModelTest : BaseTest() { @Test fun `positive test result notification is triggered on positive TeleTan code result`() { - val state = SubmissionCardState(PAIRED_POSITIVE_TELETAN, true, SUCCESS) + val state = SubmissionCardState(NetworkRequestWrapper.RequestSuccessful(PAIRED_POSITIVE_TELETAN), true) every { submissionCardsStateProvider.state } returns flowOf(state) every { testResultNotificationService.schedulePositiveTestResultReminder() } returns Unit diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt index 37d908b1033..e661eb23ae7 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt @@ -5,6 +5,7 @@ import de.rki.coronawarnapp.R import de.rki.coronawarnapp.ui.main.home.SubmissionCardState import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.clearAllMocks @@ -33,12 +34,18 @@ class SubmissionCardStateTest : BaseTest() { private fun instance( deviceUiState: DeviceUIState = mockk(), isDeviceRegistered: Boolean = true, - uiStateState: ApiRequestState = mockk() - ) = SubmissionCardState( - deviceUiState = deviceUiState, - isDeviceRegistered = isDeviceRegistered, - uiStateState = uiStateState - ) + uiStateState: ApiRequestState = ApiRequestState.SUCCESS + ) = + when (uiStateState) { + ApiRequestState.SUCCESS -> + SubmissionCardState(NetworkRequestWrapper.RequestSuccessful(deviceUiState), isDeviceRegistered) + ApiRequestState.FAILED -> + SubmissionCardState(NetworkRequestWrapper.RequestFailed(mockk()), isDeviceRegistered) + ApiRequestState.STARTED -> + SubmissionCardState(NetworkRequestWrapper.RequestStarted, isDeviceRegistered) + ApiRequestState.IDLE -> + SubmissionCardState(NetworkRequestWrapper.RequestIdle, isDeviceRegistered) + } @Test fun `risk card visibility`() { @@ -163,7 +170,7 @@ class SubmissionCardStateTest : BaseTest() { isFetchingCardVisible() shouldBe false } instance(isDeviceRegistered = true, uiStateState = ApiRequestState.FAILED).apply { - isFetchingCardVisible() shouldBe true + isFetchingCardVisible() shouldBe false } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt index 2eaac14f64c..b5bc2d4517a 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt @@ -5,8 +5,8 @@ import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.ui.main.home.SubmissionCardState import de.rki.coronawarnapp.ui.main.home.SubmissionCardsStateProvider -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.clearAllMocks @@ -46,20 +46,19 @@ class SubmissionCardsStateProviderTest : BaseTest() { @Test fun `state is combined correctly`() = runBlockingTest { - every { SubmissionRepository.deviceUIStateFlow } returns flow { emit(DeviceUIState.PAIRED_POSITIVE) } - every { SubmissionRepository.uiStateStateFlow } returns flow { emit(ApiRequestState.SUCCESS) } + every { SubmissionRepository.deviceUIStateFlow } returns flow { + emit(NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE)) + } every { LocalData.registrationToken() } returns "token" createInstance().apply { state.first() shouldBe SubmissionCardState( - deviceUiState = DeviceUIState.PAIRED_POSITIVE, - uiStateState = ApiRequestState.SUCCESS, + deviceUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), isDeviceRegistered = true ) verify { SubmissionRepository.deviceUIStateFlow - SubmissionRepository.uiStateStateFlow LocalData.registrationToken() } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt index c8310865349..c7f8e7b15f2 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt @@ -8,8 +8,8 @@ import android.text.style.ForegroundColorSpan import android.view.View import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import io.mockk.MockKAnnotations import io.mockk.every import io.mockk.impl.annotations.MockK @@ -74,52 +74,76 @@ class FormatterSubmissionHelperTest { every { context.getDrawable(R.drawable.ic_test_result_illustration_negative) } returns drawable } - private fun formatTestResultSpinnerVisibleBase(oUiStateState: ApiRequestState?, iResult: Int) { - val result = formatTestResultSpinnerVisible(uiStateState = oUiStateState) + private fun formatTestResultSpinnerVisibleBase( + oUiStateState: NetworkRequestWrapper?, + iResult: Int + ) { + val result = formatTestResultSpinnerVisible(uiState = oUiStateState) assertThat(result, `is`(iResult)) } - private fun formatTestResultVisibleBase(oUiStateState: ApiRequestState?, iResult: Int) { - val result = formatTestResultVisible(uiStateState = oUiStateState) + private fun formatTestResultVisibleBase( + oUiStateState: NetworkRequestWrapper?, + iResult: Int + ) { + val result = formatTestResultVisible(uiState = oUiStateState) assertThat(result, `is`(iResult)) } - private fun formatTestResultStatusTextBase(oUiState: DeviceUIState?, iResult: String) { + private fun formatTestResultStatusTextBase( + oUiState: NetworkRequestWrapper?, + iResult: String + ) { val result = formatTestResultStatusText(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultStatusColorBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultStatusColorBase( + oUiState: NetworkRequestWrapper?, + iResult: Int + ) { val result = formatTestResultStatusColor(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestStatusIconBase(oUiState: DeviceUIState?) { + private fun formatTestStatusIconBase(oUiState: NetworkRequestWrapper.RequestSuccessful?) { val result = formatTestStatusIcon(uiState = oUiState) assertThat(result, `is`(drawable)) } - private fun formatTestResultPendingStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultPendingStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful?, + iResult: Int + ) { val result = formatTestResultPendingStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultNegativeStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultNegativeStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful?, + iResult: Int + ) { val result = formatTestResultNegativeStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultPositiveStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultPositiveStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful?, + iResult: Int + ) { val result = formatTestResultPositiveStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultInvalidStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultInvalidStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful?, + iResult: Int + ) { val result = formatTestResultInvalidStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultBase(oUiState: DeviceUIState?) { + private fun formatTestResultBase(oUiState: NetworkRequestWrapper.RequestSuccessful?) { mockkConstructor(SpannableStringBuilder::class) val spannableStringBuilder1 = @@ -147,19 +171,19 @@ class FormatterSubmissionHelperTest { fun formatTestResultSpinnerVisible() { formatTestResultSpinnerVisibleBase(oUiStateState = null, iResult = View.VISIBLE) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.FAILED, + oUiStateState = NetworkRequestWrapper.RequestFailed(mockk()), iResult = View.VISIBLE ) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.IDLE, + oUiStateState = NetworkRequestWrapper.RequestIdle, iResult = View.VISIBLE ) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.STARTED, + oUiStateState = NetworkRequestWrapper.RequestStarted, iResult = View.VISIBLE ) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.SUCCESS, + oUiStateState = NetworkRequestWrapper.RequestSuccessful(mockk()), iResult = View.GONE ) } @@ -167,10 +191,13 @@ class FormatterSubmissionHelperTest { @Test fun formatTestResultVisible() { formatTestResultVisibleBase(oUiStateState = null, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.FAILED, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.IDLE, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.STARTED, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.SUCCESS, iResult = View.VISIBLE) + formatTestResultVisibleBase(oUiStateState = NetworkRequestWrapper.RequestFailed(mockk()), iResult = View.GONE) + formatTestResultVisibleBase(oUiStateState = NetworkRequestWrapper.RequestIdle, iResult = View.GONE) + formatTestResultVisibleBase(oUiStateState = NetworkRequestWrapper.RequestStarted, iResult = View.GONE) + formatTestResultVisibleBase( + oUiStateState = NetworkRequestWrapper.RequestSuccessful(mockk()), + iResult = View.VISIBLE + ) } @Test @@ -180,35 +207,35 @@ class FormatterSubmissionHelperTest { iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = context.getString(R.string.test_result_card_status_negative) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = context.getString(R.string.test_result_card_status_positive) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = context.getString(R.string.test_result_card_status_positive) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = context.getString(R.string.test_result_card_status_invalid) ) } @@ -220,35 +247,35 @@ class FormatterSubmissionHelperTest { iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = context.getColor(R.color.colorTextSemanticGreen) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = context.getColor(R.color.colorTextSemanticRed) ) } @@ -256,49 +283,49 @@ class FormatterSubmissionHelperTest { @Test fun formatTestStatusIcon() { formatTestStatusIconBase(oUiState = null) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_NEGATIVE) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_ERROR) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_NO_RESULT) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_POSITIVE) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN) - formatTestStatusIconBase(oUiState = DeviceUIState.SUBMITTED_FINAL) - formatTestStatusIconBase(oUiState = DeviceUIState.SUBMITTED_INITIAL) - formatTestStatusIconBase(oUiState = DeviceUIState.UNPAIRED) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED)) } @Test fun formatTestResultPendingStepsVisible() { formatTestResultPendingStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.VISIBLE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -307,35 +334,35 @@ class FormatterSubmissionHelperTest { fun formatTestResultNegativeStepsVisible() { formatTestResultNegativeStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.VISIBLE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -344,35 +371,35 @@ class FormatterSubmissionHelperTest { fun formatTestResultPositiveStepsVisible() { formatTestResultPositiveStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.VISIBLE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.VISIBLE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -381,35 +408,35 @@ class FormatterSubmissionHelperTest { fun formatTestResultInvalidStepsVisible() { formatTestResultInvalidStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.VISIBLE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -417,14 +444,14 @@ class FormatterSubmissionHelperTest { @Test fun formatTestResult() { formatTestResultBase(oUiState = null) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_NEGATIVE) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_ERROR) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_NO_RESULT) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_POSITIVE) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN) - formatTestResultBase(oUiState = DeviceUIState.SUBMITTED_FINAL) - formatTestResultBase(oUiState = DeviceUIState.SUBMITTED_INITIAL) - formatTestResultBase(oUiState = DeviceUIState.UNPAIRED) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED)) } @After From 5ae043481c50d1dcda1172c62d8f208d42eb23ff Mon Sep 17 00:00:00 2001 From: Kolya Opahle Date: Thu, 12 Nov 2020 16:57:44 +0100 Subject: [PATCH 4/4] Promoted unknown host exception to server exception --- .../java/de/rki/coronawarnapp/exception/http/CwaWebException.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt index 4fa8b6effbc..fc89eff4627 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt @@ -27,7 +27,6 @@ open class CwaSuccessResponseWithCodeMismatchNotSupportedError(statusCode: Int) open class CwaInformationalNotSupportedError(statusCode: Int) : CwaWebException(statusCode) open class CwaRedirectNotSupportedError(statusCode: Int) : CwaWebException(statusCode) -class CwaUnknownHostException : CwaWebException(901) class BadRequestException : CwaClientError(400) class UnauthorizedException : CwaClientError(401) class ForbiddenException : CwaClientError(403) @@ -44,5 +43,6 @@ class ServiceUnavailableException : CwaServerError(503) class GatewayTimeoutException : CwaServerError(504) class HTTPVersionNotSupported : CwaServerError(505) class NetworkAuthenticationRequiredException : CwaServerError(511) +class CwaUnknownHostException : CwaServerError(597) class NetworkReadTimeoutException : CwaServerError(598) class NetworkConnectTimeoutException : CwaServerError(599)