From 108f93a51c5e8f2db5b170636b42e4ade78c6c07 Mon Sep 17 00:00:00 2001 From: ApolloF <98666317+ApolloF@users.noreply.github.com> Date: Mon, 12 Oct 2026 12:04:32 +0200 Subject: [PATCH 1/2] Tests: use the v2 Compose test rule everywhere, and compare the Levels trial end to the minute The v1 rule's unconfined effect dispatcher resumed frames on the background thread that emitted a flow update (CalledFromWrongThreadException, 'performMeasureAndLayout called during measure layout', half-applied frames). Since the foss/play split runs every Robolectric test twice, that hit almost every CI run. 2429dfe fixed one test this way; this moves the other 34. LevelsGateTest waited for the trial end to match the stored start to the millisecond; until the stored start reaches the state it is a few ms off, and on a loaded runner that update missed the 30 s wait. --- .../kotlin/com/apollof/protocoltracker/ui/AppNavTest.kt | 2 +- .../com/apollof/protocoltracker/ui/LargeFontLayoutTest.kt | 2 +- .../com/apollof/protocoltracker/ui/ScreenshotTest.kt | 2 +- .../com/apollof/protocoltracker/ui/TouchTargetTest.kt | 2 +- .../protocoltracker/ui/components/TimePickerClockTest.kt | 2 +- .../protocoltracker/ui/components/TrendChartTest.kt | 2 +- .../protocoltracker/ui/journal/JournalBloodworkRowTest.kt | 2 +- .../protocoltracker/ui/journal/JournalChipRevealTest.kt | 2 +- .../protocoltracker/ui/journal/JournalDeleteEntryTest.kt | 2 +- .../protocoltracker/ui/journal/JournalHeadersTest.kt | 2 +- .../protocoltracker/ui/journal/JournalLogMenuTest.kt | 2 +- .../apollof/protocoltracker/ui/journal/JournalSiteTest.kt | 2 +- .../apollof/protocoltracker/ui/journal/JournalUndoTest.kt | 2 +- .../protocoltracker/ui/journal/MoodTrendScreenTest.kt | 2 +- .../apollof/protocoltracker/ui/levels/LevelAdjustTest.kt | 2 +- .../protocoltracker/ui/levels/LevelsAlwaysScrubTest.kt | 2 +- .../protocoltracker/ui/levels/LevelsBackToNowTest.kt | 2 +- .../apollof/protocoltracker/ui/levels/LevelsGateTest.kt | 7 +++++-- .../protocoltracker/ui/levels/LevelsLockedScreenTest.kt | 2 +- .../apollof/protocoltracker/ui/levels/LevelsReadingTest.kt | 2 +- .../apollof/protocoltracker/ui/levels/LevelsScreenTest.kt | 2 +- .../apollof/protocoltracker/ui/levels/LevelsScrubTest.kt | 2 +- .../protocoltracker/ui/plan/CompoundPeakFieldTest.kt | 2 +- .../protocoltracker/ui/settings/DayStartSettingTest.kt | 2 +- .../protocoltracker/ui/settings/PrivacyPolicyPageTest.kt | 2 +- .../protocoltracker/ui/settings/UnitsSettingsTest.kt | 2 +- .../protocoltracker/ui/today/EarlierTimeSheetTest.kt | 2 +- .../protocoltracker/ui/today/ExtraDoseLastTakenTest.kt | 2 +- .../apollof/protocoltracker/ui/today/LogAsPlannedTest.kt | 2 +- .../apollof/protocoltracker/ui/today/LogDoseSiteTest.kt | 2 +- .../com/apollof/protocoltracker/ui/today/NoteSheetTest.kt | 2 +- .../apollof/protocoltracker/ui/today/TodayLastTimeTest.kt | 2 +- .../apollof/protocoltracker/ui/today/TodayScreenTest.kt | 2 +- .../com/apollof/protocoltracker/ui/today/TodaySiteTest.kt | 2 +- .../apollof/protocoltracker/ui/today/TodayWeekPagerTest.kt | 2 +- 35 files changed, 39 insertions(+), 36 deletions(-) diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/AppNavTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/AppNavTest.kt index b8fb3d4..699fa95 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/AppNavTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/AppNavTest.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.assertIsSelected -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/LargeFontLayoutTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/LargeFontLayoutTest.kt index 52343e2..ecb407d 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/LargeFontLayoutTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/LargeFontLayoutTest.kt @@ -6,7 +6,7 @@ import androidx.compose.ui.semantics.getOrNull import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.hasClickAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithContentDescription import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/ScreenshotTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/ScreenshotTest.kt index dee563f..8a7d000 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/ScreenshotTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/ScreenshotTest.kt @@ -23,7 +23,7 @@ import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.hasScrollToNodeAction import androidx.compose.ui.test.hasText import androidx.compose.ui.test.isDialog -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithContentDescription import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/TouchTargetTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/TouchTargetTest.kt index 3a8a465..f39de7a 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/TouchTargetTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/TouchTargetTest.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.semantics.SemanticsNode import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.semantics.getOrNull -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performClick diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/components/TimePickerClockTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/components/TimePickerClockTest.kt index fceada9..9a313dd 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/components/TimePickerClockTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/components/TimePickerClockTest.kt @@ -1,6 +1,6 @@ package com.apollof.protocoltracker.ui.components -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.test.ext.junit.runners.AndroidJUnit4 import com.apollof.protocoltracker.domain.units.DisplayFormat diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/components/TrendChartTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/components/TrendChartTest.kt index 9d53f09..0387cc9 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/components/TrendChartTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/components/TrendChartTest.kt @@ -13,7 +13,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.test.click -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.performTouchInput import androidx.compose.ui.test.swipe diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalBloodworkRowTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalBloodworkRowTest.kt index 320ad4e..002a769 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalBloodworkRowTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalBloodworkRowTest.kt @@ -3,7 +3,7 @@ package com.apollof.protocoltracker.ui.journal import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.semantics.getOrNull import androidx.compose.ui.test.SemanticsMatcher -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.performSemanticsAction import androidx.test.core.app.ApplicationProvider diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalChipRevealTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalChipRevealTest.kt index b49b428..aab0398 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalChipRevealTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalChipRevealTest.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.assertIsSelected import androidx.compose.ui.test.hasClickAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.apollof.protocoltracker.ProtocolTrackerApp diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalDeleteEntryTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalDeleteEntryTest.kt index 858c27a..ecad59c 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalDeleteEntryTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalDeleteEntryTest.kt @@ -1,7 +1,7 @@ package com.apollof.protocoltracker.ui.journal import androidx.compose.ui.semantics.SemanticsActions -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performSemanticsAction diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalHeadersTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalHeadersTest.kt index ae15606..094d725 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalHeadersTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalHeadersTest.kt @@ -1,6 +1,6 @@ package com.apollof.protocoltracker.ui.journal -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalLogMenuTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalLogMenuTest.kt index bfee894..13d1edb 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalLogMenuTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalLogMenuTest.kt @@ -3,7 +3,7 @@ package com.apollof.protocoltracker.ui.journal import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.test.hasSetTextAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalSiteTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalSiteTest.kt index 97e7804..4845d4d 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalSiteTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalSiteTest.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.test.hasClickAction import androidx.compose.ui.test.hasSetTextAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performSemanticsAction diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalUndoTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalUndoTest.kt index 67548a6..5ff7cb5 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalUndoTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/JournalUndoTest.kt @@ -1,6 +1,6 @@ package com.apollof.protocoltracker.ui.journal -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/MoodTrendScreenTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/MoodTrendScreenTest.kt index 863914a..9eee09c 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/MoodTrendScreenTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/journal/MoodTrendScreenTest.kt @@ -3,7 +3,7 @@ package com.apollof.protocoltracker.ui.journal import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.test.hasClickAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithContentDescription import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.performSemanticsAction diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelAdjustTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelAdjustTest.kt index 4ec41a3..a60d5c9 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelAdjustTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelAdjustTest.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.hasScrollToNodeAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsAlwaysScrubTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsAlwaysScrubTest.kt index 3be595c..415d073 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsAlwaysScrubTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsAlwaysScrubTest.kt @@ -7,7 +7,7 @@ import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.click import androidx.compose.ui.test.hasScrollToNodeAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performScrollToNode diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsBackToNowTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsBackToNowTest.kt index f143463..5234ffd 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsBackToNowTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsBackToNowTest.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.semantics.getOrNull import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.click -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithContentDescription import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.performClick diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsGateTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsGateTest.kt index a3e7a27..7da5651 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsGateTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsGateTest.kt @@ -84,9 +84,12 @@ class LevelsGateTest { awaitMain("trial start") { trials().keys == LEVELS_FEATURES } val started = trials() // During the trial everything is open, and the banner says when it ends. Until the stored start reaches the - // state, the gate shows a trial from "now" (nanoseconds; the store keeps milliseconds), so wait for it. + // state, the gate shows a trial from "now", milliseconds off the stored one; on a loaded CI runner that update + // missed a 30 s wait, so compare to the minute (the banner shows a date). val endsAt = started.values.min().plus(Duration.ofDays(14)) - awaitMain("trial end from the stored start") { first.state.value.access.trialEndsAt == endsAt } + awaitMain("trial end from the stored start") { + first.state.value.access.trialEndsAt?.let { Duration.between(endsAt, it).abs() < Duration.ofMinutes(1) } == true + } assertEquals(3, first.state.value.current.size + first.state.value.others.size) assertEquals(2, first.state.value.views.size) first.viewModelScope.cancel() diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsLockedScreenTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsLockedScreenTest.kt index 83060a7..a45256e 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsLockedScreenTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsLockedScreenTest.kt @@ -5,7 +5,7 @@ import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.semantics.getOrNull import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.junit4.ComposeContentTestRule -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsReadingTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsReadingTest.kt index 703342b..e800371 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsReadingTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsReadingTest.kt @@ -7,7 +7,7 @@ import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.click import androidx.compose.ui.test.hasScrollToNodeAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.performScrollToNode import androidx.compose.ui.test.performTouchInput diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsScreenTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsScreenTest.kt index 8c150b4..3cdadfd 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsScreenTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsScreenTest.kt @@ -5,7 +5,7 @@ import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.semantics.getOrNull import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.assertIsNotSelected -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.SemanticsNodeInteraction diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsScrubTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsScrubTest.kt index 0d5e0f2..9501abe 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsScrubTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/levels/LevelsScrubTest.kt @@ -7,7 +7,7 @@ import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.click import androidx.compose.ui.test.hasScrollToNodeAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performScrollToNode diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/plan/CompoundPeakFieldTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/plan/CompoundPeakFieldTest.kt index c0db021..7689fa4 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/plan/CompoundPeakFieldTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/plan/CompoundPeakFieldTest.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.test.hasClickAction import androidx.compose.ui.test.hasSetTextAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performScrollTo diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/DayStartSettingTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/DayStartSettingTest.kt index 6f682fb..850a385 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/DayStartSettingTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/DayStartSettingTest.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performScrollTo diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/PrivacyPolicyPageTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/PrivacyPolicyPageTest.kt index 4748d72..4c18b56 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/PrivacyPolicyPageTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/PrivacyPolicyPageTest.kt @@ -1,7 +1,7 @@ package com.apollof.protocoltracker.ui.settings import androidx.compose.ui.test.assertIsDisplayed -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performScrollTo diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/UnitsSettingsTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/UnitsSettingsTest.kt index 3a1b367..e654b3e 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/UnitsSettingsTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/settings/UnitsSettingsTest.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performScrollTo import androidx.compose.ui.test.performSemanticsAction diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/EarlierTimeSheetTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/EarlierTimeSheetTest.kt index 0971e34..807d761 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/EarlierTimeSheetTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/EarlierTimeSheetTest.kt @@ -1,7 +1,7 @@ package com.apollof.protocoltracker.ui.today import androidx.compose.ui.test.hasContentDescription -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollTo diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/ExtraDoseLastTakenTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/ExtraDoseLastTakenTest.kt index 14ca3ac..5a83b76 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/ExtraDoseLastTakenTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/ExtraDoseLastTakenTest.kt @@ -1,6 +1,6 @@ package com.apollof.protocoltracker.ui.today -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performScrollTo diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/LogAsPlannedTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/LogAsPlannedTest.kt index 521aba5..922f09a 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/LogAsPlannedTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/LogAsPlannedTest.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.test.hasClickAction import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.hasSetTextAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithContentDescription import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/LogDoseSiteTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/LogDoseSiteTest.kt index 2b3df3c..5bc175b 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/LogDoseSiteTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/LogDoseSiteTest.kt @@ -7,7 +7,7 @@ import androidx.compose.ui.test.assertHeightIsAtLeast import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.hasSetTextAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithContentDescription import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/NoteSheetTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/NoteSheetTest.kt index e8d2610..415908d 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/NoteSheetTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/NoteSheetTest.kt @@ -1,7 +1,7 @@ package com.apollof.protocoltracker.ui.today import androidx.compose.ui.test.assertIsDisplayed -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.test.ext.junit.runners.AndroidJUnit4 diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayLastTimeTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayLastTimeTest.kt index 93e2f88..9bfdf4b 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayLastTimeTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayLastTimeTest.kt @@ -1,6 +1,6 @@ package com.apollof.protocoltracker.ui.today -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayScreenTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayScreenTest.kt index 78de736..0724163 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayScreenTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayScreenTest.kt @@ -5,7 +5,7 @@ import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.semantics.getOrNull import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.assertIsDisplayed -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodaySiteTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodaySiteTest.kt index 1e933cb..9f8eb4f 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodaySiteTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodaySiteTest.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.semantics.getOrNull import androidx.compose.ui.test.SemanticsMatcher -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithContentDescription import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription diff --git a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayWeekPagerTest.kt b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayWeekPagerTest.kt index 942fd06..3cf893f 100644 --- a/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayWeekPagerTest.kt +++ b/app/src/test/kotlin/com/apollof/protocoltracker/ui/today/TodayWeekPagerTest.kt @@ -1,7 +1,7 @@ package com.apollof.protocoltracker.ui.today import androidx.compose.ui.semantics.SemanticsActions -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onAllNodesWithContentDescription import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription From 10bd63f1d78e1525014cf232fda17d08f8dad7b6 Mon Sep 17 00:00:00 2001 From: ApolloF <98666317+ApolloF@users.noreply.github.com> Date: Mon, 12 Oct 2026 16:35:32 +0200 Subject: [PATCH 2/2] SmokeTest: close sheets once their window has focus CI run 38262804082 (foss): a sheet's text showed before its dialog window took focus, so Espresso's back press went to the activity and closed the app (NoActivityResumedException). Back on the dialog root waits for that focus. --- .../com/apollof/protocoltracker/SmokeTest.kt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/kotlin/com/apollof/protocoltracker/SmokeTest.kt b/app/src/androidTest/kotlin/com/apollof/protocoltracker/SmokeTest.kt index 1c36503..12caed5 100644 --- a/app/src/androidTest/kotlin/com/apollof/protocoltracker/SmokeTest.kt +++ b/app/src/androidTest/kotlin/com/apollof/protocoltracker/SmokeTest.kt @@ -16,6 +16,9 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.performScrollTo import androidx.compose.ui.test.performSemanticsAction import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.matcher.RootMatchers.isDialog +import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule @@ -95,6 +98,15 @@ class SmokeTest { compose.waitForIdle() } + /** + * Closes the open sheet. A sheet is its own dialog window, and its text shows before that window takes focus; + * a plain back press in between went to the activity and closed the app. Espresso waits for the dialog's focus. + */ + private fun closeSheet() { + Espresso.onView(isRoot()).inRoot(isDialog()).perform(ViewActions.pressBack()) + compose.waitForIdle() + } + private fun openLogMenu() { val log = hasClickAction() and hasAnyDescendant(hasText("Log")) waitFor(log, unmerged = true) @@ -107,7 +119,7 @@ class SmokeTest { openLogMenu() compose.onNode(hasText(row) and hasClickAction()).click() waitForText(shows) - back() + closeSheet() } @Test @@ -126,7 +138,7 @@ class SmokeTest { // A planned dose's sheet. compose.onAllNodes(hasText(doseName, substring = true) and clickLabel("Log with details"))[0].click() waitForText("Plan:") - back() + closeSheet() tab("Plan") waitForText("per week")