Chromium Code Reviews| Index: ios/web/public/test/web_view_interaction_test_util.mm |
| diff --git a/ios/web/public/test/web_view_interaction_test_util.mm b/ios/web/public/test/web_view_interaction_test_util.mm |
| index 0892593c062af9f446a3938cc0ca0e822540e89e..d67bee907f3daa6feb582d71053f9bd8158c2431 100644 |
| --- a/ios/web/public/test/web_view_interaction_test_util.mm |
| +++ b/ios/web/public/test/web_view_interaction_test_util.mm |
| @@ -4,9 +4,13 @@ |
| #import "ios/web/public/test/web_view_interaction_test_util.h" |
| -#import <Foundation/Foundation.h> |
| - |
| +#include "base/mac/bind_objc_block.h" |
| +#include "base/strings/stringprintf.h" |
| +#include "base/strings/utf_string_conversions.h" |
| +#include "base/test/ios/wait_util.h" |
| #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.
|
| +#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h" |
| +#import "ios/web/web_state/crw_web_view_proxy_impl.h" |
| #import "ios/web/web_state/ui/crw_web_controller.h" |
| #include "ios/web/web_state/web_state_impl.h" |
| @@ -21,6 +25,98 @@ enum ElementAction { |
| ELEMENT_ACTION_SUBMIT |
| }; |
| +std::unique_ptr<base::Value> ExecuteScript(web::WebState* web_state, |
| + const std::string& script) { |
| + __block std::unique_ptr<base::Value> result; |
| + __block bool did_finish = false; |
| + web_state->ExecuteJavaScript(base::UTF8ToUTF16(script), |
| + base::BindBlock(^(const base::Value* value) { |
| + if (value) |
| + result = value->CreateDeepCopy(); |
| + did_finish = true; |
| + })); |
| + |
| + testing::WaitUntilCondition(testing::kWaitForJSCompletionTimeout, ^{ |
| + return did_finish; |
| + }); |
| + |
| + // As result is marked __block, this return call does a copy and not a move |
| + // (marking the variable as __block mean it is allocated in the block object |
| + // and not the stack). Since the "return std::move()" pattern is discouraged |
| + // use a local variable. |
| + // |
| + // Fixes the following compilation failure: |
| + // ../web_view_matchers.mm:ll:cc: error: call to implicitly-deleted copy |
| + // constructor of 'std::unique_ptr<base::Value>' |
| + std::unique_ptr<base::Value> stack_result = std::move(result); |
| + return stack_result; |
| +} |
| + |
| +CGRect BoundingRectOfElementWithId(web::WebState* web_state, |
| + const std::string& element_id) { |
| + std::string kGetBoundsScript = |
| + "(function() {" |
| + " var element = document.getElementById('" + |
| + element_id + |
| + "');" |
| + " if (!element)" |
| + " return {'error': 'Element " + |
| + element_id + |
| + " not found'};" |
| + " var rect = element.getBoundingClientRect();" |
| + " var top = rect.top + document.body.scrollTop;" |
| + " var bottom = rect.bottom + document.body.scrollTop;" |
| + " var left = rect.left + document.body.scrollLeft;" |
| + " var right = rect.right + document.body.scrollLeft;" |
| + " return {" |
| + " 'left': left," |
| + " 'top': top," |
| + " 'width': right - left," |
| + " 'height': bottom - top," |
| + " 'document_width' : document.documentElement.scrollWidth," |
| + " 'document_height' : document.documentElement.scrollHeight," |
| + " };" |
| + "})();"; |
| + |
| + std::unique_ptr<base::Value> value; |
| + NSDate* deadline = |
| + [NSDate dateWithTimeIntervalSinceNow:testing::kWaitForUIElementTimeout]; |
| + while (([[NSDate date] compare:deadline] != NSOrderedDescending) && !value) { |
| + value = ExecuteScript(web_state, kGetBoundsScript); |
| + base::test::ios::SpinRunLoopWithMaxDelay( |
| + base::TimeDelta::FromSecondsD(testing::kSpinDelaySeconds)); |
| + } |
| + |
| + 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.
|
| + base::DictionaryValue const* dictionary = nullptr; |
| + bool marshalling_ok = value->GetAsDictionary(&dictionary); |
| + std::string error; |
| + // If there is in error, then that's not OK, so the GetString return value |
| + // is negated here. |
| + marshalling_ok = marshalling_ok && !dictionary->GetString("error", &error); |
| + if (!marshalling_ok) |
| + return bounds; |
| + |
| + double left, top, width, height, document_width, document_height; |
| + marshalling_ok = marshalling_ok && dictionary->GetDouble("left", &left) && |
| + dictionary->GetDouble("top", &top) && |
| + dictionary->GetDouble("width", &width) && |
| + dictionary->GetDouble("height", &height) && |
| + dictionary->GetDouble("document_width", &document_width) && |
| + dictionary->GetDouble("document_height", &document_height); |
| + |
| + if (!marshalling_ok) |
| + return bounds; |
| + |
| + CRWWebController* web_controller = |
| + static_cast<WebStateImpl*>(web_state)->GetWebController(); |
| + |
| + 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.
|
| + |
| + bounds = CGRectMake(left * scale, top * scale, width * scale, height * scale); |
| + return bounds; |
| +} |
| + |
| // Returns whether the Javascript action specified by |action| ran on |
| // |element_id| in the passed |web_state|. |
| bool RunActionOnWebViewElementWithId(web::WebState* web_state, |