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 #include "base/mac/bind_objc_block.h" | 7 #include "base/mac/bind_objc_block.h" |
8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "base/test/ios/wait_util.h" | 10 #include "base/test/ios/wait_util.h" |
11 #include "ios/testing/earl_grey/wait_util.h" | 11 #include "ios/testing/wait_util.h" |
12 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h" | 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" | 13 #import "ios/web/web_state/crw_web_view_proxy_impl.h" |
14 #import "ios/web/web_state/ui/crw_web_controller.h" | 14 #import "ios/web/web_state/ui/crw_web_controller.h" |
15 #include "ios/web/web_state/web_state_impl.h" | 15 #include "ios/web/web_state/web_state_impl.h" |
16 | 16 |
17 using web::NavigationManager; | 17 using web::NavigationManager; |
18 | 18 |
19 namespace web { | 19 namespace web { |
20 namespace test { | 20 namespace test { |
21 | 21 |
22 enum ElementAction { | 22 enum ElementAction { |
23 ELEMENT_ACTION_CLICK, | 23 ELEMENT_ACTION_CLICK, |
24 ELEMENT_ACTION_FOCUS, | 24 ELEMENT_ACTION_FOCUS, |
25 ELEMENT_ACTION_SUBMIT | 25 ELEMENT_ACTION_SUBMIT |
26 }; | 26 }; |
27 | 27 |
28 std::unique_ptr<base::Value> ExecuteJavaScript(web::WebState* web_state, | 28 std::unique_ptr<base::Value> ExecuteJavaScript(web::WebState* web_state, |
29 const std::string& script) { | 29 const std::string& script) { |
30 __block std::unique_ptr<base::Value> result; | 30 __block std::unique_ptr<base::Value> result; |
31 __block bool did_finish = false; | 31 __block bool did_finish = false; |
32 web_state->ExecuteJavaScript(base::UTF8ToUTF16(script), | 32 web_state->ExecuteJavaScript(base::UTF8ToUTF16(script), |
33 base::BindBlock(^(const base::Value* value) { | 33 base::BindBlock(^(const base::Value* value) { |
34 if (value) | 34 if (value) |
35 result = value->CreateDeepCopy(); | 35 result = value->CreateDeepCopy(); |
36 did_finish = true; | 36 did_finish = true; |
37 })); | 37 })); |
38 | 38 |
39 testing::WaitUntilCondition(testing::kWaitForJSCompletionTimeout, ^{ | 39 bool completed = testing::WaitUntilConditionOrTimeout( |
40 return did_finish; | 40 testing::kWaitForJSCompletionTimeout, ^{ |
41 }); | 41 return did_finish; |
42 }); | |
43 if (!completed) { | |
44 return nullptr; | |
baxley
2016/10/25 00:00:53
The old implementation issued a GREYAssert, which
| |
45 } | |
42 | 46 |
43 // As result is marked __block, this return call does a copy and not a move | 47 // 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 | 48 // (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 | 49 // and not the stack). Since the "return std::move()" pattern is discouraged |
46 // use a local variable. | 50 // use a local variable. |
47 // | 51 // |
48 // Fixes the following compilation failure: | 52 // Fixes the following compilation failure: |
49 // ../web_view_matchers.mm:ll:cc: error: call to implicitly-deleted copy | 53 // ../web_view_matchers.mm:ll:cc: error: call to implicitly-deleted copy |
50 // constructor of 'std::unique_ptr<base::Value>' | 54 // constructor of 'std::unique_ptr<base::Value>' |
51 std::unique_ptr<base::Value> stack_result = std::move(result); | 55 std::unique_ptr<base::Value> stack_result = std::move(result); |
(...skipping 13 matching lines...) Expand all Loading... | |
65 " not found'};" | 69 " not found'};" |
66 " var rect = element.getBoundingClientRect();" | 70 " var rect = element.getBoundingClientRect();" |
67 " return {" | 71 " return {" |
68 " 'left': rect.left," | 72 " 'left': rect.left," |
69 " 'top': rect.top," | 73 " 'top': rect.top," |
70 " 'width': rect.right - rect.left," | 74 " 'width': rect.right - rect.left," |
71 " 'height': rect.bottom - rect.top," | 75 " 'height': rect.bottom - rect.top," |
72 " };" | 76 " };" |
73 "})();"; | 77 "})();"; |
74 | 78 |
75 base::DictionaryValue const* rect = nullptr; | 79 __block base::DictionaryValue const* rect = nullptr; |
76 bool found = false; | 80 |
77 NSDate* deadline = | 81 bool found = testing::WaitUntilConditionOrTimeout( |
78 [NSDate dateWithTimeIntervalSinceNow:testing::kWaitForUIElementTimeout]; | 82 testing::kWaitForUIElementTimeout, ^bool() { |
79 while (([[NSDate date] compare:deadline] != NSOrderedDescending) && !found) { | 83 std::unique_ptr<base::Value> value = |
80 std::unique_ptr<base::Value> value = | 84 ExecuteJavaScript(web_state, kGetBoundsScript); |
81 ExecuteJavaScript(web_state, kGetBoundsScript); | 85 base::DictionaryValue* dictionary = nullptr; |
82 base::DictionaryValue* dictionary = nullptr; | 86 if (value && value->GetAsDictionary(&dictionary)) { |
83 if (value && value->GetAsDictionary(&dictionary)) { | 87 std::string error; |
84 std::string error; | 88 if (dictionary->GetString("error", &error)) { |
85 if (dictionary->GetString("error", &error)) { | 89 DLOG(ERROR) << "Error getting rect: " << error << ", retrying.."; |
86 DLOG(ERROR) << "Error getting rect: " << error << ", retrying.."; | 90 } else { |
87 } else { | 91 rect = dictionary->DeepCopy(); |
88 rect = dictionary->DeepCopy(); | 92 return true; |
89 found = true; | 93 } |
90 } | 94 } |
91 } | 95 return false; |
92 base::test::ios::SpinRunLoopWithMaxDelay( | 96 }); |
93 base::TimeDelta::FromSecondsD(testing::kSpinDelaySeconds)); | |
94 } | |
95 | 97 |
96 if (!found) | 98 if (!found) |
97 return CGRectNull; | 99 return CGRectNull; |
98 | 100 |
99 double left, top, width, height; | 101 double left, top, width, height; |
100 if (!(rect->GetDouble("left", &left) && rect->GetDouble("top", &top) && | 102 if (!(rect->GetDouble("left", &left) && rect->GetDouble("top", &top) && |
101 rect->GetDouble("width", &width) && | 103 rect->GetDouble("width", &width) && |
102 rect->GetDouble("height", &height))) { | 104 rect->GetDouble("height", &height))) { |
103 return CGRectNull; | 105 return CGRectNull; |
104 } | 106 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 "})();", | 140 "})();", |
139 element_id.c_str(), js_action]; | 141 element_id.c_str(), js_action]; |
140 __block bool did_complete = false; | 142 __block bool did_complete = false; |
141 __block bool element_found = false; | 143 __block bool element_found = false; |
142 [web_controller executeUserJavaScript:script | 144 [web_controller executeUserJavaScript:script |
143 completionHandler:^(id result, NSError*) { | 145 completionHandler:^(id result, NSError*) { |
144 did_complete = true; | 146 did_complete = true; |
145 element_found = [result boolValue]; | 147 element_found = [result boolValue]; |
146 }]; | 148 }]; |
147 | 149 |
148 testing::WaitUntilCondition(testing::kWaitForJSCompletionTimeout, ^{ | 150 testing::WaitUntilConditionOrTimeout(testing::kWaitForJSCompletionTimeout, ^{ |
149 return did_complete; | 151 return did_complete; |
150 }); | 152 }); |
151 | 153 |
152 return element_found; | 154 return element_found; |
153 } | 155 } |
154 | 156 |
155 bool TapWebViewElementWithId(web::WebState* web_state, | 157 bool TapWebViewElementWithId(web::WebState* web_state, |
156 const std::string& element_id) { | 158 const std::string& element_id) { |
157 return RunActionOnWebViewElementWithId(web_state, element_id, | 159 return RunActionOnWebViewElementWithId(web_state, element_id, |
158 ELEMENT_ACTION_CLICK); | 160 ELEMENT_ACTION_CLICK); |
159 } | 161 } |
160 | 162 |
161 bool FocusWebViewElementWithId(web::WebState* web_state, | 163 bool FocusWebViewElementWithId(web::WebState* web_state, |
162 const std::string& element_id) { | 164 const std::string& element_id) { |
163 return RunActionOnWebViewElementWithId(web_state, element_id, | 165 return RunActionOnWebViewElementWithId(web_state, element_id, |
164 ELEMENT_ACTION_FOCUS); | 166 ELEMENT_ACTION_FOCUS); |
165 } | 167 } |
166 | 168 |
167 bool SubmitWebViewFormWithId(web::WebState* web_state, | 169 bool SubmitWebViewFormWithId(web::WebState* web_state, |
168 const std::string& form_id) { | 170 const std::string& form_id) { |
169 return RunActionOnWebViewElementWithId(web_state, form_id, | 171 return RunActionOnWebViewElementWithId(web_state, form_id, |
170 ELEMENT_ACTION_SUBMIT); | 172 ELEMENT_ACTION_SUBMIT); |
171 } | 173 } |
172 | 174 |
173 } // namespace test | 175 } // namespace test |
174 } // namespace web | 176 } // namespace web |
OLD | NEW |