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

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
« no previous file with comments | « chrome/test/webdriver/session.h ('k') | chrome/test/webdriver/test/chromedriver_tests.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 if (error) 960 if (error)
959 return error; 961 return error;
960 if (!is_displayed) 962 if (!is_displayed)
961 return new Error(kElementNotVisible, "Element must be displayed to click"); 963 return new Error(kElementNotVisible, "Element must be displayed to click");
962 964
963 gfx::Rect rect; 965 gfx::Rect rect;
964 error = GetElementFirstClientRect(current_target_, element, &rect); 966 error = GetElementFirstClientRect(current_target_, element, &rect);
965 if (error) 967 if (error)
966 return error; 968 return error;
967 969
968 error = GetElementRegionInView(element, rect, true /* center */, location); 970 error = GetElementRegionInView(
971 element, rect, true /* center */, true /* verify_clickable_at_middle */,
972 location);
969 if (error) 973 if (error)
970 return error; 974 return error;
971 location->Offset(rect.width() / 2, rect.height() / 2); 975 location->Offset(rect.width() / 2, rect.height() / 2);
972 return NULL; 976 return NULL;
973 } 977 }
974 978
975 Error* Session::GetAttribute(const WebElementId& element, 979 Error* Session::GetAttribute(const WebElementId& element,
976 const std::string& key, Value** value) { 980 const std::string& key, Value** value) {
977 std::string script = base::StringPrintf( 981 std::string script = base::StringPrintf(
978 "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE); 982 "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE);
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
1306 elements->push_back(element); 1310 elements->push_back(element);
1307 } else { 1311 } else {
1308 return new Error( 1312 return new Error(
1309 kUnknownError, 1313 kUnknownError,
1310 "Find element script returned unsupported type: " + 1314 "Find element script returned unsupported type: " +
1311 JsonStringify(value.get())); 1315 JsonStringify(value.get()));
1312 } 1316 }
1313 return NULL; 1317 return NULL;
1314 } 1318 }
1315 1319
1320 Error* Session::VerifyElementIsClickable(
1321 const FrameId& frame_id,
1322 const WebElementId& element,
1323 const gfx::Point& location) {
1324 std::string jscript = base::StringPrintf(
1325 "return (%s).apply(null, arguments);", atoms::IS_ELEMENT_CLICKABLE);
1326 ListValue jscript_args;
1327 jscript_args.Append(element.ToValue());
1328 DictionaryValue* location_dict = new DictionaryValue();
1329 location_dict->SetInteger("x", location.x());
1330 location_dict->SetInteger("y", location.y());
1331 jscript_args.Append(location_dict);
1332 Value* unscoped_value = NULL;
1333 Error* error = ExecuteScript(frame_id, jscript, &jscript_args,
1334 &unscoped_value);
1335 if (error)
1336 return error;
1337
1338 scoped_ptr<Value> value(unscoped_value);
1339 if (!value->IsType(Value::TYPE_DICTIONARY)) {
1340 return new Error(
1341 kUnknownError,
1342 "isElementClickable atom returned non-dictionary type: " +
1343 JsonStringify(value.get()));
1344 }
1345 DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
1346 bool clickable = false;
1347 if (!dict->GetBoolean("clickable", &clickable)) {
1348 return new Error(
1349 kUnknownError,
1350 "isElementClickable atom returned bad invalid dictionary: " +
1351 JsonStringify(dict));
1352 }
1353 std::string message;
1354 dict->GetString("message", &message);
1355 if (!clickable) {
1356 if (message.empty())
1357 message = "element is not clickable";
1358 return new Error(kUnknownError, message);
1359 }
1360 if (message.length()) {
1361 LOG(WARNING) << message;
1362 }
1363 return NULL;
1364 }
1365
1316 Error* Session::GetElementRegionInViewHelper( 1366 Error* Session::GetElementRegionInViewHelper(
1317 const FrameId& frame_id, 1367 const FrameId& frame_id,
1318 const WebElementId& element, 1368 const WebElementId& element,
1319 const gfx::Rect& region, 1369 const gfx::Rect& region,
1320 bool center, 1370 bool center,
1371 bool verify_clickable_at_middle,
1321 gfx::Point* location) { 1372 gfx::Point* location) {
1322 std::string jscript = base::StringPrintf( 1373 std::string jscript = base::StringPrintf(
1323 "return (%s).apply(null, arguments);", atoms::GET_LOCATION_IN_VIEW); 1374 "return (%s).apply(null, arguments);", atoms::GET_LOCATION_IN_VIEW);
1324 ListValue jscript_args; 1375 ListValue jscript_args;
1325 jscript_args.Append(element.ToValue()); 1376 jscript_args.Append(element.ToValue());
1326 jscript_args.Append(Value::CreateBooleanValue(center)); 1377 jscript_args.Append(Value::CreateBooleanValue(center));
1327 DictionaryValue* elem_offset_dict = new DictionaryValue(); 1378 DictionaryValue* elem_offset_dict = new DictionaryValue();
1328 elem_offset_dict->SetInteger("left", region.x()); 1379 elem_offset_dict->SetInteger("left", region.x());
1329 elem_offset_dict->SetInteger("top", region.y()); 1380 elem_offset_dict->SetInteger("top", region.y());
1330 elem_offset_dict->SetInteger("width", region.width()); 1381 elem_offset_dict->SetInteger("width", region.width());
1331 elem_offset_dict->SetInteger("height", region.height()); 1382 elem_offset_dict->SetInteger("height", region.height());
1332 jscript_args.Append(elem_offset_dict); 1383 jscript_args.Append(elem_offset_dict);
1333 Value* unscoped_value = NULL; 1384 Value* unscoped_value = NULL;
1334 Error* error = ExecuteScript(frame_id, jscript, &jscript_args, 1385 Error* error = ExecuteScript(frame_id, jscript, &jscript_args,
1335 &unscoped_value); 1386 &unscoped_value);
1336 scoped_ptr<Value> value(unscoped_value); 1387 scoped_ptr<Value> value(unscoped_value);
1337 if (error) 1388 if (error)
1338 return error; 1389 return error;
1390
1339 if (!value->IsType(Value::TYPE_DICTIONARY)) { 1391 if (!value->IsType(Value::TYPE_DICTIONARY)) {
1340 return new Error( 1392 return new Error(
1341 kUnknownError, 1393 kUnknownError,
1342 "Location atom returned non-dictionary type: " + 1394 "Location atom returned non-dictionary type: " +
1343 JsonStringify(value.get())); 1395 JsonStringify(value.get()));
1344 } 1396 }
1345 DictionaryValue* loc_dict = static_cast<DictionaryValue*>(value.get()); 1397 DictionaryValue* loc_dict = static_cast<DictionaryValue*>(value.get());
1346 int x = 0, y = 0; 1398 int x = 0, y = 0;
1347 if (!loc_dict->GetInteger("x", &x) || 1399 if (!loc_dict->GetInteger("x", &x) ||
1348 !loc_dict->GetInteger("y", &y)) { 1400 !loc_dict->GetInteger("y", &y)) {
1349 return new Error( 1401 return new Error(
1350 kUnknownError, 1402 kUnknownError,
1351 "Location atom returned bad coordinate dictionary: " + 1403 "Location atom returned bad coordinate dictionary: " +
1352 JsonStringify(loc_dict)); 1404 JsonStringify(loc_dict));
1353 } 1405 }
1354 *location = gfx::Point(x, y); 1406 gfx::Point temp_location = gfx::Point(x, y);
1407
1408 if (verify_clickable_at_middle) {
1409 gfx::Point middle_point = temp_location;
1410 middle_point.Offset(region.width() / 2, region.height() / 2);
1411 error = VerifyElementIsClickable(frame_id, element, middle_point);
1412 if (error)
1413 return error;
1414 }
1415 *location = temp_location;
1355 return NULL; 1416 return NULL;
1356 } 1417 }
1357 1418
1358 Error* Session::GetScreenShot(std::string* png) { 1419 Error* Session::GetScreenShot(std::string* png) {
1359 Error* error = NULL; 1420 Error* error = NULL;
1360 ScopedTempDir screenshots_dir; 1421 ScopedTempDir screenshots_dir;
1361 if (!screenshots_dir.CreateUniqueTempDir()) { 1422 if (!screenshots_dir.CreateUniqueTempDir()) {
1362 return new Error(kUnknownError, 1423 return new Error(kUnknownError,
1363 "Could not create temp directory for screenshot"); 1424 "Could not create temp directory for screenshot");
1364 } 1425 }
1365 1426
1366 FilePath path = screenshots_dir.path().AppendASCII("screen"); 1427 FilePath path = screenshots_dir.path().AppendASCII("screen");
1367 RunSessionTask(NewRunnableMethod( 1428 RunSessionTask(NewRunnableMethod(
1368 automation_.get(), 1429 automation_.get(),
1369 &Automation::CaptureEntirePageAsPNG, 1430 &Automation::CaptureEntirePageAsPNG,
1370 current_target_.window_id, 1431 current_target_.window_id,
1371 path, 1432 path,
1372 &error)); 1433 &error));
1373 if (error) 1434 if (error)
1374 return error; 1435 return error;
1375 if (!file_util::ReadFileToString(path, png)) 1436 if (!file_util::ReadFileToString(path, png))
1376 return new Error(kUnknownError, "Could not read screenshot file"); 1437 return new Error(kUnknownError, "Could not read screenshot file");
1377 return NULL; 1438 return NULL;
1378 } 1439 }
1379 1440
1380 } // namespace webdriver 1441 } // namespace webdriver
OLDNEW
« no previous file with comments | « chrome/test/webdriver/session.h ('k') | chrome/test/webdriver/test/chromedriver_tests.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698