Skip to content

Commit c3c3ca4

Browse files
authored
Add switch sample UI tests (#4220)
1 parent a2ee008 commit c3c3ca4

File tree

3 files changed

+185
-6
lines changed

3 files changed

+185
-6
lines changed

maven/core-unittests/src/test/java/com/codename1/junit/UITestBase.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.codename1.io.Util;
55
import com.codename1.testing.SafeL10NManager;
66
import com.codename1.testing.TestCodenameOneImplementation;
7+
import com.codename1.testing.TestUtils;
78
import com.codename1.ui.Display;
89
import com.codename1.ui.DisplayTest;
910
import com.codename1.ui.plaf.UIManager;
@@ -16,6 +17,9 @@
1617
import java.util.Deque;
1718
import java.util.Hashtable;
1819
import java.util.List;
20+
import java.util.concurrent.CountDownLatch;
21+
22+
import static org.junit.Assert.assertTrue;
1923

2024
/**
2125
* Provides a minimal initialized {@link Display} environment for unit tests that instantiate UI components.
@@ -24,6 +28,18 @@ public abstract class UITestBase {
2428
protected Display display;
2529
protected TestCodenameOneImplementation implementation;
2630

31+
protected void waitFor(CountDownLatch latch, int timeout) {
32+
waitFor(latch, 0, timeout);
33+
}
34+
35+
protected void waitFor(CountDownLatch latch, int count, int timeout) {
36+
while(latch.getCount() > count) {
37+
assertTrue(timeout > 0);
38+
TestUtils.waitFor(5);
39+
timeout -= 5;
40+
}
41+
}
42+
2743
@BeforeEach
2844
protected void setUpDisplay() throws Exception {
2945
if (!Display.isInitialized()) {
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package com.codename1.samples;
2+
3+
import com.codename1.components.Switch;
4+
import com.codename1.components.SwitchList;
5+
import com.codename1.junit.FormTest;
6+
import com.codename1.junit.UITestBase;
7+
import com.codename1.testing.TestUtils;
8+
import com.codename1.ui.Component;
9+
import com.codename1.ui.Container;
10+
import com.codename1.ui.Display;
11+
import com.codename1.ui.DisplayTest;
12+
import com.codename1.ui.Form;
13+
import com.codename1.ui.Label;
14+
import com.codename1.ui.layouts.BoxLayout;
15+
import com.codename1.ui.layouts.FlowLayout;
16+
import com.codename1.ui.layouts.GridLayout;
17+
import com.codename1.ui.list.DefaultListModel;
18+
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
import java.util.concurrent.CountDownLatch;
22+
import java.util.concurrent.TimeUnit;
23+
24+
import static org.junit.jupiter.api.Assertions.*;
25+
26+
class SwitchSamplesTest extends UITestBase {
27+
28+
@FormTest
29+
void switchTogglesWhenTapped() {
30+
Form form = Display.getInstance().getCurrent();
31+
form.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
32+
33+
Label label = new Label("Hi World");
34+
Switch sw = new Switch();
35+
final int[] actionCount = {0};
36+
sw.addActionListener(e -> actionCount[0]++);
37+
38+
form.add(label);
39+
form.add(sw);
40+
ensureLaidOut(form);
41+
42+
assertFalse(sw.isOn());
43+
assertEquals(0, actionCount[0]);
44+
45+
CountDownLatch count = new CountDownLatch(2);
46+
sw.addActionListener(e -> count.countDown());
47+
implementation.tapComponent(sw);
48+
waitFor(count, 1, 2000);
49+
ensureLaidOut(form);
50+
51+
assertTrue(sw.isOn(), "Switch should toggle on after tap");
52+
assertEquals(1, actionCount[0], "Tapping switch should fire action listener");
53+
54+
implementation.tapComponent(sw);
55+
waitFor(count, 2000);
56+
ensureLaidOut(form);
57+
58+
assertFalse(sw.isOn(), "Second tap should toggle switch off");
59+
assertEquals(2, actionCount[0], "Action listener should run for each toggle");
60+
}
61+
62+
@FormTest
63+
void switchListFlowLayoutTogglesModelSelection() {
64+
Form form = Display.getInstance().getCurrent();
65+
form.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
66+
67+
DefaultListModel<String> model = new DefaultListModel<String>(
68+
"Red", "Green", "Blue", "Indigo", "Violet", "Orange", "Yellow");
69+
SwitchList switchList = new SwitchList(model);
70+
switchList.setLayout(new FlowLayout());
71+
switchList.refresh();
72+
73+
form.add(switchList);
74+
ensureLaidOut(form);
75+
76+
Component firstCell = switchList.getComponentAt(0);
77+
Switch firstSwitch = findSwitch(firstCell);
78+
assertNotNull(firstSwitch, "Decorated cell should contain a Switch");
79+
assertTrue(switchList.getLayout() instanceof FlowLayout);
80+
assertFalse(firstSwitch.isOn());
81+
82+
CountDownLatch latch = new CountDownLatch(2);
83+
firstSwitch.addActionListener(e -> latch.countDown());
84+
implementation.tapComponent(firstSwitch);
85+
waitFor(latch, 1, 2000);
86+
ensureLaidOut(form);
87+
88+
assertTrue(firstSwitch.isOn(), "Switch should toggle on through user interaction");
89+
assertTrue(isIndexSelected(model, 0), "Model selection should track switch state");
90+
91+
Component thirdCell = switchList.getComponentAt(2);
92+
Switch thirdSwitch = findSwitch(thirdCell);
93+
assertNotNull(thirdSwitch);
94+
thirdSwitch.addActionListener(e -> latch.countDown());
95+
implementation.tapComponent(thirdSwitch);
96+
waitFor(latch, 2000);
97+
ensureLaidOut(form);
98+
99+
assertTrue(thirdSwitch.isOn());
100+
assertTrue(isIndexSelected(model, 2), "Selecting another entry should keep multiple selections");
101+
}
102+
103+
@FormTest
104+
void switchesRemainInteractiveWhileScrolling() throws InterruptedException {
105+
implementation.setDisplaySize(480, 800);
106+
Form form = Display.getInstance().getCurrent();
107+
form.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
108+
form.setScrollableY(true);
109+
110+
List<Switch> switches = new ArrayList<Switch>();
111+
for (int i = 1; i <= 60; i++) {
112+
Container row = new Container(new GridLayout(2));
113+
row.add(new Label("Line " + i));
114+
Switch sw = new Switch();
115+
switches.add(sw);
116+
row.add(sw);
117+
form.add(row);
118+
}
119+
ensureLaidOut(form);
120+
121+
Switch target = switches.get(40);
122+
implementation.dispatchScrollToVisible(form.getContentPane(), target.getY());
123+
ensureLaidOut(form);
124+
125+
126+
boolean initialState = target.isOn();
127+
ensureLaidOut(form);
128+
final CountDownLatch latch = new CountDownLatch(1);
129+
target.addActionListener(ev -> latch.countDown());
130+
implementation.tapComponent(target);
131+
waitFor(latch, 2000);
132+
assertNotEquals(initialState, target.isOn(), "Switch should toggle even after scrolling");
133+
assertFalse(switches.get(2).isOn(), "Unrelated switches should not toggle during scrolling");
134+
}
135+
136+
private void ensureLaidOut(Form form) {
137+
form.revalidate();
138+
flushSerialCalls();
139+
DisplayTest.flushEdt();
140+
flushSerialCalls();
141+
}
142+
143+
private Switch findSwitch(Component component) {
144+
if (component instanceof Switch) {
145+
return (Switch) component;
146+
}
147+
if (component instanceof Container) {
148+
Container container = (Container) component;
149+
int count = container.getComponentCount();
150+
for (int i = 0; i < count; i++) {
151+
Switch found = findSwitch(container.getComponentAt(i));
152+
if (found != null) {
153+
return found;
154+
}
155+
}
156+
}
157+
return null;
158+
}
159+
160+
private boolean isIndexSelected(DefaultListModel<String> model, int index) {
161+
int[] selected = model.getSelectedIndices();
162+
for (int value : selected) {
163+
if (value == index) {
164+
return true;
165+
}
166+
}
167+
return false;
168+
}
169+
}

maven/core-unittests/src/test/java/com/codename1/ui/DisplayTest.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@
66
import org.junit.jupiter.api.Test;
77

88
import static org.junit.jupiter.api.Assertions.*;
9-
import static org.mockito.ArgumentMatchers.anyString;
10-
import static org.mockito.ArgumentMatchers.eq;
11-
import static org.mockito.Mockito.clearInvocations;
12-
import static org.mockito.Mockito.never;
13-
import static org.mockito.Mockito.verify;
14-
import static org.mockito.Mockito.when;
159

1610
public class DisplayTest extends UITestBase {
1711

0 commit comments

Comments
 (0)