From 1ab6e235b7afa5a378680bbe0a1700d3c3cb074a Mon Sep 17 00:00:00 2001
From: axelherbstreith <75120552+axelherbstreith@users.noreply.github.com>
Date: Tue, 20 Apr 2021 12:07:22 +0200
Subject: [PATCH] Wire new Deletion Warning Screen to Submission Flow
 (EXPOSUREAPP-6318) (#2807)

* initial connection

* add cancel navigation

* improved navigation

* added nav args + udated deletion warning view model

* fixed merge conflicts

* updated screen wiring

* linting

* fix unit tests

* lint

* updated wiring

* lint

* updated navArgs passing

* fixed merging issue

* linting

* fixunit tests

* lint

* Tweak unit tests.

* fix nav graph

* fixed merging conflict

* linting

* included UI changes

* updated navigation when code is redeemed

* updated navigation params

* addressed comments

* addressed comments

* addressed comments

Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com>
Co-authored-by: Matthias Urhahn <matthias.urhahn@sap.com>
---
 .../SubmissionConsentFragmentTest.kt          |   2 -
 .../SubmissionQrCodeScanFragmentTest.kt       |   9 +-
 .../SubmissionDeletionWarningFragment.kt      | 143 +++++++++++++++++-
 ...missionDeletionWarningFragmentViewModel.kt |  12 --
 .../SubmissionDeletionWarningModule.kt        |   4 +-
 .../SubmissionDeletionWarningViewModel.kt     | 118 +++++++++++++++
 .../consent/SubmissionConsentFragment.kt      |   8 +-
 .../consent/SubmissionConsentViewModel.kt     |   8 +-
 .../scan/SubmissionQRCodeScanFragment.kt      |  40 ++++-
 .../scan/SubmissionQRCodeScanViewModel.kt     |  39 +++--
 .../viewmodel/SubmissionNavigationEvents.kt   |   4 +
 .../fragment_submission_deletion_warning.xml  |  31 ++--
 .../src/main/res/navigation/nav_graph.xml     |  55 ++++++-
 .../consent/SubmissionConsentViewModelTest.kt |   2 -
 .../scan/SubmissionQRCodeScanViewModelTest.kt |  21 ++-
 15 files changed, 419 insertions(+), 77 deletions(-)
 delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragmentViewModel.kt
 create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningViewModel.kt

diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionConsentFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionConsentFragmentTest.kt
index 7748ab27c..27bc93242 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionConsentFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionConsentFragmentTest.kt
@@ -48,11 +48,9 @@ class SubmissionConsentFragmentTest : BaseUITest() {
         every { interoperabilityRepository.countryList } returns flowOf()
         viewModel =
             SubmissionConsentViewModel(
-                submissionRepository,
                 interoperabilityRepository,
                 TestDispatcherProvider(),
                 tekHistoryProvider,
-                analyticsKeySubmissionCollector
             )
         setupMockViewModel(
             object : SubmissionConsentViewModel.Factory {
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionQrCodeScanFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionQrCodeScanFragmentTest.kt
index 06ab62aa3..e516c0b18 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionQrCodeScanFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionQrCodeScanFragmentTest.kt
@@ -4,6 +4,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
 import dagger.Module
 import dagger.android.ContributesAndroidInjector
 import de.rki.coronawarnapp.ui.submission.qrcode.scan.SubmissionQRCodeScanFragment
+import de.rki.coronawarnapp.ui.submission.qrcode.scan.SubmissionQRCodeScanFragmentArgs
 import de.rki.coronawarnapp.ui.submission.qrcode.scan.SubmissionQRCodeScanViewModel
 import io.mockk.MockKAnnotations
 import io.mockk.impl.annotations.MockK
@@ -19,12 +20,14 @@ class SubmissionQrCodeScanFragmentTest : BaseUITest() {
 
     @MockK lateinit var viewModel: SubmissionQRCodeScanViewModel
 
+    private var fragmentArgs = SubmissionQRCodeScanFragmentArgs(isConsentGiven = true).toBundle()
+
     @Before
     fun setup() {
         MockKAnnotations.init(this, relaxed = true)
         setupMockViewModel(
             object : SubmissionQRCodeScanViewModel.Factory {
-                override fun create(): SubmissionQRCodeScanViewModel = viewModel
+                override fun create(isConsentGiven: Boolean): SubmissionQRCodeScanViewModel = viewModel
             }
         )
     }
@@ -36,7 +39,9 @@ class SubmissionQrCodeScanFragmentTest : BaseUITest() {
 
     @Test
     fun launch_fragment() {
-        launchFragment2<SubmissionQRCodeScanFragment>()
+        launchFragment2<SubmissionQRCodeScanFragment>(
+            fragmentArgs = fragmentArgs
+        )
     }
 }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragment.kt
index 8a918bfad..10d580e80 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragment.kt
@@ -3,19 +3,43 @@ package de.rki.coronawarnapp.ui.submission.deletionwarning
 import android.os.Bundle
 import android.view.View
 import android.view.accessibility.AccessibilityEvent
+import androidx.core.view.isVisible
 import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.navArgs
 import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult
+import de.rki.coronawarnapp.coronatest.type.CoronaTest
 import de.rki.coronawarnapp.databinding.FragmentSubmissionDeletionWarningBinding
+import de.rki.coronawarnapp.exception.http.BadRequestException
+import de.rki.coronawarnapp.exception.http.CwaClientError
+import de.rki.coronawarnapp.exception.http.CwaServerError
+import de.rki.coronawarnapp.exception.http.CwaWebException
+import de.rki.coronawarnapp.ui.submission.ApiRequestState
+import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents
+import de.rki.coronawarnapp.util.DialogHelper
 import de.rki.coronawarnapp.util.di.AutoInject
+import de.rki.coronawarnapp.util.ui.SingleLiveEvent
+import de.rki.coronawarnapp.util.ui.doNavigate
+import de.rki.coronawarnapp.util.ui.observe2
 import de.rki.coronawarnapp.util.ui.viewBindingLazy
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider
-import de.rki.coronawarnapp.util.viewmodel.cwaViewModels
+import de.rki.coronawarnapp.util.viewmodel.cwaViewModelsAssisted
 import javax.inject.Inject
 
 class SubmissionDeletionWarningFragment : Fragment(R.layout.fragment_submission_deletion_warning), AutoInject {
 
     @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
-    private val viewModel: SubmissionDeletionWarningFragmentViewModel by cwaViewModels { viewModelFactory }
+
+    private val args by navArgs<SubmissionDeletionWarningFragmentArgs>()
+    val routeToScreen: SingleLiveEvent<SubmissionNavigationEvents> = SingleLiveEvent()
+
+    private val viewModel: SubmissionDeletionWarningViewModel by cwaViewModelsAssisted(
+        factoryProducer = { viewModelFactory },
+        constructorCall = { factory, _ ->
+            factory as SubmissionDeletionWarningViewModel.Factory
+            factory.create(args.coronaTestQrCode, args.isConsentGiven)
+        }
+    )
     private val binding: FragmentSubmissionDeletionWarningBinding by viewBindingLazy()
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -23,14 +47,121 @@ class SubmissionDeletionWarningFragment : Fragment(R.layout.fragment_submission_
 
         binding.apply {
 
-            cancelButton.setOnClickListener { /* TODO */ }
+            when (args.coronaTestQrCode.type) {
+                CoronaTest.Type.PCR -> {
+                    headline.text = getString(R.string.submission_deletion_warning_headline_pcr_test)
+                    body.text = getString(R.string.submission_deletion_warning_body_pcr_test)
+                }
 
-            continueButton.setOnClickListener { /* TODO */ }
+                CoronaTest.Type.RAPID_ANTIGEN -> {
+                    headline.text = getString(R.string.submission_deletion_warning_headline_antigen_test)
+                    body.text = getString(R.string.submission_deletion_warning_body_antigen_test)
+                }
+            }
+
+            continueButton.setOnClickListener {
+                viewModel.deleteExistingAndRegisterNewTest()
+            }
 
-            toolbar.apply {
-                setNavigationOnClickListener { /* TODO */ }
+            toolbar.setNavigationOnClickListener {
+                viewModel.onCancelButtonClick()
             }
         }
+
+        viewModel.showRedeemedTokenWarning.observe2(this) {
+            val dialog = DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_tan_redeemed_title,
+                R.string.submission_error_dialog_web_tan_redeemed_body,
+                R.string.submission_error_dialog_web_tan_redeemed_button_positive
+            )
+
+            DialogHelper.showDialog(dialog)
+
+            navigateToDispatchScreen()
+        }
+
+        viewModel.registrationState.observe2(this) { state ->
+            binding.submissionQrCodeScanSpinner.isVisible = state.apiRequestState == ApiRequestState.STARTED
+
+            if (ApiRequestState.SUCCESS == state.apiRequestState) {
+                if (state.testResult == CoronaTestResult.PCR_POSITIVE) {
+                    viewModel.triggerNavigationToSubmissionTestResultAvailableFragment()
+                } else {
+                    viewModel.triggerNavigationToSubmissionTestResultPendingFragment()
+                }
+            }
+        }
+
+        viewModel.registrationError.observe2(this) {
+            DialogHelper.showDialog(buildErrorDialog(it))
+        }
+
+        viewModel.routeToScreen.observe2(this) {
+            when (it) {
+                SubmissionNavigationEvents.NavigateToConsent -> {
+                    doNavigate(
+                        SubmissionDeletionWarningFragmentDirections
+                            .actionSubmissionDeletionWarningFragmentToSubmissionConsentFragment()
+                    )
+                }
+                is SubmissionNavigationEvents.NavigateToResultAvailableScreen -> {
+                    doNavigate(
+                        SubmissionDeletionWarningFragmentDirections
+                            .actionSubmissionDeletionWarningFragmentToSubmissionTestResultAvailableFragment(
+                                it.consentGiven
+                            )
+                    )
+                }
+                is SubmissionNavigationEvents.NavigateToResultPendingScreen -> {
+                    doNavigate(
+                        SubmissionDeletionWarningFragmentDirections
+                            .actionSubmissionDeletionWarningFragmentToSubmissionTestResultPendingFragment(
+                                it.consentGiven
+                            )
+                    )
+                }
+            }
+        }
+    }
+
+    private fun navigateToDispatchScreen() =
+        doNavigate(
+            SubmissionDeletionWarningFragmentDirections
+                .actionSubmissionDeletionWarningFragmentToSubmissionDispatcherFragment()
+        )
+
+    private fun buildErrorDialog(exception: CwaWebException): DialogHelper.DialogInstance {
+        return when (exception) {
+            is BadRequestException -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_qr_code_scan_invalid_dialog_headline,
+                R.string.submission_qr_code_scan_invalid_dialog_body,
+                R.string.submission_qr_code_scan_invalid_dialog_button_positive,
+                R.string.submission_qr_code_scan_invalid_dialog_button_negative,
+                true,
+                { /* startDecode() */ },
+                ::navigateToDispatchScreen
+            )
+            is CwaClientError, is CwaServerError -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_generic_error_title,
+                R.string.submission_error_dialog_web_generic_network_error_body,
+                R.string.submission_error_dialog_web_generic_error_button_positive,
+                null,
+                true,
+                ::navigateToDispatchScreen
+            )
+            else -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_generic_error_title,
+                R.string.submission_error_dialog_web_generic_error_body,
+                R.string.submission_error_dialog_web_generic_error_button_positive,
+                null,
+                true,
+                ::navigateToDispatchScreen
+            )
+        }
     }
 
     override fun onResume() {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragmentViewModel.kt
deleted file mode 100644
index a2e1e2437..000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragmentViewModel.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package de.rki.coronawarnapp.ui.submission.deletionwarning
-
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
-import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
-
-class SubmissionDeletionWarningFragmentViewModel @AssistedInject constructor() : CWAViewModel() {
-
-    @AssistedFactory
-    interface Factory : SimpleCWAViewModelFactory<SubmissionDeletionWarningFragmentViewModel>
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningModule.kt
index ac2010cd7..2f9541315 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningModule.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningModule.kt
@@ -12,8 +12,8 @@ abstract class SubmissionDeletionWarningModule {
 
     @Binds
     @IntoMap
-    @CWAViewModelKey(SubmissionDeletionWarningFragmentViewModel::class)
+    @CWAViewModelKey(SubmissionDeletionWarningViewModel::class)
     abstract fun submissionDeletionWarningFragmentVM(
-        factory: SubmissionDeletionWarningFragmentViewModel.Factory
+        factory: SubmissionDeletionWarningViewModel.Factory
     ): CWAViewModelFactory<out CWAViewModel>
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningViewModel.kt
new file mode 100644
index 000000000..a4b8f62e0
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningViewModel.kt
@@ -0,0 +1,118 @@
+package de.rki.coronawarnapp.ui.submission.deletionwarning
+
+import androidx.annotation.VisibleForTesting
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import de.rki.coronawarnapp.coronatest.CoronaTestRepository
+import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQRCode
+import de.rki.coronawarnapp.coronatest.qrcode.InvalidQRCodeException
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult
+import de.rki.coronawarnapp.exception.ExceptionCategory
+import de.rki.coronawarnapp.exception.TransactionException
+import de.rki.coronawarnapp.exception.http.CwaWebException
+import de.rki.coronawarnapp.exception.reporting.report
+import de.rki.coronawarnapp.submission.SubmissionRepository
+import de.rki.coronawarnapp.ui.submission.ApiRequestState
+import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents
+import de.rki.coronawarnapp.util.ui.SingleLiveEvent
+import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
+import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory
+import timber.log.Timber
+
+class SubmissionDeletionWarningViewModel @AssistedInject constructor(
+    private val coronaTestRepository: CoronaTestRepository,
+    private val submissionRepository: SubmissionRepository,
+    @Assisted private val coronaTest: CoronaTestQRCode,
+    @Assisted private val isConsentGiven: Boolean,
+) : CWAViewModel() {
+
+    val routeToScreen = SingleLiveEvent<SubmissionNavigationEvents>()
+    val showRedeemedTokenWarning = SingleLiveEvent<Unit>()
+    private val mutableRegistrationState = MutableLiveData(RegistrationState(ApiRequestState.IDLE))
+    val registrationState: LiveData<RegistrationState> = mutableRegistrationState
+    val registrationError = SingleLiveEvent<CwaWebException>()
+
+    fun deleteExistingAndRegisterNewTest() = launch {
+        coronaTestRepository.removeTest(coronaTest.identifier)
+        doDeviceRegistration(coronaTest)
+    }
+
+    data class RegistrationState(
+        val apiRequestState: ApiRequestState,
+        val testResult: CoronaTestResult? = null
+    )
+
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    internal suspend fun doDeviceRegistration(coronaTestQRCode: CoronaTestQRCode) {
+        try {
+            mutableRegistrationState.postValue(RegistrationState(ApiRequestState.STARTED))
+            val coronaTest = submissionRepository.registerTest(coronaTestQRCode)
+            if (isConsentGiven) {
+                submissionRepository.giveConsentToSubmission(type = coronaTestQRCode.type)
+            }
+            checkTestResult(coronaTest.testResult)
+            mutableRegistrationState.postValue(
+                RegistrationState(
+                    ApiRequestState.SUCCESS,
+                    coronaTest.testResult
+                )
+            )
+        } catch (err: CwaWebException) {
+            Timber.e(err, "Msg: ${err.message}")
+            mutableRegistrationState.postValue(RegistrationState(ApiRequestState.FAILED))
+            registrationError.postValue(err)
+        } catch (err: TransactionException) {
+            Timber.e(err, "Msg: ${err.message}")
+            if (err.cause is CwaWebException) {
+                registrationError.postValue(err.cause)
+            } else {
+                err.report(ExceptionCategory.INTERNAL)
+            }
+            mutableRegistrationState.postValue(RegistrationState(ApiRequestState.FAILED))
+        } catch (err: InvalidQRCodeException) {
+            Timber.e(err, "Msg: ${err.message}")
+            mutableRegistrationState.postValue(RegistrationState(ApiRequestState.FAILED))
+            deregisterTestFromDevice(coronaTestQRCode)
+            showRedeemedTokenWarning.postValue(Unit)
+        } catch (err: Exception) {
+            Timber.e(err, "Msg: ${err.message}")
+            mutableRegistrationState.postValue(RegistrationState(ApiRequestState.FAILED))
+            err.report(ExceptionCategory.INTERNAL)
+        }
+    }
+
+    fun onCancelButtonClick() {
+        routeToScreen.postValue(SubmissionNavigationEvents.NavigateToConsent)
+    }
+
+    fun triggerNavigationToSubmissionTestResultAvailableFragment() {
+        routeToScreen.postValue(SubmissionNavigationEvents.NavigateToResultAvailableScreen(isConsentGiven))
+    }
+
+    fun triggerNavigationToSubmissionTestResultPendingFragment() {
+        routeToScreen.postValue(SubmissionNavigationEvents.NavigateToResultPendingScreen(isConsentGiven))
+    }
+
+    private fun checkTestResult(testResult: CoronaTestResult) {
+        if (testResult == CoronaTestResult.PCR_REDEEMED) {
+            throw InvalidQRCodeException()
+        }
+    }
+
+    private fun deregisterTestFromDevice(coronaTest: CoronaTestQRCode) {
+        launch {
+            Timber.d("deregisterTestFromDevice()")
+
+            submissionRepository.removeTestFromDevice(type = coronaTest.type)
+            routeToScreen.postValue(SubmissionNavigationEvents.NavigateToMainActivity)
+        }
+    }
+
+    @AssistedFactory
+    interface Factory : CWAViewModelFactory<SubmissionDeletionWarningViewModel> {
+        fun create(coronaTest: CoronaTestQRCode, isConsentGiven: Boolean): SubmissionDeletionWarningViewModel
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentFragment.kt
index 6458a16da..89a9a4a17 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentFragment.kt
@@ -32,9 +32,11 @@ class SubmissionConsentFragment : Fragment(R.layout.fragment_submission_consent)
         }
         viewModel.routeToScreen.observe2(this) {
             when (it) {
-                is SubmissionNavigationEvents.NavigateToQRCodeScan -> doNavigate(
-                    SubmissionConsentFragmentDirections.actionSubmissionConsentFragmentToSubmissionQRCodeScanFragment()
-                )
+                is SubmissionNavigationEvents.NavigateToQRCodeScan ->
+                    doNavigate(
+                        SubmissionConsentFragmentDirections
+                            .actionSubmissionConsentFragmentToSubmissionQRCodeScanFragment(isConsentGiven = true)
+                    )
                 is SubmissionNavigationEvents.NavigateToDispatcher -> popBackStack()
                 is SubmissionNavigationEvents.NavigateToDataPrivacy -> doNavigate(
                     SubmissionConsentFragmentDirections.actionSubmissionConsentFragmentToInformationPrivacyFragment()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModel.kt
index 459ea67f4..e3387e7dc 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModel.kt
@@ -4,10 +4,8 @@ import androidx.lifecycle.asLiveData
 import com.google.android.gms.common.api.ApiException
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
-import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.nearby.modules.tekhistory.TEKHistoryProvider
 import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository
-import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents
 import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
 import de.rki.coronawarnapp.util.ui.SingleLiveEvent
@@ -16,11 +14,10 @@ import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
 import timber.log.Timber
 
 class SubmissionConsentViewModel @AssistedInject constructor(
-    private val submissionRepository: SubmissionRepository,
     interoperabilityRepository: InteroperabilityRepository,
     dispatcherProvider: DispatcherProvider,
     private val tekHistoryProvider: TEKHistoryProvider,
-    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
+    // private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     val routeToScreen: SingleLiveEvent<SubmissionNavigationEvents> = SingleLiveEvent()
@@ -30,8 +27,7 @@ class SubmissionConsentViewModel @AssistedInject constructor(
 
     fun onConsentButtonClick() {
         // TODO Do we have a Test registered at this time? We need to forward the decission with navargs?
-//        submissionRepository.giveConsentToSubmission(type = CoronaTest.Type.PCR)
-        analyticsKeySubmissionCollector.reportAdvancedConsentGiven()
+        // analyticsKeySubmissionCollector.reportAdvancedConsentGiven()
         launch {
             try {
                 val preAuthorized = tekHistoryProvider.preAuthorizeExposureKeyHistory()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanFragment.kt
index f19296ecb..2cd19a7a5 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanFragment.kt
@@ -6,6 +6,7 @@ import android.os.Bundle
 import android.view.View
 import android.view.accessibility.AccessibilityEvent
 import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.navArgs
 import com.google.zxing.BarcodeFormat
 import com.journeyapps.barcodescanner.DefaultDecoderFactory
 import de.rki.coronawarnapp.R
@@ -26,18 +27,24 @@ import de.rki.coronawarnapp.util.ui.doNavigate
 import de.rki.coronawarnapp.util.ui.observe2
 import de.rki.coronawarnapp.util.ui.viewBindingLazy
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider
-import de.rki.coronawarnapp.util.viewmodel.cwaViewModels
+import de.rki.coronawarnapp.util.viewmodel.cwaViewModelsAssisted
 import javax.inject.Inject
 
 /**
  * A simple [Fragment] subclass.
  */
-class SubmissionQRCodeScanFragment :
-    Fragment(R.layout.fragment_submission_qr_code_scan),
-    AutoInject {
-
+class SubmissionQRCodeScanFragment : Fragment(R.layout.fragment_submission_qr_code_scan), AutoInject {
     @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
-    private val viewModel: SubmissionQRCodeScanViewModel by cwaViewModels { viewModelFactory }
+
+    private val args by navArgs<SubmissionQRCodeScanFragmentArgs>()
+
+    private val viewModel: SubmissionQRCodeScanViewModel by cwaViewModelsAssisted(
+        factoryProducer = { viewModelFactory },
+        constructorCall = { factory, _ ->
+            factory as SubmissionQRCodeScanViewModel.Factory
+            factory.create(args.isConsentGiven)
+        }
+    )
 
     private val binding: FragmentSubmissionQrCodeScanBinding by viewBindingLazy()
     private var showsPermissionDialog = false
@@ -62,6 +69,18 @@ class SubmissionQRCodeScanFragment :
             submissionQrCodeScanViewfinderView.setCameraPreview(binding.submissionQrCodeScanPreview)
         }
 
+        viewModel.routeToScreen.observe2(this) {
+            when (it) {
+                is SubmissionNavigationEvents.NavigateToDeletionWarningFragment -> {
+                    SubmissionQRCodeScanFragmentDirections
+                        .actionSubmissionQRCodeScanFragmentToSubmissionDeletionWarningFragment(
+                            args.isConsentGiven,
+                            it.coronaTestQRCode
+                        )
+                }
+            }
+        }
+
         viewModel.scanStatusValue.observe2(this) {
             if (ScanStatus.INVALID == it) {
                 showInvalidScanDialog()
@@ -85,16 +104,21 @@ class SubmissionQRCodeScanFragment :
                 ApiRequestState.STARTED -> View.VISIBLE
                 else -> View.GONE
             }
+
             if (ApiRequestState.SUCCESS == state.apiRequestState) {
                 if (state.testResult == CoronaTestResult.PCR_POSITIVE) {
                     doNavigate(
                         SubmissionQRCodeScanFragmentDirections
-                            .actionSubmissionQRCodeScanFragmentToSubmissionTestResultAvailableFragment()
+                            .actionSubmissionQRCodeScanFragmentToSubmissionTestResultAvailableFragment(
+                                isConsentGiven = args.isConsentGiven
+                            )
                     )
                 } else {
                     doNavigate(
                         SubmissionQRCodeScanFragmentDirections
-                            .actionSubmissionQRCodeScanFragmentToSubmissionTestResultPendingFragment()
+                            .actionSubmissionQRCodeScanFragmentToSubmissionTestResultPendingFragment(
+                                isConsentGiven = args.isConsentGiven
+                            )
                     )
                 }
             }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModel.kt
index ff300dd09..cfbc1dd68 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModel.kt
@@ -2,6 +2,7 @@ package de.rki.coronawarnapp.ui.submission.qrcode.scan
 
 import androidx.annotation.VisibleForTesting
 import androidx.lifecycle.MutableLiveData
+import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import de.rki.coronawarnapp.bugreporting.censors.QRCodeCensor
@@ -9,7 +10,6 @@ import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQRCode
 import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQrCodeValidator
 import de.rki.coronawarnapp.coronatest.qrcode.InvalidQRCodeException
 import de.rki.coronawarnapp.coronatest.server.CoronaTestResult
-import de.rki.coronawarnapp.coronatest.type.CoronaTest
 import de.rki.coronawarnapp.exception.ExceptionCategory
 import de.rki.coronawarnapp.exception.TransactionException
 import de.rki.coronawarnapp.exception.http.CwaWebException
@@ -18,29 +18,41 @@ import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.ui.submission.ApiRequestState
 import de.rki.coronawarnapp.ui.submission.ScanStatus
 import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents
+import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
 import de.rki.coronawarnapp.util.permission.CameraSettings
 import de.rki.coronawarnapp.util.ui.SingleLiveEvent
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
-import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
+import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory
+import kotlinx.coroutines.flow.first
 import timber.log.Timber
 
 class SubmissionQRCodeScanViewModel @AssistedInject constructor(
+    dispatcherProvider: DispatcherProvider,
     private val submissionRepository: SubmissionRepository,
     private val cameraSettings: CameraSettings,
+    @Assisted private val isConsentGiven: Boolean,
     private val qrCodeValidator: CoronaTestQrCodeValidator
-) : CWAViewModel() {
+) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
     val routeToScreen = SingleLiveEvent<SubmissionNavigationEvents>()
     val showRedeemedTokenWarning = SingleLiveEvent<Unit>()
     val scanStatusValue = SingleLiveEvent<ScanStatus>()
 
-    fun validateTestGUID(rawResult: String) {
+    fun validateTestGUID(rawResult: String) = launch {
         try {
             val coronaTestQRCode = qrCodeValidator.validate(rawResult)
             // TODO this needs to be adapted to work for different types
             QRCodeCensor.lastGUID = coronaTestQRCode.registrationIdentifier
             scanStatusValue.postValue(ScanStatus.SUCCESS)
-            doDeviceRegistration(coronaTestQRCode)
+
+            val coronaTest = submissionRepository.testForType(coronaTestQRCode.type).first()
+
+            if (coronaTest != null) {
+                routeToScreen.postValue(SubmissionNavigationEvents.NavigateToDeletionWarningFragment(coronaTestQRCode))
+            } else {
+                doDeviceRegistration(coronaTestQRCode)
+            }
         } catch (err: InvalidQRCodeException) {
+            Timber.e(err, "Failed to validate GUID")
             scanStatusValue.postValue(ScanStatus.INVALID)
         }
     }
@@ -54,11 +66,13 @@ class SubmissionQRCodeScanViewModel @AssistedInject constructor(
     )
 
     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    internal fun doDeviceRegistration(coronaTestQRCode: CoronaTestQRCode) = launch {
+    internal suspend fun doDeviceRegistration(coronaTestQRCode: CoronaTestQRCode) {
         try {
             registrationState.postValue(RegistrationState(ApiRequestState.STARTED))
             val coronaTest = submissionRepository.registerTest(coronaTestQRCode)
-            submissionRepository.giveConsentToSubmission(type = coronaTestQRCode.type)
+            if (isConsentGiven) {
+                submissionRepository.giveConsentToSubmission(type = coronaTestQRCode.type)
+            }
             checkTestResult(coronaTest.testResult)
             registrationState.postValue(RegistrationState(ApiRequestState.SUCCESS, coronaTest.testResult))
         } catch (err: CwaWebException) {
@@ -73,7 +87,7 @@ class SubmissionQRCodeScanViewModel @AssistedInject constructor(
             registrationState.postValue(RegistrationState(ApiRequestState.FAILED))
         } catch (err: InvalidQRCodeException) {
             registrationState.postValue(RegistrationState(ApiRequestState.FAILED))
-            deregisterTestFromDevice()
+            deregisterTestFromDevice(coronaTestQRCode)
             showRedeemedTokenWarning.postValue(Unit)
         } catch (err: Exception) {
             registrationState.postValue(RegistrationState(ApiRequestState.FAILED))
@@ -87,12 +101,11 @@ class SubmissionQRCodeScanViewModel @AssistedInject constructor(
         }
     }
 
-    private fun deregisterTestFromDevice() {
+    private fun deregisterTestFromDevice(coronaTest: CoronaTestQRCode) {
         launch {
             Timber.d("deregisterTestFromDevice()")
 
-            submissionRepository.removeTestFromDevice(type = CoronaTest.Type.PCR)
-
+            submissionRepository.removeTestFromDevice(type = coronaTest.type)
             routeToScreen.postValue(SubmissionNavigationEvents.NavigateToMainActivity)
         }
     }
@@ -111,5 +124,7 @@ class SubmissionQRCodeScanViewModel @AssistedInject constructor(
     }
 
     @AssistedFactory
-    interface Factory : SimpleCWAViewModelFactory<SubmissionQRCodeScanViewModel>
+    interface Factory : CWAViewModelFactory<SubmissionQRCodeScanViewModel> {
+        fun create(isConsentGiven: Boolean): SubmissionQRCodeScanViewModel
+    }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionNavigationEvents.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionNavigationEvents.kt
index de51d34bf..df8b68eec 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionNavigationEvents.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionNavigationEvents.kt
@@ -1,6 +1,7 @@
 package de.rki.coronawarnapp.ui.submission.viewmodel
 
 import com.google.android.gms.common.api.ApiException
+import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQRCode
 
 sealed class SubmissionNavigationEvents {
     object NavigateToContact : SubmissionNavigationEvents()
@@ -12,5 +13,8 @@ sealed class SubmissionNavigationEvents {
     object NavigateToTAN : SubmissionNavigationEvents()
     object NavigateToConsent : SubmissionNavigationEvents()
     object NavigateToMainActivity : SubmissionNavigationEvents()
+    data class NavigateToResultPendingScreen(val consentGiven: Boolean) : SubmissionNavigationEvents()
+    data class NavigateToResultAvailableScreen(val consentGiven: Boolean) : SubmissionNavigationEvents()
+    data class NavigateToDeletionWarningFragment(val coronaTestQRCode: CoronaTestQRCode) : SubmissionNavigationEvents()
     data class ResolvePlayServicesException(val exception: ApiException) : SubmissionNavigationEvents()
 }
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_deletion_warning.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_deletion_warning.xml
index 56a83c008..27fdf7bca 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_submission_deletion_warning.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_deletion_warning.xml
@@ -18,6 +18,19 @@
         app:navigationIcon="@drawable/ic_close"
         app:title="@string/submission_deletion_warning_title" />
 
+    <ProgressBar
+        android:id="@+id/submission_qr_code_scan_spinner"
+        style="?android:attr/progressBarStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/spacing_normal"
+        android:visibility="gone"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:visibility="visible" />
+
     <ScrollView
         android:layout_width="0dp"
         android:layout_height="0dp"
@@ -94,26 +107,12 @@
         android:layout_height="wrap_content"
         android:layout_marginStart="@dimen/spacing_normal"
         android:layout_marginEnd="@dimen/spacing_normal"
-        android:layout_marginBottom="8dp"
+        android:layout_marginBottom="@dimen/spacing_normal"
         android:text="@string/submission_deletion_warning_continue_button"
-        app:layout_constraintBottom_toTopOf="@id/cancel_button"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        tools:text="@string/submission_deletion_warning_continue_button" />
-
-    <Button
-        android:id="@+id/cancel_button"
-        style="@style/buttonLight"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/spacing_normal"
-        android:layout_marginEnd="@dimen/spacing_normal"
-        android:layout_marginBottom="4dp"
-        android:text="@string/submission_deletion_warning_cancel_button"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        tools:text="@string/submission_deletion_warning_cancel_button" />
+        tools:text="@string/submission_deletion_warning_continue_button" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>
 
diff --git a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
index 5ff1d99cf..accb01a0f 100644
--- a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
+++ b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
@@ -289,6 +289,10 @@
         android:name="de.rki.coronawarnapp.ui.submission.testresult.pending.SubmissionTestResultPendingFragment"
         android:label="SubmissionTestResultPendingFragment"
         tools:layout="@layout/fragment_submission_test_result_pending">
+        <argument
+            android:name="isConsentGiven"
+            android:defaultValue="false"
+            app:argType="boolean" />
         <argument
             android:name="skipInitialTestResultRefresh"
             android:defaultValue="false"
@@ -348,7 +352,12 @@
     <fragment
         android:id="@+id/submissionQRCodeScanFragment"
         android:name="de.rki.coronawarnapp.ui.submission.qrcode.scan.SubmissionQRCodeScanFragment"
-        android:label="SubmissionQRCodeScanFragment">
+        android:label="SubmissionQRCodeScanFragment"
+        tools:layout="@layout/fragment_submission_qr_code_scan">
+        <argument
+            android:name="isConsentGiven"
+            android:defaultValue="false"
+            app:argType="boolean" />
         <action
             android:id="@+id/action_submissionQRCodeScanFragment_to_submissionDispatcherFragment"
             app:popUpTo="@id/submissionQRCodeScanFragment"
@@ -368,6 +377,9 @@
             app:destination="@id/submissionTestResultAvailableFragment"
             app:popUpTo="@id/mainFragment"
             app:popUpToInclusive="false" />
+        <action
+            android:id="@+id/action_submissionQRCodeScanFragment_to_submissionDeletionWarningFragment"
+            app:destination="@id/submissionDeletionWarningFragment" />
     </fragment>
     <fragment
         android:id="@+id/submissionResultReadyFragment"
@@ -480,6 +492,10 @@
         android:name="de.rki.coronawarnapp.ui.submission.resultavailable.SubmissionTestResultAvailableFragment"
         android:label="SubmissionTestResultAvailableFragment"
         tools:layout="@layout/fragment_submission_test_result_available">
+        <argument
+            android:name="isConsentGiven"
+            android:defaultValue="false"
+            app:argType="boolean" />
         <action
             android:id="@+id/action_submissionTestResultAvailableFragment_to_mainFragment"
             app:destination="@id/mainFragment"
@@ -619,6 +635,43 @@
         android:name="de.rki.coronawarnapp.bugreporting.debuglog.ui.legal.DebugLogLegalFragment"
         android:label="DebugLogLegalFragment"
         tools:layout="@layout/bugreporting_legal_fragment" />
+    <fragment
+        android:id="@+id/submissionDeletionWarningFragment"
+        android:name="de.rki.coronawarnapp.ui.submission.deletionwarning.SubmissionDeletionWarningFragment"
+        android:label="SubmissionDeletionWarningFragment"
+        tools:layout="@layout/fragment_submission_deletion_warning">
+        <argument
+            android:name="isConsentGiven"
+            android:defaultValue="false"
+            app:argType="boolean" />
+        <argument
+            android:name="coronaTestQrCode"
+            app:argType="de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQRCode" />
+        <action
+            android:id="@+id/action_submissionDeletionWarningFragment_to_submissionDispatcherFragment"
+            app:popUpTo="@id/submissionQRCodeScanFragment"
+            app:popUpToInclusive="true" />
+        <action
+            android:id="@+id/action_submissionDeletionWarningFragment_to_submissionTestResultPendingFragment"
+            app:destination="@id/submissionTestResultPendingFragment"
+            app:popUpTo="@id/mainFragment"
+            app:popUpToInclusive="false">
+            <argument
+                android:name="skipInitialTestResultRefresh"
+                android:defaultValue="true"
+                app:argType="boolean" />
+        </action>
+        <action
+            android:id="@+id/action_submissionDeletionWarningFragment_to_submissionTestResultAvailableFragment"
+            app:destination="@id/submissionTestResultAvailableFragment"
+            app:popUpTo="@id/mainFragment"
+            app:popUpToInclusive="false" />
+        <action
+            android:id="@+id/action_submissionDeletionWarningFragment_to_submissionConsentFragment"
+            app:popUpTo="@id/mainFragment"
+            app:popUpToInclusive="false"
+            app:destination="@id/submissionConsentFragment" />
+    </fragment>
 
     <fragment
         android:id="@+id/checkInsConsentFragment"
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt
index 8a3ef38c0..73c696f80 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt
@@ -43,11 +43,9 @@ class SubmissionConsentViewModelTest {
         every { submissionRepository.giveConsentToSubmission(any()) } just Runs
         every { analyticsKeySubmissionCollector.reportAdvancedConsentGiven() } just Runs
         viewModel = SubmissionConsentViewModel(
-            submissionRepository,
             interoperabilityRepository,
             dispatcherProvider = TestDispatcherProvider(),
             tekHistoryProvider,
-            analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
         )
     }
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModelTest.kt
index 02ed331db..78b2f8517 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModelTest.kt
@@ -15,11 +15,13 @@ import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.mockk
 import io.mockk.verify
-import org.junit.Assert
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.runBlockingTest
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import org.junit.jupiter.api.extension.ExtendWith
 import testhelpers.BaseTest
+import testhelpers.TestDispatcherProvider
 import testhelpers.extensions.InstantExecutorExtension
 import testhelpers.preferences.mockFlowPreference
 
@@ -30,15 +32,23 @@ class SubmissionQRCodeScanViewModelTest : BaseTest() {
     @MockK lateinit var cameraSettings: CameraSettings
     @MockK lateinit var qrCodeValidator: CoronaTestQrCodeValidator
 
+    private val coronaTestFlow = MutableStateFlow<CoronaTest?>(
+        null
+    )
+
     @BeforeEach
     fun setUp() {
         MockKAnnotations.init(this)
+
+        every { submissionRepository.testForType(any()) } returns coronaTestFlow
     }
 
     private fun createViewModel() = SubmissionQRCodeScanViewModel(
+        TestDispatcherProvider(),
         submissionRepository,
         cameraSettings,
-        qrCodeValidator
+        isConsentGiven = true,
+        qrCodeValidator,
     )
 
     @Test
@@ -64,16 +74,17 @@ class SubmissionQRCodeScanViewModelTest : BaseTest() {
         QRCodeCensor.lastGUID = null
 
         viewModel.validateTestGUID(validQrCode)
-        viewModel.scanStatusValue.let { Assert.assertEquals(ScanStatus.SUCCESS, it.value) }
+        viewModel.scanStatusValue.observeForever {}
+        viewModel.scanStatusValue.value shouldBe ScanStatus.SUCCESS
         QRCodeCensor.lastGUID = guid
 
         // invalid guid
         viewModel.validateTestGUID(invalidQrCode)
-        viewModel.scanStatusValue.let { Assert.assertEquals(ScanStatus.INVALID, it.value) }
+        viewModel.scanStatusValue.value shouldBe ScanStatus.INVALID
     }
 
     @Test
-    fun `doDeviceRegistration calls TestResultDataCollector`() {
+    fun `doDeviceRegistration calls TestResultDataCollector`() = runBlockingTest {
         val viewModel = createViewModel()
         val mockResult = mockk<CoronaTestQRCode>().apply {
             every { registrationIdentifier } returns "guid"
-- 
GitLab