Commit 93dcfbd4 93dcfbd4ef31e52e86ba4a0bd164ec295f027f23 by Nicolas Perriault

jshint configuration, code cleaning

1 parent bcaf4e30
1 {
2 "asi": true,
3 "browser": true,
4 "debug": true,
5 "devel": true,
6 "eqeqeq": true,
7 "evil": true,
8 "maxparams": 5,
9 "maxdepth": 3,
10 "maxstatements": 15,
11 "maxcomplexity": 7,
12 "regexdash": true,
13 "strict": true,
14 "sub": true,
15 "trailing": true,
16 "undef": true,
17
18 "predef" : [
19 "exports",
20 "phantom",
21 "require",
22 "window"
23 ]
24 }
1 docs
2 modules/vendors
3 modules/events.js
4 modules/querystring.js
5 samples
6 tests/site
7 tests/testdir
8 tests/suites
...@@ -208,12 +208,6 @@ function bootstrap(global) { ...@@ -208,12 +208,6 @@ function bootstrap(global) {
208 // custom global CasperError 208 // custom global CasperError
209 global.CasperError = function CasperError(msg) { 209 global.CasperError = function CasperError(msg) {
210 Error.call(this); 210 Error.call(this);
211 try {
212 // let's get where this error has been thrown from, if we can
213 this._from = arguments.callee.caller.name;
214 } catch (e) {
215 this._from = "anonymous";
216 }
217 this.message = msg; 211 this.message = msg;
218 this.name = 'CasperError'; 212 this.name = 'CasperError';
219 }; 213 };
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
33 var colorizer = require('colorizer'); 33 var colorizer = require('colorizer');
34 var events = require('events'); 34 var events = require('events');
35 var fs = require('fs'); 35 var fs = require('fs');
36 var http = require('http');
36 var mouse = require('mouse'); 37 var mouse = require('mouse');
37 var qs = require('querystring'); 38 var qs = require('querystring');
38 var tester = require('tester'); 39 var tester = require('tester');
...@@ -192,6 +193,7 @@ utils.inherits(Casper, events.EventEmitter); ...@@ -192,6 +193,7 @@ utils.inherits(Casper, events.EventEmitter);
192 */ 193 */
193 Casper.prototype.back = function back() { 194 Casper.prototype.back = function back() {
194 "use strict"; 195 "use strict";
196 this.checkStarted();
195 return this.then(function _step() { 197 return this.then(function _step() {
196 this.emit('back'); 198 this.emit('back');
197 this.evaluate(function _evaluate() { 199 this.evaluate(function _evaluate() {
...@@ -230,9 +232,8 @@ Casper.prototype.base64encode = function base64encode(url, method, data) { ...@@ -230,9 +232,8 @@ Casper.prototype.base64encode = function base64encode(url, method, data) {
230 */ 232 */
231 Casper.prototype.capture = function capture(targetFile, clipRect) { 233 Casper.prototype.capture = function capture(targetFile, clipRect) {
232 "use strict"; 234 "use strict";
233 if (!this.started) { 235 /*jshint maxstatements:20*/
234 throw new CasperError("Casper not started, can't capture()"); 236 this.checkStarted();
235 }
236 var previousClipRect; 237 var previousClipRect;
237 targetFile = fs.absolute(targetFile); 238 targetFile = fs.absolute(targetFile);
238 if (clipRect) { 239 if (clipRect) {
...@@ -270,16 +271,9 @@ Casper.prototype.capture = function capture(targetFile, clipRect) { ...@@ -270,16 +271,9 @@ Casper.prototype.capture = function capture(targetFile, clipRect) {
270 */ 271 */
271 Casper.prototype.captureBase64 = function captureBase64(format, area) { 272 Casper.prototype.captureBase64 = function captureBase64(format, area) {
272 "use strict"; 273 "use strict";
273 if (!this.started) { 274 /*jshint maxstatements:20*/
274 throw new CasperError("Casper not started, can't captureBase64()"); 275 this.checkStarted();
275 } 276 var base64, previousClipRect, formats = ['bmp', 'jpg', 'jpeg', 'png', 'ppm', 'tiff', 'xbm', 'xpm'];
276 if (!('renderBase64' in this.page)) {
277 this.warn('captureBase64() requires PhantomJS >= 1.6');
278 return;
279 }
280 var base64;
281 var previousClipRect;
282 var formats = ['bmp', 'jpg', 'jpeg', 'png', 'ppm', 'tiff', 'xbm', 'xpm'];
283 if (formats.indexOf(format.toLowerCase()) === -1) { 277 if (formats.indexOf(format.toLowerCase()) === -1) {
284 throw new CasperError(f('Unsupported format "%s"', format)); 278 throw new CasperError(f('Unsupported format "%s"', format));
285 } 279 }
...@@ -346,6 +340,20 @@ Casper.prototype.checkStep = function checkStep(self, onComplete) { ...@@ -346,6 +340,20 @@ Casper.prototype.checkStep = function checkStep(self, onComplete) {
346 }; 340 };
347 341
348 /** 342 /**
343 * Checks if this instance is started.
344 *
345 * @return Boolean
346 * @throws CasperError
347 */
348 Casper.prototype.checkStarted = function checkStarted() {
349 "use strict";
350 if (!this.started) {
351 throw new CasperError(f("Casper is not started, can't execute `%s()`",
352 checkStarted.caller.name));
353 }
354 };
355
356 /**
349 * Clears the current page execution environment context. Useful to avoid 357 * Clears the current page execution environment context. Useful to avoid
350 * having previously loaded DOM contents being still active (refs #34). 358 * having previously loaded DOM contents being still active (refs #34).
351 * 359 *
...@@ -356,6 +364,7 @@ Casper.prototype.checkStep = function checkStep(self, onComplete) { ...@@ -356,6 +364,7 @@ Casper.prototype.checkStep = function checkStep(self, onComplete) {
356 */ 364 */
357 Casper.prototype.clear = function clear() { 365 Casper.prototype.clear = function clear() {
358 "use strict"; 366 "use strict";
367 this.checkStarted();
359 this.page.content = ''; 368 this.page.content = '';
360 return this; 369 return this;
361 }; 370 };
...@@ -371,6 +380,7 @@ Casper.prototype.clear = function clear() { ...@@ -371,6 +380,7 @@ Casper.prototype.clear = function clear() {
371 */ 380 */
372 Casper.prototype.click = function click(selector) { 381 Casper.prototype.click = function click(selector) {
373 "use strict"; 382 "use strict";
383 this.checkStarted();
374 return this.mouseEvent('click', selector); 384 return this.mouseEvent('click', selector);
375 }; 385 };
376 386
...@@ -384,6 +394,7 @@ Casper.prototype.click = function click(selector) { ...@@ -384,6 +394,7 @@ Casper.prototype.click = function click(selector) {
384 */ 394 */
385 Casper.prototype.clickLabel = function clickLabel(label, tag) { 395 Casper.prototype.clickLabel = function clickLabel(label, tag) {
386 "use strict"; 396 "use strict";
397 this.checkStarted();
387 tag = tag || "*"; 398 tag = tag || "*";
388 var escapedLabel = label.toString().replace(/"/g, '\\"'); 399 var escapedLabel = label.toString().replace(/"/g, '\\"');
389 var selector = selectXPath(f('//%s[text()="%s"]', tag, escapedLabel)); 400 var selector = selectXPath(f('//%s[text()="%s"]', tag, escapedLabel));
...@@ -416,6 +427,7 @@ Casper.prototype.createStep = function createStep(fn, options) { ...@@ -416,6 +427,7 @@ Casper.prototype.createStep = function createStep(fn, options) {
416 */ 427 */
417 Casper.prototype.debugHTML = function debugHTML(selector, outer) { 428 Casper.prototype.debugHTML = function debugHTML(selector, outer) {
418 "use strict"; 429 "use strict";
430 this.checkStarted();
419 return this.echo(this.getHTML(selector, outer)); 431 return this.echo(this.getHTML(selector, outer));
420 }; 432 };
421 433
...@@ -426,6 +438,7 @@ Casper.prototype.debugHTML = function debugHTML(selector, outer) { ...@@ -426,6 +438,7 @@ Casper.prototype.debugHTML = function debugHTML(selector, outer) {
426 */ 438 */
427 Casper.prototype.debugPage = function debugPage() { 439 Casper.prototype.debugPage = function debugPage() {
428 "use strict"; 440 "use strict";
441 this.checkStarted();
429 this.echo(this.evaluate(function _evaluate() { 442 this.echo(this.evaluate(function _evaluate() {
430 return document.body.textContent || document.body.innerText; 443 return document.body.textContent || document.body.innerText;
431 })); 444 }));
...@@ -441,6 +454,7 @@ Casper.prototype.debugPage = function debugPage() { ...@@ -441,6 +454,7 @@ Casper.prototype.debugPage = function debugPage() {
441 */ 454 */
442 Casper.prototype.die = function die(message, status) { 455 Casper.prototype.die = function die(message, status) {
443 "use strict"; 456 "use strict";
457 this.checkStarted();
444 this.result.status = "error"; 458 this.result.status = "error";
445 this.result.time = new Date().getTime() - this.startTime; 459 this.result.time = new Date().getTime() - this.startTime;
446 if (!utils.isString(message) || !message.length) { 460 if (!utils.isString(message) || !message.length) {
...@@ -465,6 +479,7 @@ Casper.prototype.die = function die(message, status) { ...@@ -465,6 +479,7 @@ Casper.prototype.die = function die(message, status) {
465 */ 479 */
466 Casper.prototype.download = function download(url, targetPath, method, data) { 480 Casper.prototype.download = function download(url, targetPath, method, data) {
467 "use strict"; 481 "use strict";
482 this.checkStarted();
468 var cu = require('clientutils').create(utils.mergeObjects({}, this.options)); 483 var cu = require('clientutils').create(utils.mergeObjects({}, this.options));
469 try { 484 try {
470 fs.write(targetPath, cu.decode(this.base64encode(url, method, data)), 'wb'); 485 fs.write(targetPath, cu.decode(this.base64encode(url, method, data)), 'wb');
...@@ -548,6 +563,7 @@ Casper.prototype.echo = function echo(text, style, pad) { ...@@ -548,6 +563,7 @@ Casper.prototype.echo = function echo(text, style, pad) {
548 */ 563 */
549 Casper.prototype.evaluate = function evaluate(fn, context) { 564 Casper.prototype.evaluate = function evaluate(fn, context) {
550 "use strict"; 565 "use strict";
566 this.checkStarted();
551 // ensure client utils are always injected 567 // ensure client utils are always injected
552 this.injectClientUtils(); 568 this.injectClientUtils();
553 // function context 569 // function context
...@@ -571,6 +587,7 @@ Casper.prototype.evaluate = function evaluate(fn, context) { ...@@ -571,6 +587,7 @@ Casper.prototype.evaluate = function evaluate(fn, context) {
571 */ 587 */
572 Casper.prototype.evaluateOrDie = function evaluateOrDie(fn, message, status) { 588 Casper.prototype.evaluateOrDie = function evaluateOrDie(fn, message, status) {
573 "use strict"; 589 "use strict";
590 this.checkStarted();
574 if (!this.evaluate(fn)) { 591 if (!this.evaluate(fn)) {
575 return this.die(message, status); 592 return this.die(message, status);
576 } 593 }
...@@ -586,6 +603,7 @@ Casper.prototype.evaluateOrDie = function evaluateOrDie(fn, message, status) { ...@@ -586,6 +603,7 @@ Casper.prototype.evaluateOrDie = function evaluateOrDie(fn, message, status) {
586 */ 603 */
587 Casper.prototype.exists = function exists(selector) { 604 Casper.prototype.exists = function exists(selector) {
588 "use strict"; 605 "use strict";
606 this.checkStarted();
589 return this.evaluate(function _evaluate(selector) { 607 return this.evaluate(function _evaluate(selector) {
590 return window.__utils__.exists(selector); 608 return window.__utils__.exists(selector);
591 }, { selector: selector }); 609 }, { selector: selector });
...@@ -612,9 +630,7 @@ Casper.prototype.exit = function exit(status) { ...@@ -612,9 +630,7 @@ Casper.prototype.exit = function exit(status) {
612 */ 630 */
613 Casper.prototype.fetchText = function fetchText(selector) { 631 Casper.prototype.fetchText = function fetchText(selector) {
614 "use strict"; 632 "use strict";
615 if (!this.started) { 633 this.checkStarted();
616 throw new CasperError("Casper not started, can't fetchText()");
617 }
618 return this.evaluate(function _evaluate(selector) { 634 return this.evaluate(function _evaluate(selector) {
619 return window.__utils__.fetchText(selector); 635 return window.__utils__.fetchText(selector);
620 }, { selector: selector }); 636 }, { selector: selector });
...@@ -629,6 +645,7 @@ Casper.prototype.fetchText = function fetchText(selector) { ...@@ -629,6 +645,7 @@ Casper.prototype.fetchText = function fetchText(selector) {
629 */ 645 */
630 Casper.prototype.fill = function fill(selector, vals, submit) { 646 Casper.prototype.fill = function fill(selector, vals, submit) {
631 "use strict"; 647 "use strict";
648 this.checkStarted();
632 submit = submit === true ? submit : false; 649 submit = submit === true ? submit : false;
633 if (!utils.isObject(vals)) { 650 if (!utils.isObject(vals)) {
634 throw new CasperError("Form values must be provided as an object"); 651 throw new CasperError("Form values must be provided as an object");
...@@ -643,15 +660,8 @@ Casper.prototype.fill = function fill(selector, vals, submit) { ...@@ -643,15 +660,8 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
643 if (!fillResults) { 660 if (!fillResults) {
644 throw new CasperError("Unable to fill form"); 661 throw new CasperError("Unable to fill form");
645 } else if (fillResults.errors.length > 0) { 662 } else if (fillResults.errors.length > 0) {
646 (function _each(self){ 663 throw new CasperError(f('Errors encountered while filling form: %s',
647 fillResults.errors.forEach(function _forEach(error) { 664 fillResults.errors.join('; ')));
648 throw new CasperError(error);
649 });
650 })(this);
651 if (submit) {
652 this.warn("Errors encountered while filling form; submission aborted");
653 submit = false;
654 }
655 } 665 }
656 // File uploads 666 // File uploads
657 if (fillResults.files && fillResults.files.length > 0) { 667 if (fillResults.files && fillResults.files.length > 0) {
...@@ -691,6 +701,7 @@ Casper.prototype.fill = function fill(selector, vals, submit) { ...@@ -691,6 +701,7 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
691 */ 701 */
692 Casper.prototype.forward = function forward(then) { 702 Casper.prototype.forward = function forward(then) {
693 "use strict"; 703 "use strict";
704 this.checkStarted();
694 return this.then(function _step() { 705 return this.then(function _step() {
695 this.emit('forward'); 706 this.emit('forward');
696 this.evaluate(function _evaluate() { 707 this.evaluate(function _evaluate() {
...@@ -717,9 +728,7 @@ Casper.prototype.getColorizer = function getColorizer() { ...@@ -717,9 +728,7 @@ Casper.prototype.getColorizer = function getColorizer() {
717 */ 728 */
718 Casper.prototype.getPageContent = function getPageContent() { 729 Casper.prototype.getPageContent = function getPageContent() {
719 "use strict"; 730 "use strict";
720 if (!this.started) { 731 this.checkStarted();
721 throw new CasperError("Casper not started, can't getPageContent()");
722 }
723 var contentType = utils.getPropertyPath(this, 'currentResponse.contentType'); 732 var contentType = utils.getPropertyPath(this, 'currentResponse.contentType');
724 if (!utils.isString(contentType)) { 733 if (!utils.isString(contentType)) {
725 return this.page.content; 734 return this.page.content;
...@@ -742,6 +751,7 @@ Casper.prototype.getPageContent = function getPageContent() { ...@@ -742,6 +751,7 @@ Casper.prototype.getPageContent = function getPageContent() {
742 */ 751 */
743 Casper.prototype.getCurrentUrl = function getCurrentUrl() { 752 Casper.prototype.getCurrentUrl = function getCurrentUrl() {
744 "use strict"; 753 "use strict";
754 this.checkStarted();
745 var url = this.evaluate(function _evaluate() { 755 var url = this.evaluate(function _evaluate() {
746 return document.location.href; 756 return document.location.href;
747 }); 757 });
...@@ -762,6 +772,7 @@ Casper.prototype.getCurrentUrl = function getCurrentUrl() { ...@@ -762,6 +772,7 @@ Casper.prototype.getCurrentUrl = function getCurrentUrl() {
762 */ 772 */
763 Casper.prototype.getElementAttribute = Casper.prototype.getElementAttr = function getElementAttr(selector, attribute) { 773 Casper.prototype.getElementAttribute = Casper.prototype.getElementAttr = function getElementAttr(selector, attribute) {
764 "use strict"; 774 "use strict";
775 this.checkStarted();
765 return this.evaluate(function _evaluate(selector, attribute) { 776 return this.evaluate(function _evaluate(selector, attribute) {
766 return document.querySelector(selector).getAttribute(attribute); 777 return document.querySelector(selector).getAttribute(attribute);
767 }, { selector: selector, attribute: attribute }); 778 }, { selector: selector, attribute: attribute });
...@@ -775,6 +786,7 @@ Casper.prototype.getElementAttribute = Casper.prototype.getElementAttr = functio ...@@ -775,6 +786,7 @@ Casper.prototype.getElementAttribute = Casper.prototype.getElementAttr = functio
775 */ 786 */
776 Casper.prototype.getElementBounds = function getElementBounds(selector) { 787 Casper.prototype.getElementBounds = function getElementBounds(selector) {
777 "use strict"; 788 "use strict";
789 this.checkStarted();
778 if (!this.exists(selector)) { 790 if (!this.exists(selector)) {
779 throw new CasperError("No element matching selector found: " + selector); 791 throw new CasperError("No element matching selector found: " + selector);
780 } 792 }
...@@ -795,6 +807,7 @@ Casper.prototype.getElementBounds = function getElementBounds(selector) { ...@@ -795,6 +807,7 @@ Casper.prototype.getElementBounds = function getElementBounds(selector) {
795 */ 807 */
796 Casper.prototype.getElementsBounds = function getElementBounds(selector) { 808 Casper.prototype.getElementsBounds = function getElementBounds(selector) {
797 "use strict"; 809 "use strict";
810 this.checkStarted();
798 if (!this.exists(selector)) { 811 if (!this.exists(selector)) {
799 throw new CasperError("No element matching selector found: " + selector); 812 throw new CasperError("No element matching selector found: " + selector);
800 } 813 }
...@@ -811,6 +824,7 @@ Casper.prototype.getElementsBounds = function getElementBounds(selector) { ...@@ -811,6 +824,7 @@ Casper.prototype.getElementsBounds = function getElementBounds(selector) {
811 */ 824 */
812 Casper.prototype.getGlobal = function getGlobal(name) { 825 Casper.prototype.getGlobal = function getGlobal(name) {
813 "use strict"; 826 "use strict";
827 this.checkStarted();
814 var result = this.evaluate(function _evaluate(name) { 828 var result = this.evaluate(function _evaluate(name) {
815 var result = {}; 829 var result = {};
816 try { 830 try {
...@@ -843,9 +857,7 @@ Casper.prototype.getGlobal = function getGlobal(name) { ...@@ -843,9 +857,7 @@ Casper.prototype.getGlobal = function getGlobal(name) {
843 */ 857 */
844 Casper.prototype.getHTML = function getHTML(selector, outer) { 858 Casper.prototype.getHTML = function getHTML(selector, outer) {
845 "use strict"; 859 "use strict";
846 if (!this.started) { 860 this.checkStarted();
847 throw new CasperError("Casper not started, can't getHTML()");
848 }
849 if (!selector) { 861 if (!selector) {
850 return this.page.content; 862 return this.page.content;
851 } 863 }
...@@ -865,12 +877,43 @@ Casper.prototype.getHTML = function getHTML(selector, outer) { ...@@ -865,12 +877,43 @@ Casper.prototype.getHTML = function getHTML(selector, outer) {
865 */ 877 */
866 Casper.prototype.getTitle = function getTitle() { 878 Casper.prototype.getTitle = function getTitle() {
867 "use strict"; 879 "use strict";
880 this.checkStarted();
868 return this.evaluate(function _evaluate() { 881 return this.evaluate(function _evaluate() {
869 return document.title; 882 return document.title;
870 }); 883 });
871 }; 884 };
872 885
873 /** 886 /**
887 * Handles received HTTP resource.
888 *
889 * @param Object resource PhantomJS HTTP resource
890 */
891 Casper.prototype.handleReceivedResource = function(resource) {
892 "use strict";
893 if (resource.stage !== "end") {
894 return;
895 }
896 this.resources.push(resource);
897 if (resource.url !== this.requestUrl) {
898 return;
899 }
900 this.currentHTTPStatus = null;
901 this.currentResponse = undefined;
902 if (utils.isHTTPResource(resource)) {
903 this.currentResponse = resource;
904 this.currentHTTPStatus = resource.status;
905 this.emit('http.status.' + resource.status, resource);
906 if (utils.isObject(this.options.httpStatusHandlers) &&
907 resource.status in this.options.httpStatusHandlers &&
908 utils.isFunction(this.options.httpStatusHandlers[resource.status])) {
909 this.options.httpStatusHandlers[resource.status].call(this, this, resource);
910 }
911 }
912 this.currentUrl = resource.url;
913 this.emit('location.changed', resource.url);
914 };
915
916 /**
874 * Initializes PhantomJS error handler. 917 * Initializes PhantomJS error handler.
875 * 918 *
876 */ 919 */
...@@ -886,11 +929,39 @@ Casper.prototype.initErrorHandler = function initErrorHandler() { ...@@ -886,11 +929,39 @@ Casper.prototype.initErrorHandler = function initErrorHandler() {
886 }; 929 };
887 930
888 /** 931 /**
932 * Injects configured client scripts.
933 *
934 * @return Casper
935 */
936 Casper.prototype.injectClientScripts = function injectClientScripts() {
937 "use strict";
938 this.checkStarted();
939 if (!this.options.clientScripts) {
940 return;
941 }
942 if (utils.isString(this.options.clientScripts)) {
943 this.options.clientScripts = [this.options.clientScripts];
944 }
945 if (!utils.isArray(this.options.clientScripts)) {
946 throw new CasperError("The clientScripts option must be an array");
947 }
948 this.options.clientScripts.forEach(function _forEach(script) {
949 if (this.page.injectJs(script)) {
950 this.log(f('Automatically injected %s client side', script), "debug");
951 } else {
952 this.warn('Failed injecting %s client side', script);
953 }
954 });
955 return this;
956 };
957
958 /**
889 * Injects Client-side utilities in current page context. 959 * Injects Client-side utilities in current page context.
890 * 960 *
891 */ 961 */
892 Casper.prototype.injectClientUtils = function injectClientUtils() { 962 Casper.prototype.injectClientUtils = function injectClientUtils() {
893 "use strict"; 963 "use strict";
964 this.checkStarted();
894 var clientUtilsInjected = this.page.evaluate(function() { 965 var clientUtilsInjected = this.page.evaluate(function() {
895 return typeof window.__utils__ === "object"; 966 return typeof window.__utils__ === "object";
896 }); 967 });
...@@ -938,8 +1009,10 @@ Casper.prototype.log = function log(message, level, space) { ...@@ -938,8 +1009,10 @@ Casper.prototype.log = function log(message, level, space) {
938 if (level in this.logFormats && utils.isFunction(this.logFormats[level])) { 1009 if (level in this.logFormats && utils.isFunction(this.logFormats[level])) {
939 message = this.logFormats[level](message, level, space); 1010 message = this.logFormats[level](message, level, space);
940 } else { 1011 } else {
941 var levelStr = this.colorizer.colorize(f('[%s]', level), this.logStyles[level]); 1012 message = f('%s [%s] %s',
942 message = f('%s [%s] %s', levelStr, space, message); 1013 this.colorizer.colorize(f('[%s]', level), this.logStyles[level]),
1014 space,
1015 message);
943 } 1016 }
944 if (this.options.verbose) { 1017 if (this.options.verbose) {
945 this.echo(this.filter('log.message', message) || message); // direct output 1018 this.echo(this.filter('log.message', message) || message); // direct output
...@@ -961,6 +1034,7 @@ Casper.prototype.log = function log(message, level, space) { ...@@ -961,6 +1034,7 @@ Casper.prototype.log = function log(message, level, space) {
961 */ 1034 */
962 Casper.prototype.mouseEvent = function mouseEvent(type, selector) { 1035 Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
963 "use strict"; 1036 "use strict";
1037 this.checkStarted();
964 this.log("Mouse event '" + type + "' on selector: " + selector, "debug"); 1038 this.log("Mouse event '" + type + "' on selector: " + selector, "debug");
965 if (!this.exists(selector)) { 1039 if (!this.exists(selector)) {
966 throw new CasperError(f("Cannot dispatch %s event on nonexistent selector: %s", type, selector)); 1040 throw new CasperError(f("Cannot dispatch %s event on nonexistent selector: %s", type, selector));
...@@ -998,6 +1072,7 @@ Casper.prototype.mouseEvent = function mouseEvent(type, selector) { ...@@ -998,6 +1072,7 @@ Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
998 */ 1072 */
999 Casper.prototype.open = function open(location, settings) { 1073 Casper.prototype.open = function open(location, settings) {
1000 "use strict"; 1074 "use strict";
1075 this.checkStarted();
1001 // settings validation 1076 // settings validation
1002 if (!settings) { 1077 if (!settings) {
1003 settings = { 1078 settings = {
...@@ -1040,9 +1115,6 @@ Casper.prototype.open = function open(location, settings) { ...@@ -1040,9 +1115,6 @@ Casper.prototype.open = function open(location, settings) {
1040 } 1115 }
1041 this.emit('open', this.requestUrl, settings); 1116 this.emit('open', this.requestUrl, settings);
1042 this.log(f('opening url: %s, HTTP %s', this.requestUrl, settings.method.toUpperCase()), "debug"); 1117 this.log(f('opening url: %s, HTTP %s', this.requestUrl, settings.method.toUpperCase()), "debug");
1043 if ('headers' in settings && phantom.version.minor < 6) {
1044 this.warn('Custom headers in outgoing requests are supported in PhantomJS >= 1.6');
1045 }
1046 this.page.openUrl(this.requestUrl, { 1118 this.page.openUrl(this.requestUrl, {
1047 operation: settings.method, 1119 operation: settings.method,
1048 data: settings.data, 1120 data: settings.data,
...@@ -1060,9 +1132,7 @@ Casper.prototype.open = function open(location, settings) { ...@@ -1060,9 +1132,7 @@ Casper.prototype.open = function open(location, settings) {
1060 */ 1132 */
1061 Casper.prototype.reload = function reload(then) { 1133 Casper.prototype.reload = function reload(then) {
1062 "use strict"; 1134 "use strict";
1063 if (!this.started) { 1135 this.checkStarted();
1064 throw new CasperError("Casper not started, can't reload()");
1065 }
1066 this.evaluate(function() { 1136 this.evaluate(function() {
1067 window.location.reload(); 1137 window.location.reload();
1068 }); 1138 });
...@@ -1097,6 +1167,7 @@ Casper.prototype.repeat = function repeat(times, then) { ...@@ -1097,6 +1167,7 @@ Casper.prototype.repeat = function repeat(times, then) {
1097 */ 1167 */
1098 Casper.prototype.resourceExists = function resourceExists(test) { 1168 Casper.prototype.resourceExists = function resourceExists(test) {
1099 "use strict"; 1169 "use strict";
1170 this.checkStarted();
1100 var testFn; 1171 var testFn;
1101 switch (utils.betterTypeOf(test)) { 1172 switch (utils.betterTypeOf(test)) {
1102 case "string": 1173 case "string":
...@@ -1128,6 +1199,7 @@ Casper.prototype.resourceExists = function resourceExists(test) { ...@@ -1128,6 +1199,7 @@ Casper.prototype.resourceExists = function resourceExists(test) {
1128 */ 1199 */
1129 Casper.prototype.run = function run(onComplete, time) { 1200 Casper.prototype.run = function run(onComplete, time) {
1130 "use strict"; 1201 "use strict";
1202 this.checkStarted();
1131 if (!this.steps || this.steps.length < 1) { 1203 if (!this.steps || this.steps.length < 1) {
1132 this.log("No steps defined, aborting", "error"); 1204 this.log("No steps defined, aborting", "error");
1133 return this; 1205 return this;
...@@ -1145,6 +1217,7 @@ Casper.prototype.run = function run(onComplete, time) { ...@@ -1145,6 +1217,7 @@ Casper.prototype.run = function run(onComplete, time) {
1145 */ 1217 */
1146 Casper.prototype.runStep = function runStep(step) { 1218 Casper.prototype.runStep = function runStep(step) {
1147 "use strict"; 1219 "use strict";
1220 this.checkStarted();
1148 var skipLog = utils.isObject(step.options) && step.options.skipLog === true; 1221 var skipLog = utils.isObject(step.options) && step.options.skipLog === true;
1149 var stepInfo = f("Step %d/%d", this.step, this.steps.length); 1222 var stepInfo = f("Step %d/%d", this.step, this.steps.length);
1150 var stepResult; 1223 var stepResult;
...@@ -1184,9 +1257,7 @@ Casper.prototype.runStep = function runStep(step) { ...@@ -1184,9 +1257,7 @@ Casper.prototype.runStep = function runStep(step) {
1184 */ 1257 */
1185 Casper.prototype.setHttpAuth = function setHttpAuth(username, password) { 1258 Casper.prototype.setHttpAuth = function setHttpAuth(username, password) {
1186 "use strict"; 1259 "use strict";
1187 if (!this.started) { 1260 this.checkStarted();
1188 throw new CasperError("Casper must be started in order to use the setHttpAuth() method");
1189 }
1190 if (!utils.isString(username) || !utils.isString(password)) { 1261 if (!utils.isString(username) || !utils.isString(password)) {
1191 throw new CasperError("Both username and password must be strings"); 1262 throw new CasperError("Both username and password must be strings");
1192 } 1263 }
...@@ -1258,6 +1329,7 @@ Casper.prototype.start = function start(location, then) { ...@@ -1258,6 +1329,7 @@ Casper.prototype.start = function start(location, then) {
1258 * @return Object 1329 * @return Object
1259 */ 1330 */
1260 Casper.prototype.status = function status(asString) { 1331 Casper.prototype.status = function status(asString) {
1332 "use strict";
1261 var properties = ['currentHTTPStatus', 'loadInProgress', 'navigationRequested', 1333 var properties = ['currentHTTPStatus', 'loadInProgress', 'navigationRequested',
1262 'options', 'pendingWait', 'requestUrl', 'started', 'step', 'url']; 1334 'options', 'pendingWait', 'requestUrl', 'started', 'step', 'url'];
1263 var currentStatus = {}; 1335 var currentStatus = {};
...@@ -1275,9 +1347,7 @@ Casper.prototype.status = function status(asString) { ...@@ -1275,9 +1347,7 @@ Casper.prototype.status = function status(asString) {
1275 */ 1347 */
1276 Casper.prototype.then = function then(step) { 1348 Casper.prototype.then = function then(step) {
1277 "use strict"; 1349 "use strict";
1278 if (!this.started) { 1350 this.checkStarted();
1279 throw new CasperError("Casper not started; please use Casper#start");
1280 }
1281 if (!utils.isFunction(step)) { 1351 if (!utils.isFunction(step)) {
1282 throw new CasperError("You can only define a step as a function"); 1352 throw new CasperError("You can only define a step as a function");
1283 } 1353 }
...@@ -1315,6 +1385,7 @@ Casper.prototype.then = function then(step) { ...@@ -1315,6 +1385,7 @@ Casper.prototype.then = function then(step) {
1315 */ 1385 */
1316 Casper.prototype.thenClick = function thenClick(selector, then, fallbackToHref) { 1386 Casper.prototype.thenClick = function thenClick(selector, then, fallbackToHref) {
1317 "use strict"; 1387 "use strict";
1388 this.checkStarted();
1318 if (arguments.length > 2) { 1389 if (arguments.length > 2) {
1319 this.emit("deprecated", "The thenClick() method does not process the fallbackToHref argument since 0.6"); 1390 this.emit("deprecated", "The thenClick() method does not process the fallbackToHref argument since 0.6");
1320 } 1391 }
...@@ -1335,6 +1406,7 @@ Casper.prototype.thenClick = function thenClick(selector, then, fallbackToHref) ...@@ -1335,6 +1406,7 @@ Casper.prototype.thenClick = function thenClick(selector, then, fallbackToHref)
1335 */ 1406 */
1336 Casper.prototype.thenEvaluate = function thenEvaluate(fn, context) { 1407 Casper.prototype.thenEvaluate = function thenEvaluate(fn, context) {
1337 "use strict"; 1408 "use strict";
1409 this.checkStarted();
1338 return this.then(function _step() { 1410 return this.then(function _step() {
1339 this.evaluate(fn, context); 1411 this.evaluate(fn, context);
1340 }); 1412 });
...@@ -1350,6 +1422,7 @@ Casper.prototype.thenEvaluate = function thenEvaluate(fn, context) { ...@@ -1350,6 +1422,7 @@ Casper.prototype.thenEvaluate = function thenEvaluate(fn, context) {
1350 */ 1422 */
1351 Casper.prototype.thenOpen = function thenOpen(location, settings, then) { 1423 Casper.prototype.thenOpen = function thenOpen(location, settings, then) {
1352 "use strict"; 1424 "use strict";
1425 this.checkStarted();
1353 if (!(settings && !utils.isFunction(settings))) { 1426 if (!(settings && !utils.isFunction(settings))) {
1354 then = settings; 1427 then = settings;
1355 settings = null; 1428 settings = null;
...@@ -1375,6 +1448,7 @@ Casper.prototype.thenOpen = function thenOpen(location, settings, then) { ...@@ -1375,6 +1448,7 @@ Casper.prototype.thenOpen = function thenOpen(location, settings, then) {
1375 */ 1448 */
1376 Casper.prototype.thenOpenAndEvaluate = function thenOpenAndEvaluate(location, fn, context) { 1449 Casper.prototype.thenOpenAndEvaluate = function thenOpenAndEvaluate(location, fn, context) {
1377 "use strict"; 1450 "use strict";
1451 this.checkStarted();
1378 return this.thenOpen(location).thenEvaluate(fn, context); 1452 return this.thenOpen(location).thenEvaluate(fn, context);
1379 }; 1453 };
1380 1454
...@@ -1384,6 +1458,7 @@ Casper.prototype.thenOpenAndEvaluate = function thenOpenAndEvaluate(location, fn ...@@ -1384,6 +1458,7 @@ Casper.prototype.thenOpenAndEvaluate = function thenOpenAndEvaluate(location, fn
1384 * @return String 1458 * @return String
1385 */ 1459 */
1386 Casper.prototype.toString = function toString() { 1460 Casper.prototype.toString = function toString() {
1461 "use strict";
1387 return '[object Casper], currently at ' + this.getCurrentUrl(); 1462 return '[object Casper], currently at ' + this.getCurrentUrl();
1388 }; 1463 };
1389 1464
...@@ -1395,9 +1470,7 @@ Casper.prototype.toString = function toString() { ...@@ -1395,9 +1470,7 @@ Casper.prototype.toString = function toString() {
1395 */ 1470 */
1396 Casper.prototype.userAgent = function userAgent(agent) { 1471 Casper.prototype.userAgent = function userAgent(agent) {
1397 "use strict"; 1472 "use strict";
1398 if (!this.started) { 1473 this.checkStarted();
1399 throw new CasperError("Casper not started, can't set userAgent");
1400 }
1401 this.options.pageSettings.userAgent = this.page.settings.userAgent = agent; 1474 this.options.pageSettings.userAgent = this.page.settings.userAgent = agent;
1402 return this; 1475 return this;
1403 }; 1476 };
...@@ -1411,9 +1484,7 @@ Casper.prototype.userAgent = function userAgent(agent) { ...@@ -1411,9 +1484,7 @@ Casper.prototype.userAgent = function userAgent(agent) {
1411 */ 1484 */
1412 Casper.prototype.viewport = function viewport(width, height) { 1485 Casper.prototype.viewport = function viewport(width, height) {
1413 "use strict"; 1486 "use strict";
1414 if (!this.started) { 1487 this.checkStarted();
1415 throw new CasperError("Casper must be started in order to set viewport at runtime");
1416 }
1417 if (!utils.isNumber(width) || !utils.isNumber(height) || width <= 0 || height <= 0) { 1488 if (!utils.isNumber(width) || !utils.isNumber(height) || width <= 0 || height <= 0) {
1418 throw new CasperError(f("Invalid viewport: %dx%d", width, height)); 1489 throw new CasperError(f("Invalid viewport: %dx%d", width, height));
1419 } 1490 }
...@@ -1435,6 +1506,7 @@ Casper.prototype.viewport = function viewport(width, height) { ...@@ -1435,6 +1506,7 @@ Casper.prototype.viewport = function viewport(width, height) {
1435 */ 1506 */
1436 Casper.prototype.visible = function visible(selector) { 1507 Casper.prototype.visible = function visible(selector) {
1437 "use strict"; 1508 "use strict";
1509 this.checkStarted();
1438 return this.evaluate(function _evaluate(selector) { 1510 return this.evaluate(function _evaluate(selector) {
1439 return window.__utils__.visible(selector); 1511 return window.__utils__.visible(selector);
1440 }, { selector: selector }); 1512 }, { selector: selector });
...@@ -1463,6 +1535,7 @@ Casper.prototype.warn = function warn(message) { ...@@ -1463,6 +1535,7 @@ Casper.prototype.warn = function warn(message) {
1463 */ 1535 */
1464 Casper.prototype.wait = function wait(timeout, then) { 1536 Casper.prototype.wait = function wait(timeout, then) {
1465 "use strict"; 1537 "use strict";
1538 this.checkStarted();
1466 timeout = ~~timeout; 1539 timeout = ~~timeout;
1467 if (timeout < 1) { 1540 if (timeout < 1) {
1468 this.die("wait() only accepts a positive integer > 0 as a timeout value"); 1541 this.die("wait() only accepts a positive integer > 0 as a timeout value");
...@@ -1505,6 +1578,7 @@ Casper.prototype.waitDone = function waitDone() { ...@@ -1505,6 +1578,7 @@ Casper.prototype.waitDone = function waitDone() {
1505 */ 1578 */
1506 Casper.prototype.waitFor = function waitFor(testFx, then, onTimeout, timeout) { 1579 Casper.prototype.waitFor = function waitFor(testFx, then, onTimeout, timeout) {
1507 "use strict"; 1580 "use strict";
1581 this.checkStarted();
1508 timeout = timeout ? timeout : this.options.waitTimeout; 1582 timeout = timeout ? timeout : this.options.waitTimeout;
1509 if (!utils.isFunction(testFx)) { 1583 if (!utils.isFunction(testFx)) {
1510 this.die("waitFor() needs a test function"); 1584 this.die("waitFor() needs a test function");
...@@ -1553,6 +1627,7 @@ Casper.prototype.waitFor = function waitFor(testFx, then, onTimeout, timeout) { ...@@ -1553,6 +1627,7 @@ Casper.prototype.waitFor = function waitFor(testFx, then, onTimeout, timeout) {
1553 */ 1627 */
1554 Casper.prototype.waitForResource = function waitForResource(test, then, onTimeout, timeout) { 1628 Casper.prototype.waitForResource = function waitForResource(test, then, onTimeout, timeout) {
1555 "use strict"; 1629 "use strict";
1630 this.checkStarted();
1556 timeout = timeout ? timeout : this.options.waitTimeout; 1631 timeout = timeout ? timeout : this.options.waitTimeout;
1557 return this.waitFor(function _check() { 1632 return this.waitFor(function _check() {
1558 return this.resourceExists(test); 1633 return this.resourceExists(test);
...@@ -1571,6 +1646,7 @@ Casper.prototype.waitForResource = function waitForResource(test, then, onTimeou ...@@ -1571,6 +1646,7 @@ Casper.prototype.waitForResource = function waitForResource(test, then, onTimeou
1571 */ 1646 */
1572 Casper.prototype.waitForSelector = function waitForSelector(selector, then, onTimeout, timeout) { 1647 Casper.prototype.waitForSelector = function waitForSelector(selector, then, onTimeout, timeout) {
1573 "use strict"; 1648 "use strict";
1649 this.checkStarted();
1574 timeout = timeout ? timeout : this.options.waitTimeout; 1650 timeout = timeout ? timeout : this.options.waitTimeout;
1575 return this.waitFor(function _check() { 1651 return this.waitFor(function _check() {
1576 return this.exists(selector); 1652 return this.exists(selector);
...@@ -1589,6 +1665,7 @@ Casper.prototype.waitForSelector = function waitForSelector(selector, then, onTi ...@@ -1589,6 +1665,7 @@ Casper.prototype.waitForSelector = function waitForSelector(selector, then, onTi
1589 */ 1665 */
1590 Casper.prototype.waitWhileSelector = function waitWhileSelector(selector, then, onTimeout, timeout) { 1666 Casper.prototype.waitWhileSelector = function waitWhileSelector(selector, then, onTimeout, timeout) {
1591 "use strict"; 1667 "use strict";
1668 this.checkStarted();
1592 timeout = timeout ? timeout : this.options.waitTimeout; 1669 timeout = timeout ? timeout : this.options.waitTimeout;
1593 return this.waitFor(function _check() { 1670 return this.waitFor(function _check() {
1594 return !this.exists(selector); 1671 return !this.exists(selector);
...@@ -1607,6 +1684,7 @@ Casper.prototype.waitWhileSelector = function waitWhileSelector(selector, then, ...@@ -1607,6 +1684,7 @@ Casper.prototype.waitWhileSelector = function waitWhileSelector(selector, then,
1607 */ 1684 */
1608 Casper.prototype.waitUntilVisible = function waitUntilVisible(selector, then, onTimeout, timeout) { 1685 Casper.prototype.waitUntilVisible = function waitUntilVisible(selector, then, onTimeout, timeout) {
1609 "use strict"; 1686 "use strict";
1687 this.checkStarted();
1610 timeout = timeout ? timeout : this.options.waitTimeout; 1688 timeout = timeout ? timeout : this.options.waitTimeout;
1611 return this.waitFor(function _check() { 1689 return this.waitFor(function _check() {
1612 return this.visible(selector); 1690 return this.visible(selector);
...@@ -1625,6 +1703,7 @@ Casper.prototype.waitUntilVisible = function waitUntilVisible(selector, then, on ...@@ -1625,6 +1703,7 @@ Casper.prototype.waitUntilVisible = function waitUntilVisible(selector, then, on
1625 */ 1703 */
1626 Casper.prototype.waitWhileVisible = function waitWhileVisible(selector, then, onTimeout, timeout) { 1704 Casper.prototype.waitWhileVisible = function waitWhileVisible(selector, then, onTimeout, timeout) {
1627 "use strict"; 1705 "use strict";
1706 this.checkStarted();
1628 timeout = timeout ? timeout : this.options.waitTimeout; 1707 timeout = timeout ? timeout : this.options.waitTimeout;
1629 return this.waitFor(function _check() { 1708 return this.waitFor(function _check() {
1630 return !this.visible(selector); 1709 return !this.visible(selector);
...@@ -1639,17 +1718,11 @@ Casper.prototype.waitWhileVisible = function waitWhileVisible(selector, then, on ...@@ -1639,17 +1718,11 @@ Casper.prototype.waitWhileVisible = function waitWhileVisible(selector, then, on
1639 */ 1718 */
1640 Casper.prototype.zoom = function zoom(factor) { 1719 Casper.prototype.zoom = function zoom(factor) {
1641 "use strict"; 1720 "use strict";
1642 if (!this.started) { 1721 this.checkStarted();
1643 throw new CasperError("Casper has not been started, can't set zoom factor");
1644 }
1645 if (!utils.isNumber(factor) || factor <= 0) { 1722 if (!utils.isNumber(factor) || factor <= 0) {
1646 throw new CasperError("Invalid zoom factor: " + factor); 1723 throw new CasperError("Invalid zoom factor: " + factor);
1647 } 1724 }
1648 if ('zoomFactor' in this.page) {
1649 this.page.zoomFactor = factor; 1725 this.page.zoomFactor = factor;
1650 } else {
1651 this.warn("zoom() requires PhantomJS >= 1.6");
1652 }
1653 return this; 1726 return this;
1654 }; 1727 };
1655 1728
...@@ -1662,7 +1735,7 @@ Casper.prototype.zoom = function zoom(factor) { ...@@ -1662,7 +1735,7 @@ Casper.prototype.zoom = function zoom(factor) {
1662 */ 1735 */
1663 Casper.extend = function(proto) { 1736 Casper.extend = function(proto) {
1664 "use strict"; 1737 "use strict";
1665 this.warn('Casper.extend() has been deprecated since 0.6; check the docs'); 1738 this.emit("deprecated", "Casper.extend() has been deprecated since 0.6; check the docs")
1666 if (!utils.isObject(proto)) { 1739 if (!utils.isObject(proto)) {
1667 throw new CasperError("extends() only accept objects as prototypes"); 1740 throw new CasperError("extends() only accept objects as prototypes");
1668 } 1741 }
...@@ -1731,21 +1804,7 @@ function createPage(casper) { ...@@ -1731,21 +1804,7 @@ function createPage(casper) {
1731 casper.options.onLoadError.call(casper, casper, casper.requestUrl, status); 1804 casper.options.onLoadError.call(casper, casper, casper.requestUrl, status);
1732 } 1805 }
1733 } 1806 }
1734 if (casper.options.clientScripts) { 1807 casper.injectClientScripts();
1735 if (utils.isString(casper.options.clientScripts)) {
1736 casper.options.clientScripts = [casper.options.clientScripts];
1737 }
1738 if (!utils.isArray(casper.options.clientScripts)) {
1739 throw new CasperError("The clientScripts option must be an array");
1740 }
1741 casper.options.clientScripts.forEach(function _forEach(script) {
1742 if (casper.page.injectJs(script)) {
1743 casper.log(f('Automatically injected %s client side', script), "debug");
1744 } else {
1745 casper.warn('Failed injecting %s client side', script);
1746 }
1747 });
1748 }
1749 // Client-side utils injection 1808 // Client-side utils injection
1750 casper.injectClientUtils(); 1809 casper.injectClientUtils();
1751 // history 1810 // history
...@@ -1765,34 +1824,12 @@ function createPage(casper) { ...@@ -1765,34 +1824,12 @@ function createPage(casper) {
1765 return casper.filter('page.prompt', message, value); 1824 return casper.filter('page.prompt', message, value);
1766 }; 1825 };
1767 page.onResourceReceived = function onResourceReceived(resource) { 1826 page.onResourceReceived = function onResourceReceived(resource) {
1768 if (utils.isHTTPResource(resource)) { 1827 http.augmentResponse(resource);
1769 require('http').augmentResponse(resource);
1770 } else {
1771 casper.log(f('Non-HTTP resource received from %s', resource.url), "debug");
1772 }
1773 casper.emit('resource.received', resource); 1828 casper.emit('resource.received', resource);
1774 if (utils.isFunction(casper.options.onResourceReceived)) { 1829 if (utils.isFunction(casper.options.onResourceReceived)) {
1775 casper.options.onResourceReceived.call(casper, casper, resource); 1830 casper.options.onResourceReceived.call(casper, casper, resource);
1776 } 1831 }
1777 if (resource.stage === "end") { 1832 casper.handleReceivedResource(resource);
1778 casper.resources.push(resource);
1779 }
1780 if (resource.url === casper.requestUrl && resource.stage === "end") {
1781 casper.currentHTTPStatus = null;
1782 casper.currentResponse = undefined;
1783 if (utils.isHTTPResource(resource)) {
1784 casper.currentResponse = resource;
1785 casper.currentHTTPStatus = resource.status;
1786 casper.emit('http.status.' + resource.status, resource);
1787 if (utils.isObject(casper.options.httpStatusHandlers) &&
1788 resource.status in casper.options.httpStatusHandlers &&
1789 utils.isFunction(casper.options.httpStatusHandlers[resource.status])) {
1790 casper.options.httpStatusHandlers[resource.status].call(casper, casper, resource);
1791 }
1792 }
1793 casper.currentUrl = resource.url;
1794 casper.emit('location.changed', resource.url);
1795 }
1796 }; 1833 };
1797 page.onResourceRequested = function onResourceRequested(request) { 1834 page.onResourceRequested = function onResourceRequested(request) {
1798 casper.emit('resource.requested', request); 1835 casper.emit('resource.requested', request);
......
...@@ -75,6 +75,7 @@ ...@@ -75,6 +75,7 @@
75 * @return string 75 * @return string
76 */ 76 */
77 this.decode = function decode(str) { 77 this.decode = function decode(str) {
78 /*jshint maxstatements:30 maxcomplexity:30 */
78 var c1, c2, c3, c4, i = 0, len = str.length, out = ""; 79 var c1, c2, c3, c4, i = 0, len = str.length, out = "";
79 while (i < len) { 80 while (i < len) {
80 do { 81 do {
...@@ -123,6 +124,7 @@ ...@@ -123,6 +124,7 @@
123 * @return string 124 * @return string
124 */ 125 */
125 this.encode = function encode(str) { 126 this.encode = function encode(str) {
127 /*jshint maxstatements:30 */
126 var out = "", i = 0, len = str.length, c1, c2, c3; 128 var out = "", i = 0, len = str.length, c1, c2, c3;
127 while (i < len) { 129 while (i < len) {
128 c1 = str.charCodeAt(i++) & 0xff; 130 c1 = str.charCodeAt(i++) & 0xff;
...@@ -295,37 +297,14 @@ ...@@ -295,37 +297,14 @@
295 * Retrieves string contents from a binary file behind an url. Silently 297 * Retrieves string contents from a binary file behind an url. Silently
296 * fails but log errors. 298 * fails but log errors.
297 * 299 *
298 * @param String url 300 * @param String url Url.
299 * @param String method 301 * @param String method HTTP method.
300 * @param Object data 302 * @param Object data Request parameters.
301 * @return string 303 * @return String
302 */ 304 */
303 this.getBinary = function getBinary(url, method, data) { 305 this.getBinary = function getBinary(url, method, data) {
304 try { 306 try {
305 var xhr = new XMLHttpRequest(), dataString = ""; 307 return this.sendAJAX(url, method, data, false);
306 if (typeof method !== "string" || ["GET", "POST"].indexOf(method.toUpperCase()) === -1) {
307 method = "GET";
308 } else {
309 method = method.toUpperCase();
310 }
311 xhr.open(method, url, false);
312 this.log("getBinary(): Using HTTP method: '" + method + "'", "debug");
313 xhr.overrideMimeType("text/plain; charset=x-user-defined");
314 if (method === "POST") {
315 if (typeof data === "object") {
316 var dataList = [];
317 for (var k in data) {
318 dataList.push(encodeURIComponent(k) + "=" + encodeURIComponent(data[k].toString()));
319 }
320 dataString = dataList.join('&');
321 this.log("getBinary(): Using request data: '" + dataString + "'", "debug");
322 } else if (typeof data === "string") {
323 dataString = data;
324 }
325 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
326 }
327 xhr.send(method === "POST" ? dataString : null);
328 return xhr.responseText;
329 } catch (e) { 308 } catch (e) {
330 if (e.name === "NETWORK_ERR" && e.code === 101) { 309 if (e.name === "NETWORK_ERR" && e.code === 101) {
331 this.log("getBinary(): Unfortunately, casperjs cannot make cross domain ajax requests", "warning"); 310 this.log("getBinary(): Unfortunately, casperjs cannot make cross domain ajax requests", "warning");
...@@ -529,6 +508,42 @@ ...@@ -529,6 +508,42 @@
529 }; 508 };
530 509
531 /** 510 /**
511 * Performs an AJAX request.
512 *
513 * @param String url Url.
514 * @param String method HTTP method.
515 * @param Object data Request parameters.
516 * @param Boolean async Asynchroneous request? (default: false)
517 * @return String Response text.
518 */
519 this.sendAJAX = function sendAJAX(url, method, data, async) {
520 var xhr = new XMLHttpRequest(), dataString = "";
521 if (typeof method !== "string" || ["GET", "POST"].indexOf(method.toUpperCase()) === -1) {
522 method = "GET";
523 } else {
524 method = method.toUpperCase();
525 }
526 xhr.open(method, url, !!async);
527 this.log("getBinary(): Using HTTP method: '" + method + "'", "debug");
528 xhr.overrideMimeType("text/plain; charset=x-user-defined");
529 if (method === "POST") {
530 if (typeof data === "object") {
531 var dataList = [];
532 for (var k in data) {
533 dataList.push(encodeURIComponent(k) + "=" + encodeURIComponent(data[k].toString()));
534 }
535 dataString = dataList.join('&');
536 this.log("sendAJAX(): Using request data: '" + dataString + "'", "debug");
537 } else if (typeof data === "string") {
538 dataString = data;
539 }
540 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
541 }
542 xhr.send(method === "POST" ? dataString : null);
543 return xhr.responseText;
544 };
545
546 /**
532 * Sets a field (or a set of fields) value. Fails silently, but log 547 * Sets a field (or a set of fields) value. Fails silently, but log
533 * error messages. 548 * error messages.
534 * 549 *
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
28 * 28 *
29 */ 29 */
30 30
31 var utils = require('utils');
32
31 /* 33 /*
32 * Building an Array subclass 34 * Building an Array subclass
33 */ 35 */
...@@ -59,7 +61,8 @@ responseHeaders.prototype.get = function get(name){ ...@@ -59,7 +61,8 @@ responseHeaders.prototype.get = function get(name){
59 * @param mixed response Phantom response or undefined (generally with local files) 61 * @param mixed response Phantom response or undefined (generally with local files)
60 */ 62 */
61 exports.augmentResponse = function(response) { 63 exports.augmentResponse = function(response) {
62 if (response === undefined) { 64 "use strict";
65 if (!utils.isHTTPResource(response)) {
63 return; 66 return;
64 } 67 }
65 response.headers.__proto__ = responseHeaders.prototype; 68 response.headers.__proto__ = responseHeaders.prototype;
......
...@@ -53,6 +53,8 @@ var Tester = function Tester(casper, options) { ...@@ -53,6 +53,8 @@ var Tester = function Tester(casper, options) {
53 throw new CasperError("Tester needs a Casper instance"); 53 throw new CasperError("Tester needs a Casper instance");
54 } 54 }
55 55
56 this.casper = casper;
57
56 this.currentTestFile = null; 58 this.currentTestFile = null;
57 this.currentSuiteNum = 0; 59 this.currentSuiteNum = 0;
58 this.exporter = require('xunit').create(); 60 this.exporter = require('xunit').create();
...@@ -132,7 +134,7 @@ var Tester = function Tester(casper, options) { ...@@ -132,7 +134,7 @@ var Tester = function Tester(casper, options) {
132 } catch (e) { 134 } catch (e) {
133 try { 135 try {
134 comment += utils.serialize(failure.values[name].toString()); 136 comment += utils.serialize(failure.values[name].toString());
135 } catch (e) { 137 } catch (e2) {
136 comment += '(unserializable value)'; 138 comment += '(unserializable value)';
137 } 139 }
138 } 140 }
...@@ -140,9 +142,13 @@ var Tester = function Tester(casper, options) { ...@@ -140,9 +142,13 @@ var Tester = function Tester(casper, options) {
140 } 142 }
141 } 143 }
142 }); 144 });
145 };
146
147 // Tester class is an EventEmitter
148 utils.inherits(Tester, events.EventEmitter);
149 exports.Tester = Tester;
143 150
144 // methods 151 /**
145 /**
146 * Asserts that a condition strictly resolves to true. Also returns an 152 * Asserts that a condition strictly resolves to true. Also returns an
147 * "assertion object" containing useful informations about the test case 153 * "assertion object" containing useful informations about the test case
148 * results. 154 * results.
...@@ -156,7 +162,8 @@ var Tester = function Tester(casper, options) { ...@@ -156,7 +162,8 @@ var Tester = function Tester(casper, options) {
156 * @param Object|null context Assertion context object (Optional) 162 * @param Object|null context Assertion context object (Optional)
157 * @return Object An assertion result object 163 * @return Object An assertion result object
158 */ 164 */
159 this.assert = this.assertTrue = function assert(subject, message, context) { 165 Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, message, context) {
166 "use strict";
160 return this.processAssertionResult(utils.mergeObjects({ 167 return this.processAssertionResult(utils.mergeObjects({
161 success: subject === true, 168 success: subject === true,
162 type: "assert", 169 type: "assert",
...@@ -167,9 +174,9 @@ var Tester = function Tester(casper, options) { ...@@ -167,9 +174,9 @@ var Tester = function Tester(casper, options) {
167 subject: utils.getPropertyPath(context, 'values.subject') || subject 174 subject: utils.getPropertyPath(context, 'values.subject') || subject
168 } 175 }
169 }, context || {})); 176 }, context || {}));
170 }; 177 };
171 178
172 /** 179 /**
173 * Asserts that two values are strictly equals. 180 * Asserts that two values are strictly equals.
174 * 181 *
175 * @param Mixed subject The value to test 182 * @param Mixed subject The value to test
...@@ -177,7 +184,8 @@ var Tester = function Tester(casper, options) { ...@@ -177,7 +184,8 @@ var Tester = function Tester(casper, options) {
177 * @param String message Test description (Optional) 184 * @param String message Test description (Optional)
178 * @return Object An assertion result object 185 * @return Object An assertion result object
179 */ 186 */
180 this.assertEquals = this.assertEqual = function assertEquals(subject, expected, message) { 187 Tester.prototype.assertEquals = Tester.prototype.assertEqual = function assertEquals(subject, expected, message) {
188 "use strict";
181 return this.assert(this.testEquals(subject, expected), message, { 189 return this.assert(this.testEquals(subject, expected), message, {
182 type: "assertEquals", 190 type: "assertEquals",
183 standard: "Subject equals the expected value", 191 standard: "Subject equals the expected value",
...@@ -186,9 +194,9 @@ var Tester = function Tester(casper, options) { ...@@ -186,9 +194,9 @@ var Tester = function Tester(casper, options) {
186 expected: expected 194 expected: expected
187 } 195 }
188 }); 196 });
189 }; 197 };
190 198
191 /** 199 /**
192 * Asserts that two values are strictly not equals. 200 * Asserts that two values are strictly not equals.
193 * 201 *
194 * @param Mixed subject The value to test 202 * @param Mixed subject The value to test
...@@ -196,7 +204,8 @@ var Tester = function Tester(casper, options) { ...@@ -196,7 +204,8 @@ var Tester = function Tester(casper, options) {
196 * @param String|null message Test description (Optional) 204 * @param String|null message Test description (Optional)
197 * @return Object An assertion result object 205 * @return Object An assertion result object
198 */ 206 */
199 this.assertNotEquals = function assertNotEquals(subject, shouldnt, message) { 207 Tester.prototype.assertNotEquals = function assertNotEquals(subject, shouldnt, message) {
208 "use strict";
200 return this.assert(!this.testEquals(subject, shouldnt), message, { 209 return this.assert(!this.testEquals(subject, shouldnt), message, {
201 type: "assertNotEquals", 210 type: "assertNotEquals",
202 standard: "Subject doesn't equal what it shouldn't be", 211 standard: "Subject doesn't equal what it shouldn't be",
...@@ -205,9 +214,9 @@ var Tester = function Tester(casper, options) { ...@@ -205,9 +214,9 @@ var Tester = function Tester(casper, options) {
205 shouldnt: shouldnt 214 shouldnt: shouldnt
206 } 215 }
207 }); 216 });
208 }; 217 };
209 218
210 /** 219 /**
211 * Asserts that a code evaluation in remote DOM resolves to true. 220 * Asserts that a code evaluation in remote DOM resolves to true.
212 * 221 *
213 * @param Function fn A function to be evaluated in remote DOM 222 * @param Function fn A function to be evaluated in remote DOM
...@@ -215,8 +224,9 @@ var Tester = function Tester(casper, options) { ...@@ -215,8 +224,9 @@ var Tester = function Tester(casper, options) {
215 * @param Object params Object containing the parameters to inject into the function (optional) 224 * @param Object params Object containing the parameters to inject into the function (optional)
216 * @return Object An assertion result object 225 * @return Object An assertion result object
217 */ 226 */
218 this.assertEval = this.assertEvaluate = function assertEval(fn, message, params) { 227 Tester.prototype.assertEval = Tester.prototype.assertEvaluate = function assertEval(fn, message, params) {
219 return this.assert(casper.evaluate(fn, params), message, { 228 "use strict";
229 return this.assert(this.casper.evaluate(fn, params), message, {
220 type: "assertEval", 230 type: "assertEval",
221 standard: "Evaluated function returns true", 231 standard: "Evaluated function returns true",
222 values: { 232 values: {
...@@ -224,9 +234,9 @@ var Tester = function Tester(casper, options) { ...@@ -224,9 +234,9 @@ var Tester = function Tester(casper, options) {
224 params: params 234 params: params
225 } 235 }
226 }); 236 });
227 }; 237 };
228 238
229 /** 239 /**
230 * Asserts that the result of a code evaluation in remote DOM equals 240 * Asserts that the result of a code evaluation in remote DOM equals
231 * an expected value. 241 * an expected value.
232 * 242 *
...@@ -236,8 +246,9 @@ var Tester = function Tester(casper, options) { ...@@ -236,8 +246,9 @@ var Tester = function Tester(casper, options) {
236 * @param Object|null params Object containing the parameters to inject into the function (optional) 246 * @param Object|null params Object containing the parameters to inject into the function (optional)
237 * @return Object An assertion result object 247 * @return Object An assertion result object
238 */ 248 */
239 this.assertEvalEquals = this.assertEvalEqual = function assertEvalEquals(fn, expected, message, params) { 249 Tester.prototype.assertEvalEquals = Tester.prototype.assertEvalEqual = function assertEvalEquals(fn, expected, message, params) {
240 var subject = casper.evaluate(fn, params); 250 "use strict";
251 var subject = this.casper.evaluate(fn, params);
241 return this.assert(this.testEquals(subject, expected), message, { 252 return this.assert(this.testEquals(subject, expected), message, {
242 type: "assertEvalEquals", 253 type: "assertEvalEquals",
243 standard: "Evaluated function returns the expected value", 254 standard: "Evaluated function returns the expected value",
...@@ -248,9 +259,9 @@ var Tester = function Tester(casper, options) { ...@@ -248,9 +259,9 @@ var Tester = function Tester(casper, options) {
248 expected: expected 259 expected: expected
249 } 260 }
250 }); 261 });
251 }; 262 };
252 263
253 /** 264 /**
254 * Asserts that a given input field has the provided value. 265 * Asserts that a given input field has the provided value.
255 * 266 *
256 * @param String input_name The name attribute of the input element 267 * @param String input_name The name attribute of the input element
...@@ -258,8 +269,9 @@ var Tester = function Tester(casper, options) { ...@@ -258,8 +269,9 @@ var Tester = function Tester(casper, options) {
258 * @param String message Test description 269 * @param String message Test description
259 * @return Object An assertion result object 270 * @return Object An assertion result object
260 */ 271 */
261 this.assertField = function assertField(input_name, expected_value, message) { 272 Tester.prototype.assertField = function assertField(input_name, expected_value, message) {
262 var actual_value = casper.evaluate(function(input_name) { 273 "use strict";
274 var actual_value = this.casper.evaluate(function(input_name) {
263 var input = document.querySelector('input[name="' + input_name + '"]'); 275 var input = document.querySelector('input[name="' + input_name + '"]');
264 return input ? input.value : null; 276 return input ? input.value : null;
265 }, { input_name: input_name }); 277 }, { input_name: input_name });
...@@ -272,9 +284,9 @@ var Tester = function Tester(casper, options) { ...@@ -272,9 +284,9 @@ var Tester = function Tester(casper, options) {
272 expected_value: expected_value 284 expected_value: expected_value
273 } 285 }
274 }); 286 });
275 }; 287 };
276 288
277 /** 289 /**
278 * Asserts that an element matching the provided selector expression exists in 290 * Asserts that an element matching the provided selector expression exists in
279 * remote DOM. 291 * remote DOM.
280 * 292 *
...@@ -282,17 +294,18 @@ var Tester = function Tester(casper, options) { ...@@ -282,17 +294,18 @@ var Tester = function Tester(casper, options) {
282 * @param String message Test description 294 * @param String message Test description
283 * @return Object An assertion result object 295 * @return Object An assertion result object
284 */ 296 */
285 this.assertExists = this.assertExist = this.assertSelectorExists = this.assertSelectorExist = function assertExists(selector, message) { 297 Tester.prototype.assertExists = Tester.prototype.assertExist = this.assertSelectorExists = Tester.prototype.assertSelectorExist = function assertExists(selector, message) {
286 return this.assert(casper.exists(selector), message, { 298 "use strict";
299 return this.assert(this.casper.exists(selector), message, {
287 type: "assertExists", 300 type: "assertExists",
288 standard: f("Found an element matching: %s", selector), 301 standard: f("Found an element matching: %s", selector),
289 values: { 302 values: {
290 selector: selector 303 selector: selector
291 } 304 }
292 }); 305 });
293 }; 306 };
294 307
295 /** 308 /**
296 * Asserts that an element matching the provided selector expression does not 309 * Asserts that an element matching the provided selector expression does not
297 * exists in remote DOM. 310 * exists in remote DOM.
298 * 311 *
...@@ -300,26 +313,28 @@ var Tester = function Tester(casper, options) { ...@@ -300,26 +313,28 @@ var Tester = function Tester(casper, options) {
300 * @param String message Test description 313 * @param String message Test description
301 * @return Object An assertion result object 314 * @return Object An assertion result object
302 */ 315 */
303 this.assertDoesntExist = this.assertNotExists = function assertDoesntExist(selector, message) { 316 Tester.prototype.assertDoesntExist = Tester.prototype.assertNotExists = function assertDoesntExist(selector, message) {
304 return this.assert(!casper.exists(selector), message, { 317 "use strict";
318 return this.assert(!this.casper.exists(selector), message, {
305 type: "assertDoesntExist", 319 type: "assertDoesntExist",
306 standard: f("No element found matching selector: %s", selector), 320 standard: f("No element found matching selector: %s", selector),
307 values: { 321 values: {
308 selector: selector 322 selector: selector
309 } 323 }
310 }); 324 });
311 }; 325 };
312 326
313 /** 327 /**
314 * Asserts that current HTTP status is the one passed as argument. 328 * Asserts that current HTTP status is the one passed as argument.
315 * 329 *
316 * @param Number status HTTP status code 330 * @param Number status HTTP status code
317 * @param String message Test description 331 * @param String message Test description
318 * @return Object An assertion result object 332 * @return Object An assertion result object
319 */ 333 */
320 this.assertHttpStatus = function assertHttpStatus(status, message) { 334 Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) {
321 var currentHTTPStatus = casper.currentHTTPStatus; 335 "use strict";
322 return this.assert(this.testEquals(casper.currentHTTPStatus, status), message, { 336 var currentHTTPStatus = this.casper.currentHTTPStatus;
337 return this.assert(this.testEquals(this.casper.currentHTTPStatus, status), message, {
323 type: "assertHttpStatus", 338 type: "assertHttpStatus",
324 standard: f("HTTP status code is: %s", status), 339 standard: f("HTTP status code is: %s", status),
325 values: { 340 values: {
...@@ -327,9 +342,9 @@ var Tester = function Tester(casper, options) { ...@@ -327,9 +342,9 @@ var Tester = function Tester(casper, options) {
327 expected: status 342 expected: status
328 } 343 }
329 }); 344 });
330 }; 345 };
331 346
332 /** 347 /**
333 * Asserts that a provided string matches a provided RegExp pattern. 348 * Asserts that a provided string matches a provided RegExp pattern.
334 * 349 *
335 * @param String subject The string to test 350 * @param String subject The string to test
...@@ -337,7 +352,8 @@ var Tester = function Tester(casper, options) { ...@@ -337,7 +352,8 @@ var Tester = function Tester(casper, options) {
337 * @param String message Test description 352 * @param String message Test description
338 * @return Object An assertion result object 353 * @return Object An assertion result object
339 */ 354 */
340 this.assertMatch = this.assertMatches = function assertMatch(subject, pattern, message) { 355 Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertMatch(subject, pattern, message) {
356 "use strict";
341 return this.assert(pattern.test(subject), message, { 357 return this.assert(pattern.test(subject), message, {
342 type: "assertMatch", 358 type: "assertMatch",
343 standard: "Subject matches the provided pattern", 359 standard: "Subject matches the provided pattern",
...@@ -346,16 +362,17 @@ var Tester = function Tester(casper, options) { ...@@ -346,16 +362,17 @@ var Tester = function Tester(casper, options) {
346 pattern: pattern.toString() 362 pattern: pattern.toString()
347 } 363 }
348 }); 364 });
349 }; 365 };
350 366
351 /** 367 /**
352 * Asserts a condition resolves to false. 368 * Asserts a condition resolves to false.
353 * 369 *
354 * @param Boolean condition The condition to test 370 * @param Boolean condition The condition to test
355 * @param String message Test description 371 * @param String message Test description
356 * @return Object An assertion result object 372 * @return Object An assertion result object
357 */ 373 */
358 this.assertNot = function assertNot(condition, message) { 374 Tester.prototype.assertNot = function assertNot(condition, message) {
375 "use strict";
359 return this.assert(!condition, message, { 376 return this.assert(!condition, message, {
360 type: "assertNot", 377 type: "assertNot",
361 standard: "Subject is falsy", 378 standard: "Subject is falsy",
...@@ -363,26 +380,27 @@ var Tester = function Tester(casper, options) { ...@@ -363,26 +380,27 @@ var Tester = function Tester(casper, options) {
363 condition: condition 380 condition: condition
364 } 381 }
365 }); 382 });
366 }; 383 };
367 384
368 /** 385 /**
369 * Asserts that a selector expression is not currently visible. 386 * Asserts that a selector expression is not currently visible.
370 * 387 *
371 * @param String expected selector expression 388 * @param String expected selector expression
372 * @param String message Test description 389 * @param String message Test description
373 * @return Object An assertion result object 390 * @return Object An assertion result object
374 */ 391 */
375 this.assertNotVisible = this.assertInvisible = function assertNotVisible(selector, message) { 392 Tester.prototype.assertNotVisible = Tester.prototype.assertInvisible = function assertNotVisible(selector, message) {
376 return this.assert(!casper.visible(selector), message, { 393 "use strict";
394 return this.assert(!this.casper.visible(selector), message, {
377 type: "assertVisible", 395 type: "assertVisible",
378 standard: "Selector is not visible", 396 standard: "Selector is not visible",
379 values: { 397 values: {
380 selector: selector 398 selector: selector
381 } 399 }
382 }); 400 });
383 }; 401 };
384 402
385 /** 403 /**
386 * Asserts that the provided function called with the given parameters 404 * Asserts that the provided function called with the given parameters
387 * will raise an exception. 405 * will raise an exception.
388 * 406 *
...@@ -391,7 +409,8 @@ var Tester = function Tester(casper, options) { ...@@ -391,7 +409,8 @@ var Tester = function Tester(casper, options) {
391 * @param String message Test description 409 * @param String message Test description
392 * @return Object An assertion result object 410 * @return Object An assertion result object
393 */ 411 */
394 this.assertRaises = this.assertRaise = this.assertThrows = function assertRaises(fn, args, message) { 412 Tester.prototype.assertRaises = Tester.prototype.assertRaise = this.assertThrows = function assertRaises(fn, args, message) {
413 "use strict";
395 var context = { 414 var context = {
396 type: "assertRaises", 415 type: "assertRaises",
397 standard: "Function raises an error" 416 standard: "Function raises an error"
...@@ -406,34 +425,36 @@ var Tester = function Tester(casper, options) { ...@@ -406,34 +425,36 @@ var Tester = function Tester(casper, options) {
406 } 425 }
407 })); 426 }));
408 } 427 }
409 }; 428 };
410 429
411 /** 430 /**
412 * Asserts that the current page has a resource that matches the provided test 431 * Asserts that the current page has a resource that matches the provided test
413 * 432 *
414 * @param Function/String test A test function that is called with every response 433 * @param Function/String test A test function that is called with every response
415 * @param String message Test description 434 * @param String message Test description
416 * @return Object An assertion result object 435 * @return Object An assertion result object
417 */ 436 */
418 this.assertResourceExists = this.assertResourceExist = function assertResourceExists(test, message) { 437 Tester.prototype.assertResourceExists = Tester.prototype.assertResourceExist = function assertResourceExists(test, message) {
419 return this.assert(casper.resourceExists(test), message, { 438 "use strict";
439 return this.assert(this.casper.resourceExists(test), message, {
420 type: "assertResourceExists", 440 type: "assertResourceExists",
421 standard: "Expected resource has been found", 441 standard: "Expected resource has been found",
422 values: { 442 values: {
423 test: test 443 test: test
424 } 444 }
425 }); 445 });
426 }; 446 };
427 447
428 /** 448 /**
429 * Asserts that given text exists in the document body. 449 * Asserts that given text exists in the document body.
430 * 450 *
431 * @param String text Text to be found 451 * @param String text Text to be found
432 * @param String message Test description 452 * @param String message Test description
433 * @return Object An assertion result object 453 * @return Object An assertion result object
434 */ 454 */
435 this.assertTextExists = this.assertTextExist = function assertTextExists(text, message) { 455 Tester.prototype.assertTextExists = Tester.prototype.assertTextExist = function assertTextExists(text, message) {
436 var textFound = (casper.evaluate(function _evaluate() { 456 "use strict";
457 var textFound = (this.casper.evaluate(function _evaluate() {
437 return document.body.textContent || document.body.innerText; 458 return document.body.textContent || document.body.innerText;
438 }).indexOf(text) !== -1); 459 }).indexOf(text) !== -1);
439 return this.assert(textFound, message, { 460 return this.assert(textFound, message, {
...@@ -443,9 +464,9 @@ var Tester = function Tester(casper, options) { ...@@ -443,9 +464,9 @@ var Tester = function Tester(casper, options) {
443 text: text 464 text: text
444 } 465 }
445 }); 466 });
446 }; 467 };
447 468
448 /** 469 /**
449 * Asserts that given text exists in the provided selector. 470 * Asserts that given text exists in the provided selector.
450 * 471 *
451 * @param String selector Selector expression 472 * @param String selector Selector expression
...@@ -453,8 +474,9 @@ var Tester = function Tester(casper, options) { ...@@ -453,8 +474,9 @@ var Tester = function Tester(casper, options) {
453 * @param String message Test description 474 * @param String message Test description
454 * @return Object An assertion result object 475 * @return Object An assertion result object
455 */ 476 */
456 this.assertSelectorHasText = function assertSelectorHasText(selector, text, message) { 477 Tester.prototype.assertSelectorHasText = function assertSelectorHasText(selector, text, message) {
457 var textFound = casper.fetchText(selector).indexOf(text) !== -1; 478 "use strict";
479 var textFound = this.casper.fetchText(selector).indexOf(text) !== -1;
458 return this.assert(textFound, message, { 480 return this.assert(textFound, message, {
459 type: "assertTextInSelector", 481 type: "assertTextInSelector",
460 standard: f('Found "%s" within the selector "%s"', text, selector), 482 standard: f('Found "%s" within the selector "%s"', text, selector),
...@@ -463,9 +485,9 @@ var Tester = function Tester(casper, options) { ...@@ -463,9 +485,9 @@ var Tester = function Tester(casper, options) {
463 text: text 485 text: text
464 } 486 }
465 }); 487 });
466 }; 488 };
467 489
468 /** 490 /**
469 * Asserts that given text does not exist in the provided selector. 491 * Asserts that given text does not exist in the provided selector.
470 * 492 *
471 * @param String selector Selector expression 493 * @param String selector Selector expression
...@@ -473,8 +495,9 @@ var Tester = function Tester(casper, options) { ...@@ -473,8 +495,9 @@ var Tester = function Tester(casper, options) {
473 * @param String message Test description 495 * @param String message Test description
474 * @return Object An assertion result object 496 * @return Object An assertion result object
475 */ 497 */
476 this.assertSelectorDoesntHaveText = function assertSelectorDoesntHaveText(selector, text, message) { 498 Tester.prototype.assertSelectorDoesntHaveText = function assertSelectorDoesntHaveText(selector, text, message) {
477 var textFound = casper.fetchText(selector).indexOf(text) === -1; 499 "use strict";
500 var textFound = this.casper.fetchText(selector).indexOf(text) === -1;
478 return this.assert(textFound, message, { 501 return this.assert(textFound, message, {
479 type: "assertNoTextInSelector", 502 type: "assertNoTextInSelector",
480 standard: f('Did not find "%s" within the selector "%s"', text, selector), 503 standard: f('Did not find "%s" within the selector "%s"', text, selector),
...@@ -483,17 +506,18 @@ var Tester = function Tester(casper, options) { ...@@ -483,17 +506,18 @@ var Tester = function Tester(casper, options) {
483 text: text 506 text: text
484 } 507 }
485 }); 508 });
486 }; 509 };
487 510
488 /** 511 /**
489 * Asserts that title of the remote page equals to the expected one. 512 * Asserts that title of the remote page equals to the expected one.
490 * 513 *
491 * @param String expected The expected title string 514 * @param String expected The expected title string
492 * @param String message Test description 515 * @param String message Test description
493 * @return Object An assertion result object 516 * @return Object An assertion result object
494 */ 517 */
495 this.assertTitle = function assertTitle(expected, message) { 518 Tester.prototype.assertTitle = function assertTitle(expected, message) {
496 var currentTitle = casper.getTitle(); 519 "use strict";
520 var currentTitle = this.casper.getTitle();
497 return this.assert(this.testEquals(currentTitle, expected), message, { 521 return this.assert(this.testEquals(currentTitle, expected), message, {
498 type: "assertTitle", 522 type: "assertTitle",
499 standard: f('Page title is: "%s"', expected), 523 standard: f('Page title is: "%s"', expected),
...@@ -502,17 +526,18 @@ var Tester = function Tester(casper, options) { ...@@ -502,17 +526,18 @@ var Tester = function Tester(casper, options) {
502 expected: expected 526 expected: expected
503 } 527 }
504 }); 528 });
505 }; 529 };
506 530
507 /** 531 /**
508 * Asserts that title of the remote page matched the provided pattern. 532 * Asserts that title of the remote page matched the provided pattern.
509 * 533 *
510 * @param RegExp pattern The pattern to test the title against 534 * @param RegExp pattern The pattern to test the title against
511 * @param String message Test description 535 * @param String message Test description
512 * @return Object An assertion result object 536 * @return Object An assertion result object
513 */ 537 */
514 this.assertTitleMatch = this.assertTitleMatches = function assertTitleMatch(pattern, message) { 538 Tester.prototype.assertTitleMatch = Tester.prototype.assertTitleMatches = function assertTitleMatch(pattern, message) {
515 var currentTitle = casper.getTitle(); 539 "use strict";
540 var currentTitle = this.casper.getTitle();
516 return this.assert(pattern.test(currentTitle), message, { 541 return this.assert(pattern.test(currentTitle), message, {
517 type: "assertTitle", 542 type: "assertTitle",
518 details: "Page title does not match the provided pattern", 543 details: "Page title does not match the provided pattern",
...@@ -521,9 +546,9 @@ var Tester = function Tester(casper, options) { ...@@ -521,9 +546,9 @@ var Tester = function Tester(casper, options) {
521 pattern: pattern.toString() 546 pattern: pattern.toString()
522 } 547 }
523 }); 548 });
524 }; 549 };
525 550
526 /** 551 /**
527 * Asserts that the provided subject is of the given type. 552 * Asserts that the provided subject is of the given type.
528 * 553 *
529 * @param mixed subject The value to test 554 * @param mixed subject The value to test
...@@ -531,7 +556,8 @@ var Tester = function Tester(casper, options) { ...@@ -531,7 +556,8 @@ var Tester = function Tester(casper, options) {
531 * @param String message Test description 556 * @param String message Test description
532 * @return Object An assertion result object 557 * @return Object An assertion result object
533 */ 558 */
534 this.assertType = function assertType(subject, type, message) { 559 Tester.prototype.assertType = function assertType(subject, type, message) {
560 "use strict";
535 var actual = utils.betterTypeOf(subject); 561 var actual = utils.betterTypeOf(subject);
536 return this.assert(this.testEquals(actual, type), message, { 562 return this.assert(this.testEquals(actual, type), message, {
537 type: "assertType", 563 type: "assertType",
...@@ -542,9 +568,9 @@ var Tester = function Tester(casper, options) { ...@@ -542,9 +568,9 @@ var Tester = function Tester(casper, options) {
542 actual: actual 568 actual: actual
543 } 569 }
544 }); 570 });
545 }; 571 };
546 572
547 /** 573 /**
548 * Asserts that a the current page url matches the provided RegExp 574 * Asserts that a the current page url matches the provided RegExp
549 * pattern. 575 * pattern.
550 * 576 *
...@@ -552,8 +578,9 @@ var Tester = function Tester(casper, options) { ...@@ -552,8 +578,9 @@ var Tester = function Tester(casper, options) {
552 * @param String message Test description 578 * @param String message Test description
553 * @return Object An assertion result object 579 * @return Object An assertion result object
554 */ 580 */
555 this.assertUrlMatch = this.assertUrlMatches = function assertUrlMatch(pattern, message) { 581 Tester.prototype.assertUrlMatch = Tester.prototype.assertUrlMatches = function assertUrlMatch(pattern, message) {
556 var currentUrl = casper.getCurrentUrl(); 582 "use strict";
583 var currentUrl = this.casper.getCurrentUrl();
557 return this.assert(pattern.test(currentUrl), message, { 584 return this.assert(pattern.test(currentUrl), message, {
558 type: "assertUrlMatch", 585 type: "assertUrlMatch",
559 standard: "Current url matches the provided pattern", 586 standard: "Current url matches the provided pattern",
...@@ -562,75 +589,82 @@ var Tester = function Tester(casper, options) { ...@@ -562,75 +589,82 @@ var Tester = function Tester(casper, options) {
562 pattern: pattern.toString() 589 pattern: pattern.toString()
563 } 590 }
564 }); 591 });
565 }; 592 };
566 593
567 /** 594 /**
568 * Asserts that a selector expression is currently visible. 595 * Asserts that a selector expression is currently visible.
569 * 596 *
570 * @param String expected selector expression 597 * @param String expected selector expression
571 * @param String message Test description 598 * @param String message Test description
572 * @return Object An assertion result object 599 * @return Object An assertion result object
573 */ 600 */
574 this.assertVisible = function assertVisible(selector, message) { 601 Tester.prototype.assertVisible = function assertVisible(selector, message) {
575 return this.assert(casper.visible(selector), message, { 602 "use strict";
603 return this.assert(this.casper.visible(selector), message, {
576 type: "assertVisible", 604 type: "assertVisible",
577 standard: "Selector is visible", 605 standard: "Selector is visible",
578 values: { 606 values: {
579 selector: selector 607 selector: selector
580 } 608 }
581 }); 609 });
582 }; 610 };
583 611
584 /** 612 /**
585 * Prints out a colored bar onto the console. 613 * Prints out a colored bar onto the console.
586 * 614 *
587 */ 615 */
588 this.bar = function bar(text, style) { 616 Tester.prototype.bar = function bar(text, style) {
589 casper.echo(text, style, this.options.pad); 617 "use strict";
590 }; 618 this.casper.echo(text, style, this.options.pad);
619 };
591 620
592 /** 621 /**
593 * Render a colorized output. Basically a proxy method for 622 * Render a colorized output. Basically a proxy method for
594 * Casper.Colorizer#colorize() 623 * Casper.Colorizer#colorize()
595 */ 624 */
596 this.colorize = function colorize(message, style) { 625 Tester.prototype.colorize = function colorize(message, style) {
597 return casper.getColorizer().colorize(message, style); 626 "use strict";
598 }; 627 return this.casper.getColorizer().colorize(message, style);
628 };
599 629
600 /** 630 /**
601 * Writes a comment-style formatted message to stdout. 631 * Writes a comment-style formatted message to stdout.
602 * 632 *
603 * @param String message 633 * @param String message
604 */ 634 */
605 this.comment = function comment(message) { 635 Tester.prototype.comment = function comment(message) {
606 casper.echo('# ' + message, 'COMMENT'); 636 "use strict";
607 }; 637 this.casper.echo('# ' + message, 'COMMENT');
638 };
608 639
609 /** 640 /**
610 * Declares the current test suite done. 641 * Declares the current test suite done.
611 * 642 *
612 */ 643 */
613 this.done = function done() { 644 Tester.prototype.done = function done() {
645 "use strict";
614 this.emit('test.done'); 646 this.emit('test.done');
615 this.running = false; 647 this.running = false;
616 }; 648 };
617 649
618 /** 650 /**
619 * Writes an error-style formatted message to stdout. 651 * Writes an error-style formatted message to stdout.
620 * 652 *
621 * @param String message 653 * @param String message
622 */ 654 */
623 this.error = function error(message) { 655 Tester.prototype.error = function error(message) {
624 casper.echo(message, 'ERROR'); 656 "use strict";
625 }; 657 this.casper.echo(message, 'ERROR');
658 };
626 659
627 /** 660 /**
628 * Executes a file, wraping and evaluating its code in an isolated 661 * Executes a file, wraping and evaluating its code in an isolated
629 * environment where only the current `casper` instance is passed. 662 * environment where only the current `casper` instance is passed.
630 * 663 *
631 * @param String file Absolute path to some js/coffee file 664 * @param String file Absolute path to some js/coffee file
632 */ 665 */
633 this.exec = function exec(file) { 666 Tester.prototype.exec = function exec(file) {
667 "use strict";
634 file = this.filter('exec.file', file) || file; 668 file = this.filter('exec.file', file) || file;
635 if (!fs.isFile(file) || !utils.isJsFile(file)) { 669 if (!fs.isFile(file) || !utils.isJsFile(file)) {
636 var e = new CasperError(f("Cannot exec %s: can only exec() files with .js or .coffee extensions", file)); 670 var e = new CasperError(f("Cannot exec %s: can only exec() files with .js or .coffee extensions", file));
...@@ -639,26 +673,28 @@ var Tester = function Tester(casper, options) { ...@@ -639,26 +673,28 @@ var Tester = function Tester(casper, options) {
639 } 673 }
640 this.currentTestFile = file; 674 this.currentTestFile = file;
641 phantom.injectJs(file); 675 phantom.injectJs(file);
642 }; 676 };
643 677
644 /** 678 /**
645 * Adds a failed test entry to the stack. 679 * Adds a failed test entry to the stack.
646 * 680 *
647 * @param String message 681 * @param String message
648 */ 682 */
649 this.fail = function fail(message) { 683 Tester.prototype.fail = function fail(message) {
684 "use strict";
650 return this.assert(false, message, { 685 return this.assert(false, message, {
651 type: "fail", 686 type: "fail",
652 standard: "explicit call to fail()" 687 standard: "explicit call to fail()"
653 }); 688 });
654 }; 689 };
655 690
656 /** 691 /**
657 * Recursively finds all test files contained in a given directory. 692 * Recursively finds all test files contained in a given directory.
658 * 693 *
659 * @param String dir Path to some directory to scan 694 * @param String dir Path to some directory to scan
660 */ 695 */
661 this.findTestFiles = function findTestFiles(dir) { 696 Tester.prototype.findTestFiles = function findTestFiles(dir) {
697 "use strict";
662 var self = this; 698 var self = this;
663 if (!fs.isDirectory(dir)) { 699 if (!fs.isDirectory(dir)) {
664 return []; 700 return [];
...@@ -676,79 +712,85 @@ var Tester = function Tester(casper, options) { ...@@ -676,79 +712,85 @@ var Tester = function Tester(casper, options) {
676 return entries.filter(function _filter(entry) { 712 return entries.filter(function _filter(entry) {
677 return utils.isJsFile(fs.absolute(fs.pathJoin(dir, entry))); 713 return utils.isJsFile(fs.absolute(fs.pathJoin(dir, entry)));
678 }).sort(); 714 }).sort();
679 }; 715 };
680 716
681 /** 717 /**
682 * Formats a message to highlight some parts of it. 718 * Formats a message to highlight some parts of it.
683 * 719 *
684 * @param String message 720 * @param String message
685 * @param String style 721 * @param String style
686 */ 722 */
687 this.formatMessage = function formatMessage(message, style) { 723 Tester.prototype.formatMessage = function formatMessage(message, style) {
724 "use strict";
688 var parts = /^([a-z0-9_\.]+\(\))(.*)/i.exec(message); 725 var parts = /^([a-z0-9_\.]+\(\))(.*)/i.exec(message);
689 if (!parts) { 726 if (!parts) {
690 return message; 727 return message;
691 } 728 }
692 return this.colorize(parts[1], 'PARAMETER') + this.colorize(parts[2], style); 729 return this.colorize(parts[1], 'PARAMETER') + this.colorize(parts[2], style);
693 }; 730 };
694 731
695 /** 732 /**
696 * Retrieves current failure data and all failed cases. 733 * Retrieves current failure data and all failed cases.
697 * 734 *
698 * @return Object casedata An object containg information about cases 735 * @return Object casedata An object containg information about cases
699 * @return Number casedata.length The number of failed cases 736 * @return Number casedata.length The number of failed cases
700 * @return Array casedata.cases An array of all the failed case objects 737 * @return Array casedata.cases An array of all the failed case objects
701 */ 738 */
702 this.getFailures = function getFailures() { 739 Tester.prototype.getFailures = function getFailures() {
740 "use strict";
703 return { 741 return {
704 length: this.testResults.failed, 742 length: this.testResults.failed,
705 cases: this.testResults.failures 743 cases: this.testResults.failures
706 }; 744 };
707 }; 745 };
708 746
709 /** 747 /**
710 * Retrieves current passed data and all passed cases. 748 * Retrieves current passed data and all passed cases.
711 * 749 *
712 * @return Object casedata An object containg information about cases 750 * @return Object casedata An object containg information about cases
713 * @return Number casedata.length The number of passed cases 751 * @return Number casedata.length The number of passed cases
714 * @return Array casedata.cases An array of all the passed case objects 752 * @return Array casedata.cases An array of all the passed case objects
715 */ 753 */
716 this.getPasses = function getPasses() { 754 Tester.prototype.getPasses = function getPasses() {
755 "use strict";
717 return { 756 return {
718 length: this.testResults.passed, 757 length: this.testResults.passed,
719 cases: this.testResults.passes 758 cases: this.testResults.passes
720 }; 759 };
721 }; 760 };
722 761
723 /** 762 /**
724 * Writes an info-style formatted message to stdout. 763 * Writes an info-style formatted message to stdout.
725 * 764 *
726 * @param String message 765 * @param String message
727 */ 766 */
728 this.info = function info(message) { 767 Tester.prototype.info = function info(message) {
729 casper.echo(message, 'PARAMETER'); 768 "use strict";
730 }; 769 this.casper.echo(message, 'PARAMETER');
770 };
731 771
732 /** 772 /**
733 * Adds a successful test entry to the stack. 773 * Adds a successful test entry to the stack.
734 * 774 *
735 * @param String message 775 * @param String message
736 */ 776 */
737 this.pass = function pass(message) { 777 Tester.prototype.pass = function pass(message) {
778 "use strict";
738 return this.assert(true, message, { 779 return this.assert(true, message, {
739 type: "pass", 780 type: "pass",
740 standard: "explicit call to pass()" 781 standard: "explicit call to pass()"
741 }); 782 });
742 }; 783 };
743 784
744 /** 785 /**
745 * Processes an assertion result by emitting the appropriate event and 786 * Processes an assertion result by emitting the appropriate event and
746 * printing result onto the console. 787 * printing result onto the console.
747 * 788 *
748 * @param Object result An assertion result object 789 * @param Object result An assertion result object
749 * @return Object The passed assertion result Object 790 * @return Object The passed assertion result Object
750 */ 791 */
751 this.processAssertionResult = function processAssertionResult(result) { 792 Tester.prototype.processAssertionResult = function processAssertionResult(result) {
793 "use strict";
752 var eventName, style, status; 794 var eventName, style, status;
753 if (result.success === true) { 795 if (result.success === true) {
754 eventName = 'success'; 796 eventName = 'success';
...@@ -762,37 +804,39 @@ var Tester = function Tester(casper, options) { ...@@ -762,37 +804,39 @@ var Tester = function Tester(casper, options) {
762 this.testResults.failed++; 804 this.testResults.failed++;
763 } 805 }
764 var message = result.message || result.standard; 806 var message = result.message || result.standard;
765 casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' ')); 807 this.casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' '));
766 this.emit(eventName, result); 808 this.emit(eventName, result);
767 return result; 809 return result;
768 }; 810 };
769 811
770 /** 812 /**
771 * Renders a detailed report for each failed test. 813 * Renders a detailed report for each failed test.
772 * 814 *
773 * @param Array failures 815 * @param Array failures
774 */ 816 */
775 this.renderFailureDetails = function renderFailureDetails(failures) { 817 Tester.prototype.renderFailureDetails = function renderFailureDetails(failures) {
818 "use strict";
776 if (failures.length === 0) { 819 if (failures.length === 0) {
777 return; 820 return;
778 } 821 }
779 casper.echo(f("\nDetails for the %d failed test%s:\n", failures.length, failures.length > 1 ? "s" : ""), "PARAMETER"); 822 this.casper.echo(f("\nDetails for the %d failed test%s:\n", failures.length, failures.length > 1 ? "s" : ""), "PARAMETER");
780 failures.forEach(function _forEach(failure) { 823 failures.forEach(function _forEach(failure) {
781 var type, message, line; 824 var type, message, line;
782 type = failure.type || "unknown"; 825 type = failure.type || "unknown";
783 line = ~~failure.line; 826 line = ~~failure.line;
784 message = failure.message; 827 message = failure.message;
785 casper.echo(f('In %s:%s', failure.file, line)); 828 this.casper.echo(f('In %s:%s', failure.file, line));
786 casper.echo(f(' %s: %s', type, message || failure.standard || "(no message was entered)"), "COMMENT"); 829 this.casper.echo(f(' %s: %s', type, message || failure.standard || "(no message was entered)"), "COMMENT");
787 }); 830 });
788 }; 831 };
789 832
790 /** 833 /**
791 * Render tests results, an optionally exit phantomjs. 834 * Render tests results, an optionally exit phantomjs.
792 * 835 *
793 * @param Boolean exit 836 * @param Boolean exit
794 */ 837 */
795 this.renderResults = function renderResults(exit, status, save) { 838 Tester.prototype.renderResults = function renderResults(exit, status, save) {
839 "use strict";
796 save = utils.isString(save) ? save : this.options.save; 840 save = utils.isString(save) ? save : this.options.save;
797 var total = this.testResults.passed + this.testResults.failed, statusText, style, result; 841 var total = this.testResults.passed + this.testResults.failed, statusText, style, result;
798 var exitStatus = ~~(status || (this.testResults.failed > 0 ? 1 : 0)); 842 var exitStatus = ~~(status || (this.testResults.failed > 0 ? 1 : 0));
...@@ -811,28 +855,29 @@ var Tester = function Tester(casper, options) { ...@@ -811,28 +855,29 @@ var Tester = function Tester(casper, options) {
811 result = f('%s %s tests executed, %d passed, %d failed.', 855 result = f('%s %s tests executed, %d passed, %d failed.',
812 statusText, total, this.testResults.passed, this.testResults.failed); 856 statusText, total, this.testResults.passed, this.testResults.failed);
813 } 857 }
814 casper.echo(result, style, this.options.pad); 858 this.casper.echo(result, style, this.options.pad);
815 if (this.testResults.failed > 0) { 859 if (this.testResults.failed > 0) {
816 this.renderFailureDetails(this.testResults.failures); 860 this.renderFailureDetails(this.testResults.failures);
817 } 861 }
818 if (save && utils.isFunction(require)) { 862 if (save && utils.isFunction(require)) {
819 try { 863 try {
820 fs.write(save, this.exporter.getXML(), 'w'); 864 fs.write(save, this.exporter.getXML(), 'w');
821 casper.echo(f('Result log stored in %s', save), 'INFO', 80); 865 this.casper.echo(f('Result log stored in %s', save), 'INFO', 80);
822 } catch (e) { 866 } catch (e) {
823 casper.echo(f('Unable to write results to %s: %s', save, e), 'ERROR', 80); 867 this.casper.echo(f('Unable to write results to %s: %s', save, e), 'ERROR', 80);
824 } 868 }
825 } 869 }
826 if (exit === true) { 870 if (exit === true) {
827 casper.exit(exitStatus); 871 this.casper.exit(exitStatus);
828 } 872 }
829 }; 873 };
830 874
831 /** 875 /**
832 * Runs al suites contained in the paths passed as arguments. 876 * Runs al suites contained in the paths passed as arguments.
833 * 877 *
834 */ 878 */
835 this.runSuites = function runSuites() { 879 Tester.prototype.runSuites = function runSuites() {
880 "use strict";
836 var testFiles = [], self = this; 881 var testFiles = [], self = this;
837 if (arguments.length === 0) { 882 if (arguments.length === 0) {
838 throw new CasperError("runSuites() needs at least one path argument"); 883 throw new CasperError("runSuites() needs at least one path argument");
...@@ -862,7 +907,7 @@ var Tester = function Tester(casper, options) { ...@@ -862,7 +907,7 @@ var Tester = function Tester(casper, options) {
862 907
863 if (testFiles.length === 0) { 908 if (testFiles.length === 0) {
864 this.bar(f("No test file found in %s, aborting.", Array.prototype.slice.call(arguments)), "RED_BAR"); 909 this.bar(f("No test file found in %s, aborting.", Array.prototype.slice.call(arguments)), "RED_BAR");
865 casper.exit(1); 910 this.casper.exit(1);
866 } 911 }
867 self.currentSuiteNum = 0; 912 self.currentSuiteNum = 0;
868 var interval = setInterval(function _check(self) { 913 var interval = setInterval(function _check(self) {
...@@ -877,30 +922,32 @@ var Tester = function Tester(casper, options) { ...@@ -877,30 +922,32 @@ var Tester = function Tester(casper, options) {
877 self.currentSuiteNum++; 922 self.currentSuiteNum++;
878 } 923 }
879 }, 100, this); 924 }, 100, this);
880 }; 925 };
881 926
882 /** 927 /**
883 * Runs a test file 928 * Runs a test file
884 * 929 *
885 */ 930 */
886 this.runTest = function runTest(testFile) { 931 Tester.prototype.runTest = function runTest(testFile) {
932 "use strict";
887 this.bar(f('Test file: %s', testFile), 'INFO_BAR'); 933 this.bar(f('Test file: %s', testFile), 'INFO_BAR');
888 this.running = true; // this.running is set back to false with done() 934 this.running = true; // this.running is set back to false with done()
889 this.exec(testFile); 935 this.exec(testFile);
890 }; 936 };
891 937
892 /** 938 /**
893 * Tests equality between the two passed arguments. 939 * Tests equality between the two passed arguments.
894 * 940 *
895 * @param Mixed v1 941 * @param Mixed v1
896 * @param Mixed v2 942 * @param Mixed v2
897 * @param Boolean 943 * @param Boolean
898 */ 944 */
899 this.testEquals = this.testEqual = function testEquals(v1, v2) { 945 Tester.prototype.testEquals = Tester.prototype.testEqual = function testEquals(v1, v2) {
946 "use strict";
900 return utils.equals(v1, v2); 947 return utils.equals(v1, v2);
901 }; 948 };
902 949
903 /** 950 /**
904 * Processes an error caught while running tests contained in a given test 951 * Processes an error caught while running tests contained in a given test
905 * file. 952 * file.
906 * 953 *
...@@ -908,7 +955,8 @@ var Tester = function Tester(casper, options) { ...@@ -908,7 +955,8 @@ var Tester = function Tester(casper, options) {
908 * @param String file Test file where the error occurred 955 * @param String file Test file where the error occurred
909 * @param Number line Line number (optional) 956 * @param Number line Line number (optional)
910 */ 957 */
911 this.uncaughtError = function uncaughtError(error, file, line) { 958 Tester.prototype.uncaughtError = function uncaughtError(error, file, line) {
959 "use strict";
912 return this.processAssertionResult({ 960 return this.processAssertionResult({
913 success: false, 961 success: false,
914 type: "uncaughtError", 962 type: "uncaughtError",
...@@ -919,10 +967,4 @@ var Tester = function Tester(casper, options) { ...@@ -919,10 +967,4 @@ var Tester = function Tester(casper, options) {
919 error: error 967 error: error
920 } 968 }
921 }); 969 });
922 };
923 }; 970 };
924
925 // Tester class is an EventEmitter
926 utils.inherits(Tester, events.EventEmitter);
927
928 exports.Tester = Tester;
......
...@@ -30,10 +30,7 @@ ...@@ -30,10 +30,7 @@
30 30
31 /*global CasperError console exports phantom require*/ 31 /*global CasperError console exports phantom require*/
32 32
33 (function(exports) { 33 /**
34 "use strict";
35
36 /**
37 * Provides a better typeof operator equivalent, able to retrieve the array 34 * Provides a better typeof operator equivalent, able to retrieve the array
38 * type. 35 * type.
39 * 36 *
...@@ -41,22 +38,24 @@ ...@@ -41,22 +38,24 @@
41 * @return String 38 * @return String
42 * @see http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/ 39 * @see http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
43 */ 40 */
44 function betterTypeOf(input) { 41 function betterTypeOf(input) {
42 "use strict";
45 try { 43 try {
46 return Object.prototype.toString.call(input).match(/^\[object\s(.*)\]$/)[1].toLowerCase(); 44 return Object.prototype.toString.call(input).match(/^\[object\s(.*)\]$/)[1].toLowerCase();
47 } catch (e) { 45 } catch (e) {
48 return typeof input; 46 return typeof input;
49 } 47 }
50 } 48 }
51 exports.betterTypeOf = betterTypeOf; 49 exports.betterTypeOf = betterTypeOf;
52 50
53 /** 51 /**
54 * Cleans a passed URL if it lacks a slash at the end when a sole domain is used. 52 * Cleans a passed URL if it lacks a slash at the end when a sole domain is used.
55 * 53 *
56 * @param String url An HTTP URL 54 * @param String url An HTTP URL
57 * @return String 55 * @return String
58 */ 56 */
59 function cleanUrl(url) { 57 function cleanUrl(url) {
58 "use strict";
60 var parts = /(https?):\/\/(.*)/i.exec(url); 59 var parts = /(https?):\/\/(.*)/i.exec(url);
61 if (!parts) { 60 if (!parts) {
62 return url; 61 return url;
...@@ -67,28 +66,30 @@ ...@@ -67,28 +66,30 @@
67 return format("%s://%s/", protocol, subparts[0]); 66 return format("%s://%s/", protocol, subparts[0]);
68 } 67 }
69 return url; 68 return url;
70 } 69 }
71 exports.cleanUrl = cleanUrl; 70 exports.cleanUrl = cleanUrl;
72 71
73 /** 72 /**
74 * Dumps a JSON representation of passed value to the console. Used for 73 * Dumps a JSON representation of passed value to the console. Used for
75 * debugging purpose only. 74 * debugging purpose only.
76 * 75 *
77 * @param Mixed value 76 * @param Mixed value
78 */ 77 */
79 function dump(value) { 78 function dump(value) {
79 "use strict";
80 console.log(serialize(value, 4)); 80 console.log(serialize(value, 4));
81 } 81 }
82 exports.dump = dump; 82 exports.dump = dump;
83 83
84 /** 84 /**
85 * Tests equality between the two passed arguments. 85 * Tests equality between the two passed arguments.
86 * 86 *
87 * @param Mixed v1 87 * @param Mixed v1
88 * @param Mixed v2 88 * @param Mixed v2
89 * @param Boolean 89 * @param Boolean
90 */ 90 */
91 function equals(v1, v2) { 91 function equals(v1, v2) {
92 "use strict";
92 if (betterTypeOf(v1) !== betterTypeOf(v2)) { 93 if (betterTypeOf(v1) !== betterTypeOf(v2)) {
93 return false; 94 return false;
94 } 95 }
...@@ -107,46 +108,49 @@ ...@@ -107,46 +108,49 @@
107 return true; 108 return true;
108 } 109 }
109 return v1 === v2; 110 return v1 === v2;
110 } 111 }
111 exports.equals = equals; 112 exports.equals = equals;
112 113
113 /** 114 /**
114 * Returns the file extension in lower case. 115 * Returns the file extension in lower case.
115 * 116 *
116 * @param String file File path 117 * @param String file File path
117 * @return string 118 * @return string
118 */ 119 */
119 function fileExt(file) { 120 function fileExt(file) {
121 "use strict";
120 try { 122 try {
121 return file.split('.').pop().toLowerCase().trim(); 123 return file.split('.').pop().toLowerCase().trim();
122 } catch(e) { 124 } catch(e) {
123 return ''; 125 return '';
124 } 126 }
125 } 127 }
126 exports.fileExt = fileExt; 128 exports.fileExt = fileExt;
127 129
128 /** 130 /**
129 * Takes a string and append blanks until the pad value is reached. 131 * Takes a string and append blanks until the pad value is reached.
130 * 132 *
131 * @param String text 133 * @param String text
132 * @param Number pad Pad value (optional; default: 80) 134 * @param Number pad Pad value (optional; default: 80)
133 * @return String 135 * @return String
134 */ 136 */
135 function fillBlanks(text, pad) { 137 function fillBlanks(text, pad) {
138 "use strict";
136 pad = pad || 80; 139 pad = pad || 80;
137 if (text.length < pad) { 140 if (text.length < pad) {
138 text += new Array(pad - text.length + 1).join(' '); 141 text += new Array(pad - text.length + 1).join(' ');
139 } 142 }
140 return text; 143 return text;
141 } 144 }
142 exports.fillBlanks = fillBlanks; 145 exports.fillBlanks = fillBlanks;
143 146
144 /** 147 /**
145 * Formats a string with passed parameters. Ported from nodejs `util.format()`. 148 * Formats a string with passed parameters. Ported from nodejs `util.format()`.
146 * 149 *
147 * @return String 150 * @return String
148 */ 151 */
149 function format(f) { 152 function format(f) {
153 "use strict";
150 var i = 1; 154 var i = 1;
151 var args = arguments; 155 var args = arguments;
152 var len = args.length; 156 var len = args.length;
...@@ -173,10 +177,10 @@ ...@@ -173,10 +177,10 @@
173 } 177 }
174 } 178 }
175 return str; 179 return str;
176 } 180 }
177 exports.format = format; 181 exports.format = format;
178 182
179 /** 183 /**
180 * Retrieves the value of an Object foreign property using a dot-separated 184 * Retrieves the value of an Object foreign property using a dot-separated
181 * path string. 185 * path string.
182 * 186 *
...@@ -185,7 +189,8 @@ ...@@ -185,7 +189,8 @@
185 * @param Object obj The source object 189 * @param Object obj The source object
186 * @param String path Dot separated path, eg. "x.y.z" 190 * @param String path Dot separated path, eg. "x.y.z"
187 */ 191 */
188 function getPropertyPath(obj, path) { 192 function getPropertyPath(obj, path) {
193 "use strict";
189 if (!isObject(obj) || !isString(path)) { 194 if (!isObject(obj) || !isString(path)) {
190 return undefined; 195 return undefined;
191 } 196 }
...@@ -198,17 +203,18 @@ ...@@ -198,17 +203,18 @@
198 } 203 }
199 }); 204 });
200 return value; 205 return value;
201 } 206 }
202 exports.getPropertyPath = getPropertyPath; 207 exports.getPropertyPath = getPropertyPath;
203 208
204 /** 209 /**
205 * Inherit the prototype methods from one constructor into another. 210 * Inherit the prototype methods from one constructor into another.
206 * 211 *
207 * @param {function} ctor Constructor function which needs to inherit the 212 * @param {function} ctor Constructor function which needs to inherit the
208 * prototype. 213 * prototype.
209 * @param {function} superCtor Constructor function to inherit prototype from. 214 * @param {function} superCtor Constructor function to inherit prototype from.
210 */ 215 */
211 function inherits(ctor, superCtor) { 216 function inherits(ctor, superCtor) {
217 "use strict";
212 ctor.super_ = ctor.__super__ = superCtor; 218 ctor.super_ = ctor.__super__ = superCtor;
213 ctor.prototype = Object.create(superCtor.prototype, { 219 ctor.prototype = Object.create(superCtor.prototype, {
214 constructor: { 220 constructor: {
...@@ -218,125 +224,135 @@ ...@@ -218,125 +224,135 @@
218 configurable: true 224 configurable: true
219 } 225 }
220 }); 226 });
221 } 227 }
222 exports.inherits = inherits; 228 exports.inherits = inherits;
223 229
224 /** 230 /**
225 * Checks if value is a javascript Array 231 * Checks if value is a javascript Array
226 * 232 *
227 * @param mixed value 233 * @param mixed value
228 * @return Boolean 234 * @return Boolean
229 */ 235 */
230 function isArray(value) { 236 function isArray(value) {
237 "use strict";
231 return Array.isArray(value) || isType(value, "array"); 238 return Array.isArray(value) || isType(value, "array");
232 } 239 }
233 exports.isArray = isArray; 240 exports.isArray = isArray;
234 241
235 /** 242 /**
236 * Checks if passed argument is an instance of Capser object. 243 * Checks if passed argument is an instance of Capser object.
237 * 244 *
238 * @param mixed value 245 * @param mixed value
239 * @return Boolean 246 * @return Boolean
240 */ 247 */
241 function isCasperObject(value) { 248 function isCasperObject(value) {
249 "use strict";
242 return value instanceof require('casper').Casper; 250 return value instanceof require('casper').Casper;
243 } 251 }
244 exports.isCasperObject = isCasperObject; 252 exports.isCasperObject = isCasperObject;
245 253
246 /** 254 /**
247 * Checks if value is a phantomjs clipRect-compatible object 255 * Checks if value is a phantomjs clipRect-compatible object
248 * 256 *
249 * @param mixed value 257 * @param mixed value
250 * @return Boolean 258 * @return Boolean
251 */ 259 */
252 function isClipRect(value) { 260 function isClipRect(value) {
261 "use strict";
253 return isType(value, "cliprect") || ( 262 return isType(value, "cliprect") || (
254 isObject(value) && 263 isObject(value) &&
255 isNumber(value.top) && isNumber(value.left) && 264 isNumber(value.top) && isNumber(value.left) &&
256 isNumber(value.width) && isNumber(value.height) 265 isNumber(value.width) && isNumber(value.height)
257 ); 266 );
258 } 267 }
259 exports.isClipRect = isClipRect; 268 exports.isClipRect = isClipRect;
260 269
261 /** 270 /**
262 * Checks if value is a javascript Function 271 * Checks if value is a javascript Function
263 * 272 *
264 * @param mixed value 273 * @param mixed value
265 * @return Boolean 274 * @return Boolean
266 */ 275 */
267 function isFunction(value) { 276 function isFunction(value) {
277 "use strict";
268 return isType(value, "function"); 278 return isType(value, "function");
269 } 279 }
270 exports.isFunction = isFunction; 280 exports.isFunction = isFunction;
271 281
272 /** 282 /**
273 * Checks if passed resource involves an HTTP url. 283 * Checks if passed resource involves an HTTP url.
274 * 284 *
275 * @param Object resource The PhantomJS HTTP resource object 285 * @param Object resource The PhantomJS HTTP resource object
276 * @return Boolean 286 * @return Boolean
277 */ 287 */
278 function isHTTPResource(resource) { 288 function isHTTPResource(resource) {
289 "use strict";
279 return isObject(resource) && /^http/i.test(resource.url); 290 return isObject(resource) && /^http/i.test(resource.url);
280 } 291 }
281 exports.isHTTPResource = isHTTPResource; 292 exports.isHTTPResource = isHTTPResource;
282 293
283 /** 294 /**
284 * Checks if a file is apparently javascript compatible (.js or .coffee). 295 * Checks if a file is apparently javascript compatible (.js or .coffee).
285 * 296 *
286 * @param String file Path to the file to test 297 * @param String file Path to the file to test
287 * @return Boolean 298 * @return Boolean
288 */ 299 */
289 function isJsFile(file) { 300 function isJsFile(file) {
301 "use strict";
290 var ext = fileExt(file); 302 var ext = fileExt(file);
291 return isString(ext, "string") && ['js', 'coffee'].indexOf(ext) !== -1; 303 return isString(ext, "string") && ['js', 'coffee'].indexOf(ext) !== -1;
292 } 304 }
293 exports.isJsFile = isJsFile; 305 exports.isJsFile = isJsFile;
294 306
295 /** 307 /**
296 * Checks if the provided value is null 308 * Checks if the provided value is null
297 * 309 *
298 * @return Boolean 310 * @return Boolean
299 */ 311 */
300 function isNull(value) { 312 function isNull(value) {
313 "use strict";
301 return isType(value, "null"); 314 return isType(value, "null");
302 } 315 }
303 exports.isNull = isNull; 316 exports.isNull = isNull;
304 317
305 /** 318 /**
306 * Checks if value is a javascript Number 319 * Checks if value is a javascript Number
307 * 320 *
308 * @param mixed value 321 * @param mixed value
309 * @return Boolean 322 * @return Boolean
310 */ 323 */
311 function isNumber(value) { 324 function isNumber(value) {
325 "use strict";
312 return isType(value, "number"); 326 return isType(value, "number");
313 } 327 }
314 exports.isNumber = isNumber; 328 exports.isNumber = isNumber;
315 329
316 /** 330 /**
317 * Checks if value is a javascript Object 331 * Checks if value is a javascript Object
318 * 332 *
319 * @param mixed value 333 * @param mixed value
320 * @return Boolean 334 * @return Boolean
321 */ 335 */
322 function isObject(value) { 336 function isObject(value) {
337 "use strict";
323 var objectTypes = ["array", "object", "qtruntimeobject"]; 338 var objectTypes = ["array", "object", "qtruntimeobject"];
324 return objectTypes.indexOf(betterTypeOf(value)) >= 0; 339 return objectTypes.indexOf(betterTypeOf(value)) >= 0;
325 } 340 }
326 exports.isObject = isObject; 341 exports.isObject = isObject;
327 342
328 /** 343 /**
329 * Checks if value is a javascript String 344 * Checks if value is a javascript String
330 * 345 *
331 * @param mixed value 346 * @param mixed value
332 * @return Boolean 347 * @return Boolean
333 */ 348 */
334 function isString(value) { 349 function isString(value) {
350 "use strict";
335 return isType(value, "string"); 351 return isType(value, "string");
336 } 352 }
337 exports.isString = isString; 353 exports.isString = isString;
338 354
339 /** 355 /**
340 * Shorthands for checking if a value is of the given type. Can check for 356 * Shorthands for checking if a value is of the given type. Can check for
341 * arrays. 357 * arrays.
342 * 358 *
...@@ -344,31 +360,34 @@ ...@@ -344,31 +360,34 @@
344 * @param String typeName The type name ("string", "number", "function", etc.) 360 * @param String typeName The type name ("string", "number", "function", etc.)
345 * @return Boolean 361 * @return Boolean
346 */ 362 */
347 function isType(what, typeName) { 363 function isType(what, typeName) {
364 "use strict";
348 if (typeof typeName !== "string" || !typeName) { 365 if (typeof typeName !== "string" || !typeName) {
349 throw new CasperError("You must pass isType() a typeName string"); 366 throw new CasperError("You must pass isType() a typeName string");
350 } 367 }
351 return betterTypeOf(what).toLowerCase() === typeName.toLowerCase(); 368 return betterTypeOf(what).toLowerCase() === typeName.toLowerCase();
352 } 369 }
353 exports.isType = isType; 370 exports.isType = isType;
354 371
355 /** 372 /**
356 * Checks if the provided value is undefined 373 * Checks if the provided value is undefined
357 * 374 *
358 * @return Boolean 375 * @return Boolean
359 */ 376 */
360 function isUndefined(value) { 377 function isUndefined(value) {
378 "use strict";
361 return isType(value, "undefined"); 379 return isType(value, "undefined");
362 } 380 }
363 exports.isUndefined = isUndefined; 381 exports.isUndefined = isUndefined;
364 382
365 /** 383 /**
366 * Checks if value is a valid selector Object. 384 * Checks if value is a valid selector Object.
367 * 385 *
368 * @param mixed value 386 * @param mixed value
369 * @return Boolean 387 * @return Boolean
370 */ 388 */
371 function isValidSelector(value) { 389 function isValidSelector(value) {
390 "use strict";
372 if (isString(value)) { 391 if (isString(value)) {
373 try { 392 try {
374 // phantomjs env has a working document object, let's use it 393 // phantomjs env has a working document object, let's use it
...@@ -392,28 +411,30 @@ ...@@ -392,28 +411,30 @@
392 return true; 411 return true;
393 } 412 }
394 return false; 413 return false;
395 } 414 }
396 exports.isValidSelector = isValidSelector; 415 exports.isValidSelector = isValidSelector;
397 416
398 /** 417 /**
399 * Checks if the provided var is a WebPage instance 418 * Checks if the provided var is a WebPage instance
400 * 419 *
401 * @param mixed what 420 * @param mixed what
402 * @return Boolean 421 * @return Boolean
403 */ 422 */
404 function isWebPage(what) { 423 function isWebPage(what) {
424 "use strict";
405 return betterTypeOf(what) === "qtruntimeobject" && what.objectName === 'WebPage'; 425 return betterTypeOf(what) === "qtruntimeobject" && what.objectName === 'WebPage';
406 } 426 }
407 exports.isWebPage = isWebPage; 427 exports.isWebPage = isWebPage;
408 428
409 /** 429 /**
410 * Object recursive merging utility. 430 * Object recursive merging utility.
411 * 431 *
412 * @param Object origin the origin object 432 * @param Object origin the origin object
413 * @param Object add the object to merge data into origin 433 * @param Object add the object to merge data into origin
414 * @return Object 434 * @return Object
415 */ 435 */
416 function mergeObjects(origin, add) { 436 function mergeObjects(origin, add) {
437 "use strict";
417 for (var p in add) { 438 for (var p in add) {
418 try { 439 try {
419 if (add[p].constructor === Object) { 440 if (add[p].constructor === Object) {
...@@ -426,17 +447,18 @@ ...@@ -426,17 +447,18 @@
426 } 447 }
427 } 448 }
428 return origin; 449 return origin;
429 } 450 }
430 exports.mergeObjects = mergeObjects; 451 exports.mergeObjects = mergeObjects;
431 452
432 /** 453 /**
433 * Creates an (SG|X)ML node element. 454 * Creates an (SG|X)ML node element.
434 * 455 *
435 * @param String name The node name 456 * @param String name The node name
436 * @param Object attributes Optional attributes 457 * @param Object attributes Optional attributes
437 * @return HTMLElement 458 * @return HTMLElement
438 */ 459 */
439 function node(name, attributes) { 460 function node(name, attributes) {
461 "use strict";
440 var _node = document.createElement(name); 462 var _node = document.createElement(name);
441 for (var attrName in attributes) { 463 for (var attrName in attributes) {
442 var value = attributes[attrName]; 464 var value = attributes[attrName];
...@@ -445,26 +467,27 @@ ...@@ -445,26 +467,27 @@
445 } 467 }
446 } 468 }
447 return _node; 469 return _node;
448 } 470 }
449 exports.node = node; 471 exports.node = node;
450 472
451 /** 473 /**
452 * Serializes a value using JSON. 474 * Serializes a value using JSON.
453 * 475 *
454 * @param Mixed value 476 * @param Mixed value
455 * @return String 477 * @return String
456 */ 478 */
457 function serialize(value, indent) { 479 function serialize(value, indent) {
480 "use strict";
458 if (isArray(value)) { 481 if (isArray(value)) {
459 value = value.map(function _map(prop) { 482 value = value.map(function _map(prop) {
460 return isFunction(prop) ? prop.toString().replace(/\s{2,}/, '') : prop; 483 return isFunction(prop) ? prop.toString().replace(/\s{2,}/, '') : prop;
461 }); 484 });
462 } 485 }
463 return JSON.stringify(value, null, indent); 486 return JSON.stringify(value, null, indent);
464 } 487 }
465 exports.serialize = serialize; 488 exports.serialize = serialize;
466 489
467 /** 490 /**
468 * Returns unique values from an array. 491 * Returns unique values from an array.
469 * 492 *
470 * Note: ugly code is ugly, but efficient: http://jsperf.com/array-unique2/8 493 * Note: ugly code is ugly, but efficient: http://jsperf.com/array-unique2/8
...@@ -472,7 +495,8 @@ ...@@ -472,7 +495,8 @@
472 * @param Array array 495 * @param Array array
473 * @return Array 496 * @return Array
474 */ 497 */
475 function unique(array) { 498 function unique(array) {
499 "use strict";
476 var o = {}, 500 var o = {},
477 r = []; 501 r = [];
478 for (var i = 0, len = array.length; i !== len; i++) { 502 for (var i = 0, len = array.length; i !== len; i++) {
...@@ -483,6 +507,5 @@ ...@@ -483,6 +507,5 @@
483 } 507 }
484 } 508 }
485 return r; 509 return r;
486 } 510 }
487 exports.unique = unique; 511 exports.unique = unique;
488 })(exports);
......
...@@ -33,6 +33,36 @@ ...@@ -33,6 +33,36 @@
33 var utils = require('utils'); 33 var utils = require('utils');
34 var fs = require('fs'); 34 var fs = require('fs');
35 35
36 /**
37 * Generates a value for 'classname' attribute of the JUnit XML report.
38 *
39 * Uses the (relative) file name of the current casper script without file
40 * extension as classname.
41 *
42 * @param String classname
43 * @return String
44 */
45 function generateClassName(classname) {
46 "use strict";
47 classname = classname.replace(phantom.casperPath, "").trim();
48 var script = classname || phantom.casperScript;
49 if (script.indexOf(fs.workingDirectory) === 0) {
50 script = script.substring(fs.workingDirectory.length + 1);
51 }
52 if (script.indexOf('/') === 0) {
53 script = script.substring(1, script.length);
54 }
55 if (~script.indexOf('.')) {
56 script = script.substring(0, script.lastIndexOf('.'));
57 }
58 return script || "unknown";
59 }
60
61 /**
62 * Creates a XUnit instance
63 *
64 * @return XUnit
65 */
36 exports.create = function create() { 66 exports.create = function create() {
37 "use strict"; 67 "use strict";
38 return new XUnitExporter(); 68 return new XUnitExporter();
...@@ -88,31 +118,6 @@ XUnitExporter.prototype.addFailure = function addFailure(classname, name, messag ...@@ -88,31 +118,6 @@ XUnitExporter.prototype.addFailure = function addFailure(classname, name, messag
88 }; 118 };
89 119
90 /** 120 /**
91 * Generates a value for 'classname' attribute of the JUnit XML report.
92 *
93 * Uses the (relative) file name of the current casper script without file
94 * extension as classname.
95 *
96 * @param String classname
97 * @return String
98 */
99 function generateClassName(classname) {
100 "use strict";
101 classname = classname.replace(phantom.casperPath, "").trim();
102 var script = classname || phantom.casperScript;
103 if (script.indexOf(fs.workingDirectory) === 0) {
104 script = script.substring(fs.workingDirectory.length + 1);
105 }
106 if (script.indexOf('/') === 0) {
107 script = script.substring(1, script.length);
108 }
109 if (~script.indexOf('.')) {
110 script = script.substring(0, script.lastIndexOf('.'));
111 }
112 return script || "unknown";
113 }
114
115 /**
116 * Retrieves generated XML object - actually an HTMLElement. 121 * Retrieves generated XML object - actually an HTMLElement.
117 * 122 *
118 * @return HTMLElement 123 * @return HTMLElement
......
1 /*global phantom*/
2
1 if (!phantom.casperLoaded) { 3 if (!phantom.casperLoaded) {
2 console.log('This script must be invoked using the casperjs executable'); 4 console.log('This script must be invoked using the casperjs executable');
3 phantom.exit(1); 5 phantom.exit(1);
...@@ -15,6 +17,7 @@ var casper = require('casper').create({ ...@@ -15,6 +17,7 @@ var casper = require('casper').create({
15 17
16 // local utils 18 // local utils
17 function checkSelfTest(tests) { 19 function checkSelfTest(tests) {
20 "use strict";
18 var isCasperTest = false; 21 var isCasperTest = false;
19 tests.forEach(function(test) { 22 tests.forEach(function(test) {
20 var testDir = fs.absolute(fs.dirname(test)); 23 var testDir = fs.absolute(fs.dirname(test));
...@@ -28,6 +31,7 @@ function checkSelfTest(tests) { ...@@ -28,6 +31,7 @@ function checkSelfTest(tests) {
28 } 31 }
29 32
30 function checkIncludeFile(include) { 33 function checkIncludeFile(include) {
34 "use strict";
31 var absInclude = fs.absolute(include.trim()); 35 var absInclude = fs.absolute(include.trim());
32 if (!fs.exists(absInclude)) { 36 if (!fs.exists(absInclude)) {
33 casper.warn("%s file not found, can't be included", absInclude); 37 casper.warn("%s file not found, can't be included", absInclude);
...@@ -60,6 +64,7 @@ if (casper.cli.get('no-colors') === true) { ...@@ -60,6 +64,7 @@ if (casper.cli.get('no-colors') === true) {
60 // test paths are passed as args 64 // test paths are passed as args
61 if (casper.cli.args.length) { 65 if (casper.cli.args.length) {
62 tests = casper.cli.args.filter(function(path) { 66 tests = casper.cli.args.filter(function(path) {
67 "use strict";
63 return fs.isFile(path) || fs.isDirectory(path); 68 return fs.isFile(path) || fs.isDirectory(path);
64 }); 69 });
65 } else { 70 } else {
...@@ -75,6 +80,7 @@ if (!phantom.casperSelfTest && checkSelfTest(tests)) { ...@@ -75,6 +80,7 @@ if (!phantom.casperSelfTest && checkSelfTest(tests)) {
75 80
76 // includes handling 81 // includes handling
77 this.loadIncludes.forEach(function(include){ 82 this.loadIncludes.forEach(function(include){
83 "use strict";
78 var container; 84 var container;
79 if (casper.cli.has(include)) { 85 if (casper.cli.has(include)) {
80 container = casper.cli.get(include).split(',').map(function(file) { 86 container = casper.cli.get(include).split(',').map(function(file) {
...@@ -89,6 +95,7 @@ this.loadIncludes.forEach(function(include){ ...@@ -89,6 +95,7 @@ this.loadIncludes.forEach(function(include){
89 95
90 // test suites completion listener 96 // test suites completion listener
91 casper.test.on('tests.complete', function() { 97 casper.test.on('tests.complete', function() {
98 "use strict";
92 this.renderResults(true, undefined, casper.cli.get('xunit') || undefined); 99 this.renderResults(true, undefined, casper.cli.get('xunit') || undefined);
93 }); 100 });
94 101
......
1 /** 1 /**
2 * CasperJS local HTTP test server 2 * CasperJS local HTTP test server
3 */ 3 */
4
5 /*global phantom casper require*/
6
4 var colorizer = require('colorizer').create('Colorizer'); 7 var colorizer = require('colorizer').create('Colorizer');
5 var fs = require('fs'); 8 var fs = require('fs');
6 var utils = require('utils'); 9 var utils = require('utils');
...@@ -9,10 +12,12 @@ var service; ...@@ -9,10 +12,12 @@ var service;
9 var testServerPort = 54321; 12 var testServerPort = 54321;
10 13
11 function info(message) { 14 function info(message) {
15 "use strict";
12 console.log(colorizer.colorize('INFO', 'INFO_BAR') + ' ' + message); 16 console.log(colorizer.colorize('INFO', 'INFO_BAR') + ' ' + message);
13 } 17 }
14 18
15 service = server.listen(testServerPort, function(request, response) { 19 service = server.listen(testServerPort, function(request, response) {
20 "use strict";
16 var pageFile = fs.pathJoin(phantom.casperPath, request.url); 21 var pageFile = fs.pathJoin(phantom.casperPath, request.url);
17 if (!fs.exists(pageFile) || !fs.isFile(pageFile)) { 22 if (!fs.exists(pageFile) || !fs.isFile(pageFile)) {
18 response.statusCode = 404; 23 response.statusCode = 404;
...@@ -26,16 +31,18 @@ service = server.listen(testServerPort, function(request, response) { ...@@ -26,16 +31,18 @@ service = server.listen(testServerPort, function(request, response) {
26 31
27 // overriding Casper.open to prefix all test urls 32 // overriding Casper.open to prefix all test urls
28 casper.setFilter('open.location', function(location) { 33 casper.setFilter('open.location', function(location) {
34 "use strict";
29 if (/^file/.test(location)) { 35 if (/^file/.test(location)) {
30 return location; 36 return location;
31 } 37 }
32 if (!/^http/.test(location)) { 38 if (!/^http/.test(location)) {
33 return f('http://localhost:%d/%s', testServerPort, location); 39 return utils.format('http://localhost:%d/%s', testServerPort, location);
34 } 40 }
35 return location; 41 return location;
36 }); 42 });
37 43
38 // test suites completion listener 44 // test suites completion listener
39 casper.test.on('tests.complete', function() { 45 casper.test.on('tests.complete', function() {
46 "use strict";
40 server.close(); 47 server.close();
41 }); 48 });
......