implemented Casper.clickLabel()
Casper.clickLabel() can click on an element found by its innerText content.
Showing
5 changed files
with
100 additions
and
77 deletions
... | @@ -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 | ... | ... |
-
Please register or sign in to post a comment