Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: chrome/test/webdriver/session.cc

Issue 7465053: In chromedriver, check if an element is clickable before clicking. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 #include "chrome/test/webdriver/session.h" 5 #include "chrome/test/webdriver/session.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 705
706 Error* Session::GetElementLocationInView( 706 Error* Session::GetElementLocationInView(
707 const WebElementId& element, 707 const WebElementId& element,
708 gfx::Point* location) { 708 gfx::Point* location) {
709 gfx::Size size; 709 gfx::Size size;
710 Error* error = GetElementSize(current_target_, element, &size); 710 Error* error = GetElementSize(current_target_, element, &size);
711 if (error) 711 if (error)
712 return error; 712 return error;
713 return GetElementRegionInView( 713 return GetElementRegionInView(
714 element, gfx::Rect(gfx::Point(0, 0), size), 714 element, gfx::Rect(gfx::Point(0, 0), size),
715 false /* center */, location); 715 false /* center */, false /* verify_clickable_at_middle */, location);
716 } 716 }
717 717
718 Error* Session::GetElementRegionInView( 718 Error* Session::GetElementRegionInView(
719 const WebElementId& element, 719 const WebElementId& element,
720 const gfx::Rect& region, 720 const gfx::Rect& region,
721 bool center, 721 bool center,
722 bool verify_clickable_at_middle,
722 gfx::Point* location) { 723 gfx::Point* location) {
723 CHECK(element.is_valid()); 724 CHECK(element.is_valid());
724 725
725 gfx::Point region_offset = region.origin(); 726 gfx::Point region_offset = region.origin();
726 gfx::Size region_size = region.size(); 727 gfx::Size region_size = region.size();
727 Error* error = GetElementRegionInViewHelper( 728 Error* error = GetElementRegionInViewHelper(
728 current_target_, element, region, center, &region_offset); 729 current_target_, element, region, center, verify_clickable_at_middle,
730 &region_offset);
729 if (error) 731 if (error)
730 return error; 732 return error;
731 733
732 for (FramePath frame_path = current_target_.frame_path; 734 for (FramePath frame_path = current_target_.frame_path;
733 frame_path.IsSubframe(); 735 frame_path.IsSubframe();
734 frame_path = frame_path.Parent()) { 736 frame_path = frame_path.Parent()) {
735 // Find the frame element for the current frame path. 737 // Find the frame element for the current frame path.
736 FrameId frame_id(current_target_.window_id, frame_path.Parent()); 738 FrameId frame_id(current_target_.window_id, frame_path.Parent());
737 WebElementId frame_element; 739 WebElementId frame_element;
738 error = FindElement( 740 error = FindElement(
(...skipping 10 matching lines...) Expand all
749 // Modify |region_offset| by the frame's border. 751 // Modify |region_offset| by the frame's border.
750 int border_left, border_top; 752 int border_left, border_top;
751 error = GetElementBorder( 753 error = GetElementBorder(
752 frame_id, frame_element, &border_left, &border_top); 754 frame_id, frame_element, &border_left, &border_top);
753 if (error) 755 if (error)
754 return error; 756 return error;
755 region_offset.Offset(border_left, border_top); 757 region_offset.Offset(border_left, border_top);
756 758
757 error = GetElementRegionInViewHelper( 759 error = GetElementRegionInViewHelper(
758 frame_id, frame_element, gfx::Rect(region_offset, region_size), 760 frame_id, frame_element, gfx::Rect(region_offset, region_size),
759 center, &region_offset); 761 center, verify_clickable_at_middle, &region_offset);
760 if (error) 762 if (error)
761 return error; 763 return error;
762 } 764 }
763 *location = region_offset; 765 *location = region_offset;
764 return NULL; 766 return NULL;
765 } 767 }
766 768
767 Error* Session::GetElementSize(const FrameId& frame_id, 769 Error* Session::GetElementSize(const FrameId& frame_id,
768 const WebElementId& element, 770 const WebElementId& element,
769 gfx::Size* size) { 771 gfx::Size* size) {
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 if (error) 958 if (error)
957 return error; 959 return error;
958 if (!is_displayed) 960 if (!is_displayed)
959 return new Error(kElementNotVisible, "Element must be displayed to click"); 961 return new Error(kElementNotVisible, "Element must be displayed to click");
960 962
961 gfx::Rect rect; 963 gfx::Rect rect;
962 error = GetElementFirstClientRect(current_target_, element, &rect); 964 error = GetElementFirstClientRect(current_target_, element, &rect);
963 if (error) 965 if (error)
964 return error; 966 return error;
965 967
966 error = GetElementRegionInView(element, rect, true /* center */, location); 968 error = GetElementRegionInView(
969 element, rect, true /* center */, true /* verify_clickable_at_middle */,
970 location);
967 if (error) 971 if (error)
968 return error; 972 return error;
969 location->Offset(rect.width() / 2, rect.height() / 2); 973 location->Offset(rect.width() / 2, rect.height() / 2);
970 return NULL; 974 return NULL;
971 } 975 }
972 976
973 Error* Session::GetAttribute(const WebElementId& element, 977 Error* Session::GetAttribute(const WebElementId& element,
974 const std::string& key, Value** value) { 978 const std::string& key, Value** value) {
975 std::string script = base::StringPrintf( 979 std::string script = base::StringPrintf(
976 "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE); 980 "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE);
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 elements->push_back(element); 1308 elements->push_back(element);
1305 } else { 1309 } else {
1306 return new Error( 1310 return new Error(
1307 kUnknownError, 1311 kUnknownError,
1308 "Find element script returned unsupported type: " + 1312 "Find element script returned unsupported type: " +
1309 JsonStringify(value.get())); 1313 JsonStringify(value.get()));
1310 } 1314 }
1311 return NULL; 1315 return NULL;
1312 } 1316 }
1313 1317
1318 Error* Session::VerifyElementIsClickable(
1319 const FrameId& frame_id,
1320 const WebElementId& element,
1321 const gfx::Point& location) {
1322 std::string jscript = base::StringPrintf(
1323 "return (%s).apply(null, arguments);", atoms::IS_ELEMENT_CLICKABLE);
1324 ListValue jscript_args;
1325 jscript_args.Append(element.ToValue());
1326 DictionaryValue* location_dict = new DictionaryValue();
1327 location_dict->SetInteger("x", location.x());
1328 location_dict->SetInteger("y", location.y());
1329 jscript_args.Append(location_dict);
1330 Value* unscoped_value = NULL;
1331 Error* error = ExecuteScript(frame_id, jscript, &jscript_args,
1332 &unscoped_value);
1333 if (error)
1334 return error;
1335
1336 scoped_ptr<Value> value(unscoped_value);
1337 if (!value->IsType(Value::TYPE_DICTIONARY)) {
1338 return new Error(
1339 kUnknownError,
1340 "isElementClickable atom returned non-dictionary type: " +
1341 JsonStringify(value.get()));
1342 }
1343 DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
1344 bool clickable = false;
1345 if (!dict->GetBoolean("clickable", &clickable)) {
1346 return new Error(
1347 kUnknownError,
1348 "isElementClickable atom returned bad invalid dictionary: " +
1349 JsonStringify(dict));
1350 }
1351 std::string message;
1352 dict->GetString("message", &message);
1353 if (!clickable) {
1354 if (message.empty())
1355 message = "element is not clickable";
1356 return new Error(kUnknownError, message);
1357 }
1358 if (message.length()) {
1359 LOG(WARNING) << message;
1360 }
1361 return NULL;
1362 }
1363
1314 Error* Session::GetElementRegionInViewHelper( 1364 Error* Session::GetElementRegionInViewHelper(
1315 const FrameId& frame_id, 1365 const FrameId& frame_id,
1316 const WebElementId& element, 1366 const WebElementId& element,
1317 const gfx::Rect& region, 1367 const gfx::Rect& region,
1318 bool center, 1368 bool center,
1369 bool verify_clickable_at_middle,
1319 gfx::Point* location) { 1370 gfx::Point* location) {
1320 std::string jscript = base::StringPrintf( 1371 std::string jscript = base::StringPrintf(
1321 "return (%s).apply(null, arguments);", atoms::GET_LOCATION_IN_VIEW); 1372 "return (%s).apply(null, arguments);", atoms::GET_LOCATION_IN_VIEW);
1322 ListValue jscript_args; 1373 ListValue jscript_args;
1323 jscript_args.Append(element.ToValue()); 1374 jscript_args.Append(element.ToValue());
1324 jscript_args.Append(Value::CreateBooleanValue(center)); 1375 jscript_args.Append(Value::CreateBooleanValue(center));
1325 DictionaryValue* elem_offset_dict = new DictionaryValue(); 1376 DictionaryValue* elem_offset_dict = new DictionaryValue();
1326 elem_offset_dict->SetInteger("left", region.x()); 1377 elem_offset_dict->SetInteger("left", region.x());
1327 elem_offset_dict->SetInteger("top", region.y()); 1378 elem_offset_dict->SetInteger("top", region.y());
1328 elem_offset_dict->SetInteger("width", region.width()); 1379 elem_offset_dict->SetInteger("width", region.width());
1329 elem_offset_dict->SetInteger("height", region.height()); 1380 elem_offset_dict->SetInteger("height", region.height());
1330 jscript_args.Append(elem_offset_dict); 1381 jscript_args.Append(elem_offset_dict);
1331 Value* unscoped_value = NULL; 1382 Value* unscoped_value = NULL;
1332 Error* error = ExecuteScript(frame_id, jscript, &jscript_args, 1383 Error* error = ExecuteScript(frame_id, jscript, &jscript_args,
1333 &unscoped_value); 1384 &unscoped_value);
1334 scoped_ptr<Value> value(unscoped_value); 1385 scoped_ptr<Value> value(unscoped_value);
1335 if (error) 1386 if (error)
1336 return error; 1387 return error;
1388
1337 if (!value->IsType(Value::TYPE_DICTIONARY)) { 1389 if (!value->IsType(Value::TYPE_DICTIONARY)) {
1338 return new Error( 1390 return new Error(
1339 kUnknownError, 1391 kUnknownError,
1340 "Location atom returned non-dictionary type: " + 1392 "Location atom returned non-dictionary type: " +
1341 JsonStringify(value.get())); 1393 JsonStringify(value.get()));
1342 } 1394 }
1343 DictionaryValue* loc_dict = static_cast<DictionaryValue*>(value.get()); 1395 DictionaryValue* loc_dict = static_cast<DictionaryValue*>(value.get());
1344 int x = 0, y = 0; 1396 int x = 0, y = 0;
1345 if (!loc_dict->GetInteger("x", &x) || 1397 if (!loc_dict->GetInteger("x", &x) ||
1346 !loc_dict->GetInteger("y", &y)) { 1398 !loc_dict->GetInteger("y", &y)) {
1347 return new Error( 1399 return new Error(
1348 kUnknownError, 1400 kUnknownError,
1349 "Location atom returned bad coordinate dictionary: " + 1401 "Location atom returned bad coordinate dictionary: " +
1350 JsonStringify(loc_dict)); 1402 JsonStringify(loc_dict));
1351 } 1403 }
1352 *location = gfx::Point(x, y); 1404 gfx::Point temp_location = gfx::Point(x, y);
1405
1406 if (verify_clickable_at_middle) {
1407 gfx::Point middle_point = temp_location;
1408 middle_point.Offset(region.width() / 2, region.height() / 2);
1409 error = VerifyElementIsClickable(frame_id, element, middle_point);
1410 if (error)
1411 return error;
1412 }
1413 *location = temp_location;
1353 return NULL; 1414 return NULL;
1354 } 1415 }
1355 1416
1356 Error* Session::GetScreenShot(std::string* png) { 1417 Error* Session::GetScreenShot(std::string* png) {
1357 Error* error = NULL; 1418 Error* error = NULL;
1358 ScopedTempDir screenshots_dir; 1419 ScopedTempDir screenshots_dir;
1359 if (!screenshots_dir.CreateUniqueTempDir()) { 1420 if (!screenshots_dir.CreateUniqueTempDir()) {
1360 return new Error(kUnknownError, 1421 return new Error(kUnknownError,
1361 "Could not create temp directory for screenshot"); 1422 "Could not create temp directory for screenshot");
1362 } 1423 }
1363 1424
1364 FilePath path = screenshots_dir.path().AppendASCII("screen"); 1425 FilePath path = screenshots_dir.path().AppendASCII("screen");
1365 RunSessionTask(NewRunnableMethod( 1426 RunSessionTask(NewRunnableMethod(
1366 automation_.get(), 1427 automation_.get(),
1367 &Automation::CaptureEntirePageAsPNG, 1428 &Automation::CaptureEntirePageAsPNG,
1368 current_target_.window_id, 1429 current_target_.window_id,
1369 path, 1430 path,
1370 &error)); 1431 &error));
1371 if (error) 1432 if (error)
1372 return error; 1433 return error;
1373 if (!file_util::ReadFileToString(path, png)) 1434 if (!file_util::ReadFileToString(path, png))
1374 return new Error(kUnknownError, "Could not read screenshot file"); 1435 return new Error(kUnknownError, "Could not read screenshot file");
1375 return NULL; 1436 return NULL;
1376 } 1437 }
1377 1438
1378 } // namespace webdriver 1439 } // namespace webdriver
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698