diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/covidcertificate/test/ui/CertificatesFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/covidcertificate/test/ui/CertificatesFragmentTest.kt index 9d1d1223d2290c7c2fd1becf3a911447d91d5843..c36cb24610b6aabd39782549adc9be355ff38be8 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/covidcertificate/test/ui/CertificatesFragmentTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/covidcertificate/test/ui/CertificatesFragmentTest.kt @@ -46,7 +46,7 @@ class CertificatesFragmentTest : BaseUITest() { @Before fun setup() { MockKAnnotations.init(this, relaxed = true) - every { vaccinatedPerson.fullName } returns "Max Mustermann" + every { vaccinatedPerson.fullName } returns "Andrea Schneider" every { vaccinatedPerson.getMostRecentVaccinationCertificate.expiresAt } returns testDate.plus(Duration.standardDays(365)).toInstant() @@ -148,7 +148,7 @@ class CertificatesFragmentTest : BaseUITest() { ), CovidTestCertificateCard.Item( testDate = testDate, - testPerson = "Max Mustermann" + testPerson = "Andrea Schneider" ) { } ) ) diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/covidcertificate/test/ui/CovidCertificateDetailsFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/covidcertificate/test/ui/CovidCertificateDetailsFragmentTest.kt index ec0076572f455d92bcc69677f6821d3a753f64eb..ad52fa92bba5a5aa7cf6ea6be89462fd26bec974 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/covidcertificate/test/ui/CovidCertificateDetailsFragmentTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/covidcertificate/test/ui/CovidCertificateDetailsFragmentTest.kt @@ -87,7 +87,7 @@ class VaccinationDetailsFragmentTest : BaseUITest() { return MutableLiveData( object : TestCertificate { override val targetName: String - get() = "Mustermann, Max" + get() = "Schneider, Andrea" override val testType: String get() = "SARS-CoV-2-Test" override val testResult: String @@ -111,11 +111,11 @@ class VaccinationDetailsFragmentTest : BaseUITest() { override val qrCode: QrCodeString get() = "" override val firstName: String - get() = "Max" + get() = "Andrea" override val lastName: String - get() = "Mustermann" + get() = "Schneider" override val fullName: String - get() = "Mustermann, Max" + get() = "Schneider, Andrea" override val dateOfBirth: LocalDate get() = LocalDate.parse("18.04.1943 00:00", formatter) override val personIdentifier: CertificatePersonIdentifier diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeData.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeData.kt index e12a5aa4f0fd3a606a469d5119c59b0ec0ce277f..6558306eee081b949efe07097fa9c6776ea9d08b 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeData.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeData.kt @@ -145,7 +145,8 @@ object HomeData { state = TestPositive( testRegisteredAt = Instant.now() ), - onClickAction = {} + onClickAction = {}, + onRemoveAction = {} ) val TEST_NEGATIVE_ITEM = PcrTestNegativeCard.Item( diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/hometestcards/ui/HomeTestCardsFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/hometestcards/ui/HomeTestCardsFragmentViewModel.kt index a91ab2477efe5d3a744713b3dac6397d3d03be1a..95980e35e5f261ad4fc9651ec040f94f6afaf6b0 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/hometestcards/ui/HomeTestCardsFragmentViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/hometestcards/ui/HomeTestCardsFragmentViewModel.kt @@ -45,7 +45,7 @@ class HomeTestCardsFragmentViewModel @AssistedInject constructor( PcrTestInvalidCard.Item(SubmissionStatePCR.TestInvalid) {}, PcrTestErrorCard.Item(SubmissionStatePCR.TestError) {}, PcrTestNegativeCard.Item(SubmissionStatePCR.TestNegative(Instant.now())) {}, - PcrTestPositiveCard.Item(SubmissionStatePCR.TestPositive(Instant.now())) {}, + PcrTestPositiveCard.Item(SubmissionStatePCR.TestPositive(Instant.now()), {}) {}, PcrTestSubmissionDoneCard.Item(SubmissionStatePCR.SubmissionDone(Instant.now())) {}, RapidTestPendingCard.Item(SubmissionStateRAT.TestPending) {}, RapidTestReadyCard.Item(SubmissionStateRAT.TestResultReady) {}, @@ -53,7 +53,7 @@ class HomeTestCardsFragmentViewModel @AssistedInject constructor( RapidTestOutdatedCard.Item(SubmissionStateRAT.TestOutdated) {}, RapidTestErrorCard.Item(SubmissionStateRAT.TestError) {}, RapidTestNegativeCard.Item(SubmissionStateRAT.TestNegative(Instant.now())) {}, - RapidTestPositiveCard.Item(SubmissionStateRAT.TestPositive(Instant.now())) {}, + RapidTestPositiveCard.Item(SubmissionStateRAT.TestPositive(Instant.now()), {}) {}, RapidTestSubmissionDoneCard.Item(SubmissionStateRAT.SubmissionDone(Instant.now())) {} ) ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/Dcc.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/Dcc.kt index 8d8c4b030802099b01ee409d6f422c46f96b1c2c..52d13dd0873100170f356ef936efe1fee2af6456 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/Dcc.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/Dcc.kt @@ -1,9 +1,14 @@ package de.rki.coronawarnapp.covidcertificate.common.certificate import com.google.gson.annotations.SerializedName +import org.joda.time.DateTime import org.joda.time.LocalDate +import org.joda.time.format.DateTimeFormat +import org.joda.time.format.DateTimeFormatterBuilder +import org.joda.time.format.ISODateTimeFormat +import timber.log.Timber -interface Dcc<PayloadType : Dcc.Payload> { +abstract class Dcc<PayloadType : Dcc.Payload> { data class NameData( @SerializedName("fn") internal val familyName: String?, @SerializedName("fnt") internal val familyNameStandardized: String, @@ -23,14 +28,16 @@ interface Dcc<PayloadType : Dcc.Payload> { } } - val version: String - val nameData: NameData - val dob: String + abstract val version: String + abstract val nameData: NameData + abstract val dob: String + // Can't use lazy because GSON will NULL it, as we have no no-args constructor + private var dateOfBirthCache: LocalDate? = null val dateOfBirth: LocalDate - get() = LocalDate.parse(dob) + get() = dateOfBirthCache ?: dob.toLocalDateLeniently().also { dateOfBirthCache = it } - val payloads: List<PayloadType> + abstract val payloads: List<PayloadType> val payload: PayloadType get() = payloads.single() @@ -48,3 +55,21 @@ interface Dcc<PayloadType : Dcc.Payload> { val uniqueCertificateIdentifier: String } } + +internal fun String.toLocalDateLeniently(): LocalDate = try { + LocalDate.parse(this, DateTimeFormat.forPattern("yyyy-MM-dd")) +} catch (e: Exception) { + Timber.w("Irregular date string: %s", this) + try { + DateTime.parse( + this, + DateTimeFormatterBuilder() + .append(ISODateTimeFormat.date()) + .append(ISODateTimeFormat.timeParser().withOffsetParsed()) + .toFormatter() + ).toLocalDate() + } catch (giveUp: Exception) { + Timber.e("Invalid date string: %s", this) + throw giveUp + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestDccV1.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestDccV1.kt index c105167986ab66c556716285921ab8978fddef9b..3ebb7e072cf8b41edb5c1ef43aa64faaf0f016e5 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestDccV1.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestDccV1.kt @@ -6,10 +6,10 @@ import org.joda.time.Instant data class TestDccV1( @SerializedName("ver") override val version: String, - @SerializedName("nam") override val nameData: Dcc.NameData, + @SerializedName("nam") override val nameData: NameData, @SerializedName("dob") override val dob: String, @SerializedName("t") override val payloads: List<TestCertificateData>, -) : Dcc<TestDccV1.TestCertificateData> { +) : Dcc<TestDccV1.TestCertificateData>() { data class TestCertificateData( // Disease or agent targeted, e.g. "tg": "840539006" @@ -34,7 +34,7 @@ data class TestDccV1( @SerializedName("is") override val certificateIssuer: String, // Unique Certificate Identifier, e.g. "ci": "urn:uvci:01:NL:PlA8UWS60Z4RZXVALl6GAZ" @SerializedName("ci") override val uniqueCertificateIdentifier: String - ) : Dcc.Payload { + ) : Payload { val testResultAt: Instant? get() = dr?.let { Instant.parse(it) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDccV1.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDccV1.kt index e231e3ed67601d3b246d406059bea3260c50fb4d..5a163335cbbbe659fd9e43a46339c301e9bbc491 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDccV1.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDccV1.kt @@ -2,16 +2,15 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate import com.google.gson.annotations.SerializedName import de.rki.coronawarnapp.covidcertificate.common.certificate.Dcc -import org.joda.time.DateTime +import de.rki.coronawarnapp.covidcertificate.common.certificate.toLocalDateLeniently import org.joda.time.LocalDate -import timber.log.Timber data class VaccinationDccV1( @SerializedName("ver") override val version: String, @SerializedName("nam") override val nameData: Dcc.NameData, @SerializedName("dob") override val dob: String, @SerializedName("v") override val payloads: List<VaccinationData>, -) : Dcc<VaccinationDccV1.VaccinationData> { +) : Dcc<VaccinationDccV1.VaccinationData>() { data class VaccinationData( // Disease or agent targeted, e.g. "tg": "840539006" @@ -34,30 +33,10 @@ data class VaccinationDccV1( @SerializedName("is") override val certificateIssuer: String, // Unique Certificate Identifier, e.g. "ci": "urn:uvci:01:NL:PlA8UWS60Z4RZXVALl6GAZ" @SerializedName("ci") override val uniqueCertificateIdentifier: String - ) : Dcc.Payload { + ) : Payload { // Can't use lazy because GSON will NULL it, as we have no no-args constructor private var vaccinatedAtCache: LocalDate? = null val vaccinatedAt: LocalDate - get() = vaccinatedAtCache ?: dt.toLocalDateLeniently().also { - vaccinatedAtCache = it - } - } - - // Can't use lazy because GSON will NULL it, as we have no no-args constructor - private var dateOfBirthCache: LocalDate? = null - override val dateOfBirth: LocalDate - get() = dateOfBirthCache ?: dob.toLocalDateLeniently().also { - dateOfBirthCache = it - } -} - -private fun String.toLocalDateLeniently(): LocalDate = try { - LocalDate.parse(this) -} catch (e: Exception) { - Timber.w("Irregular date string: %s", this) - try { - DateTime.parse(this).toLocalDate() - } catch (giveUp: Exception) { - throw giveUp + get() = vaccinatedAtCache ?: dt.toLocalDateLeniently().also { vaccinatedAtCache = it } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/PcrTestPositiveCard.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/PcrTestPositiveCard.kt index 5d52d9acdaaf1c2ebe84b0f9a60e2380357cbef9..ad9112328b512fc3410d615c1928961eb7a597b1 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/PcrTestPositiveCard.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/PcrTestPositiveCard.kt @@ -34,11 +34,13 @@ class PcrTestPositiveCard( itemView.setOnClickListener { curItem.onClickAction(item) } submissionStatusCardPositiveButton.setOnClickListener { itemView.performClick() } + submissionStatusCardPositiveButtonDelete.setOnClickListener { curItem.onRemoveAction() } } data class Item( val state: SubmissionStatePCR.TestPositive, - val onClickAction: (Item) -> Unit + val onClickAction: (Item) -> Unit, + val onRemoveAction: () -> Unit ) : TestResultItem.PCR, HasPayloadDiffer { override fun diffPayload(old: Any, new: Any): Any? = if (old::class == new::class) new else null } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/RapidTestPositiveCard.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/RapidTestPositiveCard.kt index 4b244824e66be08097bea31ec4f26035307f8c82..fe04cbfbc8ed50c2c5d07064eda7254e5c1545e4 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/RapidTestPositiveCard.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/RapidTestPositiveCard.kt @@ -34,11 +34,13 @@ class RapidTestPositiveCard( itemView.setOnClickListener { curItem.onClickAction(item) } submissionStatusCardPositiveButton.setOnClickListener { itemView.performClick() } + submissionStatusCardPositiveButtonDelete.setOnClickListener { curItem.onRemoveAction() } } data class Item( val state: SubmissionStateRAT.TestPositive, - val onClickAction: (Item) -> Unit + val onClickAction: (Item) -> Unit, + val onRemoveAction: () -> Unit ) : TestResultItem.RA, HasPayloadDiffer { override fun diffPayload(old: Any, new: Any): Any? = if (old::class == new::class) new else null } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt index 32109ff0f4f2b481a1e4a87334bc8fc8cb6ad5c8..57a9d2cbf64f8fbbabd0288505c47acb259dc0ce 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt @@ -96,11 +96,18 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject { binding.container.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) } - private fun showRemoveTestDialog(type: CoronaTest.Type) { + private fun showRemoveTestDialog(type: CoronaTest.Type, submission: Boolean) { + val title = + if (submission) R.string.submission_test_result_dialog_remove_test_title + else R.string.submission_test_result_dialog_remove_test_title_no_submission + val msg = + if (submission) R.string.submission_test_result_dialog_remove_test_message + else R.string.submission_test_result_dialog_remove_test_message_no_submission + val removeTestDialog = DialogHelper.DialogInstance( requireActivity(), - R.string.submission_test_result_dialog_remove_test_title, - R.string.submission_test_result_dialog_remove_test_message, + title, + msg, R.string.submission_test_result_dialog_remove_test_button_positive, R.string.submission_test_result_dialog_remove_test_button_negative, positiveButtonFunction = { @@ -108,8 +115,10 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject { } ) DialogHelper.showDialog(removeTestDialog).apply { - getButton(DialogInterface.BUTTON_POSITIVE) - .setTextColor(context.getColorCompat(R.color.colorTextSemanticRed)) + if (submission) { + getButton(DialogInterface.BUTTON_POSITIVE) + .setTextColor(context.getColorCompat(R.color.colorTextSemanticRed)) + } } } @@ -156,7 +165,7 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject { HomeFragmentEvents.GoToRapidTestResultNegativeFragment -> doNavigate( HomeFragmentDirections.actionMainFragmentToSubmissionNegativeAntigenTestResultFragment() ) - is HomeFragmentEvents.ShowDeleteTestDialog -> showRemoveTestDialog(event.type) + is HomeFragmentEvents.ShowDeleteTestDialog -> showRemoveTestDialog(event.type, event.submission) is HomeFragmentEvents.OpenIncompatibleUrl -> openUrl(getString(event.url)) is HomeFragmentEvents.OpenTraceLocationOrganizerGraph -> openPresenceTracingOrganizerGraph(event) is HomeFragmentEvents.GoToTestResultAvailableFragment -> doNavigate( diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt index d044daeb0d0a85966afd023324984c4a46b88330..e38ec25b954eb2ba36dd4c02e83001bdc404ad53 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt @@ -42,7 +42,7 @@ sealed class HomeFragmentEvents { val forceUpdate: Boolean = false ) : HomeFragmentEvents() - data class ShowDeleteTestDialog(val type: CoronaTest.Type) : HomeFragmentEvents() + data class ShowDeleteTestDialog(val type: CoronaTest.Type, val submission: Boolean = true) : HomeFragmentEvents() data class GoToTestResultAvailableFragment(val type: CoronaTest.Type) : HomeFragmentEvents() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt index b75e523a1e49a607e4a4d52fe522fb96a5815d89..c2af97d86b29b396c8cc766d21e9cff02d22824c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt @@ -279,9 +279,11 @@ class HomeFragmentViewModel @AssistedInject constructor( is SubmissionStatePCR.TestResultReady -> PcrTestReadyCard.Item(state) { events.postValue(HomeFragmentEvents.GoToTestResultAvailableFragment(PCR)) } - is SubmissionStatePCR.TestPositive -> PcrTestPositiveCard.Item(state) { - events.postValue(HomeFragmentEvents.GoToTestResultPositiveFragment(PCR)) - } + is SubmissionStatePCR.TestPositive -> PcrTestPositiveCard.Item( + state = state, + onClickAction = { events.postValue(HomeFragmentEvents.GoToTestResultPositiveFragment(PCR)) }, + onRemoveAction = { events.postValue(HomeFragmentEvents.ShowDeleteTestDialog(PCR, false)) } + ) is SubmissionStatePCR.TestNegative -> PcrTestNegativeCard.Item(state) { events.postValue(HomeFragmentEvents.GoToPcrTestResultNegativeFragment(PCR)) } @@ -308,9 +310,11 @@ class HomeFragmentViewModel @AssistedInject constructor( is SubmissionStateRAT.TestResultReady -> RapidTestReadyCard.Item(state) { events.postValue(HomeFragmentEvents.GoToTestResultAvailableFragment(RAPID_ANTIGEN)) } - is SubmissionStateRAT.TestPositive -> RapidTestPositiveCard.Item(state) { - events.postValue(HomeFragmentEvents.GoToTestResultPositiveFragment(RAPID_ANTIGEN)) - } + is SubmissionStateRAT.TestPositive -> RapidTestPositiveCard.Item( + state = state, + onClickAction = { events.postValue(HomeFragmentEvents.GoToTestResultPositiveFragment(RAPID_ANTIGEN)) }, + onRemoveAction = { events.postValue(HomeFragmentEvents.ShowDeleteTestDialog(RAPID_ANTIGEN, false)) } + ) is SubmissionStateRAT.TestNegative -> RapidTestNegativeCard.Item(state) { events.postValue(HomeFragmentEvents.GoToRapidTestResultNegativeFragment) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt index 709851dc71f520e468b27b8f4882a29899eae992..60a7816a55c5db850fe2426482ea28d5927a9307 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt @@ -61,6 +61,10 @@ class SubmissionTestResultPendingFragment : Fragment(R.layout.fragment_submissio } } + viewModel.testCertResultInfo.observe2(this) { result -> + binding.testResultPendingStepsCertificateInfo.setEntryText(result.get(requireContext())) + } + binding.apply { val isPcr = navArgs.testType == CoronaTest.Type.PCR testResultPendingStepsWaitingAntigenResult.isVisible = !isPcr diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingViewModel.kt index ada54dddd635a7c436a98d3a6788c3adc792f0f3..0a7ea7fe96df788be96c9b00af8de2dc9ff166ac 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingViewModel.kt @@ -101,12 +101,16 @@ class SubmissionTestResultPendingViewModel @AssistedInject constructor( val testCertResultInfo: LiveData<LazyString> = testResultFlow .map { - when (it.coronaTest.type) { - CoronaTest.Type.RAPID_ANTIGEN -> + when { + !it.coronaTest.isDccSupportedByPoc -> { R.string.submission_test_result_pending_steps_test_certificate_not_supported_body - CoronaTest.Type.PCR -> when (it.coronaTest.isAdvancedConsentGiven) { - true -> R.string.submission_test_result_pending_steps_test_certificate_not_available_yet_body - false -> R.string.submission_test_result_pending_steps_test_certificate_not_desired_by_user_body + } + else -> { + if (it.coronaTest.isAdvancedConsentGiven) { + R.string.submission_test_result_pending_steps_test_certificate_not_available_yet_body + } else { + R.string.submission_test_result_pending_steps_test_certificate_not_desired_by_user_body + } } }.toResolvingString() } diff --git a/Corona-Warn-App/src/main/res/layout/home_submission_pcr_status_card_positive_not_shared.xml b/Corona-Warn-App/src/main/res/layout/home_submission_pcr_status_card_positive_not_shared.xml index f69b2b2634964a7451b048a8aa7766960d869a27..37f23daf1b8fad85557e3f9e397ad9780eaa5f1d 100644 --- a/Corona-Warn-App/src/main/res/layout/home_submission_pcr_status_card_positive_not_shared.xml +++ b/Corona-Warn-App/src/main/res/layout/home_submission_pcr_status_card_positive_not_shared.xml @@ -84,7 +84,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/body" /> - <ImageView + <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -115,7 +115,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/divider" /> - <ImageView + <ImageView android:id="@+id/contact_icon" style="@style/icon" android:layout_width="wrap_content" @@ -143,7 +143,7 @@ app:layout_constraintStart_toEndOf="@+id/contact_icon" app:layout_constraintTop_toTopOf="@+id/contact_icon" /> - <ImageView + <ImageView android:id="@+id/contagious_icon" style="@style/icon" android:layout_width="wrap_content" @@ -171,7 +171,7 @@ app:layout_constraintStart_toEndOf="@+id/contagious_icon" app:layout_constraintTop_toTopOf="@+id/contagious_icon" /> - <ImageView + <ImageView android:id="@+id/share_icon" style="@style/icon" android:layout_width="wrap_content" @@ -210,4 +210,15 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/share_subtitle" /> + <Button + android:id="@+id/submission_status_card_positive_button_delete" + style="@style/button" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/submission_test_result_positive_no_consent_button_remove_test" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/submission_status_card_positive_button" /> + </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/Corona-Warn-App/src/main/res/layout/home_submission_rapid_status_card_positive_not_shared.xml b/Corona-Warn-App/src/main/res/layout/home_submission_rapid_status_card_positive_not_shared.xml index 380fce89b3016e3ca2d4b27d521cf9f0410672e7..d656a622ac0c20a51b1a0b35daedf011bfb2635e 100644 --- a/Corona-Warn-App/src/main/res/layout/home_submission_rapid_status_card_positive_not_shared.xml +++ b/Corona-Warn-App/src/main/res/layout/home_submission_rapid_status_card_positive_not_shared.xml @@ -84,7 +84,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/body" /> - <ImageView + <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -115,7 +115,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/divider" /> - <ImageView + <ImageView android:id="@+id/prc_icon" style="@style/icon" android:layout_width="wrap_content" @@ -144,7 +144,7 @@ app:layout_constraintStart_toEndOf="@+id/prc_icon" app:layout_constraintTop_toTopOf="@+id/prc_icon" /> - <ImageView + <ImageView android:id="@+id/contact_icon" style="@style/icon" android:layout_width="wrap_content" @@ -172,7 +172,7 @@ app:layout_constraintStart_toEndOf="@+id/contact_icon" app:layout_constraintTop_toTopOf="@+id/contact_icon" /> - <ImageView + <ImageView android:id="@+id/contagious_icon" style="@style/icon" android:layout_width="wrap_content" @@ -200,7 +200,7 @@ app:layout_constraintStart_toEndOf="@+id/contagious_icon" app:layout_constraintTop_toTopOf="@+id/contagious_icon" /> - <ImageView + <ImageView android:id="@+id/share_icon" style="@style/icon" android:layout_width="wrap_content" @@ -239,4 +239,15 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/share_subtitle" /> + <Button + android:id="@+id/submission_status_card_positive_button_delete" + style="@style/button" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/submission_test_result_positive_no_consent_button_remove_test" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/submission_status_card_positive_button" /> + </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/Corona-Warn-App/src/main/res/values-de/strings.xml b/Corona-Warn-App/src/main/res/values-de/strings.xml index 3c2ca8c99dbbce8683002e84e14fedda9ea8a9e0..5c2a6fd7b080a4f9e325f54c9ab3489875fb66b7 100644 --- a/Corona-Warn-App/src/main/res/values-de/strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/strings.xml @@ -309,7 +309,7 @@ <!-- XHED: risk details - infection period logged headling, below behaviors --> <string name="risk_details_subtitle_period_logged">"Dieser Zeitraum wird berücksichtigt."</string> <!-- XHED: risk details - infection period logged information body, below behaviors --> -<!-- Dialog part 1--> + <!-- Dialog part 1--> <string name="risk_details_information_body_period_logged">"Die Berechnung des Infektionsrisikos kann nur für die Zeiträume erfolgen, an denen die Risiko-Ermittlung aktiv war. Die Risiko- Ermittlung sollte daher dauerhaft aktiv sein. Für Ihre Risiko-Ermittlung wird der Zeitraum der letzten 14 Tage betrachtet."</string> <!-- XTXT: risk details - infection period logged information body, under 14 days --> <string name="risk_details_information_body_period_logged_assessment_under_14_days">"Die Corona-Warn-App ist seit %s Tagen installiert. Das Infektionsrisiko wird für Zeiträume berechnet, in denen die Risiko-Ermittlung aktiv ist. Wenn Sie andere Personen getroffen haben und die Risiko-Ermittlung aktiv war, wird Ihr Infektions-Risiko berechnet."</string> @@ -1144,8 +1144,12 @@ <string name="submission_test_result_dialog_tracing_required_button">"OK"</string> <!-- XHED: Dialog title for test removal --> <string name="submission_test_result_dialog_remove_test_title">"Test kann nur einmal gescannt werden"</string> + <!-- XHED: Dialog title for test removal no submission --> + <string name="submission_test_result_dialog_remove_test_title_no_submission">"Sind Sie sicher, dass Sie Ihren Test entfernen wollen?"</string> <!-- YTXT: Dialog text for test removal --> <string name="submission_test_result_dialog_remove_test_message">"Wenn Sie den Test entfernen, können Sie Ihr Testergebnis nicht mehr abrufen. Ihr Testergebnis bekommen Sie vom Testcenter oder Labor, unabhängig von der Gültigkeit des QR-Codes. Bei einem positiven Testergebnis wird auch das zuständige Gesundheitsamt auf dem gesetzlich vorgeschriebenen Weg informiert und sich an Sie wenden."</string> + <!-- YTXT: Dialog text for test removal no submission --> + <string name="submission_test_result_dialog_remove_test_message_no_submission">"Dadurch werden andere nicht gewarnt."</string> <!-- XBUT: Positive button for test removal --> <string name="submission_test_result_dialog_remove_test_button_positive">"Entfernen"</string> <!-- XBUT: Negative button for test removal --> @@ -1234,6 +1238,8 @@ <string name="submission_test_result_positive_no_consent_text_3">Bitte beachten Sie unbedingt die Hinweise des zuständigen Gesundheitsamtes und bleiben Sie zuhause, um andere Personen nicht anzustecken.</string> <!-- XBUT: Button for giving consent for key sharing --> <string name="submission_test_result_positive_no_consent_button_warn_others">Andere warnen</string> + <!-- XBUT: Button for test removal --> + <string name="submission_test_result_positive_no_consent_button_remove_test">Test entfernen</string> <!-- Submission Country Selector --> <!-- XHED: Page title for the submission country selection page --> diff --git a/Corona-Warn-App/src/main/res/values-de/vaccination_strings.xml b/Corona-Warn-App/src/main/res/values-de/vaccination_strings.xml index 5dac53f66a7249075be755c34e1f42a74a3e98f1..fb6b9a2d8abb9aae09b857e3221ad23c26153d4e 100644 --- a/Corona-Warn-App/src/main/res/values-de/vaccination_strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/vaccination_strings.xml @@ -104,7 +104,7 @@ <!-- XTXT: Vaccination Consent title--> <string name="vaccination_consent_title">Ihr Einverständnis</string> <!-- XTXT: Vaccination Consent subtitle--> - <string name="vaccination_consent_headline">"Nachweise hinzufügen"</string> + <string name="vaccination_consent_headline">"Zertifikate hinzufügen"</string> <!-- XTXT: Vaccination Consent subtitle of qr info --> <string name="vaccination_consent_info_subtitle_text">"Fügen Sie ihre digitalen COVID-Zertifikate in der App hinzu, um mit der App Ihren Impfschutz oder ein negatives Testergebnis nachweisen zu können."</string> <!-- XTXT: Vaccination Consent text of qr info --> diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml index 5f70fd55b741fd292e7e66e3375b84278211384a..e58a781dac8d6cd8cd56b5711a12618c7feffe10 100644 --- a/Corona-Warn-App/src/main/res/values/strings.xml +++ b/Corona-Warn-App/src/main/res/values/strings.xml @@ -1144,8 +1144,12 @@ <string name="submission_test_result_dialog_tracing_required_button">"OK"</string> <!-- XHED: Dialog title for test removal --> <string name="submission_test_result_dialog_remove_test_title">"The test can only be scanned once."</string> + <!-- XHED: Dialog title for test removal no submission --> + <string name="submission_test_result_dialog_remove_test_title_no_submission">"Sind Sie sicher, dass Sie Ihren Test entfernen wollen?"</string> <!-- YTXT: Dialog text for test removal --> <string name="submission_test_result_dialog_remove_test_message">"If you delete the test, you can no longer retrieve your test result. You will receive your test result from the test center or laboratory regardless of the validity of the QR code. If you are diagnosed with coronavirus, the public health authority will be notified through the legally prescribed channel and will contact you."</string> + <!-- YTXT: Dialog text for test removal no submission --> + <string name="submission_test_result_dialog_remove_test_message_no_submission">"Dadurch werden andere nicht gewarnt."</string> <!-- XBUT: Positive button for test removal --> <string name="submission_test_result_dialog_remove_test_button_positive">"Delete"</string> <!-- XBUT: Negative button for test removal --> @@ -1234,6 +1238,8 @@ <string name="submission_test_result_positive_no_consent_text_3">"Please be sure to follow the instructions from your public health authority and stay home, so you don’t infect others."</string> <!-- XBUT: Button for giving consent for key sharing --> <string name="submission_test_result_positive_no_consent_button_warn_others">"Warn Others"</string> + <!-- XBUT: Button for test removal --> + <string name="submission_test_result_positive_no_consent_button_remove_test">Test entfernen</string> <!-- Submission Country Selector --> <!-- XHED: Page title for the submission country selection page --> diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationQrCodeTestData.java b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationQrCodeTestData.java index 449bb349b7bde6a840af11ed0f3c40bf32b3981a..a4aa6186f7506191ad2dcf54979198b865ee8485 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationQrCodeTestData.java +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationQrCodeTestData.java @@ -15,4 +15,16 @@ public class VaccinationQrCodeTestData { static public String qrCodeSweden = "HC1:NCFOXN%TSMAHN-HVN8J7UQMJ4/3RZLH62V2G1PC9CMSRH+QKFNTAVD3B19*AJCBMF6.UCOMIN6R%E5BD7HG8CU6O8QGU68ORJSPAEQOIR+SPCVO.28DDQHQ1BW9XX7ZY7NTICZU1*8X/KQ96/-KKTCY73JC3KD3LWT HB3ZC64JX7JQ1LK$2965VMFD-48YI 3533LC4TZ0BR/S09T./0ZYTS P-$0R:67PPDFPVX1R270:6C$Q0R6EOMUF5LDCPF5RBQ746B46O1N646RM9AL5CBVW566LH 469/9-3AKI6%T6LEQ-P6UQK*%NH$RSC9FFFW+7H9N$W2JO2C6S3UJ92KEST.ZJ-8B ZJ83B 2TAAUZZ2LH2%EUBUJZ0KZPIR145%T0YIF0JEYI1DLNCK1627ACW-T%NSY18KT911GL.EHNTI+SB-5A-ARUQNFW$ 2:.NU6W/CU8WDTFVG:BG3JFCSAVH-4V:HP4$0/.D9OV-RM60R7Z3B8PXICK+L/S1P*O:FG"; // vaccinatedAt: Irregular date string: 2021-05-29T15:31:00+02:00 static public String qrCodePoland = "HC1:6BFOXN%TS3DH+M8.IAS0RTAN:2MCID:D42:O%CM9W48+5MOOP-I3Z58MJNC5FAPQHIZC4.OI1RM8ZA.A53XHMKN4NN3F85QNPZ0K8C$JCW0KK.A96UJBC.P2R9CZXIAHAPEDG8C5DL-9C.PDI9309D: C+8DV9CA$DPN0NTICZU80LZW4Z*AK.GNNVR*G0C7PHBO33/X086B QTVINMJJDG3AE3RK38FN:43JON$97*97:L32SJ.L78PJ/FJBINB/S7-SN2HOH03I31M3EG3J%4UZ2UI7Y6T4R2H4T8%K+-8*S2E6J1$48X2-36D-I/2DW9J0$9+Q6X46Q3QR$P2OIC0JBLI+USK3UBVTVIJM/I2OC8ALD-ILOVGKFWZ07Y4 CTZ/3+N0ZUIQJAZGA2:UG%UJMI:TU+MM0W5-R53W12XE2O14P3.2O55O:FA$VKN6HQK3OKPEON4QDN7T*.53%1/HVII9H2JS6VS%J*HBXUCY+TU5EBYL5%T3V79YG%Q90MURRHY5D6$NN6VAQI8OEH.5PQ2WJF"; + + // vaccination date (`dt`) without day (YYYY-MM) + static public String failVaccinatedAtWithoutDay1 = "HC1:6BF$70A90T9WTWGSLKC 4759S-JXYFZJU:6MFBBOF1*70HS8FN07LCF$KWY0LACGEED97TK0F90JPCT3E5JDLA7$Q6E464W5TG6..DX%DZJC6/DTZ9 QE5$CB$DA/DLPCG/DXJDIZAITA9IANB8-+9I3D5 C*KE*PDMPCG/D5 C5IA5N9KECTHGWJC0FDC:5AIA%G7X+AQB9746HS80:54IBQF60R6$A80X6S1BTYACG6M+9XG8KIAWNA91AY%67092L4WJCT3EHS8XJC$+DXJC9WENF6OF63W5VX6+EDXVET3E5$CSUE6O9NPCSW5F/DBWENWE4WEB$D% D3IA4W5646946%96X47.JCP9EJY8L/5M/5546.96D463KC.SC4KCD3DX47B46IL6646H*6Z/E5JD%96IA74R6646407O/EZKEZ96446156O98J41PL2X+2P4OJ1K2:M7GKVJIG%MZ1TC 8X:6UL2C88TL9T DNKP/W5Z3QZ3T/EQHU7A78$JD0TPGDVYW778PC48+ADC%93DHSIVL1"; + // vaccination date (`dt`) without day (YYYY) + static public String failVaccinatedAtWithoutDayAndMonth = "HC1:6BFY70D90T9WTWGSLKC 4759S-JXYFZJU:6MFBBL/0*70HS8FN07LCN%KWY0LACOFED97TK0F90JPCT3E5JDLA7$Q6E464W5TG6..DX%DZJC6/DTZ9 QE5$CB$DA/DLPCG/DXJDIZAITA9IANB8-+9I3D5 C*KE*PDMPCG/D5 C5IA5N9KECTHGWJC0FDC:5AIA%G7X+AQB9746HS80:54IBQF60R6$A80X6S1BTYACG6M+9XG8KIAWNA91AY%67092L4WJCT3EHS8XJC$+DXJC6WENF6OF6%JC QE/IAYJC5LEW34U3ET7DXC9 QE-ED8%E.JCBECB1A-:8$96646AL60A60S6Q$D.UDRYA 96NF6L/5QW6307KQEPD09WEQDD+Q6TW6FA7C466KCN9E%961A6DL6FA7D46$PC5$CUZCY$5Y$527B//UUBM/WJ6$V8.K.XER%O K1 HR5+OA-M/BLRMAFHK7 N4DWV.8HTB9AB:WA/:10N9 1NM*HDFAUURPAI7C4M46$21D8O-YTEF5P F"; + + // German reference case + static public String passGermanReferenceCase = "HC1:6BF+70790T9WTWGSLKC 4759S-JXYFZJU:6MFBBRW1*70HS8FN07LCP+KWY0LACQHED97TK0F90JPCT3E5JDLA7$Q6E464W5TG6..DX%DZJC6/DTZ9 QE5$CB$DA/DLPCG/DXJDIZAITA9IANB8-+9I3D5 C*KE*PDMPCG/D5 C5IA5N9KECTHGWJC0FDC:5AIA%G7X+AQB9746HS80:54IBQF60R6$A80X6S1BTYACG6M+9XG8KIAWNA91AY%67092L4WJCT3EHS8XJC$+DXJCCWENF6OF63W5NW6WF6%JC QE/IAYJC5LEW34U3ET7DXC9 QE-ED8%E.JCBECB1A-:8$96646AL60A60S6Q$D.UDRYA 96NF6L/5QW6307KQEPD09WEQDD+Q6TW6FA7C466KCN9E%961A6DL6FA7D46$PC5$CUZCY$5Y$527B//UUBM/WJ6$V8.K.XER%O K1 HR5+OA-M/BLRMAFHK7 N4DWV.8HTB9AB:WA/:10N9 1NM*HDFAUURPAI7C4M46$21D8O-YTMK2*-F"; + // dates (`dob` and `dt`) with time information at midnight + static public String passDatesWithTimeAtMidnight = "HC1:6BFOXN%TSMAHN-HVN8J7UQMJ4/36 L-AHZR61RO4.S-OPT-IAVCQN68WAYKS.-CF/8X*GBUP:TH$X44WFVR5VVBJZI+EBS7BBYIPZA 1JQEDK8C$2TB-DVQTLTCGJSR4UIIDG4UHT3/%DRWDJZIR9KQ+S9ZIHAPZXI+IA1VCSWC%PD*ZLV6CTJCB6C%*8ZJJY 84IJZJJ1W4*$I*NVPC1LJL4A7%83MKN4NN3F85QNCY0O%0 58:0LPHN6D7LLK*2HG%89UV-0LZ 2S-O:S9UZ4+FJE 4Y3LL/II 0OC9SX0+*B85T%62*5PZD5UE9T0H.3TCNNK1HM+8/AE:PI/E2$4JY/K :SOCJ1HC7%G5/2K$B64FEIA6LF2.GQ*GH988VGBPEH$P$CN583937VNOI34NL0HOJ ZJ83B6+2.H3//T 1JZ0K4LIET32KTN6E84UIXEJ7L78BUDBQEAJJKHHGWC8CVO5/H9QO$$OUBU%I75YC%HI: R*3ETE7WXE5WTOYU/MSH$17+NCDTC-J5MQ447$TUPDWSAN9+6Y6S5EODANF3A+YAY0EMFO+LMYCV$*006JB8J"; + // vaccination date (`dt`) with real time information + static public String passDatesWithRealTimeInfo = "HC1:6BFS80J80T9WTWGSLKC 4759S-JXYFZJU:6MFBBF+5*70HS8FN07LCK.KWY0LACLJED97TK0F90$PC5$CUZCY$5Y$5TPCBEC7ZKW.CUEEY3EAECWGDMXG2QDUW5*MEWUMLPCG/DD3E01ALB81C9%NASB9MN951A JC6/DYOACEC+EDR/OLECMPCG/D8EDETAG+9*NAWB8JPCT3E5JDKA7Q47%964W5-A67:EDOL9WEQDD+Q6TW6FA7C466KCK9E2H9G:6V6BEM6Q$D.UDRYA 96OF6L/5SW6KB7B$D% D3IA4W5646946846.96XJC +D3KC.SCXJCQWEF83846Y969464W5K57.964G72A6646VK5XF6646WJCT3E 6A%JCXQEIN8G/D6LE ZDQZCAJB0LEE4F0ECOPCY8FHZA1+9LZAZM81G72A6 6A2G7O/5L*8U%61H8E46H%6SG8H%6M*8:G85S8D46DM8+A8BM8-Q68+8O98J41PL2X+2P4OJ1K2:M7GKVJIG%MZ1TC 8X:6UL2C88TL9T DNKP/W5Z3QZ3T/EQHU7A78$JD0TPGDVYW778PC48+ADC%9:DHWCJ55"; } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt index b0e8c2fbe520707ff46d6202355714fb1fcb468f..3b07c2bc3eac89027fb3c4d168798382bc1b8511 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt @@ -216,4 +216,57 @@ class VaccinationQRCodeExtractorTest : BaseTest() { mode = Mode.CERT_VAC_STRICT ) } + + @Test + fun `fail vaccinated at date without day`() { + shouldThrow<InvalidVaccinationCertificateException> { + extractor.extract( + VaccinationQrCodeTestData.failVaccinatedAtWithoutDay1, + mode = Mode.CERT_VAC_STRICT + ) + }.errorCode shouldBe InvalidHealthCertificateException.ErrorCode.JSON_SCHEMA_INVALID + } + + @Test + fun `fail vaccinated at date without day and month`() { + shouldThrow<InvalidVaccinationCertificateException> { + extractor.extract( + VaccinationQrCodeTestData.failVaccinatedAtWithoutDayAndMonth, + mode = Mode.CERT_VAC_STRICT + ) + }.errorCode shouldBe InvalidHealthCertificateException.ErrorCode.JSON_SCHEMA_INVALID + } + + @Test + fun `pass german reference case`() { + extractor.extract( + VaccinationQrCodeTestData.passGermanReferenceCase, + mode = Mode.CERT_VAC_STRICT + ).apply { + data.certificate.dateOfBirth shouldBe LocalDate.parse("1964-08-12") + data.certificate.payload.vaccinatedAt shouldBe LocalDate.parse("2021-05-29") + } + } + + @Test + fun `pass vaccination and dob with time at midnight`() { + extractor.extract( + VaccinationQrCodeTestData.passDatesWithTimeAtMidnight, + mode = Mode.CERT_VAC_STRICT + ).apply { + data.certificate.dateOfBirth shouldBe LocalDate.parse("1978-01-26") + data.certificate.payload.vaccinatedAt shouldBe LocalDate.parse("2021-03-09") + } + } + + @Test + fun `pass vaccination date with full timestamp`() { + extractor.extract( + VaccinationQrCodeTestData.passDatesWithRealTimeInfo, + mode = Mode.CERT_VAC_STRICT + ).apply { + data.certificate.dateOfBirth shouldBe LocalDate.parse("1958-11-11") + data.certificate.payload.vaccinatedAt shouldBe LocalDate.parse("2021-03-18") + } + } }