2323package net.opatry.tasks.app.test.screenshot
2424
2525import android.content.Context
26+ import androidx.appcompat.app.AppCompatActivity
2627import androidx.appcompat.app.AppCompatDelegate
28+ import androidx.compose.ui.test.AndroidComposeUiTest
2729import androidx.compose.ui.test.ExperimentalTestApi
2830import androidx.compose.ui.test.assertIsDisplayed
2931import androidx.compose.ui.test.hasTestTag
3032import androidx.compose.ui.test.hasText
3133import androidx.compose.ui.test.isDialog
32- import androidx.compose.ui.test.junit4.createAndroidComposeRule
3334import androidx.compose.ui.test.onNodeWithTag
3435import androidx.compose.ui.test.onNodeWithText
3536import androidx.compose.ui.test.performClick
3637import androidx.compose.ui.test.performTextInput
38+ import androidx.compose.ui.test.runAndroidComposeUiTest
39+ import androidx.compose.ui.test.waitUntilAtLeastOneExists
40+ import androidx.compose.ui.test.waitUntilExactlyOneExists
3741import androidx.test.platform.app.InstrumentationRegistry
3842import androidx.test.uiautomator.UiDevice
39- import kotlinx.coroutines.test.runTest
4043import net.opatry.tasks.app.MainActivity
4144import net.opatry.tasks.app.R
4245import net.opatry.tasks.app.test.ScreenshotOnFailureRule
@@ -52,9 +55,6 @@ import java.io.File
5255@OptIn(ExperimentalTestApi ::class )
5356class StoreScreenshotTest {
5457
55- @get:Rule
56- val composeTestRule = createAndroidComposeRule<MainActivity >()
57-
5858 @get:Rule
5959 val screenshotOnFailureRule = ScreenshotOnFailureRule ()
6060
@@ -72,128 +72,128 @@ class StoreScreenshotTest {
7272 .takeScreenshot(outputFile)
7373 }
7474
75- private fun pressBack () {
76- // FIXME how to "press back" with ComposeTestRule (without Espresso)
77- // UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).pressBack()
75+ private fun AndroidComposeUiTest < * >. pressBack () {
76+ // FIXME how to "press back" with `runAndroidComposeUiTest` (without Espresso)
77+ // ` UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).pressBack()`
7878 // UI Automator doesn't work for navigation (but does for IME dismiss)
79- composeTestRule. activity.onBackPressed()
79+ activity? .onBackPressed()
8080 }
8181
8282 private fun dismissKeyboard () {
8383 UiDevice .getInstance(InstrumentationRegistry .getInstrumentation()).pressBack()
8484 }
8585
86- private fun switchToNightMode (nightMode : Int ) {
87- composeTestRule.activity.runOnUiThread {
88- composeTestRule.activity.delegate.localNightMode = nightMode
86+ private fun <A : AppCompatActivity > AndroidComposeUiTest<A>.switchToNightMode (nightMode : Int ) {
87+ activity?.runOnUiThread {
88+ activity?.delegate?.localNightMode = nightMode
89+ activity?.recreate()
8990 }
90- composeTestRule.activityRule.scenario.recreate()
91- composeTestRule.waitForIdle()
91+ waitForIdle()
9292 }
9393
9494 /* *
9595 * This test should be executed with the `demo` flavor which stub content for store screenshots.
9696 */
9797 @Test
98- fun storeScreenshotSequence () = runTest {
99- val initialNightMode = composeTestRule. activity.delegate.localNightMode
98+ fun storeScreenshotSequence () = runAndroidComposeUiTest< MainActivity > {
99+ val initialNightMode = activity? .delegate? .localNightMode ? : AppCompatDelegate . MODE_NIGHT_UNSPECIFIED
100100
101- composeTestRule. waitForIdle()
101+ waitForIdle()
102102 takeScreenshot(" initial_screen" )
103103
104104 switchToNightMode(AppCompatDelegate .MODE_NIGHT_NO )
105105
106106 val defaultTaskTitle = targetContext.getString(R .string.demo_task_list_default)
107- composeTestRule. waitUntilAtLeastOneExists(hasText(defaultTaskTitle))
108- composeTestRule. onNodeWithText(defaultTaskTitle)
107+ waitUntilAtLeastOneExists(hasText(defaultTaskTitle))
108+ onNodeWithText(defaultTaskTitle)
109109 .assertIsDisplayed()
110110
111111 val homeTaskTitle = targetContext.getString(R .string.demo_task_list_home)
112- composeTestRule. onNodeWithText(homeTaskTitle)
112+ onNodeWithText(homeTaskTitle)
113113 .assertIsDisplayed()
114114
115115 val groceriesTaskTitle = targetContext.getString(R .string.demo_task_list_groceries)
116- composeTestRule. onNodeWithText(groceriesTaskTitle)
116+ onNodeWithText(groceriesTaskTitle)
117117 .assertIsDisplayed()
118118
119119 val workTaskTitle = targetContext.getString(R .string.demo_task_list_work)
120- composeTestRule. onNodeWithText(workTaskTitle)
120+ onNodeWithText(workTaskTitle)
121121 .assertIsDisplayed()
122122
123123 takeScreenshot(" task_lists_light" )
124124
125- composeTestRule. onNodeWithText(defaultTaskTitle)
125+ onNodeWithText(defaultTaskTitle)
126126 .assertIsDisplayed()
127127 .performClick()
128128 val defaultTask1Title = targetContext.getString(R .string.demo_task_list_default_task1)
129- composeTestRule. waitUntilAtLeastOneExists(hasText(defaultTask1Title))
129+ waitUntilAtLeastOneExists(hasText(defaultTask1Title))
130130 // FIXME unreliable, need to wait for something else?
131131 takeScreenshot(" my_tasks_light" )
132132
133- composeTestRule. waitUntilExactlyOneExists(hasTestTag(ADD_TASK_FAB ))
134- composeTestRule. onNodeWithTag(ADD_TASK_FAB )
133+ waitUntilExactlyOneExists(hasTestTag(ADD_TASK_FAB ))
134+ onNodeWithTag(ADD_TASK_FAB )
135135 .assertIsDisplayed()
136136 .performClick()
137- composeTestRule. waitUntilExactlyOneExists(isDialog())
137+ waitUntilExactlyOneExists(isDialog())
138138
139- composeTestRule. waitUntilExactlyOneExists(hasTestTag(TITLE_FIELD ))
140- composeTestRule. onNodeWithTag(TITLE_FIELD )
139+ waitUntilExactlyOneExists(hasTestTag(TITLE_FIELD ))
140+ onNodeWithTag(TITLE_FIELD )
141141 .performTextInput(" Wash the car 🧽" )
142- composeTestRule. waitForIdle()
142+ waitForIdle()
143143 dismissKeyboard()
144144
145- composeTestRule. waitUntilExactlyOneExists(hasTestTag(NOTES_FIELD ))
146- composeTestRule. onNodeWithTag(NOTES_FIELD )
145+ waitUntilExactlyOneExists(hasTestTag(NOTES_FIELD ))
146+ onNodeWithTag(NOTES_FIELD )
147147 .performTextInput(" Keys are in the drawer" )
148148
149149 dismissKeyboard()
150150
151- composeTestRule. waitForIdle()
151+ waitForIdle()
152152 takeScreenshot(" add_task_light" )
153153
154154 // FIXME how to dismiss bottom sheet without clicking on the button? (press back somehow? tap outside?)
155155 // FIXME how to use Res strings from :tasks-app-shared?
156- composeTestRule. onNodeWithText(" Cancel" )
156+ onNodeWithText(" Cancel" )
157157 .assertIsDisplayed()
158158 .performClick()
159159 // go back
160160 pressBack()
161- composeTestRule. waitUntilAtLeastOneExists(hasText(groceriesTaskTitle))
161+ waitUntilAtLeastOneExists(hasText(groceriesTaskTitle))
162162
163- composeTestRule. onNodeWithText(groceriesTaskTitle)
163+ onNodeWithText(groceriesTaskTitle)
164164 .assertIsDisplayed()
165165 .performClick()
166166 val groceriesTask1Title = targetContext.getString(R .string.demo_task_list_groceries_task1)
167- composeTestRule. waitUntilAtLeastOneExists(hasText(groceriesTask1Title))
168- composeTestRule. onNodeWithTag(COMPLETED_TASKS_TOGGLE )
167+ waitUntilAtLeastOneExists(hasText(groceriesTask1Title))
168+ onNodeWithTag(COMPLETED_TASKS_TOGGLE )
169169 .assertIsDisplayed()
170170 .performClick()
171171 val groceriesTask3Title = targetContext.getString(R .string.demo_task_list_groceries_task3)
172- composeTestRule. waitUntilAtLeastOneExists(hasText(groceriesTask3Title))
172+ waitUntilAtLeastOneExists(hasText(groceriesTask3Title))
173173 takeScreenshot(" groceries_light" )
174174
175175 pressBack()
176- composeTestRule. waitUntilAtLeastOneExists(hasText(workTaskTitle))
176+ waitUntilAtLeastOneExists(hasText(workTaskTitle))
177177
178- composeTestRule. onNodeWithText(workTaskTitle)
178+ onNodeWithText(workTaskTitle)
179179 .assertIsDisplayed()
180180 .performClick()
181181 val workTask1Title = targetContext.getString(R .string.demo_task_list_work_task1)
182- composeTestRule. waitUntilAtLeastOneExists(hasText(workTask1Title))
182+ waitUntilAtLeastOneExists(hasText(workTask1Title))
183183 takeScreenshot(" work_light" )
184184
185185 pressBack()
186- composeTestRule. waitUntilAtLeastOneExists(hasText(homeTaskTitle))
186+ waitUntilAtLeastOneExists(hasText(homeTaskTitle))
187187
188- composeTestRule. onNodeWithText(homeTaskTitle)
188+ onNodeWithText(homeTaskTitle)
189189 .assertIsDisplayed()
190190 .performClick()
191191 val homeTask1Title = targetContext.getString(R .string.demo_task_list_home_task1)
192- composeTestRule. waitUntilAtLeastOneExists(hasText(homeTask1Title))
192+ waitUntilAtLeastOneExists(hasText(homeTask1Title))
193193 takeScreenshot(" home_light" )
194194
195195 switchToNightMode(AppCompatDelegate .MODE_NIGHT_YES )
196- composeTestRule. waitUntilAtLeastOneExists(hasText(homeTask1Title))
196+ waitUntilAtLeastOneExists(hasText(homeTask1Title))
197197 takeScreenshot(" home_dark" )
198198 switchToNightMode(initialNightMode)
199199 }
0 commit comments