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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ report-images

# temporary pom file by shade plugin
dependency-reduced-pom.xml

# TODO: put logs to some other location, e.g. under target that gets cleaned
# docker demo environment robot reports
src/test/robotframework/results/
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ JavaFXLibrary works with both Jython (local and remote use) and Python (remote o
JavaFXLibrary is tested to work with Robot Framework 3.0.2 or later.

## Keyword documentation
See keyword [documentation](https://repo1.maven.org/maven2/org/robotframework/javafxlibrary/0.5.3/javafxlibrary-0.5.3.html).
See keyword [documentation](https://repo1.maven.org/maven2/org/robotframework/javafxlibrary/0.5.4/javafxlibrary-0.5.4.html).

For editors (IDEs) keyword documentation can be obtained from [here](https://repo1.maven.org/maven2/org/robotframework/javafxlibrary/0.5.3/javafxlibrary-0.5.3.xml).
For editors (IDEs) keyword documentation can be obtained from [here](https://repo1.maven.org/maven2/org/robotframework/javafxlibrary/0.5.4/javafxlibrary-0.5.4.xml).

## Taking the library into use
### As a local library
Expand Down Expand Up @@ -46,7 +46,7 @@ To use JavaFXLibrary on macOS Mojave you must enable the accessibility features
- Enable accessibility features by checking the box: :white_check_mark: Terminal

## Identifying JavaFX UI objects
[Scenic View](http://fxexperience.com/scenic-view/) is a tool that allows you to inspect the JavaFX application scenegraph. This can be useful especially when you do not have access to the source code.
[Scenic View](https://github.com/JonathanGiles/scenic-view) is a tool that allows you to inspect the JavaFX application scenegraph. This can be useful especially when you do not have access to the source code.

See [keyword documentation](https://eficode.github.io/JavaFXLibrary/javafxlibrary.html#3.%20Locating%20JavaFX%20Nodes) for detailed information about handling UI elements with the library.

Expand Down
2 changes: 1 addition & 1 deletion docs/javafxlibrary.html

Large diffs are not rendered by default.

31 changes: 23 additions & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<groupId>org.robotframework</groupId>
<artifactId>javafxlibrary</artifactId>
<packaging>jar</packaging>
<version>0.5.3</version>
<version>0.5.4</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jmockit.version>1.44</jmockit.version>
Expand Down Expand Up @@ -165,6 +165,22 @@
</distributionManagement>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down Expand Up @@ -251,7 +267,6 @@
<configuration>
<includes>
<include>smoke</include>
<!-- <include>set-datepicker</include>-->
</includes>
<excludes>
<exclude>not-ready</exclude>
Expand Down Expand Up @@ -377,7 +392,7 @@
<dependency>
<groupId>org.robotframework</groupId>
<artifactId>javalib-core</artifactId>
<version>1.2.1</version>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>org.robotframework</groupId>
Expand All @@ -394,11 +409,11 @@
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
<dependency>
<groupId>com.github.ombre42</groupId>
<artifactId>jrobotremoteserver</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.robotframework</groupId>
<artifactId>jrobotremoteserver</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
Expand Down
104 changes: 93 additions & 11 deletions src/main/java/JavaFXLibrary.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,13 @@
import org.python.google.common.base.Throwables;
import org.robotframework.javalib.annotation.Autowired;
import org.robotframework.javalib.library.AnnotationLibrary;
import org.robotframework.remoteserver.RemoteServer;
import org.testfx.util.WaitForAsyncUtils;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import static javafxlibrary.utils.HelperFunctions.*;
import static org.testfx.util.WaitForAsyncUtils.waitFor;
import java.util.ResourceBundle;

public class JavaFXLibrary extends AnnotationLibrary {

Expand Down Expand Up @@ -78,15 +77,93 @@ public JavaFXLibrary(boolean headless) {
}
}

public static String loadRobotLibraryVersion() {
try {
return ResourceBundle.getBundle(JavaFXLibrary.class.getCanonicalName().replace(".", File.separator))
.getString("version");
} catch (RuntimeException e) {
return "unknown";
}
}

@Autowired
protected RunOnFailure runOnFailure;

@Override
public Object runKeyword(String keywordName, List args, Map kwargs) {

if (kwargs == null) {
kwargs = new HashMap();
}

List finalArgs;
Map finalKwargs;

// JavalibCore changes arguments of Call Method keywords to Strings after this check, so they need to handle their own objectMapping
if (!(keywordName.equals("callObjectMethod") || keywordName.equals("callObjectMethodInFxApplicationThread"))) {
finalArgs = HelperFunctions.useMappedObjects(args);
finalKwargs = HelperFunctions.useMappedObjects(kwargs);
} else {
finalArgs = args;
finalKwargs = kwargs;
}


AtomicReference<Object> retval = new AtomicReference<>();
AtomicReference<RuntimeException> retExcep = new AtomicReference<>();

try {
RobotLog.ignoreDuplicates();
// timeout + 500 ms so that underlying timeout has a chance to expire first
waitFor(getWaitUntilTimeout(TimeUnit.MILLISECONDS) + 500, TimeUnit.MILLISECONDS, () -> {

try {
retval.set(super.runKeyword(keywordName, finalArgs, finalKwargs));
return true;

} catch (JavaFXLibraryTimeoutException jfxte){
// timeout already expired, catch exception and jump out
retExcep.set(jfxte);
throw jfxte;

} catch (RuntimeException e){
// catch exception and continue trying
retExcep.set(e);
return false;
}
});
} catch (TimeoutException te) {
RobotLog.reset();
RuntimeException e = retExcep.get();
runOnFailure.runOnFailure();

if (e.getCause() instanceof JavaFXLibraryFatalException) {
RobotLog.trace("JavaFXLibrary: Caught JavaFXLibrary FATAL exception: \n" + Throwables.getStackTraceAsString(e));
throw e;
} else if (e.getCause() instanceof JavaFXLibraryNonFatalException) {
RobotLog.trace("JavaFXLibrary: Caught JavaFXLibrary NON-FATAL exception: \n" + Throwables.getStackTraceAsString(e));
throw e;
} else {
RobotLog.trace("JavaFXLibrary: Caught JavaFXLibrary RUNTIME exception: \n" + Throwables.getStackTraceAsString(e));
throw e;
}
} catch (JavaFXLibraryTimeoutException jfxte) {
RobotLog.reset();
RobotLog.trace("JavaFXLibrary: Caught JavaFXLibrary TIMEOUT exception: \n" + Throwables.getStackTraceAsString(jfxte));
throw jfxte;
}
RobotLog.reset();
return retval.get();
}

// overriding the run method to catch the control in case of failure, so that desired runOnFailureKeyword
// can be executed in controlled manner.
@Override
public Object runKeyword(String keywordName, Object[] args) {
public Object runKeyword(String keywordName, List args) {
// TODO: Check if this is ever called anymore
RobotLog.info("runKeyword called with args ONLY");

Object[] finalArgs;
List finalArgs;
// JavalibCore changes arguments of Call Method keywords to Strings after this check, so they need to handle their own objectMapping
if (!(keywordName.equals("callObjectMethod") || keywordName.equals("callObjectMethodInFxApplicationThread")))
finalArgs = HelperFunctions.useMappedObjects(args);
Expand Down Expand Up @@ -181,22 +258,23 @@ public static JavaFXLibrary getLibraryInstance() throws ScriptException {
}

public static void main(String[] args) throws Exception {
JavaFXLibraryRemoteServer.configureLogging();
System.out.println("---------------------------= JavaFXLibrary =---------------------------- ");
RemoteServer server = new JavaFXLibraryRemoteServer();
server.putLibrary("/RPC2", new JavaFXLibrary());
int port = 8270;
InetAddress ipAddr = InetAddress.getLocalHost();

try {
if (args.length > 0)
JavaFXLibraryRemoteServer.configureLogging();
System.out.println("----------------------------= JavaFXLibrary =-----------------------------");
if (args.length > 0) {
port = Integer.parseInt(args[0]);
else
}
else {
System.out.println("RemoteServer for JavaFXLibrary will be started at default port of: " + port + ".\n" +
"If you wish to use another port, restart the library and give port number\n" +
"as an argument.");
}

server.setPort(port);
JavaFXLibraryRemoteServer server = new JavaFXLibraryRemoteServer(port);
server.putLibrary("/RPC2", new JavaFXLibrary());
server.start();
System.out.println("\n JavaFXLibrary " + ROBOT_LIBRARY_VERSION + " is now available at: " +
ipAddr.getHostAddress() + ":" + port + "\n");
Expand All @@ -210,6 +288,10 @@ public static void main(String[] args) throws Exception {
} catch (BindException be) {
System.out.println("\n Error! " + be.getMessage() + ": " + ipAddr.getHostAddress() + ":" + port + "\n");
System.exit(1);
} catch (IOException ioe) {
System.out.println("\n Error! " + ioe.getMessage() + ": " + ipAddr.getHostAddress() + ":" + port + "\n");
System.exit(1);
}
}
}

18 changes: 10 additions & 8 deletions src/main/java/JavaFXLibraryRemoteServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,27 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.DefaultConfiguration;
import org.robotframework.remoteserver.RemoteServer;
import org.robotframework.remoteserver.logging.Jetty2Log4J;

public class JavaFXLibraryRemoteServer extends RemoteServer {

public JavaFXLibraryRemoteServer(int port) {
super(port);
}

private static Log log = LogFactory.getLog(RemoteServer.class);

public static void configureLogging() {
Logger root = Logger.getRootLogger();
root.removeAllAppenders();
BasicConfigurator.configure();
root.setLevel(Level.FATAL);
Configurator.initialize(new DefaultConfiguration());
Configurator.setRootLevel(Level.FATAL);
org.eclipse.jetty.util.log.Log.setLog(new Jetty2Log4J());
LogFactory.releaseAll();
LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log",
"org.apache.commons.logging.impl.Log4JLogger");
log = LogFactory.getLog(RemoteServer.class);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,23 @@ public void clearObjectMap() {


@RobotKeyword("Returns the class name of currently active JavaFX Application")
public String getCurrentApplication() {
try {
return getCurrentSessionApplicationName();
} catch (Exception e) {
throw new JavaFXLibraryNonFatalException("Problem getting current application name.", e);
}
}

@Deprecated
@RobotKeyword("*DEPRECATED in version 0.6.0!* Use `Get Current Application` keyword instead.\n\n"
+ "Returns the class name of currently active JavaFX Application\n")
public String currentApplication() {
try {
return getCurrentSessionApplicationName();
} catch (Exception e) {
throw new JavaFXLibraryNonFatalException("Problem getting current application name.", e);
}
}

}
Loading