Commit 918e9906 918e990687f8a43441bd3c0521cb6f002c6ae85f by Nicolas Perriault

merged with master

2 parents 789f60d0 c335de2e
1 CasperJS Changelog 1 CasperJS Changelog
2 ================== 2 ==================
3 3
4 XXXX-XX-XX, v0.6.11
5 -------------------
6
7 - fixed [#132](https://github.com/n1k0/casperjs/issues/132) - added ability to include js/coffee files using a dedicated option when using the [`casper test` command](http://casperjs.org/testing.html)
8 - fixed [#140](https://github.com/n1k0/casperjs/issues/140) - `casper test` now resolves local paths urls
9 - fixed [#148](https://github.com/n1k0/casperjs/issues/148) - [`utils.isWebPage()`](http://casperjs.org/api.html#utils.isWebPage) was broken
10 - fixed [#149](https://github.com/n1k0/casperjs/issues/149) - [`ClientUtils.fill()`](http://casperjs.org/api.html#casper.fill) was searching elements globally
11 - fixed [#144](https://github.com/n1k0/casperjs/issues/144) - added a [`safeLogs` option](http://casperjs.org/api.html#casper.options) to blur password values in debug logs. **This option is set to `true` by default.**
12 - added [`Casper.userAgent()`](http://casperjs.org/api.html#casper.userAgent) to ease a more dynamic setting of user-agent string
13 - added [`Tester.assertTitleMatch()`](http://casperjs.org/api.html#tester.assertTitleMatch) method
14 - added experimental support of custom headers sending in outgoing request (refs [#137](https://github.com/n1k0/casperjs/issues/137) - PhantomJS 1.6 required)
15 - switched to more standard `.textContent` property to get a node text; this allows a better compatibility of the clientutils bookmarklet with non-webkit browsers
16 - casper modules now all use [javascript strict mode](http://www.nczonline.net/blog/2012/03/13/its-time-to-start-using-javascript-strict-mode/)
17
4 2012-06-04, v0.6.10 18 2012-06-04, v0.6.10
5 ------------------- 19 -------------------
6 20
......
...@@ -4,15 +4,15 @@ CasperJS is a navigation scripting & testing utility for [PhantomJS](http://www. ...@@ -4,15 +4,15 @@ CasperJS is a navigation scripting & testing utility for [PhantomJS](http://www.
4 It eases the process of defining a full navigation scenario and provides useful 4 It eases the process of defining a full navigation scenario and provides useful
5 high-level functions, methods & syntaxic sugar for doing common tasks such as: 5 high-level functions, methods & syntaxic sugar for doing common tasks such as:
6 6
7 - defining & ordering [navigation steps](http://casperjs.org/#quickstart) 7 - defining & ordering [navigation steps](http://casperjs.org/quickstart.html)
8 - [filling forms](http://casperjs.org/#phantom_Casper_fill) 8 - [filling forms](http://casperjs.org/api.html#casper.fill)
9 - [clicking links](http://casperjs.org/#phantom_Casper_click) 9 - [clicking links](http://casperjs.org/api.html#casper.click)
10 - [capturing screenshots](http://casperjs.org/#phantom_Casper_captureSelector) of a page (or an area) 10 - [capturing screenshots](http://casperjs.org/api.html#casper.captureSelector) of a page (or an area)
11 - [making assertions on remote DOM](http://casperjs.org/#phantom_Casper_Tester) 11 - [making assertions on remote DOM](http://casperjs.org/api.html#tester)
12 - [logging](http://casperjs.org/#logging) & [events](http://casperjs.org/#events-filters) 12 - [logging](http://casperjs.org/logging.html) & [events](http://casperjs.org/events-filters.html)
13 - [downloading base64](http://casperjs.org/#phantom_Casper_download) encoded resources, even binary ones 13 - [downloading base64](http://casperjs.org/api.html#casper.download) encoded resources, even binary ones
14 - catching errors and react accordingly 14 - catching errors and react accordingly
15 - writing [functional test suites](http://casperjs.org/#testing), exporting results as JUnit XML (xUnit) 15 - writing [functional test suites](http://casperjs.org/testing.html), exporting results as JUnit XML (xUnit)
16 16
17 Browse the [sample examples repository](https://github.com/n1k0/casperjs/tree/master/samples). 17 Browse the [sample examples repository](https://github.com/n1k0/casperjs/tree/master/samples).
18 Don't hesitate to pull request for any cool example of yours as well! 18 Don't hesitate to pull request for any cool example of yours as well!
......
...@@ -48,6 +48,6 @@ CASPER_COMMAND.extend(CASPER_ARGS) ...@@ -48,6 +48,6 @@ CASPER_COMMAND.extend(CASPER_ARGS)
48 48
49 try: 49 try:
50 os.execvp(CASPER_COMMAND[0], CASPER_COMMAND) 50 os.execvp(CASPER_COMMAND[0], CASPER_COMMAND)
51 except OSError, err: 51 except OSError as err:
52 print('Fatal: %s; did you install phantomjs?' % err) 52 print(('Fatal: %s; did you install phantomjs?' % err))
53 sys.exit(1) 53 sys.exit(1)
......
1 Subproject commit ead2191ceb086cd5665e18a822f72689d90a6c3d 1 Subproject commit 76cc32f262a3ef924a67f33bb17432e3a5c33e03
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
28 * 28 *
29 */ 29 */
30 30
31 /*global CasperError console exports phantom require*/
32
31 var utils = require('utils'); 33 var utils = require('utils');
32 34
33 /** 35 /**
...@@ -38,6 +40,7 @@ var utils = require('utils'); ...@@ -38,6 +40,7 @@ var utils = require('utils');
38 * @return Object 40 * @return Object
39 */ 41 */
40 exports.parse = function parse(phantomArgs) { 42 exports.parse = function parse(phantomArgs) {
43 "use strict";
41 var extract = { 44 var extract = {
42 args: [], 45 args: [],
43 options: {}, 46 options: {},
...@@ -110,6 +113,7 @@ exports.parse = function parse(phantomArgs) { ...@@ -110,6 +113,7 @@ exports.parse = function parse(phantomArgs) {
110 * @return Mixed 113 * @return Mixed
111 */ 114 */
112 function castArgument(arg) { 115 function castArgument(arg) {
116 "use strict";
113 if (arg.match(/^-?\d+$/)) { 117 if (arg.match(/^-?\d+$/)) {
114 return parseInt(arg, 10); 118 return parseInt(arg, 10);
115 } else if (arg.match(/^-?\d+\.\d+$/)) { 119 } else if (arg.match(/^-?\d+\.\d+$/)) {
......
...@@ -27,15 +27,21 @@ ...@@ -27,15 +27,21 @@
27 * DEALINGS IN THE SOFTWARE. 27 * DEALINGS IN THE SOFTWARE.
28 * 28 *
29 */ 29 */
30
31 /*global console escape exports NodeList window*/
32
30 (function(exports) { 33 (function(exports) {
31 exports.create = function create() { 34 "use strict";
32 return new this.ClientUtils(); 35
36 exports.create = function create(options) {
37 return new this.ClientUtils(options);
33 }; 38 };
34 39
35 /** 40 /**
36 * Casper client-side helpers. 41 * Casper client-side helpers.
37 */ 42 */
38 exports.ClientUtils = function ClientUtils() { 43 exports.ClientUtils = function ClientUtils(options) {
44 // private members
39 var BASE64_ENCODE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 45 var BASE64_ENCODE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
40 var BASE64_DECODE_CHARS = new Array( 46 var BASE64_DECODE_CHARS = new Array(
41 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 47 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
...@@ -49,6 +55,9 @@ ...@@ -49,6 +55,9 @@
49 ); 55 );
50 var SUPPORTED_SELECTOR_TYPES = ['css', 'xpath']; 56 var SUPPORTED_SELECTOR_TYPES = ['css', 'xpath'];
51 57
58 // public members
59 this.options = options || {};
60
52 /** 61 /**
53 * Clicks on the DOM element behind the provided selector. 62 * Clicks on the DOM element behind the provided selector.
54 * 63 *
...@@ -70,35 +79,35 @@ ...@@ -70,35 +79,35 @@
70 while (i < len) { 79 while (i < len) {
71 do { 80 do {
72 c1 = BASE64_DECODE_CHARS[str.charCodeAt(i++) & 0xff]; 81 c1 = BASE64_DECODE_CHARS[str.charCodeAt(i++) & 0xff];
73 } while (i < len && c1 == -1); 82 } while (i < len && c1 === -1);
74 if (c1 == -1) { 83 if (c1 === -1) {
75 break; 84 break;
76 } 85 }
77 do { 86 do {
78 c2 = BASE64_DECODE_CHARS[str.charCodeAt(i++) & 0xff]; 87 c2 = BASE64_DECODE_CHARS[str.charCodeAt(i++) & 0xff];
79 } while (i < len && c2 == -1); 88 } while (i < len && c2 === -1);
80 if (c2 == -1) { 89 if (c2 === -1) {
81 break; 90 break;
82 } 91 }
83 out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4)); 92 out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
84 do { 93 do {
85 c3 = str.charCodeAt(i++) & 0xff; 94 c3 = str.charCodeAt(i++) & 0xff;
86 if (c3 == 61) 95 if (c3 === 61)
87 return out; 96 return out;
88 c3 = BASE64_DECODE_CHARS[c3]; 97 c3 = BASE64_DECODE_CHARS[c3];
89 } while (i < len && c3 == -1); 98 } while (i < len && c3 === -1);
90 if (c3 == -1) { 99 if (c3 === -1) {
91 break; 100 break;
92 } 101 }
93 out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2)); 102 out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
94 do { 103 do {
95 c4 = str.charCodeAt(i++) & 0xff; 104 c4 = str.charCodeAt(i++) & 0xff;
96 if (c4 == 61) { 105 if (c4 === 61) {
97 return out; 106 return out;
98 } 107 }
99 c4 = BASE64_DECODE_CHARS[c4]; 108 c4 = BASE64_DECODE_CHARS[c4];
100 } while (i < len && c4 == -1); 109 } while (i < len && c4 === -1);
101 if (c4 == -1) { 110 if (c4 === -1) {
102 break; 111 break;
103 } 112 }
104 out += String.fromCharCode(((c3 & 0x03) << 6) | c4); 113 out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
...@@ -117,14 +126,14 @@ ...@@ -117,14 +126,14 @@
117 var out = "", i = 0, len = str.length, c1, c2, c3; 126 var out = "", i = 0, len = str.length, c1, c2, c3;
118 while (i < len) { 127 while (i < len) {
119 c1 = str.charCodeAt(i++) & 0xff; 128 c1 = str.charCodeAt(i++) & 0xff;
120 if (i == len) { 129 if (i === len) {
121 out += BASE64_ENCODE_CHARS.charAt(c1 >> 2); 130 out += BASE64_ENCODE_CHARS.charAt(c1 >> 2);
122 out += BASE64_ENCODE_CHARS.charAt((c1 & 0x3) << 4); 131 out += BASE64_ENCODE_CHARS.charAt((c1 & 0x3) << 4);
123 out += "=="; 132 out += "==";
124 break; 133 break;
125 } 134 }
126 c2 = str.charCodeAt(i++); 135 c2 = str.charCodeAt(i++);
127 if (i == len) { 136 if (i === len) {
128 out += BASE64_ENCODE_CHARS.charAt(c1 >> 2); 137 out += BASE64_ENCODE_CHARS.charAt(c1 >> 2);
129 out += BASE64_ENCODE_CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); 138 out += BASE64_ENCODE_CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
130 out += BASE64_ENCODE_CHARS.charAt((c2 & 0xF) << 2); 139 out += BASE64_ENCODE_CHARS.charAt((c2 & 0xF) << 2);
...@@ -165,7 +174,7 @@ ...@@ -165,7 +174,7 @@
165 var text = '', elements = this.findAll(selector); 174 var text = '', elements = this.findAll(selector);
166 if (elements && elements.length) { 175 if (elements && elements.length) {
167 Array.prototype.forEach.call(elements, function _forEach(element) { 176 Array.prototype.forEach.call(elements, function _forEach(element) {
168 text += element.innerText; 177 text += element.textContent || element.innerText;
169 }); 178 });
170 } 179 }
171 return text; 180 return text;
...@@ -185,7 +194,7 @@ ...@@ -185,7 +194,7 @@
185 files: [] 194 files: []
186 }; 195 };
187 if (!(form instanceof HTMLElement) || typeof form === "string") { 196 if (!(form instanceof HTMLElement) || typeof form === "string") {
188 __utils__.log("attempting to fetch form element from selector: '" + form + "'", "info"); 197 this.log("attempting to fetch form element from selector: '" + form + "'", "info");
189 try { 198 try {
190 form = this.findOne(form); 199 form = this.findOne(form);
191 } catch (e) { 200 } catch (e) {
...@@ -203,7 +212,7 @@ ...@@ -203,7 +212,7 @@
203 if (!vals.hasOwnProperty(name)) { 212 if (!vals.hasOwnProperty(name)) {
204 continue; 213 continue;
205 } 214 }
206 var field = this.findAll('[name="' + name + '"]'); 215 var field = this.findAll('[name="' + name + '"]', form);
207 var value = vals[name]; 216 var value = vals[name];
208 if (!field) { 217 if (!field) {
209 out.errors.push('no field named "' + name + '" in form'); 218 out.errors.push('no field named "' + name + '" in form');
...@@ -229,16 +238,18 @@ ...@@ -229,16 +238,18 @@
229 /** 238 /**
230 * Finds all DOM elements matching by the provided selector. 239 * Finds all DOM elements matching by the provided selector.
231 * 240 *
232 * @param String selector CSS3 selector 241 * @param String selector CSS3 selector
242 * @param HTMLElement|null scope Element to search child elements within
233 * @return NodeList|undefined 243 * @return NodeList|undefined
234 */ 244 */
235 this.findAll = function findAll(selector) { 245 this.findAll = function findAll(selector, scope) {
246 scope = scope || document;
236 try { 247 try {
237 var pSelector = this.processSelector(selector); 248 var pSelector = this.processSelector(selector);
238 if (pSelector.type === 'xpath') { 249 if (pSelector.type === 'xpath') {
239 return this.getElementsByXPath(pSelector.path); 250 return this.getElementsByXPath(pSelector.path);
240 } else { 251 } else {
241 return document.querySelectorAll(pSelector.path); 252 return scope.querySelectorAll(pSelector.path);
242 } 253 }
243 } catch (e) { 254 } catch (e) {
244 this.log('findAll(): invalid selector provided "' + selector + '":' + e, "error"); 255 this.log('findAll(): invalid selector provided "' + selector + '":' + e, "error");
...@@ -248,16 +259,18 @@ ...@@ -248,16 +259,18 @@
248 /** 259 /**
249 * Finds a DOM element by the provided selector. 260 * Finds a DOM element by the provided selector.
250 * 261 *
251 * @param String selector CSS3 selector 262 * @param String selector CSS3 selector
263 * @param HTMLElement|null scope Element to search child elements within
252 * @return HTMLElement|undefined 264 * @return HTMLElement|undefined
253 */ 265 */
254 this.findOne = function findOne(selector) { 266 this.findOne = function findOne(selector, scope) {
267 scope = scope || document;
255 try { 268 try {
256 var pSelector = this.processSelector(selector); 269 var pSelector = this.processSelector(selector);
257 if (pSelector.type === 'xpath') { 270 if (pSelector.type === 'xpath') {
258 return this.getElementByXPath(pSelector.path); 271 return this.getElementByXPath(pSelector.path);
259 } else { 272 } else {
260 return document.querySelector(pSelector.path); 273 return scope.querySelector(pSelector.path);
261 } 274 }
262 } catch (e) { 275 } catch (e) {
263 this.log('findOne(): invalid selector provided "' + selector + '":' + e, "error"); 276 this.log('findOne(): invalid selector provided "' + selector + '":' + e, "error");
...@@ -462,8 +475,8 @@ ...@@ -462,8 +475,8 @@
462 * @param mixed value The field value to set 475 * @param mixed value The field value to set
463 */ 476 */
464 this.setField = function setField(field, value) { 477 this.setField = function setField(field, value) {
465 var fields, out; 478 var logValue, fields, out;
466 value = value || ""; 479 value = logValue = (value || "");
467 if (field instanceof NodeList) { 480 if (field instanceof NodeList) {
468 fields = field; 481 fields = field;
469 field = fields[0]; 482 field = fields[0];
...@@ -471,11 +484,15 @@ ...@@ -471,11 +484,15 @@
471 if (!field instanceof HTMLElement) { 484 if (!field instanceof HTMLElement) {
472 this.log("Invalid field type; only HTMLElement and NodeList are supported", "error"); 485 this.log("Invalid field type; only HTMLElement and NodeList are supported", "error");
473 } 486 }
474 this.log('Set "' + field.getAttribute('name') + '" field value to ' + value, "debug"); 487 if (this.options && this.options.safeLogs && field.getAttribute('type') === "password") {
488 // obfuscate password value
489 logValue = new Array(value.length + 1).join("*");
490 }
491 this.log('Set "' + field.getAttribute('name') + '" field value to ' + logValue, "debug");
475 try { 492 try {
476 field.focus(); 493 field.focus();
477 } catch (e) { 494 } catch (e) {
478 __utils__.log("Unable to focus() input field " + field.getAttribute('name') + ": " + e, "warning"); 495 this.log("Unable to focus() input field " + field.getAttribute('name') + ": " + e, "warning");
479 } 496 }
480 var nodeName = field.nodeName.toLowerCase(); 497 var nodeName = field.nodeName.toLowerCase();
481 switch (nodeName) { 498 switch (nodeName) {
...@@ -544,7 +561,7 @@ ...@@ -544,7 +561,7 @@
544 try { 561 try {
545 field.blur(); 562 field.blur();
546 } catch (err) { 563 } catch (err) {
547 __utils__.log("Unable to blur() input field " + field.getAttribute('name') + ": " + err, "warning"); 564 this.log("Unable to blur() input field " + field.getAttribute('name') + ": " + err, "warning");
548 } 565 }
549 return out; 566 return out;
550 }; 567 };
...@@ -570,7 +587,4 @@ ...@@ -570,7 +587,4 @@
570 } 587 }
571 }; 588 };
572 }; 589 };
573
574 // silly "hack" to force having an instance available
575 exports.__utils__ = new exports.ClientUtils();
576 })(typeof exports === "object" ? exports : window); 590 })(typeof exports === "object" ? exports : window);
......
...@@ -28,10 +28,13 @@ ...@@ -28,10 +28,13 @@
28 * 28 *
29 */ 29 */
30 30
31 /*global exports console require*/
32
31 var fs = require('fs'); 33 var fs = require('fs');
32 var utils = require('utils'); 34 var utils = require('utils');
33 35
34 exports.create = function create(type) { 36 exports.create = function create(type) {
37 "use strict";
35 if (!type) { 38 if (!type) {
36 return; 39 return;
37 } 40 }
...@@ -48,6 +51,7 @@ exports.create = function create(type) { ...@@ -48,6 +51,7 @@ exports.create = function create(type) {
48 * (c) Fabien Potencier, Symfony project, MIT license 51 * (c) Fabien Potencier, Symfony project, MIT license
49 */ 52 */
50 var Colorizer = function Colorizer() { 53 var Colorizer = function Colorizer() {
54 "use strict";
51 var options = { bold: 1, underscore: 4, blink: 5, reverse: 7, conceal: 8 }; 55 var options = { bold: 1, underscore: 4, blink: 5, reverse: 7, conceal: 8 };
52 var foreground = { black: 30, red: 31, green: 32, yellow: 33, blue: 34, magenta: 35, cyan: 36, white: 37 }; 56 var foreground = { black: 30, red: 31, green: 32, yellow: 33, blue: 34, magenta: 35, cyan: 36, white: 37 };
53 var background = { black: 40, red: 41, green: 42, yellow: 43, blue: 44, magenta: 45, cyan: 46, white: 47 }; 57 var background = { black: 40, red: 41, green: 42, yellow: 43, blue: 44, magenta: 45, cyan: 46, white: 47 };
...@@ -104,7 +108,7 @@ var Colorizer = function Colorizer() { ...@@ -104,7 +108,7 @@ var Colorizer = function Colorizer() {
104 if (typeof pad === "number" && text.length < pad) { 108 if (typeof pad === "number" && text.length < pad) {
105 text += new Array(pad - text.length + 1).join(' '); 109 text += new Array(pad - text.length + 1).join(' ');
106 } 110 }
107 return "\033[" + codes.join(';') + 'm' + text + "\033[0m"; 111 return "\u001b[" + codes.join(';') + 'm' + text + "\u001b[0m";
108 }; 112 };
109 }; 113 };
110 exports.Colorizer = Colorizer; 114 exports.Colorizer = Colorizer;
...@@ -114,6 +118,7 @@ exports.Colorizer = Colorizer; ...@@ -114,6 +118,7 @@ exports.Colorizer = Colorizer;
114 * 118 *
115 */ 119 */
116 var Dummy = function Dummy() { 120 var Dummy = function Dummy() {
121 "use strict";
117 this.colorize = function colorize(text, styleName, pad) { 122 this.colorize = function colorize(text, styleName, pad) {
118 return text; 123 return text;
119 }; 124 };
......
...@@ -28,9 +28,12 @@ ...@@ -28,9 +28,12 @@
28 * 28 *
29 */ 29 */
30 30
31 /*global CasperError console encodeURIComponent escape exports require*/
32
31 var utils = require('utils'); 33 var utils = require('utils');
32 34
33 exports.create = function create(fn) { 35 exports.create = function create(fn) {
36 "use strict";
34 return new FunctionArgsInjector(fn); 37 return new FunctionArgsInjector(fn);
35 }; 38 };
36 39
...@@ -40,6 +43,7 @@ exports.create = function create(fn) { ...@@ -40,6 +43,7 @@ exports.create = function create(fn) {
40 * FIXME: use new Function() instead of eval() 43 * FIXME: use new Function() instead of eval()
41 */ 44 */
42 var FunctionArgsInjector = function FunctionArgsInjector(fn) { 45 var FunctionArgsInjector = function FunctionArgsInjector(fn) {
46 "use strict";
43 if (!utils.isFunction(fn)) { 47 if (!utils.isFunction(fn)) {
44 throw new CasperError("FunctionArgsInjector() can only process functions"); 48 throw new CasperError("FunctionArgsInjector() can only process functions");
45 } 49 }
......
...@@ -28,13 +28,17 @@ ...@@ -28,13 +28,17 @@
28 * 28 *
29 */ 29 */
30 30
31 /*global CasperError exports require*/
32
31 var utils = require('utils'); 33 var utils = require('utils');
32 34
33 exports.create = function create(casper) { 35 exports.create = function create(casper) {
36 "use strict";
34 return new Mouse(casper); 37 return new Mouse(casper);
35 }; 38 };
36 39
37 var Mouse = function Mouse(casper) { 40 var Mouse = function Mouse(casper) {
41 "use strict";
38 if (!utils.isCasperObject(casper)) { 42 if (!utils.isCasperObject(casper)) {
39 throw new CasperError('Mouse() needs a Casper instance'); 43 throw new CasperError('Mouse() needs a Casper instance');
40 } 44 }
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
28 * 28 *
29 */ 29 */
30 30
31 /*global exports:false, phantom:false, require:false, CasperError:false*/ 31 /*global CasperError exports phantom require*/
32 32
33 var fs = require('fs'); 33 var fs = require('fs');
34 var events = require('events'); 34 var events = require('events');
...@@ -55,6 +55,7 @@ var Tester = function Tester(casper, options) { ...@@ -55,6 +55,7 @@ var Tester = function Tester(casper, options) {
55 55
56 this.currentTestFile = null; 56 this.currentTestFile = null;
57 this.exporter = require('xunit').create(); 57 this.exporter = require('xunit').create();
58 this.includes = [];
58 this.running = false; 59 this.running = false;
59 this.suites = []; 60 this.suites = [];
60 this.options = utils.mergeObjects({ 61 this.options = utils.mergeObjects({
...@@ -287,7 +288,7 @@ var Tester = function Tester(casper, options) { ...@@ -287,7 +288,7 @@ var Tester = function Tester(casper, options) {
287 standard: "Subject matches the provided pattern", 288 standard: "Subject matches the provided pattern",
288 values: { 289 values: {
289 subject: subject, 290 subject: subject,
290 pattern: pattern 291 pattern: pattern.toString()
291 } 292 }
292 }); 293 });
293 }; 294 };
...@@ -361,7 +362,7 @@ var Tester = function Tester(casper, options) { ...@@ -361,7 +362,7 @@ var Tester = function Tester(casper, options) {
361 */ 362 */
362 this.assertTextExists = this.assertTextExist = function assertTextExists(text, message) { 363 this.assertTextExists = this.assertTextExist = function assertTextExists(text, message) {
363 var textFound = (casper.evaluate(function _evaluate() { 364 var textFound = (casper.evaluate(function _evaluate() {
364 return document.body.innerText; 365 return document.body.textContent || document.body.innerText;
365 }).indexOf(text) !== -1); 366 }).indexOf(text) !== -1);
366 return this.assert(textFound, message, { 367 return this.assert(textFound, message, {
367 type: "assertTextExists", 368 type: "assertTextExists",
...@@ -392,6 +393,25 @@ var Tester = function Tester(casper, options) { ...@@ -392,6 +393,25 @@ var Tester = function Tester(casper, options) {
392 }; 393 };
393 394
394 /** 395 /**
396 * Asserts that title of the remote page matched the provided pattern.
397 *
398 * @param RegExp pattern The pattern to test the title against
399 * @param String message Test description
400 * @return Object An assertion result object
401 */
402 this.assertTitleMatch = this.assertTitleMatches = function assertTitleMatch(pattern, message) {
403 var currentTitle = casper.getTitle();
404 return this.assert(pattern.test(currentTitle), message, {
405 type: "assertTitle",
406 details: "Page title does not match the provided pattern",
407 values: {
408 subject: currentTitle,
409 pattern: pattern.toString()
410 }
411 });
412 };
413
414 /**
395 * Asserts that the provided subject is of the given type. 415 * Asserts that the provided subject is of the given type.
396 * 416 *
397 * @param mixed subject The value to test 417 * @param mixed subject The value to test
...@@ -427,7 +447,7 @@ var Tester = function Tester(casper, options) { ...@@ -427,7 +447,7 @@ var Tester = function Tester(casper, options) {
427 standard: "Current url matches the provided pattern", 447 standard: "Current url matches the provided pattern",
428 values: { 448 values: {
429 currentUrl: currentUrl, 449 currentUrl: currentUrl,
430 pattern: pattern 450 pattern: pattern.toString()
431 } 451 }
432 }); 452 });
433 }; 453 };
...@@ -695,6 +715,9 @@ var Tester = function Tester(casper, options) { ...@@ -695,6 +715,9 @@ var Tester = function Tester(casper, options) {
695 this.runTest = function runTest(testFile) { 715 this.runTest = function runTest(testFile) {
696 this.bar(f('Test file: %s', testFile), 'INFO_BAR'); 716 this.bar(f('Test file: %s', testFile), 'INFO_BAR');
697 this.running = true; // this.running is set back to false with done() 717 this.running = true; // this.running is set back to false with done()
718 this.includes.forEach(function(include) {
719 phantom.injectJs(include);
720 });
698 this.exec(testFile); 721 this.exec(testFile);
699 }; 722 };
700 723
......
This diff could not be displayed because it is too large.
...@@ -27,13 +27,15 @@ ...@@ -27,13 +27,15 @@
27 * DEALINGS IN THE SOFTWARE. 27 * DEALINGS IN THE SOFTWARE.
28 * 28 *
29 */ 29 */
30 /*global exports, phantom, require, CasperError*/ 30
31 /*global CasperError console exports phantom require*/
32
31 var utils = require('utils'); 33 var utils = require('utils');
32 var fs = require('fs'); 34 var fs = require('fs');
33 35
34 exports.create = function create() { 36 exports.create = function create() {
35 "use strict"; 37 "use strict";
36 return new this.XUnitExporter(); 38 return new XUnitExporter();
37 }; 39 };
38 40
39 /** 41 /**
......
1 casper = require("casper").create 1 casper = require("casper").create
2 verbose: true 2 verbose: true
3 3
4 # If we don't set a limit, it could go on forever
5 upTo = ~~casper.cli.get(0) || 10
6
7 ###
8 Fetch all <a> elements from the page and return
9 the ones which contains a href starting with 'http://'
10 ###
11 searchLinks = ->
12 filter = Array::filter
13 map = Array::map
14 map.call filter.call(document.querySelectorAll("a"), (a) ->
15 (/^http:\/\/.*/i).test a.getAttribute("href")
16 ), (a) ->
17 a.getAttribute "href"
18
19 # The base links array 4 # The base links array
20 links = [ 5 links = [
21 "http://google.com/" 6 "http://google.com/"
...@@ -23,10 +8,10 @@ links = [ ...@@ -23,10 +8,10 @@ links = [
23 "http://bing.com/" 8 "http://bing.com/"
24 ] 9 ]
25 10
26 # Just opens the page and prints the title 11 currentLink = 0;
27 start = (link) -> 12
28 @start link, -> 13 # If we don't set a limit, it could go on forever
29 @echo "Page title: #{ @getTitle() }" 14 upTo = ~~casper.cli.get(0) || 10
30 15
31 ### 16 ###
32 Get the links, and add them to the links array 17 Get the links, and add them to the links array
...@@ -38,12 +23,22 @@ addLinks = (link) -> ...@@ -38,12 +23,22 @@ addLinks = (link) ->
38 @echo "#{found.length} links found on #{link}" 23 @echo "#{found.length} links found on #{link}"
39 links = links.concat found 24 links = links.concat found
40 25
41 casper.start() 26 ###
42 27 Fetch all <a> elements from the page and return
43 casper.then -> 28 the ones which contains a href starting with 'http://'
44 @echo "Starting" 29 ###
30 searchLinks = ->
31 filter = Array::filter
32 map = Array::map
33 map.call filter.call(document.querySelectorAll("a"), (a) ->
34 (/^http:\/\/.*/i).test a.getAttribute("href")
35 ), (a) ->
36 a.getAttribute "href"
45 37
46 currentLink = 0; 38 # Just opens the page and prints the title
39 start = (link) ->
40 @start link, ->
41 @echo "Page title: #{ @getTitle() }"
47 42
48 # As long as it has a next link, and is under the maximum limit, will keep running 43 # As long as it has a next link, and is under the maximum limit, will keep running
49 check = -> 44 check = ->
...@@ -57,4 +52,9 @@ check = -> ...@@ -57,4 +52,9 @@ check = ->
57 @echo "All done." 52 @echo "All done."
58 @exit() 53 @exit()
59 54
55 casper.start()
56
57 casper.then ->
58 @echo "Starting"
59
60 casper.run check 60 casper.run check
......
...@@ -2,24 +2,6 @@ var casper = require("casper").create({ ...@@ -2,24 +2,6 @@ var casper = require("casper").create({
2 verbose: true 2 verbose: true
3 }); 3 });
4 4
5 // If we don't set a limit, it could go on forever
6 var upTo = ~~casper.cli.get(0) || 10;
7
8 /*
9 Fetch all <a> elements from the page and return
10 the ones which contains a href starting with 'http://'
11 */
12 var searchLinks = function() {
13 var filter, map;
14 filter = Array.prototype.filter;
15 map = Array.prototype.map;
16 return map.call(filter.call(document.querySelectorAll("a"), function(a) {
17 return /^http:\/\/.*/i.test(a.getAttribute("href"));
18 }), function(a) {
19 return a.getAttribute("href");
20 });
21 };
22
23 // The base links array 5 // The base links array
24 var links = [ 6 var links = [
25 "http://google.com/", 7 "http://google.com/",
...@@ -27,30 +9,40 @@ var links = [ ...@@ -27,30 +9,40 @@ var links = [
27 "http://bing.com/" 9 "http://bing.com/"
28 ]; 10 ];
29 11
30 // Just opens the page and prints the title 12 // If we don't set a limit, it could go on forever
31 var start = function(link) { 13 var upTo = ~~casper.cli.get(0) || 10;
32 this.start(link, function() { 14
33 this.echo('Page title: ' + this.getTitle()); 15 var currentLink = 0;
34 });
35 };
36 16
37 // Get the links, and add them to the links array 17 // Get the links, and add them to the links array
38 // (It could be done all in one step, but it is intentionally splitted) 18 // (It could be done all in one step, but it is intentionally splitted)
39 var addLinks = function(link) { 19 function addLinks(link) {
40 this.then(function() { 20 this.then(function() {
41 var found = this.evaluate(searchLinks); 21 var found = this.evaluate(searchLinks);
42 this.echo(found.length + " links found on " + link); 22 this.echo(found.length + " links found on " + link);
43 links = links.concat(found); 23 links = links.concat(found);
44 }); 24 });
45 }; 25 }
46 26
47 casper.start(); 27 // Fetch all <a> elements from the page and return
48 28 // the ones which contains a href starting with 'http://'
49 casper.then(function() { 29 function searchLinks() {
50 this.echo("Starting"); 30 var filter, map;
51 }); 31 filter = Array.prototype.filter;
32 map = Array.prototype.map;
33 return map.call(filter.call(document.querySelectorAll("a"), function(a) {
34 return (/^http:\/\/.*/i).test(a.getAttribute("href"));
35 }), function(a) {
36 return a.getAttribute("href");
37 });
38 }
52 39
53 var currentLink = 0; 40 // Just opens the page and prints the title
41 function start(link) {
42 this.start(link, function() {
43 this.echo('Page title: ' + this.getTitle());
44 });
45 }
54 46
55 // As long as it has a next link, and is under the maximum limit, will keep running 47 // As long as it has a next link, and is under the maximum limit, will keep running
56 function check() { 48 function check() {
...@@ -64,6 +56,10 @@ function check() { ...@@ -64,6 +56,10 @@ function check() {
64 this.echo("All done."); 56 this.echo("All done.");
65 this.exit(); 57 this.exit();
66 } 58 }
67 }; 59 }
60
61 casper.start().then(function() {
62 this.echo("Starting");
63 });
68 64
69 casper.run(check); 65 casper.run(check);
......
...@@ -6,24 +6,47 @@ if (!phantom.casperLoaded) { ...@@ -6,24 +6,47 @@ if (!phantom.casperLoaded) {
6 var fs = require('fs'); 6 var fs = require('fs');
7 var utils = require('utils'); 7 var utils = require('utils');
8 var f = utils.format; 8 var f = utils.format;
9 var includes = [];
10 var tests = [];
9 var casper = require('casper').create({ 11 var casper = require('casper').create({
10 exitOnError: false 12 exitOnError: false
11 }); 13 });
12 14
13 // Options from cli 15 // local utils
16 function checkIncludeFile(include) {
17 var absInclude = fs.absolute(include.trim());
18 if (!fs.exists(absInclude)) {
19 casper.warn("%s file not found, can't be included", absInclude);
20 return;
21 }
22 if (!utils.isJsFile(absInclude)) {
23 casper.warn("%s is not a supported file type, can't be included", absInclude);
24 return;
25 }
26 if (fs.isDirectory(absInclude)) {
27 casper.warn("%s is a directory, can't be included", absInclude);
28 return;
29 }
30 if (tests.indexOf(include) > -1 || tests.indexOf(absInclude) > -1) {
31 casper.warn("%s is a test file, can't be included", absInclude);
32 return;
33 }
34 return absInclude;
35 }
36
37 // parse some options from cli
14 casper.options.verbose = casper.cli.get('direct') || false; 38 casper.options.verbose = casper.cli.get('direct') || false;
15 casper.options.logLevel = casper.cli.get('log-level') || "error"; 39 casper.options.logLevel = casper.cli.get('log-level') || "error";
16 40
17 // Overriding Casper.open to prefix all test urls 41 // overriding Casper.open to prefix all test urls
18 casper.setFilter('open.location', function(location) { 42 casper.setFilter('open.location', function(location) {
19 if (!/^http/.test(location)) { 43 if (!/^http/.test(location)) {
20 return f('file://%s/%s', phantom.casperPath, location); 44 return f('file://%s/%s', fs.workingDirectory, location);
21 } 45 }
22 return location; 46 return location;
23 }); 47 });
24 48
25 var tests = []; 49 // test paths are passed as args
26
27 if (casper.cli.args.length) { 50 if (casper.cli.args.length) {
28 tests = casper.cli.args.filter(function(path) { 51 tests = casper.cli.args.filter(function(path) {
29 return fs.isFile(path) || fs.isDirectory(path); 52 return fs.isFile(path) || fs.isDirectory(path);
...@@ -33,8 +56,21 @@ if (casper.cli.args.length) { ...@@ -33,8 +56,21 @@ if (casper.cli.args.length) {
33 casper.exit(1); 56 casper.exit(1);
34 } 57 }
35 58
59 // includes handling
60 if (casper.cli.has('includes')) {
61 includes = casper.cli.get('includes').split(',').map(function(include) {
62 // we can't use filter() directly because of abspath transformation
63 return checkIncludeFile(include);
64 }).filter(function(include) {
65 return utils.isString(include);
66 });
67 casper.test.includes = utils.unique(includes);
68 }
69
70 // test suites completion listener
36 casper.test.on('tests.complete', function() { 71 casper.test.on('tests.complete', function() {
37 this.renderResults(true, undefined, casper.cli.get('xunit') || undefined); 72 this.renderResults(true, undefined, casper.cli.get('xunit') || undefined);
38 }); 73 });
39 74
75 // run all the suites
40 casper.test.runSuites.apply(casper.test, tests); 76 casper.test.runSuites.apply(casper.test, tests);
......
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <html> 2 <html>
3 <head> 3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5 <title>CasperJS test form</title> 5 <title>CasperJS test form</title>
6 </head> 6 </head>
7 <body> 7 <body>
8 <form action="result.html" enctype="multipart/form-data"> 8 <form action="result.html" enctype="multipart/form-data">
9 <input type="text" name="email" placeholder="email" /> 9 <input type="text" name="email" placeholder="email">
10 <input type="password" name="password" placeholder="password">
10 <textarea name="content"></textarea> 11 <textarea name="content"></textarea>
11 <select name="topic"> 12 <select name="topic">
12 <option>foo</option> 13 <option>foo</option>
13 <option value="bar">baz</option> 14 <option value="bar">baz</option>
14 </select> 15 </select>
15 <input type="checkbox" name="check" /> 16 <input type="checkbox" name="check">
16 <input type="radio" name="choice" value="yes"/> 17 <input type="radio" name="choice" value="yes">
17 <input type="radio" name="choice" value="no"/> 18 <input type="radio" name="choice" value="no">
18 <input type="file" name="file"/> 19 <input type="file" name="file">
19 <input type="checkbox" name="checklist[]" value="1" /> 20 <input type="checkbox" name="checklist[]" value="1">
20 <input type="checkbox" name="checklist[]" value="2" /> 21 <input type="checkbox" name="checklist[]" value="2">
21 <input type="checkbox" name="checklist[]" value="3" /> 22 <input type="checkbox" name="checklist[]" value="3">
22 <input type="submit" name="submit" value="submit" /> 23 <input type="submit" name="submit" value="submit">
23 </form> 24 </form>
24 </body> 25 </body>
25 </html> 26 </html>
......
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Multiple forms test</title>
5 </head>
6 <body>
7 <form name="f1">
8 <input type="hidden" name="f" value="f1">
9 <input type="text" name="yo">
10 </form>
11 <form name="f2">
12 <input type="hidden" name="f" value="f2">
13 <input type="text" name="yo">
14 </form>
15 </body>
16 </html>
1 function testUA(ua, match) {
2 casper.test.assertMatch(
3 ua, match, 'Default user agent matches ' + match
4 );
5 }
6
7 function fetchUA(request) {
8 testUA(request.headers.filter(function(header) {
9 return header.name === "User-Agent";
10 }).pop().value, /plop/);
11 }
12
13 testUA(casper.options.pageSettings.userAgent, /CasperJS/);
14
15 casper.start();
16
17 casper.userAgent('plop').on('resource.requested', fetchUA);
18
19 casper.thenOpen('tests/site/index.html');
20
21 casper.run(function() {
22 this.removeListener('resource.requested', fetchUA);
23 this.test.done();
24 });
1 var fs = require('fs');
2 var clientutils = require('clientutils').create();
3
4 var testCases = {
5 'an empty string': '',
6 'a word': 'plop',
7 'a null char': 'a\u0000',
8 'an utf8 string': 'ÀÁÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ',
9 'song lyrics': ("Voilà l'été, j'aperçois le soleil\n" +
10 "Les nuages filent et le ciel s'éclaircit\n" +
11 "Et dans ma tête qui bourdonnent?\n" +
12 "Les abeilles!"),
13 'a file contents': fs.read(phantom.casperPath + '/tests/site/alert.html')
14 };
15
16 casper.test.comment('ClientUtils.encode()');
17
18 for (var what in testCases) {
19 var source = testCases[what];
20 var encoded = clientutils.encode(source);
21 casper.test.assertEquals(clientutils.decode(encoded), source, 'ClientUtils can encode and decode ' + what);
22 }
23
24 casper.test.done();
...@@ -2,6 +2,7 @@ casper.start('tests/site/form.html', function() { ...@@ -2,6 +2,7 @@ casper.start('tests/site/form.html', function() {
2 this.test.comment('Casper.fill()'); 2 this.test.comment('Casper.fill()');
3 this.fill('form[action="result.html"]', { 3 this.fill('form[action="result.html"]', {
4 email: 'chuck@norris.com', 4 email: 'chuck@norris.com',
5 password: 'chuck',
5 content: 'Am watching thou', 6 content: 'Am watching thou',
6 check: true, 7 check: true,
7 choice: 'no', 8 choice: 'no',
...@@ -13,6 +14,9 @@ casper.start('tests/site/form.html', function() { ...@@ -13,6 +14,9 @@ casper.start('tests/site/form.html', function() {
13 return document.querySelector('input[name="email"]').value; 14 return document.querySelector('input[name="email"]').value;
14 }, 'chuck@norris.com', 'Casper.fill() can fill an input[type=text] form field'); 15 }, 'chuck@norris.com', 'Casper.fill() can fill an input[type=text] form field');
15 this.test.assertEvalEquals(function() { 16 this.test.assertEvalEquals(function() {
17 return document.querySelector('input[name="password"]').value;
18 }, 'chuck', 'Casper.fill() can fill an input[type=password] form field');
19 this.test.assertEvalEquals(function() {
16 return document.querySelector('textarea[name="content"]').value; 20 return document.querySelector('textarea[name="content"]').value;
17 }, 'Am watching thou', 'Casper.fill() can fill a textarea form field'); 21 }, 'Am watching thou', 'Casper.fill() can fill a textarea form field');
18 this.test.assertEvalEquals(function() { 22 this.test.assertEvalEquals(function() {
...@@ -41,12 +45,25 @@ casper.start('tests/site/form.html', function() { ...@@ -41,12 +45,25 @@ casper.start('tests/site/form.html', function() {
41 casper.then(function() { 45 casper.then(function() {
42 this.test.comment('Form submitted'); 46 this.test.comment('Form submitted');
43 this.test.assertUrlMatch(/email=chuck@norris.com/, 'Casper.fill() input[type=email] field was submitted'); 47 this.test.assertUrlMatch(/email=chuck@norris.com/, 'Casper.fill() input[type=email] field was submitted');
48 this.test.assertUrlMatch(/password=chuck/, 'Casper.fill() input[type=password] field was submitted');
44 this.test.assertUrlMatch(/content=Am\+watching\+thou/, 'Casper.fill() textarea field was submitted'); 49 this.test.assertUrlMatch(/content=Am\+watching\+thou/, 'Casper.fill() textarea field was submitted');
45 this.test.assertUrlMatch(/check=on/, 'Casper.fill() input[type=checkbox] field was submitted'); 50 this.test.assertUrlMatch(/check=on/, 'Casper.fill() input[type=checkbox] field was submitted');
46 this.test.assertUrlMatch(/choice=no/, 'Casper.fill() input[type=radio] field was submitted'); 51 this.test.assertUrlMatch(/choice=no/, 'Casper.fill() input[type=radio] field was submitted');
47 this.test.assertUrlMatch(/topic=bar/, 'Casper.fill() select field was submitted'); 52 this.test.assertUrlMatch(/topic=bar/, 'Casper.fill() select field was submitted');
48 }); 53 });
49 54
55 // multiple forms
56 casper.thenOpen('tests/site/multiple-forms.html', function() {
57 this.test.comment('Multiple forms');
58 this.fill('form[name="f2"]', {
59 yo: "ok"
60 }, true);
61 });
62
63 casper.then(function() {
64 this.test.assertUrlMatch(/\?f=f2&yo=ok$/, 'Casper.fill() handles multiple forms');
65 }),
66
50 casper.run(function() { 67 casper.run(function() {
51 this.test.done(); 68 this.test.done();
52 }); 69 });
......
1 var fs = require('fs');
2 var x = require('casper').selectXPath;
3
4 function fakeDocument(html) {
5 window.document.body.innerHTML = html;
6 }
7
8 (function(casper) {
9 casper.test.comment('ClientUtils.encode()');
10 var clientutils = require('clientutils').create();
11 var testCases = {
12 'an empty string': '',
13 'a word': 'plop',
14 'a null char': 'a\u0000',
15 'an utf8 string': 'ÀÁÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ',
16 'song lyrics': ("Voilà l'été, j'aperçois le soleil\n" +
17 "Les nuages filent et le ciel s'éclaircit\n" +
18 "Et dans ma tête qui bourdonnent?\n" +
19 "Les abeilles!"),
20 'a file contents': fs.read(phantom.casperPath + '/tests/site/alert.html')
21 };
22 for (var what in testCases) {
23 var source = testCases[what];
24 var encoded = clientutils.encode(source);
25 casper.test.assertEquals(clientutils.decode(encoded), source, 'ClientUtils.encode() encodes and decodes ' + what);
26 }
27 })(casper);
28
29 (function(casper) {
30 casper.test.comment('ClientUtils.exists()');
31 var clientutils = require('clientutils').create();
32 fakeDocument('<ul class="foo"><li>bar</li><li>baz</li></ul>');
33 casper.test.assert(clientutils.exists('ul'), 'ClientUtils.exists() checks that an element exist');
34 casper.test.assertNot(clientutils.exists('ol'), 'ClientUtils.exists() checks that an element exist');
35 casper.test.assert(clientutils.exists('ul.foo li'), 'ClientUtils.exists() checks that an element exist');
36 // xpath
37 casper.test.assert(clientutils.exists(x('//ul')), 'ClientUtils.exists() checks that an element exist using XPath');
38 casper.test.assertNot(clientutils.exists(x('//ol')), 'ClientUtils.exists() checks that an element exist using XPath');
39 fakeDocument(null);
40 })(casper);
41
42 (function(casper) {
43 casper.test.comment('ClientUtils.findAll()');
44 var clientutils = require('clientutils').create();
45 fakeDocument('<ul class="foo"><li>bar</li><li>baz</li></ul>');
46 casper.test.assertType(clientutils.findAll('li'), 'nodelist', 'ClientUtils.findAll() can find matching DOM elements');
47 casper.test.assertEquals(clientutils.findAll('li').length, 2, 'ClientUtils.findAll() can find matching DOM elements');
48 casper.test.assertType(clientutils.findAll('ol'), 'nodelist', 'ClientUtils.findAll() can find matching DOM elements');
49 casper.test.assertEquals(clientutils.findAll('ol').length, 0, 'ClientUtils.findAll() can find matching DOM elements');
50 // scoped
51 var scope = clientutils.findOne('ul');
52 casper.test.assertType(clientutils.findAll('li', scope), 'nodelist', 'ClientUtils.findAll() can find matching DOM elements within a given scope');
53 fakeDocument(null);
54 })(casper);
55
56 (function(casper) {
57 casper.test.comment('ClientUtils.findOne()');
58 var clientutils = require('clientutils').create();
59 fakeDocument('<ul class="foo"><li>bar</li><li>baz</li></ul>');
60 casper.test.assertType(clientutils.findOne('ul'), 'htmlulistelement', 'ClientUtils.findOne() can find a matching DOM element');
61 casper.test.assertNot(clientutils.findOne('ol'), 'ClientUtils.findOne() can find a matching DOM element');
62 // scoped
63 var scope = clientutils.findOne('ul');
64 casper.test.assertType(clientutils.findAll('li', scope), 'nodelist', 'ClientUtils.findAll() can find matching DOM elements within a given scope');
65 casper.test.assertEquals(clientutils.findAll('li', scope).length, 2, 'ClientUtils.findAll() can find matching DOM elements within a given scope');
66 fakeDocument(null);
67 })(casper);
68
69 (function(casper) {
70 casper.test.comment('ClientUtils.processSelector()');
71 var clientutils = require('clientutils').create();
72 // CSS3 selector
73 var cssSelector = clientutils.processSelector('html body > ul.foo li');
74 casper.test.assertType(cssSelector, 'object', 'ClientUtils.processSelector() can process a CSS3 selector');
75 casper.test.assertEquals(cssSelector.type, 'css', 'ClientUtils.processSelector() can process a CSS3 selector');
76 casper.test.assertEquals(cssSelector.path, 'html body > ul.foo li', 'ClientUtils.processSelector() can process a CSS3 selector');
77 // XPath selector
78 var xpathSelector = clientutils.processSelector(x('//li[text()="blah"]'));
79 casper.test.assertType(xpathSelector, 'object', 'ClientUtils.processSelector() can process a XPath selector');
80 casper.test.assertEquals(xpathSelector.type, 'xpath', 'ClientUtils.processSelector() can process a XPath selector');
81 casper.test.assertEquals(xpathSelector.path, '//li[text()="blah"]', 'ClientUtils.processSelector() can process a XPath selector');
82 })(casper);
83
84 casper.test.done();
...@@ -96,6 +96,9 @@ casper.then(function() { ...@@ -96,6 +96,9 @@ casper.then(function() {
96 t.comment('Tester.assertTitle()'); 96 t.comment('Tester.assertTitle()');
97 t.assertTitle('CasperJS test index', 'Tester.assertTitle() works as expected'); 97 t.assertTitle('CasperJS test index', 'Tester.assertTitle() works as expected');
98 98
99 t.comment('Tester.assertTitleMatch()');
100 t.assertTitleMatch(/test index/, 'Tester.assertTitleMatch() works as expected');
101
99 t.comment('Tester.assertType()'); 102 t.comment('Tester.assertType()');
100 t.assertType("plop", "string", "Tester.assertType() works as expected"); 103 t.assertType("plop", "string", "Tester.assertType() works as expected");
101 104
......
...@@ -29,6 +29,13 @@ t.comment('fillBlanks()'); ...@@ -29,6 +29,13 @@ t.comment('fillBlanks()');
29 } 29 }
30 })(); 30 })();
31 31
32 t.comment('isArray()');
33 (function() {
34 t.assertEquals(utils.isArray([]), true, 'isArray() checks for an Array');
35 t.assertEquals(utils.isArray({}), false, 'isArray() checks for an Array');
36 t.assertEquals(utils.isArray("foo"), false, 'isArray() checks for an Array');
37 })();
38
32 t.comment('isClipRect()'); 39 t.comment('isClipRect()');
33 (function() { 40 (function() {
34 testCases = [ 41 testCases = [
...@@ -44,6 +51,26 @@ t.comment('isClipRect()'); ...@@ -44,6 +51,26 @@ t.comment('isClipRect()');
44 }); 51 });
45 })(); 52 })();
46 53
54 t.comment('isObject()');
55 (function() {
56 t.assertEquals(utils.isObject({}), true, 'isObject() checks for an Object');
57 t.assertEquals(utils.isObject([]), true, 'isObject() checks for an Object');
58 t.assertEquals(utils.isObject(1), false, 'isObject() checks for an Object');
59 t.assertEquals(utils.isObject("1"), false, 'isObject() checks for an Object');
60 t.assertEquals(utils.isObject(function(){}), false, 'isObject() checks for an Object');
61 t.assertEquals(utils.isObject(new Function('return {};')()), true, 'isObject() checks for an Object');
62 t.assertEquals(utils.isObject(require('webpage').create()), true, 'isObject() checks for an Object');
63 t.assertEquals(utils.isObject(null), false, 'isObject() checks for an Object');
64 })();
65
66 t.comment('isWebPage()');
67 (function() {
68 var pageModule = require('webpage');
69 t.assertEquals(utils.isWebPage(pageModule), false, 'isWebPage() checks for a WebPage instance');
70 t.assertEquals(utils.isWebPage(pageModule.create()), true, 'isWebPage() checks for a WebPage instance');
71 t.assertEquals(utils.isWebPage(null), false, 'isWebPage() checks for a WebPage instance');
72 })();
73
47 t.comment('isJsFile()'); 74 t.comment('isJsFile()');
48 (function() { 75 (function() {
49 testCases = { 76 testCases = {
...@@ -90,4 +117,29 @@ t.comment('mergeObjects()'); ...@@ -90,4 +117,29 @@ t.comment('mergeObjects()');
90 }); 117 });
91 })(); 118 })();
92 119
120 t.comment('unique()');
121 (function() {
122 testCases = [
123 {
124 input: [1,2,3],
125 output: [1,2,3]
126 },
127 {
128 input: [1,2,3,2,1],
129 output: [1,2,3]
130 },
131 {
132 input: ["foo", "bar", "foo"],
133 output: ["foo", "bar"]
134 },
135 {
136 input: [],
137 output: []
138 }
139 ];
140 testCases.forEach(function(testCase) {
141 t.assertEquals(utils.unique(testCase.input), testCase.output, 'unique() computes unique values of an array');
142 });
143 })();
144
93 t.done(); 145 t.done();
......