Skip to content
This repository has been archived by the owner on May 22, 2018. It is now read-only.

Commit

Permalink
EranMes, on behalf of Ken Kania: Add chrome-specific atom for checkin…
Browse files Browse the repository at this point in the history
…g whether an element is clickable at a certain point.

r13091
  • Loading branch information
eranmes committed Jul 26, 2011
1 parent ff53669 commit a431302
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 0 deletions.
53 changes: 53 additions & 0 deletions javascript/chrome-driver/atoms.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,56 @@ webdriver.chrome.getFirstClientRect = function(elem) {
clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);
};


/**
* Returns whether the element or any of its descendants would receive a click
* at the given location. Useful for debugging test clicking issues.
*
* @param {!Element} elem The element to use.
* @param {!goog.math.Coordinate} coord, The coordinate to use.
* @return {{clickable:boolean, message:string=}} Object containing a boolean
* "clickable" property, as to whether it can be clicked, and an optional
* "message" string property, which contains any warning/error message.
*/
webdriver.chrome.isElementClickable = function(elem, coord) {
function makeResult(clickable, opt_msg) {
var dict = {'clickable': clickable};
if (opt_msg)
dict['message'] = opt_msg;
return dict;
}

var elemAtPoint = elem.ownerDocument.elementFromPoint(coord.x, coord.y);
if (elemAtPoint == elem)
return makeResult(true);

var coord = '(' + coord.x + ', ' + coord.y + ')';
if (elemAtPoint == null) {
return makeResult(
false, 'Element is not clickable at point ' + coord);
}
var elemAtPointHTML = elemAtPoint.outerHTML;
if (elemAtPoint.hasChildNodes()) {
var inner = elemAtPoint.innerHTML;
var closingTag = '</' + elemAtPoint.tagName + '>';
var innerStart = elemAtPointHTML.length - inner.length - closingTag.length;
elemAtPointHTML = elemAtPointHTML.substring(0, innerStart) + '...' +
elemAtPointHTML.substring(innerStart + inner.length);
}
var parentElemIter = elemAtPoint.parentNode;
while (parentElemIter) {
if (parentElemIter == elem) {
return makeResult(
true,
'Element\'s descendant would receive the click. Consider ' +
'clicking the descendant instead. Descendant: ' +
elemAtPointHTML);
}
parentElemIter = parentElemIter.parentNode;
}
return makeResult(
false,
'Element is not clickable at point ' + coord + '. Unrelated element ' +
'would receive the click: ' + elemAtPointHTML);
};

6 changes: 6 additions & 0 deletions javascript/chrome-driver/build.desc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ js_fragment(name = "get_first_client_rect",
function = "webdriver.chrome.getFirstClientRect",
deps = [ ":deps" ])

js_fragment(name = "is_element_clickable",
module = "webdriver.chrome",
function = "webdriver.chrome.isElementClickable",
deps = [ ":deps" ])

js_test(name = "test",
srcs = [ "test/*_test.html" ],
path = "/javascript/chrome-driver/test",
Expand All @@ -30,6 +35,7 @@ js_fragment_header(name = "atoms",
deps = [
"//javascript/chrome-driver:get_first_client_rect:chrome",
"//javascript/chrome-driver:get_location_in_view:chrome",
"//javascript/chrome-driver:is_element_clickable:chrome",
"//javascript/webdriver-atoms:clear:chrome",
"//javascript/webdriver-atoms:execute_script:chrome",
"//javascript/webdriver-atoms:execute_async_script:chrome",
Expand Down
79 changes: 79 additions & 0 deletions javascript/chrome-driver/test/is_element_clickable_test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!DOCTYPE html>
<!--
Copyright 2011 WebDriver committers
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<title>is_element_clickable_test.html</title>
<script type="text/javascript" src="../../webdriver-bootstrap.js">
</script>
<script type="text/javascript">
goog.require('goog.math.Coordinate');
goog.require('goog.testing.jsunit');
goog.require('webdriver.chrome');
</script>

<script type="text/javascript">
function isClickable(elem, coord) {
var result = webdriver.chrome.isElementClickable(elem, coord);
console.log(result.message);
return result.clickable;
}

function getMidClientRect(elem) {
var rect = elem.getClientRects()[0];
var x = rect.left + (rect.right - rect.left) / 2;
var y = rect.top + (rect.bottom - rect.top) / 2;
return new goog.math.Coordinate(x, y);
}

function testElementIsClickable() {
var elem = document.getElementById('1');
assertTrue(isClickable(elem, getMidClientRect(elem)));
}

function testNotClickableAtPoint() {
var elem = document.getElementById('2');
var otherElem = document.getElementById('2b');
assertFalse(isClickable(elem, getMidClientRect(otherElem)));
}

function testElementIsClickableByDescendant() {
var elem = document.getElementById('3');
var child = document.getElementById('4');
assertTrue(isClickable(elem, getMidClientRect(child)));
}

function testInvalidCoordinateIsNotClickable() {
var elem = document.getElementById('1');
assertFalse(isClickable(elem, new goog.math.Coordinate(-1, -1)));
}

</script>
</head>
<body>
<div id='1' style='background-color:black'>1</div>
<div id='2' style='background-color:orange'>2</div>
<div id='2b' style='background-color:purple'>2b</div>
<div id='3' style='background-color:green'>
<div>3</div>
<div id='4' style='background-color:blue; position:relative; top:50px'>
div
</div>
</div>
</body>
</html>

0 comments on commit a431302

Please sign in to comment.