Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
273 commits
Select commit Hold shift + click to select a range
4db7d3a
fix: correct dependency verification conflict resolution error
xavimolloy Jan 20, 2026
1a2ef22
Merge pull request #4597 from dhis2/release/3.3.1
xavimolloy Jan 20, 2026
7121cc2
chore: [ANDROAPP-7466] add new MetadataSyncPeriod item 6h (#4604)
taridepaco Jan 21, 2026
165951d
fix: Manage Invalid configuration d2 error (#4606)
xavimolloy Jan 23, 2026
e9e4c8a
fix: set compose multiplatform resources of type XML (#4608)
andresmr Jan 23, 2026
feec09f
fix: [ANDROAPP-7433] Do not format option set display name values (#4…
xavimolloy Jan 23, 2026
fdeb192
chore: [ANDROAPP-7303] Update apk name and use custom debug keystore …
ferdyrod Jan 23, 2026
e74911f
ANDROAPP-7231-Test-legacy-login [skip size] (#4410)
andresmr Jan 27, 2026
4a6bca7
chore: [ANDROAPP-7387] Update README.md (#4611)
xavimolloy Jan 28, 2026
a1fdd00
deps: update sdk version (#4617)
andresmr Jan 28, 2026
84112c1
chore: [ANDROAPP- 6429] feature/tracker-search-refactor [skip size] (…
andresmr Jan 29, 2026
d3767fe
ANDROAPP-7478-dependabot-specific-rules (#4619)
andresmr Jan 30, 2026
d63432c
test: improve some tests (#4629)
andresmr Jan 30, 2026
468e168
deps: update dependabot (#4630)
andresmr Jan 30, 2026
b321675
build: Move flavor dependant class to correct path (#4612)
Balcan Feb 1, 2026
b650763
ci: [ANDROAPP-7303] Updates Apk name and uploads correct artifact (#4…
ferdyrod Feb 1, 2026
a1501ca
feat: [ANDROAPP-7472] I Clean up old search repository [skip size] I …
xavimolloy Feb 2, 2026
e4e52e4
refactor: [ANDROAPP-7461] remove deprecated onNextClicked (#4613)
mmmateos Feb 2, 2026
feb6b1d
feat: [ANDROAPP-7472] II data models and mappers (#4623)
xavimolloy Feb 2, 2026
de1a818
fix: [ANDROAPP-7465] ds data input periods appear available but are a…
taridepaco Feb 2, 2026
98ffe5b
fix(translations): sync translations from transifex (develop) [skip s…
dhis2-bot Feb 3, 2026
af7ccdd
chore: [ANDROAPP-7472] Update paging data (#4632)
xavimolloy Feb 4, 2026
c0892d1
chore: [ANDROAPP-7483] Adapt app to changes caused by category combo …
marcamsn Feb 4, 2026
381bfd2
feat: [ANDROAPP-7472] III Repositories and usecase [skip size] (#4624)
xavimolloy Feb 4, 2026
f2dbbec
feat: [ANDROAPP-7472] V Use case implementation into SearchTEIViewMod…
xavimolloy Feb 5, 2026
42031e3
feat: [ANDROAPP-7370] Support 6 and 12 hours metadata sync (#4605)
Balcan Feb 6, 2026
1759a88
test: Add waitForView in openMenuMoreOptions action in EventRobot.kt …
andresmr Feb 9, 2026
ca9f339
fix(translations): sync translations from transifex (develop) (#4634)
dhis2-bot Feb 10, 2026
8c4244a
test: update DataSetTableViewModel.kt to increment and decrement asyn…
andresmr Feb 10, 2026
78afccf
refactor: [ANDROAPP-7305] Include error when device doesn't have netw…
ferdyrod Feb 10, 2026
a30b68f
translations: update transifex types to Android (#4645)
andresmr Feb 11, 2026
bb677b0
fix(translations): sync translations from transifex (develop) [skip s…
dhis2-bot Feb 12, 2026
5e177fa
test: Add NotesIdlingResource to NoteDetailPresenter.kt on save() met…
andresmr Feb 12, 2026
d3fd9f8
review-flaky-tests (#4653)
andresmr Feb 13, 2026
b52006d
ANDROAPP-7218-Implement-OAuth-login-flow-Part-2-Retrieving-authentica…
andresmr Feb 13, 2026
b0fb5a0
refactor(test): [Login] Update test annotations to use Kotlin test fr…
andresmr Feb 16, 2026
24b20d9
feat: [ANDROAPP-7459][1/6] Added new worker to update sync settings […
Balcan Feb 18, 2026
ff25169
test: refactor how dataset waits to table (#4655)
Balcan Feb 19, 2026
58a37a2
chore: [ANDROAPP-7470] File relocation and fetchOptionSets usecase (I…
xavimolloy Feb 19, 2026
8372fc8
test: Replaced all awaitIdle() calls with waitForIdle() (#4673)
andresmr Feb 20, 2026
387070c
feat: [ANDROAPP-7470] - II - Fetch parameters use case [skip size] (…
xavimolloy Feb 20, 2026
bf7b8e2
feat: [ANDROAPP-7470] - III - Injection of new use cases and final pr…
xavimolloy Feb 20, 2026
f8af65f
chore: [ANDROAPP-7498 ] handle new period types [skip size] (#4664)
taridepaco Feb 20, 2026
6e30070
chore: [ANDROAPP-7517] Adapt to mandatory enrollment category combo o…
taridepaco Feb 20, 2026
1ffd849
feat: [ANDROAPP-7470] - IV - Move SearchParameters Screen to tracker …
xavimolloy Feb 23, 2026
d320e42
test: adding WaitForView in checkDataSetIsNotCompletedAndModified ste…
andresmr Feb 23, 2026
f8a57fd
feat: [ANDROAPP-7459][3/6] Added wew sync metadata worker [skip size]…
Balcan Feb 24, 2026
e804222
feat: [ANDROAPP-7129] Update to Rule Engine 3.6.0, apply sort order f…
vgarciabnz Feb 24, 2026
5d3e48e
fix(translations): sync translations from transifex (develop) (#4666)
dhis2-bot Feb 25, 2026
d3592d3
deps: bump the gradle-updates group across 1 directory with 4 updates…
dependabot[bot] Feb 25, 2026
39cddbc
fix: [ANDROAPP-7081] program stage sections order is not applied corr…
taridepaco Feb 26, 2026
49a8189
feat: check minCharacters to search and display warning (#4682)
andresmr Feb 26, 2026
9f28705
feat: [ANDROAPP-7226] Support of search operators [skip size] (#4683)
ferdyrod Feb 26, 2026
0282fc6
feat: Use new Indicator component for feedback [ANDROAPP-7511] (#4689)
fernandogmz Feb 26, 2026
f4b9f2e
test: Implement SearchParametersIntegrationTest.kt (#4684)
andresmr Feb 27, 2026
ee9bff4
chore: [ANDROAPP-7525] adapt to changes in sdk event service and enro…
taridepaco Mar 2, 2026
1b29526
fix: Replace .height(columnHeightDp) from MainContent.kt by fillMaxHe…
andresmr Mar 3, 2026
04cb2ef
Androapp 7534 refactor data set table view model to improve asynchron…
andresmr Mar 5, 2026
2e0ac97
fix: [ANDROAPP-7522] Handles Yes Only value when checked (#4707)
ferdyrod Mar 5, 2026
f7556c3
test: Search operators automation tests (#4704)
ferdyrod Mar 5, 2026
f221b3d
test: update NoteRobot.kt (#4709)
andresmr Mar 5, 2026
70fca84
build: ANDROAPP-7529 update-gradle-9 [skip size] (#4694)
andresmr Mar 5, 2026
db30687
feat: [ANDROAPP-7189] implement InputSegmentedShell on TFA (#4677)
mmmateos Mar 6, 2026
821f462
build: update dhis2sdk to 1.14.0-SNAPSHOT (#4715)
andresmr Mar 9, 2026
f9e35a5
fix: [ANDROAPP-7510] Update compose android and multiplatform [skip s…
xavimolloy Mar 10, 2026
7701483
fix: escape special characters in string resources (#4716)
andresmr Mar 10, 2026
3c5c8a8
feat: [ANDROAPP-7507] Support hybrid basemaps (#4708)
Balcan Mar 10, 2026
0d364dd
fix: Wrap OpenID login response handling in IO context in LoginReposi…
andresmr Mar 10, 2026
402f2e2
build(deps): bump actions/upload-artifact from 6.0.0 to 7.0.0 (#4713)
dependabot[bot] Mar 11, 2026
8abb993
build: update composePluginVersion to 1.10.2 and refresh verification…
andresmr Mar 11, 2026
1f67d3d
build: [ANDROAPP-7497] Move data sync to sync module [skip size] (#4690)
Balcan Mar 11, 2026
5ea695e
test: update testing DB to include search operators
rohit-wa Mar 11, 2026
c746384
Merge pull request #4725 from dhis2/ANDROAPP-7545-update-test-db-add-…
rohit-wa Mar 11, 2026
b3931e7
add focus change handler to input fields for ui event triggering (#4718)
ferdyrod Mar 12, 2026
0565c52
feat: Add ColorMatcher.kt to find the closest color palette [skip siz…
andresmr Mar 12, 2026
b4abb3c
build: Allow rooted devices for training app (#4719)
Balcan Mar 12, 2026
0df74ce
Updates Rule engine. (#4724)
ferdyrod Mar 12, 2026
079c3c7
fix: [ANDROAPP-7494] Remove compose animation forced version (#4723)
Balcan Mar 12, 2026
8ef16e6
remove legacy unused code
Balcan Mar 13, 2026
81a8636
feat: [ANDROAPP-7445] adapt to mandatory dataset for value (#4717)
mmmateos Mar 13, 2026
36d86fb
fix: [ANDROAPP-7530] Sync config status not updating occasionally (#4…
Balcan Mar 13, 2026
83d3dbb
fix: [ANDROAPP-7496] hide enrolled orgunit (#4726)
mmmateos Mar 13, 2026
e229dec
ANDROAPP-7448 Replace Pin layout [skip size] (#4712)
andresmr Mar 16, 2026
9e28875
build: [ANDROAPP-7455] Improve Program Rule performance in forms [ski…
Balcan Mar 17, 2026
50b5004
fix: [ANDROAPP-7539] optimize data loading in stock management (#4736)
xavimolloy Mar 17, 2026
db54310
fix(translations): sync translations from transifex (develop) [skip s…
dhis2-bot Mar 17, 2026
921680a
Update rule engine to 3.7.0 (#4740)
Copilot Mar 17, 2026
26d2847
feat: [ANDROAPP-7456] Legend evaluation for rule actions (#4727)
vgarciabnz Mar 17, 2026
2da3def
Update version to 3.4.0-RC
dhis2-bot Mar 18, 2026
f7830ce
Update version to 3.4.1-Dev (#4743)
github-actions[bot] Mar 18, 2026
b21f24b
feat: [ANDROAPP-7340] Implement new MainViewModel [skip size] (#4714)
Balcan Mar 18, 2026
8469434
translations: remove-unused-strings-resources [skip size] (#4742)
andresmr Mar 18, 2026
c88892f
deps: bump the gradle-updates group across 1 directory with 15 update…
dependabot[bot] Mar 18, 2026
4176f20
fix(translations): sync translations from transifex (develop) (#4745)
dhis2-bot Mar 19, 2026
a16c3aa
deps: bump the gradle-updates group with 3 updates (#4749)
dependabot[bot] Mar 24, 2026
60cbd91
build(deps): bump ncipollo/release-action from 1.20.0 to 1.21.0 (#4748)
dependabot[bot] Mar 24, 2026
955aab1
build: update ruleEngine to 3.7.1 and expressionParser to 1.4.0 (#4758)
andresmr Mar 24, 2026
1b5c53f
chore: [ANDROAPP-7547] Refactor Gradle dependency verification — rele…
andresmr Mar 24, 2026
5672497
chore: [ANDROAPP-7393] OpenId tests [skip size] (#4509)
xavimolloy Mar 26, 2026
1716716
fix(translations): sync translations from transifex (develop) [skip s…
dhis2-bot Mar 26, 2026
11d2556
fix(translations): sync translations from transifex (develop) (#4771)
dhis2-bot Mar 27, 2026
181f989
fix(translations): sync translations from transifex (develop) (#4776)
dhis2-bot Mar 30, 2026
2deafc5
docs: add CLAUDE.md (#4778)
andresmr Mar 30, 2026
716d298
refactor: [ANDROAPP-7495] Search refactor [skip size] (#4774)
xavimolloy Mar 31, 2026
c9862a8
ci: Remove [skip size] from verify-dependency-metadata.yml commit mes…
andresmr Mar 31, 2026
c71791e
fix: [ANDROAPP-7287] flicker when tei list is empty (#4777)
mmmateos Mar 31, 2026
0aa6a3b
Feature/androapp 7532 anr in tei dashboard with display analytics [sk…
andresmr Mar 31, 2026
638adaa
docs: update developer and agent guidelines for KMP testing [skip siz…
andresmr Apr 1, 2026
98c13da
deps: bump the gradle-updates group across 1 directory with 10 update…
dependabot[bot] Apr 1, 2026
e6341f5
feat: [ANDROAPP-7509][1] Add and update classes [skip size] (#4763)
Balcan Apr 1, 2026
de2cd0f
fix: [ANDROAPP-7550] Update filters in main thread (#4783)
xavimolloy Apr 6, 2026
e0edafb
fix: [ANDROAPP-7550] maintain running status in syncStatusController …
xavimolloy Apr 10, 2026
aa15034
fix: [ANDROAPP-7569] change sync settings job period to one hour, syn…
xavimolloy Apr 10, 2026
5135535
chore: [ANDROAPP-7540] Adds the compose multiplatform dependencies di…
ferdyrod Apr 13, 2026
b53d3e5
Add tracker search flow instrumented test for TB program (ANDROAPP-59…
Copilot Mar 17, 2026
dc8818a
test: Add TB Program search flow instrumentation test
rohit-wa Mar 27, 2026
cd95391
Test updated to complete Search operators flow test
rohit-wa Apr 1, 2026
9b68488
[Test]: Added test to count and verify number of search fields.
rohit-wa Apr 1, 2026
4821c50
Update app/src/androidTest/java/org/dhis2/usescases/searchte/robot/Se…
rohit-wa Apr 1, 2026
d862363
Update app/src/androidTest/java/org/dhis2/usescases/searchte/robot/Se…
rohit-wa Apr 1, 2026
7c359b1
Update app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTE…
rohit-wa Apr 1, 2026
ffd91a9
Update app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTE…
rohit-wa Apr 1, 2026
ef9bbaf
Update app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTE…
rohit-wa Apr 1, 2026
e557f9e
Update app/src/androidTest/java/org/dhis2/usescases/searchte/robot/Se…
rohit-wa Apr 1, 2026
fea532c
Fix unused imports and replace Kotlin assert with JUnit assertions
Copilot Apr 1, 2026
16f194f
Add performScrollTo() to make the clear button visible
rohit-wa Apr 1, 2026
116cc51
Update app/src/main/java/org/dhis2/usescases/searchTrackEntity/ui/Sea…
rohit-wa Apr 7, 2026
263ddd8
Add missing onAllNodes import and improve per-field error validation
Copilot Apr 7, 2026
dda590c
Update app/src/androidTest/java/org/dhis2/usescases/searchte/robot/Se…
rohit-wa Apr 9, 2026
49890e7
adding missing dependencies and edits for landscape testing
rohit-wa Apr 10, 2026
2056e89
edit imports - remove onAllNodes and add performScrollTo
rohit-wa Apr 10, 2026
d4394ee
Update app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTE…
rohit-wa Apr 10, 2026
8d2aad0
restore working clickOnClearSearch implementation for landscape testing
rohit-wa Apr 10, 2026
57f61a0
updated navigation between inputfields
rohit-wa Apr 13, 2026
9221b2b
fix(translations): sync translations from transifex (develop) (#4796)
dhis2-bot Apr 14, 2026
485d9b2
deps: bump org.hisp.dhis.lib.expression:expression-parser-jvm from 1.…
dependabot[bot] Apr 14, 2026
d4c1af5
fix(translations): sync translations from transifex (develop) (#4796)
dhis2-bot Apr 14, 2026
59f0821
deps: bump org.hisp.dhis.lib.expression:expression-parser-jvm from 1.…
dependabot[bot] Apr 14, 2026
66cc62f
Initial plan
Copilot Mar 17, 2026
9951df1
fix(translations): sync translations from transifex (develop) (#4771)
dhis2-bot Mar 27, 2026
c5f9ad3
Initial plan
Copilot Mar 17, 2026
9554ea2
Initial plan
Copilot Mar 17, 2026
4764950
fix(translations): sync translations from transifex (develop) (#4771)
dhis2-bot Mar 27, 2026
7f7d772
Initial plan
Copilot Mar 17, 2026
d62d52d
test: improve synchronization in `NoteRobot` and `TeiDashboardRobot` …
andresmr Apr 14, 2026
6e2bce9
adding step to close keyboard to make the test less flaky
rohit-wa Apr 14, 2026
c59c73e
test: Wait closeKeyboard animation before continue
andresmr Apr 15, 2026
b69b859
doc: update AGENTS.md and SKILL.md reducing duplications (#4801)
andresmr Apr 16, 2026
55ece22
refactor: [ANDROAPP-7527] change granular sync's state from RxJava to…
ferdyrod Apr 17, 2026
339fbea
Add tracker search flow instrumented test for TB program (ANDROAPP-59…
Copilot Mar 17, 2026
bbbf61d
test: Add TB Program search flow instrumentation test
rohit-wa Mar 27, 2026
53cfa3a
Test updated to complete Search operators flow test
rohit-wa Apr 1, 2026
7390ff8
[Test]: Added test to count and verify number of search fields.
rohit-wa Apr 1, 2026
937ec22
Update app/src/androidTest/java/org/dhis2/usescases/searchte/robot/Se…
rohit-wa Apr 1, 2026
d2fcf7c
Update app/src/androidTest/java/org/dhis2/usescases/searchte/robot/Se…
rohit-wa Apr 1, 2026
95a63ce
Update app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTE…
rohit-wa Apr 1, 2026
eceade6
Update app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTE…
rohit-wa Apr 1, 2026
6b4bc6e
Update app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTE…
rohit-wa Apr 1, 2026
7cdf216
Update app/src/androidTest/java/org/dhis2/usescases/searchte/robot/Se…
rohit-wa Apr 1, 2026
d6fe6fd
Fix unused imports and replace Kotlin assert with JUnit assertions
Copilot Apr 1, 2026
d750e46
Add performScrollTo() to make the clear button visible
rohit-wa Apr 1, 2026
08a47fe
Update app/src/main/java/org/dhis2/usescases/searchTrackEntity/ui/Sea…
rohit-wa Apr 7, 2026
d9b2f3c
Add missing onAllNodes import and improve per-field error validation
Copilot Apr 7, 2026
5371a60
Update app/src/androidTest/java/org/dhis2/usescases/searchte/robot/Se…
rohit-wa Apr 9, 2026
5793eda
adding missing dependencies and edits for landscape testing
rohit-wa Apr 10, 2026
ee528eb
edit imports - remove onAllNodes and add performScrollTo
rohit-wa Apr 10, 2026
b3255a6
Update app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTE…
rohit-wa Apr 10, 2026
e545975
restore working clickOnClearSearch implementation for landscape testing
rohit-wa Apr 10, 2026
6c546ce
updated navigation between inputfields
rohit-wa Apr 13, 2026
bb2536c
Initial plan
Copilot Mar 17, 2026
e23665c
fix(translations): sync translations from transifex (develop) (#4771)
dhis2-bot Mar 27, 2026
e14ea07
Initial plan
Copilot Mar 17, 2026
f24aa91
Initial plan
Copilot Mar 17, 2026
1426ff7
fix(translations): sync translations from transifex (develop) (#4771)
dhis2-bot Mar 27, 2026
ad7891b
Initial plan
Copilot Mar 17, 2026
b284880
adding step to close keyboard to make the test less flaky
rohit-wa Apr 14, 2026
c7103a7
test: Wait closeKeyboard animation before continue
andresmr Apr 15, 2026
8856482
Merge remote-tracking branch 'origin/ANDROAPP-7548-Add-search-operato…
rohit-wa Apr 20, 2026
b7165eb
refactored clickOnClearSearch to include the correct test tag
rohit-wa Apr 20, 2026
1ff931e
fix: [ANDROAPP-7569] Crash when rotating device in event programs (#4…
Balcan Apr 21, 2026
75165b5
Set up notation parameter to InputNumber in TrackerInputProvider (#4815)
ferdyrod Apr 21, 2026
b51f330
Update version to 3.4.1
dhis2-bot Apr 22, 2026
08d194f
build: [ANDROAPP-7565] Migrage EventCaptureRepositoryImpl to kotlin […
Balcan Apr 23, 2026
d49a5a9
fix: [ANDROAPP-7533] Polygons should end with initial coordinate (#4794)
Balcan Apr 23, 2026
481a204
Saves cursor's position (#4817)
ferdyrod Apr 23, 2026
44d359b
fix: [ANDROAPP-7520] bind openIdController to the Fragment everytime …
xavimolloy Apr 24, 2026
d25eecb
feat: [ANDROAPP-7541] Set text and icon colors for theme (#4790)
Balcan Apr 24, 2026
242dd6e
fix flaky test by using hardware back press to dismiss the keyboard.
rohit-wa Apr 27, 2026
a5c56ac
Merge branch 'release/3.4.1' into ANDROAPP-7548-Add-search-operator-e…
rohit-wa Apr 27, 2026
d901176
fix: [ANDROAPP-7569] Workers not been properly scheduled (#4807)
Balcan Apr 28, 2026
b62c03b
fix: improve search test stability and coroutine tracking
andresmr Apr 28, 2026
20ebb7f
fix(translations): sync translations from transifex (main) (#4833)
dhis2-bot Apr 28, 2026
a09d850
fix: [ANDROAPP-6516] update event when synced (#4795)
mmmateos Apr 28, 2026
94f889d
fix: [ANDROAPP-7569] Set default sync periods if ASWA is not configur…
Balcan Apr 28, 2026
5bbc4da
Merge branch 'release/3.4.1' into ANDROAPP-7548-Add-search-operator-e…
rohit-wa Apr 28, 2026
4721fc7
fix: [ANDROAPP-7567] Hide unsupported value types in search (#4836)
xavimolloy Apr 29, 2026
bdf18a4
fix: [ANDROAPP-7533] Multiple clicks on WorkingList item not updating…
Balcan Apr 30, 2026
a93eefb
Merge branch 'release/3.4.1' into ANDROAPP-7548-Add-search-operator-e…
andresmr Apr 30, 2026
8a411ab
fix: [ANDROAPP-7531] Text inputs save value after 1 seconds of not ty…
Balcan Apr 30, 2026
9a3b01b
Merge branch 'release/3.4.1' into ANDROAPP-7548-Add-search-operator-e…
andresmr Apr 30, 2026
27a2905
Merge pull request #4785 from dhis2/ANDROAPP-7548-Add-search-operator…
rohit-wa Apr 30, 2026
aeffb4a
fix: add imports and missing file for training build variant (#4841)
xavimolloy Apr 30, 2026
ac5fd7d
Update Sdk, Design System, and Version Code (#4845)
github-actions[bot] May 1, 2026
97bf68c
Merge branch 'main' into release/3.4.0-RC
andresmr May 1, 2026
315eb8d
build: update release 3.4.0 with main
andresmr May 1, 2026
f75af25
Merge pull request #4847 from dhis2/release/3.4.0-RC
andresmr May 1, 2026
b370a95
build: update release 3.4.0 version name and version code
andresmr May 1, 2026
23edd7d
Merge pull request #4850 from dhis2/update-version-name-and-version-code
andresmr May 1, 2026
48cc5b9
Merge branch 'release/3.4.1' into release/3.4.0-RC
andresmr May 4, 2026
f9761fa
Merge pull request #4848 from dhis2/release/3.4.0-RC
andresmr May 4, 2026
9daf419
ANDROAPP-7580-OpenId-expose-property-to-configure-prompt-selection [s…
andresmr May 4, 2026
cd2f373
Remove remained ui components string (#4851)
andresmr May 4, 2026
8840f02
fix(translations): sync translations from transifex (main) (#4853)
dhis2-bot May 5, 2026
87d4c31
fix: [ANDROAPP-7574] make navigation context safe (#4829)
xavimolloy May 5, 2026
5942e56
fix(translations): sync translations from transifex (main) (#4856)
dhis2-bot May 6, 2026
a366f75
Add keystore decoding and variant assembly to dependency metadata ver…
andresmr May 6, 2026
5903f95
fix: [ANDROAPP-7431] Trim username in login (#4838)
xavimolloy May 8, 2026
4287ebf
fix: [ANDROAPP-7588] Offline snackbar message not shown (#4854)
Balcan May 11, 2026
3aaff22
fix: [ANDROAPP-7420] check build flavour (#4839)
xavimolloy May 11, 2026
443f9ea
build: [ANDROAPP-7477] Move wiki docs to developer portal [skip size]…
Balcan May 12, 2026
325d16f
fix: [ANDROAPP-7615] remove fabric.properties file (#4863)
xavimolloy May 19, 2026
065a8db
fix: [ANDROAPP-7439] Enrollment date custom label not displayed (#4859)
Balcan May 19, 2026
99cbd77
docs: update OpenID/OAuth configuration instructions (#4871)
andresmr May 21, 2026
448ea82
build: [ANDROAPP-7610] Reduce stock usecase ui complexity [skip size]…
Balcan May 21, 2026
ca28420
fix: [ANDROAPP-7499] Update network status for VPN connections (#4831)
xavimolloy May 22, 2026
32f8645
fix: open id handle cancellation error (#4877)
andresmr May 22, 2026
9d4ec6d
fix: [ANDROAPP-7635] Manage null values for deleted check (#4876)
xavimolloy May 25, 2026
7f8ea5e
fix: [ANDROAPP-7634] SMS module is accidentally enabled when ASWA is …
Balcan May 25, 2026
ceb2184
fix: [ANDROAPP-7603] Allow screen share in training flavor (#4872)
Balcan May 25, 2026
475db46
build: 3.4.0.1 release
ferdyrod May 25, 2026
3e53ac5
Merge pull request #4883 from dhis2/hotfix
ferdyrod May 25, 2026
34cd679
fix: [ANDROAPP-7619] ANR in home filters (#4874)
Balcan May 26, 2026
2c7b410
Automatically select the first map layer that have data, ignoring the…
ferdyrod May 26, 2026
0cdb02f
fix: [ANDROAPP-7601] Blank screen upon rotation in MainActivity (#4878)
Balcan May 28, 2026
71648c9
fix: [ANDROAPP-7572] Use owner org unit for new events (#4879)
xavimolloy May 28, 2026
6ab61c3
fix: [ANDROAPP-7352] add ALL in authority checks (#4881)
mmmateos May 28, 2026
a4f7b0e
Merge branch 'release/3.4.1' into hotfix
andresmr May 28, 2026
0c13d50
fix:[ANDROAPP-7632] Capture conscrypt crash (#4886)
Balcan May 29, 2026
acb3e5a
fix: [ANDROAPP-7446] Validates the can create without searching setti…
ferdyrod May 29, 2026
7ad8201
fix: [ANDROAPP-7546] handle multitext for assignValue program rule (#…
mmmateos May 31, 2026
860740b
fix: [ANDROAPP-7238] Separate numeric FieldValuetype into Decimal and…
xavimolloy Jun 1, 2026
104c5de
fix: fix test (#4896)
xavimolloy Jun 2, 2026
405530b
fix: [ANDROAPP-7398] Use correct snackbar colors (#4889)
xavimolloy Jun 2, 2026
f332784
Merge branch 'release/3.4.1' into hotfix-2
andresmr Jun 2, 2026
1e50f5c
chore: update vName to 3.4.1-RC (#4898)
xavimolloy Jun 2, 2026
9944ac5
Merge branch 'release/3.4.1' into hotfix-2
xavimolloy Jun 2, 2026
e6cfcfc
Merge pull request #4891 from dhis2/hotfix-2
xavimolloy Jun 2, 2026
56397e7
fix: fix test (#4899)
xavimolloy Jun 10, 2026
3802288
Merge pull request #4911 from dhis2/release/3.4.1
xavimolloy Jun 16, 2026
33424f5
Merge upstream 3.4.1 into SimCapture main
alex-vt Jul 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
235 changes: 235 additions & 0 deletions .claude/skills/android-testing/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
---
name: android-testing
description: >
Guidelines for writing unit tests (mockito-kotlin, Turbine, runTest) and
UI instrumented tests (Robot pattern, CoroutineTracker, Compose test tags)
for the DHIS2 Android KMP project. Load this when creating, fixing, or
reviewing any test in the codebase.
---

# DHIS2 Android Testing Guidelines

## Testing Stack

- **Unit Tests**: `mockito-kotlin` (`mock()`, `whenever()`, `verify()`), JUnit / `kotlin.test`
- **Flow tests**: Turbine (`app.cash.turbine`) + `kotlinx-coroutines-test`
- **UI Tests**: Compose Testing + Espresso with Robot pattern
- **Test locations**:
- `commonTest/` — platform-agnostic unit tests (`kotlin.test` annotations: `@Test`, `@BeforeTest`)
- `androidUnitTest/` — Android-specific unit tests (JUnit `@Test`)
- `androidInstrumentedTest/` / `androidTest/` — UI/instrumented tests

## Run Commands

```bash
# Shortcut: lint + all unit tests (mirrors CI)
./run_tests.sh

# All unit tests (legacy + KMP host + KMP debug)
./gradlew testDebugUnitTest testDhis2DebugUnitTest testAndroidHostTest

# Desktop targets in KMP modules
./gradlew desktopTest

# Single KMP module test class (commonTest + androidUnitTest source sets)
./gradlew :login:testAndroidHostTest --tests "org.dhis2.mobile.login.main.ui.viewmodel.LoginViewModelTest"

# Single KMP module test class (androidUnitTest source set only)
./gradlew :login:testAndroidDebugUnitTest --tests "org.dhis2.mobile.login.main.ui.viewmodel.LoginViewModelTest"

# Single legacy Android module test class
./gradlew :form:testDebugUnitTest --tests "org.dhis2.form.ui.FormViewModelTest"

# Single test method (commonTest + androidUnitTest source sets)
./gradlew :login:testAndroidHostTest --tests "org.dhis2.mobile.login.main.ui.viewmodel.LoginViewModelTest.initial screen is set correctly when starting"
```

## Critical Rule: No Hard-Coded Delays

ViewModels use `launchUseCase { }` which wraps `CoroutineTracker`. Espresso's
`IdlingResource` automatically waits for tracked coroutines. `Thread.sleep()` and
hard-coded timeouts are **forbidden**.

```kotlin
// ✅ CORRECT — IdlingResource waits automatically
@Test
fun shouldLoadData() {
exampleRobot(composeTestRule) {
clickLoadButton()
verifyDataDisplayed() // no delay needed
}
}

// ❌ WRONG
@Test
fun shouldLoadData() {
clickLoadButton()
Thread.sleep(2000) // FORBIDDEN
verifyDataDisplayed()
}
```

## Mocking: mockito-kotlin only

Use `mock()`, `whenever()`, `verify()` from `org.mockito.kotlin`. Do **not** use MockK.

```kotlin
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
```

## Unit Test Patterns

### Use Case test
```kotlin
class SavePinUseCaseTest {
private val repository: SessionRepository = mock()
private val useCase = SavePinUseCase(repository)

@Test
fun `should return success when pin is saved`() = runTest {
whenever(repository.savePin("1234")).thenReturn(Unit)

val result = useCase("1234")

assertTrue(result.isSuccess)
verify(repository).savePin("1234")
}
}
```

### ViewModel test
```kotlin
class ExampleViewModelTest {
private val useCase: GetDataUseCase = mock()
private val testDispatcher = UnconfinedTestDispatcher()
private lateinit var viewModel: ExampleViewModel

@BeforeTest
fun setUp() {
Dispatchers.setMain(testDispatcher)
}

@AfterTest
fun tearDown() {
Dispatchers.resetMain()
}

@Test
fun `should emit success state when use case succeeds`() = runTest {
whenever(useCase()).thenReturn(Result.success(flowOf(listOf(item))))

viewModel = ExampleViewModel(useCase)

viewModel.uiState.test {
assertEquals(UiState.Success(listOf(item)), awaitItem())
}
}
}
```

### Repository test
```kotlin
class ExampleRepositoryTest {
// D2 chains calls across multiple intermediate objects — RETURNS_DEEP_STUBS is required
// so that d2.someModule().someRepository().blockingGet() doesn't NPE on the intermediates.
private val d2: D2 = mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS)
private val domainErrorMapper: DomainErrorMapper = mock()
private val repository = ExampleRepositoryImpl(d2, domainErrorMapper)

@Test
fun `should map D2Error to domain error`() = runTest {
val d2Error = D2Error.builder().errorCode(D2ErrorCode.API_RESPONSE_PROCESS_ERROR).build()
whenever(d2.exampleModule().examples().blockingGet()).thenThrow(d2Error)
whenever(domainErrorMapper.mapToDomainError(d2Error)).thenReturn(DomainException("error"))

val result = runCatching { repository.getData() }

assertTrue(result.isFailure)
verify(domainErrorMapper).mapToDomainError(d2Error)
}
}
```

## UI Tests: Robot Pattern

All UI tests go in `androidInstrumentedTest/`. Always use the Robot pattern. Tests extend
`BaseTest`, which provides `mockWebServerRobot` — a helper that stubs HTTP responses from the
DHIS2 server so tests run fully offline against a local `MockWebServer`. Register stubs
**before** launching the robot body.

```kotlin
fun exampleRobot(rule: ComposeTestRule, body: ExampleRobot.() -> Unit) =
ExampleRobot(rule).apply { body() }

class ExampleRobot(val rule: ComposeTestRule) : BaseRobot() {
fun typeUsername(username: String) {
rule.waitUntilExactlyOneExists(hasTestTag(USERNAME_TAG), TIMEOUT)
rule.onNodeWithTag(USERNAME_TAG).performClick()
rule.onAllNodesWithTag("INPUT_TEXT_FIELD")[0].performTextInput(username)
}

fun clickSubmitButton() {
rule.waitUntilExactlyOneExists(hasTestTag(SUBMIT_TAG), TIMEOUT)
rule.onNodeWithTag(SUBMIT_TAG).performClick()
}
}

class ExampleTest : BaseTest() {
@get:Rule val rule = createComposeRule()

@Test
fun shouldPerformSuccessfulAction() {
// Stub the network response before any UI interaction
mockWebServerRobot.addResponse(GET, "/api/endpoint", MOCK_RESPONSE, 200)
exampleRobot(rule) {
typeUsername("user")
clickSubmitButton()
verifySuccessMessageDisplayed()
}
// Call cleanDatabase() after any test that writes to the local DB —
// it clears all DHIS2 SDK tables so state doesn't leak into the next test.
cleanDatabase()
}
}
```

## Test Tags

Export constants from the screen file. Format: `{SCREEN}_{COMPONENT}_TAG`.

```kotlin
const val LOGIN_BUTTON_TAG = "LOGIN_BUTTON_TAG"
const val USERNAME_INPUT_TAG = "USERNAME_INPUT_TAG"

@Composable
fun LoginScreen() {
InputField(modifier = Modifier.testTag(USERNAME_INPUT_TAG))
Button(modifier = Modifier.testTag(LOGIN_BUTTON_TAG)) { ... }
}
```

## DHIS2 Design System Inputs

DHIS2 input components are composite. Click the wrapper to focus, then target the
inner `"INPUT_TEXT_FIELD"` node. Use `performTextInput()`, never `performTextReplacement()`.

```kotlin
// ✅ CORRECT
rule.onNodeWithTag(USERNAME_TAG).performClick()
rule.onAllNodesWithTag("INPUT_TEXT_FIELD")[0].performTextInput(username)

// ❌ WRONG
rule.onNodeWithTag(USERNAME_TAG).performTextReplacement(username)
```

## Common Mistakes to Avoid

- Using `Thread.sleep()` or any hard-coded delays
- Using MockK (`mockk()`, `every {}`, `coEvery {}`) — use mockito-kotlin instead
- Using `performTextReplacement()` on DHIS2 design system components
- Not exporting test tag constants from screen files
- Not extending `BaseRobot` for robot classes
- Not cleaning up after tests (`cleanDatabase()`, clear preferences)
- Testing implementation details instead of user flows
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ ktlint_standard_no-wildcard-imports = enabled
ktlint_standard_trailing-comma-on-call-site = enabled
ktlint_standard_trailing-comma-on-declaration-site = enabled
ktlint_standard_import-ordering = enabled
ktlint_experimental_no-unused-imports = enabled
Loading
Loading