Commit 11c23f08 11c23f080d0ea7c9a45c817515468785a102a1b8 by Nicolas Perriault

implemented Casper.clickLabel()

Casper.clickLabel() can click on an element found by its innerText
content.
1 parent 9fcf6740
Subproject commit 391905e247c441e818c2e13bc6951f962bb7bcab
Subproject commit d42ca8ba7d2d174c381175e1562b867b679f3d77
......
......@@ -46,7 +46,7 @@ exports.selectXPath = function selectXPath(expression) {
type: 'xpath',
path: expression,
toString: function() {
return this.type + ' selector: ' + this.selector;
return this.type + ' selector: ' + this.path;
}
};
};
......@@ -279,7 +279,7 @@ Casper.prototype.clear = function clear() {
*
* In case of success, `true` is returned, `false` otherwise.
*
* @param String selector A DOM CSS3 compatible selector
* @param String selector A DOM CSS3 compatible selector
* @return Boolean
*/
Casper.prototype.click = function click(selector) {
......@@ -287,36 +287,15 @@ Casper.prototype.click = function click(selector) {
};
/**
* Emulates an event on the element from the provided selector using the mouse
* pointer, if possible.
* Emulates a click on the element having `label` as innerText. The first
* element matching this label will be selected, so use with caution.
*
* 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
* @param String label Element innerText value
* @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 dispatch an event on nonexistent selector: " + selector);
}
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.processEvent(type, selector);
} catch (e) {
this.log(f("Error while trying to emulate event %s on selector %s: %s", type, selector, e), "error");
return false;
}
}
return true;
Casper.prototype.clickLabel = function clickLabel(label) {
var selector = exports.selectXPath('//*[text()="' + label.toString() + '"]');
return this.click(selector);
};
/**
......@@ -733,6 +712,39 @@ Casper.prototype.log = function log(message, level, space) {
};
/**
* 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 dispatch an event on nonexistent selector: " + selector);
}
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.processEvent(type, selector);
} catch (e) {
this.log(f("Couldn't emulate event '%s' on %s: %s", type, selector, e), "error");
return false;
}
}
return true;
};
/**
* Performs an HTTP request.
*
* @param String location The url to open
......
......@@ -50,32 +50,12 @@
var SUPPORTED_SELECTOR_TYPES = ['css', 'xpath'];
/**
* Dispatches a mouse event to the DOM element behind the provided selector.
*
* @param String type Type of event to dispatch
* @param String selector A CSS3 selector to the element to click
* @return Boolean
*/
this.mouseEvent = function(type, selector) {
var elem = this.findOne(selector);
if (!elem) {
this.log("mouseEvent(): Couldn't find any element matching '" + selector + "' selector", "error");
return false;
}
var evt = document.createEvent("MouseEvents");
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) {
this.click = function click(selector) {
return this.mouseEvent('click', selector);
};
......@@ -391,19 +371,6 @@
};
/**
* Removes all DOM elements matching a given XPath expression.
*
* @param String expression The XPath expression
* @return Array
*/
this.removeElementsByXPath = function removeElementsByXPath(expression) {
var a = document.evaluate(expression, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < a.snapshotLength; i++) {
a.snapshotItem(i).parentNode.removeChild(a.snapshotItem(i));
}
};
/**
* Logs a message. Will format the message a way CasperJS will be able
* to log phantomjs side.
*
......@@ -415,6 +382,26 @@
};
/**
* Dispatches a mouse event to the DOM element behind the provided selector.
*
* @param String type Type of event to dispatch
* @param String selector A CSS3 selector to the element to click
* @return Boolean
*/
this.mouseEvent = function mouseEvent(type, selector) {
var elem = this.findOne(selector);
if (!elem) {
this.log("mouseEvent(): Couldn't find any element matching '" + selector + "' selector", "error");
return false;
}
var evt = document.createEvent("MouseEvents");
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);
};
/**
* Processes a selector input, either as a string or an object.
*
* If passed an object, if must be of the form:
......@@ -455,6 +442,19 @@
};
/**
* Removes all DOM elements matching a given XPath expression.
*
* @param String expression The XPath expression
* @return Array
*/
this.removeElementsByXPath = function removeElementsByXPath(expression) {
var a = document.evaluate(expression, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < a.snapshotLength; i++) {
a.snapshotItem(i).parentNode.removeChild(a.snapshotItem(i));
}
};
/**
* Sets a field (or a set of fields) value. Fails silently, but log
* error messages.
*
......
......@@ -58,7 +58,7 @@ var Mouse = function Mouse(casper) {
if (!utils.isString(type) || supportedEvents.indexOf(type) === -1) {
throw new CasperError('Mouse.processEvent(): Unsupported mouse event type: ' + type);
}
if (supportedEvents.indexOf(type) > 0) {
if (emulatedEvents.indexOf(type) > -1) {
casper.log("Mouse.processEvent(): no native fallback for type " + type, "warning");
}
args = slice.call(args); // cast Arguments -> Array
......@@ -69,9 +69,6 @@ var Mouse = function Mouse(casper) {
case 1:
// selector
var selector = args[0];
if (!utils.isString(selector)) {
throw new CasperError('Mouse.processEvent(): No valid CSS selector passed: ' + selector);
}
casper.page.sendEvent.apply(casper.page, [type].concat(computeCenter(selector)));
break;
case 2:
......
......@@ -12,16 +12,30 @@ casper.then(function() {
// onclick variants tests
casper.thenOpen('tests/site/click.html', function() {
this.test.comment('CasperUtils.click()');
this.test.assert(this.click('#test1'), 'CasperUtils.click() can click an `href="javascript:` link');
this.test.assert(this.click('#test2'), 'CasperUtils.click() can click an `href="#"` link');
this.test.assert(this.click('#test3'), 'CasperUtils.click() can click an `onclick=".*; return false"` link');
this.test.assert(this.click('#test4'), 'CasperUtils.click() can click an unobstrusive js handled link');
this.test.comment('Casper.click()');
this.test.assert(this.click('#test1'), 'Casper.click() can click an `href="javascript:` link');
this.test.assert(this.click('#test2'), 'Casper.click() can click an `href="#"` link');
this.test.assert(this.click('#test3'), 'Casper.click() can click an `onclick=".*; return false"` link');
this.test.assert(this.click('#test4'), 'Casper.click() can click an unobstrusive js handled link');
var results = this.getGlobal('results');
this.test.assert(results.test1, 'Casper.click() has clicked an `href="javascript:` link');
this.test.assert(results.test2, 'Casper.click() has clicked an `href="#"` link');
this.test.assert(results.test3, 'Casper.click() has clicked an `onclick=".*; return false"` link');
this.test.assert(results.test4, 'Casper.click() has clicked an unobstrusive js handled link');
});
// clickLabel tests
casper.thenOpen('tests/site/click.html', function() {
this.test.comment('Casper.clickLabel()');
this.test.assert(this.clickLabel('test1'), 'Casper.clickLabel() can click an `href="javascript:` link');
this.test.assert(this.clickLabel('test2'), 'Casper.clickLabel() can click an `href="#"` link');
this.test.assert(this.clickLabel('test3'), 'Casper.clickLabel() can click an `onclick=".*; return false"` link');
this.test.assert(this.clickLabel('test4'), 'Casper.clickLabel() can click an unobstrusive js handled link');
var results = this.getGlobal('results');
this.test.assert(results.test1, 'CasperUtils.click() has clicked an `href="javascript:` link');
this.test.assert(results.test2, 'CasperUtils.click() has clicked an `href="#"` link');
this.test.assert(results.test3, 'CasperUtils.click() has clicked an `onclick=".*; return false"` link');
this.test.assert(results.test4, 'CasperUtils.click() has clicked an unobstrusive js handled link');
this.test.assert(results.test1, 'Casper.clickLabel() has clicked an `href="javascript:` link');
this.test.assert(results.test2, 'Casper.clickLabel() has clicked an `href="#"` link');
this.test.assert(results.test3, 'Casper.clickLabel() has clicked an `onclick=".*; return false"` link');
this.test.assert(results.test4, 'Casper.clickLabel() has clicked an unobstrusive js handled link');
});
// casper.mouse
......