From 6049f4d883027d0fe1ee9122bc799817ff3348db Mon Sep 17 00:00:00 2001 From: Mohamed Metwalli <mohamed.metwalli@sap.com> Date: Thu, 17 Jun 2021 17:03:57 +0200 Subject: [PATCH] Sort persons by name (EXPOSUREAPP-7952) (#3476) * Sort persons by full name * Setup tests * Add tests * Fix test * Update PersonCertificatesData.kt * Fix test Co-authored-by: BMItter <Berndus@gmx.de> --- .../ui/overview/PersonOverviewViewModel.kt | 3 +- .../ui/overview/PersonCertificatesData.kt | 71 +++++++++ .../overview/PersonOverviewViewModelTest.kt | 149 ++++++++++++++++++ 3 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonCertificatesData.kt create mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewViewModelTest.kt diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewViewModel.kt index b6d64f628..7ed8a797b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewViewModel.kt @@ -139,6 +139,7 @@ class PersonOverviewViewModel @AssistedInject constructor( private fun Set<PersonCertificates>.filterNotPending() = this .filter { !it.hasPendingTestCertificate() } + .sortedBy { it.highestPriorityCertificate.fullName } .sortedByDescending { it.isCwaUser } private suspend fun generateQrCode(qrCode: QrCodeString): Bitmap? = try { @@ -148,7 +149,7 @@ class PersonOverviewViewModel @AssistedInject constructor( null } - private fun refreshCertificate(identifier: TestCertificateIdentifier) = + fun refreshCertificate(identifier: TestCertificateIdentifier) = launch { val error = testCertificateRepository.refresh(identifier).mapNotNull { it.error }.singleOrNull() error?.let { events.postValue(ShowRefreshErrorDialog(error)) } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonCertificatesData.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonCertificatesData.kt new file mode 100644 index 000000000..49097d8ba --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonCertificatesData.kt @@ -0,0 +1,71 @@ +package de.rki.coronawarnapp.covidcertificate.person.ui.overview + +import de.rki.coronawarnapp.covidcertificate.common.certificate.CertificatePersonIdentifier +import de.rki.coronawarnapp.covidcertificate.common.qrcode.QrCodeString +import de.rki.coronawarnapp.covidcertificate.person.core.PersonCertificates +import de.rki.coronawarnapp.covidcertificate.test.core.TestCertificate +import org.joda.time.Instant +import org.joda.time.LocalDate + +object PersonCertificatesData { + val certificatesWithPending = mutableSetOf<PersonCertificates>() + .apply { + add(PersonCertificates(listOf(testCertificate(fullName = "Andrea Schneider")))) + add(PersonCertificates(listOf(testCertificate(fullName = "Max Mustermann", isPending = true)))) + add(PersonCertificates(listOf(testCertificate(fullName = "Zeebee")), isCwaUser = true)) + } + val certificatesWithUpdating = mutableSetOf<PersonCertificates>().apply { + add(PersonCertificates(listOf(testCertificate(fullName = "Andrea Schneider")))) + add(PersonCertificates(listOf(testCertificate(fullName = "Zeebee")), isCwaUser = true)) + add( + PersonCertificates( + listOf(testCertificate(fullName = "Max Mustermann", isPending = true, isUpdating = true)) + ) + ) + } + val certificatesWithCwaUser = mutableSetOf<PersonCertificates>().apply { + add(PersonCertificates(listOf(testCertificate(fullName = "Max Mustermann")))) + add(PersonCertificates(listOf(testCertificate(fullName = "Erika Musterfrau")))) + add(PersonCertificates(listOf(testCertificate(fullName = "Andrea Schneider")))) + add(PersonCertificates(listOf(testCertificate(fullName = "Zeebee")), isCwaUser = true)) + add(PersonCertificates(listOf(testCertificate(fullName = "Zeebee A")))) + } + val certificatesWithoutCwaUser = mutableSetOf<PersonCertificates>().apply { + add(PersonCertificates(listOf(testCertificate("Max Mustermann")))) + add(PersonCertificates(listOf(testCertificate("Erika Musterfrau")))) + add(PersonCertificates(listOf(testCertificate("Andrea Schneider")))) + } +} + +fun testCertificate( + fullName: String, + isPending: Boolean = false, + isUpdating: Boolean = false +) = object : TestCertificate { + override val targetName: String = "targetName" + override val testType: String = "testType" + override val testResult: String = "testResult" + override val testName: String = "testName" + override val testNameAndManufacturer: String = "testNameAndManufacturer" + override val sampleCollectedAt: Instant = Instant.EPOCH + override val testCenter: String = "" + override val registeredAt: Instant = Instant.EPOCH + override val isUpdatingData: Boolean = isUpdating + override val isCertificateRetrievalPending: Boolean = isPending + override val issuer: String = "issuer" + override val issuedAt: Instant = Instant.EPOCH + override val expiresAt: Instant = Instant.EPOCH + override val qrCode: QrCodeString = "qrCode" + override val firstName: String = "firstName" + override val lastName: String = "lastName" + override val fullName: String = fullName + override val dateOfBirth: LocalDate = LocalDate.now() + override val personIdentifier = CertificatePersonIdentifier( + dateOfBirth = LocalDate(System.currentTimeMillis()), + lastNameStandardized = "lastNameStandardized", + firstNameStandardized = "firstNameStandardized" + ) + override val certificateIssuer: String = "certificateIssuer" + override val certificateCountry: String = "certificateCountry" + override val certificateId: String = "certificateId" +} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewViewModelTest.kt new file mode 100644 index 000000000..5aea17846 --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewViewModelTest.kt @@ -0,0 +1,149 @@ +package de.rki.coronawarnapp.covidcertificate.person.ui.overview + +import android.content.Context +import de.rki.coronawarnapp.contactdiary.util.getLocale +import de.rki.coronawarnapp.covidcertificate.person.core.PersonCertificatesProvider +import de.rki.coronawarnapp.covidcertificate.person.ui.overview.items.CovidTestCertificatePendingCard +import de.rki.coronawarnapp.covidcertificate.person.ui.overview.items.PersonCertificateCard +import de.rki.coronawarnapp.covidcertificate.test.core.TestCertificateRepository +import de.rki.coronawarnapp.covidcertificate.valueset.ValueSetsRepository +import de.rki.coronawarnapp.presencetracing.checkins.qrcode.QrCodeGenerator +import de.rki.coronawarnapp.ui.presencetracing.attendee.checkins.permission.CameraPermissionProvider +import io.kotest.matchers.shouldBe +import io.mockk.MockKAnnotations +import io.mockk.Runs +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.just +import io.mockk.mockk +import io.mockk.mockkStatic +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flowOf +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.extensions.getOrAwaitValue +import java.util.Locale + +@ExtendWith(InstantExecutorExtension::class) +class PersonOverviewViewModelTest : BaseTest() { + + @MockK lateinit var qrCodeGenerator: QrCodeGenerator + @MockK lateinit var personCertificatesProvider: PersonCertificatesProvider + @MockK lateinit var testCertificateRepository: TestCertificateRepository + @MockK lateinit var refreshResult: TestCertificateRepository.RefreshResult + @MockK lateinit var valueSetsRepository: ValueSetsRepository + @MockK lateinit var context: Context + @MockK lateinit var cameraPermissionProvider: CameraPermissionProvider + + @BeforeEach + fun setup() { + MockKAnnotations.init(this, true) + mockkStatic("de.rki.coronawarnapp.contactdiary.util.ContactDiaryExtensionsKt") + coEvery { testCertificateRepository.refresh(any()) } returns setOf(refreshResult) + coEvery { qrCodeGenerator.createQrCode(any(), any(), any(), any(), any()) } returns mockk() + every { personCertificatesProvider.personCertificates } returns emptyFlow() + every { refreshResult.error } returns null + every { testCertificateRepository.certificates } returns emptyFlow() + every { context.getLocale() } returns Locale.GERMAN + every { valueSetsRepository.triggerUpdateValueSet(any()) } just Runs + every { cameraPermissionProvider.deniedPermanently } returns flowOf(false) + } + + @Test + fun `refreshCertificate causes an error dialog event`() { + val error = mockk<Exception>() + every { refreshResult.error } returns error + + instance.apply { + refreshCertificate("Identifier") + events.getOrAwaitValue() shouldBe ShowRefreshErrorDialog(error) + } + } + + @Test + fun `refreshCertificate triggers refresh operation in repo`() { + instance.refreshCertificate("Identifier") + coVerify { testCertificateRepository.refresh(any()) } + } + + @Test + fun `deleteTestCertificate deletes certificates from repo`() { + coEvery { testCertificateRepository.deleteCertificate(any()) } just Runs + instance.apply { + deleteTestCertificate("Identifier") + } + + coEvery { testCertificateRepository.deleteCertificate(any()) } + } + + @Test + fun onScanQrCode() { + instance.apply { + onScanQrCode() + events.getOrAwaitValue() shouldBe ScanQrCode + } + } + + @Test + fun `Sorting - List has pending certificate`() { + every { personCertificatesProvider.personCertificates } returns + flowOf(PersonCertificatesData.certificatesWithPending) + instance.personCertificates.getOrAwaitValue().apply { + (get(0) as CovidTestCertificatePendingCard.Item).apply { certificate.fullName shouldBe "Max Mustermann" } + (get(1) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Zeebee" } + (get(2) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Andrea Schneider" } + } + } + + @Test + fun `Sorting - List has pending & updating certificate`() { + every { personCertificatesProvider.personCertificates } returns + flowOf(PersonCertificatesData.certificatesWithUpdating) + instance.personCertificates.getOrAwaitValue().apply { + (get(0) as CovidTestCertificatePendingCard.Item).apply { certificate.fullName shouldBe "Max Mustermann" } + (get(1) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Zeebee" } + (get(2) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Andrea Schneider" } + } + } + + @Test + fun `Sorting - List has no CWA user`() { + every { personCertificatesProvider.personCertificates } returns + flowOf(PersonCertificatesData.certificatesWithoutCwaUser) + instance.personCertificates.getOrAwaitValue().apply { + (get(0) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Andrea Schneider" } + (get(1) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Erika Musterfrau" } + (get(2) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Max Mustermann" } + } + } + + @Test + fun `Sorting - List has CWA user`() { + every { personCertificatesProvider.personCertificates } returns + flowOf(PersonCertificatesData.certificatesWithCwaUser) + instance.personCertificates.getOrAwaitValue().apply { + (get(0) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Zeebee" } // CWA user + (get(1) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Andrea Schneider" } + (get(2) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Erika Musterfrau" } + (get(3) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Max Mustermann" } + (get(4) as PersonCertificateCard.Item).apply { certificate.fullName shouldBe "Zeebee A" } + } + } + + private val instance + get() = PersonOverviewViewModel( + dispatcherProvider = TestDispatcherProvider(), + testCertificateRepository = testCertificateRepository, + certificatesProvider = personCertificatesProvider, + qrCodeGenerator = qrCodeGenerator, + valueSetsRepository = valueSetsRepository, + context = context, + cameraPermissionProvider = cameraPermissionProvider + ) +} -- GitLab