sync with latest master
Showing
35 changed files
with
831 additions
and
473 deletions
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() { | ... | ... |
... | @@ -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> | ... | ... |
tests/site/mouse-events.html
0 → 100644
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 | ... | ... |
tests/suites/casper/mouseevents.js
0 → 100644
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 | }); | ... | ... |
-
Please register or sign in to post a comment