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/web_view_interaction_test_util.h" | 5 #import "ios/web/public/test/web_view_interaction_test_util.h" |
6 | 6 |
7 #import <Foundation/Foundation.h> | 7 #include "base/mac/bind_objc_block.h" |
8 | 8 #include "base/strings/stringprintf.h" |
9 #include "base/strings/utf_string_conversions.h" | |
10 #include "base/test/ios/wait_util.h" | |
9 #include "ios/testing/earl_grey/wait_util.h" | 11 #include "ios/testing/earl_grey/wait_util.h" |
baxley
2016/08/31 05:27:02
Just an FYI. I am working on a CL to remove this d
marq (ping after 24h)
2016/08/31 13:07:58
Acknowledged.
| |
12 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h" | |
13 #import "ios/web/web_state/crw_web_view_proxy_impl.h" | |
10 #import "ios/web/web_state/ui/crw_web_controller.h" | 14 #import "ios/web/web_state/ui/crw_web_controller.h" |
11 #include "ios/web/web_state/web_state_impl.h" | 15 #include "ios/web/web_state/web_state_impl.h" |
12 | 16 |
13 using web::NavigationManager; | 17 using web::NavigationManager; |
14 | 18 |
15 namespace web { | 19 namespace web { |
16 namespace test { | 20 namespace test { |
17 | 21 |
18 enum ElementAction { | 22 enum ElementAction { |
19 ELEMENT_ACTION_CLICK, | 23 ELEMENT_ACTION_CLICK, |
20 ELEMENT_ACTION_FOCUS, | 24 ELEMENT_ACTION_FOCUS, |
21 ELEMENT_ACTION_SUBMIT | 25 ELEMENT_ACTION_SUBMIT |
22 }; | 26 }; |
23 | 27 |
28 std::unique_ptr<base::Value> ExecuteScript(web::WebState* web_state, | |
29 const std::string& script) { | |
30 __block std::unique_ptr<base::Value> result; | |
31 __block bool did_finish = false; | |
32 web_state->ExecuteJavaScript(base::UTF8ToUTF16(script), | |
33 base::BindBlock(^(const base::Value* value) { | |
34 if (value) | |
35 result = value->CreateDeepCopy(); | |
36 did_finish = true; | |
37 })); | |
38 | |
39 testing::WaitUntilCondition(testing::kWaitForJSCompletionTimeout, ^{ | |
40 return did_finish; | |
41 }); | |
42 | |
43 // As result is marked __block, this return call does a copy and not a move | |
44 // (marking the variable as __block mean it is allocated in the block object | |
45 // and not the stack). Since the "return std::move()" pattern is discouraged | |
46 // use a local variable. | |
47 // | |
48 // Fixes the following compilation failure: | |
49 // ../web_view_matchers.mm:ll:cc: error: call to implicitly-deleted copy | |
50 // constructor of 'std::unique_ptr<base::Value>' | |
51 std::unique_ptr<base::Value> stack_result = std::move(result); | |
52 return stack_result; | |
53 } | |
54 | |
55 CGRect BoundingRectOfElementWithId(web::WebState* web_state, | |
56 const std::string& element_id) { | |
57 std::string kGetBoundsScript = | |
58 "(function() {" | |
59 " var element = document.getElementById('" + | |
60 element_id + | |
61 "');" | |
62 " if (!element)" | |
63 " return {'error': 'Element " + | |
64 element_id + | |
65 " not found'};" | |
66 " var rect = element.getBoundingClientRect();" | |
67 " var top = rect.top + document.body.scrollTop;" | |
68 " var bottom = rect.bottom + document.body.scrollTop;" | |
69 " var left = rect.left + document.body.scrollLeft;" | |
70 " var right = rect.right + document.body.scrollLeft;" | |
71 " return {" | |
72 " 'left': left," | |
73 " 'top': top," | |
74 " 'width': right - left," | |
75 " 'height': bottom - top," | |
76 " 'document_width' : document.documentElement.scrollWidth," | |
77 " 'document_height' : document.documentElement.scrollHeight," | |
78 " };" | |
79 "})();"; | |
80 | |
81 std::unique_ptr<base::Value> value; | |
82 NSDate* deadline = | |
83 [NSDate dateWithTimeIntervalSinceNow:testing::kWaitForUIElementTimeout]; | |
84 while (([[NSDate date] compare:deadline] != NSOrderedDescending) && !value) { | |
85 value = ExecuteScript(web_state, kGetBoundsScript); | |
86 base::test::ios::SpinRunLoopWithMaxDelay( | |
87 base::TimeDelta::FromSecondsD(testing::kSpinDelaySeconds)); | |
88 } | |
89 | |
90 CGRect bounds = CGRectZero; | |
Eugene But (OOO till 7-30)
2016/08/30 18:11:05
NIT: Do you need this variable? It's lifetime quit
marq (ping after 24h)
2016/08/31 13:07:58
Good catch, done.
| |
91 base::DictionaryValue const* dictionary = nullptr; | |
92 bool marshalling_ok = value->GetAsDictionary(&dictionary); | |
93 std::string error; | |
94 // If there is in error, then that's not OK, so the GetString return value | |
95 // is negated here. | |
96 marshalling_ok = marshalling_ok && !dictionary->GetString("error", &error); | |
97 if (!marshalling_ok) | |
98 return bounds; | |
99 | |
100 double left, top, width, height, document_width, document_height; | |
101 marshalling_ok = marshalling_ok && dictionary->GetDouble("left", &left) && | |
102 dictionary->GetDouble("top", &top) && | |
103 dictionary->GetDouble("width", &width) && | |
104 dictionary->GetDouble("height", &height) && | |
105 dictionary->GetDouble("document_width", &document_width) && | |
106 dictionary->GetDouble("document_height", &document_height); | |
107 | |
108 if (!marshalling_ok) | |
109 return bounds; | |
110 | |
111 CRWWebController* web_controller = | |
112 static_cast<WebStateImpl*>(web_state)->GetWebController(); | |
113 | |
114 CGFloat scale = [[web_controller.webViewProxy scrollViewProxy] zoomScale]; | |
Eugene But (OOO till 7-30)
2016/08/30 18:11:05
No need to use web controller here:
web_state->Ge
marq (ping after 24h)
2016/08/31 13:07:58
Done.
| |
115 | |
116 bounds = CGRectMake(left * scale, top * scale, width * scale, height * scale); | |
117 return bounds; | |
118 } | |
119 | |
24 // Returns whether the Javascript action specified by |action| ran on | 120 // Returns whether the Javascript action specified by |action| ran on |
25 // |element_id| in the passed |web_state|. | 121 // |element_id| in the passed |web_state|. |
26 bool RunActionOnWebViewElementWithId(web::WebState* web_state, | 122 bool RunActionOnWebViewElementWithId(web::WebState* web_state, |
27 const std::string& element_id, | 123 const std::string& element_id, |
28 ElementAction action) { | 124 ElementAction action) { |
29 CRWWebController* web_controller = | 125 CRWWebController* web_controller = |
30 static_cast<WebStateImpl*>(web_state)->GetWebController(); | 126 static_cast<WebStateImpl*>(web_state)->GetWebController(); |
31 const char* js_action = nullptr; | 127 const char* js_action = nullptr; |
32 switch (action) { | 128 switch (action) { |
33 case ELEMENT_ACTION_CLICK: | 129 case ELEMENT_ACTION_CLICK: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 } | 174 } |
79 | 175 |
80 bool SubmitWebViewFormWithId(web::WebState* web_state, | 176 bool SubmitWebViewFormWithId(web::WebState* web_state, |
81 const std::string& form_id) { | 177 const std::string& form_id) { |
82 return RunActionOnWebViewElementWithId(web_state, form_id, | 178 return RunActionOnWebViewElementWithId(web_state, form_id, |
83 ELEMENT_ACTION_SUBMIT); | 179 ELEMENT_ACTION_SUBMIT); |
84 } | 180 } |
85 | 181 |
86 } // namespace test | 182 } // namespace test |
87 } // namespace web | 183 } // namespace web |
OLD | NEW |