Skip to content

Commit 8ec9cbb

Browse files
committed
added tests for PDEWelcome
1 parent 7081e78 commit 8ec9cbb

1 file changed

Lines changed: 258 additions & 0 deletions

File tree

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
package processing.app.ui
2+
3+
import androidx.compose.ui.test.*
4+
import org.junit.jupiter.api.Test
5+
import org.mockito.kotlin.mock
6+
import org.mockito.kotlin.verify
7+
import org.mockito.kotlin.verifyNoInteractions
8+
import processing.app.Base
9+
import processing.app.ui.theme.PDETheme
10+
import processing.app.api.Sketch.Companion.Sketch
11+
12+
@OptIn(ExperimentalTestApi::class)
13+
class PDEWelcomeTest {
14+
15+
// Critical Function Tests
16+
17+
@Test
18+
fun testWelcomeScreenRendersWithoutBase() = runComposeUiTest {
19+
setContent {
20+
PDETheme { PDEWelcome(base = null) }
21+
}
22+
waitForIdle()
23+
}
24+
25+
@Test
26+
fun testWelcomeScreenRendersWithBase() = runComposeUiTest {
27+
val base: Base = mock()
28+
setContent {
29+
PDETheme { PDEWelcome(base = base) }
30+
}
31+
waitForIdle()
32+
}
33+
34+
35+
// Action button visibility
36+
37+
@Test
38+
fun testNewSketchButtonIsDisplayed() = runComposeUiTest {
39+
setContent { PDETheme { PDEWelcome(base = mock()) } }
40+
onNodeWithText(Labels.NEW_SKETCH, substring = true).assertIsDisplayed()
41+
}
42+
43+
@Test
44+
fun testSketchbookButtonIsDisplayed() = runComposeUiTest {
45+
setContent { PDETheme { PDEWelcome(base = mock()) } }
46+
onNodeWithText(Labels.SKETCHBOOK, substring = true).assertIsDisplayed()
47+
}
48+
49+
@Test
50+
fun testExamplesButtonIsDisplayed() = runComposeUiTest {
51+
setContent { PDETheme { PDEWelcome(base = mock()) } }
52+
onNodeWithText(Labels.EXAMPLES, substring = true).assertIsDisplayed()
53+
}
54+
55+
// Action button clicks
56+
57+
@Test
58+
fun testNewSketchButtonCallsHandleNew() = runComposeUiTest {
59+
val base: Base = mock()
60+
setContent { PDETheme { PDEWelcome(base = base) } }
61+
onNodeWithText(Labels.NEW_SKETCH, substring = true).performClick()
62+
verify(base).handleNew()
63+
}
64+
65+
@Test
66+
fun testSketchbookButtonCallsShowSketchbookFrame() = runComposeUiTest {
67+
val base: Base = mock()
68+
setContent { PDETheme { PDEWelcome(base = base) } }
69+
onNodeWithText(Labels.SKETCHBOOK, substring = true).performClick()
70+
verify(base).showSketchbookFrame()
71+
}
72+
73+
@Test
74+
fun debugSemanticTree() = runComposeUiTest {
75+
setContent { PDETheme { PDEWelcome(base = mock()) } }
76+
waitForIdle()
77+
onRoot().printToLog("PDEWelcome")
78+
}
79+
80+
@Test
81+
fun testExamplesButtonCallsShowExamplesFrame() = runComposeUiTest {
82+
val base: Base = mock()
83+
setContent { PDETheme { PDEWelcome(base = base) } }
84+
onNodeWithText(Labels.EXAMPLES, substring = true).performClick()
85+
verify(base).showExamplesFrame()
86+
}
87+
88+
// Null-base safety
89+
90+
@Test
91+
fun testNewSketchWithNullBaseDoesNotCrash() = runComposeUiTest {
92+
setContent { PDETheme { PDEWelcome(base = null) } }
93+
onNodeWithText(Labels.NEW_SKETCH, substring = true).performClick()
94+
waitForIdle()
95+
}
96+
97+
@Test
98+
fun testSketchbookWithNullBaseDoesNotCrash() = runComposeUiTest {
99+
setContent { PDETheme { PDEWelcome(base = null) } }
100+
onNodeWithText(Labels.SKETCHBOOK, substring = true).performClick()
101+
waitForIdle()
102+
}
103+
104+
@Test
105+
fun testExamplesWithNullBaseDoesNotCrash() = runComposeUiTest {
106+
setContent { PDETheme { PDEWelcome(base = null) } }
107+
onNodeWithText(Labels.EXAMPLES, substring = true).performClick()
108+
waitForIdle()
109+
}
110+
111+
@Test
112+
fun testNoBaseMethodsCalledWhenBaseIsNull() = runComposeUiTest {
113+
val base: Base = mock()
114+
setContent { PDETheme { PDEWelcome(base = null) } }
115+
onNodeWithText(Labels.NEW_SKETCH, substring = true).performClick()
116+
onNodeWithText(Labels.SKETCHBOOK, substring = true).performClick()
117+
onNodeWithText(Labels.EXAMPLES, substring = true).performClick()
118+
verifyNoInteractions(base)
119+
}
120+
121+
// Show on startup checkbox
122+
123+
@Test
124+
fun testShowOnStartupCheckboxIsDisplayed() = runComposeUiTest {
125+
setContent { PDETheme { PDEWelcome(base = mock()) } }
126+
onNodeWithText(Labels.SHOW_ON_STARTUP, substring = true).assertIsDisplayed()
127+
}
128+
129+
@Test
130+
fun testShowOnStartupCheckboxTogglesPreference() = runComposeUiTest {
131+
setContent { PDETheme { PDEWelcome(base = mock()) } }
132+
onNodeWithText(Labels.SHOW_ON_STARTUP, substring = true).performClick()
133+
waitForIdle()
134+
// Row must still be present after toggling
135+
onNodeWithText(Labels.SHOW_ON_STARTUP, substring = true).assertIsDisplayed()
136+
}
137+
138+
// Resource & community links
139+
140+
@Test
141+
fun testGetStartedLinkIsDisplayed() = runComposeUiTest {
142+
setContent { PDETheme { PDEWelcome(base = mock()) } }
143+
onNodeWithText(Labels.GET_STARTED, substring = true).assertIsDisplayed()
144+
}
145+
146+
@Test
147+
fun testTutorialsLinkIsDisplayed() = runComposeUiTest {
148+
setContent { PDETheme { PDEWelcome(base = mock()) } }
149+
onNodeWithText(Labels.TUTORIALS, substring = true).assertIsDisplayed()
150+
}
151+
152+
@Test
153+
fun testDocumentationLinkIsDisplayed() = runComposeUiTest {
154+
setContent { PDETheme { PDEWelcome(base = mock()) } }
155+
onNodeWithText(Labels.DOCUMENTATION, substring = true).assertIsDisplayed()
156+
}
157+
158+
@Test
159+
fun testForumLinkIsDisplayed() = runComposeUiTest {
160+
setContent { PDETheme { PDEWelcome(base = mock()) } }
161+
onNodeWithText(Labels.FORUM, substring = true).assertIsDisplayed()
162+
}
163+
164+
@Test
165+
fun testDiscordLinkIsDisplayed() = runComposeUiTest {
166+
setContent { PDETheme { PDEWelcome(base = mock()) } }
167+
onNodeWithText("Discord", substring = true).assertIsDisplayed()
168+
}
169+
170+
@Test
171+
fun testGithubLinkIsDisplayed() = runComposeUiTest {
172+
setContent { PDETheme { PDEWelcome(base = mock()) } }
173+
onNodeWithText("GitHub", substring = true).assertIsDisplayed()
174+
}
175+
176+
@Test
177+
fun testInstagramLinkIsDisplayed() = runComposeUiTest {
178+
setContent { PDETheme { PDEWelcome(base = mock()) } }
179+
onNodeWithText("Instagram", substring = true).assertIsDisplayed()
180+
}
181+
182+
// Examples list
183+
184+
@Test
185+
fun testExamplesListIsDisplayed() = runComposeUiTest {
186+
setContent { PDETheme { PDEWelcome(base = mock()) } }
187+
waitForIdle()
188+
onAllNodesWithText(Labels.OPEN_SKETCH, substring = true)
189+
.onFirst()
190+
.assertExists()
191+
}
192+
193+
@Test
194+
fun testExamplesListFallsBackToDefaultsWhenNoSketches() = runComposeUiTest {
195+
// When listAllExamples() yields nothing, PDEWelcome falls back to the
196+
// 4 hard-coded sketches. Either way at least one card must exist.
197+
setContent { PDETheme { PDEWelcome(base = mock()) } }
198+
waitForIdle()
199+
onAllNodesWithText(Labels.OPEN_SKETCH, substring = true)
200+
.onFirst()
201+
.assertExists()
202+
}
203+
204+
@Test
205+
fun testSketchCardOpenButtonTriggersCallback() = runComposeUiTest {
206+
var opened = false
207+
setContent {
208+
PDETheme {
209+
val sketch = Sketch(path = "/tmp", name = "test")
210+
sketch.card(onOpen = { opened = true })
211+
}
212+
}
213+
// Hover to reveal the overlay
214+
onRoot().performMouseInput { moveTo(center) }
215+
waitForIdle()
216+
onNodeWithText(Labels.OPEN_SKETCH, substring = true).performClick()
217+
assert(opened)
218+
}
219+
220+
@Test
221+
fun testSketchCardHoverRevealsBanner() = runComposeUiTest {
222+
setContent {
223+
PDETheme {
224+
val sketch = Sketch(path = "/tmp", name = "MySketch")
225+
sketch.card()
226+
}
227+
}
228+
onRoot().performMouseInput { moveTo(center) }
229+
waitForIdle()
230+
onNodeWithText("MySketch", substring = true).assertIsDisplayed()
231+
}
232+
233+
@Test
234+
fun testPDEWelcomeWithSurveyRendersWithoutCrash() = runComposeUiTest {
235+
setContent { PDETheme { PDEWelcomeWithSurvey(base = mock()) } }
236+
waitForIdle()
237+
}
238+
239+
@Test
240+
fun testPDEWelcomeWithSurveyRendersWithNullBase() = runComposeUiTest {
241+
setContent { PDETheme { PDEWelcomeWithSurvey(base = null) } }
242+
waitForIdle()
243+
}
244+
245+
// Label constants. Update if anything is changed
246+
247+
private object Labels {
248+
const val NEW_SKETCH = "New Sketch"
249+
const val SKETCHBOOK = "My Sketches" // was "Sketchbook"
250+
const val EXAMPLES = "Open Examples" // was "Examples"
251+
const val SHOW_ON_STARTUP = "Show this window at startup" // was "Show on startup"
252+
const val GET_STARTED = "Get Started"
253+
const val TUTORIALS = "Tutorials"
254+
const val DOCUMENTATION = "Reference" // was "Documentation"
255+
const val FORUM = "Forum"
256+
const val OPEN_SKETCH = "Open"
257+
}
258+
}

0 commit comments

Comments
 (0)