|
16 | 16 |
|
17 | 17 | #import "Action/GREYActions.h" |
18 | 18 |
|
| 19 | +#import <WebKit/WebKit.h> |
| 20 | + |
19 | 21 | #import "Action/GREYAction.h" |
20 | 22 | #import "Action/GREYActionBlock.h" |
21 | 23 | #import "Action/GREYChangeStepperAction.h" |
|
48 | 50 |
|
49 | 51 | static Class gWebAccessibilityObjectWrapperClass; |
50 | 52 | static Class gAccessibilityTextFieldElementClass; |
| 53 | +// Timeout for JavaScript execution using WKWebView. |
| 54 | +static const CFTimeInterval kJavaScriptTimeoutSeconds = 60; |
51 | 55 |
|
52 | 56 | @implementation GREYActions |
53 | 57 |
|
@@ -292,22 +296,46 @@ + (void)initialize { |
292 | 296 | + (id<GREYAction>)actionForJavaScriptExecution:(NSString *)js |
293 | 297 | output:(__strong NSString **)outResult { |
294 | 298 | // TODO: JS Errors should be propagated up. |
295 | | - id<GREYMatcher> constraints = grey_allOf(grey_not(grey_systemAlertViewShown()), |
296 | | - grey_kindOfClass([UIWebView class]), |
297 | | - nil); |
| 299 | + id<GREYMatcher> constraints = |
| 300 | + grey_allOf(grey_not(grey_systemAlertViewShown()), |
| 301 | + grey_anyOf(grey_kindOfClass([UIWebView class]), |
| 302 | + grey_kindOfClass([WKWebView class]), nil), |
| 303 | + nil); |
| 304 | + BOOL (^performBlock)(id webView, __strong NSError **errorOrNil) = ^( |
| 305 | + id webView, __strong NSError **errorOrNil) { |
| 306 | + if ([webView isKindOfClass:[WKWebView class]]) { |
| 307 | + WKWebView *wkWebView = webView; |
| 308 | + __block NSString *resultString = nil; |
| 309 | + __block BOOL completionDone = NO; |
| 310 | + [wkWebView evaluateJavaScript:js |
| 311 | + completionHandler:^(id result, NSError *error) { |
| 312 | + resultString = [result description]; |
| 313 | + completionDone = YES; |
| 314 | + }]; |
| 315 | + NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:kJavaScriptTimeoutSeconds]; |
| 316 | + while (!completionDone && timeoutDate.timeIntervalSinceNow > 0) { |
| 317 | + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; |
| 318 | + } |
| 319 | + if (completionDone && outResult) { |
| 320 | + *outResult = resultString; |
| 321 | + } |
| 322 | + return completionDone; |
| 323 | + } else if ([webView isKindOfClass:[UIWebView class]]) { |
| 324 | + UIWebView *uiWebView = webView; |
| 325 | + if (outResult) { |
| 326 | + *outResult = [uiWebView stringByEvaluatingJavaScriptFromString:js]; |
| 327 | + } else { |
| 328 | + [uiWebView stringByEvaluatingJavaScriptFromString:js]; |
| 329 | + } |
| 330 | + // TODO: Delay should be removed once webview sync is stable. |
| 331 | + [[GREYUIThreadExecutor sharedInstance] drainForTime:0.5]; // Wait for actions to register. |
| 332 | + return YES; |
| 333 | + } |
| 334 | + return NO; |
| 335 | + }; |
298 | 336 | return [[GREYActionBlock alloc] initWithName:@"Execute JavaScript" |
299 | 337 | constraints:constraints |
300 | | - performBlock:^BOOL (UIWebView *webView, |
301 | | - __strong NSError **errorOrNil) { |
302 | | - if (outResult) { |
303 | | - *outResult = [webView stringByEvaluatingJavaScriptFromString:js]; |
304 | | - } else { |
305 | | - [webView stringByEvaluatingJavaScriptFromString:js]; |
306 | | - } |
307 | | - // TODO: Delay should be removed once webview sync is stable. |
308 | | - [[GREYUIThreadExecutor sharedInstance] drainForTime:0.5]; // Wait for actions to register. |
309 | | - return YES; |
310 | | - }]; |
| 338 | + performBlock:performBlock]; |
311 | 339 | } |
312 | 340 |
|
313 | 341 | + (id<GREYAction>)actionForSnapshot:(__strong UIImage **)outImage { |
|
0 commit comments