4141import javax .script .ScriptEngine ;
4242import javax .script .ScriptEngineManager ;
4343import javax .script .ScriptException ;
44+ import static org .testfx .util .WaitForAsyncUtils .*;
4445import static javafxlibrary .utils .HelperFunctions .*;
45- import static org . testfx . util . WaitForAsyncUtils . waitFor ;
46+
4647import java .util .ResourceBundle ;
4748
4849public class JavaFXLibrary extends AnnotationLibrary {
@@ -51,6 +52,66 @@ public class JavaFXLibrary extends AnnotationLibrary {
5152 public static final String ROBOT_LIBRARY_VERSION = loadRobotLibraryVersion ();
5253 public static final TestListener ROBOT_LIBRARY_LISTENER = new TestListener ();
5354
55+ static List <String > noLibraryKeywordTimeoutKeywords = new ArrayList <String >() {{
56+ add ("launchJavafxApplication" );
57+ add ("launchSwingApplication" );
58+ add ("launchSwingApplicationInSeparateThread" );
59+ add ("closeJavafxApplication" );
60+ add ("closeSwingApplication" );
61+ add ("waitForEventsInFxApplicationThread" );
62+ add ("waitUntilElementDoesNotExists" );
63+ add ("waitUntilElementExists" );
64+ add ("waitUntilNodeIsEnabled" );
65+ add ("waitUntilNodeIsNotEnabled" );
66+ add ("waitUntilNodeIsNotVisible" );
67+ add ("waitUntilNodeIsVisible" );
68+ add ("waitUntilProgressBarIsFinished" );
69+ }};
70+
71+ static List <String > noWrappedAsyncFxKeywords = new ArrayList <String >() {{
72+ add ("callObjectMethodInFxApplicationThread" );
73+ add ("captureImage" );
74+ add ("capturePrimaryScreen" );
75+ add ("captureSceneContainingNode" );
76+ add ("clearObjectMap" );
77+ add ("closeJavafxApplication" );
78+ add ("closeSwingApplication" );
79+ add ("dragFrom" );
80+ add ("dropTo" );
81+ add ("dropToCoordinates" );
82+ add ("getCurrentApplication" );
83+ add ("getLibraryVersion" );
84+ add ("getScreenshot Directory" );
85+ add ("getScreenshotDirectory" );
86+ add ("getSystemProperty" );
87+ add ("isJavaAgent" );
88+ add ("launchJavafxApplication" );
89+ add ("launchSwingApplication" );
90+ add ("launchSwingApplicationInSeparateThread" );
91+ add ("logApplicationClasspath" );
92+ add ("logSystemProperties" );
93+ add ("moveTo" );
94+ add ("nodeShouldBeHoverable" );
95+ add ("nodeShouldNotBeHoverable" );
96+ add ("pushManyTimes" );
97+ add ("setImageLogging" );
98+ add ("setSafeClicking" );
99+ add ("setScreenshotDirectory" );
100+ add ("setSystemProperty" );
101+ add ("setTimeout" );
102+ add ("setToClasspath" );
103+ add ("setWriteSpeed" );
104+ add ("waitForEventsInFxApplicationThread" );
105+ add ("waitUntilElementDoesNotExists" );
106+ add ("waitUntilElementExists" );
107+ add ("waitUntilNodeIsEnabled" );
108+ add ("waitUntilNodeIsNotEnabled" );
109+ add ("waitUntilNodeIsNotVisible" );
110+ add ("waitUntilNodeIsVisible" );
111+ add ("waitUntilProgressBarIsFinished" );
112+ add ("writeTo" );
113+ }};
114+
54115 static List <String > includePatterns = new ArrayList <String >() {{
55116 add ("javafxlibrary/keywords/AdditionalKeywords/*.class" );
56117 add ("javafxlibrary/keywords/Keywords/*.class" );
@@ -91,11 +152,9 @@ public static String loadRobotLibraryVersion() {
91152
92153 @ Override
93154 public Object runKeyword (String keywordName , List args , Map kwargs ) {
94-
95155 if (kwargs == null ) {
96156 kwargs = new HashMap ();
97157 }
98-
99158 List finalArgs ;
100159 Map finalKwargs ;
101160
@@ -108,110 +167,70 @@ public Object runKeyword(String keywordName, List args, Map kwargs) {
108167 finalKwargs = kwargs ;
109168 }
110169
170+ // Run keyword either in async or asyncFx thread with or without timeout
171+ // Execution collects retval and retExcep from keyword
111172 AtomicReference <Object > retval = new AtomicReference <>();
112173 AtomicReference <RuntimeException > retExcep = new AtomicReference <>();
113-
174+ RobotLog . ignoreDuplicates ();
114175 try {
115- RobotLog .ignoreDuplicates ();
116- // timeout + 500 ms so that underlying timeout has a chance to expire first
117- waitFor (getWaitUntilTimeout (TimeUnit .MILLISECONDS ) + 500 , TimeUnit .MILLISECONDS , () -> {
118-
119- try {
176+ if (noWrappedAsyncFxKeywords .contains (keywordName )) {
177+ // no asyncFx thread
178+ if (noLibraryKeywordTimeoutKeywords .contains (keywordName )) {
179+ // without timeout
120180 retval .set (super .runKeyword (keywordName , finalArgs , finalKwargs ));
121- return true ;
122-
123- } catch (JavaFXLibraryTimeoutException jfxte ) {
124- // timeout already expired, catch exception and jump out
125- retExcep .set (jfxte );
126- throw jfxte ;
127-
128- } catch (RuntimeException e ) {
129- // catch exception and continue trying
130- retExcep .set (e );
131- return false ;
181+ } else {
182+ // in async thread
183+ retval .set (waitForAsync (getLibraryKeywordTimeout (TimeUnit .MILLISECONDS ), () -> {
184+ try {
185+ return super .runKeyword (keywordName , finalArgs , finalKwargs );
186+ } catch (RuntimeException rte ) {
187+ retExcep .set (rte );
188+ return null ;
189+ }
190+ }));
132191 }
133- });
134- } catch (TimeoutException te ) {
135- RobotLog .reset ();
136- RuntimeException e = retExcep .get ();
137- runOnFailure .runOnFailure ();
138-
139- if (e .getCause () instanceof JavaFXLibraryFatalException ) {
140- RobotLog .trace ("JavaFXLibrary: Caught JavaFXLibrary FATAL exception: \n " + Throwables .getStackTraceAsString (e ));
141- throw e ;
142- } else if (e .getCause () instanceof JavaFXLibraryNonFatalException ) {
143- RobotLog .trace ("JavaFXLibrary: Caught JavaFXLibrary NON-FATAL exception: \n " + Throwables .getStackTraceAsString (e ));
144- throw e ;
145192 } else {
146- RobotLog .trace ("JavaFXLibrary: Caught JavaFXLibrary RUNTIME exception: \n " + Throwables .getStackTraceAsString (e ));
147- throw e ;
193+ // in asyncFx thread
194+ retval .set (waitForAsyncFx (getLibraryKeywordTimeout (TimeUnit .MILLISECONDS ), () -> {
195+ try {
196+ return super .runKeyword (keywordName , finalArgs , finalKwargs );
197+ } catch (RuntimeException rte ) {
198+ retExcep .set (rte );
199+ return null ;
200+ }
201+ }));
202+ waitForFxEvents ( 5 );
148203 }
149204 } catch (JavaFXLibraryTimeoutException jfxte ) {
150- RobotLog .reset ();
151- RobotLog .trace ("JavaFXLibrary: Caught JavaFXLibrary TIMEOUT exception: \n " + Throwables .getStackTraceAsString (jfxte ));
152- throw jfxte ;
205+ // timeout already expired, catch exception and jump out
206+ retExcep .set (jfxte );
207+ } catch (RuntimeException rte ) {
208+ // catch exception and continue trying
209+ retExcep .set (rte );
153210 }
154- RobotLog .reset ();
155- return retval .get ();
156- }
157-
158- // overriding the run method to catch the control in case of failure, so that desired runOnFailureKeyword
159- // can be executed in controlled manner.
160- @ Override
161- public Object runKeyword (String keywordName , List args ) {
162- // TODO: Check if this is ever called anymore
163- RobotLog .info ("runKeyword called with args ONLY" );
164-
165- List finalArgs ;
166- // JavalibCore changes arguments of Call Method keywords to Strings after this check, so they need to handle their own objectMapping
167- if (!(keywordName .equals ("callObjectMethod" ) || keywordName .equals ("callObjectMethodInFxApplicationThread" ))) {
168- finalArgs = HelperFunctions .useMappedObjects (args );
169- } else {
170- finalArgs = args ;
171- }
172-
173- AtomicReference <Object > retval = new AtomicReference <>();
174- AtomicReference <RuntimeException > retExcep = new AtomicReference <>();
175-
176- try {
177- RobotLog .ignoreDuplicates ();
178- // timeout + 500 ms so that underlying timeout has a chance to expire first
179- waitFor (getWaitUntilTimeout (TimeUnit .MILLISECONDS ) + 500 , TimeUnit .MILLISECONDS , () -> {
180211
181- try {
182- retval .set (super .runKeyword (keywordName , finalArgs ));
183- return true ;
184-
185- } catch (JavaFXLibraryTimeoutException jfxte ) {
186- // timeout already expired, catch exception and jump out
187- retExcep .set (jfxte );
188- throw jfxte ;
189-
190- } catch (RuntimeException e ) {
191- // catch exception and continue trying
192- retExcep .set (e );
193- return false ;
194- }
195- });
196- } catch (TimeoutException te ) {
212+ // in failure take screenshot and handle exception
213+ if (retExcep .get ()!=null ) {
197214 RobotLog .reset ();
198215 RuntimeException e = retExcep .get ();
199216 runOnFailure .runOnFailure ();
200-
201217 if (e .getCause () instanceof JavaFXLibraryFatalException ) {
202218 RobotLog .trace ("JavaFXLibrary: Caught JavaFXLibrary FATAL exception: \n " + Throwables .getStackTraceAsString (e ));
203219 throw e ;
204220 } else if (e .getCause () instanceof JavaFXLibraryNonFatalException ) {
205221 RobotLog .trace ("JavaFXLibrary: Caught JavaFXLibrary NON-FATAL exception: \n " + Throwables .getStackTraceAsString (e ));
206222 throw e ;
223+ } else if (e .getCause () instanceof TimeoutException ) {
224+ throw new JavaFXLibraryNonFatalException ("Library keyword timeout (" + getLibraryKeywordTimeout () + "s) for keyword: " + keywordName );
225+ } else if (e .getCause () instanceof IllegalArgumentException ) {
226+ RobotLog .trace ("JavaFXLibrary: Caught IllegalArgumentException: \n " + Throwables .getStackTraceAsString (e ));
227+ throw new JavaFXLibraryNonFatalException ("Illegal arguments for keyword '" + keywordName + "':\n " +
228+ " ARGS: " + Arrays .toString (args .toArray ()) + "\n " +
229+ " KWARGS: " + Arrays .toString (kwargs .entrySet ().toArray ()));
207230 } else {
208231 RobotLog .trace ("JavaFXLibrary: Caught JavaFXLibrary RUNTIME exception: \n " + Throwables .getStackTraceAsString (e ));
209232 throw e ;
210233 }
211- } catch (JavaFXLibraryTimeoutException jfxte ) {
212- RobotLog .reset ();
213- RobotLog .trace ("JavaFXLibrary: Caught JavaFXLibrary TIMEOUT exception: \n " + Throwables .getStackTraceAsString (jfxte ));
214- throw jfxte ;
215234 }
216235 RobotLog .reset ();
217236 return retval .get ();
0 commit comments