Commit 11c23f08 11c23f080d0ea7c9a45c817515468785a102a1b8 by Nicolas Perriault

implemented Casper.clickLabel()

Casper.clickLabel() can click on an element found by its innerText
content.
1 parent 9fcf6740
1 Subproject commit 391905e247c441e818c2e13bc6951f962bb7bcab 1 Subproject commit d42ca8ba7d2d174c381175e1562b867b679f3d77
......
...@@ -46,7 +46,7 @@ exports.selectXPath = function selectXPath(expression) { ...@@ -46,7 +46,7 @@ exports.selectXPath = function selectXPath(expression) {
46 type: 'xpath', 46 type: 'xpath',
47 path: expression, 47 path: expression,
48 toString: function() { 48 toString: function() {
49 return this.type + ' selector: ' + this.selector; 49 return this.type + ' selector: ' + this.path;
50 } 50 }
51 }; 51 };
52 }; 52 };
...@@ -279,7 +279,7 @@ Casper.prototype.clear = function clear() { ...@@ -279,7 +279,7 @@ Casper.prototype.clear = function clear() {
279 * 279 *
280 * In case of success, `true` is returned, `false` otherwise. 280 * In case of success, `true` is returned, `false` otherwise.
281 * 281 *
282 * @param String selector A DOM CSS3 compatible selector 282 * @param String selector A DOM CSS3 compatible selector
283 * @return Boolean 283 * @return Boolean
284 */ 284 */
285 Casper.prototype.click = function click(selector) { 285 Casper.prototype.click = function click(selector) {
...@@ -287,36 +287,15 @@ Casper.prototype.click = function click(selector) { ...@@ -287,36 +287,15 @@ Casper.prototype.click = function click(selector) {
287 }; 287 };
288 288
289 /** 289 /**
290 * Emulates an event on the element from the provided selector using the mouse 290 * Emulates a click on the element having `label` as innerText. The first
291 * pointer, if possible. 291 * element matching this label will be selected, so use with caution.
292 * 292 *
293 * In case of success, `true` is returned, `false` otherwise. 293 * @param String label Element innerText value
294 *
295 * @param String type Type of event to emulate
296 * @param String selector A DOM CSS3 compatible selector
297 * @return Boolean 294 * @return Boolean
298 */ 295 */
299 Casper.prototype.mouseEvent = function mouseEvent(type, selector) { 296 Casper.prototype.clickLabel = function clickLabel(label) {
300 this.log("Mouse event '" + type + "' on selector: " + selector, "debug"); 297 var selector = exports.selectXPath('//*[text()="' + label.toString() + '"]');
301 if (!this.exists(selector)) { 298 return this.click(selector);
302 throw new CasperError("Cannot dispatch an event on nonexistent selector: " + selector);
303 }
304 var eventSuccess = this.evaluate(function(type, selector) {
305 return __utils__.mouseEvent(type, selector);
306 }, {
307 type: type,
308 selector: selector
309 });
310 if (!eventSuccess) {
311 // fallback onto native QtWebKit mouse events
312 try {
313 this.mouse.processEvent(type, selector);
314 } catch (e) {
315 this.log(f("Error while trying to emulate event %s on selector %s: %s", type, selector, e), "error");
316 return false;
317 }
318 }
319 return true;
320 }; 299 };
321 300
322 /** 301 /**
...@@ -733,6 +712,39 @@ Casper.prototype.log = function log(message, level, space) { ...@@ -733,6 +712,39 @@ Casper.prototype.log = function log(message, level, space) {
733 }; 712 };
734 713
735 /** 714 /**
715 * Emulates an event on the element from the provided selector using the mouse
716 * pointer, if possible.
717 *
718 * In case of success, `true` is returned, `false` otherwise.
719 *
720 * @param String type Type of event to emulate
721 * @param String selector A DOM CSS3 compatible selector
722 * @return Boolean
723 */
724 Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
725 this.log("Mouse event '" + type + "' on selector: " + selector, "debug");
726 if (!this.exists(selector)) {
727 throw new CasperError("Cannot dispatch an event on nonexistent selector: " + selector);
728 }
729 var eventSuccess = this.evaluate(function(type, selector) {
730 return __utils__.mouseEvent(type, selector);
731 }, {
732 type: type,
733 selector: selector
734 });
735 if (!eventSuccess) {
736 // fallback onto native QtWebKit mouse events
737 try {
738 this.mouse.processEvent(type, selector);
739 } catch (e) {
740 this.log(f("Couldn't emulate event '%s' on %s: %s", type, selector, e), "error");
741 return false;
742 }
743 }
744 return true;
745 };
746
747 /**
736 * Performs an HTTP request. 748 * Performs an HTTP request.
737 * 749 *
738 * @param String location The url to open 750 * @param String location The url to open
......
...@@ -50,32 +50,12 @@ ...@@ -50,32 +50,12 @@
50 var SUPPORTED_SELECTOR_TYPES = ['css', 'xpath']; 50 var SUPPORTED_SELECTOR_TYPES = ['css', 'xpath'];
51 51
52 /** 52 /**
53 * Dispatches a mouse event to the DOM element behind the provided selector.
54 *
55 * @param String type Type of event to dispatch
56 * @param String selector A CSS3 selector to the element to click
57 * @return Boolean
58 */
59 this.mouseEvent = function(type, selector) {
60 var elem = this.findOne(selector);
61 if (!elem) {
62 this.log("mouseEvent(): Couldn't find any element matching '" + selector + "' selector", "error");
63 return false;
64 }
65 var evt = document.createEvent("MouseEvents");
66 evt.initMouseEvent(type, true, true, window, 1, 1, 1, 1, 1, false, false, false, false, 0, elem);
67 // dispatchEvent return value is false if at least one of the event
68 // handlers which handled this event called preventDefault
69 return elem.dispatchEvent(evt);
70 };
71
72 /**
73 * Clicks on the DOM element behind the provided selector. 53 * Clicks on the DOM element behind the provided selector.
74 * 54 *
75 * @param String selector A CSS3 selector to the element to click 55 * @param String selector A CSS3 selector to the element to click
76 * @return Boolean 56 * @return Boolean
77 */ 57 */
78 this.click = function(selector) { 58 this.click = function click(selector) {
79 return this.mouseEvent('click', selector); 59 return this.mouseEvent('click', selector);
80 }; 60 };
81 61
...@@ -391,19 +371,6 @@ ...@@ -391,19 +371,6 @@
391 }; 371 };
392 372
393 /** 373 /**
394 * Removes all DOM elements matching a given XPath expression.
395 *
396 * @param String expression The XPath expression
397 * @return Array
398 */
399 this.removeElementsByXPath = function removeElementsByXPath(expression) {
400 var a = document.evaluate(expression, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
401 for (var i = 0; i < a.snapshotLength; i++) {
402 a.snapshotItem(i).parentNode.removeChild(a.snapshotItem(i));
403 }
404 };
405
406 /**
407 * Logs a message. Will format the message a way CasperJS will be able 374 * Logs a message. Will format the message a way CasperJS will be able
408 * to log phantomjs side. 375 * to log phantomjs side.
409 * 376 *
...@@ -415,6 +382,26 @@ ...@@ -415,6 +382,26 @@
415 }; 382 };
416 383
417 /** 384 /**
385 * Dispatches a mouse event to the DOM element behind the provided selector.
386 *
387 * @param String type Type of event to dispatch
388 * @param String selector A CSS3 selector to the element to click
389 * @return Boolean
390 */
391 this.mouseEvent = function mouseEvent(type, selector) {
392 var elem = this.findOne(selector);
393 if (!elem) {
394 this.log("mouseEvent(): Couldn't find any element matching '" + selector + "' selector", "error");
395 return false;
396 }
397 var evt = document.createEvent("MouseEvents");
398 evt.initMouseEvent(type, true, true, window, 1, 1, 1, 1, 1, false, false, false, false, 0, elem);
399 // dispatchEvent return value is false if at least one of the event
400 // handlers which handled this event called preventDefault
401 return elem.dispatchEvent(evt);
402 };
403
404 /**
418 * Processes a selector input, either as a string or an object. 405 * Processes a selector input, either as a string or an object.
419 * 406 *
420 * If passed an object, if must be of the form: 407 * If passed an object, if must be of the form:
...@@ -455,6 +442,19 @@ ...@@ -455,6 +442,19 @@
455 }; 442 };
456 443
457 /** 444 /**
445 * Removes all DOM elements matching a given XPath expression.
446 *
447 * @param String expression The XPath expression
448 * @return Array
449 */
450 this.removeElementsByXPath = function removeElementsByXPath(expression) {
451 var a = document.evaluate(expression, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
452 for (var i = 0; i < a.snapshotLength; i++) {
453 a.snapshotItem(i).parentNode.removeChild(a.snapshotItem(i));
454 }
455 };
456
457 /**
458 * Sets a field (or a set of fields) value. Fails silently, but log 458 * Sets a field (or a set of fields) value. Fails silently, but log
459 * error messages. 459 * error messages.
460 * 460 *
......
...@@ -58,7 +58,7 @@ var Mouse = function Mouse(casper) { ...@@ -58,7 +58,7 @@ var Mouse = function Mouse(casper) {
58 if (!utils.isString(type) || supportedEvents.indexOf(type) === -1) { 58 if (!utils.isString(type) || supportedEvents.indexOf(type) === -1) {
59 throw new CasperError('Mouse.processEvent(): Unsupported mouse event type: ' + type); 59 throw new CasperError('Mouse.processEvent(): Unsupported mouse event type: ' + type);
60 } 60 }
61 if (supportedEvents.indexOf(type) > 0) { 61 if (emulatedEvents.indexOf(type) > -1) {
62 casper.log("Mouse.processEvent(): no native fallback for type " + type, "warning"); 62 casper.log("Mouse.processEvent(): no native fallback for type " + type, "warning");
63 } 63 }
64 args = slice.call(args); // cast Arguments -> Array 64 args = slice.call(args); // cast Arguments -> Array
...@@ -69,9 +69,6 @@ var Mouse = function Mouse(casper) { ...@@ -69,9 +69,6 @@ var Mouse = function Mouse(casper) {
69 case 1: 69 case 1:
70 // selector 70 // selector
71 var selector = args[0]; 71 var selector = args[0];
72 if (!utils.isString(selector)) {
73 throw new CasperError('Mouse.processEvent(): No valid CSS selector passed: ' + selector);
74 }
75 casper.page.sendEvent.apply(casper.page, [type].concat(computeCenter(selector))); 72 casper.page.sendEvent.apply(casper.page, [type].concat(computeCenter(selector)));
76 break; 73 break;
77 case 2: 74 case 2:
......
...@@ -12,16 +12,30 @@ casper.then(function() { ...@@ -12,16 +12,30 @@ casper.then(function() {
12 12
13 // onclick variants tests 13 // onclick variants tests
14 casper.thenOpen('tests/site/click.html', function() { 14 casper.thenOpen('tests/site/click.html', function() {
15 this.test.comment('CasperUtils.click()'); 15 this.test.comment('Casper.click()');
16 this.test.assert(this.click('#test1'), 'CasperUtils.click() can click an `href="javascript:` link'); 16 this.test.assert(this.click('#test1'), 'Casper.click() can click an `href="javascript:` link');
17 this.test.assert(this.click('#test2'), 'CasperUtils.click() can click an `href="#"` link'); 17 this.test.assert(this.click('#test2'), 'Casper.click() can click an `href="#"` link');
18 this.test.assert(this.click('#test3'), 'CasperUtils.click() can click an `onclick=".*; return false"` link'); 18 this.test.assert(this.click('#test3'), 'Casper.click() can click an `onclick=".*; return false"` link');
19 this.test.assert(this.click('#test4'), 'CasperUtils.click() can click an unobstrusive js handled link'); 19 this.test.assert(this.click('#test4'), 'Casper.click() can click an unobstrusive js handled link');
20 var results = this.getGlobal('results');
21 this.test.assert(results.test1, 'Casper.click() has clicked an `href="javascript:` link');
22 this.test.assert(results.test2, 'Casper.click() has clicked an `href="#"` link');
23 this.test.assert(results.test3, 'Casper.click() has clicked an `onclick=".*; return false"` link');
24 this.test.assert(results.test4, 'Casper.click() has clicked an unobstrusive js handled link');
25 });
26
27 // clickLabel tests
28 casper.thenOpen('tests/site/click.html', function() {
29 this.test.comment('Casper.clickLabel()');
30 this.test.assert(this.clickLabel('test1'), 'Casper.clickLabel() can click an `href="javascript:` link');
31 this.test.assert(this.clickLabel('test2'), 'Casper.clickLabel() can click an `href="#"` link');
32 this.test.assert(this.clickLabel('test3'), 'Casper.clickLabel() can click an `onclick=".*; return false"` link');
33 this.test.assert(this.clickLabel('test4'), 'Casper.clickLabel() can click an unobstrusive js handled link');
20 var results = this.getGlobal('results'); 34 var results = this.getGlobal('results');
21 this.test.assert(results.test1, 'CasperUtils.click() has clicked an `href="javascript:` link'); 35 this.test.assert(results.test1, 'Casper.clickLabel() has clicked an `href="javascript:` link');
22 this.test.assert(results.test2, 'CasperUtils.click() has clicked an `href="#"` link'); 36 this.test.assert(results.test2, 'Casper.clickLabel() has clicked an `href="#"` link');
23 this.test.assert(results.test3, 'CasperUtils.click() has clicked an `onclick=".*; return false"` link'); 37 this.test.assert(results.test3, 'Casper.clickLabel() has clicked an `onclick=".*; return false"` link');
24 this.test.assert(results.test4, 'CasperUtils.click() has clicked an unobstrusive js handled link'); 38 this.test.assert(results.test4, 'Casper.clickLabel() has clicked an unobstrusive js handled link');
25 }); 39 });
26 40
27 // casper.mouse 41 // casper.mouse
......