From db86126f096ee988607382a0831c4739267b21d6 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Thu, 20 Mar 2025 12:59:15 +0100 Subject: [PATCH 01/33] test [only test] --- Jenkinsfile | 21 +++++++++++++++++++++ scripts/browserstackJenkins.sh | 3 ++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index b746c05f8d..43b2551d0a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -58,6 +58,11 @@ pipeline { } } stage('Lint Check') { + when { + expression { + return onlyUiTest() != true + } + } steps { script { echo 'Running Ktlint' @@ -66,6 +71,11 @@ pipeline { } } stage('Unit tests') { + when { + expression { + return onlyUiTest() != true + } + } environment { ANDROID_HOME = '/opt/android-sdk' } @@ -89,6 +99,11 @@ pipeline { stage('Run tests') { parallel { stage('Deploy and run Form Tests') { + when { + expression { + return onlyUiTest() != true + } + } environment { BROWSERSTACK = credentials('android-browserstack') form_apk = sh(returnStdout: true, script: 'find form/build/outputs -iname "*.apk" | sed -n 1p') @@ -212,4 +227,10 @@ def isSkipSizeCheck() { def prTitle = env.CHANGE_TITLE ?: "" def prDescription = env.CHANGE_DESCRIPTION ?: "" return (prTitle.contains("[skip size]") || prDescription.contains("[skip size]")) +} + +def onlyUiTest(){ + def prTitle = env.CHANGE_TITLE ?: "" + def prDescription = env.CHANGE_DESCRIPTION ?: "" + return (prTitle.contains("[only test]") || prDescription.contains("[only test]")) } \ No newline at end of file diff --git a/scripts/browserstackJenkins.sh b/scripts/browserstackJenkins.sh index b8ffe7e4ab..74cebc105c 100644 --- a/scripts/browserstackJenkins.sh +++ b/scripts/browserstackJenkins.sh @@ -32,8 +32,9 @@ json=$(jq -n \ --arg deviceLogs "$browserstack_deviceLogs" \ --arg allowDeviceMockServer "$browserstack_allowDeviceMockServer" \ --argjson shards "$shards" \ + --arg singleRunnerInvocation "$browserstack_singleRunnerInvocation" \ --arg buildTag "$buildTag" \ - '{devices: $devices, app: $app_url, testSuite: $test_url, class: $class, logs: $logs, video: $video, local: $loc, localIdentifier: $locId, gpsLocation: $gpsLocation, language: $language, locale: $locale, deviceLogs: $deviceLogs, allowDeviceMockServer: $allowDeviceMockServer, shards: $shards, buildTag: $buildTag}') + '{devices: $devices, app: $app_url, testSuite: $test_url, class: $class, logs: $logs, video: $video, local: $loc, localIdentifier: $locId, gpsLocation: $gpsLocation, language: $language, locale: $locale, deviceLogs: $deviceLogs, allowDeviceMockServer: $allowDeviceMockServer, shards: $shards,singleRunnerInvocation: $singleRunnerInvocation, buildTag: $buildTag}') test_execution_response="$(curl -X POST https://api-cloud.browserstack.com/app-automate/espresso/v2/build -d \ "$json" -H "Content-Type: application/json" -u "$BROWSERSTACK_USR:$BROWSERSTACK_PSW")" From 31bc3bcb680d358929907bfaf6f32c2bbbdec0e2 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Thu, 20 Mar 2025 13:52:30 +0100 Subject: [PATCH 02/33] test [only test] --- .../java/org/dhis2/usescases/programevent/ProgramEventTest.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt index 53f39779b3..6d5ebf0683 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt @@ -51,6 +51,7 @@ class ProgramEventTest : BaseTest() { } @Test + @Ignore("Not passing with single test runner") fun shouldOpenExistingEvent() { val eventDate = "07/04/2024" val eventOrgUnit = "Ngelehun CHC" @@ -67,6 +68,7 @@ class ProgramEventTest : BaseTest() { } @Test + @Ignore("Not passing with single test runner") fun shouldCompleteAnEventAndReopenIt() { val eventDate = "07/04/2024" @@ -93,6 +95,7 @@ class ProgramEventTest : BaseTest() { } @Test + @Ignore("Not passing with single test runner") fun shouldDeleteEvent() { val eventDate = "07/04/2024" @@ -116,6 +119,7 @@ class ProgramEventTest : BaseTest() { } @Test + @Ignore("Not passing with single test runner") fun shouldOpenEventAndShowMap() { prepareProgramAndLaunchActivity(informationCampaign) From e426b37e3d67a298c4e4b78b94bb950a8b4a0d19 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Thu, 20 Mar 2025 14:49:10 +0100 Subject: [PATCH 03/33] test [only test] --- .../java/org/dhis2/usescases/searchte/SearchTETest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt b/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt index 4ee392e327..7053ea2b96 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt @@ -78,6 +78,7 @@ class SearchTETest : BaseTest() { } @Test + @Ignore("Not passing with single test runner") fun shouldShowErrorWhenCanNotFindSearchResult() { mockWebServerRobot.addResponse( ResponseController.GET, From b3036d11dc3314927ddc3663a332180b8db42b61 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Thu, 20 Mar 2025 15:17:04 +0100 Subject: [PATCH 04/33] test [only test] --- app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt | 1 + .../eventDetails/EventInitialTest.kt | 2 ++ .../java/org/dhis2/usescases/programevent/ProgramEventTest.kt | 4 ---- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt index defba3b47b..b585595088 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt @@ -125,6 +125,7 @@ open class BaseTest { closeKeyboard() disableIntents() cleanPreferences() + cleanLocalDatabase() cleanKeystore() stopMockServer() unregisterCountingIdlingResource() diff --git a/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt b/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt index 6f57ba5407..c366322cee 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt @@ -51,6 +51,7 @@ import org.mockito.kotlin.mock import java.text.SimpleDateFormat import java.util.Date import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.domain.ConfigurePeriodSelector +import org.junit.Ignore class EventInitialTest { @@ -214,6 +215,7 @@ class EventInitialTest { ) @Test + @Ignore("Not passing with single test runner") fun shouldAddStandardIntervalDaysIfScheduleIntervalIsGreaterThanZero() { viewModel = initViewModel( periodType = null, diff --git a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt index 6d5ebf0683..3ba94f79a4 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt @@ -4,7 +4,6 @@ import android.Manifest import android.content.Intent import androidx.compose.ui.test.junit4.createComposeRule import androidx.test.core.app.ApplicationProvider -import org.dhis2.AppTest.Companion.DB_TO_IMPORT import org.dhis2.lazyActivityScenarioRule import org.dhis2.usescases.BaseTest import org.dhis2.usescases.programEventDetail.ProgramEventDetailActivity @@ -113,9 +112,6 @@ class ProgramEventTest : BaseTest() { checkEventWasDeleted(eventDate) } composeTestRule.waitForIdle() - rule.getScenario().onActivity { - context.applicationContext.deleteDatabase(DB_TO_IMPORT) - } } @Test From 83ebe38e37314f14b1317880bc3e441d56091d31 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Fri, 21 Mar 2025 08:02:13 +0100 Subject: [PATCH 05/33] test [only test] --- scripts/config_jenkins.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/config_jenkins.init b/scripts/config_jenkins.init index 1f09348aef..478b6a720c 100644 --- a/scripts/config_jenkins.init +++ b/scripts/config_jenkins.init @@ -10,7 +10,7 @@ browserstack_language="en" browserstack_locale="en" browserstack_deviceLogs=true browserstack_singleRunnerInvocation=true -browserstack_number_of_parallel_executions=2 +browserstack_number_of_parallel_executions=1 bitrise_max_parallel_builds=3 browserstack_class="\"org.dhis2.usescases.UseCaseTestsSuite\",\"org.dhis2.usescases.FlowTestsSuite\"" browserstack_allowDeviceMockServer=true From 646565fc80c4423e2af1e04962688a7e80cc3346 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Fri, 21 Mar 2025 09:03:21 +0100 Subject: [PATCH 06/33] test [only test] --- app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt index 100cace246..1f8a820e52 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt @@ -22,6 +22,7 @@ import org.junit.Ignore import org.junit.Rule import org.junit.Test +@Ignore("Not passing with single test runner") class LoginTest : BaseTest() { @get:Rule From 3de2d0b72e31d3617e44c24c7af7d70f9d15135e Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Fri, 21 Mar 2025 09:37:54 +0100 Subject: [PATCH 07/33] test [only test] --- app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt b/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt index 69f4581637..b0e0bbcc1d 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt @@ -14,6 +14,7 @@ import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) +@Ignore("Not passing with single test runner") class PinTest : BaseTest() { @get:Rule From 5d190fa8a2fd2008b409a432ff62fab67ba61920 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Fri, 21 Mar 2025 13:33:23 +0100 Subject: [PATCH 08/33] restore workInfoStatus --- .../java/org/dhis2/usescases/sync/SyncActivityTest.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/androidTest/java/org/dhis2/usescases/sync/SyncActivityTest.kt b/app/src/androidTest/java/org/dhis2/usescases/sync/SyncActivityTest.kt index a89404a409..af87a246ff 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/sync/SyncActivityTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/sync/SyncActivityTest.kt @@ -14,6 +14,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import java.util.UUID +import org.junit.After @RunWith(AndroidJUnit4::class) class SyncActivityTest : BaseTest() { @@ -29,6 +30,12 @@ class SyncActivityTest : BaseTest() { ApplicationProvider.getApplicationContext().mutableWorkInfoStatuses } + @After + override fun teardown() { + super.teardown() + workInfoStatusLiveData.postValue(emptyList()) + } + @Test fun shouldShowMetadataErrorDialog() { From 7231f3cd0bbd6b766b96c17c263e51745140331e Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Thu, 27 Mar 2025 13:24:57 +0100 Subject: [PATCH 09/33] remove ignore --- .../eventsWithoutRegistration/eventDetails/EventInitialTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt b/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt index c366322cee..c00b42148d 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt @@ -215,7 +215,6 @@ class EventInitialTest { ) @Test - @Ignore("Not passing with single test runner") fun shouldAddStandardIntervalDaysIfScheduleIntervalIsGreaterThanZero() { viewModel = initViewModel( periodType = null, From 78b3048138040c6cb142d8937294c739ed8ce843 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Thu, 27 Mar 2025 15:17:38 +0100 Subject: [PATCH 10/33] remove ignore --- .../eventsWithoutRegistration/eventDetails/EventInitialTest.kt | 1 - .../java/org/dhis2/usescases/searchte/SearchTETest.kt | 1 - 2 files changed, 2 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt b/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt index c00b42148d..6f57ba5407 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt @@ -51,7 +51,6 @@ import org.mockito.kotlin.mock import java.text.SimpleDateFormat import java.util.Date import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.domain.ConfigurePeriodSelector -import org.junit.Ignore class EventInitialTest { diff --git a/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt b/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt index 7053ea2b96..cdde8e3462 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt @@ -51,7 +51,6 @@ class SearchTETest : BaseTest() { setupMockServer() } - @Ignore("Test needs to be fixed in ANDROAPP-6459") @Test fun shouldSuccessfullySearchByName() { mockWebServerRobot.addResponse( From 445533a399149854d2a65d2fd52f7ad8237a00f5 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Thu, 27 Mar 2025 16:01:09 +0100 Subject: [PATCH 11/33] add ignore --- .../java/org/dhis2/usescases/searchte/SearchTETest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt b/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt index cdde8e3462..7053ea2b96 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt @@ -51,6 +51,7 @@ class SearchTETest : BaseTest() { setupMockServer() } + @Ignore("Test needs to be fixed in ANDROAPP-6459") @Test fun shouldSuccessfullySearchByName() { mockWebServerRobot.addResponse( From 65f6fab437d40f12ae342cf704e31f9b0caf538c Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Fri, 28 Mar 2025 07:08:19 +0100 Subject: [PATCH 12/33] remove ProgramEventTest ignores --- .../org/dhis2/usescases/programevent/ProgramEventTest.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt index 3ba94f79a4..b6c54f2cb8 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt @@ -50,7 +50,6 @@ class ProgramEventTest : BaseTest() { } @Test - @Ignore("Not passing with single test runner") fun shouldOpenExistingEvent() { val eventDate = "07/04/2024" val eventOrgUnit = "Ngelehun CHC" @@ -67,7 +66,6 @@ class ProgramEventTest : BaseTest() { } @Test - @Ignore("Not passing with single test runner") fun shouldCompleteAnEventAndReopenIt() { val eventDate = "07/04/2024" @@ -94,7 +92,6 @@ class ProgramEventTest : BaseTest() { } @Test - @Ignore("Not passing with single test runner") fun shouldDeleteEvent() { val eventDate = "07/04/2024" @@ -111,11 +108,9 @@ class ProgramEventTest : BaseTest() { programEventsRobot(composeTestRule) { checkEventWasDeleted(eventDate) } - composeTestRule.waitForIdle() } @Test - @Ignore("Not passing with single test runner") fun shouldOpenEventAndShowMap() { prepareProgramAndLaunchActivity(informationCampaign) From 91677cc6b6303252610dbbb76d06a466566fbe3d Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Fri, 28 Mar 2025 08:58:39 +0100 Subject: [PATCH 13/33] restart database --- app/src/androidTest/java/org/dhis2/AppTest.kt | 6 ++--- .../java/org/dhis2/DBTestLoader.kt | 4 +-- .../java/org/dhis2/usescases/BaseTest.kt | 25 ++++++++++--------- .../eventList/EventListScreen.kt | 1 - .../eventList/EventListViewModel.kt | 8 ++++++ 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/AppTest.kt b/app/src/androidTest/java/org/dhis2/AppTest.kt index abfb14fd8e..99ff2f2832 100644 --- a/app/src/androidTest/java/org/dhis2/AppTest.kt +++ b/app/src/androidTest/java/org/dhis2/AppTest.kt @@ -24,13 +24,13 @@ class AppTest : App() { @Override override fun onCreate() { - populateDBIfNeeded() + populateDBIfNeeded(false) super.onCreate() } - private fun populateDBIfNeeded() { + fun populateDBIfNeeded(forceCleanDatabase: Boolean) { TestingInjector.provideDBImporter(applicationContext).apply { - copyDatabaseFromAssetsIfNeeded() + copyDatabaseFromAssetsIfNeeded(forceCleanDatabase) } } diff --git a/app/src/androidTest/java/org/dhis2/DBTestLoader.kt b/app/src/androidTest/java/org/dhis2/DBTestLoader.kt index 1d5cff96c4..252aac9a73 100644 --- a/app/src/androidTest/java/org/dhis2/DBTestLoader.kt +++ b/app/src/androidTest/java/org/dhis2/DBTestLoader.kt @@ -11,11 +11,11 @@ import java.io.OutputStream class DBTestLoader(private val context: Context) { - fun copyDatabaseFromAssetsIfNeeded() { + fun copyDatabaseFromAssetsIfNeeded(force: Boolean = false) { val databasePath = context.applicationInfo?.dataDir + "/databases" val file = File("$databasePath/$DB_NAME") - if (file.exists()) { + if (file.exists() and !force) { Timber.i("Database won't be copy, it already exits") return } diff --git a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt index b585595088..52429f6a1a 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt @@ -73,11 +73,24 @@ open class BaseTest { @Before @Throws(Exception::class) open fun setUp() { + (context.applicationContext as AppTest).populateDBIfNeeded(true) injectDependencies() registerCountingIdlingResource() setupCredentials() } + @After + @Throws(Exception::class) + open fun teardown() { + closeKeyboard() + disableIntents() + cleanPreferences() + cleanLocalDatabase() + cleanKeystore() + stopMockServer() + unregisterCountingIdlingResource() + } + private fun injectDependencies() { TestingInjector.apply { keyStoreRobot = providesKeyStoreRobot(context) @@ -119,18 +132,6 @@ open class BaseTest { mockWebServerRobot.start() } - @After - @Throws(Exception::class) - open fun teardown() { - closeKeyboard() - disableIntents() - cleanPreferences() - cleanLocalDatabase() - cleanKeystore() - stopMockServer() - unregisterCountingIdlingResource() - } - fun enableIntents() { if (!isIntentsEnable) { Intents.init() diff --git a/app/src/main/java/org/dhis2/usescases/programEventDetail/eventList/EventListScreen.kt b/app/src/main/java/org/dhis2/usescases/programEventDetail/eventList/EventListScreen.kt index 6a448b8adf..77a94c33e8 100644 --- a/app/src/main/java/org/dhis2/usescases/programEventDetail/eventList/EventListScreen.kt +++ b/app/src/main/java/org/dhis2/usescases/programEventDetail/eventList/EventListScreen.kt @@ -102,6 +102,5 @@ fun EventListScreen( } } } - EventListIdlingResourceSingleton.decrement() } } diff --git a/app/src/main/java/org/dhis2/usescases/programEventDetail/eventList/EventListViewModel.kt b/app/src/main/java/org/dhis2/usescases/programEventDetail/eventList/EventListViewModel.kt index f352e09210..92b34b71c1 100644 --- a/app/src/main/java/org/dhis2/usescases/programEventDetail/eventList/EventListViewModel.kt +++ b/app/src/main/java/org/dhis2/usescases/programEventDetail/eventList/EventListViewModel.kt @@ -7,9 +7,11 @@ import androidx.paging.PagingData import androidx.paging.map import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.withContext import org.dhis2.commons.filters.FilterManager import org.dhis2.commons.ui.model.ListCardUiModel @@ -71,6 +73,12 @@ class EventListViewModel( } }.flowOn(dispatchers.io()) }.flowOn(dispatchers.io()) + .onEach { + EventListIdlingResourceSingleton.decrement() + } + .catch { + EventListIdlingResourceSingleton.decrement() + } val eventList = _eventList From 96f253420c1e680933276cca596e9aea06b42b57 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Fri, 28 Mar 2025 09:38:24 +0100 Subject: [PATCH 14/33] restart database --- app/src/androidTest/java/org/dhis2/AppTest.kt | 13 ++++++++++--- .../java/org/dhis2/usescases/BaseTest.kt | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/AppTest.kt b/app/src/androidTest/java/org/dhis2/AppTest.kt index 99ff2f2832..a70bd7d8df 100644 --- a/app/src/androidTest/java/org/dhis2/AppTest.kt +++ b/app/src/androidTest/java/org/dhis2/AppTest.kt @@ -24,16 +24,23 @@ class AppTest : App() { @Override override fun onCreate() { - populateDBIfNeeded(false) + populateDBIfNeeded() super.onCreate() } - fun populateDBIfNeeded(forceCleanDatabase: Boolean) { + private fun populateDBIfNeeded() { TestingInjector.provideDBImporter(applicationContext).apply { - copyDatabaseFromAssetsIfNeeded(forceCleanDatabase) + copyDatabaseFromAssetsIfNeeded() } } + fun restoreDB() { + TestingInjector.provideDBImporter(applicationContext).apply { + copyDatabaseFromAssetsIfNeeded(true) + } + setUpServerComponent() + } + @Override override fun setUpServerComponent() { D2Manager.setTestingDatabase(MOCK_SERVER_URL, DB_TO_IMPORT, USERNAME) diff --git a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt index 52429f6a1a..a113f6c90f 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt @@ -73,7 +73,7 @@ open class BaseTest { @Before @Throws(Exception::class) open fun setUp() { - (context.applicationContext as AppTest).populateDBIfNeeded(true) + (context.applicationContext as AppTest).restoreDB() injectDependencies() registerCountingIdlingResource() setupCredentials() From fc45a6ec79b018adfcb2fff31451f5235fac94d8 Mon Sep 17 00:00:00 2001 From: Pablo Pajuelo Cabezas Date: Fri, 28 Mar 2025 11:05:28 +0100 Subject: [PATCH 15/33] add logs --- .../java/org/dhis2/usescases/BaseTest.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt index a113f6c90f..01f06f7666 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt @@ -35,9 +35,12 @@ import org.junit.After import org.junit.Before import org.junit.ClassRule import org.junit.Rule +import org.junit.rules.TestName import org.junit.rules.Timeout +import timber.log.Timber import java.util.concurrent.TimeUnit + open class BaseTest { @JvmField @@ -55,6 +58,9 @@ open class BaseTest { @get:Rule val timeout: Timeout = Timeout(120000, TimeUnit.MILLISECONDS) + @get: Rule + var testName: TestName = TestName() + @get:Rule var permissionRule = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) { GrantPermissionRule.grant( @@ -73,6 +79,8 @@ open class BaseTest { @Before @Throws(Exception::class) open fun setUp() { + val currentTest = testName.methodName + Timber.tag("RUNNER_LOG").d("Executing Before Actions for $currentTest") (context.applicationContext as AppTest).restoreDB() injectDependencies() registerCountingIdlingResource() @@ -82,6 +90,8 @@ open class BaseTest { @After @Throws(Exception::class) open fun teardown() { + val currentTest = testName.methodName + Timber.tag("RUNNER_LOG").d("Executing After Actions for $currentTest") closeKeyboard() disableIntents() cleanPreferences() @@ -178,7 +188,9 @@ open class BaseTest { } fun cleanLocalDatabase() { - (context.applicationContext as AppTest).deleteDatabase(DB_TO_IMPORT) + val deleted = (context.applicationContext as AppTest).deleteDatabase(DB_TO_IMPORT) + val currentTest = testName.methodName + Timber.tag("RUNNER_LOG").d("CleanDataBaseResult. Is deleted? answer: $deleted for $currentTest") } protected fun enableFeatureConfigValue(feature: Feature) { From 6f28f35b75b98c5006e0fe90f3382f25679d5730 Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 1 Apr 2025 13:46:53 +0200 Subject: [PATCH 16/33] test: Ignore shouldDeleteEvent test --- .../java/org/dhis2/usescases/programevent/ProgramEventTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt index b6c54f2cb8..b65b52dafb 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt @@ -91,6 +91,7 @@ class ProgramEventTest : BaseTest() { } } + @Ignore("Deletes an element and make open existing event fail") @Test fun shouldDeleteEvent() { val eventDate = "07/04/2024" From f4920975cecd1aeed0440841715f2d4004a9ac43 Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 1 Apr 2025 14:50:16 +0200 Subject: [PATCH 17/33] test: Remove instrumented log --- .../dhis2/usescases/datasets/DataSetTest.kt | 60 ++----------------- 1 file changed, 4 insertions(+), 56 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/datasets/DataSetTest.kt b/app/src/androidTest/java/org/dhis2/usescases/datasets/DataSetTest.kt index adb2d8f624..cad87bb8e6 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/datasets/DataSetTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/datasets/DataSetTest.kt @@ -1,10 +1,7 @@ package org.dhis2.usescases.datasets import android.app.Instrumentation -import android.os.Bundle import androidx.compose.ui.test.junit4.createComposeRule -import androidx.compose.ui.test.onRoot -import androidx.compose.ui.test.printToLog import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import kotlinx.coroutines.test.runTest @@ -113,12 +110,13 @@ class DataSetTest : BaseTest() { } private fun checkCustomTitleIsDisplayed() { - logStep("Starting check custom title is displayed") dataSetDetailRobot(composeTestRule) { assertItemWithTextIsDisplayed("Line end: Custom Title", true) - assertItemWithTextIsDisplayed("Line end: Custom Subtitle test a very long subtitle", true) + assertItemWithTextIsDisplayed( + "Line end: Custom Subtitle test a very long subtitle", + true + ) } - logStep("Finish check custom title is displayed") } private suspend fun waitForTableToBeVisible() { @@ -131,7 +129,6 @@ class DataSetTest : BaseTest() { private suspend fun checkContentBoxesAreDisplayed() { tableIsVisible() - logStep("Starting Check content boxes above and below the table") // Check top and bottom content is displayed in initial section dataSetDetailRobot(composeTestRule) { assertItemWithTextIsDisplayed("CONTENT BEFORE 1:", true) @@ -153,8 +150,6 @@ class DataSetTest : BaseTest() { scrollToItemWithText("CONTENT AFTER 2:") assertItemWithTextIsDisplayed("CONTENT AFTER 2:", true) } - logStep("Finish Check content boxes above and below the table") - } @Test @@ -278,9 +273,6 @@ class DataSetTest : BaseTest() { cellId: String, legendData: List ) { - - logStep("Starting checking legends") - dataSetTableRobot(composeTestRule) { clickOnCell(tableId, cellId) assertInputDialogIsDisplayed() @@ -306,12 +298,9 @@ class DataSetTest : BaseTest() { pressOnInputDialogDismiss() closeKeyboard() } - - logStep("Finished checking legends") } private fun checkCategoryIsMovedToRow() { - logStep("Starting Check category is moved to row") dataSetTableRobot(composeTestRule) { categoryToRowList.forEach { data -> clickOnSection(data.sectionIndex, data.sectionName) @@ -321,62 +310,47 @@ class DataSetTest : BaseTest() { assertCategoryHeaderIsDisplayed(data.headerTestTags) } } - logStep("Finish Check category is moved to row") - } private fun runOptionalValidationRules() { - logStep("Starting Run Optional Validation Rules") dataSetTableRobot(composeTestRule) { acceptOptionalValidationRule() } - logStep("Finished Run Optional Validation Rules") } private fun checkValidationBarIsDisplayedAndReview() { - logStep("Starting Check Validation Rule errors and review") - dataSetTableRobot(composeTestRule) { assertValidationBarIsDisplayed() expandValidationRulesErrorDialog() tapOnReview() } - logStep("Finished Check Validation Rule errors and review") } private fun checkValidationBarIsDisplayedAndCompleteAnyway() { - logStep("Starting Check Validation Rule errors and complete anyway") - dataSetTableRobot(composeTestRule) { assertValidationBarIsDisplayed() expandValidationRulesErrorDialog() tapOnCompleteAnyway() } - logStep("Finished Check Validation Rule errors and complete anyway") } private fun checkDataSetInstanceHasBeenCreated( period: String, orgUnit: String, ) { - logStep("Starting Check dataset instance has been created") dataSetDetailRobot(composeTestRule) { checkDataSetInList(period, orgUnit) } - logStep("Finished Check dataset instance has been created") } private fun checkMandatoryDialogIsDisplayedAndAcceptStep() { - logStep("Starting Checking Mandatory Dialog") dataSetTableRobot(composeTestRule) { checkMandatoryDialogIsDisplayed() acceptMandatoryDialog() } - logStep("Finished Checking Mandatory Dialog") } private fun checkAutomaticGroupingDisabled() { - logStep("Starting Check Automatic Grouping") dataSetTableRobot(composeTestRule) { disableAutomaticGroupingList.forEach { data -> clickOnSection(data.sectionIndex, data.sectionName) @@ -384,12 +358,9 @@ class DataSetTest : BaseTest() { assertTablesAreDisplayedInOrder(data.tableIdTestTags) } } - logStep("Finish Check Automatic Grouping") - } private fun checkPivotOptions() { - logStep("Starting check Pivot Options") dataSetTableRobot(composeTestRule) { pivotTestingData.forEach { data -> clickOnSection(data.sectionIndex, data.sectionName) @@ -398,39 +369,30 @@ class DataSetTest : BaseTest() { assertTableRows(data.rowTestTags) } } - logStep("Finish check Pivot Options") } private fun checkCompleteDialogIsDisplayedAndAttemptToCompleteStep() { - logStep("Starting Trying to complete dataset") - dataSetTableRobot(composeTestRule) { checkCompleteDialogIsDisplayed() tapOnCompleteButton() } - logStep("Finished Trying to complete dataset") } private fun tapOnSaveButtonStep() { - logStep("Starting Tap on Done button") - dataSetTableRobot(composeTestRule) { tapOnSaveButton() } - logStep("Finished Tap on Done button") } private fun enterDataSetStep( uid: String, name: String, ) { - logStep("Starting Entering dataset $name") startDataSetDetailActivity( dataSetUid = uid, dataSetName = name, rule = ruleDataSetDetail ) - logStep("Finished Entering dataset $name") } private fun dataSetInstanceInChronologicalOrderStep() { @@ -479,8 +441,6 @@ class DataSetTest : BaseTest() { value: String, inputTestTag: String, ) { - logStep("Starting Enter value: $value into cell ${dataElementDescription ?: cellId}") - dataSetTableRobot(composeTestRule) { clickOnCell(tableId, cellId) assertInputDialogIsDisplayed() @@ -492,7 +452,6 @@ class DataSetTest : BaseTest() { assertCellHasValue(tableId, cellId, value) } - logStep("Finished Enter value: $value into cell ${dataElementDescription ?: cellId}") } private fun enterTwoSequentialSteps( @@ -503,7 +462,6 @@ class DataSetTest : BaseTest() { inputTestTag: String, ) { - logStep("Starting Enter value: $firstValue into cell $firstCellId") dataSetTableRobot(composeTestRule) { clickOnCell(tableId, firstCellId) typeOnInputDialog(firstValue, inputTestTag) @@ -511,7 +469,6 @@ class DataSetTest : BaseTest() { typeOnInputDialog(secondValue, inputTestTag) pressOnInputDialogDismiss() } - logStep("Finished Enter value") } private fun checkTotalsUpdated( @@ -585,8 +542,6 @@ class DataSetTest : BaseTest() { period: String, catCombo: String? = null, ) { - logStep("Starting Creating dataset instance $period") - dataSetDetailRobot(composeTestRule) { clickOnAddDataSet() } @@ -616,12 +571,5 @@ class DataSetTest : BaseTest() { dataSetInitialRobot { clickOnActionButton() } - logStep("Finished Creating dataset instance $period") - } - - private fun logStep(message: String) { - val bundle = Bundle() - bundle.putString("Step", message) - instrumentation.sendStatus(0, bundle) } } From 558d5e9719e0a47dcc559398028d8e18144d7d19 Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 1 Apr 2025 15:33:08 +0200 Subject: [PATCH 18/33] test: Rename some stages --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 43b2551d0a..bf1c670c00 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -98,7 +98,7 @@ pipeline { } stage('Run tests') { parallel { - stage('Deploy and run Form Tests') { + stage('Run Form Tests') { when { expression { return onlyUiTest() != true @@ -120,7 +120,7 @@ pipeline { } } } - stage('Deploy and Run UI Tests') { + stage('Run UI Tests in portrait') { environment { BROWSERSTACK = credentials('android-browserstack') app_apk = sh(returnStdout: true, script: 'find app/build/outputs/apk/dhis2/debug -iname "*.apk"') From df9a1879cd85844ffcc416a952d47c36d8a52bcb Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 2 Apr 2025 09:59:58 +0200 Subject: [PATCH 19/33] test: [ANDROAPP-6869] comment restore database action --- app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt index 01f06f7666..a2f92fb372 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt @@ -81,7 +81,7 @@ open class BaseTest { open fun setUp() { val currentTest = testName.methodName Timber.tag("RUNNER_LOG").d("Executing Before Actions for $currentTest") - (context.applicationContext as AppTest).restoreDB() +// (context.applicationContext as AppTest).restoreDB() injectDependencies() registerCountingIdlingResource() setupCredentials() From 0f00834b76fe4b5aa3686ed1dd466a641f8f24b8 Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 2 Apr 2025 10:48:30 +0200 Subject: [PATCH 20/33] test: [ANDROAPP-6869] launch pin Test --- app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt b/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt index b0e0bbcc1d..5ed7683f1b 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt @@ -14,7 +14,7 @@ import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) -@Ignore("Not passing with single test runner") +//@Ignore("Not passing with single test runner") class PinTest : BaseTest() { @get:Rule @@ -51,6 +51,7 @@ class PinTest : BaseTest() { } } + @Ignore("Blocks the access to the database") @Test fun shouldSuccessfullyLoginIfClickForgotYourCode() { enableIntents() @@ -65,6 +66,8 @@ class PinTest : BaseTest() { homeRobot { checkLogInIsLaunched() } + preferencesRobot.saveValue(SESSION_LOCKED, false) + preferencesRobot.saveValue(PIN, null) } fun startActivity() { From 5d62e9d7adad3e948f7e3d93f4da304d37f99c91 Mon Sep 17 00:00:00 2001 From: andresmr Date: Thu, 3 Apr 2025 10:47:50 +0200 Subject: [PATCH 21/33] test: [ANDROAPP-6869] uncomment LoginTest --- app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt | 1 - app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt | 1 - 2 files changed, 2 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt index 1f8a820e52..100cace246 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt @@ -22,7 +22,6 @@ import org.junit.Ignore import org.junit.Rule import org.junit.Test -@Ignore("Not passing with single test runner") class LoginTest : BaseTest() { @get:Rule diff --git a/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt b/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt index 5ed7683f1b..6fc903d2ca 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/pin/PinTest.kt @@ -14,7 +14,6 @@ import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) -//@Ignore("Not passing with single test runner") class PinTest : BaseTest() { @get:Rule From 6e5df5e86fa364d40034fc343c50e6432769d0c1 Mon Sep 17 00:00:00 2001 From: andresmr Date: Thu, 3 Apr 2025 11:50:54 +0200 Subject: [PATCH 22/33] test: [ANDROAPP-6869] Set credentials after LoginTest --- app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt | 1 - .../java/org/dhis2/usescases/login/LoginTest.kt | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt index a2f92fb372..e7bffc12a8 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt @@ -81,7 +81,6 @@ open class BaseTest { open fun setUp() { val currentTest = testName.methodName Timber.tag("RUNNER_LOG").d("Executing Before Actions for $currentTest") -// (context.applicationContext as AppTest).restoreDB() injectDependencies() registerCountingIdlingResource() setupCredentials() diff --git a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt index 100cace246..6233805664 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt @@ -7,6 +7,7 @@ import androidx.compose.ui.test.junit4.createComposeRule import androidx.test.core.app.ApplicationProvider import androidx.test.espresso.intent.Intents.intending import androidx.test.espresso.intent.matcher.IntentMatchers +import org.dhis2.common.keystore.KeyStoreRobot import org.dhis2.commons.Constants.EXTRA_DATA import org.dhis2.commons.prefs.Preference.Companion.PIN import org.dhis2.commons.prefs.Preference.Companion.SESSION_LOCKED @@ -36,6 +37,12 @@ class LoginTest : BaseTest() { D2Manager.removeCredentials() } + + override fun teardown() { + super.teardown() + D2Manager.setCredentials(KeyStoreRobot.KEYSTORE_USERNAME, KeyStoreRobot.PASSWORD) + } + @Test fun loginFlow() { mockWebServerRobot.addResponse(GET, API_ME_PATH, API_ME_RESPONSE_OK) From cd2a89b43291fbc9a883d18e8fa51dc8adaa2d63 Mon Sep 17 00:00:00 2001 From: andresmr Date: Thu, 3 Apr 2025 15:18:28 +0200 Subject: [PATCH 23/33] test: [ANDROAPP-6869] ignore login flow in LoginTest --- app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt index 6233805664..a72d3e4f29 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt @@ -43,6 +43,7 @@ class LoginTest : BaseTest() { D2Manager.setCredentials(KeyStoreRobot.KEYSTORE_USERNAME, KeyStoreRobot.PASSWORD) } + @Ignore("To check if makes the tests fail") @Test fun loginFlow() { mockWebServerRobot.addResponse(GET, API_ME_PATH, API_ME_RESPONSE_OK) From 9586535e8023fc2ad64907b4d11a2a3ed46670e7 Mon Sep 17 00:00:00 2001 From: andresmr Date: Fri, 4 Apr 2025 07:50:29 +0200 Subject: [PATCH 24/33] test: [ANDROAPP-6869] Review loginFlow --- .../androidTest/java/org/dhis2/usescases/login/LoginTest.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt index a72d3e4f29..9d177e3d29 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt @@ -43,7 +43,6 @@ class LoginTest : BaseTest() { D2Manager.setCredentials(KeyStoreRobot.KEYSTORE_USERNAME, KeyStoreRobot.PASSWORD) } - @Ignore("To check if makes the tests fail") @Test fun loginFlow() { mockWebServerRobot.addResponse(GET, API_ME_PATH, API_ME_RESPONSE_OK) @@ -101,7 +100,7 @@ class LoginTest : BaseTest() { acceptTrackerDialog() clickYesOnAcceptTrackerDialog() } - cleanDatabase() +// cleanDatabase() } @Test From 40bf877297ecdb5b8c90002d209d955553de1065 Mon Sep 17 00:00:00 2001 From: andresmr Date: Fri, 4 Apr 2025 12:48:00 +0200 Subject: [PATCH 25/33] build: reduce browserstask waiting time --- app/src/androidTest/java/org/dhis2/AppTest.kt | 5 +++++ app/src/androidTest/java/org/dhis2/DBTestLoader.kt | 1 + app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt | 1 + .../androidTest/java/org/dhis2/usescases/login/LoginTest.kt | 3 ++- scripts/config_jenkins.init | 2 +- 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/AppTest.kt b/app/src/androidTest/java/org/dhis2/AppTest.kt index a70bd7d8df..179600be26 100644 --- a/app/src/androidTest/java/org/dhis2/AppTest.kt +++ b/app/src/androidTest/java/org/dhis2/AppTest.kt @@ -1,6 +1,8 @@ package org.dhis2 +import android.os.Bundle import androidx.lifecycle.MutableLiveData +import androidx.test.platform.app.InstrumentationRegistry import androidx.work.WorkInfo import org.dhis2.common.di.TestingInjector import org.dhis2.common.keystore.KeyStoreRobot @@ -24,6 +26,9 @@ class AppTest : App() { @Override override fun onCreate() { + val bundle = Bundle() + bundle.putString("RUNNER_LOG", "AppTest - OnCreate()") + InstrumentationRegistry.getInstrumentation().sendStatus(0, bundle) populateDBIfNeeded() super.onCreate() } diff --git a/app/src/androidTest/java/org/dhis2/DBTestLoader.kt b/app/src/androidTest/java/org/dhis2/DBTestLoader.kt index 252aac9a73..cff717391f 100644 --- a/app/src/androidTest/java/org/dhis2/DBTestLoader.kt +++ b/app/src/androidTest/java/org/dhis2/DBTestLoader.kt @@ -20,6 +20,7 @@ class DBTestLoader(private val context: Context) { return } try { + Timber.tag("RUNNER_LOG").d("Copying database") val input = InstrumentationRegistry.getInstrumentation() .context.assets.open("databases/$DB_NAME_TEST") val output = FileOutputStream("$databasePath/$DB_NAME") diff --git a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt index e7bffc12a8..01f06f7666 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt @@ -81,6 +81,7 @@ open class BaseTest { open fun setUp() { val currentTest = testName.methodName Timber.tag("RUNNER_LOG").d("Executing Before Actions for $currentTest") + (context.applicationContext as AppTest).restoreDB() injectDependencies() registerCountingIdlingResource() setupCredentials() diff --git a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt index 9d177e3d29..bb3e2bfd65 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt @@ -43,6 +43,7 @@ class LoginTest : BaseTest() { D2Manager.setCredentials(KeyStoreRobot.KEYSTORE_USERNAME, KeyStoreRobot.PASSWORD) } + @Ignore("makes the tests fail") @Test fun loginFlow() { mockWebServerRobot.addResponse(GET, API_ME_PATH, API_ME_RESPONSE_OK) @@ -100,7 +101,7 @@ class LoginTest : BaseTest() { acceptTrackerDialog() clickYesOnAcceptTrackerDialog() } -// cleanDatabase() + cleanDatabase() } @Test diff --git a/scripts/config_jenkins.init b/scripts/config_jenkins.init index 478b6a720c..c5aaada253 100644 --- a/scripts/config_jenkins.init +++ b/scripts/config_jenkins.init @@ -1,5 +1,5 @@ build_time_average_short=60 -build_time_average_long=660 +build_time_average_long=180 polling_interval=10 browserstack_device_list="\"Samsung Galaxy S10-9.0\"" browserstack_device_list_landscape="\"Samsung Galaxy Tab S6-9.0\"" From c5f3d05cf446cc6c007ffeffabf8b747b386ad4b Mon Sep 17 00:00:00 2001 From: andresmr Date: Mon, 7 Apr 2025 11:21:20 +0200 Subject: [PATCH 26/33] test: [ANDROAPP-6869] remove instrumentation login in AppTest --- app/src/androidTest/java/org/dhis2/AppTest.kt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/AppTest.kt b/app/src/androidTest/java/org/dhis2/AppTest.kt index 179600be26..4cb2dd7b3a 100644 --- a/app/src/androidTest/java/org/dhis2/AppTest.kt +++ b/app/src/androidTest/java/org/dhis2/AppTest.kt @@ -1,8 +1,6 @@ package org.dhis2 -import android.os.Bundle import androidx.lifecycle.MutableLiveData -import androidx.test.platform.app.InstrumentationRegistry import androidx.work.WorkInfo import org.dhis2.common.di.TestingInjector import org.dhis2.common.keystore.KeyStoreRobot @@ -12,8 +10,8 @@ import org.dhis2.commons.schedulers.SchedulersProviderImpl import org.dhis2.data.server.ServerModule import org.dhis2.data.user.UserModule import org.dhis2.usescases.BaseTest.Companion.MOCK_SERVER_URL -import org.dhis2.usescases.sync.MockedWorkManagerModule import org.dhis2.usescases.sync.MockedWorkManagerController +import org.dhis2.usescases.sync.MockedWorkManagerModule import org.dhis2.utils.analytics.AnalyticsModule import org.hisp.dhis.android.core.D2Manager import org.hisp.dhis.android.core.D2Manager.blockingInstantiateD2 @@ -26,9 +24,6 @@ class AppTest : App() { @Override override fun onCreate() { - val bundle = Bundle() - bundle.putString("RUNNER_LOG", "AppTest - OnCreate()") - InstrumentationRegistry.getInstrumentation().sendStatus(0, bundle) populateDBIfNeeded() super.onCreate() } From a9b488cd0ea48fd68b0505e7342d4a3706e636ad Mon Sep 17 00:00:00 2001 From: andresmr Date: Mon, 7 Apr 2025 12:35:00 +0200 Subject: [PATCH 27/33] test: [ANDROAPP-6869] remove parallel executions --- Jenkinsfile | 116 +++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 60 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index bf1c670c00..9aaab02570 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -96,71 +96,67 @@ pipeline { } } } - stage('Run tests') { - parallel { - stage('Run Form Tests') { - when { - expression { - return onlyUiTest() != true - } - } - environment { - BROWSERSTACK = credentials('android-browserstack') - form_apk = sh(returnStdout: true, script: 'find form/build/outputs -iname "*.apk" | sed -n 1p') - form_apk_path = "${env.WORKSPACE}/${form_apk}" - buildTag = "${env.GIT_BRANCH} - form" - } - steps { - dir("${env.WORKSPACE}/scripts"){ - script { - echo 'Browserstack deployment and running Form module tests' - sh 'chmod +x browserstackJenkinsForm.sh' - sh './browserstackJenkinsForm.sh' - } - } - } - } - stage('Run UI Tests in portrait') { - environment { - BROWSERSTACK = credentials('android-browserstack') - app_apk = sh(returnStdout: true, script: 'find app/build/outputs/apk/dhis2/debug -iname "*.apk"') - test_apk = sh(returnStdout: true, script: 'find app/build/outputs/apk/androidTest -iname "*.apk"') - app_apk_path = "${env.WORKSPACE}/${app_apk}" - test_apk_path = "${env.WORKSPACE}/${test_apk}" - buildTag = "${env.GIT_BRANCH}" - } - steps { - dir("${env.WORKSPACE}/scripts"){ - script { - echo 'Browserstack deployment and running tests' - sh 'chmod +x browserstackJenkins.sh' - sh './browserstackJenkins.sh' - } - } + stage('Run Form Tests') { + when { + expression { + return onlyUiTest() != true } } - stage('Run UI Tests in Landscape') { - when { - expression { - return JOB_NAME.startsWith('android-multibranch-PUSH') + environment { + BROWSERSTACK = credentials('android-browserstack') + form_apk = sh(returnStdout: true, script: 'find form/build/outputs -iname "*.apk" | sed -n 1p') + form_apk_path = "${env.WORKSPACE}/${form_apk}" + buildTag = "${env.GIT_BRANCH} - form" + } + steps { + dir("${env.WORKSPACE}/scripts"){ + script { + echo 'Browserstack deployment and running Form module tests' + sh 'chmod +x browserstackJenkinsForm.sh' + sh './browserstackJenkinsForm.sh' } } - environment { - BROWSERSTACK = credentials('android-browserstack') - app_apk = sh(returnStdout: true, script: 'find app/build/outputs/apk/dhis2/debug -iname "*.apk"') - test_apk = sh(returnStdout: true, script: 'find app/build/outputs/apk/androidTest -iname "*.apk"') - app_apk_path = "${env.WORKSPACE}/${app_apk}" - test_apk_path = "${env.WORKSPACE}/${test_apk}" - buildTag = "${env.GIT_BRANCH}" + } + } + stage('Run UI Tests in portrait') { + environment { + BROWSERSTACK = credentials('android-browserstack') + app_apk = sh(returnStdout: true, script: 'find app/build/outputs/apk/dhis2/debug -iname "*.apk"') + test_apk = sh(returnStdout: true, script: 'find app/build/outputs/apk/androidTest -iname "*.apk"') + app_apk_path = "${env.WORKSPACE}/${app_apk}" + test_apk_path = "${env.WORKSPACE}/${test_apk}" + buildTag = "${env.GIT_BRANCH}" + } + steps { + dir("${env.WORKSPACE}/scripts"){ + script { + echo 'Browserstack deployment and running tests' + sh 'chmod +x browserstackJenkins.sh' + sh './browserstackJenkins.sh' } - steps { - dir("${env.WORKSPACE}/scripts"){ - script { - echo 'Browserstack deployment and running tests' - sh 'chmod +x browserstackJenkinsLandscape.sh' - sh './browserstackJenkinsLandscape.sh' - } - } + } + } + } + stage('Run UI Tests in Landscape') { + when { + expression { + return JOB_NAME.startsWith('android-multibranch-PUSH') + } + } + environment { + BROWSERSTACK = credentials('android-browserstack') + app_apk = sh(returnStdout: true, script: 'find app/build/outputs/apk/dhis2/debug -iname "*.apk"') + test_apk = sh(returnStdout: true, script: 'find app/build/outputs/apk/androidTest -iname "*.apk"') + app_apk_path = "${env.WORKSPACE}/${app_apk}" + test_apk_path = "${env.WORKSPACE}/${test_apk}" + buildTag = "${env.GIT_BRANCH}" + } + steps { + dir("${env.WORKSPACE}/scripts"){ + script { + echo 'Browserstack deployment and running tests' + sh 'chmod +x browserstackJenkinsLandscape.sh' + sh './browserstackJenkinsLandscape.sh' } } } From 20694f12d8825970c96abc86e012dbdddbf4b81b Mon Sep 17 00:00:00 2001 From: andresmr Date: Mon, 7 Apr 2025 15:22:03 +0200 Subject: [PATCH 28/33] test: [ANDROAPP-6869] remove only test --- Jenkinsfile | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 9aaab02570..1713b27bfb 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -58,11 +58,6 @@ pipeline { } } stage('Lint Check') { - when { - expression { - return onlyUiTest() != true - } - } steps { script { echo 'Running Ktlint' @@ -71,11 +66,6 @@ pipeline { } } stage('Unit tests') { - when { - expression { - return onlyUiTest() != true - } - } environment { ANDROID_HOME = '/opt/android-sdk' } @@ -97,11 +87,6 @@ pipeline { } } stage('Run Form Tests') { - when { - expression { - return onlyUiTest() != true - } - } environment { BROWSERSTACK = credentials('android-browserstack') form_apk = sh(returnStdout: true, script: 'find form/build/outputs -iname "*.apk" | sed -n 1p') @@ -224,9 +209,3 @@ def isSkipSizeCheck() { def prDescription = env.CHANGE_DESCRIPTION ?: "" return (prTitle.contains("[skip size]") || prDescription.contains("[skip size]")) } - -def onlyUiTest(){ - def prTitle = env.CHANGE_TITLE ?: "" - def prDescription = env.CHANGE_DESCRIPTION ?: "" - return (prTitle.contains("[only test]") || prDescription.contains("[only test]")) -} \ No newline at end of file From f09fc9cac336b855eca13d59be89194be849c45e Mon Sep 17 00:00:00 2001 From: andresmr Date: Mon, 7 Apr 2025 15:22:26 +0200 Subject: [PATCH 29/33] test: [ANDROAPP-6869] change LoginTest order --- .../androidTest/java/org/dhis2/usescases/UseCaseTestsSuite.kt | 2 +- app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/UseCaseTestsSuite.kt b/app/src/androidTest/java/org/dhis2/usescases/UseCaseTestsSuite.kt index 8d49b3beda..e32c8a7ece 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/UseCaseTestsSuite.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/UseCaseTestsSuite.kt @@ -24,7 +24,6 @@ import org.junit.runners.Suite EnrollmentTest::class, EventInitialTest::class, EventTest::class, - LoginTest::class, MainTest::class, PinTest::class, ProgramEventTest::class, @@ -33,5 +32,6 @@ import org.junit.runners.Suite SyncActivityTest::class, TeiDashboardTest::class, SchedulingDialogUiTest::class, + LoginTest::class, ) class UseCaseTestsSuite diff --git a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt index bb3e2bfd65..be3f0d9be2 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/login/LoginTest.kt @@ -19,7 +19,6 @@ import org.hisp.dhis.android.core.D2Manager import org.hisp.dhis.android.core.mockwebserver.ResponseController.Companion.API_ME_PATH import org.hisp.dhis.android.core.mockwebserver.ResponseController.Companion.API_SYSTEM_INFO_PATH import org.hisp.dhis.android.core.mockwebserver.ResponseController.Companion.GET -import org.junit.Ignore import org.junit.Rule import org.junit.Test @@ -43,7 +42,6 @@ class LoginTest : BaseTest() { D2Manager.setCredentials(KeyStoreRobot.KEYSTORE_USERNAME, KeyStoreRobot.PASSWORD) } - @Ignore("makes the tests fail") @Test fun loginFlow() { mockWebServerRobot.addResponse(GET, API_ME_PATH, API_ME_RESPONSE_OK) From 13feaf2e608a8c812ac7a0d07ad0da8dbc756d3a Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 8 Apr 2025 08:28:56 +0200 Subject: [PATCH 30/33] test: [ANDROAPP-6869] change suite order --- scripts/config_jenkins.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/config_jenkins.init b/scripts/config_jenkins.init index c5aaada253..0ba9bd07e0 100644 --- a/scripts/config_jenkins.init +++ b/scripts/config_jenkins.init @@ -12,6 +12,6 @@ browserstack_deviceLogs=true browserstack_singleRunnerInvocation=true browserstack_number_of_parallel_executions=1 bitrise_max_parallel_builds=3 -browserstack_class="\"org.dhis2.usescases.UseCaseTestsSuite\",\"org.dhis2.usescases.FlowTestsSuite\"" +browserstack_class="\"org.dhis2.usescases.FlowTestsSuite\",\"org.dhis2.usescases.UseCaseTestsSuite\"" browserstack_allowDeviceMockServer=true browserstack_deviceOrientation="landscape" \ No newline at end of file From b902a2148b1e888f969a89b036b2fdbdd2878f44 Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 8 Apr 2025 09:06:45 +0200 Subject: [PATCH 31/33] test: [ANDROAPP-6869] fix shouldDeleteEvent test --- .../java/org/dhis2/usescases/programevent/ProgramEventTest.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt index b65b52dafb..e0c46e9314 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt @@ -91,10 +91,9 @@ class ProgramEventTest : BaseTest() { } } - @Ignore("Deletes an element and make open existing event fail") @Test fun shouldDeleteEvent() { - val eventDate = "07/04/2024" + val eventDate = "26/11/2021" prepareProgramAndLaunchActivity(antenatalCare) From 99189ab9125f518d247008e756609fc89f8bd216 Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 9 Apr 2025 12:46:13 +0200 Subject: [PATCH 32/33] test: [ANDROAPP-6869] Set counter idling resources when loading the dataset instance list --- .../datasetDetail/datasetList/DataSetListViewModel.kt | 8 +++++++- .../mobile/commons/coroutine/AndroidIdlingResource.kt | 7 ++++++- .../dhis2/mobile/commons/coroutine/CoroutineTracker.kt | 2 -- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/dhis2/usescases/datasets/datasetDetail/datasetList/DataSetListViewModel.kt b/app/src/main/java/org/dhis2/usescases/datasets/datasetDetail/datasetList/DataSetListViewModel.kt index e9a611cfec..a96bd2cc74 100644 --- a/app/src/main/java/org/dhis2/usescases/datasets/datasetDetail/datasetList/DataSetListViewModel.kt +++ b/app/src/main/java/org/dhis2/usescases/datasets/datasetDetail/datasetList/DataSetListViewModel.kt @@ -15,6 +15,7 @@ import org.dhis2.commons.matomo.Categories import org.dhis2.commons.matomo.Labels import org.dhis2.commons.matomo.MatomoAnalyticsController import org.dhis2.commons.viewmodel.DispatcherProvider +import org.dhis2.mobile.commons.coroutine.CoroutineTracker import org.dhis2.usescases.datasets.datasetDetail.DataSetDetailModel import org.dhis2.usescases.datasets.datasetDetail.DataSetDetailRepository import org.dhis2.utils.Action @@ -43,6 +44,7 @@ class DataSetListViewModel( filterManager.asFlowable() .startWith(filterManager) .flatMap { filterManager: FilterManager -> + CoroutineTracker.increment() dataSetDetailRepository.dataSetGroups( filterManager.orgUnitUidsFilters, filterManager.periodFilters, @@ -51,10 +53,14 @@ class DataSetListViewModel( ) } .asFlow() - .catch { Timber.d(it) } + .catch { + Timber.d(it) + CoroutineTracker.decrement() + } .collectLatest { withContext(dispatcher.ui()) { _datasets.value = it + CoroutineTracker.decrement() } } diff --git a/commonskmm/src/androidMain/kotlin/org/dhis2/mobile/commons/coroutine/AndroidIdlingResource.kt b/commonskmm/src/androidMain/kotlin/org/dhis2/mobile/commons/coroutine/AndroidIdlingResource.kt index 204102e2ec..24e8c2ceb0 100644 --- a/commonskmm/src/androidMain/kotlin/org/dhis2/mobile/commons/coroutine/AndroidIdlingResource.kt +++ b/commonskmm/src/androidMain/kotlin/org/dhis2/mobile/commons/coroutine/AndroidIdlingResource.kt @@ -1,5 +1,6 @@ package org.dhis2.mobile.commons.coroutine +import android.util.Log import androidx.test.espresso.idling.CountingIdlingResource object AndroidIdlingResource : CoroutineIdlingResource { @@ -7,11 +8,15 @@ object AndroidIdlingResource : CoroutineIdlingResource { private val countingIdlingResource = CountingIdlingResource(RESOURCE) override fun increment() { - countingIdlingResource.increment() + if (countingIdlingResource.isIdleNow) { + Log.d("CoroutineIdlingResource", "Increment") + countingIdlingResource.increment() + } } override fun decrement() { if (!countingIdlingResource.isIdleNow) { + Log.d("CoroutineIdlingResource", "Decrement") countingIdlingResource.decrement() } } diff --git a/commonskmm/src/commonMain/kotlin/org/dhis2/mobile/commons/coroutine/CoroutineTracker.kt b/commonskmm/src/commonMain/kotlin/org/dhis2/mobile/commons/coroutine/CoroutineTracker.kt index 737b0266cb..0d05bcfa71 100644 --- a/commonskmm/src/commonMain/kotlin/org/dhis2/mobile/commons/coroutine/CoroutineTracker.kt +++ b/commonskmm/src/commonMain/kotlin/org/dhis2/mobile/commons/coroutine/CoroutineTracker.kt @@ -14,13 +14,11 @@ object CoroutineTracker { val count = activeTasks.incrementAndGet() _isIdle.value = false IdlingResourceProvider.idlingResource.increment() -// println("CoroutineTracker Incremented: $count") } fun decrement() { val count = activeTasks.decrementAndGet() _isIdle.value = (count == 0) IdlingResourceProvider.idlingResource.decrement() -// println("CoroutineTracker Decremented: $count") } } From e2f78c6a37a7377728c113fc328b9fab7db92975 Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 9 Apr 2025 15:49:47 +0200 Subject: [PATCH 33/33] test: [ANDROAPP-6869] fix AndroidIdlingResource --- .../mobile/aggregates/ui/viewModel/DataSetTableViewModel.kt | 5 +++-- .../java/org/dhis2/usescases/datasets/DataSetTest.kt | 4 ---- .../dhis2/mobile/commons/coroutine/AndroidIdlingResource.kt | 5 ++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/aggregates/src/commonMain/kotlin/org/dhis2/mobile/aggregates/ui/viewModel/DataSetTableViewModel.kt b/aggregates/src/commonMain/kotlin/org/dhis2/mobile/aggregates/ui/viewModel/DataSetTableViewModel.kt index 50a07ab7ad..6685d4656b 100644 --- a/aggregates/src/commonMain/kotlin/org/dhis2/mobile/aggregates/ui/viewModel/DataSetTableViewModel.kt +++ b/aggregates/src/commonMain/kotlin/org/dhis2/mobile/aggregates/ui/viewModel/DataSetTableViewModel.kt @@ -541,10 +541,11 @@ internal class DataSetTableViewModel( fun onSaveClicked() { viewModelScope.launch { CoroutineTracker.increment() - val result = withContext(dispatcher.io()) { checkValidationRulesConfiguration() } + CoroutineTracker.decrement() + when (result) { NONE -> { attemptToFinnish() @@ -558,7 +559,6 @@ internal class DataSetTableViewModel( askRunValidationRules() } } - CoroutineTracker.decrement() } } @@ -577,6 +577,7 @@ internal class DataSetTableViewModel( it } } + CoroutineTracker.decrement() } } diff --git a/app/src/androidTest/java/org/dhis2/usescases/datasets/DataSetTest.kt b/app/src/androidTest/java/org/dhis2/usescases/datasets/DataSetTest.kt index cad87bb8e6..a422863067 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/datasets/DataSetTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/datasets/DataSetTest.kt @@ -1,9 +1,7 @@ package org.dhis2.usescases.datasets -import android.app.Instrumentation import androidx.compose.ui.test.junit4.createComposeRule import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry import kotlinx.coroutines.test.runTest import org.dhis2.lazyActivityScenarioRule import org.dhis2.usescases.BaseTest @@ -23,8 +21,6 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class DataSetTest : BaseTest() { - private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() - @get:Rule val ruleDataSetDetail = lazyActivityScenarioRule(launchActivity = false) diff --git a/commonskmm/src/androidMain/kotlin/org/dhis2/mobile/commons/coroutine/AndroidIdlingResource.kt b/commonskmm/src/androidMain/kotlin/org/dhis2/mobile/commons/coroutine/AndroidIdlingResource.kt index 24e8c2ceb0..939d2479d6 100644 --- a/commonskmm/src/androidMain/kotlin/org/dhis2/mobile/commons/coroutine/AndroidIdlingResource.kt +++ b/commonskmm/src/androidMain/kotlin/org/dhis2/mobile/commons/coroutine/AndroidIdlingResource.kt @@ -1,6 +1,5 @@ package org.dhis2.mobile.commons.coroutine -import android.util.Log import androidx.test.espresso.idling.CountingIdlingResource object AndroidIdlingResource : CoroutineIdlingResource { @@ -9,16 +8,16 @@ object AndroidIdlingResource : CoroutineIdlingResource { override fun increment() { if (countingIdlingResource.isIdleNow) { - Log.d("CoroutineIdlingResource", "Increment") countingIdlingResource.increment() } + countingIdlingResource.dumpStateToLogs() } override fun decrement() { if (!countingIdlingResource.isIdleNow) { - Log.d("CoroutineIdlingResource", "Decrement") countingIdlingResource.decrement() } + countingIdlingResource.dumpStateToLogs() } fun getIdlingResource() = countingIdlingResource