Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 6 additions & 59 deletions scripts/device-runner-app/main/HelloCodenameOne.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
import com.codename1.ui.Label;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.ui.CN;

import com.codenameone.examples.hellocodenameone.tests.Cn1ssDeviceRunner;
import com.codenameone.examples.hellocodenameone.tests.Cn1ssDeviceRunnerReporter;

public class HelloCodenameOne {
private Form current;
private Form mainForm;
private static boolean deviceRunnerExecuted;

public void init(Object context) {
Expand All @@ -28,11 +28,13 @@ public void start() {
current.show();
return;
}
if (!deviceRunnerExecuted) {
Form c = CN.getCurrentForm();
if (!deviceRunnerExecuted || c == null) {
deviceRunnerExecuted = true;
new Cn1ssDeviceRunner().runSuite();
CN.callSerially(() -> new Cn1ssDeviceRunner().runSuite());
return;
}
showMainForm();
c.show();
}

public void stop() {
Expand All @@ -42,59 +44,4 @@ public void stop() {
public void destroy() {
// Nothing to clean up for this sample
}

private void showMainForm() {
if (mainForm == null) {
mainForm = new Form("Main Screen", new BorderLayout());

Container content = new Container(BoxLayout.y());
content.getAllStyles().setBgColor(0x1f2937);
content.getAllStyles().setBgTransparency(255);
content.getAllStyles().setPadding(6, 6, 6, 6);
content.getAllStyles().setFgColor(0xf9fafb);

Label heading = new Label("Hello Codename One");
heading.getAllStyles().setFgColor(0x38bdf8);
heading.getAllStyles().setMargin(0, 4, 0, 0);

Label body = new Label("Instrumentation main activity preview");
body.getAllStyles().setFgColor(0xf9fafb);

Button openBrowser = new Button("Open Browser Screen");
openBrowser.addActionListener(evt -> showBrowserForm());

content.add(heading);
content.add(body);
content.add(openBrowser);

mainForm.add(BorderLayout.CENTER, content);
}
current = mainForm;
mainForm.show();
}

private void showBrowserForm() {
Form browserForm = new Form("Browser Screen", new BorderLayout());

BrowserComponent browser = new BrowserComponent();
browser.setPage(buildBrowserHtml(), null);
browserForm.add(BorderLayout.CENTER, browser);
browserForm.getToolbar().addMaterialCommandToLeftBar(
"Back",
FontImage.MATERIAL_ARROW_BACK,
evt -> showMainForm()
);

current = browserForm;
browserForm.show();
}

private String buildBrowserHtml() {
return "<html><head><meta charset='utf-8'/>"
+ "<style>body{margin:0;font-family:sans-serif;background:#0e1116;color:#f3f4f6;}"
+ ".container{padding:24px;text-align:center;}h1{font-size:24px;margin-bottom:12px;}"
+ "p{font-size:16px;line-height:1.4;}span{color:#4cc9f0;}</style></head>"
+ "<body><div class='container'><h1>Codename One</h1>"
+ "<p>BrowserComponent <span>instrumentation</span> test content.</p></div></body></html>";
}
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
package com.codenameone.examples.hellocodenameone.tests;

import com.codename1.testing.AbstractTest;
import com.codename1.ui.Component;
import com.codename1.ui.Form;
import com.codename1.ui.layouts.BorderLayout;

abstract class AbstractGraphicsScreenshotTest extends AbstractTest {
abstract class AbstractGraphicsScreenshotTest extends BaseTest {
protected abstract Component createContent();

protected abstract String screenshotName();

@Override
public boolean runTest() throws Exception {
final Form[] holder = new Form[1];
Cn1ssDeviceRunnerHelper.runOnEdtSync(() -> {
Form form = new Form("Graphics", new BorderLayout());
form.add(BorderLayout.CENTER, createContent());
holder[0] = form;
form.show();
});

Cn1ssDeviceRunnerHelper.waitForMillis(1200);

final boolean[] result = new boolean[1];
Cn1ssDeviceRunnerHelper.runOnEdtSync(() -> {
if (holder[0] != null) {
holder[0].revalidate();
holder[0].repaint();
}
result[0] = Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshot(screenshotName());
});
return result[0];
Form form = createForm("Graphics", new BorderLayout(), screenshotName());
form.add(BorderLayout.CENTER, createContent());
form.show();
return waitForDone();
}
}
42 changes: 42 additions & 0 deletions scripts/device-runner-app/tests/BaseTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.codenameone.examples.hellocodenameone.tests;

import com.codename1.testing.AbstractTest;
import com.codename1.ui.Form;
import com.codename1.ui.util.UITimer;
import com.codename1.ui.layouts.Layout;
import com.codename1.testing.TestUtils;

public abstract class BaseTest extends AbstractTest {
private boolean done;

protected Form createForm(String title, Layout layout, final String imageName) {
return new Form(title, layout) {
@Override
protected void onShowCompleted() {
registerReadyCallback(this, () -> {
Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshot(imageName);
done = true;
});
}
};
}

protected void registerReadyCallback(Form parent, Runnable run) {
// Android misses some images when the time is lower
UITimer.timer(1500, false, parent, run);
}

protected boolean waitForDone() {
int timeout = 100;
while(!done) {
TestUtils.waitFor(20);
timeout--;
if(timeout == 0) {
return false;
}
}
// give the test a few additional milliseconds for the screenshot emission
TestUtils.waitFor(100);
return true;
}
}
50 changes: 13 additions & 37 deletions scripts/device-runner-app/tests/BrowserComponentScreenshotTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,26 @@
import com.codename1.testing.TestUtils;
import com.codename1.ui.BrowserComponent;
import com.codename1.ui.Form;
import com.codename1.ui.CN;
import com.codename1.ui.layouts.BorderLayout;

public class BrowserComponentScreenshotTest extends AbstractTest {
public class BrowserComponentScreenshotTest extends BaseTest {
private BrowserComponent browser;
@Override
public boolean runTest() throws Exception {
final boolean[] supported = new boolean[1];
Cn1ssDeviceRunnerHelper.runOnEdtSync(() -> supported[0] = BrowserComponent.isNativeBrowserSupported());
if (!supported[0]) {
TestUtils.log("BrowserComponent native support unavailable; skipping screenshot test");
if (!BrowserComponent.isNativeBrowserSupported()) {
return true;
}
Form form = createForm("Browser Test", new BorderLayout(), "BrowserComponent");
browser = new BrowserComponent();
browser.setPage(buildHtml(), null);
form.add(BorderLayout.CENTER, browser);
form.show();
return waitForDone();
}

final boolean[] loadFinished = new boolean[1];
final Form[] formHolder = new Form[1];
Cn1ssDeviceRunnerHelper.runOnEdtSync(() -> {
Form form = new Form("Browser Test", new BorderLayout());
BrowserComponent browser = new BrowserComponent();
browser.addWebEventListener(BrowserComponent.onLoad, evt -> loadFinished[0] = true);
browser.setPage(buildHtml(), null);
form.add(BorderLayout.CENTER, browser);
formHolder[0] = form;
form.show();
});

for (int elapsed = 0; elapsed < 15000 && !loadFinished[0]; elapsed += 200) {
TestUtils.waitFor(200);
}
if (!loadFinished[0]) {
TestUtils.log("BrowserComponent content did not finish loading in time");
return false;
}

Cn1ssDeviceRunnerHelper.waitForMillis(3000);

final boolean[] result = new boolean[1];
Cn1ssDeviceRunnerHelper.runOnEdtSync(() -> {
Form current = formHolder[0];
if (current != null) {
current.revalidate();
current.repaint();
}
result[0] = Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshot("BrowserComponent");
});
return result[0];
protected void registerReadyCallback(Form parent, final Runnable run) {
browser.addWebEventListener(BrowserComponent.onLoad, evt -> CN.callSerially(run));
}

private static String buildHtml() {
Expand Down
36 changes: 25 additions & 11 deletions scripts/device-runner-app/tests/Cn1ssDeviceRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,40 @@
import com.codename1.testing.TestReporting;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.testing.AbstractTest;

public final class Cn1ssDeviceRunner extends DeviceRunner {
private static final String[] TEST_CLASSES = new String[] {
MainScreenScreenshotTest.class.getName(),
BrowserComponentScreenshotTest.class.getName(),
MediaPlaybackScreenshotTest.class.getName(),
GraphicsPipelineScreenshotTest.class.getName(),
GraphicsShapesAndGradientsScreenshotTest.class.getName(),
GraphicsStateAndTextScreenshotTest.class.getName(),
GraphicsTransformationsScreenshotTest.class.getName(),
GraphicsMethodsScreenshotTest.class.getName()
private static final AbstractTest[] TEST_CLASSES = new AbstractTest[] {
new MainScreenScreenshotTest(),
new GraphicsPipelineScreenshotTest(),
new GraphicsShapesAndGradientsScreenshotTest(),
new GraphicsStateAndTextScreenshotTest(),
new GraphicsTransformationsScreenshotTest(),
new BrowserComponentScreenshotTest(),
new MediaPlaybackScreenshotTest()
};

public void runSuite() {
for (String testClass : TEST_CLASSES) {
runTest(testClass);
for (AbstractTest testClass : TEST_CLASSES) {
log("CN1SS:INFO:suite starting test=" + testClass);
try {
testClass.prepare();
testClass.runTest();
testClass.cleanup();
Comment on lines +23 to +26

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Record runTest outcomes

runSuite now calls testClass.prepare(); testClass.runTest(); testClass.cleanup(); directly and never checks the boolean returned by runTest() or notifies TestReporting about start/finish. If any test returns false (e.g., MediaPlaybackScreenshotTest when media creation fails), the suite logs it as “finished” and still emits CN1SS:SUITE:FINISHED, so CI and Cn1ssDeviceRunnerReporter will never mark the test as failed. Please capture the return value and call startingTestCase/finishedTestCase so failed tests are surfaced.

Useful? React with 👍 / 👎.

Comment on lines +22 to +26

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep tests off the EDT

The suite now executes each AbstractTest inline on the EDT (HelloCodenameOne.start schedules runSuite via CN.callSerially) without the DeviceRunner.runTest threading logic that honored shouldExecuteOnEDT(). With the default false, tests such as BrowserComponentScreenshotTest and MediaPlaybackScreenshotTest call Cn1ssDeviceRunnerHelper.waitForMillis() (uses Util.sleep) and rely on the EDT to process onLoad/media callbacks; running them on the EDT freezes the event loop so those callbacks never fire and the suite hangs/fails. Restore the off-EDT execution or thread-switching before invoking each test.

Useful? React with 👍 / 👎.

log("CN1SS:INFO:suite finished test=" + testClass);
} catch (Throwable t) {
log("CN1SS:ERR:suite test=" + testClass + " failed=" + t);
t.printStackTrace();
}
}
log("CN1SS:SUITE:FINISHED");
TestReporting.getInstance().testExecutionFinished(getClass().getName());
}

private static void log(String msg) {
System.out.println(msg);
}

@Override
protected void startApplicationInstance() {
Cn1ssDeviceRunnerHelper.runOnEdtSync(() -> {
Expand Down
Loading
Loading