merged with master
Showing
26 changed files
with
421 additions
and
146 deletions
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! | ... | ... |
This diff is collapsed.
Click to expand it.
... | @@ -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) | ... | ... |
This diff is collapsed.
Click to expand it.
... | @@ -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 is collapsed.
Click to expand it.
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> | ... | ... |
tests/site/multiple-forms.html
0 → 100644
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> |
tests/suites/casper/agent.js
0 → 100644
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 | }); |
tests/suites/casper/clientutils.js
deleted
100644 → 0
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 | }); | ... | ... |
tests/suites/clientutils.js
0 → 100644
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(); | ... | ... |
-
Please register or sign in to post a comment