@@ -4,25 +4,24 @@ import androidx.test.core.app.ActivityScenario
44import androidx.test.espresso.matcher.ViewMatchers.isNotEnabled
55import androidx.test.ext.junit.runners.AndroidJUnit4
66import androidx.test.platform.app.InstrumentationRegistry
7- import androidx.test.uiautomator.UiSelector
87import com.itsaky.androidide.activities.SplashActivity
98import com.itsaky.androidide.helper.advancePastWelcomeScreen
109import com.itsaky.androidide.helper.clickFirstAccessibilityNodeByText
10+ import com.itsaky.androidide.helper.configureAutomationBuildPreferences
1111import com.itsaky.androidide.helper.ensureOnHomeScreenBeforeCreateProject
1212import com.itsaky.androidide.helper.grantAllRequiredPermissionsThroughOnboardingUi
13+ import com.itsaky.androidide.helper.handlePrivacyDisclosure
1314import com.itsaky.androidide.helper.initializeProjectAndCancelBuild
1415import com.itsaky.androidide.helper.selectProjectTemplate
1516import com.itsaky.androidide.helper.waitForMainHomeOrEditorUi
16- import com.itsaky.androidide.resources.R as ResourcesR
1717import com.itsaky.androidide.screens.HomeScreen.clickCreateProjectHomeScreen
1818import com.itsaky.androidide.screens.OnboardingScreen
19+ import com.itsaky.androidide.screens.PermissionScreen
1920import com.itsaky.androidide.screens.ProjectSettingsScreen.clickCreateProjectProjectSettings
2021import com.itsaky.androidide.screens.ProjectSettingsScreen.setProjectName
21- import com.itsaky.androidide.screens.PermissionScreen
2222import com.itsaky.androidide.utils.PermissionsHelper
2323import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
2424import org.junit.Assert.assertEquals
25- import org.junit.Assert.assertFalse
2625import org.junit.Assert.assertTrue
2726import org.junit.Test
2827import org.junit.runner.RunWith
@@ -36,167 +35,141 @@ import org.junit.runner.RunWith
3635 */
3736@RunWith(AndroidJUnit4 ::class )
3837class EndToEndTest : TestCase () {
39-
40- private val targetContext
41- get() = InstrumentationRegistry .getInstrumentation().targetContext
42-
43- private val acceptText: String
44- get() = targetContext.getString(ResourcesR .string.privacy_disclosure_accept)
45-
46- private val learnMoreText: String
47- get() = targetContext.getString(ResourcesR .string.privacy_disclosure_learn_more)
48-
49- private val dialogTitle: String
50- get() = targetContext.getString(ResourcesR .string.privacy_disclosure_title)
51-
52- @Test
53- fun test_endToEnd () = run {
54-
55- // ── Launch ──
56-
57- step(" Launch app" ) {
58- ActivityScenario .launch(SplashActivity ::class .java)
59- Thread .sleep(1000 )
60- }
61-
62- // ── Welcome Screen ──
63-
64- step(" Verify welcome screen" ) {
65- OnboardingScreen {
66- greetingTitle.isVisible()
67- greetingSubtitle.isVisible()
68- nextButton {
69- isVisible()
70- isClickable()
71- }
72- }
73- }
74-
75- advancePastWelcomeScreen()
76-
77- // ── Permissions Screen (with privacy disclosure dialog overlay) ──
78-
79- step(" Verify privacy disclosure dialog" ) {
80- val d = device.uiDevice
81- val title = d.findObject(UiSelector ().text(dialogTitle))
82- assertTrue(" Dialog title missing" , title.waitForExists(2_000 ))
83- assertTrue(" Accept button missing" , d.findObject(UiSelector ().text(acceptText)).exists())
84- assertTrue(" Learn more button missing" , d.findObject(UiSelector ().text(learnMoreText)).exists())
85- }
86-
87- step(" Accept privacy disclosure" ) {
88- clickFirstAccessibilityNodeByText(acceptText)
89- device.uiDevice.waitForIdle()
90- }
91-
92- step(" Verify privacy dialog does not reappear" ) {
93- assertFalse(
94- " Dialog should not reappear" ,
95- device.uiDevice.findObject(UiSelector ().text(dialogTitle)).exists(),
96- )
97- }
98-
99- val required = PermissionsHelper .getRequiredPermissions(targetContext)
100-
101- step(" Verify all permission items" ) {
102- flakySafely(timeoutMs = 3_000 ) {
103- PermissionScreen {
104- title { isVisible() }
105- subTitle { isVisible() }
106- rvPermissions {
107- isVisible()
108- isDisplayed()
109- }
110- assertEquals(required.size, rvPermissions.getSize())
111-
112- rvPermissions {
113- required.forEachIndexed { index, item ->
114- childAt<PermissionScreen .PermissionItem >(index) {
115- title {
116- isVisible()
117- hasText(item.title)
118- }
119- description {
120- isVisible()
121- hasText(item.description)
122- }
123- grantButton {
124- isVisible()
125- isClickable()
126- hasText(R .string.title_grant)
127- }
128- }
129- }
130- }
131- }
132- }
133- }
134-
135- grantAllRequiredPermissionsThroughOnboardingUi()
136-
137- step(" Confirm all permissions granted" ) {
138- flakySafely(timeoutMs = 3_000 ) {
139- assertTrue(PermissionsHelper .areAllPermissionsGranted(targetContext))
140- }
141- }
142-
143- step(" Confirm all grant buttons disabled" ) {
144- device.uiDevice.waitForIdle()
145- PermissionScreen {
146- rvPermissions {
147- required.indices.forEach { index ->
148- childAt<PermissionScreen .PermissionItem >(index) {
149- grantButton {
150- isNotEnabled()
151- }
152- }
153- }
154- }
155- }
156- }
157-
158- step(" Tap Finish installation" ) {
159- // The button is in the gesture exclusion zone — use accessibility click
160- clickFirstAccessibilityNodeByText(" Finish installation" )
161- }
162-
163- step(" Wait for IDE setup to complete" ) {
164- waitForMainHomeOrEditorUi(
165- device.uiDevice,
166- maxWaitMs = 60_000L ,
167- )
168- }
169-
170- // ── Phase 2: Project creation + build for first 3 templates ──
171-
172- ensureOnHomeScreenBeforeCreateProject()
173-
174- data class TemplateConfig (
175- val label : String ,
176- val templateResId : Int ,
177- val projectName : String ,
178- )
179-
180- val templates = listOf (
181- TemplateConfig (" No Activity" , R .string.template_no_activity, " TestNoActivity" ),
182- TemplateConfig (" Empty Activity" , R .string.template_empty, " TestEmptyActivity" ),
183- TemplateConfig (" Basic Activity" , R .string.template_basic, " TestBasicActivity" ),
184- )
185-
186- for ((index, config) in templates.withIndex()) {
187- step(" Create+build template ${index + 1 } /${templates.size} : ${config.label} " ) {
188- clickCreateProjectHomeScreen()
189- }
190- selectProjectTemplate(" Select ${config.label} template" , config.templateResId)
191- setProjectName(config.projectName)
192- clickCreateProjectProjectSettings()
193- initializeProjectAndCancelBuild()
194-
195- if (index < templates.lastIndex) {
196- ensureOnHomeScreenBeforeCreateProject()
197- }
198- }
199-
200- // ── Future phases (preferences, more templates, etc.) go here ──
201- }
38+ private val targetContext
39+ get() = InstrumentationRegistry .getInstrumentation().targetContext
40+
41+ @Test
42+ fun test_endToEnd () =
43+ run {
44+ // ── Launch ──
45+
46+ step(" Launch app" ) {
47+ ActivityScenario .launch(SplashActivity ::class .java)
48+ Thread .sleep(1000 )
49+ }
50+
51+ // ── Welcome Screen ──
52+
53+ step(" Verify welcome screen" ) {
54+ OnboardingScreen {
55+ greetingTitle.isVisible()
56+ greetingSubtitle.isVisible()
57+ nextButton {
58+ isVisible()
59+ isClickable()
60+ }
61+ }
62+ }
63+
64+ advancePastWelcomeScreen()
65+
66+ // ── Permissions Screen (with privacy disclosure dialog overlay) ──
67+
68+ handlePrivacyDisclosure()
69+
70+ val required = PermissionsHelper .getRequiredPermissions(targetContext)
71+
72+ step(" Verify all permission items" ) {
73+ flakySafely(timeoutMs = 3_000 ) {
74+ PermissionScreen {
75+ title { isVisible() }
76+ subTitle { isVisible() }
77+ rvPermissions {
78+ isVisible()
79+ isDisplayed()
80+ }
81+ assertEquals(required.size, rvPermissions.getSize())
82+
83+ rvPermissions {
84+ required.forEachIndexed { index, item ->
85+ childAt<PermissionScreen .PermissionItem >(index) {
86+ title {
87+ isVisible()
88+ hasText(item.title)
89+ }
90+ description {
91+ isVisible()
92+ hasText(item.description)
93+ }
94+ grantButton {
95+ isVisible()
96+ if (! item.isGranted && ! item.isOptional) {
97+ isClickable()
98+ hasText(R .string.title_grant)
99+ }
100+ }
101+ }
102+ }
103+ }
104+ }
105+ }
106+ }
107+
108+ grantAllRequiredPermissionsThroughOnboardingUi()
109+
110+ step(" Confirm all permissions granted" ) {
111+ flakySafely(timeoutMs = 3_000 ) {
112+ assertTrue(PermissionsHelper .areAllPermissionsGranted(targetContext))
113+ }
114+ }
115+
116+ step(" Confirm all grant buttons disabled" ) {
117+ device.uiDevice.waitForIdle()
118+ PermissionScreen {
119+ rvPermissions {
120+ required.indices.forEach { index ->
121+ childAt<PermissionScreen .PermissionItem >(index) {
122+ grantButton {
123+ isNotEnabled()
124+ }
125+ }
126+ }
127+ }
128+ }
129+ }
130+
131+ step(" Tap Finish installation" ) {
132+ // The button is in the gesture exclusion zone — use accessibility click
133+ clickFirstAccessibilityNodeByText(" Finish installation" )
134+ }
135+
136+ step(" Wait for IDE setup to complete" ) {
137+ waitForMainHomeOrEditorUi(device.uiDevice)
138+ }
139+
140+ configureAutomationBuildPreferences()
141+
142+ // ── Phase 2: Project creation + build for first 3 templates ──
143+
144+ ensureOnHomeScreenBeforeCreateProject()
145+
146+ data class TemplateConfig (
147+ val label : String ,
148+ val templateResId : Int ,
149+ val projectName : String ,
150+ )
151+
152+ val templates =
153+ listOf (
154+ TemplateConfig (" No Activity" , R .string.template_no_activity, " TestNoActivity" ),
155+ TemplateConfig (" Empty Activity" , R .string.template_empty, " TestEmptyActivity" ),
156+ TemplateConfig (" Basic Activity" , R .string.template_basic, " TestBasicActivity" ),
157+ )
158+
159+ for ((index, config) in templates.withIndex()) {
160+ step(" Create+build template ${index + 1 } /${templates.size} : ${config.label} " ) {
161+ clickCreateProjectHomeScreen()
162+ }
163+ selectProjectTemplate(" Select ${config.label} template" , config.templateResId)
164+ setProjectName(config.projectName)
165+ clickCreateProjectProjectSettings()
166+ initializeProjectAndCancelBuild()
167+
168+ if (index < templates.lastIndex) {
169+ ensureOnHomeScreenBeforeCreateProject()
170+ }
171+ }
172+
173+ // ── Future phases (preferences, more templates, etc.) go here ──
174+ }
202175}
0 commit comments