Skip to content
This repository has been archived by the owner on Sep 15, 2023. It is now read-only.

Automated testing of certificates #404

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
6 changes: 4 additions & 2 deletions .github/workflows/browserstack_wallet_abn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Build with Gradle
uses: ./.github/actions/gradle_docker
with:
gradle-cmd: wallet:assembleAbnRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}}
gradle-cmd: wallet:assembleAbnRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}} -Ptesting.otp="${{secrets.TESTING_CERTGEN_OTP}}" -Ptesting.keystore="${{secrets.TESTING_CERTGEN_KEYSTORE}}" -Ptesting.keystore-pass="${{secrets.TESTING_CERTGEN_KEYSTORE_PASS}}"
- name: upload artefact to Browserstack
run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/app" -F "file=@wallet/build/outputs/apk/abn/release/wallet-abn-release.apk" >> appResponse.json
- id: upload-app
Expand All @@ -46,7 +46,7 @@ jobs:
- name: Build with Gradle
uses: ./.github/actions/gradle_docker
with:
gradle-cmd: wallet:assembleAbnDebugAndroidTest -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}}
gradle-cmd: wallet:assembleAbnDebugAndroidTest -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}} -Ptesting.otp="${{secrets.TESTING_CERTGEN_OTP}}" -Ptesting.keystore="${{secrets.TESTING_CERTGEN_KEYSTORE}}" -Ptesting.keystore-pass="${{secrets.TESTING_CERTGEN_KEYSTORE_PASS}}"
- name: upload artefact to Browserstack
run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/test-suite" -F "file=@wallet/build/outputs/apk/androidTest/abn/debug/wallet-abn-debug-androidTest.apk" >> testSuiteResponse.json
- id: upload-test-suite
Expand All @@ -68,5 +68,7 @@ jobs:
run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" -d '{"app":"${{ needs.build-app-and-upload.outputs.app-url }}", "testSuite":"${{ needs.build-test-suite-and-upload.outputs.test-url }}", "devices":["Samsung Galaxy S10e-9.0"] , "language":"de", "annotation":["ch.admin.bag.covidcertificate.common.browserstack.Onboarding"] }' -H "Content-Type:application/json"
- name: run onboarding test offline
run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" -d '{"app":"${{ needs.build-app-and-upload.outputs.app-url }}", "testSuite":"${{ needs.build-test-suite-and-upload.outputs.test-url }}", "devices":["Samsung Galaxy S10e-9.0"] , "language":"de", "networkProfile":"airplane-mode", "annotation":["ch.admin.bag.covidcertificate.common.browserstack.Onboarding"] }' -H "Content-Type:application/json"
- name: run tests with generated certificates
run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" -d '{"app":"${{ needs.build-app-and-upload.outputs.app-url }}", "testSuite":"${{ needs.build-test-suite-and-upload.outputs.test-url }}", "devices":["Samsung Galaxy S10e-9.0"] , "language":"de", "annotation":["ch.admin.bag.covidcertificate.common.browserstack.Certificates"] }' -H "Content-Type:application/json"


Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package ch.admin.bag.covidcertificate.common.browserstack

annotation class Certificates
9 changes: 7 additions & 2 deletions wallet/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ android {

buildConfigField "long", "BUILD_TIME", readPropertyWithDefault('buildTimestamp', System.currentTimeMillis()) + 'L'

buildConfigField "String", "OTP", readPropertyWithDefault('testing.otp', '""')
buildConfigField "String", "KEYSTORE", readPropertyWithDefault('testing.keystore', '""')
buildConfigField "String", "KEYSTORE_PASS", readPropertyWithDefault('testing.keystore-pass', '""')

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// The following argument makes the Android Test Orchestrator run its
// "pm clear" command after each test invocation. This command ensures
Expand Down Expand Up @@ -134,8 +138,8 @@ sonarqube {
}

dependencies {
androidTestImplementation 'androidx.test:rules:1.4.1-alpha03'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.0-alpha03'
androidTestImplementation 'androidx.test:rules:1.4.1-alpha05'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.0-alpha05'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'

implementation 'com.google.android.material:material:1.5.0'
Expand All @@ -160,6 +164,7 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0'
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestUtil 'androidx.test:orchestrator:1.4.1'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
/*
* Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/

package ch.admin.bag.covidcertificate.wallet

import androidx.test.espresso.intent.Intents
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.AndroidJUnit4
import ch.admin.bag.covidcertificate.common.browserstack.Certificates
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import java.util.*
import ch.admin.bag.covidcertificate.wallet.VaccineType.*


private val DAYS = 24 * 60 * 60 *1000L
private val HOURS = 60 * 60 *1000L
private val NOW = System.currentTimeMillis()

private val VACCINE_VALIDITY_2OF2_END = 270
private val VACCINE_VALIDITY_1OF1_START = 21
private val VACCINE_VALIDITY_1OF1_END = 270 + VACCINE_VALIDITY_1OF1_START

private val PCR_VALIDITY = 72
private val RAT_VALIDITY = 24

private val RECOVERY_VALIDITY_START = 10
private val RECOVERY_VALIDITY_END = 180

@Certificates
@RunWith(AndroidJUnit4::class)
class CertTest : EspressoUtil() {

@Rule
@JvmField
var mActivityTestRule = ActivityTestRule(MainActivity::class.java)

@Test
fun testValidVaccines() {
Intents.init()
if(needsOnboarding()) doOnboarding()



importCert(
downloadVaccineCert(PFIZER, 3, 3, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(MODERNA, 2, 2, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(ASTRAZENECA, 3, 3, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(NUVOVAXOVID, 3, 3, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(CORONAVAC, 3, 3, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(CORV, 3, 3, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(COVISHIELD, 3, 3, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(COVAXIN, 3, 3, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(R_COVI, 3, 3, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(RECOMBININANT, 3, 3, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(COVOVAX, 3, 3, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(JANSSEN, 1, 1, Date(NOW - (VACCINE_VALIDITY_1OF1_START) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(JANSSEN, 1, 1, Date(NOW - (VACCINE_VALIDITY_2OF2_END-1) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadVaccineCert(JANSSEN, 2, 2, Date(NOW))
)
checkCertValidity(UiValidityState.VALID)

}

@Test
fun testExpiredVaccines() {
Intents.init()
if(needsOnboarding()) doOnboarding()

importCert(
downloadVaccineCert(MODERNA, 2,2, Date( NOW - VACCINE_VALIDITY_2OF2_END * DAYS))
)
checkCertValidity(UiValidityState.EXPIRED)

importCert(
downloadVaccineCert(PFIZER, 3,3, Date( NOW - VACCINE_VALIDITY_2OF2_END * DAYS))
)
checkCertValidity(UiValidityState.EXPIRED)

importCert(
downloadVaccineCert(JANSSEN, 2,2, Date( NOW - VACCINE_VALIDITY_2OF2_END * DAYS))
)
checkCertValidity(UiValidityState.EXPIRED)

importCert(
downloadVaccineCert(JANSSEN, 1,1, Date( NOW - VACCINE_VALIDITY_1OF1_END * DAYS))
)
checkCertValidity(UiValidityState.EXPIRED)

}

@Test
fun testNotYetValidVaccines(){
Intents.init()
if(needsOnboarding()) doOnboarding()

importCert(
downloadVaccineCert(JANSSEN, 1,1, Date( NOW - (VACCINE_VALIDITY_1OF1_START-1) * DAYS))
)
checkCertValidity(UiValidityState.NOT_YET_VALID)

}

@Test
fun testValidTestCerts(){
Intents.init()
if(needsOnboarding()) doOnboarding()
importCert(
downloadTestCert(TestType.PCR, Date(NOW - (PCR_VALIDITY - 1) * HOURS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadTestCert(TestType.RAT, Date(NOW - (RAT_VALIDITY - 1) * HOURS))
)
checkCertValidity(UiValidityState.VALID)
}

@Test
fun testExpiredTestCerts(){
Intents.init()
if(needsOnboarding()) doOnboarding()
//extra time added to account for timezones and summer time
importCert(
downloadTestCert(TestType.PCR, Date(NOW - (PCR_VALIDITY + 2) * HOURS))
)
checkCertValidity(UiValidityState.EXPIRED)

importCert(
downloadTestCert(TestType.RAT, Date(NOW - (RAT_VALIDITY + 2) * HOURS))
)
checkCertValidity(UiValidityState.EXPIRED)
}


@Test
fun testRecoveryCerts(){
Intents.init()
if(needsOnboarding()) doOnboarding()
importCert(
downloadRecoveryCert(Date(NOW - (RECOVERY_VALIDITY_START - 1 ) * DAYS))
)
checkCertValidity(UiValidityState.NOT_YET_VALID)

importCert(
downloadRecoveryCert(Date(NOW - (RECOVERY_VALIDITY_START ) * DAYS))
)
checkCertValidity(UiValidityState.VALID)

importCert(
downloadRecoveryCert(Date(NOW - (RECOVERY_VALIDITY_END - 1 ) * DAYS))
)
checkCertValidity(UiValidityState.VALID)


importCert(
downloadRecoveryCert(Date(NOW - (RECOVERY_VALIDITY_END ) * DAYS))
)
checkCertValidity(UiValidityState.EXPIRED)
}


}
Loading