Skip to content

Commit 3c78ec6

Browse files
authored
Add AsyncResourceSample media unit tests (#4166)
* Add tests for AsyncResourceSample media flow * Add AsyncResourceSample test fixture
1 parent dc9abaf commit 3c78ec6

File tree

3 files changed

+271
-1
lines changed

3 files changed

+271
-1
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.codename1.samples;
2+
3+
import com.codename1.components.ToastBar;
4+
import com.codename1.io.Log;
5+
import com.codename1.media.MediaManager;
6+
import com.codename1.ui.Button;
7+
import com.codename1.ui.Dialog;
8+
import com.codename1.ui.Display;
9+
import com.codename1.ui.Form;
10+
import com.codename1.ui.Label;
11+
import com.codename1.ui.layouts.BoxLayout;
12+
13+
/**
14+
* Test-local copy of the AsyncResource sample used by {@link AsyncResourceSampleTest}.
15+
*/
16+
public class AsyncResourceSample {
17+
private static final String SUCCESS_URI = "https://sample-videos.com/audio/mp3/crowd-cheering.mp3";
18+
private static final String ERROR_URI = "https://sample-videos.com/audio/mp3/crowd-cheering-not-found.mp3";
19+
20+
private Form current;
21+
22+
public void start() {
23+
if (current != null) {
24+
current.show();
25+
return;
26+
}
27+
final Form hi = new Form("Hi World", BoxLayout.y());
28+
hi.add(new Label("Hi World"));
29+
final Button playAsync = new Button("Play Async");
30+
playAsync.addActionListener(e -> handleAsyncMedia(playAsync, SUCCESS_URI));
31+
hi.add(playAsync);
32+
33+
final Button playAsyncErr = new Button("Play Async (Not Found)");
34+
playAsyncErr.addActionListener(e -> handleAsyncMedia(playAsyncErr, ERROR_URI));
35+
hi.add(playAsyncErr);
36+
hi.show();
37+
}
38+
39+
private void handleAsyncMedia(final Button source, String uri) {
40+
source.setEnabled(false);
41+
final ToastBar.Status status = ToastBar.getInstance().createStatus();
42+
status.setMessage("Loading Audio...");
43+
status.setShowProgressIndicator(true);
44+
status.show();
45+
source.repaint();
46+
MediaManager.createMediaAsync(uri, false, null)
47+
.ready(media -> {
48+
status.clear();
49+
source.setEnabled(true);
50+
source.repaint();
51+
media.play();
52+
})
53+
.except(ex -> {
54+
status.clear();
55+
source.setEnabled(true);
56+
source.repaint();
57+
Log.e(ex);
58+
ToastBar.showErrorMessage(ex.getMessage());
59+
});
60+
}
61+
62+
public void stop() {
63+
current = Display.getInstance().getCurrent();
64+
if (current instanceof Dialog) {
65+
((Dialog) current).dispose();
66+
current = Display.getInstance().getCurrent();
67+
}
68+
}
69+
70+
public void destroy() {
71+
}
72+
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
package com.codename1.samples;
2+
3+
import com.codename1.junit.FormTest;
4+
import com.codename1.junit.UITestBase;
5+
import com.codename1.media.Media;
6+
import com.codename1.ui.Button;
7+
import com.codename1.ui.Component;
8+
import com.codename1.ui.Container;
9+
import com.codename1.ui.Display;
10+
import com.codename1.ui.Form;
11+
import com.codename1.util.AsyncResource;
12+
13+
import static org.junit.jupiter.api.Assertions.*;
14+
15+
class AsyncResourceSampleTest extends UITestBase {
16+
private static final String SUCCESS_URI = "https://sample-videos.com/audio/mp3/crowd-cheering.mp3";
17+
private static final String ERROR_URI = "https://sample-videos.com/audio/mp3/crowd-cheering-not-found.mp3";
18+
19+
@FormTest
20+
void playAsyncCompletesAndPlaysMedia() {
21+
AsyncResource<Media> asyncMedia = new AsyncResource<Media>();
22+
FakeMedia media = new FakeMedia();
23+
implementation.setMediaAsync(SUCCESS_URI, asyncMedia);
24+
25+
AsyncResourceSample sample = new AsyncResourceSample();
26+
sample.start();
27+
28+
Button playAsync = findButton(Display.getInstance().getCurrent(), "Play Async");
29+
assertNotNull(playAsync);
30+
31+
playAsync.released();
32+
assertFalse(playAsync.isEnabled());
33+
34+
implementation.completeMediaAsync(SUCCESS_URI, media);
35+
flushSerialCalls();
36+
37+
assertTrue(playAsync.isEnabled());
38+
assertTrue(media.playInvoked);
39+
}
40+
41+
@FormTest
42+
void playAsyncHandlesErrors() {
43+
AsyncResource<Media> asyncMedia = new AsyncResource<Media>();
44+
implementation.setMediaAsync(ERROR_URI, asyncMedia);
45+
46+
AsyncResourceSample sample = new AsyncResourceSample();
47+
sample.start();
48+
49+
Button errorButton = findButton(Display.getInstance().getCurrent(), "Play Async (Not Found)");
50+
assertNotNull(errorButton);
51+
52+
errorButton.released();
53+
assertFalse(errorButton.isEnabled());
54+
55+
RuntimeException failure = new RuntimeException("Resource missing");
56+
implementation.failMediaAsync(ERROR_URI, failure);
57+
flushSerialCalls();
58+
59+
assertTrue(errorButton.isEnabled());
60+
}
61+
62+
private Button findButton(Form form, String text) {
63+
if (form == null) {
64+
return null;
65+
}
66+
return findButtonRecursive(form.getContentPane(), text);
67+
}
68+
69+
private Button findButtonRecursive(Container container, String text) {
70+
for (Component child : container) {
71+
if (child instanceof Button) {
72+
Button button = (Button) child;
73+
if (text.equals(button.getText())) {
74+
return button;
75+
}
76+
}
77+
if (child instanceof Container) {
78+
Button nested = findButtonRecursive((Container) child, text);
79+
if (nested != null) {
80+
return nested;
81+
}
82+
}
83+
}
84+
return null;
85+
}
86+
87+
private static class FakeMedia implements Media {
88+
private boolean playInvoked;
89+
90+
public void play() {
91+
playInvoked = true;
92+
}
93+
94+
public void pause() {
95+
}
96+
97+
public void prepare() {
98+
}
99+
100+
public void cleanup() {
101+
}
102+
103+
public int getTime() {
104+
return 0;
105+
}
106+
107+
public void setTime(int time) {
108+
}
109+
110+
public int getDuration() {
111+
return 0;
112+
}
113+
114+
public int getVolume() {
115+
return 0;
116+
}
117+
118+
public void setVolume(int vol) {
119+
}
120+
121+
public boolean isPlaying() {
122+
return playInvoked;
123+
}
124+
125+
public Component getVideoComponent() {
126+
return null;
127+
}
128+
129+
public boolean isVideo() {
130+
return false;
131+
}
132+
133+
public boolean isFullScreen() {
134+
return false;
135+
}
136+
137+
public void setFullScreen(boolean fullScreen) {
138+
}
139+
140+
public boolean isNativePlayerMode() {
141+
return false;
142+
}
143+
144+
public void setNativePlayerMode(boolean nativePlayerMode) {
145+
}
146+
147+
public void setVariable(String key, Object value) {
148+
}
149+
150+
public Object getVariable(String key) {
151+
return null;
152+
}
153+
154+
public boolean isTimeSupported() {
155+
return true;
156+
}
157+
158+
public boolean isSeekSupported() {
159+
return true;
160+
}
161+
}
162+
}

maven/core-unittests/src/test/java/com/codename1/testing/TestCodenameOneImplementation.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ public class TestCodenameOneImplementation extends CodenameOneImplementation {
125125
private Media backgroundMedia;
126126
private Media media;
127127
private AsyncResource<Media> mediaAsync;
128+
private final Map<String, AsyncResource<Media>> mediaAsyncByUri = new ConcurrentHashMap<String, AsyncResource<Media>>();
128129
private Purchase inAppPurchase;
129130
private int startRemoteControlInvocations;
130131
private int stopRemoteControlInvocations;
@@ -339,6 +340,13 @@ public boolean supportsNativeImageCache() {
339340
return nativeImageCacheSupported;
340341
}
341342

343+
private AsyncResource<Media> resolveMediaAsync(String uri) {
344+
if (uri != null && mediaAsyncByUri.containsKey(uri)) {
345+
return mediaAsyncByUri.get(uri);
346+
}
347+
return mediaAsync;
348+
}
349+
342350
@Override
343351
public AsyncResource<Media> createBackgroundMediaAsync(String uri) {
344352
return backgroundMediaAsync;
@@ -359,7 +367,7 @@ public Media createBackgroundMedia(String uri) throws IOException {
359367

360368
@Override
361369
public AsyncResource<Media> createMediaAsync(String uri, boolean video, Runnable onCompletion) {
362-
return mediaAsync;
370+
return resolveMediaAsync(uri);
363371
}
364372

365373
@Override
@@ -380,6 +388,34 @@ public void setMediaAsync(AsyncResource<Media> mediaAsync) {
380388
this.mediaAsync = mediaAsync;
381389
}
382390

391+
public void setMediaAsync(String uri, AsyncResource<Media> asyncResource) {
392+
if (uri == null) {
393+
mediaAsync = asyncResource;
394+
} else if (asyncResource == null) {
395+
mediaAsyncByUri.remove(uri);
396+
} else {
397+
mediaAsyncByUri.put(uri, asyncResource);
398+
}
399+
}
400+
401+
public void clearMediaAsyncMappings() {
402+
mediaAsyncByUri.clear();
403+
}
404+
405+
public void completeMediaAsync(String uri, Media value) {
406+
AsyncResource<Media> async = resolveMediaAsync(uri);
407+
if (async != null) {
408+
async.complete(value);
409+
}
410+
}
411+
412+
public void failMediaAsync(String uri, Throwable error) {
413+
AsyncResource<Media> async = resolveMediaAsync(uri);
414+
if (async != null) {
415+
async.error(error);
416+
}
417+
}
418+
383419
@Override
384420
public void initializeTextSelection(TextSelection aThis) {
385421
initializeTextSelectionCount++;

0 commit comments

Comments
 (0)