From 57386e65f7478e1f88de351ff90c41998c57d9b1 Mon Sep 17 00:00:00 2001 From: Wolfgang Fahl Date: Tue, 11 Jul 2017 19:04:51 +0200 Subject: [PATCH] adds Unit Tests for e.g. #128 --- .../java/eu/hansolo/skins/LcdSkinTest.java | 74 ++++++++ src/test/java/eu/hansolo/skins/SampleApp.java | 96 +++++++++++ src/test/java/eu/hansolo/skins/SkinTest.java | 26 +++ .../java/eu/hansolo/skins/WaitableApp.java | 163 ++++++++++++++++++ 4 files changed, 359 insertions(+) create mode 100644 src/test/java/eu/hansolo/skins/LcdSkinTest.java create mode 100644 src/test/java/eu/hansolo/skins/SampleApp.java create mode 100644 src/test/java/eu/hansolo/skins/SkinTest.java create mode 100644 src/test/java/eu/hansolo/skins/WaitableApp.java diff --git a/src/test/java/eu/hansolo/skins/LcdSkinTest.java b/src/test/java/eu/hansolo/skins/LcdSkinTest.java new file mode 100644 index 00000000..ff1f89dc --- /dev/null +++ b/src/test/java/eu/hansolo/skins/LcdSkinTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017 by Gerrit Grunwald + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package eu.hansolo.skins; + +import org.junit.Test; + +import eu.hansolo.medusa.Gauge; +import eu.hansolo.medusa.Gauge.SkinType; +import eu.hansolo.medusa.GaugeBuilder; +import eu.hansolo.medusa.LcdDesign; +import eu.hansolo.medusa.LcdFont; +import javafx.beans.property.Property; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.scene.layout.GridPane; + +/** + * Unit Test for LcdSkin + * @author wf + * + */ +public class LcdSkinTest extends SkinTest { + + public static LcdFont lcdFont=LcdFont.DIGITAL; + public static LcdDesign lcdDesign=LcdDesign.GRAY; + + /** + * create the given LCD Gauge + * @param title + * @param unit + * @return the gauge + */ + public static Gauge createGauge(String title, String unit, int decimals) { + Gauge gauge = GaugeBuilder.create().skinType(SkinType.LCD).animated(true) + .oldValueVisible(false).maxMeasuredValueVisible(false) + .minMeasuredValueVisible(false).decimals(decimals).tickLabelDecimals(0) + .title(title).unit(unit) + .lcdDesign(lcdDesign).lcdFont(lcdFont).build(); + return gauge; + } + + @Test + public void testIssue128() throws Exception { + WaitableApp.toolkitInit(); + GridPane gridPane=new GridPane(); + Gauge speedGauge = createGauge("speed","km/h",0); + gridPane.add(speedGauge, 0, 0); + //int showTimeMSecs=10000; + //SampleApp.createAndShow("Issue128", gridPane, showTimeMSecs); + SampleApp sampleApp = new SampleApp("Issue128",gridPane); + sampleApp.show(); + sampleApp.waitOpen(); + Property speed=new SimpleDoubleProperty(); + speedGauge.valueProperty().bind(speed); + for (int i=0;i<=100;i++) { + speed.setValue(50.0+Math.random()*10); + Thread.sleep(10); + } + sampleApp.close(); + } + +} diff --git a/src/test/java/eu/hansolo/skins/SampleApp.java b/src/test/java/eu/hansolo/skins/SampleApp.java new file mode 100644 index 00000000..6bdd8d5c --- /dev/null +++ b/src/test/java/eu/hansolo/skins/SampleApp.java @@ -0,0 +1,96 @@ +package eu.hansolo.skins; +/** +* +* This file is derived from the https://github.com/BITPlan/can4eve open source project +* +* Copyright 2017 BITPlan GmbH https://github.com/BITPlan +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* +* You may obtain a copy of the License at +* +* http:www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import javafx.geometry.Rectangle2D; +import javafx.scene.Scene; +import javafx.scene.layout.Region; +import javafx.stage.Stage; + +/** +* create a sample App +* +* @author wf +* +*/ +public class SampleApp extends WaitableApp { + private String title; + private Region region; + private int screenPercent; + private int divX; + private int divY; + + /** + * construct the given Sample App + * + * @param title + * @param region + */ + public SampleApp(String title, Region region) { + this(title,region,67,2,2); + } + + /** + * construct me + * @param title + * @param region + * @param screenPercent + * @param divX + * @param divY + */ + public SampleApp(String title, Region region, int screenPercent,int divX,int divY) { + this.title=title; + this.region=region; + this.screenPercent=screenPercent; + this.divX=divX; + this.divY=divY; + } + + /** + * create and show the given Sample App + * @param title + * @param region + * @param showTimeMSecs + * @return the app + * @throws Exception + */ + public static SampleApp createAndShow(String title,Region region,int showTimeMSecs) throws Exception { + SampleApp sampleApp = new SampleApp(title, region); + sampleApp.show(); + sampleApp.waitOpen(); + Thread.sleep(showTimeMSecs); + sampleApp.close(); + return sampleApp; + } + + @Override + public void start(Stage stage) { + super.start(stage); + stage.setTitle(title); + Rectangle2D sceneBounds=super.getSceneBounds(screenPercent,divX,divY); + Scene scene = new Scene(region, sceneBounds.getWidth(), sceneBounds.getHeight()); + stage.setScene(scene); + stage.setX(sceneBounds.getMinX()); + stage.setY(sceneBounds.getMinY()); + stage.show(); + } + +} diff --git a/src/test/java/eu/hansolo/skins/SkinTest.java b/src/test/java/eu/hansolo/skins/SkinTest.java new file mode 100644 index 00000000..3b8c7c4d --- /dev/null +++ b/src/test/java/eu/hansolo/skins/SkinTest.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017 by Gerrit Grunwald + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package eu.hansolo.skins; + +/** + * Base test class for skin Tests + * @author wf + * + */ +public class SkinTest { + static boolean debug=false; + +} diff --git a/src/test/java/eu/hansolo/skins/WaitableApp.java b/src/test/java/eu/hansolo/skins/WaitableApp.java new file mode 100644 index 00000000..3f9a9b06 --- /dev/null +++ b/src/test/java/eu/hansolo/skins/WaitableApp.java @@ -0,0 +1,163 @@ +package eu.hansolo.skins; +/** +* +* This file is derived from the https://github.com/BITPlan/can4eve open source project +* +* Copyright 2017 BITPlan GmbH https://github.com/BITPlan +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* +* You may obtain a copy of the License at +* +* http:www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.geometry.Rectangle2D; +import javafx.stage.Screen; +import javafx.stage.Stage; + +/** + * Waitable Application that does not need launch + * + * @author wf + * + */ +public abstract class WaitableApp extends Application { + protected Stage stage; + static boolean toolkitStarted; + File screenShot = null; + + /** + * allow startup without launch + */ + public static void toolkitInit() { + if (!toolkitStarted) { + toolkitStarted = true; + // do not exit on close of last window + // https://stackoverflow.com/a/10217157/1497139 + Platform.setImplicitExit(false); + /// https://stackoverflow.com/a/38883432/1497139 + // http://www.programcreek.com/java-api-examples/index.php?api=com.sun.javafx.application.PlatformImpl + com.sun.javafx.application.PlatformImpl.startup(() -> { + }); + } + } + + /** + * get SceneBounds + * + * @param screenPercent + * @return + */ + public Rectangle2D getSceneBounds(int screenPercent, int xDiv, int yDiv) { + Rectangle2D primScreenBounds = Screen.getPrimary().getVisualBounds(); + double screenWidth = primScreenBounds.getWidth(); + double screenHeight = primScreenBounds.getHeight(); + double sceneWidth = screenWidth * screenPercent / 100.0; + double sceneHeight = screenHeight * screenPercent / 100.0; + double x = (primScreenBounds.getWidth() - sceneWidth) / xDiv; + double y = (primScreenBounds.getHeight() - sceneHeight) / yDiv; + Rectangle2D sceneBounds = new Rectangle2D(x, y, sceneWidth, sceneHeight); + return sceneBounds; + } + + @Override + public void start(Stage stage) { + this.stage = stage; + } + + public Stage getStage() { + return stage; + } + + public void setStage(Stage stage) { + this.stage = stage; + } + + /** + * wait for close + * + * @throws InterruptedException + */ + public void waitStatus(boolean open) { + int sleep = 1000 / 50; // human eye reaction time + try { + if (open) + while ((stage == null) || (!stage.isShowing())) { + Thread.sleep(sleep); + } + else + while (stage != null && stage.isShowing()) { + Thread.sleep(sleep); + } + } catch (InterruptedException e) { + handleException(e); + } + } + + public void waitOpen() { + waitStatus(true); + } + + public void waitClose() { + waitStatus(false); + } + + /** + * show me + */ + public void show() { + if (stage != null) + return; + Platform.runLater(() -> { + try { + start(new Stage()); + } catch (Exception e) { + handleException(e); + } + }); + } + + /** + * close this display + */ + public void close() { + if (stage != null) + Platform.runLater(() -> stage.close()); + this.waitClose(); + } + + /*** + * handle the given Throwable + * + * @param th + */ + public static void handleException(Throwable th, String msg) { + if (msg == null) { + msg = ""; + } else { + msg = "(" + msg + ")"; + } + StringWriter sw = new StringWriter(); + th.printStackTrace(new PrintWriter(sw)); + System.out.println("Error"+th.getClass().getName()+msg+"\n"+sw.toString()); + } + + public static void handleException(Throwable th) { + handleException(th, null); + } +}