Commit 01c97982 01c97982e27853a89d55c5872aa5c6b1d6ff7f05 by Brikou CARRE

sync with latest master

2 parents f44d37b6 a05a2586
1 CasperJS Changelog 1 CasperJS Changelog
2 ================== 2 ==================
3 3
4 2012-06-04, v0.6.10
5 -------------------
6
7 - fixed [#73](https://github.com/n1k0/casperjs/issues/73) - `Casper.download()` not working correctly with binaries
8 - fixed [#129](https://github.com/n1k0/casperjs/issues/129) - Can't put `//` comments in evaluate() function
9 - closed [#130](https://github.com/n1k0/casperjs/issues/130) - Added a `Dummy` [colorizer](http://casperjs.org/api.html#colorizer) class, in order to disable colors in console output
10 - fixed [#133](https://github.com/n1k0/casperjs/issues/133) - updated and fixed documentation about [extensibility](http://casperjs.org/extending.html)
11 - added `Casper.clickLabel()` for clicking on an element found by its `innerText` content
12
13 As a side note, the official website monolithic page has been split across several ones: http://casperjs.org/
14
15 2012-05-29, v0.6.9
16 ------------------
17
18 - **BC BREAK:** PhantomJS 1.5 is now the minimal PhantomJS version supported.
19 - fixed [#114](https://github.com/n1k0/casperjs/issues/114) - ensured client-side utils are injected before any `evaluate()` call
20 - merged [#89](https://github.com/n1k0/casperjs/pull/89) - Support for more mouse events (@nrabinowitz)
21 - [added a new `error` event, better error reporting](https://github.com/n1k0/casperjs/commit/2e6988ae821b3251e063d11ba28af59b0683852a)
22 - fixed [#117](https://github.com/n1k0/casperjs/issues/117) - `fill()` coulnd't `submit()` a form with a submit input named *submit*
23 - merged [#122](https://github.com/n1k0/casperjs/pull/122) - allow downloads to be triggered by more than just `GET` requests
24 - closed [#57](https://github.com/n1k0/casperjs/issues/57) - added context to emitted test events + complete assertion framework refactor
25 - fixed loaded resources array is now reset adequately [reference discussion](https://groups.google.com/forum/?hl=fr?fromgroups#!topic/casperjs/TCkNzrj1IoA)
26 - fixed incomplete error message logged when passed an erroneous selector (xpath and css)
27
4 2012-05-20, v0.6.8 28 2012-05-20, v0.6.8
5 ------------------ 29 ------------------
6 30
......
...@@ -4,7 +4,7 @@ CasperJS is a navigation scripting & testing utility for [PhantomJS](http://www. ...@@ -4,7 +4,7 @@ CasperJS is a navigation scripting & testing utility for [PhantomJS](http://www.
4 It eases the process of defining a full navigation scenario and provides useful 4 It eases the process of defining a full navigation scenario and provides useful
5 high-level functions, methods & syntaxic sugar for doing common tasks such as: 5 high-level functions, methods & syntaxic sugar for doing common tasks such as:
6 6
7 - defining & ordering [navigation steps](http://casperjs.org/#phantom_Casper_run) 7 - defining & ordering [navigation steps](http://casperjs.org/#quickstart)
8 - [filling forms](http://casperjs.org/#phantom_Casper_fill) 8 - [filling forms](http://casperjs.org/#phantom_Casper_fill)
9 - [clicking links](http://casperjs.org/#phantom_Casper_click) 9 - [clicking links](http://casperjs.org/#phantom_Casper_click)
10 - [capturing screenshots](http://casperjs.org/#phantom_Casper_captureSelector) of a page (or an area) 10 - [capturing screenshots](http://casperjs.org/#phantom_Casper_captureSelector) of a page (or an area)
...@@ -12,15 +12,16 @@ high-level functions, methods & syntaxic sugar for doing common tasks such as: ...@@ -12,15 +12,16 @@ high-level functions, methods & syntaxic sugar for doing common tasks such as:
12 - [logging](http://casperjs.org/#logging) & [events](http://casperjs.org/#events-filters) 12 - [logging](http://casperjs.org/#logging) & [events](http://casperjs.org/#events-filters)
13 - [downloading base64](http://casperjs.org/#phantom_Casper_download) encoded resources, even binary ones 13 - [downloading base64](http://casperjs.org/#phantom_Casper_download) encoded resources, even binary ones
14 - catching errors and react accordingly 14 - catching errors and react accordingly
15 - writing [functional test suite](http://casperjs.org/#testing), exporting results as JUnit XML (xUnit) 15 - writing [functional test suites](http://casperjs.org/#testing), exporting results as JUnit XML (xUnit)
16 16
17 Feel free to browse our [sample examples repository](https://github.com/n1k0/casperjs/tree/master/samples). 17 Browse the [sample examples repository](https://github.com/n1k0/casperjs/tree/master/samples).
18 Don't hesitate to pull request for any cool example of yours as well! 18 Don't hesitate to pull request for any cool example of yours as well!
19 19
20 **Read the [full documentation](http://casperjs.org/) on casperjs dedicated website.** 20 **Read the [full documentation](http://casperjs.org/) on casperjs dedicated website.**
21 21
22 Subscribe to the [project mailing-list](https://groups.google.com/forum/#!forum/casperjs) 22 Subscribe to the [project mailing-list](https://groups.google.com/forum/#!forum/casperjs)
23 23
24 Follow [@casperjs_org on twitter](https://twitter.com/casperjs_org).
24 25
25 ## Contributing to the docs 26 ## Contributing to the docs
26 27
......
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
27 * DEALINGS IN THE SOFTWARE. 27 * DEALINGS IN THE SOFTWARE.
28 * 28 *
29 */ 29 */
30 if (phantom.version.major !== 1 || phantom.version.minor < 5) {
31 console.error('CasperJS needs at least PhantomJS v1.5.0');
32 phantom.exit(1);
33 }
30 34
31 /** 35 /**
32 * Loads and initialize the CasperJS environment. 36 * Loads and initialize the CasperJS environment.
...@@ -151,7 +155,7 @@ phantom.loadCasper = function loadCasper() { ...@@ -151,7 +155,7 @@ phantom.loadCasper = function loadCasper() {
151 * TODO: remove when PhantomJS has full module support 155 * TODO: remove when PhantomJS has full module support
152 */ 156 */
153 require = (function _require(require, requireDir) { 157 require = (function _require(require, requireDir) {
154 var phantomBuiltins = ['fs', 'webpage', 'webserver']; 158 var phantomBuiltins = ['fs', 'webpage', 'webserver', 'system'];
155 var phantomRequire = phantom.__orig__require = require; 159 var phantomRequire = phantom.__orig__require = require;
156 var requireCache = {}; 160 var requireCache = {};
157 return function _require(path) { 161 return function _require(path) {
...@@ -229,32 +233,6 @@ phantom.loadCasper = function loadCasper() { ...@@ -229,32 +233,6 @@ phantom.loadCasper = function loadCasper() {
229 }; 233 };
230 234
231 /** 235 /**
232 * Custom global error handler.
233 */
234 phantom.onError = function phantom_onError(msg, backtrace) {
235 var c = require('colorizer').create();
236 var match = /^(.*): __mod_error(.*):: (.*)/.exec(msg);
237 var notices = [];
238 if (match && match.length === 4) {
239 notices.push(' in module ' + match[2]);
240 notices.push(' NOTICE: errors within modules cannot be backtraced yet.');
241 msg = match[3];
242 }
243 console.error(c.colorize(msg, 'RED_BAR', 80));
244 notices.forEach(function(notice) {
245 console.error(c.colorize(notice, 'COMMENT'));
246 });
247 backtrace.forEach(function(item) {
248 var message = require('fs').absolute(item.file) + ":" + c.colorize(item.line, "COMMENT");
249 if (item['function']) {
250 message += " in " + c.colorize(item['function'], "PARAMETER");
251 }
252 console.error(" " + message);
253 });
254 phantom.exit(1);
255 };
256
257 /**
258 * Initializes the CasperJS Command Line Interface. 236 * Initializes the CasperJS Command Line Interface.
259 */ 237 */
260 phantom.initCasperCli = function initCasperCli() { 238 phantom.initCasperCli = function initCasperCli() {
......
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 2
3 import os 3 import os
4 import subprocess
5 import sys 4 import sys
6 5
7 6
......
1 Subproject commit 100ffeb02edee0d765efd29ef897c25343e24b2d 1 Subproject commit 9ec9627555680a13c411d6b19541f3d23c8f30f7
......
...@@ -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 };
...@@ -66,7 +66,8 @@ var Casper = function Casper(options) { ...@@ -66,7 +66,8 @@ var Casper = function Casper(options) {
66 // default options 66 // default options
67 this.defaults = { 67 this.defaults = {
68 clientScripts: [], 68 clientScripts: [],
69 faultTolerant: true, 69 colorizerType: 'Colorizer',
70 exitOnError: true,
70 logLevel: "error", 71 logLevel: "error",
71 httpStatusHandlers: {}, 72 httpStatusHandlers: {},
72 onAlert: null, 73 onAlert: null,
...@@ -88,10 +89,12 @@ var Casper = function Casper(options) { ...@@ -88,10 +89,12 @@ var Casper = function Casper(options) {
88 timeout: null, 89 timeout: null,
89 verbose: false 90 verbose: false
90 }; 91 };
92 // options
93 this.options = utils.mergeObjects(this.defaults, options);
91 // properties 94 // properties
92 this.checker = null; 95 this.checker = null;
93 this.cli = phantom.casperArgs; 96 this.cli = phantom.casperArgs;
94 this.colorizer = colorizer.create(); 97 this.colorizer = this.getColorizer();
95 this.currentUrl = 'about:blank'; 98 this.currentUrl = 'about:blank';
96 this.currentHTTPStatus = 200; 99 this.currentHTTPStatus = 200;
97 this.defaultWaitTimeout = 5000; 100 this.defaultWaitTimeout = 5000;
...@@ -106,7 +109,6 @@ var Casper = function Casper(options) { ...@@ -106,7 +109,6 @@ var Casper = function Casper(options) {
106 error: 'ERROR' 109 error: 'ERROR'
107 }; 110 };
108 this.mouse = mouse.create(this); 111 this.mouse = mouse.create(this);
109 this.options = utils.mergeObjects(this.defaults, options);
110 this.page = null; 112 this.page = null;
111 this.pendingWait = false; 113 this.pendingWait = false;
112 this.requestUrl = 'about:blank'; 114 this.requestUrl = 'about:blank';
...@@ -121,10 +123,38 @@ var Casper = function Casper(options) { ...@@ -121,10 +123,38 @@ var Casper = function Casper(options) {
121 this.steps = []; 123 this.steps = [];
122 this.test = tester.create(this); 124 this.test = tester.create(this);
123 125
124 // basic event handlers 126 // init phantomjs error handler
127 this.initErrorHandler();
128
129 this.on('error', function(msg, backtrace) {
130 var c = this.getColorizer();
131 var match = /^(.*): __mod_error(.*):: (.*)/.exec(msg);
132 var notices = [];
133 if (match && match.length === 4) {
134 notices.push(' in module ' + match[2]);
135 notices.push(' NOTICE: errors within modules cannot be backtraced yet.');
136 msg = match[3];
137 }
138 console.error(c.colorize(msg, 'RED_BAR', 80));
139 notices.forEach(function(notice) {
140 console.error(c.colorize(notice, 'COMMENT'));
141 });
142 backtrace.forEach(function(item) {
143 var message = fs.absolute(item.file) + ":" + c.colorize(item.line, "COMMENT");
144 if (item['function']) {
145 message += " in " + c.colorize(item['function'], "PARAMETER");
146 }
147 console.error(" " + message);
148 });
149 });
150
151 // deprecated feature event handler
125 this.on('deprecated', function onDeprecated(message) { 152 this.on('deprecated', function onDeprecated(message) {
126 this.echo('[deprecated] ' + message, 'COMMENT'); 153 this.echo('[deprecated] ' + message, 'COMMENT');
127 }); 154 });
155
156 // dispatching an event when instance has been constructed
157 this.emit('init');
128 }; 158 };
129 159
130 // Casper class is an EventEmitter 160 // Casper class is an EventEmitter
...@@ -156,7 +186,6 @@ Casper.prototype.back = function back() { ...@@ -156,7 +186,6 @@ Casper.prototype.back = function back() {
156 * @return string Base64 encoded result 186 * @return string Base64 encoded result
157 */ 187 */
158 Casper.prototype.base64encode = function base64encode(url, method, data) { 188 Casper.prototype.base64encode = function base64encode(url, method, data) {
159 this.injectClientUtils();
160 return this.evaluate(function _evaluate(url, method, data) { 189 return this.evaluate(function _evaluate(url, method, data) {
161 return __utils__.getBase64(url, method, data); 190 return __utils__.getBase64(url, method, data);
162 }, { url: url, method: method, data: data }); 191 }, { url: url, method: method, data: data });
...@@ -227,11 +256,7 @@ Casper.prototype.checkStep = function checkStep(self, onComplete) { ...@@ -227,11 +256,7 @@ Casper.prototype.checkStep = function checkStep(self, onComplete) {
227 clearInterval(self.checker); 256 clearInterval(self.checker);
228 self.emit('run.complete'); 257 self.emit('run.complete');
229 if (utils.isFunction(onComplete)) { 258 if (utils.isFunction(onComplete)) {
230 try {
231 onComplete.call(self, self); 259 onComplete.call(self, self);
232 } catch (err) {
233 self.log("Could not complete final step: " + err, "error");
234 }
235 } else { 260 } else {
236 // default behavior is to exit 261 // default behavior is to exit
237 self.exit(); 262 self.exit();
...@@ -263,26 +288,19 @@ Casper.prototype.clear = function clear() { ...@@ -263,26 +288,19 @@ Casper.prototype.clear = function clear() {
263 * @return Boolean 288 * @return Boolean
264 */ 289 */
265 Casper.prototype.click = function click(selector) { 290 Casper.prototype.click = function click(selector) {
266 this.log("Click on selector: " + selector, "debug"); 291 return this.mouseEvent('click', selector);
267 if (arguments.length > 1) { 292 };
268 this.emit("deprecated", "The click() method does not process the fallbackToHref argument since 0.6"); 293
269 } 294 /**
270 if (!this.exists(selector)) { 295 * Emulates a click on the element having `label` as innerText. The first
271 throw new CasperError("Cannot click on unexistent selector: " + selector); 296 * element matching this label will be selected, so use with caution.
272 } 297 *
273 var clicked = this.evaluate(function _evaluate(selector) { 298 * @param String label Element innerText value
274 return __utils__.click(selector); 299 * @return Boolean
275 }, { selector: selector }); 300 */
276 if (!clicked) { 301 Casper.prototype.clickLabel = function clickLabel(label) {
277 // fallback onto native QtWebKit mouse events 302 var selector = exports.selectXPath('//*[text()="' + label.toString() + '"]');
278 try { 303 return this.click(selector);
279 this.mouse.click(selector);
280 } catch (e) {
281 this.log(f("Error while trying to click on selector %s: %s", selector, e), "error");
282 return false;
283 }
284 }
285 return true;
286 }; 304 };
287 305
288 /** 306 /**
...@@ -351,10 +369,10 @@ Casper.prototype.die = function die(message, status) { ...@@ -351,10 +369,10 @@ Casper.prototype.die = function die(message, status) {
351 * @param String targetPath The destination file path 369 * @param String targetPath The destination file path
352 * @return Casper 370 * @return Casper
353 */ 371 */
354 Casper.prototype.download = function download(url, targetPath) { 372 Casper.prototype.download = function download(url, targetPath, method, data) {
355 var cu = require('clientutils').create(); 373 var cu = require('clientutils').create();
356 try { 374 try {
357 fs.write(targetPath, cu.decode(this.base64encode(url)), 'w'); 375 fs.write(targetPath, cu.decode(this.base64encode(url, method, data)), 'wb');
358 this.emit('downloaded.file', targetPath); 376 this.emit('downloaded.file', targetPath);
359 this.log(f("Downloaded and saved resource in %s", targetPath)); 377 this.log(f("Downloaded and saved resource in %s", targetPath));
360 } catch (e) { 378 } catch (e) {
...@@ -422,6 +440,9 @@ Casper.prototype.echo = function echo(text, style, pad) { ...@@ -422,6 +440,9 @@ Casper.prototype.echo = function echo(text, style, pad) {
422 * @see WebPage#evaluate 440 * @see WebPage#evaluate
423 */ 441 */
424 Casper.prototype.evaluate = function evaluate(fn, context) { 442 Casper.prototype.evaluate = function evaluate(fn, context) {
443 // ensure client utils are always injected
444 this.injectClientUtils();
445 // function processing
425 context = utils.isObject(context) ? context : {}; 446 context = utils.isObject(context) ? context : {};
426 var newFn = require('injector').create(fn).process(context); 447 var newFn = require('injector').create(fn).process(context);
427 return this.page.evaluate(newFn); 448 return this.page.evaluate(newFn);
...@@ -533,7 +554,12 @@ Casper.prototype.fill = function fill(selector, vals, submit) { ...@@ -533,7 +554,12 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
533 var method = (form.getAttribute('method') || "GET").toUpperCase(); 554 var method = (form.getAttribute('method') || "GET").toUpperCase();
534 var action = form.getAttribute('action') || "unknown"; 555 var action = form.getAttribute('action') || "unknown";
535 __utils__.log('submitting form to ' + action + ', HTTP ' + method, 'info'); 556 __utils__.log('submitting form to ' + action + ', HTTP ' + method, 'info');
557 if (typeof form.submit === "function") {
536 form.submit(); 558 form.submit();
559 } else {
560 // http://www.spiration.co.uk/post/1232/Submit-is-not-a-function
561 form.submit.click();
562 }
537 }, { selector: selector }); 563 }, { selector: selector });
538 } 564 }
539 }; 565 };
...@@ -553,6 +579,16 @@ Casper.prototype.forward = function forward(then) { ...@@ -553,6 +579,16 @@ Casper.prototype.forward = function forward(then) {
553 }; 579 };
554 580
555 /** 581 /**
582 * Creates a new Colorizer instance. Sets `Casper.options.type` to change the
583 * colorizer type name (see the `colorizer` module).
584 *
585 * @return Object
586 */
587 Casper.prototype.getColorizer = function getColorizer() {
588 return colorizer.create(this.options.colorizerType || 'Colorizer');
589 };
590
591 /**
556 * Retrieves current document url. 592 * Retrieves current document url.
557 * 593 *
558 * @return String 594 * @return String
...@@ -621,11 +657,25 @@ Casper.prototype.getTitle = function getTitle() { ...@@ -621,11 +657,25 @@ Casper.prototype.getTitle = function getTitle() {
621 }; 657 };
622 658
623 /** 659 /**
660 * Initializes PhantomJS error handler.
661 *
662 */
663 Casper.prototype.initErrorHandler = function initErrorHandler() {
664 var casper = this;
665 phantom.onError = function phantom_onError(msg, backtrace) {
666 casper.emit('error', msg, backtrace);
667 if (casper.options.exitOnError === true) {
668 casper.exit(1);
669 }
670 };
671 };
672
673 /**
624 * Injects Client-side utilities in current page context. 674 * Injects Client-side utilities in current page context.
625 * 675 *
626 */ 676 */
627 Casper.prototype.injectClientUtils = function injectClientUtils() { 677 Casper.prototype.injectClientUtils = function injectClientUtils() {
628 var clientUtilsInjected = this.evaluate(function() { 678 var clientUtilsInjected = this.page.evaluate(function() {
629 return typeof __utils__ === "object"; 679 return typeof __utils__ === "object";
630 }); 680 });
631 if (true === clientUtilsInjected) { 681 if (true === clientUtilsInjected) {
...@@ -677,17 +727,36 @@ Casper.prototype.log = function log(message, level, space) { ...@@ -677,17 +727,36 @@ Casper.prototype.log = function log(message, level, space) {
677 }; 727 };
678 728
679 /** 729 /**
680 * Emulates a click on an HTML element matching a given CSS3 selector, 730 * Emulates an event on the element from the provided selector using the mouse
681 * using the mouse pointer. 731 * pointer, if possible.
682 * 732 *
733 * In case of success, `true` is returned, `false` otherwise.
734 *
735 * @param String type Type of event to emulate
683 * @param String selector A DOM CSS3 compatible selector 736 * @param String selector A DOM CSS3 compatible selector
684 * @return Casper 737 * @return Boolean
685 * @deprecated
686 * @since 0.6
687 */ 738 */
688 Casper.prototype.mouseClick = function mouseClick(selector) { 739 Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
689 this.emit("deprecated", "The mouseClick() method has been deprecated since 0.6; use click() instead"); 740 this.log("Mouse event '" + type + "' on selector: " + selector, "debug");
690 return this.click(selector); 741 if (!this.exists(selector)) {
742 throw new CasperError("Cannot dispatch an event on nonexistent selector: " + selector);
743 }
744 var eventSuccess = this.evaluate(function(type, selector) {
745 return __utils__.mouseEvent(type, selector);
746 }, {
747 type: type,
748 selector: selector
749 });
750 if (!eventSuccess) {
751 // fallback onto native QtWebKit mouse events
752 try {
753 this.mouse.processEvent(type, selector);
754 } catch (e) {
755 this.log(f("Couldn't emulate event '%s' on %s: %s", type, selector, e), "error");
756 return false;
757 }
758 }
759 return true;
691 }; 760 };
692 761
693 /** 762 /**
...@@ -737,10 +806,12 @@ Casper.prototype.open = function open(location, settings) { ...@@ -737,10 +806,12 @@ Casper.prototype.open = function open(location, settings) {
737 } 806 }
738 } 807 }
739 this.emit('open', this.requestUrl, settings); 808 this.emit('open', this.requestUrl, settings);
809 this.log(f('opening url: %s, HTTP %s', this.requestUrl, settings.method.toUpperCase()), "debug");
740 this.page.openUrl(this.requestUrl, { 810 this.page.openUrl(this.requestUrl, {
741 operation: settings.method, 811 operation: settings.method,
742 data: settings.data 812 data: settings.data
743 }, this.page.settings); 813 }, this.page.settings);
814 this.resources = [];
744 return this; 815 return this;
745 }; 816 };
746 817
...@@ -770,17 +841,18 @@ Casper.prototype.resourceExists = function resourceExists(test) { ...@@ -770,17 +841,18 @@ Casper.prototype.resourceExists = function resourceExists(test) {
770 var testFn; 841 var testFn;
771 switch (utils.betterTypeOf(test)) { 842 switch (utils.betterTypeOf(test)) {
772 case "string": 843 case "string":
773 testFn = function _test(res) { 844 testFn = function _testResourceExists_String(res) {
774 return res.url.search(test) !== -1; 845 return res.url.search(test) !== -1;
775 }; 846 };
776 break; 847 break;
777 case "regexp": 848 case "regexp":
778 testFn = function _test(res) { 849 testFn = function _testResourceExists_Regexp(res) {
779 return test.test(res.url); 850 return test.test(res.url);
780 }; 851 };
781 break; 852 break;
782 case "function": 853 case "function":
783 testFn = test; 854 testFn = test;
855 testFn.name = "_testResourceExists_Function";
784 break; 856 break;
785 default: 857 default:
786 throw new CasperError("Invalid type"); 858 throw new CasperError("Invalid type");
...@@ -834,16 +906,7 @@ Casper.prototype.runStep = function runStep(step) { ...@@ -834,16 +906,7 @@ Casper.prototype.runStep = function runStep(step) {
834 }, this.options.stepTimeout, this, new Date().getTime(), this.step); 906 }, this.options.stepTimeout, this, new Date().getTime(), this.step);
835 } 907 }
836 this.emit('step.start', step); 908 this.emit('step.start', step);
837 try {
838 stepResult = step.call(this, this); 909 stepResult = step.call(this, this);
839 } catch (e) {
840 this.emit('step.error', e);
841 if (this.options.faultTolerant) {
842 this.log("Step error: " + e, "error");
843 } else {
844 throw e;
845 }
846 }
847 if (utils.isFunction(this.options.onStepComplete)) { 910 if (utils.isFunction(this.options.onStepComplete)) {
848 this.options.onStepComplete.call(this, this, stepResult); 911 this.options.onStepComplete.call(this, this, stepResult);
849 } 912 }
...@@ -922,8 +985,8 @@ Casper.prototype.start = function start(location, then) { ...@@ -922,8 +985,8 @@ Casper.prototype.start = function start(location, then) {
922 }, this.options.timeout, this); 985 }, this.options.timeout, this);
923 } 986 }
924 if (utils.isString(location) && location.length > 0) { 987 if (utils.isString(location) && location.length > 0) {
925 return this.thenOpen(location, utils.isFunction(then) ? then : this.createStep(function _step(self) { 988 return this.thenOpen(location, utils.isFunction(then) ? then : this.createStep(function _step() {
926 self.log("start page is loaded", "debug"); 989 this.log("start page is loaded", "debug");
927 })); 990 }));
928 } 991 }
929 return this; 992 return this;
...@@ -1086,7 +1149,7 @@ Casper.prototype.wait = function wait(timeout, then) { ...@@ -1086,7 +1149,7 @@ Casper.prototype.wait = function wait(timeout, then) {
1086 return this.then(function _step() { 1149 return this.then(function _step() {
1087 this.waitStart(); 1150 this.waitStart();
1088 setTimeout(function _check(self) { 1151 setTimeout(function _check(self) {
1089 self.log(f("wait() finished wating for %dms.", timeout), "info"); 1152 self.log(f("wait() finished waiting for %dms.", timeout), "info");
1090 if (then) { 1153 if (then) {
1091 then.call(self, self); 1154 then.call(self, self);
1092 } 1155 }
...@@ -1294,7 +1357,6 @@ function createPage(casper) { ...@@ -1294,7 +1357,6 @@ function createPage(casper) {
1294 }; 1357 };
1295 page.onLoadStarted = function onLoadStarted() { 1358 page.onLoadStarted = function onLoadStarted() {
1296 casper.loadInProgress = true; 1359 casper.loadInProgress = true;
1297 casper.resources = [];
1298 casper.emit('load.started'); 1360 casper.emit('load.started');
1299 }; 1361 };
1300 page.onLoadFinished = function onLoadFinished(status) { 1362 page.onLoadFinished = function onLoadFinished(status) {
......
...@@ -29,13 +29,13 @@ ...@@ -29,13 +29,13 @@
29 */ 29 */
30 (function(exports) { 30 (function(exports) {
31 exports.create = function create() { 31 exports.create = function create() {
32 return new ClientUtils(); 32 return new this.ClientUtils();
33 }; 33 };
34 34
35 /** 35 /**
36 * Casper client-side helpers. 36 * Casper client-side helpers.
37 */ 37 */
38 ClientUtils = function ClientUtils() { 38 exports.ClientUtils = function ClientUtils() {
39 var BASE64_ENCODE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 39 var BASE64_ENCODE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
40 var BASE64_DECODE_CHARS = new Array( 40 var BASE64_DECODE_CHARS = new Array(
41 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
...@@ -56,16 +56,7 @@ ...@@ -56,16 +56,7 @@
56 * @return Boolean 56 * @return Boolean
57 */ 57 */
58 this.click = function click(selector) { 58 this.click = function click(selector) {
59 var elem = this.findOne(selector); 59 return this.mouseEvent('click', selector);
60 if (!elem) {
61 this.log("click(): Couldn't find any element matching '" + selector + "' selector", "error");
62 return false;
63 }
64 var evt = document.createEvent("MouseEvents");
65 evt.initMouseEvent("click", true, true, window, 1, 1, 1, 1, 1, false, false, false, false, 0, elem);
66 // dispatchEvent return value is false if at least one of the event
67 // handlers which handled this event called preventDefault
68 return elem.dispatchEvent(evt);
69 }; 60 };
70 61
71 /** 62 /**
...@@ -380,19 +371,6 @@ ...@@ -380,19 +371,6 @@
380 }; 371 };
381 372
382 /** 373 /**
383 * Removes all DOM elements matching a given XPath expression.
384 *
385 * @param String expression The XPath expression
386 * @return Array
387 */
388 this.removeElementsByXPath = function removeElementsByXPath(expression) {
389 var a = document.evaluate(expression, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
390 for (var i = 0; i < a.snapshotLength; i++) {
391 a.snapshotItem(i).parentNode.removeChild(a.snapshotItem(i));
392 }
393 };
394
395 /**
396 * 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
397 * to log phantomjs side. 375 * to log phantomjs side.
398 * 376 *
...@@ -404,6 +382,26 @@ ...@@ -404,6 +382,26 @@
404 }; 382 };
405 383
406 /** 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 /**
407 * Processes a selector input, either as a string or an object. 405 * Processes a selector input, either as a string or an object.
408 * 406 *
409 * If passed an object, if must be of the form: 407 * If passed an object, if must be of the form:
...@@ -420,7 +418,7 @@ ...@@ -420,7 +418,7 @@
420 this.processSelector = function processSelector(selector) { 418 this.processSelector = function processSelector(selector) {
421 var selectorObject = { 419 var selectorObject = {
422 toString: function toString() { 420 toString: function toString() {
423 return this.type + ' selector: ' + this.selector; 421 return this.type + ' selector: ' + this.path;
424 } 422 }
425 }; 423 };
426 if (typeof selector === "string") { 424 if (typeof selector === "string") {
...@@ -444,6 +442,19 @@ ...@@ -444,6 +442,19 @@
444 }; 442 };
445 443
446 /** 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 /**
447 * 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
448 * error messages. 459 * error messages.
449 * 460 *
...@@ -546,14 +557,19 @@ ...@@ -546,14 +557,19 @@
546 */ 557 */
547 this.visible = function visible(selector) { 558 this.visible = function visible(selector) {
548 try { 559 try {
549 var el = this.findOne(selector); 560 var comp,
550 return el && el.style.visibility !== 'hidden' && el.offsetHeight > 0 && el.offsetWidth > 0; 561 el = this.findOne(selector);
562
563 if (el) {
564 comp = window.getComputedStyle(el, null);
565 return comp.visibility !== 'hidden' && comp.display !== 'none' && el.offsetHeight > 0 && el.offsetWidth > 0;
566 }
567 return false;
551 } catch (e) { 568 } catch (e) {
552 return false; 569 return false;
553 } 570 }
554 }; 571 };
555 }; 572 };
556 exports.ClientUtils = ClientUtils;
557 573
558 // silly "hack" to force having an instance available 574 // silly "hack" to force having an instance available
559 exports.__utils__ = new exports.ClientUtils(); 575 exports.__utils__ = new exports.ClientUtils();
......
...@@ -31,13 +31,19 @@ ...@@ -31,13 +31,19 @@
31 var fs = require('fs'); 31 var fs = require('fs');
32 var utils = require('utils'); 32 var utils = require('utils');
33 33
34 exports.create = function create() { 34 exports.create = function create(type) {
35 return new Colorizer(); 35 if (!type) {
36 return;
37 }
38 if (!(type in exports)) {
39 throw new Error(utils.format('Unsupported colorizer type "%s"', type));
40 }
41 return new exports[type]();
36 }; 42 };
37 43
38 /** 44 /**
39 * This is a port of lime colorizer. 45 * This is a port of lime colorizer.
40 * http://trac.symfony-project.org/browser/tools/lime/trunk/lib/lime.php) 46 * http://trac.symfony-project.org/browser/tools/lime/trunk/lib/lime.php
41 * 47 *
42 * (c) Fabien Potencier, Symfony project, MIT license 48 * (c) Fabien Potencier, Symfony project, MIT license
43 */ 49 */
...@@ -102,3 +108,17 @@ var Colorizer = function Colorizer() { ...@@ -102,3 +108,17 @@ var Colorizer = function Colorizer() {
102 }; 108 };
103 }; 109 };
104 exports.Colorizer = Colorizer; 110 exports.Colorizer = Colorizer;
111
112 /**
113 * Dummy colorizer. Does basically nothing.
114 *
115 */
116 var Dummy = function Dummy() {
117 this.colorize = function colorize(text, styleName, pad) {
118 return text;
119 };
120 this.format = function format(text, style, pad){
121 return text;
122 };
123 };
124 exports.Dummy = Dummy;
......
...@@ -67,7 +67,9 @@ var FunctionArgsInjector = function FunctionArgsInjector(fn) { ...@@ -67,7 +67,9 @@ var FunctionArgsInjector = function FunctionArgsInjector(fn) {
67 throw new CasperError("Unable to process function " + this.fn.toString()); 67 throw new CasperError("Unable to process function " + this.fn.toString());
68 } 68 }
69 var inject = this.getArgsInjectionString(fnObj.args, values); 69 var inject = this.getArgsInjectionString(fnObj.args, values);
70 return 'function ' + (fnObj.name || '') + '(){' + inject + fnObj.body + '}'; 70 var newFn = new Function([inject, fnObj.body].join('\n'));
71 newFn.name = fnObj.name || '';
72 return newFn;
71 }; 73 };
72 74
73 this.getArgsInjectionString = function getArgsInjectionString(args, values) { 75 this.getArgsInjectionString = function getArgsInjectionString(args, values) {
......
...@@ -39,7 +39,11 @@ var Mouse = function Mouse(casper) { ...@@ -39,7 +39,11 @@ var Mouse = function Mouse(casper) {
39 throw new CasperError('Mouse() needs a Casper instance'); 39 throw new CasperError('Mouse() needs a Casper instance');
40 } 40 }
41 41
42 var supportedEvents = ['mouseup', 'mousedown', 'click', 'mousemove']; 42 var slice = Array.prototype.slice;
43
44 var nativeEvents = ['mouseup', 'mousedown', 'click', 'mousemove'];
45 var emulatedEvents = ['mouseover', 'mouseout'];
46 var supportedEvents = nativeEvents.concat(emulatedEvents);
43 47
44 function computeCenter(selector) { 48 function computeCenter(selector) {
45 var bounds = casper.getElementBounds(selector); 49 var bounds = casper.getElementBounds(selector);
...@@ -54,7 +58,10 @@ var Mouse = function Mouse(casper) { ...@@ -54,7 +58,10 @@ var Mouse = function Mouse(casper) {
54 if (!utils.isString(type) || supportedEvents.indexOf(type) === -1) { 58 if (!utils.isString(type) || supportedEvents.indexOf(type) === -1) {
55 throw new CasperError('Mouse.processEvent(): Unsupported mouse event type: ' + type); 59 throw new CasperError('Mouse.processEvent(): Unsupported mouse event type: ' + type);
56 } 60 }
57 args = Array.prototype.slice.call(args); // cast Arguments -> Array 61 if (emulatedEvents.indexOf(type) > -1) {
62 casper.log("Mouse.processEvent(): no native fallback for type " + type, "warning");
63 }
64 args = slice.call(args); // cast Arguments -> Array
58 casper.emit('mouse.' + type.replace('mouse', ''), args); 65 casper.emit('mouse.' + type.replace('mouse', ''), args);
59 switch (args.length) { 66 switch (args.length) {
60 case 0: 67 case 0:
...@@ -62,9 +69,6 @@ var Mouse = function Mouse(casper) { ...@@ -62,9 +69,6 @@ var Mouse = function Mouse(casper) {
62 case 1: 69 case 1:
63 // selector 70 // selector
64 var selector = args[0]; 71 var selector = args[0];
65 if (!utils.isString(selector)) {
66 throw new CasperError('Mouse.processEvent(): No valid CSS selector passed: ' + selector);
67 }
68 casper.page.sendEvent.apply(casper.page, [type].concat(computeCenter(selector))); 72 casper.page.sendEvent.apply(casper.page, [type].concat(computeCenter(selector)));
69 break; 73 break;
70 case 2: 74 case 2:
...@@ -79,6 +83,10 @@ var Mouse = function Mouse(casper) { ...@@ -79,6 +83,10 @@ var Mouse = function Mouse(casper) {
79 } 83 }
80 } 84 }
81 85
86 this.processEvent = function() {
87 processEvent(arguments[0], slice.call(arguments, 1));
88 };
89
82 this.click = function click() { 90 this.click = function click() {
83 processEvent('click', arguments); 91 processEvent('click', arguments);
84 }; 92 };
......
...@@ -66,9 +66,18 @@ var Tester = function Tester(casper, options) { ...@@ -66,9 +66,18 @@ var Tester = function Tester(casper, options) {
66 }; 66 };
67 67
68 // events 68 // events
69 casper.on('error', function(msg, backtrace) {
70 var line = 0;
71 try {
72 line = backtrace[0].line;
73 } catch (e) {}
74 this.test.uncaughtError(msg, this.test.currentTestFile, line);
75 this.test.done();
76 });
77
69 casper.on('step.error', function onStepError(e) { 78 casper.on('step.error', function onStepError(e) {
70 casper.test.fail(e); 79 this.test.uncaughtError(e, this.test.currentTestFile);
71 casper.test.done(); 80 this.test.done();
72 }); 81 });
73 82
74 this.on('success', function onSuccess(success) { 83 this.on('success', function onSuccess(success) {
...@@ -76,39 +85,49 @@ var Tester = function Tester(casper, options) { ...@@ -76,39 +85,49 @@ var Tester = function Tester(casper, options) {
76 }); 85 });
77 86
78 this.on('fail', function onFail(failure) { 87 this.on('fail', function onFail(failure) {
88 // export
79 this.exporter.addFailure(fs.absolute(failure.file), failure.message, failure.details || "test failed", failure.type || "unknown"); 89 this.exporter.addFailure(fs.absolute(failure.file), failure.message, failure.details || "test failed", failure.type || "unknown");
80 this.testResults.failures.push(failure); 90 this.testResults.failures.push(failure);
91 // special printing
92 if (failure.type) {
93 this.comment(' type: ' + failure.type);
94 }
95 if (failure.details) {
96 this.comment(' details: ' + failure.details);
97 }
98 if (failure.values && Object.keys(failure.values).length > 0) {
99 for (var name in failure.values) {
100 this.comment(' ' + name + ': ' + utils.serialize(failure.values[name]));
101 }
102 }
81 }); 103 });
82 104
83 // methods 105 // methods
84 /** 106 /**
85 * Asserts that a condition strictly resolves to true. 107 * Asserts that a condition strictly resolves to true. Also returns an
108 * "assertion object" containing useful informations about the test case
109 * results.
110 *
111 * This method is also used as the base one used for all other `assert*`
112 * family methods; supplementary informations are then passed using the
113 * `context` argument.
86 * 114 *
87 * @param Boolean subject 115 * @param Boolean subject The condition to test
88 * @param String message Test description 116 * @param String message Test description
117 * @param Object|null context Assertion context object (Optional)
118 * @return Object An assertion result object
89 */ 119 */
90 this.assert = this.assertTrue = function assert(subject, message) { 120 this.assert = this.assertTrue = function assert(subject, message, context) {
91 var status = this.options.passText, eventName; 121 return this.processAssertionResult(utils.mergeObjects({
92 if (subject === true) { 122 success: subject === true,
93 eventName = 'success';
94 style = 'INFO';
95 this.testResults.passed++;
96 } else {
97 eventName = 'fail';
98 status = this.options.failText;
99 style = 'RED_BAR';
100 this.testResults.failed++;
101 }
102 this.emit(eventName, {
103 type: "assert", 123 type: "assert",
104 details: "test failed", 124 details: "Subject's not a strict boolean true",
105 message: message, 125 message: message,
106 file: this.currentTestFile, 126 file: this.currentTestFile,
107 values: { 127 values: {
108 subject: subject 128 subject: subject
109 } 129 }
110 }); 130 }, context || {}));
111 casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' '));
112 }; 131 };
113 132
114 /** 133 /**
...@@ -116,27 +135,13 @@ var Tester = function Tester(casper, options) { ...@@ -116,27 +135,13 @@ var Tester = function Tester(casper, options) {
116 * 135 *
117 * @param Mixed subject The value to test 136 * @param Mixed subject The value to test
118 * @param Mixed expected The expected value 137 * @param Mixed expected The expected value
119 * @param String message Test description 138 * @param String message Test description (Optional)
139 * @return Object An assertion result object
120 */ 140 */
121 this.assertEquals = this.assertEqual = function assertEquals(subject, expected, message) { 141 this.assertEquals = this.assertEqual = function assertEquals(subject, expected, message) {
122 var eventName; 142 return this.assert(this.testEquals(subject, expected), message, {
123 message = message || "";
124 if (this.testEquals(subject, expected)) {
125 eventName = "success";
126 casper.echo(this.colorize(this.options.passText, 'INFO') + ' ' + this.formatMessage(message));
127 this.testResults.passed++;
128 } else {
129 eventName = "fail";
130 casper.echo(this.colorize(this.options.failText, 'RED_BAR') + ' ' + this.formatMessage(message, 'WARNING'));
131 this.comment(' got: ' + utils.serialize(subject));
132 this.comment(' expected: ' + utils.serialize(expected));
133 this.testResults.failed++;
134 }
135 this.emit(eventName, {
136 type: "assertEquals", 143 type: "assertEquals",
137 message: message, 144 details: "Subject didn't equal the expected value",
138 details: f("test failed; expected: %s; got: %s", expected, subject),
139 file: this.currentTestFile,
140 values: { 145 values: {
141 subject: subject, 146 subject: subject,
142 expected: expected 147 expected: expected
...@@ -149,27 +154,13 @@ var Tester = function Tester(casper, options) { ...@@ -149,27 +154,13 @@ var Tester = function Tester(casper, options) {
149 * 154 *
150 * @param Mixed subject The value to test 155 * @param Mixed subject The value to test
151 * @param Mixed expected The unwanted value 156 * @param Mixed expected The unwanted value
152 * @param String message Test description 157 * @param String|null message Test description (Optional)
158 * @return Object An assertion result object
153 */ 159 */
154 this.assertNotEquals = function assertNotEquals(subject, shouldnt, message) { 160 this.assertNotEquals = function assertNotEquals(subject, shouldnt, message) {
155 var eventName; 161 return this.assert(!this.testEquals(subject, shouldnt), message, {
156 message = message || "";
157 if (!this.testEquals(subject, shouldnt)) {
158 eventName = "success";
159 casper.echo(this.colorize(this.options.passText, 'INFO') + ' ' + this.formatMessage(message));
160 this.testResults.passed++;
161 } else {
162 eventName = "fail";
163 casper.echo(this.colorize(this.options.failText, 'RED_BAR') + ' ' + this.formatMessage(message, 'WARNING'));
164 this.comment(' got: ' + utils.serialize(subject));
165 this.comment(' shouldnt: ' + utils.serialize(shouldnt));
166 this.testResults.failed++;
167 }
168 this.emit(eventName, {
169 type: "assertNotEquals", 162 type: "assertNotEquals",
170 message: message, 163 details: "Subject actually equals to what it shouldn't be",
171 details: f("test failed; shouldnt: %s; got: %s", shouldnt, subject),
172 file: this.currentTestFile,
173 values: { 164 values: {
174 subject: subject, 165 subject: subject,
175 shouldnt: shouldnt 166 shouldnt: shouldnt
...@@ -182,10 +173,18 @@ var Tester = function Tester(casper, options) { ...@@ -182,10 +173,18 @@ var Tester = function Tester(casper, options) {
182 * 173 *
183 * @param Function fn A function to be evaluated in remote DOM 174 * @param Function fn A function to be evaluated in remote DOM
184 * @param String message Test description 175 * @param String message Test description
185 * @param Object context Object containing the parameters to inject into the function (optional) 176 * @param Object params Object containing the parameters to inject into the function (optional)
177 * @return Object An assertion result object
186 */ 178 */
187 this.assertEval = function assertEval(fn, message, context) { 179 this.assertEval = this.assertEvaluate = function assertEval(fn, message, params) {
188 return this.assert(casper.evaluate(fn, context), message); 180 return this.assert(casper.evaluate(fn, params), message, {
181 type: "assertEval",
182 details: "Function didn't evaluate to true",
183 values: {
184 fn: fn,
185 params: params
186 }
187 });
189 }; 188 };
190 189
191 /** 190 /**
...@@ -194,11 +193,22 @@ var Tester = function Tester(casper, options) { ...@@ -194,11 +193,22 @@ var Tester = function Tester(casper, options) {
194 * 193 *
195 * @param Function fn The function to be evaluated in remote DOM 194 * @param Function fn The function to be evaluated in remote DOM
196 * @param Boolean expected The expected value 195 * @param Boolean expected The expected value
197 * @param String message Test description 196 * @param String|null message Test description
198 * @param Object context Object containing the parameters to inject into the function (optional) 197 * @param Object|null params Object containing the parameters to inject into the function (optional)
199 */ 198 * @return Object An assertion result object
200 this.assertEvalEquals = this.assertEvalEqual = function assertEvalEquals(fn, expected, message, context) { 199 */
201 return this.assertEquals(casper.evaluate(fn, context), expected, message); 200 this.assertEvalEquals = this.assertEvalEqual = function assertEvalEquals(fn, expected, message, params) {
201 var subject = casper.evaluate(fn, params);
202 return this.assert(this.testEquals(subject, expected), message, {
203 type: "assertEvalEquals",
204 details: "Evaluated function didn't return the expected value",
205 values: {
206 fn: fn,
207 params: params,
208 subject: subject,
209 expected: expected
210 }
211 });
202 }; 212 };
203 213
204 /** 214 /**
...@@ -207,9 +217,16 @@ var Tester = function Tester(casper, options) { ...@@ -207,9 +217,16 @@ var Tester = function Tester(casper, options) {
207 * 217 *
208 * @param String selector Selector expression 218 * @param String selector Selector expression
209 * @param String message Test description 219 * @param String message Test description
220 * @return Object An assertion result object
210 */ 221 */
211 this.assertExists = this.assertExist = function assertExists(selector, message) { 222 this.assertExists = this.assertExist = this.assertSelectorExists = this.assertSelectorExist = function assertExists(selector, message) {
212 return this.assert(casper.exists(selector), message); 223 return this.assert(casper.exists(selector), message, {
224 type: "assertExists",
225 details: f("No element matching selector %s was found", selector),
226 values: {
227 selector: selector
228 }
229 });
213 }; 230 };
214 231
215 /** 232 /**
...@@ -218,9 +235,16 @@ var Tester = function Tester(casper, options) { ...@@ -218,9 +235,16 @@ var Tester = function Tester(casper, options) {
218 * 235 *
219 * @param String selector Selector expression 236 * @param String selector Selector expression
220 * @param String message Test description 237 * @param String message Test description
238 * @return Object An assertion result object
221 */ 239 */
222 this.assertDoesntExist = this.assertNotExists = function assertDoesntExist(selector, message) { 240 this.assertDoesntExist = this.assertNotExists = function assertDoesntExist(selector, message) {
223 return this.assertNot(casper.exists(selector), message); 241 return this.assert(!casper.exists(selector), message, {
242 type: "assertDoesntExist",
243 details: f("At least one element matching selector %s was found", selector),
244 values: {
245 selector: selector
246 }
247 });
224 }; 248 };
225 249
226 /** 250 /**
...@@ -228,9 +252,18 @@ var Tester = function Tester(casper, options) { ...@@ -228,9 +252,18 @@ var Tester = function Tester(casper, options) {
228 * 252 *
229 * @param Number status HTTP status code 253 * @param Number status HTTP status code
230 * @param String message Test description 254 * @param String message Test description
255 * @return Object An assertion result object
231 */ 256 */
232 this.assertHttpStatus = function assertHttpStatus(status, message) { 257 this.assertHttpStatus = function assertHttpStatus(status, message) {
233 return this.assertEquals(casper.currentHTTPStatus, status, message || f("HTTP status code is %d", status)); 258 var currentHTTPStatus = casper.currentHTTPStatus;
259 return this.assert(this.testEquals(casper.currentHTTPStatus, status), message, {
260 type: "assertHttpStatus",
261 details: f("HTTP status code is not %s, but %s", status, currentHTTPStatus),
262 values: {
263 current: currentHTTPStatus,
264 expected: status
265 }
266 });
234 }; 267 };
235 268
236 /** 269 /**
...@@ -239,25 +272,12 @@ var Tester = function Tester(casper, options) { ...@@ -239,25 +272,12 @@ var Tester = function Tester(casper, options) {
239 * @param String subject The string to test 272 * @param String subject The string to test
240 * @param RegExp pattern A RegExp object instance 273 * @param RegExp pattern A RegExp object instance
241 * @param String message Test description 274 * @param String message Test description
275 * @return Object An assertion result object
242 */ 276 */
243 this.assertMatch = this.assertMatches = function assertMatch(subject, pattern, message) { 277 this.assertMatch = this.assertMatches = function assertMatch(subject, pattern, message) {
244 var eventName; 278 return this.assert(pattern.test(subject), message, {
245 if (pattern.test(subject)) {
246 eventName = "success";
247 casper.echo(this.colorize(this.options.passText, 'INFO') + ' ' + this.formatMessage(message));
248 this.testResults.passed++;
249 } else {
250 eventName = "fail";
251 casper.echo(this.colorize(this.options.failText, 'RED_BAR') + ' ' + this.formatMessage(message, 'WARNING'));
252 this.comment(' subject: ' + subject);
253 this.comment(' pattern: ' + pattern.toString());
254 this.testResults.failed++;
255 }
256 this.emit(eventName, {
257 type: "assertMatch", 279 type: "assertMatch",
258 message: message, 280 details: "Subject didn't match the provided pattern",
259 details: f("test failed; subject: %s; pattern: %s", subject, pattern.toString()),
260 file: this.currentTestFile,
261 values: { 281 values: {
262 subject: subject, 282 subject: subject,
263 pattern: pattern 283 pattern: pattern
...@@ -268,11 +288,18 @@ var Tester = function Tester(casper, options) { ...@@ -268,11 +288,18 @@ var Tester = function Tester(casper, options) {
268 /** 288 /**
269 * Asserts a condition resolves to false. 289 * Asserts a condition resolves to false.
270 * 290 *
271 * @param Boolean condition 291 * @param Boolean condition The condition to test
272 * @param String message Test description 292 * @param String message Test description
293 * @return Object An assertion result object
273 */ 294 */
274 this.assertNot = function assertNot(condition, message) { 295 this.assertNot = function assertNot(condition, message) {
275 return this.assert(!condition, message); 296 return this.assert(!condition, message, {
297 type: "assertNot",
298 details: "The condition is not falsy",
299 values: {
300 condition: condition
301 }
302 });
276 }; 303 };
277 304
278 /** 305 /**
...@@ -282,13 +309,22 @@ var Tester = function Tester(casper, options) { ...@@ -282,13 +309,22 @@ var Tester = function Tester(casper, options) {
282 * @param Function fn The function to test 309 * @param Function fn The function to test
283 * @param Array args The arguments to pass to the function 310 * @param Array args The arguments to pass to the function
284 * @param String message Test description 311 * @param String message Test description
312 * @return Object An assertion result object
285 */ 313 */
286 this.assertRaises = this.assertRaise = function assertRaises(fn, args, message) { 314 this.assertRaises = this.assertRaise = this.assertThrows = function assertRaises(fn, args, message) {
315 var context = {
316 type: "assertRaises",
317 details: "Function didn't raise any error"
318 };
287 try { 319 try {
288 fn.apply(null, args); 320 fn.apply(null, args);
289 this.fail(message); 321 this.assert(false, message, context);
290 } catch (e) { 322 } catch (error) {
291 this.pass(message); 323 this.assert(true, message, utils.mergeObjects(context, {
324 values: {
325 error: error
326 }
327 }));
292 } 328 }
293 }; 329 };
294 330
...@@ -297,20 +333,16 @@ var Tester = function Tester(casper, options) { ...@@ -297,20 +333,16 @@ var Tester = function Tester(casper, options) {
297 * 333 *
298 * @param Function/String test A test function that is called with every response 334 * @param Function/String test A test function that is called with every response
299 * @param String message Test description 335 * @param String message Test description
336 * @return Object An assertion result object
300 */ 337 */
301 this.assertResourceExists = this.assertResourceExist = function assertResourceExists(test, message) { 338 this.assertResourceExists = this.assertResourceExist = function assertResourceExists(test, message) {
302 return this.assert(casper.resourceExists(test), message); 339 return this.assert(casper.resourceExists(test), message, {
303 }; 340 type: "assertResourceExists",
304 341 details: "Resource was not found",
305 /** 342 values: {
306 * Asserts that at least an element matching the provided selector expression 343 test: test
307 * exists in remote DOM. 344 }
308 * 345 });
309 * @param String selector A selector expression string
310 * @param String message Test description
311 */
312 this.assertSelectorExists = this.assertSelectorExist = function assertSelectorExists(selector, message) {
313 return this.assert(casper.exists(selector), message);
314 }; 346 };
315 347
316 /** 348 /**
...@@ -318,11 +350,19 @@ var Tester = function Tester(casper, options) { ...@@ -318,11 +350,19 @@ var Tester = function Tester(casper, options) {
318 * 350 *
319 * @param String text Text to be found 351 * @param String text Text to be found
320 * @param String message Test description 352 * @param String message Test description
353 * @return Object An assertion result object
321 */ 354 */
322 this.assertTextExists = this.assertTextExist = function assertTextExists(text, message) { 355 this.assertTextExists = this.assertTextExist = function assertTextExists(text, message) {
323 return this.assert((casper.evaluate(function _evaluate() { 356 var textFound = (casper.evaluate(function _evaluate() {
324 return document.body.innerText; 357 return document.body.innerText;
325 }).indexOf(text) != -1), message); 358 }).indexOf(text) != -1);
359 return this.assert(textFound, message, {
360 type: "assertTextExists",
361 details: "Text was not found within the document body textual contents",
362 values: {
363 text: text
364 }
365 });
326 }; 366 };
327 367
328 /** 368 /**
...@@ -330,20 +370,39 @@ var Tester = function Tester(casper, options) { ...@@ -330,20 +370,39 @@ var Tester = function Tester(casper, options) {
330 * 370 *
331 * @param String expected The expected title string 371 * @param String expected The expected title string
332 * @param String message Test description 372 * @param String message Test description
373 * @return Object An assertion result object
333 */ 374 */
334 this.assertTitle = function assertTitle(expected, message) { 375 this.assertTitle = function assertTitle(expected, message) {
335 return this.assertEquals(casper.getTitle(), expected, message); 376 var currentTitle = casper.getTitle();
377 return this.assert(this.testEquals(currentTitle, expected), message, {
378 type: "assertTitle",
379 details: "Page title is not the one expected",
380 values: {
381 subject: currentTitle,
382 expected: expected
383 }
384 });
336 }; 385 };
337 386
338 /** 387 /**
339 * Asserts that the provided input is of the given type. 388 * Asserts that the provided subject is of the given type.
340 * 389 *
341 * @param mixed input The value to test 390 * @param mixed subject The value to test
342 * @param String type The javascript type name 391 * @param String type The javascript type name
343 * @param String message Test description 392 * @param String message Test description
393 * @return Object An assertion result object
344 */ 394 */
345 this.assertType = function assertType(input, type, message) { 395 this.assertType = function assertType(subject, type, message) {
346 return this.assertEquals(utils.betterTypeOf(input), type, message); 396 var actual = utils.betterTypeOf(subject);
397 return this.assert(this.testEquals(actual, type), message, {
398 type: "assertType",
399 details: f("Expected type %s, got %s", typeof subject, actual),
400 values: {
401 subject: subject,
402 type: type,
403 actual: actual
404 }
405 });
347 }; 406 };
348 407
349 /** 408 /**
...@@ -352,11 +411,24 @@ var Tester = function Tester(casper, options) { ...@@ -352,11 +411,24 @@ var Tester = function Tester(casper, options) {
352 * 411 *
353 * @param RegExp pattern A RegExp object instance 412 * @param RegExp pattern A RegExp object instance
354 * @param String message Test description 413 * @param String message Test description
414 * @return Object An assertion result object
355 */ 415 */
356 this.assertUrlMatch = this.assertUrlMatches = function assertUrlMatch(pattern, message) { 416 this.assertUrlMatch = this.assertUrlMatches = function assertUrlMatch(pattern, message) {
357 return this.assertMatch(casper.getCurrentUrl(), pattern, message); 417 var currentUrl = casper.getCurrentUrl();
418 return this.assert(pattern.test(currentUrl), message, {
419 type: "assertUrlMatch",
420 details: "Current url did not match the provided pattern",
421 values: {
422 currentUrl: currentUrl,
423 pattern: pattern
424 }
425 });
358 }; 426 };
359 427
428 /**
429 * Prints out a colored bar onto the console.
430 *
431 */
360 this.bar = function bar(text, style) { 432 this.bar = function bar(text, style) {
361 casper.echo(text, style, this.options.pad); 433 casper.echo(text, style, this.options.pad);
362 }; 434 };
...@@ -409,14 +481,7 @@ var Tester = function Tester(casper, options) { ...@@ -409,14 +481,7 @@ var Tester = function Tester(casper, options) {
409 throw e; 481 throw e;
410 } 482 }
411 this.currentTestFile = file; 483 this.currentTestFile = file;
412 try { 484 phantom.injectJs(file);
413 new Function('casper', phantom.getScriptCode(file))(casper);
414 } catch (e) {
415 // do not abort the whole suite, just fail fast displaying the
416 // caught error and process next suite
417 this.fail(e);
418 this.done();
419 }
420 }; 485 };
421 486
422 /** 487 /**
...@@ -425,7 +490,10 @@ var Tester = function Tester(casper, options) { ...@@ -425,7 +490,10 @@ var Tester = function Tester(casper, options) {
425 * @param String message 490 * @param String message
426 */ 491 */
427 this.fail = function fail(message) { 492 this.fail = function fail(message) {
428 this.assert(false, message); 493 return this.assert(false, message, {
494 type: "fail",
495 details: "explicit call to fail()"
496 });
429 }; 497 };
430 498
431 /** 499 /**
...@@ -482,7 +550,35 @@ var Tester = function Tester(casper, options) { ...@@ -482,7 +550,35 @@ var Tester = function Tester(casper, options) {
482 * @param String message 550 * @param String message
483 */ 551 */
484 this.pass = function pass(message) { 552 this.pass = function pass(message) {
485 this.assert(true, message); 553 return this.assert(true, message, {
554 type: "pass",
555 details: "explicit call to pass()"
556 });
557 };
558
559 /**
560 * Processes an assertion result by emitting the appropriate event and
561 * printing result onto the console.
562 *
563 * @param Object result An assertion result object
564 * @return Object The passed assertion result Object
565 */
566 this.processAssertionResult = function processAssertionResult(result) {
567 var eventName, style, status;
568 if (result.success === true) {
569 eventName = 'success';
570 style = 'INFO';
571 status = this.options.passText;
572 this.testResults.passed++;
573 } else {
574 eventName = 'fail';
575 style = 'RED_BAR';
576 status = this.options.failText;
577 this.testResults.failed++;
578 }
579 casper.echo([this.colorize(status, style), this.formatMessage(result.message)].join(' '));
580 this.emit(eventName, result);
581 return result;
486 }; 582 };
487 583
488 /** 584 /**
...@@ -496,16 +592,12 @@ var Tester = function Tester(casper, options) { ...@@ -496,16 +592,12 @@ var Tester = function Tester(casper, options) {
496 } 592 }
497 casper.echo(f("\nDetails for the %d failed test%s:\n", failures.length, failures.length > 1 ? "s" : ""), "PARAMETER"); 593 casper.echo(f("\nDetails for the %d failed test%s:\n", failures.length, failures.length > 1 ? "s" : ""), "PARAMETER");
498 failures.forEach(function _forEach(failure) { 594 failures.forEach(function _forEach(failure) {
499 var message, line; 595 var type, message, line;
500 if (utils.isType(failure.message, "object") && failure.message.stack) { 596 type = failure.type || "unknown";
501 line = failure.message.line ? failure.message.line : 0; 597 line = ~~failure.line;
502 message = failure.message.stack;
503 } else {
504 line = 0;
505 message = failure.message; 598 message = failure.message;
506 } 599 casper.echo(f('In %s:%s', failure.file, line));
507 casper.echo(f('In %s:%d', failure.file, line)); 600 casper.echo(f(' %s: %s', type, message || "(no message was entered)"), "COMMENT");
508 casper.echo(f(' %s', message), "COMMENT");
509 }); 601 });
510 }; 602 };
511 603
...@@ -595,12 +687,7 @@ var Tester = function Tester(casper, options) { ...@@ -595,12 +687,7 @@ var Tester = function Tester(casper, options) {
595 this.runTest = function runTest(testFile) { 687 this.runTest = function runTest(testFile) {
596 this.bar(f('Test file: %s', testFile), 'INFO_BAR'); 688 this.bar(f('Test file: %s', testFile), 'INFO_BAR');
597 this.running = true; // this.running is set back to false with done() 689 this.running = true; // this.running is set back to false with done()
598 try {
599 this.exec(testFile); 690 this.exec(testFile);
600 } catch (e) {
601 this.fail(e);
602 this.done();
603 }
604 }; 691 };
605 692
606 /** 693 /**
...@@ -630,6 +717,27 @@ var Tester = function Tester(casper, options) { ...@@ -630,6 +717,27 @@ var Tester = function Tester(casper, options) {
630 } 717 }
631 return v1 === v2; 718 return v1 === v2;
632 }; 719 };
720
721 /**
722 * Processes an error caught while running tests contained in a given test
723 * file.
724 *
725 * @param Error|String error The error
726 * @param String file Test file where the error occured
727 * @param Number line Line number (optional)
728 */
729 this.uncaughtError = function uncaughtError(error, file, line) {
730 return this.processAssertionResult({
731 success: false,
732 type: "uncaughtError",
733 file: file,
734 line: ~~line || "unknown",
735 message: utils.isObject(error) ? error.message : error,
736 values: {
737 error: error
738 }
739 });
740 };
633 }; 741 };
634 742
635 // Tester class is an EventEmitter 743 // Tester class is an EventEmitter
......
...@@ -131,27 +131,22 @@ function format(f) { ...@@ -131,27 +131,22 @@ function format(f) {
131 exports.format = format; 131 exports.format = format;
132 132
133 /** 133 /**
134 * Inherit the prototype methods from one constructor into another, also 134 * Inherit the prototype methods from one constructor into another.
135 * exposes the `__super__` property to child class.
136 * 135 *
137 * @param Function child Constructor function which needs to inherit the 136 * @param {function} ctor Constructor function which needs to inherit the
138 * prototype. 137 * prototype.
139 * @param Function parent Constructor function to inherit prototype from. 138 * @param {function} superCtor Constructor function to inherit prototype from.
140 * @return Function The child class
141 */ 139 */
142 function inherits(child, parent) { 140 function inherits(ctor, superCtor) {
143 for (var key in parent) { 141 ctor.super_ = ctor.__super__ = superCtor;
144 if (Object.prototype.hasOwnProperty.call(parent, key)) { 142 ctor.prototype = Object.create(superCtor.prototype, {
145 child[key] = parent[key]; 143 constructor: {
144 value: ctor,
145 enumerable: false,
146 writable: true,
147 configurable: true
146 } 148 }
147 } 149 });
148 function ctor() {
149 this.constructor = child;
150 }
151 ctor.prototype = parent.prototype;
152 child.prototype = new ctor();
153 child.__super__ = parent.prototype;
154 return child;
155 } 150 }
156 exports.inherits = inherits; 151 exports.inherits = inherits;
157 152
...@@ -305,23 +300,23 @@ exports.isWebPage = isWebPage; ...@@ -305,23 +300,23 @@ exports.isWebPage = isWebPage;
305 /** 300 /**
306 * Object recursive merging utility. 301 * Object recursive merging utility.
307 * 302 *
308 * @param Object obj1 the destination object 303 * @param Object origin the origin object
309 * @param Object obj2 the source object 304 * @param Object add the object to merge data into origin
310 * @return Object 305 * @return Object
311 */ 306 */
312 function mergeObjects(obj1, obj2) { 307 function mergeObjects(origin, add) {
313 for (var p in obj2) { 308 for (var p in add) {
314 try { 309 try {
315 if (obj2[p].constructor === Object) { 310 if (add[p].constructor === Object) {
316 obj1[p] = mergeObjects(obj1[p], obj2[p]); 311 origin[p] = mergeObjects(origin[p], add[p]);
317 } else { 312 } else {
318 obj1[p] = obj2[p]; 313 origin[p] = add[p];
319 } 314 }
320 } catch(e) { 315 } catch(e) {
321 obj1[p] = obj2[p]; 316 origin[p] = add[p];
322 } 317 }
323 } 318 }
324 return obj1; 319 return origin;
325 } 320 }
326 exports.mergeObjects = mergeObjects; 321 exports.mergeObjects = mergeObjects;
327 322
......
1 { 1 {
2 "name": "casperjs", 2 "name": "casperjs",
3 "description": "Navigation scripting & testing utility for PhantomJS", 3 "description": "Navigation scripting & testing utility for PhantomJS",
4 "version": "0.6.8", 4 "version": "0.6.10",
5 "keywords": [ 5 "keywords": [
6 "phantomjs", 6 "phantomjs",
7 "javascript" 7 "javascript"
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
14 } 14 }
15 ], 15 ],
16 "dependencies": { 16 "dependencies": {
17 "http://www.phantomjs.org/": "1.3" 17 "http://www.phantomjs.org/": "1.5"
18 }, 18 },
19 "bugs": { 19 "bugs": {
20 "url": "https://github.com/n1k0/casperjs/issues" 20 "url": "https://github.com/n1k0/casperjs/issues"
......
1 casper = require("casper").create() 1 casper = require("casper").create()
2 2
3 ### listening to a custom event ### 3 # listening to a custom event
4 casper.on "google.loaded", (title) -> 4 casper.on "google.loaded", (title) ->
5 casper.echo "Google page title is #{title}" 5 @echo "Google page title is #{title}"
6 6
7 casper.start "http://google.com/", -> 7 casper.start "http://google.com/", ->
8 ### emitting a custom event ### 8 # emitting a custom event
9 @emit "google.loaded", @getTitle() 9 @emit "google.loaded", @getTitle()
10 10
11 casper.run() 11 casper.run()
......
1 var casper; 1 var casper = require("casper").create();
2 2
3 casper = require("casper").create(); 3 // listening to a custom event
4
5 /* listening to a custom event */
6 casper.on("google.loaded", function(title) { 4 casper.on("google.loaded", function(title) {
7 casper.echo("Google page title is " + title); 5 this.echo("Google page title is " + title);
8 }); 6 });
9 7
10 casper.start("http://google.com/", function() { 8 casper.start("http://google.com/", function() {
11 /* emitting a custom event */ 9 // emitting a custom event
12 this.emit("google.loaded", this.getTitle()); 10 this.emit("google.loaded", this.getTitle());
13 }); 11 });
14 12
......
1 ### 1 ###
2 A basic custom logging implementation. The idea is to (extremely) verbosely log 2 A basic custom logging implementation. The idea is to (extremely) verbosely
3 every received resource. 3 log every received resource.
4 ### 4 ###
5 5
6 casper = require("casper").create 6 casper = require("casper").create
7 ### 7 ###
8 Every time a resource is received, a new log entry is added to the stack at 8 Every time a resource is received, a new log entry is added to the stack
9 the 'verbose' level. 9 at the 'verbose' level.
10
11 @param Object resource A phantomjs resource object
10 ### 12 ###
11 onResourceReceived: (self, resource) -> 13 onResourceReceived: (self, resource) ->
12 infos = [] 14 infos = []
...@@ -23,9 +25,9 @@ casper = require("casper").create ...@@ -23,9 +25,9 @@ casper = require("casper").create
23 verbose: true # we want to see the log printed out to the console 25 verbose: true # we want to see the log printed out to the console
24 logLevel: "verbose" # of course we want to see logs to our new level :) 26 logLevel: "verbose" # of course we want to see logs to our new level :)
25 27
26 ### add a new 'verbose' logging level at the lowest priority ### 28 # add a new 'verbose' logging level at the lowest priority
27 casper.logLevels = ["verbose"].concat casper.logLevels 29 casper.logLevels = ["verbose"].concat casper.logLevels
28 30
29 ### test our new logger with google ### 31 # test our new logger with google
30 casper.start "http://www.google.com/" 32 casper.start("http://www.google.com/").run ->
31 casper.run() 33 @exit()
......
1 /* 1 /*
2 A basic custom logging implementation. The idea is to (extremely) verbosely log 2 * A basic custom logging implementation. The idea is to (extremely) verbosely
3 every received resource. 3 * log every received resource.
4 */ 4 */
5
6 var casper;
7 5
8 casper = require("casper").create({ 6 var casper = require("casper").create({
9 /* 7 /*
10 Every time a resource is received, a new log entry is added to the stack at 8 Every time a resource is received, a new log entry is added to the stack at
11 the 'verbose' level. 9 the 'verbose' level.
...@@ -38,7 +36,7 @@ casper = require("casper").create({ ...@@ -38,7 +36,7 @@ casper = require("casper").create({
38 /* add a new 'verbose' logging level at the lowest priority */ 36 /* add a new 'verbose' logging level at the lowest priority */
39 casper.logLevels = ["verbose"].concat(casper.logLevels); 37 casper.logLevels = ["verbose"].concat(casper.logLevels);
40 38
41 /* test our new logger with google */
42 casper.start("http://www.google.com/");
43
44 casper.run();
...\ No newline at end of file ...\ No newline at end of file
39 // test our new logger with google
40 casper.start("http://www.google.com/").run(function() {
41 this.exit();
42 });
......
1 ### 1 ###
2 Download the google logo image as base64 2 Download the google logo image onto the local filesystem
3 ### 3 ###
4 4
5 casper = require("casper").create verbose: true 5 casper = require("casper").create()
6 6
7 casper.start "http://www.google.fr/", -> 7 casper.start "http://www.google.fr/", ->
8 @echo @base64encode "http://www.google.fr/images/srpr/logo3w.png" 8 @echo @download "http://www.google.fr/images/srpr/logo3w.png", "logo.png"
9 9
10 casper.run() 10 casper.run()
......
1 /* 1 /*
2 Download the google logo image as base64 2 * download the google logo image onto the local filesystem
3 */ 3 */
4 4
5 var casper; 5 var casper = require("casper").create();
6
7 casper = require("casper").create({
8 verbose: true
9 });
10 6
11 casper.start("http://www.google.fr/", function() { 7 casper.start("http://www.google.fr/", function() {
12 this.echo(this.base64encode("http://www.google.fr/images/srpr/logo3w.png")); 8 this.download("http://www.google.fr/images/srpr/logo3w.png", "logo.png");
13 }); 9 });
14 10
15 casper.run(); 11 casper.run();
......
...@@ -29,21 +29,18 @@ links = [ ...@@ -29,21 +29,18 @@ links = [
29 "http://bing.com/" 29 "http://bing.com/"
30 ]; 30 ];
31 31
32 /* Just opens the page and prints the title */ 32 // Just opens the page and prints the title
33 start = function(link) { 33 var start = function(link) {
34 this.start(link, function() { 34 this.start(link, function() {
35 this.echo("Page title: " + this.getTitle()); 35 this.echo('Page title: ' + this.getTitle());
36 }); 36 });
37 }; 37 };
38 38
39 /* 39 // Get the links, and add them to the links array
40 Get the links, and add them to the links array 40 // (It could be done all in one step, but it is intentionally splitted)
41 (It could be done all in one step, but it is intentionally splitted) 41 var addLinks = function(link) {
42 */
43 addLinks = function(link) {
44 this.then(function() { 42 this.then(function() {
45 var found; 43 var found = this.evaluate(searchLinks);
46 found = this.evaluate(searchLinks);
47 this.echo(found.length + " links found on " + link); 44 this.echo(found.length + " links found on " + link);
48 links = links.concat(found); 45 links = links.concat(found);
49 }); 46 });
...@@ -57,10 +54,10 @@ casper.then(function() { ...@@ -57,10 +54,10 @@ casper.then(function() {
57 54
58 currentLink = 0; 55 currentLink = 0;
59 56
60 /* As long as it has a next link, and is under the maximum limit, will keep running */ 57 // As long as it has a next link, and is under the maximum limit, will keep running
61 check = function() { 58 function check() {
62 if (links[currentLink] && currentLink < upTo) { 59 if (links[currentLink] && currentLink < upTo) {
63 this.echo("--- Link " + currentLink + " ---"); 60 this.echo('--- Link ' + currentLink + ' ---');
64 start.call(this, links[currentLink]); 61 start.call(this, links[currentLink]);
65 addLinks.call(this, links[currentLink]); 62 addLinks.call(this, links[currentLink]);
66 currentLink++; 63 currentLink++;
......
1 getLinks = -> 1 getLinks = ->
2 links = document.querySelectorAll "h3.r a" 2 links = document.querySelectorAll("h3.r a")
3 Array::map.call links, (e) -> e.getAttribute "href" 3 Array::map.call links, (e) ->
4 4 e.getAttribute "href"
5 links = []
6 casper = require("casper").create()
7 5
8 casper.start "http://google.fr/", -> 6 casper.start "http://google.fr/", ->
9 ### search for 'casperjs' from google form ### 7 # search for 'casperjs' from google form
10 @fill 'form[action="/search"]', q: "casperjs", true 8 @fill "form[action=\"/search\"]", q: "casperjs" , true
11 9
12 casper.then -> 10 casper.then ->
13 ### aggregate results for the 'casperjs' search ### 11 # aggregate results for the 'casperjs' search
14 links = @evaluate getLinks 12 links = @evaluate(getLinks)
15 ### search for 'phantomjs' from google form ### 13 # now search for 'phantomjs' by fillin the form again
16 @fill 'form[action="/search"]', q: "phantomjs", true 14 @fill "form[action=\"/search\"]", q: "phantomjs" , true
17 15
18 casper.then -> 16 casper.then ->
19 ### concat results for the 'phantomjs' search ### 17 # aggregate results for the 'phantomjs' search
20 links = links.concat @evaluate(getLinks) 18 links = links.concat(@evaluate(getLinks))
21 19
22 casper.run -> 20 casper.run ->
23 ### display results ### 21 # echo results in some pretty fashion
24 @echo "#{links.length} links found:" 22 @echo links.length + " links found:"
25 @echo " - " + links.join "\n - " 23 @echo(" - " + links.join("\n - "))
26 @exit() 24 @exit()
......
1 var casper, getLinks, links; 1 var casper, getLinks, links;
2 2
3 getLinks = function() { 3 getLinks = function() {
4 var links; 4 var links = document.querySelectorAll("h3.r a");
5 links = document.querySelectorAll("h3.r a");
6 return Array.prototype.map.call(links, function(e) { 5 return Array.prototype.map.call(links, function(e) {
7 return e.getAttribute("href"); 6 return e.getAttribute("href");
8 }); 7 });
9 }; 8 };
10 9
11 links = [];
12
13 casper = require("casper").create();
14
15 casper.start("http://google.fr/", function() { 10 casper.start("http://google.fr/", function() {
16 /* search for 'casperjs' from google form */ 11 // search for 'casperjs' from google form
17 this.fill('form[action="/search"]', { 12 this.fill('form[action="/search"]', { q: "casperjs" }, true);
18 q: "casperjs"
19 }, true);
20 }); 13 });
21 14
22 casper.then(function() { 15 casper.then(function() {
23 /* aggregate results for the 'casperjs' search */ 16 // aggregate results for the 'casperjs' search
24 links = this.evaluate(getLinks); 17 links = this.evaluate(getLinks);
25 /* search for 'phantomjs' from google form */ 18 // now search for 'phantomjs' by fillin the form again
26 this.fill('form[action="/search"]', { 19 this.fill('form[action="/search"]', { q: "phantomjs" }, true);
27 q: "phantomjs"
28 }, true);
29 }); 20 });
30 21
31 casper.then(function() { 22 casper.then(function() {
32 /* concat results for the 'phantomjs' search */ 23 // aggregate results for the 'phantomjs' search
33 links = links.concat(this.evaluate(getLinks)); 24 links = links.concat(this.evaluate(getLinks));
34 }); 25 });
35 26
36 casper.run(function() { 27 casper.run(function() {
37 /* display results */ 28 // echo results in some pretty fashion
38 this.echo(links.length + " links found:"); 29 this.echo(links.length + " links found:");
39 this.echo(" - " + links.join("\n - ")); 30 this.echo(" - " + links.join("\n - "))
40 this.exit(); 31 this.exit();
41 }); 32 });
......
...@@ -15,7 +15,7 @@ casper = require("casper").create verbose: true ...@@ -15,7 +15,7 @@ casper = require("casper").create verbose: true
15 casper.fetchScore = -> 15 casper.fetchScore = ->
16 @evaluate -> 16 @evaluate ->
17 result = document.querySelector('#resultStats').innerText 17 result = document.querySelector('#resultStats').innerText
18 ~~(/Environ ([0-9\s]{1,}).*/.exec(result)[1].replace(/\s/g, '')) 18 parseInt /Environ ([0-9\s]{1,}).*/.exec(result)[1].replace(/\s/g, '')
19 19
20 terms = casper.cli.args # terms are passed through command-line arguments 20 terms = casper.cli.args # terms are passed through command-line arguments
21 21
...@@ -35,10 +35,13 @@ casper.each terms, (self, term) -> ...@@ -35,10 +35,13 @@ casper.each terms, (self, term) ->
35 @then -> 35 @then ->
36 score = @fetchScore() 36 score = @fetchScore()
37 scores.push term: term, score: score 37 scores.push term: term, score: score
38 self.echo "#{term}: #{score}" 38 @echo "#{term}: #{score}"
39 39
40 casper.run -> 40 casper.run ->
41 scores.sort (a, b) -> b.score - a.score; 41 if scores.length is 0
42 @echo "No result found"
43 else
44 scores.sort (a, b) -> b.score - a.score
42 winner = scores[0] 45 winner = scores[0]
43 @echo "Winner is \"#{winner.term}\" with #{winner.score} results" 46 @echo "Winner is \"" + winner.term + "\" with " + winner.score + " results"
44 @exit() 47 @exit()
......
1 /* 1 /*
2 Takes provided terms passed as arguments and query google for the number of 2 * Takes provided terms passed as arguments and query google for the number of
3 estimated results each have. 3 * estimated results each have.
4 4 *
5 Usage: 5 * Usage:
6 $ casperjs googlematch.js nicolas chuck borris 6 * $ casperjs googlematch.js nicolas chuck borris
7 nicolas: 69600000 7 * nicolas: 69600000
8 chuck: 49500000 8 * chuck: 49500000
9 borris: 2370000 9 * borris: 2370000
10 winner is "nicolas" with 69600000 results 10 * winner is "nicolas" with 69600000 results
11 */ 11 */
12 12
13 var casper, scores, terms; 13 var casper, scores, terms;
14 14
...@@ -18,9 +18,8 @@ casper = require("casper").create({ ...@@ -18,9 +18,8 @@ casper = require("casper").create({
18 18
19 casper.fetchScore = function() { 19 casper.fetchScore = function() {
20 return this.evaluate(function() { 20 return this.evaluate(function() {
21 var result; 21 var result = document.querySelector('#resultStats').innerText;
22 result = document.querySelector('#resultStats').innerText; 22 return parseInt(/Environ ([0-9\s]{1,}).*/.exec(result)[1].replace(/\s/g, ''), 10);
23 return ~~(/Environ ([0-9\s]{1,}).*/.exec(result)[1].replace(/\s/g, ''));
24 }); 23 });
25 }; 24 };
26 25
...@@ -39,29 +38,30 @@ casper.echo("Let the match begin between \"" + (terms.join('", "')) + "\"!"); ...@@ -39,29 +38,30 @@ casper.echo("Let the match begin between \"" + (terms.join('", "')) + "\"!");
39 38
40 casper.start("http://google.fr/"); 39 casper.start("http://google.fr/");
41 40
42 casper.each(terms, function(self, term) { 41 casper.each(terms, function(casper, term, i) {
42 this.echo('Fecthing score for ' + term);
43 this.then(function() { 43 this.then(function() {
44 this.fill('form[action="/search"]', { 44 this.fill('form[action="/search"]', {q: term}, true);
45 q: term
46 }, true);
47 }); 45 });
48 this.then(function() { 46 this.then(function() {
49 var score; 47 var score = this.fetchScore();
50 score = this.fetchScore();
51 scores.push({ 48 scores.push({
52 term: term, 49 term: term,
53 score: score 50 score: score
54 }); 51 });
55 self.echo(term + ": " + score); 52 this.echo(term + ': ' + score);
56 }); 53 });
57 }); 54 });
58 55
59 casper.run(function() { 56 casper.run(function() {
60 var winner; 57 if (scores.length === 0) {
58 this.echo("No result found");
59 } else {
61 scores.sort(function(a, b) { 60 scores.sort(function(a, b) {
62 return b.score - a.score; 61 return b.score - a.score;
63 }); 62 });
64 winner = scores[0]; 63 var winner = scores[0];
65 this.echo("Winner is \"" + winner.term + "\" with " + winner.score + " results"); 64 this.echo("Winner is \"" + winner.term + "\" with " + winner.score + " results");
65 }
66 this.exit(); 66 this.exit();
67 }); 67 });
......
1 failed = []; 1 failed = []
2 start = null
3 links = [
4 "http://google.com/"
5 "http://akei.com/"
6 "http://lemonde.fr/"
7 "http://liberation.fr/"
8 "http://cdiscount.fr/"
9 ]
2 10
3 casper = require("casper").create 11 casper = require("casper").create
4 onStepTimeout: -> failed.push @requestUrl 12 onStepTimeout: ->
13 failed.push @requestUrl
14 @test.fail "#{@requestUrl} loads in less than #{timeout}ms."
5 15
6 links = [ 16 casper.on "load.finished", ->
7 'http://google.com/' 17 @echo "#{@requestUrl} loaded in #{new Date() - start}ms", "PARAMETER"
8 'http://akei.com/'
9 'http://lemonde.fr/'
10 'http://liberation.fr/'
11 'http://cdiscount.fr/'
12 ]
13 18
14 timeout = ~~casper.cli.get(0) 19 timeout = ~~casper.cli.get(0)
15 timeout = 1000 if timeout < 1 20 timeout = 1000 if timeout < 1
16 casper.options.stepTimeout = timeout 21 casper.options.stepTimeout = timeout
17 22
18 casper.echo "Testing with timeout=#{casper.options.stepTimeout}ms." 23 casper.echo "Testing with timeout=#{timeout}ms, please be patient."
19 24
20 casper.start() 25 casper.start()
21 26
22 casper.each links, (self, link) -> 27 casper.each links, (self, link) ->
23 @test.comment "Adding #{link} to test suite" 28 @then ->
24 @thenOpen link, -> 29 @test.comment "Loading #{link}"
25 if @requestUrl in failed 30 start = new Date()
26 @test.fail "#{@requestUrl} loaded in less than #{timeout}ms." 31 @open link
27 else 32 @then ->
33 if @requestUrl not in failed
28 @test.pass "#{@requestUrl} loaded in less than #{timeout}ms." 34 @test.pass "#{@requestUrl} loaded in less than #{timeout}ms."
29 35
30 casper.run -> 36 casper.run ->
......
1 var casper, failed, links, timeout, 1 var failed = [];
2 __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 2 var start = null;
3 3 var links = [
4 failed = []; 4 "http://google.com/'",
5 "http://akei.com/'",
6 "http://lemonde.fr/'",
7 "http://liberation.fr/'",
8 "http://cdiscount.fr/"
9 ];
5 10
6 casper = require("casper").create({ 11 var casper = require("casper").create({
7 onStepTimeout: function() { 12 onStepTimeout: function() {
8 failed.push(this.requestUrl); 13 failed.push(this.requestUrl);
14 this.test.fail(this.requestUrl + " loads in less than " + timeout + "ms.");
9 } 15 }
10 }); 16 });
11 17
12 links = [ 18 casper.on("load.finished", function() {
13 'http://google.com/', 19 this.echo(this.requestUrl + " loaded in " + (new Date() - start) + "ms", "PARAMETER");
14 'http://akei.com/', 20 });
15 'http://lemonde.fr/',
16 'http://liberation.fr/',
17 'http://cdiscount.fr/'
18 ];
19
20 timeout = ~~casper.cli.get(0);
21
22 if (timeout < 1) {
23 timeout = 1000;
24 }
25 21
26 casper.options.stepTimeout = timeout; 22 var timeout = ~~casper.cli.get(0);
23 casper.options.stepTimeout = timeout > 0 ? timeout : 1000;
27 24
28 casper.echo("Testing with timeout=" + casper.options.stepTimeout + "ms."); 25 casper.echo("Testing with timeout=" + casper.options.stepTimeout + "ms, please be patient.");
29 26
30 casper.start(); 27 casper.start();
31 28
32 casper.each(links, function(self, link) { 29 casper.each(links, function(casper, link) {
33 this.test.comment("Adding " + link + " to test suite"); 30 this.then(function() {
34 this.thenOpen(link, function() { 31 this.test.comment("Loading " + link);
35 var _ref; 32 start = new Date();
36 if (_ref = this.requestUrl, __indexOf.call(failed, _ref) >= 0) { 33 this.open(link);
37 this.test.fail("" + this.requestUrl + " loaded in less than " + timeout + "ms."); 34 });
38 } else { 35 this.then(function() {
39 this.test.pass("" + this.requestUrl + " loaded in less than " + timeout + "ms."); 36 var message = this.requestUrl + " loads in less than " + timeout + "ms.";
37 if (failed.indexOf(this.requestUrl) === -1) {
38 this.test.pass(message);
40 } 39 }
41 }); 40 });
42 }); 41 });
......
...@@ -4,12 +4,15 @@ Just a silly game. ...@@ -4,12 +4,15 @@ Just a silly game.
4 $ casperjs samples/timeout.js 500 4 $ casperjs samples/timeout.js 500
5 Will google.com load in less than 500ms? 5 Will google.com load in less than 500ms?
6 NOPE. 6 NOPE.
7
7 $ casperjs samples/timeout.js 1000 8 $ casperjs samples/timeout.js 1000
8 Will google.com load in less than 1000ms? 9 Will google.com load in less than 1000ms?
9 NOPE. 10 NOPE.
11
10 $ casperjs samples/timeout.js 1500 12 $ casperjs samples/timeout.js 1500
11 Will google.com load in less than 1500ms? 13 Will google.com load in less than 1500ms?
12 NOPE. 14 NOPE.
15
13 $ casperjs samples/timeout.js 2000 16 $ casperjs samples/timeout.js 2000
14 Will google.com load in less than 2000ms? 17 Will google.com load in less than 2000ms?
15 YES! 18 YES!
......
1 /* 1 /*
2 Just a silly game. 2 * Just a silly game.
3 3 *
4 $ casperjs samples/timeout.js 500 4 * $ casperjs samples/timeout.js 500
5 Will google.com load in less than 500ms? 5 * Will google.com load in less than 500ms?
6 NOPE. 6 * NOPE.
7 $ casperjs samples/timeout.js 1000 7 *
8 Will google.com load in less than 1000ms? 8 * $ casperjs samples/timeout.js 1000
9 NOPE. 9 * Will google.com load in less than 1000ms?
10 $ casperjs samples/timeout.js 1500 10 * NOPE.
11 Will google.com load in less than 1500ms? 11 *
12 NOPE. 12 * $ casperjs samples/timeout.js 1500
13 $ casperjs samples/timeout.js 2000 13 * Will google.com load in less than 1500ms?
14 Will google.com load in less than 2000ms? 14 * NOPE.
15 YES! 15 *
16 */ 16 * $ casperjs samples/timeout.js 2000
17 * Will google.com load in less than 2000ms?
18 * YES!
19 */
17 20
18 var casper, timeout; 21 var casper, timeout;
19 22
...@@ -39,7 +42,7 @@ casper.echo("Will google.com load in less than " + timeout + "ms?"); ...@@ -39,7 +42,7 @@ casper.echo("Will google.com load in less than " + timeout + "ms?");
39 casper.options.timeout = timeout; 42 casper.options.timeout = timeout;
40 43
41 casper.start("http://www.google.com/", function() { 44 casper.start("http://www.google.com/", function() {
42 this.echo("YES!", 'GREEN_BAR'); 45 this.echo("YES!", "GREEN_BAR");
43 this.exit(); 46 this.exit();
44 }); 47 });
45 48
......
...@@ -7,7 +7,7 @@ var fs = require('fs'); ...@@ -7,7 +7,7 @@ var fs = require('fs');
7 var utils = require('utils'); 7 var utils = require('utils');
8 var f = utils.format; 8 var f = utils.format;
9 var casper = require('casper').create({ 9 var casper = require('casper').create({
10 faultTolerant: false 10 exitOnError: false
11 }); 11 });
12 12
13 // Options from cli 13 // Options from cli
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
19 <input type="checkbox" name="checklist[]" value="1" /> 19 <input type="checkbox" name="checklist[]" value="1" />
20 <input type="checkbox" name="checklist[]" value="2" /> 20 <input type="checkbox" name="checklist[]" value="2" />
21 <input type="checkbox" name="checklist[]" value="3" /> 21 <input type="checkbox" name="checklist[]" value="3" />
22 <input type="submit"/> 22 <input type="submit" name="submit" value="submit" />
23 </form> 23 </form>
24 </body> 24 </body>
25 </html> 25 </html>
......
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>CasperJS test mouse events</title>
6 </head>
7 <body>
8 <a id="test1" href="#" onmousedown="results.test1 = true;">test</a>
9 <a id="test2" href="#">test</a>
10 <a id="test3" href="#" onmouseup="results.test3 = true;">test</a>
11 <a id="test4" href="#">test</a>
12 <a id="test5" href="#" onmouseover="results.test5 = true;">test</a>
13 <a id="test6" href="#">test</a>
14 <a id="test7" href="#" onmouseout="results.test7 = true;">test</a>
15 <a id="test8" href="#">test</a>
16 <script>
17 (function(window) {
18 window.results = {
19 test1: false,
20 test2: false,
21 test3: false,
22 test4: false,
23 test5: false,
24 test6: false,
25 test7: false,
26 test8: false
27 };
28 document.querySelector('#test2').onmousedown = function(event) {
29 results.test2 = true;
30 event.preventDefault();
31 };
32 document.querySelector('#test4').onmouseup = function(event) {
33 results.test4 = true;
34 event.preventDefault();
35 };
36 document.querySelector('#test6').onmouseover = function(event) {
37 results.test6 = true;
38 event.preventDefault();
39 };
40 document.querySelector('#test8').onmouseout = function(event) {
41 results.test8 = true;
42 event.preventDefault();
43 };
44 })(window);
45 </script>
46 </body>
47 </html>
...@@ -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
......
1 casper.start('tests/site/mouse-events.html');
2
3 casper.then(function() {
4 this.test.comment('CasperUtils.mouseEvent()');
5 this.test.assert(this.mouseEvent('mousedown', '#test1'), 'CasperUtils.mouseEvent() can dispatch a mousedown event');
6 this.test.assert(this.mouseEvent('mousedown', '#test2'), 'CasperUtils.mouseEvent() can dispatch a mousedown event handled by unobstrusive js');
7 this.test.assert(this.mouseEvent('mouseup', '#test3'), 'CasperUtils.mouseEvent() can dispatch a mouseup event');
8 this.test.assert(this.mouseEvent('mouseup', '#test4'), 'CasperUtils.mouseEvent() can dispatch a mouseup event handled by unobstrusive js');
9 this.test.assert(this.mouseEvent('mouseover', '#test5'), 'CasperUtils.mouseEvent() can dispatch a mouseover event');
10 this.test.assert(this.mouseEvent('mouseover', '#test6'), 'CasperUtils.mouseEvent() can dispatch a mouseover event handled by unobstrusive js');
11 this.test.assert(this.mouseEvent('mouseout', '#test7'), 'CasperUtils.mouseEvent() can dispatch a mouseout event');
12 this.test.assert(this.mouseEvent('mouseout', '#test8'), 'CasperUtils.mouseEvent() can dispatch a mouseout event handled by unobstrusive js');
13
14 var results = this.getGlobal('results');
15 this.test.assert(results.test1, 'CasperUtils.mouseEvent() triggered mousedown');
16 this.test.assert(results.test2, 'CasperUtils.mouseEvent() triggered mousedown via unobstrusive js');
17 this.test.assert(results.test3, 'CasperUtils.mouseEvent() triggered mouseup');
18 this.test.assert(results.test4, 'CasperUtils.mouseEvent() triggered mouseup via unobstrusive js');
19 this.test.assert(results.test5, 'CasperUtils.mouseEvent() triggered mouseover');
20 this.test.assert(results.test6, 'CasperUtils.mouseEvent() triggered mouseover via unobstrusive js');
21 this.test.assert(results.test7, 'CasperUtils.mouseEvent() triggered mouseout');
22 this.test.assert(results.test8, 'CasperUtils.mouseEvent() triggered mouseout via unobstrusive js');
23 });
24
25 casper.run(function() {
26 this.test.done();
27 });
...@@ -19,6 +19,11 @@ function Plip() { return 'plop'; } ...@@ -19,6 +19,11 @@ function Plip() { return 'plop'; }
19 function foo_bar(boz) {} 19 function foo_bar(boz) {}
20 var gni = function ($bubu_bibi, __popo__) {}; 20 var gni = function ($bubu_bibi, __popo__) {};
21 var gno = function ( arg1, /*plop*/ arg2 ) { }; 21 var gno = function ( arg1, /*plop*/ arg2 ) { };
22 function issue129(term) {
23 // see issue #129
24 return term;
25 // see issue #129
26 }
22 t.assertEquals(injector.extract(Plop), { 27 t.assertEquals(injector.extract(Plop), {
23 name: 'Plop', 28 name: 'Plop',
24 args: ['foo', 'bar'], 29 args: ['foo', 'bar'],
...@@ -52,4 +57,8 @@ eval('processed = ' + injector.process({ a: 1, b: 2 })); ...@@ -52,4 +57,8 @@ eval('processed = ' + injector.process({ a: 1, b: 2 }));
52 t.assertType(processed, "function", 'FunctionArgsInjector.process() processed a function'); 57 t.assertType(processed, "function", 'FunctionArgsInjector.process() processed a function');
53 t.assertEquals(processed(), 3, 'FunctionArgsInjector.process() processed the function correctly'); 58 t.assertEquals(processed(), 3, 'FunctionArgsInjector.process() processed the function correctly');
54 59
60 // Issue #129
61 var fnIssue129 = createInjector(issue129).process({term: 'fixed'});
62 t.assertEquals(fnIssue129('fixed'), 'fixed', 'FunctionArgsInjector.process() has issue #129 fixed');
63
55 t.done(); 64 t.done();
......
...@@ -2,6 +2,8 @@ var fs = require('fs'); ...@@ -2,6 +2,8 @@ var fs = require('fs');
2 2
3 var t = casper.test; 3 var t = casper.test;
4 4
5 casper.start();
6
5 t.comment('Tester.testEquals()'); 7 t.comment('Tester.testEquals()');
6 t.assert(t.testEquals(null, null), 'Tester.testEquals() null equality'); 8 t.assert(t.testEquals(null, null), 'Tester.testEquals() null equality');
7 t.assertNot(t.testEquals(null, undefined), 'Tester.testEquals() null vs. undefined inequality'); 9 t.assertNot(t.testEquals(null, undefined), 'Tester.testEquals() null vs. undefined inequality');
...@@ -26,8 +28,6 @@ t.assertNot(t.testEquals({1:{name:"bob",age:28}, 2:{name:"john",age:26}}, {1:{na ...@@ -26,8 +28,6 @@ t.assertNot(t.testEquals({1:{name:"bob",age:28}, 2:{name:"john",age:26}}, {1:{na
26 t.assert(t.testEquals(function(x){return x;}, function(x){return x;}), 'Tester.testEquals() function equality'); 28 t.assert(t.testEquals(function(x){return x;}, function(x){return x;}), 'Tester.testEquals() function equality');
27 t.assertNot(t.testEquals(function(x){return x;}, function(y){return y+2;}), 'Tester.testEquals() function inequality'); 29 t.assertNot(t.testEquals(function(x){return x;}, function(y){return y+2;}), 'Tester.testEquals() function inequality');
28 30
29 t.assertNotEquals(42, 43, 'Tester.assertNotEquals() works as expected');
30
31 t.comment('Tester.sortFiles()'); 31 t.comment('Tester.sortFiles()');
32 var testDirRoot = fs.pathJoin(phantom.casperPath, 'tests', 'testdir'); 32 var testDirRoot = fs.pathJoin(phantom.casperPath, 'tests', 'testdir');
33 var files = t.findTestFiles(testDirRoot); 33 var files = t.findTestFiles(testDirRoot);
...@@ -44,11 +44,65 @@ var expected = [ ...@@ -44,11 +44,65 @@ var expected = [
44 }); 44 });
45 t.assertEquals(files, expected, 'findTestFiles() find test files and sort them'); 45 t.assertEquals(files, expected, 'findTestFiles() find test files and sort them');
46 46
47 t.comment('Tester.assertTextExists()'); 47 casper.thenOpen('tests/site/index.html', function() {
48 casper.start('tests/site/index.html', function() { 48 t.comment('Tester.assertTextExists()');
49 t.assertTextExists('form', 'Tester.assertTextExists() checks that page body contains text'); 49 t.assertTextExists('form', 'Tester.assertTextExists() checks that page body contains text');
50 }); 50 });
51 51
52 casper.then(function() {
53 t.comment('Tester.assert()');
54 t.assert(true, 'Tester.assert() works as expected');
55
56 t.comment('Tester.assertNot()');
57 t.assertNot(false, 'Tester.assertNot() works as expected');
58
59 t.comment('Tester.assertEquals()');
60 t.assertEquals(true, true, 'Tester.assertEquals() works as expected');
61
62 t.comment('Tester.assertNotEquals()');
63 t.assertNotEquals(true, false, 'Tester.assertNotEquals() works as expected');
64
65 t.comment('Tester.assertEval()');
66 t.assertEval(function() {
67 return true;
68 }, 'Tester.assertEval() works as expected');
69
70 t.comment('Tester.assertEvalEquals()');
71 t.assertEvalEquals(function() {
72 return 42;
73 }, 42, 'Tester.assertEvalEquals() works as expected');
74
75 t.comment('Tester.assertExists()');
76 t.assertExists('body', 'Tester.assertExists() works as expected');
77
78 t.comment('Tester.assertDoesntExist()');
79 t.assertDoesntExist('foobar', 'Tester.assertDoesntExist() works as expected');
80
81 t.comment('Tester.assertHttpStatus()');
82 // using file:// protocol, HTTP status is always null
83 t.assertHttpStatus(null, 'Tester.assertHttpStatus() works as expected');
84
85 t.comment('Tester.assertMatch()');
86 t.assertMatch("the lazy dog", /lazy/, 'Tester.assertMatch() works as expected');
87
88 t.comment('Tester.assertRaises()');
89 t.assertRaises(function() {
90 throw new Error('plop');
91 }, [], 'Tester.assertRaises() works as expected');
92
93 t.comment('Tester.assertResourceExists()');
94 t.assertResourceExists(/index\.html/, 'Tester.assertResourceExists() works as expected');
95
96 t.comment('Tester.assertTitle()');
97 t.assertTitle('CasperJS test index', 'Tester.assertTitle() works as expected');
98
99 t.comment('Tester.assertType()');
100 t.assertType("plop", "string", "Tester.assertType() works as expected");
101
102 t.comment('Tester.assertUrlMatch()');
103 t.assertUrlMatch(/index\.html$/, "Tester.assertUrlMatch() works as expected");
104 });
105
52 casper.run(function() { 106 casper.run(function() {
53 t.done(); 107 t.done();
54 }); 108 });
......