Skip to content

Commit c02a85a

Browse files
Port VideoTransition and ZoomOutImageSample to unit tests. (#4228)
Ported `VideoTransition` and `ZoomOutImageSample` from `Samples/samples` to `maven/core-unittests`. - Created `VideoTransitionSampleTest.java` and `ZoomOutImageSampleTest.java` in `com.codename1.samples` package. - Adapted logic to work in headless environment using `UITestBase` and `TestCodenameOneImplementation`. - Replaced remote resources with mocked/local substitutes. - Verified functionality via assertions and event simulation. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
1 parent c28c339 commit c02a85a

File tree

2 files changed

+352
-0
lines changed

2 files changed

+352
-0
lines changed
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
package com.codename1.samples;
2+
3+
import com.codename1.components.MediaPlayer;
4+
import com.codename1.ui.*;
5+
import com.codename1.ui.animations.Motion;
6+
import com.codename1.ui.layouts.BorderLayout;
7+
import com.codename1.ui.layouts.LayeredLayout;
8+
import com.codename1.util.AsyncResource;
9+
import com.codename1.junit.UITestBase;
10+
import com.codename1.junit.FormTest;
11+
12+
import java.io.IOException;
13+
import java.util.Timer;
14+
import java.util.TimerTask;
15+
16+
import static com.codename1.ui.ComponentSelector.$;
17+
import static org.junit.jupiter.api.Assertions.*;
18+
19+
public class VideoTransitionSampleTest extends UITestBase {
20+
21+
private Image image;
22+
private boolean mediaLoaded = false;
23+
private Form hi;
24+
private Button swap;
25+
private Container theCnt;
26+
private Label imageLabel;
27+
private MediaPlayer mediaPlayer;
28+
29+
@FormTest
30+
public void testVideoTransition() {
31+
hi = new Form("Hi World", new BorderLayout());
32+
swap = new Button("Swap");
33+
theCnt = new Container(new LayeredLayout());
34+
imageLabel = new Label();
35+
imageLabel.getAllStyles().setBgColor(0);
36+
imageLabel.getAllStyles().setBgTransparency(255);
37+
38+
mediaPlayer = new MediaPlayer();
39+
mediaPlayer.getAllStyles().setBgColor(0);
40+
mediaPlayer.getAllStyles().setBgTransparency(255);
41+
42+
swap.addActionListener(e -> {
43+
if (image == null) {
44+
// Mock image download
45+
image = Image.createImage(100, 100, 0xff0000);
46+
imageLabel.setIcon(image.scaled(Display.getInstance().getDisplayWidth(), Display.getInstance().getDisplayHeight()));
47+
}
48+
if (!mediaLoaded) {
49+
// In a real app we would set data source here.
50+
// In test, we skip setting real media source to avoid network/codec issues.
51+
// try {
52+
// mediaPlayer.setDataSource("...", null);
53+
// } catch (IOException ex) {}
54+
mediaLoaded = true;
55+
}
56+
57+
if (theCnt.getComponentCount() == 0) {
58+
theCnt.add(mediaPlayer);
59+
if (mediaPlayer.getMedia() != null) {
60+
mediaPlayer.getMedia().play();
61+
}
62+
hi.revalidate();
63+
} else if (theCnt.contains(mediaPlayer) && !theCnt.contains(imageLabel)) {
64+
imageLabel.getAllStyles().setOpacity(0);
65+
imageLabel.getAllStyles().setBgTransparency(0);
66+
theCnt.add(imageLabel);
67+
theCnt.revalidate();
68+
// Speed up animation for test
69+
fadeIn(imageLabel, 50).ready(res -> {
70+
if (mediaPlayer.getMedia() != null) {
71+
mediaPlayer.getMedia().pause();
72+
}
73+
mediaPlayer.remove();
74+
hi.revalidate();
75+
});
76+
77+
} else if (theCnt.contains(imageLabel) && !theCnt.contains(mediaPlayer)) {
78+
theCnt.addComponent(0, mediaPlayer);
79+
if (mediaPlayer.getMedia() != null) {
80+
mediaPlayer.getMedia().play();
81+
}
82+
// Speed up animation for test
83+
fadeOut(imageLabel, 50).ready(res -> {
84+
imageLabel.remove();
85+
theCnt.revalidate();
86+
});
87+
}
88+
});
89+
90+
hi.add(BorderLayout.NORTH, swap);
91+
hi.add(BorderLayout.CENTER, theCnt);
92+
hi.show();
93+
94+
waitForForm(hi);
95+
96+
// Test Step 1: Initial State - empty
97+
assertEquals(0, theCnt.getComponentCount(), "Container should be initially empty");
98+
99+
// Test Step 2: First Click - Show MediaPlayer
100+
clickButton(swap);
101+
assertEquals(1, theCnt.getComponentCount(), "Container should have 1 component (MediaPlayer)");
102+
assertTrue(theCnt.contains(mediaPlayer), "Container should contain MediaPlayer");
103+
104+
// Test Step 3: Second Click - Transition to Image
105+
clickButton(swap);
106+
107+
// At this point, both might be present during animation or imageLabel added
108+
assertTrue(theCnt.contains(imageLabel), "Container should contain imageLabel during transition");
109+
110+
// Wait for animation to finish
111+
waitForAnimation(300);
112+
113+
assertTrue(theCnt.contains(imageLabel), "Container should contain imageLabel after transition");
114+
assertFalse(theCnt.contains(mediaPlayer), "Container should NOT contain MediaPlayer after transition");
115+
assertEquals(255, imageLabel.getStyle().getOpacity(), "ImageLabel should be fully opaque");
116+
117+
// Test Step 4: Third Click - Transition back to MediaPlayer
118+
clickButton(swap);
119+
120+
// Wait for animation
121+
waitForAnimation(300);
122+
123+
assertTrue(theCnt.contains(mediaPlayer), "Container should contain MediaPlayer after switching back");
124+
assertFalse(theCnt.contains(imageLabel), "Container should NOT contain imageLabel after switching back");
125+
}
126+
127+
private void waitForForm(Form form) {
128+
long start = System.currentTimeMillis();
129+
while (System.currentTimeMillis() - start < 3000) {
130+
if (Display.getInstance().getCurrent() == form) {
131+
return;
132+
}
133+
try {
134+
Thread.sleep(20);
135+
com.codename1.ui.DisplayTest.flushEdt();
136+
} catch (InterruptedException e) {
137+
}
138+
}
139+
}
140+
141+
private void clickButton(Button b) {
142+
// Use public method from TestCodenameOneImplementation
143+
implementation.dispatchPointerPress(b.getAbsoluteX() + b.getWidth() / 2, b.getAbsoluteY() + b.getHeight() / 2);
144+
implementation.dispatchPointerRelease(b.getAbsoluteX() + b.getWidth() / 2, b.getAbsoluteY() + b.getHeight() / 2);
145+
com.codename1.ui.DisplayTest.flushEdt();
146+
}
147+
148+
private void waitForAnimation(int timeout) {
149+
long start = System.currentTimeMillis();
150+
while (System.currentTimeMillis() - start < timeout) {
151+
com.codename1.ui.DisplayTest.flushEdt();
152+
try {
153+
Thread.sleep(50);
154+
} catch (InterruptedException e) {}
155+
}
156+
}
157+
158+
private AsyncResource<Component> fadeIn(Component cmp, int duration) {
159+
AsyncResource<Component> out = new AsyncResource<Component>();
160+
Motion m = Motion.createEaseInMotion(cmp.getStyle().getOpacity(), 255, duration);
161+
162+
final java.util.Timer t = new java.util.Timer();
163+
t.schedule(new TimerTask() {
164+
public void run() {
165+
Display.getInstance().callSerially(() -> {
166+
int currOpacity = cmp.getStyle().getOpacity();
167+
int newOpacity = m.getValue();
168+
if (currOpacity != newOpacity) {
169+
cmp.getStyle().setOpacity(newOpacity);
170+
cmp.getStyle().setBgTransparency(newOpacity);
171+
cmp.repaint();
172+
}
173+
if (m.isFinished()) {
174+
t.cancel();
175+
out.complete(cmp);
176+
}
177+
});
178+
}
179+
}, 0, 20);
180+
181+
m.start();
182+
return out;
183+
}
184+
185+
private AsyncResource<Component> fadeOut(Component cmp, int duration) {
186+
AsyncResource<Component> out = new AsyncResource<Component>();
187+
Motion m = Motion.createEaseInMotion(cmp.getStyle().getOpacity(), 0, duration);
188+
final java.util.Timer t = new java.util.Timer();
189+
t.schedule(new TimerTask() {
190+
public void run() {
191+
Display.getInstance().callSerially(() -> {
192+
int currOpacity = cmp.getStyle().getOpacity();
193+
int newOpacity = m.getValue();
194+
if (currOpacity != newOpacity) {
195+
cmp.getStyle().setBgTransparency(newOpacity);
196+
cmp.getStyle().setOpacity(newOpacity);
197+
cmp.repaint();
198+
}
199+
if (m.isFinished()) {
200+
t.cancel();
201+
out.complete(cmp);
202+
}
203+
});
204+
}
205+
}, 0, 20);
206+
m.start();
207+
return out;
208+
}
209+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package com.codename1.samples;
2+
3+
import com.codename1.ui.*;
4+
import com.codename1.ui.geom.Dimension;
5+
import com.codename1.ui.layouts.BorderLayout;
6+
import com.codename1.ui.layouts.GridLayout;
7+
import com.codename1.ui.layouts.Layout;
8+
import com.codename1.junit.UITestBase;
9+
import com.codename1.junit.FormTest;
10+
11+
import static org.junit.jupiter.api.Assertions.*;
12+
13+
public class ZoomOutImageSampleTest extends UITestBase {
14+
15+
private ImageCmp lbl;
16+
private Form hi;
17+
18+
@FormTest
19+
public void testZoomOutImageSample() {
20+
hi = new Form("Hi World", new BorderLayout());
21+
Button zoomIn = new Button("Zoom In");
22+
23+
Button zoomOut = new Button("Zoom Out");
24+
25+
// Setup UI
26+
// Mock image download
27+
Image img = Image.createImage(100, 100, 0xff0000);
28+
lbl = new ImageCmp(img);
29+
Container cnt = new Container(new ZoomLayout());
30+
cnt.add(lbl);
31+
hi.add(BorderLayout.CENTER, cnt);
32+
hi.add(BorderLayout.NORTH, GridLayout.encloseIn(2, zoomIn, zoomOut));
33+
hi.show();
34+
35+
waitForForm(hi);
36+
37+
// Logic for buttons
38+
zoomIn.addActionListener(evt -> {
39+
if (lbl == null) return;
40+
lbl.setScale(10.0);
41+
lbl.getParent().animateLayout(100); // 100ms for test
42+
});
43+
44+
zoomOut.addActionListener(evt -> {
45+
if (lbl == null) return;
46+
lbl.setScale(0.1);
47+
lbl.getParent().animateLayout(100); // 100ms for test
48+
});
49+
50+
// Verification
51+
52+
// Initial state
53+
assertEquals(1.0, lbl.scale, 0.001, "Initial scale should be 1.0");
54+
55+
// Zoom In
56+
clickButton(zoomIn);
57+
waitForAnimation(300);
58+
assertEquals(10.0, lbl.scale, 0.001, "Scale should be 10.0 after zooming in");
59+
60+
// Zoom Out
61+
clickButton(zoomOut);
62+
waitForAnimation(300);
63+
assertEquals(0.1, lbl.scale, 0.001, "Scale should be 0.1 after zooming out");
64+
}
65+
66+
private void waitForForm(Form form) {
67+
long start = System.currentTimeMillis();
68+
while (System.currentTimeMillis() - start < 3000) {
69+
if (Display.getInstance().getCurrent() == form) {
70+
return;
71+
}
72+
try {
73+
Thread.sleep(20);
74+
com.codename1.ui.DisplayTest.flushEdt();
75+
} catch (InterruptedException e) {
76+
}
77+
}
78+
}
79+
80+
private void clickButton(Button b) {
81+
// Use public method from TestCodenameOneImplementation
82+
implementation.dispatchPointerPress(b.getAbsoluteX() + b.getWidth() / 2, b.getAbsoluteY() + b.getHeight() / 2);
83+
implementation.dispatchPointerRelease(b.getAbsoluteX() + b.getWidth() / 2, b.getAbsoluteY() + b.getHeight() / 2);
84+
com.codename1.ui.DisplayTest.flushEdt();
85+
}
86+
87+
private void waitForAnimation(int timeout) {
88+
long start = System.currentTimeMillis();
89+
while (System.currentTimeMillis() - start < timeout) {
90+
com.codename1.ui.DisplayTest.flushEdt();
91+
try {
92+
Thread.sleep(50);
93+
} catch (InterruptedException e) {}
94+
}
95+
}
96+
97+
static class ImageCmp extends Component {
98+
private Image img;
99+
private double scale = 1.0;
100+
101+
ImageCmp(Image img) {
102+
this.img = img;
103+
}
104+
105+
@Override
106+
protected Dimension calcPreferredSize() {
107+
return new Dimension((int)(img.getWidth()*scale), (int)(img.getHeight()*scale));
108+
}
109+
110+
void setScale(double scale) {
111+
this.scale = scale;
112+
setShouldCalcPreferredSize(true);
113+
}
114+
115+
@Override
116+
public void paint(Graphics g) {
117+
super.paint(g);
118+
g.drawImage(img, getX(), getY(), getWidth(), getHeight());
119+
}
120+
}
121+
122+
static class ZoomLayout extends Layout {
123+
@Override
124+
public void layoutContainer(Container cnt) {
125+
for (Component cmp : cnt) {
126+
cmp.setX((cnt.getLayoutWidth() - cmp.getPreferredW())/2);
127+
cmp.setY((cnt.getLayoutHeight() - cmp.getPreferredH())/2);
128+
cmp.setWidth(cmp.getPreferredW());
129+
cmp.setHeight(cmp.getPreferredH());
130+
}
131+
}
132+
133+
@Override
134+
public Dimension getPreferredSize(Container cnt) {
135+
Dimension dim = new Dimension();
136+
for (Component cmp : cnt) {
137+
dim.setWidth(Math.max(cmp.getPreferredW(), dim.getWidth()));
138+
dim.setHeight(Math.max(cmp.getPreferredH(), dim.getHeight()));
139+
}
140+
return dim;
141+
}
142+
}
143+
}

0 commit comments

Comments
 (0)