Commit 6c10a819 6c10a819df85627b1a93bb63dc75011204d0b58f by Nicolas Perriault

Merge remote-tracking branch 'nrabinowitz/mouse-events' into mouse-events

closes #89 - Support for more mouse events

Conflicts:
	modules/casper.js
	modules/clientutils.js
2 parents 13b6dd03 fe240a71
......@@ -257,22 +257,36 @@ Casper.prototype.clear = function clear() {
* @return Boolean
*/
Casper.prototype.click = function click(selector) {
this.log("Click on selector: " + selector, "debug");
if (arguments.length > 1) {
this.emit("deprecated", "The click() method does not process the fallbackToHref argument since 0.6");
}
return this.mouseEvent('click', selector);
};
/**
* Emulates an event on the element from the provided selector using the mouse
* pointer, if possible.
*
* In case of success, `true` is returned, `false` otherwise.
*
* @param String type Type of event to emulate
* @param String selector A DOM CSS3 compatible selector
* @return Boolean
*/
Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
this.log("Mouse event '" + type + "' on selector: " + selector, "debug");
if (!this.exists(selector)) {
throw new CasperError("Cannot click on unexistent selector: " + selector);
throw new CasperError("Cannot dispatch an event on nonexistent selector: " + selector);
}
var clicked = this.evaluate(function _evaluate(selector) {
return __utils__.click(selector);
}, { selector: selector });
if (!clicked) {
var eventSuccess = this.evaluate(function(type, selector) {
return __utils__.mouseEvent(type, selector);
}, {
type: type,
selector: selector
});
if (!eventSuccess) {
// fallback onto native QtWebKit mouse events
try {
this.mouse.click(selector);
this.mouse.processEvent(type, selector);
} catch (e) {
this.log(f("Error while trying to click on selector %s: %s", selector, e), "error");
this.log(f("Error while trying to emulate event %s on selector %s: %s", type, selector, e), "error");
return false;
}
}
......@@ -679,20 +693,6 @@ Casper.prototype.log = function log(message, level, space) {
};
/**
* Emulates a click on an HTML element matching a given CSS3 selector,
* using the mouse pointer.
*
* @param String selector A DOM CSS3 compatible selector
* @return Casper
* @deprecated
* @since 0.6
*/
Casper.prototype.mouseClick = function mouseClick(selector) {
this.emit("deprecated", "The mouseClick() method has been deprecated since 0.6; use click() instead");
return this.click(selector);
};
/**
* Performs an HTTP request.
*
* @param String location The url to open
......
......@@ -50,25 +50,36 @@
var SUPPORTED_SELECTOR_TYPES = ['css', 'xpath'];
/**
* Clicks on the DOM element behind the provided selector.
* Dispatches a mouse event to the DOM element behind the provided selector.
*
* @param String selector A CSS3 selector to the element to click
* @param String type Type of event to dispatch
* @param String selector A CSS3 selector to the element to click
* @return Boolean
*/
this.click = function click(selector) {
this.mouseEvent = function(type, selector) {
var elem = this.findOne(selector);
if (!elem) {
this.log("click(): Couldn't find any element matching '" + selector + "' selector", "error");
this.log("mouseEvent(): Couldn't find any element matching '" + selector + "' selector", "error");
return false;
}
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window, 1, 1, 1, 1, 1, false, false, false, false, 0, elem);
evt.initMouseEvent(type, true, true, window, 1, 1, 1, 1, 1, false, false, false, false, 0, elem);
// dispatchEvent return value is false if at least one of the event
// handlers which handled this event called preventDefault
return elem.dispatchEvent(evt);
};
/**
* Clicks on the DOM element behind the provided selector.
*
* @param String selector A CSS3 selector to the element to click
* @return Boolean
*/
this.click = function(selector) {
return this.mouseEvent('click', selector);
};
/**
* Decodes a base64 encoded string. Succeeds where window.atob() fails.
*
* @param String str The base64 encoded contents
......
......@@ -39,7 +39,11 @@ var Mouse = function Mouse(casper) {
throw new CasperError('Mouse() needs a Casper instance');
}
var supportedEvents = ['mouseup', 'mousedown', 'click', 'mousemove'];
var slice = Array.prototype.slice;
var nativeEvents = ['mouseup', 'mousedown', 'click', 'mousemove'];
var emulatedEvents = ['mouseover', 'mouseout'];
var supportedEvents = nativeEvents.concat(emulatedEvents);
function computeCenter(selector) {
var bounds = casper.getElementBounds(selector);
......@@ -54,7 +58,10 @@ var Mouse = function Mouse(casper) {
if (!utils.isString(type) || supportedEvents.indexOf(type) === -1) {
throw new CasperError('Mouse.processEvent(): Unsupported mouse event type: ' + type);
}
args = Array.prototype.slice.call(args); // cast Arguments -> Array
if (supportedEvents.indexOf(type) > 0) {
casper.log("Mouse.processEvent(): no native fallback for type " + type, "warning");
}
args = slice.call(args); // cast Arguments -> Array
casper.emit('mouse.' + type.replace('mouse', ''), args);
switch (args.length) {
case 0:
......@@ -79,6 +86,10 @@ var Mouse = function Mouse(casper) {
}
}
this.processEvent = function() {
processEvent(arguments[0], slice.call(arguments, 1));
};
this.click = function click() {
processEvent('click', arguments);
};
......
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CasperJS test mouse events</title>
</head>
<body>
<a id="test1" href="#" onmousedown="results.test1 = true;">test</a>
<a id="test2" href="#">test</a>
<a id="test3" href="#" onmouseup="results.test3 = true;">test</a>
<a id="test4" href="#">test</a>
<a id="test5" href="#" onmouseover="results.test5 = true;">test</a>
<a id="test6" href="#">test</a>
<a id="test7" href="#" onmouseout="results.test7 = true;">test</a>
<a id="test8" href="#">test</a>
<script>
(function(window) {
window.results = {
test1: false,
test2: false,
test3: false,
test4: false,
test5: false,
test6: false,
test7: false,
test8: false
};
document.querySelector('#test2').onmousedown = function(event) {
results.test2 = true;
event.preventDefault();
};
document.querySelector('#test4').onmouseup = function(event) {
results.test4 = true;
event.preventDefault();
};
document.querySelector('#test6').onmouseover = function(event) {
results.test6 = true;
event.preventDefault();
};
document.querySelector('#test8').onmouseout = function(event) {
results.test8 = true;
event.preventDefault();
};
})(window);
</script>
</body>
</html>
casper.start('tests/site/mouse-events.html');
casper.then(function() {
this.test.comment('CasperUtils.mouseEvent()');
this.test.assert(this.mouseEvent('mousedown', '#test1'), 'CasperUtils.mouseEvent() can dispatch a mousedown event');
this.test.assert(this.mouseEvent('mousedown', '#test2'), 'CasperUtils.mouseEvent() can dispatch a mousedown event handled by unobstrusive js');
this.test.assert(this.mouseEvent('mouseup', '#test3'), 'CasperUtils.mouseEvent() can dispatch a mouseup event');
this.test.assert(this.mouseEvent('mouseup', '#test4'), 'CasperUtils.mouseEvent() can dispatch a mouseup event handled by unobstrusive js');
this.test.assert(this.mouseEvent('mouseover', '#test5'), 'CasperUtils.mouseEvent() can dispatch a mouseover event');
this.test.assert(this.mouseEvent('mouseover', '#test6'), 'CasperUtils.mouseEvent() can dispatch a mouseover event handled by unobstrusive js');
this.test.assert(this.mouseEvent('mouseout', '#test7'), 'CasperUtils.mouseEvent() can dispatch a mouseout event');
this.test.assert(this.mouseEvent('mouseout', '#test8'), 'CasperUtils.mouseEvent() can dispatch a mouseout event handled by unobstrusive js');
var results = this.getGlobal('results');
this.test.assert(results.test1, 'CasperUtils.mouseEvent() triggered mousedown');
this.test.assert(results.test2, 'CasperUtils.mouseEvent() triggered mousedown via unobstrusive js');
this.test.assert(results.test3, 'CasperUtils.mouseEvent() triggered mouseup');
this.test.assert(results.test4, 'CasperUtils.mouseEvent() triggered mouseup via unobstrusive js');
this.test.assert(results.test5, 'CasperUtils.mouseEvent() triggered mouseover');
this.test.assert(results.test6, 'CasperUtils.mouseEvent() triggered mouseover via unobstrusive js');
this.test.assert(results.test7, 'CasperUtils.mouseEvent() triggered mouseout');
this.test.assert(results.test8, 'CasperUtils.mouseEvent() triggered mouseout via unobstrusive js');
});
casper.run(function() {
this.test.done();
});