diff --git a/src/main/java/javafxlibrary/keywords/AdditionalKeywords/ApplicationLauncher.java b/src/main/java/javafxlibrary/keywords/AdditionalKeywords/ApplicationLauncher.java index eae81ec..282ad1d 100644 --- a/src/main/java/javafxlibrary/keywords/AdditionalKeywords/ApplicationLauncher.java +++ b/src/main/java/javafxlibrary/keywords/AdditionalKeywords/ApplicationLauncher.java @@ -122,15 +122,19 @@ private void _addPathToClassPath(String path) { @RobotKeyword("Loads given path to classpath.\n\n" + "``path`` is the path to add.\n\n" + + "``failIfNotFound`` is either True or False, default False. In case of False error is written as warning.\n\n" + "If directory path has asterisk(*) after directory separator all jar files are added from directory.\n" + "\nExample:\n" + "| Set To Classpath | C:${/}users${/}my${/}test${/}folder | \n" - + "| Set To Classpath | C:${/}users${/}my${/}test${/}folder${/}* | \n") - @ArgumentNames({ "path" }) - public void setToClasspath(String path) { + + "| Set To Classpath | C:${/}users${/}my${/}test${/}folder${/}* | \n" + + "| Set To Classpath | C:${/}users${/}my${/}test${/}folder2${/}* | failIfNotFound=${True} | \n") + @ArgumentNames({ "path", "failIfNotFound=False" }) + public void setToClasspath(String path, boolean failIfNotFound) { + RobotLog.info("Setting \"" + path + "\" to classpath, failIfNotFound=\"" + failIfNotFound + "\""); if (path.endsWith("*")) { path = path.substring(0, path.length() - 1); - RobotLog.info("Adding all jars from directory: " + path); + RobotLog.info("Adding all jars from directory."); + String fullPath = FileSystems.getDefault().getPath(path).normalize().toAbsolutePath().toString(); try { File directory = new File(path); @@ -143,11 +147,20 @@ public void setToClasspath(String path) { } } if (!jarsFound) { - throw new JavaFXLibraryNonFatalException("No jar files found from classpath: " - + FileSystems.getDefault().getPath(path).normalize().toAbsolutePath().toString()); + String jarsNotFoundError = "No jar files found from classpath: " + fullPath; + if (failIfNotFound) { + throw new JavaFXLibraryNonFatalException(jarsNotFoundError); + } else { + RobotLog.warn(jarsNotFoundError); + } } } catch (NullPointerException e) { - throw new JavaFXLibraryFatalException("Directory not found: " + path + "\n" + e.getMessage(), e); + String directoryNotFoundError = "Directory not found: " + fullPath; + if (failIfNotFound) { + throw new JavaFXLibraryFatalException(directoryNotFoundError); + } else { + RobotLog.warn(directoryNotFoundError); + } } } else { _addPathToClassPath(path); @@ -250,17 +263,6 @@ public String getCurrentApplication() { } } - @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); - } - } - @RobotKeyword("Returns if JavaFXLibrary is started as java agent.") public boolean isJavaAgent() { return TestFxAdapter.isAgent; diff --git a/src/main/java/javafxlibrary/keywords/AdditionalKeywords/ConvenienceKeywords.java b/src/main/java/javafxlibrary/keywords/AdditionalKeywords/ConvenienceKeywords.java index 5d40723..e5e07c1 100644 --- a/src/main/java/javafxlibrary/keywords/AdditionalKeywords/ConvenienceKeywords.java +++ b/src/main/java/javafxlibrary/keywords/AdditionalKeywords/ConvenienceKeywords.java @@ -54,30 +54,6 @@ @RobotKeywords public class ConvenienceKeywords extends TestFxAdapter { - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Use keyword `Find` instead.\n\n" + - "finder that mimics _xpath_ style search.\n\n" - + "``query`` is a query locator, see `3.1 Locator syntax`.\n\n" - + "``failIfNotFound`` specifies if keyword should fail if nothing is found. By default it's false and " - + "keyword returns null in case lookup returns nothing.\n\n" - + "\nExample:\n" - + " | ${node}= | Find With Path | .main-view[0] .split-pane[0] \\#node-id class=GridPane .toggle-button[3] sometext | ") - @ArgumentNames({"query", "failIfNotFound=False"}) - public Object findWithPath(String query, boolean failIfNotFound){ - - try { - return mapObject(findNode(query)); - - } catch (JavaFXLibraryNonFatalException e){ - if(failIfNotFound) - throw new JavaFXLibraryNonFatalException("Unable to find anything with query: \"" + query + "\""); - return ""; - - } catch (Exception e) { - throw new JavaFXLibraryNonFatalException("Find operation failed for query: \"" + query + "\"", e); - } - } - @RobotKeyword("Brings the given stage to front\n\n" + "``stage`` is an Object:Stage to be set in front of others, see `3.2 Using locators as keyword arguments`. \n\n") @ArgumentNames({ "stage" }) @@ -130,116 +106,6 @@ public void callObjectMethodInFxApplicationThread(Object object, String method, callMethod(object, method, finalArgs, true); } - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Use keyword `Find` instead.\n\n" - + "Returns the *first* node matching the query. \n\n" - + "``query`` is the Class name String to use in lookup.\n" - + "\nExample:\n" - + "| ${my node}= | Find | javafx.scene.control.Button | # button class |") - @ArgumentNames({ "query" }) - public Object findClass(final String query) { - try { - Class clazz = Class.forName(query); - InstanceOfMatcher matcher = new InstanceOfMatcher(clazz); - return mapObject(robot.lookup(matcher).query()); - } catch (Exception e) { - RobotLog.trace("Problem has occurred during node lookup: " + e); - return ""; - } - } - - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Use keyword `Find All` instead.\n\n" - + "Returns *all* descendant nodes of given node matching the query. \n\n" - + "``node`` is the starting point Object:Node from where to start looking, see `3.2 Using locators as keyword arguments`. \n\n" - + "``query`` is a query locator, see `3.1 Locator syntax`.\n\n" - + "``failIfNotFound`` specifies if keyword should fail if nothing is found. By default it's false and " - + "keyword returns null in case lookup returns nothing.\n\n" - + "\nExample:\n" - + "| ${my nodes}= | Find All From Node | ${some node} | .css | \n" - + "See keyword `Find` for further examples of query usage.\n") - @ArgumentNames({ "node", "query", "failIfNotFound=False" }) - public List findAllFromNode(Object node, String query, boolean failIfNotFound) { - try { - if ( node instanceof Node ) { - RobotLog.info("Trying to find all nodes with query: \"" + query + "\" that are under starting " + - "point node: \"" + node + "\", failIfNotFound= \"" + failIfNotFound + "\""); - return mapObjects(((Node) node).lookupAll(query)); - } - // fail in case no valid node argument. - failIfNotFound = true; - throw new JavaFXLibraryNonFatalException("Illegal argument type for node."); - } catch (JavaFXLibraryNonFatalException e){ - if(failIfNotFound) - throw e; - return Collections.emptyList(); - - } catch (Exception e) { - throw new JavaFXLibraryNonFatalException("Find all from node operation failed for node: \"" + node.toString() + - "\" and query: " + query, e); - } - } - - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Use keyword `Find All` instead.\n\n" - + "Returns *all* nodes matching query AND given pseudo-class state. \r\n" - + "``query`` is a query locator, see `3.1 Locator syntax`.\n\n" - + "``pseudo`` is a String value specifying pseudo class value.\n\n" - + "``failIfNotFound`` specifies if keyword should fail if nothing is found. By default it's false and " - + "keyword returns null in case lookup returns nothing.\n\n" - + "\nExample:\n" - + "| ${my node}= | Find All With Pseudo Class | .check-box-tree-cell .check-box | selected | \n") - @ArgumentNames({ "query", "pseudo", "failIfNotFound=False" }) - public List findAllWithPseudoClass(String query, String pseudo, boolean failIfNotFound) { - RobotLog.info("Trying to find all nodes with query: \"" + query + "\" that has pseudoclass state as: \"" + - pseudo + "\", failIfNotFound= \"" + failIfNotFound + "\""); - try { - Set nodes = robot.lookup(query).queryAll(); - Set matches = nodes.stream() - .filter(n -> n.getPseudoClassStates().stream(). - map(PseudoClass::getPseudoClassName).anyMatch(pseudo::contains)) - .collect(Collectors.toSet()); - return mapObjects(matches); - - } catch (JavaFXLibraryNonFatalException e){ - if(failIfNotFound) - throw e; - return Collections.emptyList(); - - } catch (Exception e) { - throw new JavaFXLibraryNonFatalException("Find all with pseudo class operation failed for query: \"" + - query + "\" and pseudo: \"" + pseudo + "\"", e); - } - } - - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Use keyword `Find` instead.\n\n" - + "Returns the *first* descendant node of given node matching the query. \n\n" - + "``node`` is the starting point Object:Node from where to start looking, see `3.2 Using locators as keyword arguments`. \n\n" - + "``query`` is a query locator, see `3.1 Locator syntax`.\n\n" - + "``failIfNotFound`` specifies if keyword should fail if nothing is found. By default it's false and " - + "keyword returns null in case lookup returns nothing.\n\n" - + "\nExample:\n" - + "| ${my node}= | Find From Node | ${some node} | .css |\n" - + "See keyword `Find` for further examples of query usage.\n") - @ArgumentNames({ "node", "query", "failIfNotFound=False" }) - public Object findFromNode(Node node, String query, boolean failIfNotFound) { - RobotLog.info("Trying to find: \"" + query + "\" from node: \"" + node + "\", failIfNotFound= \"" + failIfNotFound + "\""); - try { - Node childNode = node.lookup(query); - return mapObject(childNode); - - } catch (JavaFXLibraryNonFatalException e){ - if(failIfNotFound) - throw e; - return ""; - - } catch (Exception e) { - throw new JavaFXLibraryNonFatalException("Find from node operation failed for node: \"" + node + - "\" and query: " + query, e); - } - } - @RobotKeyword("Lists methods available for given node.\n" + "``node`` is the Object:Node which methods to list, see `3.2 Using locators as keyword arguments`. \n\n" + "When working with custom components you may use this keyword to discover methods you can call " @@ -390,40 +256,6 @@ public Set getPseudoClassStates(Object locator) { } } - // TODO: Should this be deleted? Find All From Node has the same functionality - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Use keyword `Find` instead.\n\n" - + "Returns *all* descendant nodes of given node matching the given Java class name. \n\n" - + "``locator`` is either a _query_ or _Object_ for node whose children will be queried, see " - + "`3.2 Using locators as keyword arguments`. \n\n" - + "``className`` is the Java class name to look for.\n" - + "\nExample:\n" - + "| ${panes}= | Get Node Children By Class Name | ${some node} | BorderPane | \n" - + "Returns an empty list if none is found. \n") - @ArgumentNames({ "node", "className" }) - public Set getNodeChildrenByClassName(Object locator, String className) { - Node node = objectToNode(locator); - RobotLog.info("Getting node: \"" + node + "\" children by class name: \"" + className + "\""); - try { - Set keys = new HashSet<>(); - Set childNodes = node.lookupAll("*"); - - for (Object o : childNodes) { - Node childNode = (Node) o; - if (childNode.getClass().getSimpleName().equals(className)) { - RobotLog.trace("Classname: \"" + className + "\" found: \"" + childNode + "\""); - keys.add(mapObject(childNode)); - } - } - return keys; - } catch (Exception e) { - if(e instanceof JavaFXLibraryNonFatalException) - throw e; - throw new JavaFXLibraryNonFatalException("Unable to get node children for node: \"" + node.toString() + - "\" with class name: " + className, e); - } - } - @RobotKeyword("Returns text value of the Node. \n\n" + "``locator`` is either a _query_ or _Object_ for a node whose getText method will be called, see " + "`3. Locating JavaFX Nodes`. \n\n") @@ -441,35 +273,6 @@ public String getNodeText(Object locator) { } } - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Use keyword `Find` instead.\n\n" - + "Returns height value of the node. \n\n" - + "``locator`` is either a _query_ or _Object_ for a node whose getHeight method will be called, see " - + "`3. Locating JavaFX Nodes`. \n\n") - @ArgumentNames({ "locator" }) - public String getNodeHeight(Object locator) { - Node node = objectToNode(locator); - try { - Method[] methods = node.getClass().getMethods(); - for (Method m : methods) { - if (m.getName().equals("getHeight")) { - try { - Object result = m.invoke(node, (Object) null); - return result.toString(); - } catch (Exception e) { - throw new JavaFXLibraryNonFatalException("Problem calling method: .getHeight(): " + e.getMessage(), e); - } - } - } - throw new JavaFXLibraryNonFatalException( - "Get node height failed for node: \"" + node.toString() + "\". Element has no method getHeight()"); - } catch (Exception e) { - if (e instanceof JavaFXLibraryNonFatalException) - throw e; - throw new JavaFXLibraryNonFatalException("Unable to get node height for node: " + node.toString(), e); - } - } - @RobotKeyword("Returns image name and path of the node. \n\n" + "``locator`` is either a _query_ or _Object_ for a node whose getHeight method will be called, see " + "`3. Locating JavaFX Nodes`. \n\n" @@ -535,31 +338,6 @@ public String getObjectClassName(Object locator) { } } - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Use keyword `Get Scene` instead.\n\n" - +"Returns given locators Scene object. \n\n" - + "``locator`` is either a _query_ or a _Node_, see `3.2 Using locators as keyword arguments`\n\n") - @ArgumentNames({ "locator" }) - public Object getNodesScene(Object locator) { - try { - if (locator instanceof Node){ - RobotLog.info("Getting a Scene object for a Node: \"" + locator + "\""); - return mapObject(((Node) locator).getScene()); - } else if (locator instanceof String) { - RobotLog.info("Getting a Scene object for a query: \"" + locator + "\""); - Node node = objectToNode(locator); - return mapObject(node.getScene()); - } - - throw new JavaFXLibraryNonFatalException("Locator type is not a Node or a query string!"); - - } catch (Exception e) { - if (e instanceof JavaFXLibraryNonFatalException) - throw e; - throw new JavaFXLibraryNonFatalException("Unable to get Scene object for locator: \"" + locator + "\"", e); - } - } - @RobotKeyword("Returns Scene of the given object. \n\n" + "``locator`` is either a _query_, a _Node_ or a _Window_, see `3.2 Using locators as keyword arguments`\n\n") @ArgumentNames({ "locator" }) @@ -776,11 +554,24 @@ public int getTableColumnCount(Object locator){ } @RobotKeyword("Sets the screenshot directory for current application\n\n" - + "``directory`` is a path to a folder which is to be set as current screenshot directory") - @ArgumentNames({ "directory" }) - public void setScreenshotDirectory(String dir){ - RobotLog.info("Setting new screenshot directory: " + dir); - setCurrentSessionScreenshotDirectory(dir); + + "Notice that relative paths are from current work dir of JavaFXLibrary:\n" + + "- In case of Java Agent it comes from Application Under Test (AUT).\n" + + "- In case of JavaFXLibrary is started with \"java -jar *\" command it uses the current working directory as source.\n" + + "``directory`` is a path to a folder which is to be set as current screenshot directory in host where " + + "JavaFXLibrary is run.\n\n" + + "``logDirectory`` is a path that is put to log.html files that can be used after screenshots are moved " + + "from target system to e.g. CI workspace. Typically this is relative path.\n\n\n" + + "Example:\n" + + "| Set Screenshot Directory | /Users/robotuser/output/AUT-screenshots/ | ./output/AUT-screenshots/ | \n" + + "or\n" + + "| Set Screenshot Directory | ./output/AUT-screenshots/ | \n") + @ArgumentNames({ "directory", "logDirectory=" }) + public void setScreenshotDirectory(String dir, String logDir){ + RobotLog.info("Setting screenshot directory to \"" + dir + "\"."); + if (logDir != null && !logDir.isEmpty()) { + RobotLog.info("Log directory is set to \"" + logDir + "\""); + } + setCurrentSessionScreenshotDirectory(dir, logDir); } @RobotKeyword("Gets the screenshot directory for current application") diff --git a/src/main/java/javafxlibrary/keywords/AdditionalKeywords/Verifiers.java b/src/main/java/javafxlibrary/keywords/AdditionalKeywords/Verifiers.java index 869fdaa..f6181d3 100644 --- a/src/main/java/javafxlibrary/keywords/AdditionalKeywords/Verifiers.java +++ b/src/main/java/javafxlibrary/keywords/AdditionalKeywords/Verifiers.java @@ -158,16 +158,6 @@ public static void nodeShouldNotBeVisible(Object locator) { verifyThat(objectToNode(locator), isInvisible() ); } - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Use `Node Should Not Be Visible` instead.\n\n" - + "Verifies that node is invisible. \n\n" - + "``locator`` is either a _query_ or _Object:Node_ for identifying the Node, see " - + "`3. Locating JavaFX Nodes`. \n\n") - @ArgumentNames({ "locator" }) - public static void nodeShouldBeInvisible(Object locator) { - verifyThat(objectToNode(locator), isInvisible() ); - } - @RobotKeyword("Verifies that node is focused. \n\n" + "``locator`` is either a _query_ or _Object:Node_ for identifying the Node, see " + "`3. Locating JavaFX Nodes`. \n\n") @@ -204,16 +194,6 @@ public static void nodeShouldNotBeEnabled(Object locator) { verifyThat(objectToNode(locator), NodeMatchers.isDisabled() ); } - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Use `Node Should Not Be Enabled` instead." - + "Verifies that node is disabled. \n\n" - + "``locator`` is either a _query_ or _Object:Node_ for identifying the Node, see " - + "`3. Locating JavaFX Nodes`. \n\n") - @ArgumentNames({ "locator" }) - public static void nodeShouldBeDisabled(Object locator) { - verifyThat(objectToNode(locator), NodeMatchers.isDisabled() ); - } - @RobotKeyword("Verifies that node is hoverable with mouse. \n\n" + "``locator`` is either a _query_ or _Object:Node_ for identifying the Node, see " + "`3. Locating JavaFX Nodes`. \n\n") @@ -290,14 +270,6 @@ public static void windowShouldBeVisible(Object window) { verifyThat((Window) window, WindowMatchers.isShowing()); } - @Deprecated - @RobotKeyword("*DEPRECATED in version 0.6.0!* Please use `Window Should Be Visible` instead.\n\n" +"Verifies that given window is showing. \n\n" - + "``window`` is the _Object:Window_ that specifies which window should be showing, see `3.2 Using locators as keyword arguments`.") - @ArgumentNames({ "window" }) - public static void windowShouldBeShowing(Object window) { - verifyThat((Window) window, WindowMatchers.isShowing()); - } - @RobotKeyword("Verifies that given window is not visible.\n\n" + "``window`` is the _Object:Window_ that specifies which window should be not visible, see `3.2 Using locators as keyword arguments`.") @ArgumentNames({ "window" }) diff --git a/src/main/java/javafxlibrary/keywords/Keywords/BoundsLocation.java b/src/main/java/javafxlibrary/keywords/Keywords/BoundsLocation.java index 71617ca..8804c04 100644 --- a/src/main/java/javafxlibrary/keywords/Keywords/BoundsLocation.java +++ b/src/main/java/javafxlibrary/keywords/Keywords/BoundsLocation.java @@ -125,7 +125,7 @@ public Object getBounds(Object locator) { return HelperFunctions.mapObject(bounds.query()); } catch (IllegalAccessException | InvocationTargetException e) { - throw new JavaFXLibraryNonFatalException("Could not execute move to using locator \"" + locator + "\": " + throw new JavaFXLibraryNonFatalException("getBounds: Could not execute move to using locator \"" + locator + "\": " + e.getCause().getMessage()); } catch (JavaFXLibraryNonFatalException e){ diff --git a/src/main/java/javafxlibrary/keywords/Keywords/MoveRobot.java b/src/main/java/javafxlibrary/keywords/Keywords/MoveRobot.java index 3da2df5..27ba604 100644 --- a/src/main/java/javafxlibrary/keywords/Keywords/MoveRobot.java +++ b/src/main/java/javafxlibrary/keywords/Keywords/MoveRobot.java @@ -48,23 +48,21 @@ public class MoveRobot extends TestFxAdapter { + "| Move To | ${POINT} | VERTICAL_FIRST | | # moves mouse on top of given Point object by moving first vertically and then horizontally |") @ArgumentNames({ "locator", "motion=DIRECT" }) public FxRobotInterface moveTo(Object locator, String motion) { - RobotLog.info("Moving to target \"" + locator + "\" using motion: \"" + getMotion(motion) + "\""); - if (locator instanceof String) { - String originalLocator = (String) locator; - locator = new Finder().find((String) locator); - if(locator==null) { - throw new JavaFXLibraryNonFatalException("Unable to move as locator \"" + originalLocator + "\" not found!"); - } else { - RobotLog.info("Locator at this point: " + locator); - } - } - - Method method = MethodUtils.getMatchingAccessibleMethod(robot.getClass(), "moveTo", locator.getClass(), Motion.class); - try { + RobotLog.info("Moving to target \"" + locator + "\" using motion: \"" + getMotion(motion) + "\""); + if (locator instanceof String) { + String originalLocator = (String) locator; + locator = new Finder().find((String) locator); + if(locator==null) { + throw new JavaFXLibraryNonFatalException("Unable to move as locator \"" + originalLocator + "\" not found!"); + } else { + RobotLog.info("Locator at this point: " + locator); + } + } + Method method = MethodUtils.getMatchingAccessibleMethod(robot.getClass(), "moveTo", locator.getClass(), Motion.class); return (FxRobotInterface) method.invoke(robot, locator, getMotion(motion)); } catch (IllegalAccessException | InvocationTargetException e) { - throw new JavaFXLibraryNonFatalException("Could not execute move to using locator \"" + locator + "\" " + + throw new JavaFXLibraryNonFatalException("moveTo: Could not execute move to using locator \"" + locator + "\" " + "and motion " + motion + ": " + e.getCause().getMessage(), e); } } diff --git a/src/main/java/javafxlibrary/keywords/Keywords/ScreenCapturing.java b/src/main/java/javafxlibrary/keywords/Keywords/ScreenCapturing.java index 1d4532f..ae2a27f 100644 --- a/src/main/java/javafxlibrary/keywords/Keywords/ScreenCapturing.java +++ b/src/main/java/javafxlibrary/keywords/Keywords/ScreenCapturing.java @@ -91,12 +91,19 @@ public Object captureImage(Object locator, boolean logImage){ RobotLog.info("Capturing screenshot from locator: \"" + locator + "\""); Image image; Bounds targetBounds = objectToBounds(locator); + String logPath; try { image = robot.capture(targetBounds).getImage(); Path path = createNewImageFileNameWithPath(); robotContext().getCaptureSupport().saveImage(image, path); + if (getCurrentSessionScreenshotDirectoryInLogs() != null) { + logPath = getCurrentSessionScreenshotDirectoryInLogs()+"/"+path.getFileName(); + } else { + logPath = path.toString(); + } + if (logImage) { double printSize = targetBounds.getWidth() > 800 ? 800 : targetBounds.getWidth(); @@ -113,13 +120,13 @@ public Object captureImage(Object locator, boolean logImage){ RobotLog.warn("Capture temporary image \"" + imageFile.getAbsolutePath() + "\" deletion failed."); } } - RobotLog.html("" + RobotLog.html("" + "" + ""); } else { // diskonly option - RobotLog.html("" + RobotLog.html("" + "" + ""); } diff --git a/src/main/java/javafxlibrary/matchers/ExtendedNodeMatchers.java b/src/main/java/javafxlibrary/matchers/ExtendedNodeMatchers.java index 89ae237..d2bd9c7 100644 --- a/src/main/java/javafxlibrary/matchers/ExtendedNodeMatchers.java +++ b/src/main/java/javafxlibrary/matchers/ExtendedNodeMatchers.java @@ -60,7 +60,6 @@ private static boolean hoverable(Node node) { waitFor(HelperFunctions.getWaitUntilTimeout(), HelperFunctions.getTimeUnit("SECONDS"), () -> { return asyncFx(() -> new javafxlibrary.keywords.Keywords.MoveRobot().moveTo(node, "DIRECT") != null).get(); }); - waitForFxEvents(); return node.isHover(); } catch (JavaFXLibraryNonFatalException nfe) { throw nfe; diff --git a/src/main/java/javafxlibrary/utils/HelperFunctions.java b/src/main/java/javafxlibrary/utils/HelperFunctions.java index 1c82fc3..b932560 100644 --- a/src/main/java/javafxlibrary/utils/HelperFunctions.java +++ b/src/main/java/javafxlibrary/utils/HelperFunctions.java @@ -89,7 +89,6 @@ public static Node waitUntilExists(String target, int timeout, String timeUnit) Node node = asyncFx(() -> createFinder().find(target)).get(); // TODO: Add null checks for node.getScene() waitFor(timeout, getTimeUnit(timeUnit), () -> asyncFx(() -> hasValidCoordinates(node)).get()); - waitForFxEvents(); return node; } catch (JavaFXLibraryNonFatalException nfe) { throw nfe; @@ -97,8 +96,8 @@ public static Node waitUntilExists(String target, int timeout, String timeUnit) throw new JavaFXLibraryTimeoutException("Given element \"" + target + "\" was not found within given timeout of " + timeout + " " + timeUnit); } catch (Exception e) { - RobotLog.trace("Exception in waitUntilExists: " + e + "\n" + e.getCause().toString()); - throw new JavaFXLibraryNonFatalException("Given element \"" + target + "\" was not found.", e); + RobotLog.trace("Exception in waitUntilExists: " + e.getCause().toString()); + throw new JavaFXLibraryNonFatalException("Given element \"" + target + "\" was not found (" + e.getCause().toString() + ")."); } } @@ -108,7 +107,6 @@ public static void waitUntilDoesNotExists(String target, int timeout, String tim try { waitFor(timeout, getTimeUnit(timeUnit), () -> asyncFx(() -> createFinder().find(target) == null).get()); - waitForFxEvents(); } catch (JavaFXLibraryNonFatalException nfe) { throw nfe; } catch (TimeoutException te) { @@ -131,7 +129,7 @@ public static Node waitUntilVisible(Object target, int timeout) { RobotLog.trace("Waiting until target \"" + target + "\" becomes visible, timeout=" + timeout); try { - waitFor(timeout, TimeUnit.SECONDS, () -> Matchers.is(isVisible()).matches(finalTarget)); + waitFor(timeout, TimeUnit.SECONDS, () -> asyncFx(() -> Matchers.is(isVisible()).matches(finalTarget)).get()); return (Node) target; } catch (JavaFXLibraryNonFatalException nfe) { throw nfe; @@ -153,7 +151,7 @@ public static Node waitUntilInvisible(Object target, int timeout) { RobotLog.trace("Waiting until target \"" + target + "\" becomes invisible, timeout=" + timeout); try { - waitFor(timeout, TimeUnit.SECONDS, () -> Matchers.is(isInvisible()).matches(finalTarget)); + waitFor(timeout, TimeUnit.SECONDS, () -> asyncFx(() -> Matchers.is(isInvisible()).matches(finalTarget)).get()); return (Node) target; } catch (JavaFXLibraryNonFatalException nfe) { throw nfe; @@ -174,7 +172,7 @@ public static Node waitUntilEnabled(Object target, int timeout) { RobotLog.trace("Waiting until target \"" + target + "\" becomes enabled, timeout=" + timeout); try { - waitFor(timeout, TimeUnit.SECONDS, () -> Matchers.is(isEnabled()).matches(finalTarget)); + waitFor(timeout, TimeUnit.SECONDS, () -> asyncFx(() -> (Matchers.is(isEnabled()).matches(finalTarget))== true).get()); return (Node) target; } catch (JavaFXLibraryNonFatalException nfe) { throw nfe; @@ -195,7 +193,7 @@ public static Node waitUntilDisabled(Object target, int timeout) { RobotLog.trace("Waiting until target \"" + target + "\" becomes disabled, timeout=" + timeout); try { - waitFor(timeout, TimeUnit.SECONDS, () -> Matchers.is(isDisabled()).matches(finalTarget)); + waitFor(timeout, TimeUnit.SECONDS, () -> asyncFx(() -> Matchers.is(isDisabled()).matches(finalTarget) == true).get()); return (Node) target; } catch (JavaFXLibraryNonFatalException nfe) { throw nfe; @@ -209,7 +207,7 @@ public static Node waitUntilDisabled(Object target, int timeout) { public static void waitForProgressBarToFinish(ProgressBar pb, int timeout) { try { - waitFor(timeout, TimeUnit.SECONDS, () -> Matchers.is(ProgressBarMatchers.isComplete()).matches(pb)); + waitFor(timeout, TimeUnit.SECONDS, () -> asyncFx(() -> Matchers.is(ProgressBarMatchers.isComplete()).matches(pb)).get()); } catch (TimeoutException te) { throw new JavaFXLibraryNonFatalException("Given ProgressBar did not complete in " + timeout + " seconds!"); } @@ -650,73 +648,6 @@ private static String remainingQueries(String query) { return queries[1]; } - - // Deprecated: Use javafxlibrary.utils.finder.finder instead - @Deprecated - public static Node findNode(Node node, String query) { - - RobotLog.info("Finding from node: " + node.toString() + " with query: " + query); - - if (query != null) { - List nodelist = new ArrayList<>(); - - String currentQuery = query.split(" ", 2)[0]; - String nextQuery = remainingQueries(query); - RobotLog.info("CurrentQuery: " + currentQuery + ", nextQuery: " + nextQuery); - - if (currentQuery.startsWith("class=")) { - nodelist.addAll(node.lookupAll((getQueryString(currentQuery)).replaceFirst("^class=", ""))); - } else { - nodelist.addAll(robot.from(node).lookup(getQueryString(currentQuery)).queryAll()); - } - - if (nodelist.isEmpty()) { - return null; - } else { - if (getQueryIndex(currentQuery) != -1) { - // if index [..] was given, continue search with only one match - return findNode(nodelist.get(getQueryIndex(currentQuery)), nextQuery); - } else { - // no index given, continue search with all matches - Node newNode; - - for (Node n : nodelist) { - newNode = findNode(n, nextQuery); - if (newNode != null) - return newNode; - } - return null; - } - } - } else { - return node; - } - } - - // Deprecated: Use javafxlibrary.utils.finder.finder instead - @Deprecated - public static Node findNode(String query) { - return findNode(robot.listTargetWindows().get(0).getScene().getRoot(), query); - } - - // Deprecated: Used only in deprecated method findNode - @Deprecated - public static String getQueryString(String query) { - return query.replaceAll("\\[\\d]$", ""); - } - - // Deprecated: Used only in deprecated method findNode - @Deprecated - public static int getQueryIndex(String query) { - Pattern pattern = Pattern.compile(".*\\[\\d]$"); - Matcher matcher = pattern.matcher(query); - if (matcher.matches()) { - String index = StringUtils.substringBetween(query, "[", "]"); - return Integer.parseInt(index); - } - return -1; - } - public static Node getHoveredNode() { return getHoveredNode(robot.listTargetWindows().get(0).getScene().getRoot()); } diff --git a/src/main/java/javafxlibrary/utils/Session.java b/src/main/java/javafxlibrary/utils/Session.java index e415c82..5950b0a 100644 --- a/src/main/java/javafxlibrary/utils/Session.java +++ b/src/main/java/javafxlibrary/utils/Session.java @@ -44,6 +44,7 @@ public class Session { public Application sessionApplication; public String applicationName; public String screenshotDirectory; + public String screenshotDirectoryInLogs; public Session(String appName, String... appArgs) { try { diff --git a/src/main/java/javafxlibrary/utils/TestFxAdapter.java b/src/main/java/javafxlibrary/utils/TestFxAdapter.java index 59633ee..bc4f084 100644 --- a/src/main/java/javafxlibrary/utils/TestFxAdapter.java +++ b/src/main/java/javafxlibrary/utils/TestFxAdapter.java @@ -106,8 +106,14 @@ public String getCurrentSessionScreenshotDirectory() { } } - public void setCurrentSessionScreenshotDirectory(String dir) { - + public String getCurrentSessionScreenshotDirectoryInLogs() { + if (activeSession != null) { + return activeSession.screenshotDirectoryInLogs; + } else { + throw new JavaFXLibraryNonFatalException("Unable to get screenshot directory in logs, no application is currently open!"); + } + } + public void setCurrentSessionScreenshotDirectory(String dir, String logDir) { if (activeSession != null) { File errDir = new File(dir); if (!errDir.exists()) { @@ -116,6 +122,9 @@ public void setCurrentSessionScreenshotDirectory(String dir) { } } activeSession.screenshotDirectory = dir; + if (logDir != null && !logDir.isEmpty()) { + activeSession.screenshotDirectoryInLogs = logDir; + } } else { throw new JavaFXLibraryNonFatalException("Unable to set screenshot directory, no application is currently open!"); } diff --git a/src/main/java/javafxlibrary/utils/finder/Finder.java b/src/main/java/javafxlibrary/utils/finder/Finder.java index e7687d3..23f053e 100644 --- a/src/main/java/javafxlibrary/utils/finder/Finder.java +++ b/src/main/java/javafxlibrary/utils/finder/Finder.java @@ -136,7 +136,6 @@ private Set findAll(Parent root, int queryIndex) { } else { results.addAll(nodes); } - return results; } diff --git a/src/main/java/libdoc-documentation.txt b/src/main/java/libdoc-documentation.txt index e5b91ba..99c3d9a 100644 --- a/src/main/java/libdoc-documentation.txt +++ b/src/main/java/libdoc-documentation.txt @@ -47,11 +47,11 @@ Experimental headless mode can be activated in remote mode at the import time by | *Settings* | *Value* | | Library | Remote | http://localhost:8270 | ${True} | WITH NAME | JavaFXLibrary | -Experimental: Java agent support +Experimental Java agent support Library can be used as java agent. Launch application with `-javaagent:/path/to/javafxlibrary-.jar`. Default port is 8270 and can be changed with adding `=` to java agent command. Only remote library is supported. -Using launch keyword is still required but instead of starting new application keyword initializes Stage for library. +Using `Launch JavaFX Application` is still required but instead of starting new application keyword initializes Stage for library. == 3. Locating JavaFX Nodes == === 3.1 Locator syntax === diff --git a/src/test/java/javafxlibrary/keywords/AdditionalKeywordsTests/ConvenienceKeywords/DeprecatedFindKeywordsTest.java b/src/test/java/javafxlibrary/keywords/AdditionalKeywordsTests/ConvenienceKeywords/DeprecatedFindKeywordsTest.java deleted file mode 100644 index c9ae337..0000000 --- a/src/test/java/javafxlibrary/keywords/AdditionalKeywordsTests/ConvenienceKeywords/DeprecatedFindKeywordsTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2017-2018 Eficode Oy - * Copyright 2018- Robot Framework Foundation - * - * 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 javafxlibrary.keywords.AdditionalKeywordsTests.ConvenienceKeywords; - -import java.util.List; -import com.google.common.collect.ImmutableSet; -import javafx.css.PseudoClass; -import javafx.scene.control.Button; -import javafxlibrary.TestFxAdapterTest; -import javafxlibrary.keywords.AdditionalKeywords.ConvenienceKeywords; -import javafxlibrary.utils.HelperFunctions; -import mockit.Expectations; -import mockit.Mocked; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.testfx.service.query.NodeQuery; - -public class DeprecatedFindKeywordsTest extends TestFxAdapterTest { - - @Mocked - NodeQuery rootQuery; - - private Button button; - private Button button2; - private static ConvenienceKeywords keywords; - - @BeforeClass - public static void setupKeywords() { - keywords = new ConvenienceKeywords(); - } - - @Before - public void setup() { - button = new Button(); - button2 = new Button(); - button.pseudoClassStateChanged(PseudoClass.getPseudoClass("selected"), true); - new Expectations() { - { - getRobot().lookup("rootId"); - result = rootQuery; - minTimes = 0; - } - }; - } - - @Test - public void findAllWithPseudoClass() { - expectTwoButtonsFromNodeQuery(); - List allWithPseudoClass = keywords.findAllWithPseudoClass("rootId", "selected", true); - Assert.assertEquals(HelperFunctions.mapObject(button), allWithPseudoClass.get(0)); - } - - @Test - public void findNoPseudoClasses() { - expectTwoButtonsFromNodeQuery(); - List hits = keywords.findAllWithPseudoClass("rootId", "something", false); - Assert.assertEquals(0, hits.size()); - } - - @Test - public void findNoNodes() { - new Expectations() { - { - rootQuery.queryAll(); - result = ImmutableSet.of(); - } - }; - List hits = keywords.findAllWithPseudoClass("rootId", "something", false); - Assert.assertEquals(0, hits.size()); - } - - private void expectTwoButtonsFromNodeQuery() { - new Expectations() { - { - rootQuery.queryAll(); - result = ImmutableSet.of(button, button2); - } - }; - } -}