OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/web/public/test/earl_grey/web_view_matchers.h" | 5 #import "ios/web/public/test/earl_grey/web_view_matchers.h" |
6 | 6 |
7 #import <UIKit/UIKit.h> | 7 #import <UIKit/UIKit.h> |
8 #import <WebKit/WebKit.h> | 8 #import <WebKit/WebKit.h> |
9 | 9 |
10 #import "base/mac/bind_objc_block.h" | 10 #import "base/mac/bind_objc_block.h" |
11 #import "base/mac/scoped_nsobject.h" | |
12 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
13 #include "base/strings/sys_string_conversions.h" | 12 #include "base/strings/sys_string_conversions.h" |
14 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
15 #import "base/test/ios/wait_util.h" | 14 #import "base/test/ios/wait_util.h" |
16 #include "base/values.h" | 15 #include "base/values.h" |
17 #import "ios/testing/wait_util.h" | 16 #import "ios/testing/wait_util.h" |
18 #import "ios/web/interstitials/web_interstitial_impl.h" | 17 #import "ios/web/interstitials/web_interstitial_impl.h" |
19 #import "ios/web/public/test/earl_grey/js_test_util.h" | 18 #import "ios/web/public/test/earl_grey/js_test_util.h" |
20 #import "ios/web/public/test/web_view_interaction_test_util.h" | 19 #import "ios/web/public/test/web_view_interaction_test_util.h" |
21 #import "net/base/mac/url_conversions.h" | 20 #import "net/base/mac/url_conversions.h" |
22 | 21 |
22 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
23 #error "This file requires ARC support." | |
24 #endif | |
25 | |
23 using testing::kWaitForDownloadTimeout; | 26 using testing::kWaitForDownloadTimeout; |
24 using testing::WaitUntilConditionOrTimeout; | 27 using testing::WaitUntilConditionOrTimeout; |
25 | 28 |
26 // A helper delegate class that allows downloading responses with invalid | 29 // A helper delegate class that allows downloading responses with invalid |
27 // SSL certs. | 30 // SSL certs. |
28 @interface TestURLSessionDelegate : NSObject<NSURLSessionDelegate> | 31 @interface TestURLSessionDelegate : NSObject<NSURLSessionDelegate> |
29 @end | 32 @end |
30 | 33 |
31 @implementation TestURLSessionDelegate | 34 @implementation TestURLSessionDelegate |
32 | 35 |
(...skipping 19 matching lines...) Expand all Loading... | |
52 }; | 55 }; |
53 | 56 |
54 // Script that returns document.body as a string. | 57 // Script that returns document.body as a string. |
55 char kGetDocumentBodyJavaScript[] = | 58 char kGetDocumentBodyJavaScript[] = |
56 "document.body ? document.body.textContent : null"; | 59 "document.body ? document.body.textContent : null"; |
57 // Script that tests presence of css selector. | 60 // Script that tests presence of css selector. |
58 char kTestCssSelectorJavaScriptTemplate[] = "!!document.querySelector(\"%s\");"; | 61 char kTestCssSelectorJavaScriptTemplate[] = "!!document.querySelector(\"%s\");"; |
59 | 62 |
60 // Fetches the image from |image_url|. | 63 // Fetches the image from |image_url|. |
61 UIImage* LoadImage(const GURL& image_url) { | 64 UIImage* LoadImage(const GURL& image_url) { |
62 __block base::scoped_nsobject<UIImage> image; | 65 __block UIImage* image; |
63 __block base::scoped_nsobject<NSError> error; | 66 __block NSError* error; |
64 TestURLSessionDelegate* session_delegate = | 67 TestURLSessionDelegate* session_delegate = |
65 [[TestURLSessionDelegate alloc] init]; | 68 [[TestURLSessionDelegate alloc] init]; |
66 NSURLSessionConfiguration* session_config = | 69 NSURLSessionConfiguration* session_config = |
67 [NSURLSessionConfiguration defaultSessionConfiguration]; | 70 [NSURLSessionConfiguration defaultSessionConfiguration]; |
68 NSURLSession* session = | 71 NSURLSession* session = |
69 [NSURLSession sessionWithConfiguration:session_config | 72 [NSURLSession sessionWithConfiguration:session_config |
70 delegate:session_delegate | 73 delegate:session_delegate |
71 delegateQueue:nil]; | 74 delegateQueue:nil]; |
72 id completion_handler = ^(NSData* data, NSURLResponse*, NSError* task_error) { | 75 id completion_handler = ^(NSData* data, NSURLResponse*, NSError* task_error) { |
73 if (task_error) { | 76 if (task_error) { |
Eugene But (OOO till 7-30)
2017/05/16 22:39:37
Do we even need this if-else? Should we simply ass
baxley
2017/06/02 15:39:38
Done.
| |
74 error.reset([task_error retain]); | 77 error = task_error; |
75 } else { | 78 } else { |
76 image.reset([[UIImage alloc] initWithData:data]); | 79 image = [[UIImage alloc] initWithData:data]; |
77 } | 80 } |
78 [session_delegate autorelease]; | |
79 }; | 81 }; |
80 | 82 |
81 NSURLSessionDataTask* task = | 83 NSURLSessionDataTask* task = |
82 [session dataTaskWithURL:net::NSURLWithGURL(image_url) | 84 [session dataTaskWithURL:net::NSURLWithGURL(image_url) |
83 completionHandler:completion_handler]; | 85 completionHandler:completion_handler]; |
84 [task resume]; | 86 [task resume]; |
85 | 87 |
86 bool image_loaded = WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{ | 88 bool image_loaded = WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{ |
87 return image || error; | 89 return image || error; |
88 }); | 90 }); |
89 GREYAssert(image_loaded, @"Failed to download image"); | 91 GREYAssert(image_loaded, @"Failed to download image"); |
90 | 92 |
91 return [[image retain] autorelease]; | 93 return image; |
92 } | 94 } |
93 | 95 |
94 // Helper function for matching web views containing or not containing |text|, | 96 // Helper function for matching web views containing or not containing |text|, |
95 // depending on the value of |should_contain_text|. | 97 // depending on the value of |should_contain_text|. |
96 id<GREYMatcher> WebViewWithText(std::string text, | 98 id<GREYMatcher> WebViewWithText(std::string text, |
97 web::WebState* web_state, | 99 web::WebState* web_state, |
98 bool should_contain_text) { | 100 bool should_contain_text) { |
99 MatchesBlock matches = ^BOOL(WKWebView*) { | 101 MatchesBlock matches = ^BOOL(WKWebView*) { |
100 return WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, ^{ | 102 return WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, ^{ |
101 std::unique_ptr<base::Value> value = | 103 std::unique_ptr<base::Value> value = |
102 web::test::ExecuteJavaScript(web_state, kGetDocumentBodyJavaScript); | 104 web::test::ExecuteJavaScript(web_state, kGetDocumentBodyJavaScript); |
103 std::string body; | 105 std::string body; |
104 if (value && value->GetAsString(&body)) { | 106 if (value && value->GetAsString(&body)) { |
105 BOOL contains_text = body.find(text) != std::string::npos; | 107 BOOL contains_text = body.find(text) != std::string::npos; |
106 return contains_text == should_contain_text; | 108 return contains_text == should_contain_text; |
107 } | 109 } |
108 return false; | 110 return false; |
109 }); | 111 }); |
110 }; | 112 }; |
111 | 113 |
112 DescribeToBlock describe = ^(id<GREYDescription> description) { | 114 DescribeToBlock describe = ^(id<GREYDescription> description) { |
113 [description appendText:should_contain_text ? @"web view containing " | 115 [description appendText:should_contain_text ? @"web view containing " |
114 : @"web view not containing "]; | 116 : @"web view not containing "]; |
115 [description appendText:base::SysUTF8ToNSString(text)]; | 117 [description appendText:base::SysUTF8ToNSString(text)]; |
116 }; | 118 }; |
117 | 119 |
118 return grey_allOf(WebViewInWebState(web_state), | 120 return grey_allOf( |
119 [[[GREYElementMatcherBlock alloc] | 121 WebViewInWebState(web_state), |
120 initWithMatchesBlock:matches | 122 [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches |
121 descriptionBlock:describe] autorelease], | 123 descriptionBlock:describe], |
122 nil); | 124 nil); |
123 } | 125 } |
124 | 126 |
125 // Matcher for WKWebView containing loaded or blocked image with |image_id|. | 127 // Matcher for WKWebView containing loaded or blocked image with |image_id|. |
126 // Pass IMAGE_STATE_LOADED |image_state| to match fully loaded image and | 128 // Pass IMAGE_STATE_LOADED |image_state| to match fully loaded image and |
127 // IMAGE_STATE_BLOCKED to match fully blocked image. | 129 // IMAGE_STATE_BLOCKED to match fully blocked image. |
128 id<GREYMatcher> WebViewContainingImage(std::string image_id, | 130 id<GREYMatcher> WebViewContainingImage(std::string image_id, |
129 web::WebState* web_state, | 131 web::WebState* web_state, |
130 ImageState image_state) { | 132 ImageState image_state) { |
131 std::string get_url_script = | 133 std::string get_url_script = |
132 base::StringPrintf("document.getElementById('%s').src", image_id.c_str()); | 134 base::StringPrintf("document.getElementById('%s').src", image_id.c_str()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
184 [description appendText:@"web view blocked resource with id "]; | 186 [description appendText:@"web view blocked resource with id "]; |
185 break; | 187 break; |
186 case IMAGE_STATE_LOADED: | 188 case IMAGE_STATE_LOADED: |
187 [description appendText:@"web view loaded resource with id "]; | 189 [description appendText:@"web view loaded resource with id "]; |
188 break; | 190 break; |
189 } | 191 } |
190 | 192 |
191 [description appendText:base::SysUTF8ToNSString(image_id)]; | 193 [description appendText:base::SysUTF8ToNSString(image_id)]; |
192 }; | 194 }; |
193 | 195 |
194 return grey_allOf(WebViewInWebState(web_state), | 196 return grey_allOf( |
195 [[[GREYElementMatcherBlock alloc] | 197 WebViewInWebState(web_state), |
196 initWithMatchesBlock:matches | 198 [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches |
197 descriptionBlock:describe] autorelease], | 199 descriptionBlock:describe], |
198 nil); | 200 nil); |
199 } | 201 } |
200 | 202 |
201 } // namespace | 203 } // namespace |
202 | 204 |
203 namespace web { | 205 namespace web { |
204 | 206 |
205 id<GREYMatcher> WebViewInWebState(WebState* web_state) { | 207 id<GREYMatcher> WebViewInWebState(WebState* web_state) { |
206 MatchesBlock matches = ^BOOL(UIView* view) { | 208 MatchesBlock matches = ^BOOL(UIView* view) { |
207 return [view isKindOfClass:[WKWebView class]] && | 209 return [view isKindOfClass:[WKWebView class]] && |
208 [view isDescendantOfView:web_state->GetView()]; | 210 [view isDescendantOfView:web_state->GetView()]; |
209 }; | 211 }; |
210 | 212 |
211 DescribeToBlock describe = ^(id<GREYDescription> description) { | 213 DescribeToBlock describe = ^(id<GREYDescription> description) { |
212 [description appendText:@"web view in web state"]; | 214 [description appendText:@"web view in web state"]; |
213 }; | 215 }; |
214 | 216 |
215 return [[[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches | 217 return [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches |
216 descriptionBlock:describe] | 218 descriptionBlock:describe]; |
217 autorelease]; | |
218 } | 219 } |
219 | 220 |
220 id<GREYMatcher> WebViewContainingText(std::string text, WebState* web_state) { | 221 id<GREYMatcher> WebViewContainingText(std::string text, WebState* web_state) { |
221 return WebViewWithText(text, web_state, true); | 222 return WebViewWithText(text, web_state, true); |
222 } | 223 } |
223 | 224 |
224 id<GREYMatcher> WebViewNotContainingText(std::string text, | 225 id<GREYMatcher> WebViewNotContainingText(std::string text, |
225 WebState* web_state) { | 226 WebState* web_state) { |
226 return WebViewWithText(text, web_state, false); | 227 return WebViewWithText(text, web_state, false); |
227 } | 228 } |
(...skipping 21 matching lines...) Expand all Loading... | |
249 } | 250 } |
250 return did_succeed; | 251 return did_succeed; |
251 }); | 252 }); |
252 }; | 253 }; |
253 | 254 |
254 DescribeToBlock describe = ^(id<GREYDescription> description) { | 255 DescribeToBlock describe = ^(id<GREYDescription> description) { |
255 [description appendText:@"web view selector "]; | 256 [description appendText:@"web view selector "]; |
256 [description appendText:base::SysUTF8ToNSString(selector)]; | 257 [description appendText:base::SysUTF8ToNSString(selector)]; |
257 }; | 258 }; |
258 | 259 |
259 return grey_allOf(WebViewInWebState(web_state), | 260 return grey_allOf( |
260 [[[GREYElementMatcherBlock alloc] | 261 WebViewInWebState(web_state), |
261 initWithMatchesBlock:matches | 262 [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches |
262 descriptionBlock:describe] autorelease], | 263 descriptionBlock:describe], |
263 nil); | 264 nil); |
264 } | 265 } |
265 | 266 |
266 id<GREYMatcher> WebViewScrollView(WebState* web_state) { | 267 id<GREYMatcher> WebViewScrollView(WebState* web_state) { |
267 MatchesBlock matches = ^BOOL(UIView* view) { | 268 MatchesBlock matches = ^BOOL(UIView* view) { |
268 return [view isKindOfClass:[UIScrollView class]] && | 269 return [view isKindOfClass:[UIScrollView class]] && |
269 [view.superview isKindOfClass:[WKWebView class]] && | 270 [view.superview isKindOfClass:[WKWebView class]] && |
270 [view isDescendantOfView:web_state->GetView()]; | 271 [view isDescendantOfView:web_state->GetView()]; |
271 }; | 272 }; |
272 | 273 |
273 DescribeToBlock describe = ^(id<GREYDescription> description) { | 274 DescribeToBlock describe = ^(id<GREYDescription> description) { |
274 [description appendText:@"web view scroll view"]; | 275 [description appendText:@"web view scroll view"]; |
275 }; | 276 }; |
276 | 277 |
277 return [[[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches | 278 return [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches |
278 descriptionBlock:describe] | 279 descriptionBlock:describe]; |
279 autorelease]; | |
280 } | 280 } |
281 | 281 |
282 id<GREYMatcher> Interstitial(WebState* web_state) { | 282 id<GREYMatcher> Interstitial(WebState* web_state) { |
283 MatchesBlock matches = ^BOOL(WKWebView* view) { | 283 MatchesBlock matches = ^BOOL(WKWebView* view) { |
284 web::WebInterstitialImpl* interstitial = | 284 web::WebInterstitialImpl* interstitial = |
285 static_cast<web::WebInterstitialImpl*>(web_state->GetWebInterstitial()); | 285 static_cast<web::WebInterstitialImpl*>(web_state->GetWebInterstitial()); |
286 return interstitial && | 286 return interstitial && |
287 [view isDescendantOfView:interstitial->GetContentView()]; | 287 [view isDescendantOfView:interstitial->GetContentView()]; |
288 }; | 288 }; |
289 | 289 |
290 DescribeToBlock describe = ^(id<GREYDescription> description) { | 290 DescribeToBlock describe = ^(id<GREYDescription> description) { |
291 [description appendText:@"interstitial displayed"]; | 291 [description appendText:@"interstitial displayed"]; |
292 }; | 292 }; |
293 | 293 |
294 return grey_allOf(WebViewInWebState(web_state), | 294 return grey_allOf( |
295 [[[GREYElementMatcherBlock alloc] | 295 WebViewInWebState(web_state), |
296 initWithMatchesBlock:matches | 296 [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches |
297 descriptionBlock:describe] autorelease], | 297 descriptionBlock:describe], |
298 nil); | 298 nil); |
299 } | 299 } |
300 | 300 |
301 id<GREYMatcher> InterstitialContainingText(NSString* text, | 301 id<GREYMatcher> InterstitialContainingText(NSString* text, |
302 WebState* web_state) { | 302 WebState* web_state) { |
303 MatchesBlock matches = ^BOOL(WKWebView* view) { | 303 MatchesBlock matches = ^BOOL(WKWebView* view) { |
304 return WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, ^{ | 304 return WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, ^{ |
305 NSString* script = base::SysUTF8ToNSString(kGetDocumentBodyJavaScript); | 305 NSString* script = base::SysUTF8ToNSString(kGetDocumentBodyJavaScript); |
306 id body = ExecuteScriptOnInterstitial(web_state, script); | 306 id body = ExecuteScriptOnInterstitial(web_state, script); |
307 return [body containsString:text] ? true : false; | 307 return [body containsString:text] ? true : false; |
308 }); | 308 }); |
309 }; | 309 }; |
310 | 310 |
311 DescribeToBlock describe = ^(id<GREYDescription> description) { | 311 DescribeToBlock describe = ^(id<GREYDescription> description) { |
312 [description appendText:@"interstitial containing "]; | 312 [description appendText:@"interstitial containing "]; |
313 [description appendText:text]; | 313 [description appendText:text]; |
314 }; | 314 }; |
315 | 315 |
316 return grey_allOf(Interstitial(web_state), | 316 return grey_allOf( |
317 [[[GREYElementMatcherBlock alloc] | 317 Interstitial(web_state), |
318 initWithMatchesBlock:matches | 318 [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches |
319 descriptionBlock:describe] autorelease], | 319 descriptionBlock:describe], |
320 nil); | 320 nil); |
321 } | 321 } |
322 | 322 |
323 } // namespace web | 323 } // namespace web |
OLD | NEW |