Initial attempt at bringing support for test cases - refs #56
Showing
11 changed files
with
665 additions
and
429 deletions
... | @@ -4,6 +4,7 @@ CasperJS Changelog | ... | @@ -4,6 +4,7 @@ CasperJS Changelog |
4 | XXXX-XX-XX, v1.0.0 | 4 | XXXX-XX-XX, v1.0.0 |
5 | ------------------ | 5 | ------------------ |
6 | 6 | ||
7 | - merged PR [#322](https://github.com/n1k0/casperjs/pull/322) - Support number in withFrame() | ||
7 | - fixed [#323](https://github.com/n1k0/casperjs/issues/323) - `thenEvaluate()` should be updated to take the same parameters as `evaluate()`, while maintaining backwards compatibility. | 8 | - fixed [#323](https://github.com/n1k0/casperjs/issues/323) - `thenEvaluate()` should be updated to take the same parameters as `evaluate()`, while maintaining backwards compatibility. |
8 | - merged PR [#319](https://github.com/n1k0/casperjs/pull/319), fixed [#209](https://github.com/n1k0/casperjs/issues/209) - test duration has been added to XUnit XML result file. | 9 | - merged PR [#319](https://github.com/n1k0/casperjs/pull/319), fixed [#209](https://github.com/n1k0/casperjs/issues/209) - test duration has been added to XUnit XML result file. |
9 | - `Casper.userAgent()` does not require the instance to be started anymore | 10 | - `Casper.userAgent()` does not require the instance to be started anymore | ... | ... |
... | @@ -5,17 +5,18 @@ You can check out the [contribution graphs on github](https://github.com/n1k0/ca | ... | @@ -5,17 +5,18 @@ You can check out the [contribution graphs on github](https://github.com/n1k0/ca |
5 | ``` | 5 | ``` |
6 | $ git shortlog -s -n | cut -c8- | 6 | $ git shortlog -s -n | cut -c8- |
7 | Nicolas Perriault | 7 | Nicolas Perriault |
8 | oncletom | ||
9 | Brikou CARRE | 8 | Brikou CARRE |
9 | oncletom | ||
10 | hannyu | 10 | hannyu |
11 | Chris Lorenzo | 11 | Chris Lorenzo |
12 | Victor Yap | 12 | Victor Yap |
13 | nrabinowitz | 13 | nrabinowitz |
14 | pborreli | 14 | pborreli |
15 | Dave Lee | 15 | Rob Barreca |
16 | Andrew Childs | ||
16 | Solomon White | 17 | Solomon White |
17 | reina.sweet | 18 | reina.sweet |
18 | Andrew Childs | 19 | Dave Lee |
19 | Reina Sweet | 20 | Reina Sweet |
20 | Elmar Langholz | 21 | Elmar Langholz |
21 | Jason Funk | 22 | Jason Funk |
... | @@ -24,7 +25,6 @@ Julien Moulin | ... | @@ -24,7 +25,6 @@ Julien Moulin |
24 | Michael Geers | 25 | Michael Geers |
25 | Jan Schaumann | 26 | Jan Schaumann |
26 | Clochix | 27 | Clochix |
27 | Rafael Garcia | ||
28 | Raphaël Benitte | 28 | Raphaël Benitte |
29 | Tim Bunce | 29 | Tim Bunce |
30 | alfetopito | 30 | alfetopito |
... | @@ -49,4 +49,5 @@ Mehdi Kabab | ... | @@ -49,4 +49,5 @@ Mehdi Kabab |
49 | Mikko Peltonen | 49 | Mikko Peltonen |
50 | Pascal Borreli | 50 | Pascal Borreli |
51 | Rafael | 51 | Rafael |
52 | Rafael Garcia | ||
52 | ``` | 53 | ``` | ... | ... |
... | @@ -1372,6 +1372,19 @@ Casper.prototype.sendKeys = function(selector, keys, options) { | ... | @@ -1372,6 +1372,19 @@ Casper.prototype.sendKeys = function(selector, keys, options) { |
1372 | }; | 1372 | }; |
1373 | 1373 | ||
1374 | /** | 1374 | /** |
1375 | * Sets current page content. | ||
1376 | * | ||
1377 | * @param String content Desired page content | ||
1378 | * @return Casper | ||
1379 | */ | ||
1380 | Casper.prototype.setContent = function setContent(content) { | ||
1381 | "use strict"; | ||
1382 | this.checkStarted(); | ||
1383 | this.page.content = content; | ||
1384 | return this; | ||
1385 | }; | ||
1386 | |||
1387 | /** | ||
1375 | * Sets current WebPage instance the credentials for HTTP authentication. | 1388 | * Sets current WebPage instance the credentials for HTTP authentication. |
1376 | * | 1389 | * |
1377 | * @param String username | 1390 | * @param String username |
... | @@ -1873,18 +1886,22 @@ Casper.prototype.waitWhileVisible = function waitWhileVisible(selector, then, on | ... | @@ -1873,18 +1886,22 @@ Casper.prototype.waitWhileVisible = function waitWhileVisible(selector, then, on |
1873 | * Makes the provided frame page as the currently active one. Note that the | 1886 | * Makes the provided frame page as the currently active one. Note that the |
1874 | * active page will be reverted when finished. | 1887 | * active page will be reverted when finished. |
1875 | * | 1888 | * |
1876 | * @param String frameName Target frame name | 1889 | * @param String|Number frameInfo Target frame name or number |
1877 | * @param Function then Next step function | 1890 | * @param Function then Next step function |
1878 | * @return Casper | 1891 | * @return Casper |
1879 | */ | 1892 | */ |
1880 | Casper.prototype.withFrame = function withFrame(frameName, then) { | 1893 | Casper.prototype.withFrame = function withFrame(frameInfo, then) { |
1881 | "use strict"; | 1894 | "use strict"; |
1882 | this.then(function _step() { | 1895 | this.then(function _step() { |
1883 | if (this.page.childFramesName().indexOf(frameName) === -1) { | 1896 | if (utils.isNumber(frameInfo)) { |
1884 | throw new CasperError(f('No frame named "%s" was found.', frameName)); | 1897 | if (frameInfo > this.page.childFramesCount() - 1) { |
1898 | throw new CasperError(f('Frame number "%d" is out of bounds.', frameInfo)); | ||
1899 | } | ||
1900 | } else if (this.page.childFramesName().indexOf(frameInfo) === -1) { | ||
1901 | throw new CasperError(f('No frame named "%s" was found.', frameInfo)); | ||
1885 | } | 1902 | } |
1886 | // make the frame page the currently active one | 1903 | // make the frame page the currently active one |
1887 | this.page.switchToChildFrame(frameName); | 1904 | this.page.switchToChildFrame(frameInfo); |
1888 | }); | 1905 | }); |
1889 | try { | 1906 | try { |
1890 | this.then(then); | 1907 | this.then(then); | ... | ... |
... | @@ -35,6 +35,13 @@ var events = require('events'); | ... | @@ -35,6 +35,13 @@ var events = require('events'); |
35 | var utils = require('utils'); | 35 | var utils = require('utils'); |
36 | var f = utils.format; | 36 | var f = utils.format; |
37 | 37 | ||
38 | /** | ||
39 | * Creates a tester instance. | ||
40 | * | ||
41 | * @param Casper casper A Casper instance | ||
42 | * @param Object options Tester options | ||
43 | * @return Tester | ||
44 | */ | ||
38 | exports.create = function create(casper, options) { | 45 | exports.create = function create(casper, options) { |
39 | "use strict"; | 46 | "use strict"; |
40 | return new Tester(casper, options); | 47 | return new Tester(casper, options); |
... | @@ -48,7 +55,7 @@ exports.create = function create(casper, options) { | ... | @@ -48,7 +55,7 @@ exports.create = function create(casper, options) { |
48 | */ | 55 | */ |
49 | var Tester = function Tester(casper, options) { | 56 | var Tester = function Tester(casper, options) { |
50 | "use strict"; | 57 | "use strict"; |
51 | /*jshint maxstatements:20*/ | 58 | /*jshint maxstatements:30*/ |
52 | 59 | ||
53 | if (!utils.isCasperObject(casper)) { | 60 | if (!utils.isCasperObject(casper)) { |
54 | throw new CasperError("Tester needs a Casper instance"); | 61 | throw new CasperError("Tester needs a Casper instance"); |
... | @@ -60,32 +67,22 @@ var Tester = function Tester(casper, options) { | ... | @@ -60,32 +67,22 @@ var Tester = function Tester(casper, options) { |
60 | 67 | ||
61 | this.executed = 0; | 68 | this.executed = 0; |
62 | this.currentTestFile = null; | 69 | this.currentTestFile = null; |
70 | this.currentSuite = undefined; | ||
63 | this.currentSuiteNum = 0; | 71 | this.currentSuiteNum = 0; |
64 | this.exporter = require('xunit').create(); | ||
65 | this.loadIncludes = { | 72 | this.loadIncludes = { |
66 | includes: [], | 73 | includes: [], |
67 | pre: [], | 74 | pre: [], |
68 | post: [] | 75 | post: [] |
69 | }; | 76 | }; |
70 | this.running = false; | 77 | this.running = false; |
71 | this.suites = []; | 78 | this.suites = new TestSuite(); |
72 | this.options = utils.mergeObjects({ | 79 | this.options = utils.mergeObjects({ |
73 | failFast: false, // terminates a suite as soon as a test fails? | 80 | failFast: false, // terminates a suite as soon as a test fails? |
74 | failText: "FAIL", // text to use for a successful test | 81 | failText: "FAIL", // text to use for a succesful test |
75 | passText: "PASS", // text to use for a failed test | 82 | passText: "PASS", // text to use for a failed test |
76 | pad: 80 // maximum number of chars for a result line | 83 | pad: 80 // maximum number of chars for a result line |
77 | }, options); | 84 | }, options); |
78 | 85 | ||
79 | // properties | ||
80 | this.testResults = { | ||
81 | passed: 0, | ||
82 | failed: 0, | ||
83 | passes: [], | ||
84 | failures: [], | ||
85 | passesTime: [], | ||
86 | failuresTime: [] | ||
87 | }; | ||
88 | |||
89 | // measuring test duration | 86 | // measuring test duration |
90 | this.currentTestStartTime = null; | 87 | this.currentTestStartTime = null; |
91 | this.lastAssertTime = 0; | 88 | this.lastAssertTime = 0; |
... | @@ -93,47 +90,27 @@ var Tester = function Tester(casper, options) { | ... | @@ -93,47 +90,27 @@ var Tester = function Tester(casper, options) { |
93 | this.configure(); | 90 | this.configure(); |
94 | 91 | ||
95 | this.on('success', function onSuccess(success) { | 92 | this.on('success', function onSuccess(success) { |
96 | this.testResults.passes.push(success); | ||
97 | var timeElapsed = new Date() - this.currentTestStartTime; | 93 | var timeElapsed = new Date() - this.currentTestStartTime; |
98 | this.testResults.passesTime.push(timeElapsed - this.lastAssertTime); | 94 | this.currentSuite.addSuccess(success, timeElapsed - this.lastAssertTime); |
99 | this.exporter.addSuccess(fs.absolute(success.file), success.message || success.standard, timeElapsed - this.lastAssertTime); | ||
100 | this.lastAssertTime = timeElapsed; | 95 | this.lastAssertTime = timeElapsed; |
101 | }); | 96 | }); |
102 | 97 | ||
103 | this.on('fail', function onFail(failure) { | 98 | this.on('fail', function onFail(failure) { |
104 | // export | 99 | // export |
105 | var timeElapsed = new Date() - this.currentTestStartTime; | 100 | var valueKeys = Object.keys(failure.values), |
106 | this.testResults.failuresTime.push(timeElapsed - this.lastAssertTime); | 101 | timeElapsed = new Date() - this.currentTestStartTime; |
107 | this.exporter.addFailure( | 102 | this.currentSuite.addFailure(failure, timeElapsed - this.lastAssertTime); |
108 | fs.absolute(failure.file), | ||
109 | failure.message || failure.standard, | ||
110 | failure.standard || "test failed", | ||
111 | failure.type || "unknown", | ||
112 | (timeElapsed - this.lastAssertTime) | ||
113 | ); | ||
114 | this.lastAssertTime = timeElapsed; | 103 | this.lastAssertTime = timeElapsed; |
115 | this.testResults.failures.push(failure); | ||
116 | |||
117 | // special printing | 104 | // special printing |
118 | if (failure.type) { | 105 | if (failure.type) { |
119 | this.comment(' type: ' + failure.type); | 106 | this.comment(' type: ' + failure.type); |
120 | } | 107 | } |
121 | if (failure.values && Object.keys(failure.values).length > 0) { | 108 | if (!failure.values || valueKeys.length === 0) { |
122 | for (var name in failure.values) { | 109 | return; |
123 | var comment = ' ' + name + ': '; | ||
124 | var value = failure.values[name]; | ||
125 | try { | ||
126 | comment += utils.serialize(failure.values[name]); | ||
127 | } catch (e) { | ||
128 | try { | ||
129 | comment += utils.serialize(failure.values[name].toString()); | ||
130 | } catch (e2) { | ||
131 | comment += '(unserializable value)'; | ||
132 | } | ||
133 | } | ||
134 | this.comment(comment); | ||
135 | } | ||
136 | } | 110 | } |
111 | valueKeys.forEach(function(name) { | ||
112 | this.comment(f(' %s: %s', name, utils.formatTestValue(failure.values[name], name))); | ||
113 | }.bind(this)); | ||
137 | }); | 114 | }); |
138 | 115 | ||
139 | // casper events | 116 | // casper events |
... | @@ -147,7 +124,7 @@ var Tester = function Tester(casper, options) { | ... | @@ -147,7 +124,7 @@ var Tester = function Tester(casper, options) { |
147 | line = backtrace[0].line; | 124 | line = backtrace[0].line; |
148 | } catch (e) {} | 125 | } catch (e) {} |
149 | } | 126 | } |
150 | this.test.uncaughtError(msg, this.test.currentTestFile, line); | 127 | this.test.uncaughtError(msg, this.test.currentTestFile, line, backtrace); |
151 | this.test.done(); | 128 | this.test.done(); |
152 | }); | 129 | }); |
153 | 130 | ||
... | @@ -175,16 +152,17 @@ exports.Tester = Tester; | ... | @@ -175,16 +152,17 @@ exports.Tester = Tester; |
175 | * @param Object|null context Assertion context object (Optional) | 152 | * @param Object|null context Assertion context object (Optional) |
176 | * @return Object An assertion result object | 153 | * @return Object An assertion result object |
177 | */ | 154 | */ |
178 | Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, message, context) { | 155 | Tester.prototype.assert = |
156 | Tester.prototype.assertTrue = function assert(subject, message, context) { | ||
179 | "use strict"; | 157 | "use strict"; |
180 | this.executed++; | 158 | this.executed++; |
181 | return this.processAssertionResult(utils.mergeObjects({ | 159 | return this.processAssertionResult(utils.mergeObjects({ |
182 | success: subject === true, | 160 | success: subject === true, |
183 | type: "assert", | 161 | type: "assert", |
184 | standard: "Subject is strictly true", | 162 | standard: "Subject is strictly true", |
185 | message: message, | 163 | message: message, |
186 | file: this.currentTestFile, | 164 | file: this.currentTestFile, |
187 | values: { | 165 | values: { |
188 | subject: utils.getPropertyPath(context, 'values.subject') || subject | 166 | subject: utils.getPropertyPath(context, 'values.subject') || subject |
189 | } | 167 | } |
190 | }, context || {})); | 168 | }, context || {})); |
... | @@ -198,12 +176,13 @@ Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, | ... | @@ -198,12 +176,13 @@ Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, |
198 | * @param String message Test description (Optional) | 176 | * @param String message Test description (Optional) |
199 | * @return Object An assertion result object | 177 | * @return Object An assertion result object |
200 | */ | 178 | */ |
201 | Tester.prototype.assertEquals = Tester.prototype.assertEqual = function assertEquals(subject, expected, message) { | 179 | Tester.prototype.assertEquals = |
180 | Tester.prototype.assertEqual = function assertEquals(subject, expected, message) { | ||
202 | "use strict"; | 181 | "use strict"; |
203 | return this.assert(this.testEquals(subject, expected), message, { | 182 | return this.assert(utils.equals(subject, expected), message, { |
204 | type: "assertEquals", | 183 | type: "assertEquals", |
205 | standard: "Subject equals the expected value", | 184 | standard: "Subject equals the expected value", |
206 | values: { | 185 | values: { |
207 | subject: subject, | 186 | subject: subject, |
208 | expected: expected | 187 | expected: expected |
209 | } | 188 | } |
... | @@ -221,9 +200,9 @@ Tester.prototype.assertEquals = Tester.prototype.assertEqual = function assertEq | ... | @@ -221,9 +200,9 @@ Tester.prototype.assertEquals = Tester.prototype.assertEqual = function assertEq |
221 | Tester.prototype.assertNotEquals = function assertNotEquals(subject, shouldnt, message) { | 200 | Tester.prototype.assertNotEquals = function assertNotEquals(subject, shouldnt, message) { |
222 | "use strict"; | 201 | "use strict"; |
223 | return this.assert(!this.testEquals(subject, shouldnt), message, { | 202 | return this.assert(!this.testEquals(subject, shouldnt), message, { |
224 | type: "assertNotEquals", | 203 | type: "assertNotEquals", |
225 | standard: "Subject doesn't equal what it shouldn't be", | 204 | standard: "Subject doesn't equal what it shouldn't be", |
226 | values: { | 205 | values: { |
227 | subject: subject, | 206 | subject: subject, |
228 | shouldnt: shouldnt | 207 | shouldnt: shouldnt |
229 | } | 208 | } |
... | @@ -235,13 +214,15 @@ Tester.prototype.assertNotEquals = function assertNotEquals(subject, shouldnt, m | ... | @@ -235,13 +214,15 @@ Tester.prototype.assertNotEquals = function assertNotEquals(subject, shouldnt, m |
235 | * | 214 | * |
236 | * @param Function fn A function to be evaluated in remote DOM | 215 | * @param Function fn A function to be evaluated in remote DOM |
237 | * @param String message Test description | 216 | * @param String message Test description |
238 | * @param Object params Object/Array containing the parameters to inject into the function (optional) | 217 | * @param Object params Object/Array containing the parameters to inject into |
218 | * the function (optional) | ||
239 | * @return Object An assertion result object | 219 | * @return Object An assertion result object |
240 | */ | 220 | */ |
241 | Tester.prototype.assertEval = Tester.prototype.assertEvaluate = function assertEval(fn, message, params) { | 221 | Tester.prototype.assertEval = |
222 | Tester.prototype.assertEvaluate = function assertEval(fn, message, params) { | ||
242 | "use strict"; | 223 | "use strict"; |
243 | return this.assert(this.casper.evaluate(fn, params), message, { | 224 | return this.assert(this.casper.evaluate(fn, params), message, { |
244 | type: "assertEval", | 225 | type: "assertEval", |
245 | standard: "Evaluated function returns true", | 226 | standard: "Evaluated function returns true", |
246 | values: { | 227 | values: { |
247 | fn: fn, | 228 | fn: fn, |
... | @@ -257,16 +238,18 @@ Tester.prototype.assertEval = Tester.prototype.assertEvaluate = function assertE | ... | @@ -257,16 +238,18 @@ Tester.prototype.assertEval = Tester.prototype.assertEvaluate = function assertE |
257 | * @param Function fn The function to be evaluated in remote DOM | 238 | * @param Function fn The function to be evaluated in remote DOM |
258 | * @param Boolean expected The expected value | 239 | * @param Boolean expected The expected value |
259 | * @param String|null message Test description | 240 | * @param String|null message Test description |
260 | * @param Object|null params Object containing the parameters to inject into the function (optional) | 241 | * @param Object|null params Object containing the parameters to inject into the |
242 | * function (optional) | ||
261 | * @return Object An assertion result object | 243 | * @return Object An assertion result object |
262 | */ | 244 | */ |
263 | Tester.prototype.assertEvalEquals = Tester.prototype.assertEvalEqual = function assertEvalEquals(fn, expected, message, params) { | 245 | Tester.prototype.assertEvalEquals = |
246 | Tester.prototype.assertEvalEqual = function assertEvalEquals(fn, expected, message, params) { | ||
264 | "use strict"; | 247 | "use strict"; |
265 | var subject = this.casper.evaluate(fn, params); | 248 | var subject = this.casper.evaluate(fn, params); |
266 | return this.assert(this.testEquals(subject, expected), message, { | 249 | return this.assert(utils.equals(subject, expected), message, { |
267 | type: "assertEvalEquals", | 250 | type: "assertEvalEquals", |
268 | standard: "Evaluated function returns the expected value", | 251 | standard: "Evaluated function returns the expected value", |
269 | values: { | 252 | values: { |
270 | fn: fn, | 253 | fn: fn, |
271 | params: params, | 254 | params: params, |
272 | subject: subject, | 255 | subject: subject, |
... | @@ -288,13 +271,13 @@ Tester.prototype.assertField = function assertField(inputName, expected, messag | ... | @@ -288,13 +271,13 @@ Tester.prototype.assertField = function assertField(inputName, expected, messag |
288 | var actual = this.casper.evaluate(function(inputName) { | 271 | var actual = this.casper.evaluate(function(inputName) { |
289 | return __utils__.getFieldValue(inputName); | 272 | return __utils__.getFieldValue(inputName); |
290 | }, inputName); | 273 | }, inputName); |
291 | return this.assert(this.testEquals(actual, expected), message, { | 274 | return this.assert(utils.equals(actual, expected), message, { |
292 | type: 'assertField', | 275 | type: 'assertField', |
293 | standard: f('"%s" input field has the value "%s"', inputName, expected), | 276 | standard: f('"%s" input field has the value "%s"', inputName, expected), |
294 | values: { | 277 | values: { |
295 | inputName: inputName, | 278 | inputName: inputName, |
296 | actual: actual, | 279 | actual: actual, |
297 | expected: expected | 280 | expected: expected |
298 | } | 281 | } |
299 | }); | 282 | }); |
300 | }; | 283 | }; |
... | @@ -307,7 +290,10 @@ Tester.prototype.assertField = function assertField(inputName, expected, messag | ... | @@ -307,7 +290,10 @@ Tester.prototype.assertField = function assertField(inputName, expected, messag |
307 | * @param String message Test description | 290 | * @param String message Test description |
308 | * @return Object An assertion result object | 291 | * @return Object An assertion result object |
309 | */ | 292 | */ |
310 | Tester.prototype.assertExists = Tester.prototype.assertExist = Tester.prototype.assertSelectorExists = Tester.prototype.assertSelectorExist = function assertExists(selector, message) { | 293 | Tester.prototype.assertExists = |
294 | Tester.prototype.assertExist = | ||
295 | Tester.prototype.assertSelectorExists = | ||
296 | Tester.prototype.assertSelectorExist = function assertExists(selector, message) { | ||
311 | "use strict"; | 297 | "use strict"; |
312 | return this.assert(this.casper.exists(selector), message, { | 298 | return this.assert(this.casper.exists(selector), message, { |
313 | type: "assertExists", | 299 | type: "assertExists", |
... | @@ -326,7 +312,8 @@ Tester.prototype.assertExists = Tester.prototype.assertExist = Tester.prototype. | ... | @@ -326,7 +312,8 @@ Tester.prototype.assertExists = Tester.prototype.assertExist = Tester.prototype. |
326 | * @param String message Test description | 312 | * @param String message Test description |
327 | * @return Object An assertion result object | 313 | * @return Object An assertion result object |
328 | */ | 314 | */ |
329 | Tester.prototype.assertDoesntExist = Tester.prototype.assertNotExists = function assertDoesntExist(selector, message) { | 315 | Tester.prototype.assertDoesntExist = |
316 | Tester.prototype.assertNotExists = function assertDoesntExist(selector, message) { | ||
330 | "use strict"; | 317 | "use strict"; |
331 | return this.assert(!this.casper.exists(selector), message, { | 318 | return this.assert(!this.casper.exists(selector), message, { |
332 | type: "assertDoesntExist", | 319 | type: "assertDoesntExist", |
... | @@ -347,7 +334,7 @@ Tester.prototype.assertDoesntExist = Tester.prototype.assertNotExists = function | ... | @@ -347,7 +334,7 @@ Tester.prototype.assertDoesntExist = Tester.prototype.assertNotExists = function |
347 | Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) { | 334 | Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) { |
348 | "use strict"; | 335 | "use strict"; |
349 | var currentHTTPStatus = this.casper.currentHTTPStatus; | 336 | var currentHTTPStatus = this.casper.currentHTTPStatus; |
350 | return this.assert(this.testEquals(this.casper.currentHTTPStatus, status), message, { | 337 | return this.assert(utils.equals(this.casper.currentHTTPStatus, status), message, { |
351 | type: "assertHttpStatus", | 338 | type: "assertHttpStatus", |
352 | standard: f("HTTP status code is: %s", status), | 339 | standard: f("HTTP status code is: %s", status), |
353 | values: { | 340 | values: { |
... | @@ -365,7 +352,8 @@ Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) { | ... | @@ -365,7 +352,8 @@ Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) { |
365 | * @param String message Test description | 352 | * @param String message Test description |
366 | * @return Object An assertion result object | 353 | * @return Object An assertion result object |
367 | */ | 354 | */ |
368 | Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertMatch(subject, pattern, message) { | 355 | Tester.prototype.assertMatch = |
356 | Tester.prototype.assertMatches = function assertMatch(subject, pattern, message) { | ||
369 | "use strict"; | 357 | "use strict"; |
370 | return this.assert(pattern.test(subject), message, { | 358 | return this.assert(pattern.test(subject), message, { |
371 | type: "assertMatch", | 359 | type: "assertMatch", |
... | @@ -384,7 +372,8 @@ Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertM | ... | @@ -384,7 +372,8 @@ Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertM |
384 | * @param String message Test description | 372 | * @param String message Test description |
385 | * @return Object An assertion result object | 373 | * @return Object An assertion result object |
386 | */ | 374 | */ |
387 | Tester.prototype.assertNot = Tester.prototype.assertFalse = function assertNot(condition, message) { | 375 | Tester.prototype.assertNot = |
376 | Tester.prototype.assertFalse = function assertNot(condition, message) { | ||
388 | "use strict"; | 377 | "use strict"; |
389 | return this.assert(!condition, message, { | 378 | return this.assert(!condition, message, { |
390 | type: "assertNot", | 379 | type: "assertNot", |
... | @@ -402,7 +391,8 @@ Tester.prototype.assertNot = Tester.prototype.assertFalse = function assertNot(c | ... | @@ -402,7 +391,8 @@ Tester.prototype.assertNot = Tester.prototype.assertFalse = function assertNot(c |
402 | * @param String message Test description | 391 | * @param String message Test description |
403 | * @return Object An assertion result object | 392 | * @return Object An assertion result object |
404 | */ | 393 | */ |
405 | Tester.prototype.assertNotVisible = Tester.prototype.assertInvisible = function assertNotVisible(selector, message) { | 394 | Tester.prototype.assertNotVisible = |
395 | Tester.prototype.assertInvisible = function assertNotVisible(selector, message) { | ||
406 | "use strict"; | 396 | "use strict"; |
407 | return this.assert(!this.casper.visible(selector), message, { | 397 | return this.assert(!this.casper.visible(selector), message, { |
408 | type: "assertVisible", | 398 | type: "assertVisible", |
... | @@ -422,7 +412,9 @@ Tester.prototype.assertNotVisible = Tester.prototype.assertInvisible = function | ... | @@ -422,7 +412,9 @@ Tester.prototype.assertNotVisible = Tester.prototype.assertInvisible = function |
422 | * @param String message Test description | 412 | * @param String message Test description |
423 | * @return Object An assertion result object | 413 | * @return Object An assertion result object |
424 | */ | 414 | */ |
425 | Tester.prototype.assertRaises = Tester.prototype.assertRaise = Tester.prototype.assertThrows = function assertRaises(fn, args, message) { | 415 | Tester.prototype.assertRaises = |
416 | Tester.prototype.assertRaise = | ||
417 | Tester.prototype.assertThrows = function assertRaises(fn, args, message) { | ||
426 | "use strict"; | 418 | "use strict"; |
427 | var context = { | 419 | var context = { |
428 | type: "assertRaises", | 420 | type: "assertRaises", |
... | @@ -447,7 +439,8 @@ Tester.prototype.assertRaises = Tester.prototype.assertRaise = Tester.prototype. | ... | @@ -447,7 +439,8 @@ Tester.prototype.assertRaises = Tester.prototype.assertRaise = Tester.prototype. |
447 | * @param String message Test description | 439 | * @param String message Test description |
448 | * @return Object An assertion result object | 440 | * @return Object An assertion result object |
449 | */ | 441 | */ |
450 | Tester.prototype.assertResourceExists = Tester.prototype.assertResourceExist = function assertResourceExists(test, message) { | 442 | Tester.prototype.assertResourceExists = |
443 | Tester.prototype.assertResourceExist = function assertResourceExists(test, message) { | ||
451 | "use strict"; | 444 | "use strict"; |
452 | return this.assert(this.casper.resourceExists(test), message, { | 445 | return this.assert(this.casper.resourceExists(test), message, { |
453 | type: "assertResourceExists", | 446 | type: "assertResourceExists", |
... | @@ -465,7 +458,8 @@ Tester.prototype.assertResourceExists = Tester.prototype.assertResourceExist = f | ... | @@ -465,7 +458,8 @@ Tester.prototype.assertResourceExists = Tester.prototype.assertResourceExist = f |
465 | * @param String message Test description | 458 | * @param String message Test description |
466 | * @return Object An assertion result object | 459 | * @return Object An assertion result object |
467 | */ | 460 | */ |
468 | Tester.prototype.assertTextDoesntExist = Tester.prototype.assertTextDoesntExist = function assertTextDoesntExist(text, message) { | 461 | Tester.prototype.assertTextDoesntExist = |
462 | Tester.prototype.assertTextDoesntExist = function assertTextDoesntExist(text, message) { | ||
469 | "use strict"; | 463 | "use strict"; |
470 | var textFound = (this.casper.evaluate(function _evaluate() { | 464 | var textFound = (this.casper.evaluate(function _evaluate() { |
471 | return document.body.textContent || document.body.innerText; | 465 | return document.body.textContent || document.body.innerText; |
... | @@ -486,7 +480,8 @@ Tester.prototype.assertTextDoesntExist = Tester.prototype.assertTextDoesntExist | ... | @@ -486,7 +480,8 @@ Tester.prototype.assertTextDoesntExist = Tester.prototype.assertTextDoesntExist |
486 | * @param String message Test description | 480 | * @param String message Test description |
487 | * @return Object An assertion result object | 481 | * @return Object An assertion result object |
488 | */ | 482 | */ |
489 | Tester.prototype.assertTextExists = Tester.prototype.assertTextExist = function assertTextExists(text, message) { | 483 | Tester.prototype.assertTextExists = |
484 | Tester.prototype.assertTextExist = function assertTextExists(text, message) { | ||
490 | "use strict"; | 485 | "use strict"; |
491 | var textFound = (this.casper.evaluate(function _evaluate() { | 486 | var textFound = (this.casper.evaluate(function _evaluate() { |
492 | return document.body.textContent || document.body.innerText; | 487 | return document.body.textContent || document.body.innerText; |
... | @@ -511,9 +506,9 @@ Tester.prototype.assertTruthy = function assertTruthy(subject, message) { | ... | @@ -511,9 +506,9 @@ Tester.prototype.assertTruthy = function assertTruthy(subject, message) { |
511 | "use strict"; | 506 | "use strict"; |
512 | /*jshint eqeqeq:false*/ | 507 | /*jshint eqeqeq:false*/ |
513 | return this.assert(utils.isTruthy(subject), message, { | 508 | return this.assert(utils.isTruthy(subject), message, { |
514 | type: "assertTruthy", | 509 | type: "assertTruthy", |
515 | standard: "Subject is truthy", | 510 | standard: "Subject is truthy", |
516 | values: { | 511 | values: { |
517 | subject: subject | 512 | subject: subject |
518 | } | 513 | } |
519 | }); | 514 | }); |
... | @@ -530,9 +525,9 @@ Tester.prototype.assertFalsy = function assertFalsy(subject, message) { | ... | @@ -530,9 +525,9 @@ Tester.prototype.assertFalsy = function assertFalsy(subject, message) { |
530 | "use strict"; | 525 | "use strict"; |
531 | /*jshint eqeqeq:false*/ | 526 | /*jshint eqeqeq:false*/ |
532 | return this.assert(utils.isFalsy(subject), message, { | 527 | return this.assert(utils.isFalsy(subject), message, { |
533 | type: "assertFalsy", | 528 | type: "assertFalsy", |
534 | standard: "Subject is falsy", | 529 | standard: "Subject is falsy", |
535 | values: { | 530 | values: { |
536 | subject: subject | 531 | subject: subject |
537 | } | 532 | } |
538 | }); | 533 | }); |
... | @@ -546,7 +541,8 @@ Tester.prototype.assertFalsy = function assertFalsy(subject, message) { | ... | @@ -546,7 +541,8 @@ Tester.prototype.assertFalsy = function assertFalsy(subject, message) { |
546 | * @param String message Test description | 541 | * @param String message Test description |
547 | * @return Object An assertion result object | 542 | * @return Object An assertion result object |
548 | */ | 543 | */ |
549 | Tester.prototype.assertSelectorHasText = Tester.prototype.assertSelectorContains = function assertSelectorHasText(selector, text, message) { | 544 | Tester.prototype.assertSelectorHasText = |
545 | Tester.prototype.assertSelectorContains = function assertSelectorHasText(selector, text, message) { | ||
550 | "use strict"; | 546 | "use strict"; |
551 | var textFound = this.casper.fetchText(selector).indexOf(text) !== -1; | 547 | var textFound = this.casper.fetchText(selector).indexOf(text) !== -1; |
552 | return this.assert(textFound, message, { | 548 | return this.assert(textFound, message, { |
... | @@ -567,7 +563,8 @@ Tester.prototype.assertSelectorHasText = Tester.prototype.assertSelectorContains | ... | @@ -567,7 +563,8 @@ Tester.prototype.assertSelectorHasText = Tester.prototype.assertSelectorContains |
567 | * @param String message Test description | 563 | * @param String message Test description |
568 | * @return Object An assertion result object | 564 | * @return Object An assertion result object |
569 | */ | 565 | */ |
570 | Tester.prototype.assertSelectorDoesntHaveText = Tester.prototype.assertSelectorDoesntContain = function assertSelectorDoesntHaveText(selector, text, message) { | 566 | Tester.prototype.assertSelectorDoesntHaveText = |
567 | Tester.prototype.assertSelectorDoesntContain = function assertSelectorDoesntHaveText(selector, text, message) { | ||
571 | "use strict"; | 568 | "use strict"; |
572 | var textFound = this.casper.fetchText(selector).indexOf(text) === -1; | 569 | var textFound = this.casper.fetchText(selector).indexOf(text) === -1; |
573 | return this.assert(textFound, message, { | 570 | return this.assert(textFound, message, { |
... | @@ -590,7 +587,7 @@ Tester.prototype.assertSelectorDoesntHaveText = Tester.prototype.assertSelectorD | ... | @@ -590,7 +587,7 @@ Tester.prototype.assertSelectorDoesntHaveText = Tester.prototype.assertSelectorD |
590 | Tester.prototype.assertTitle = function assertTitle(expected, message) { | 587 | Tester.prototype.assertTitle = function assertTitle(expected, message) { |
591 | "use strict"; | 588 | "use strict"; |
592 | var currentTitle = this.casper.getTitle(); | 589 | var currentTitle = this.casper.getTitle(); |
593 | return this.assert(this.testEquals(currentTitle, expected), message, { | 590 | return this.assert(utils.equals(currentTitle, expected), message, { |
594 | type: "assertTitle", | 591 | type: "assertTitle", |
595 | standard: f('Page title is: "%s"', expected), | 592 | standard: f('Page title is: "%s"', expected), |
596 | values: { | 593 | values: { |
... | @@ -607,7 +604,8 @@ Tester.prototype.assertTitle = function assertTitle(expected, message) { | ... | @@ -607,7 +604,8 @@ Tester.prototype.assertTitle = function assertTitle(expected, message) { |
607 | * @param String message Test description | 604 | * @param String message Test description |
608 | * @return Object An assertion result object | 605 | * @return Object An assertion result object |
609 | */ | 606 | */ |
610 | Tester.prototype.assertTitleMatch = Tester.prototype.assertTitleMatches = function assertTitleMatch(pattern, message) { | 607 | Tester.prototype.assertTitleMatch = |
608 | Tester.prototype.assertTitleMatches = function assertTitleMatch(pattern, message) { | ||
611 | "use strict"; | 609 | "use strict"; |
612 | var currentTitle = this.casper.getTitle(); | 610 | var currentTitle = this.casper.getTitle(); |
613 | return this.assert(pattern.test(currentTitle), message, { | 611 | return this.assert(pattern.test(currentTitle), message, { |
... | @@ -631,7 +629,7 @@ Tester.prototype.assertTitleMatch = Tester.prototype.assertTitleMatches = functi | ... | @@ -631,7 +629,7 @@ Tester.prototype.assertTitleMatch = Tester.prototype.assertTitleMatches = functi |
631 | Tester.prototype.assertType = function assertType(subject, type, message) { | 629 | Tester.prototype.assertType = function assertType(subject, type, message) { |
632 | "use strict"; | 630 | "use strict"; |
633 | var actual = utils.betterTypeOf(subject); | 631 | var actual = utils.betterTypeOf(subject); |
634 | return this.assert(this.testEquals(actual, type), message, { | 632 | return this.assert(utils.equals(actual, type), message, { |
635 | type: "assertType", | 633 | type: "assertType", |
636 | standard: f('Subject type is: "%s"', type), | 634 | standard: f('Subject type is: "%s"', type), |
637 | values: { | 635 | values: { |
... | @@ -651,7 +649,8 @@ Tester.prototype.assertType = function assertType(subject, type, message) { | ... | @@ -651,7 +649,8 @@ Tester.prototype.assertType = function assertType(subject, type, message) { |
651 | * @param String message Test description | 649 | * @param String message Test description |
652 | * @return Object An assertion result object | 650 | * @return Object An assertion result object |
653 | */ | 651 | */ |
654 | Tester.prototype.assertUrlMatch = Tester.prototype.assertUrlMatches = function assertUrlMatch(pattern, message) { | 652 | Tester.prototype.assertUrlMatch = |
653 | Tester.prototype.assertUrlMatches = function assertUrlMatch(pattern, message) { | ||
655 | "use strict"; | 654 | "use strict"; |
656 | var currentUrl = this.casper.getCurrentUrl(), | 655 | var currentUrl = this.casper.getCurrentUrl(), |
657 | patternType = utils.betterTypeOf(pattern), | 656 | patternType = utils.betterTypeOf(pattern), |
... | @@ -701,16 +700,26 @@ Tester.prototype.bar = function bar(text, style) { | ... | @@ -701,16 +700,26 @@ Tester.prototype.bar = function bar(text, style) { |
701 | }; | 700 | }; |
702 | 701 | ||
703 | /** | 702 | /** |
704 | * Retrieves the sum of all durations of the tests which were | 703 | * Starts a suite. |
705 | * executed in the current suite | ||
706 | * | 704 | * |
707 | * @return Number duration of all tests executed until now (in the current suite) | 705 | * @param String description Test suite description |
706 | * @param Function suiteFn Suite function | ||
708 | */ | 707 | */ |
709 | Tester.prototype.calculateSuiteDuration = function calculateSuiteDuration() { | 708 | Tester.prototype.begin = function begin(description, suiteFn) { |
710 | "use strict"; | 709 | "use strict"; |
711 | return this.testResults.passesTime.concat(this.testResults.failuresTime).reduce(function add(a, b) { | 710 | description = description || "Untitled suite in " + this.currentTestFile; |
712 | return a + b; | 711 | this.comment(description); |
713 | }, 0); | 712 | this.executed = 0; |
713 | this.currentSuite = new TestSuiteResult({ | ||
714 | name: description, | ||
715 | file: this.currentTestFile | ||
716 | }); | ||
717 | try { | ||
718 | suiteFn.call(this, this.casper); | ||
719 | } catch (e) { | ||
720 | this.uncaughtError(e, this.currentTestFile, e.line); | ||
721 | this.done(); | ||
722 | } | ||
714 | }; | 723 | }; |
715 | 724 | ||
716 | /** | 725 | /** |
... | @@ -767,14 +776,38 @@ Tester.prototype.configure = function configure() { | ... | @@ -767,14 +776,38 @@ Tester.prototype.configure = function configure() { |
767 | Tester.prototype.done = function done(planned) { | 776 | Tester.prototype.done = function done(planned) { |
768 | "use strict"; | 777 | "use strict"; |
769 | if (planned > 0 && planned !== this.executed) { | 778 | if (planned > 0 && planned !== this.executed) { |
770 | this.fail(f('%s: %d tests planned, %d tests executed', | 779 | this.dubious(planned, this.executed); |
771 | this.currentTestFile, planned, this.executed)); | 780 | } |
781 | if (this.currentSuite) { | ||
782 | this.suites.push(this.currentSuite); | ||
783 | this.currentSuite = undefined; | ||
784 | this.executed = 0; | ||
772 | } | 785 | } |
773 | this.emit('test.done'); | 786 | this.emit('test.done'); |
774 | this.running = false; | 787 | this.running = false; |
775 | }; | 788 | }; |
776 | 789 | ||
777 | /** | 790 | /** |
791 | * Marks a test as dubious, when the number of planned tests doesn't match the | ||
792 | * number of actually executed one. | ||
793 | * | ||
794 | * @param String message | ||
795 | */ | ||
796 | Tester.prototype.dubious = function dubious(planned, executed) { | ||
797 | "use strict"; | ||
798 | var message = f('%d tests planned, %d tests executed', planned, executed); | ||
799 | return this.assert(false, message, { | ||
800 | type: "dubious", | ||
801 | standard: message, | ||
802 | message: message, | ||
803 | values: { | ||
804 | planned: planned, | ||
805 | executed: executed | ||
806 | } | ||
807 | }); | ||
808 | }; | ||
809 | |||
810 | /** | ||
778 | * Writes an error-style formatted message to stdout. | 811 | * Writes an error-style formatted message to stdout. |
779 | * | 812 | * |
780 | * @param String message | 813 | * @param String message |
... | @@ -857,57 +890,6 @@ Tester.prototype.formatMessage = function formatMessage(message, style) { | ... | @@ -857,57 +890,6 @@ Tester.prototype.formatMessage = function formatMessage(message, style) { |
857 | }; | 890 | }; |
858 | 891 | ||
859 | /** | 892 | /** |
860 | * Retrieves current failure data and all failed cases. | ||
861 | * | ||
862 | * @return Object casedata An object containg information about cases | ||
863 | * @return Number casedata.length The number of failed cases | ||
864 | * @return Array casedata.cases An array of all the failed case objects | ||
865 | */ | ||
866 | Tester.prototype.getFailures = function getFailures() { | ||
867 | "use strict"; | ||
868 | return { | ||
869 | length: this.testResults.failed, | ||
870 | cases: this.testResults.failures | ||
871 | }; | ||
872 | }; | ||
873 | |||
874 | /** | ||
875 | * Retrieves current passed data and all passed cases. | ||
876 | * | ||
877 | * @return Object casedata An object containg information about cases | ||
878 | * @return Number casedata.length The number of passed cases | ||
879 | * @return Array casedata.cases An array of all the passed case objects | ||
880 | */ | ||
881 | Tester.prototype.getPasses = function getPasses() { | ||
882 | "use strict"; | ||
883 | return { | ||
884 | length: this.testResults.passed, | ||
885 | cases: this.testResults.passes | ||
886 | }; | ||
887 | }; | ||
888 | |||
889 | /** | ||
890 | * Retrieves the array where all the durations of failed tests are stored | ||
891 | * | ||
892 | * @return Array durations of failed tests | ||
893 | */ | ||
894 | Tester.prototype.getFailuresTime = function getFailuresTime() { | ||
895 | "use strict"; | ||
896 | return this.testResults.failuresTime; | ||
897 | } | ||
898 | |||
899 | /** | ||
900 | * Retrieves the array where all the durations of passed tests are stored | ||
901 | * | ||
902 | * @return Array durations of passed tests | ||
903 | */ | ||
904 | Tester.prototype.getPassesTime = function getPassesTime() { | ||
905 | "use strict"; | ||
906 | return this.testResults.passesTime; | ||
907 | } | ||
908 | |||
909 | |||
910 | /** | ||
911 | * Writes an info-style formatted message to stdout. | 893 | * Writes an info-style formatted message to stdout. |
912 | * | 894 | * |
913 | * @param String message | 895 | * @param String message |
... | @@ -918,7 +900,7 @@ Tester.prototype.info = function info(message) { | ... | @@ -918,7 +900,7 @@ Tester.prototype.info = function info(message) { |
918 | }; | 900 | }; |
919 | 901 | ||
920 | /** | 902 | /** |
921 | * Adds a successful test entry to the stack. | 903 | * Adds a succesful test entry to the stack. |
922 | * | 904 | * |
923 | * @param String message | 905 | * @param String message |
924 | */ | 906 | */ |
... | @@ -939,6 +921,12 @@ Tester.prototype.pass = function pass(message) { | ... | @@ -939,6 +921,12 @@ Tester.prototype.pass = function pass(message) { |
939 | */ | 921 | */ |
940 | Tester.prototype.processAssertionResult = function processAssertionResult(result) { | 922 | Tester.prototype.processAssertionResult = function processAssertionResult(result) { |
941 | "use strict"; | 923 | "use strict"; |
924 | if (!this.currentSuite) { | ||
925 | this.currentSuite = new TestSuiteResult({ | ||
926 | name: "Untitled suite in " + this.currentTestFile, | ||
927 | file: this.currentTestFile | ||
928 | }); | ||
929 | } | ||
942 | var eventName= 'success', | 930 | var eventName= 'success', |
943 | message = result.message || result.standard, | 931 | message = result.message || result.standard, |
944 | style = 'INFO', | 932 | style = 'INFO', |
... | @@ -947,9 +935,6 @@ Tester.prototype.processAssertionResult = function processAssertionResult(result | ... | @@ -947,9 +935,6 @@ Tester.prototype.processAssertionResult = function processAssertionResult(result |
947 | eventName = 'fail'; | 935 | eventName = 'fail'; |
948 | style = 'RED_BAR'; | 936 | style = 'RED_BAR'; |
949 | status = this.options.failText; | 937 | status = this.options.failText; |
950 | this.testResults.failed++; | ||
951 | } else { | ||
952 | this.testResults.passed++; | ||
953 | } | 938 | } |
954 | this.casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' ')); | 939 | this.casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' ')); |
955 | this.emit(eventName, result); | 940 | this.emit(eventName, result); |
... | @@ -962,21 +947,22 @@ Tester.prototype.processAssertionResult = function processAssertionResult(result | ... | @@ -962,21 +947,22 @@ Tester.prototype.processAssertionResult = function processAssertionResult(result |
962 | /** | 947 | /** |
963 | * Renders a detailed report for each failed test. | 948 | * Renders a detailed report for each failed test. |
964 | * | 949 | * |
965 | * @param Array failures | ||
966 | */ | 950 | */ |
967 | Tester.prototype.renderFailureDetails = function renderFailureDetails(failures) { | 951 | Tester.prototype.renderFailureDetails = function renderFailureDetails() { |
968 | "use strict"; | 952 | "use strict"; |
953 | var failures = this.suites.getAllFailures(); | ||
969 | if (failures.length === 0) { | 954 | if (failures.length === 0) { |
970 | return; | 955 | return; |
971 | } | 956 | } |
972 | this.casper.echo(f("\nDetails for the %d failed test%s:\n", failures.length, failures.length > 1 ? "s" : ""), "PARAMETER"); | 957 | this.casper.echo(f("\nDetails for the %d failed test%s:\n", |
958 | failures.length, failures.length > 1 ? "s" : ""), "PARAMETER"); | ||
973 | failures.forEach(function _forEach(failure) { | 959 | failures.forEach(function _forEach(failure) { |
974 | var type, message, line; | 960 | this.casper.echo(f('In %s%s', failure.file, ~~failure.line ? ':' + ~~failure.line : '')); |
975 | type = failure.type || "unknown"; | 961 | if (failure.suite) { |
976 | line = ~~failure.line; | 962 | this.casper.echo(f(' %s', failure.suite), "PARAMETER"); |
977 | message = failure.message; | 963 | } |
978 | this.casper.echo(f('In %s:%s', failure.file, line)); | 964 | this.casper.echo(f(' %s: %s', failure.type || "unknown", |
979 | this.casper.echo(f(' %s: %s', type, message || failure.standard || "(no message was entered)"), "COMMENT"); | 965 | failure.message || failure.standard || "(no message was entered)"), "COMMENT"); |
980 | }); | 966 | }); |
981 | }; | 967 | }; |
982 | 968 | ||
... | @@ -989,14 +975,19 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) { | ... | @@ -989,14 +975,19 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) { |
989 | "use strict"; | 975 | "use strict"; |
990 | /*jshint maxstatements:20*/ | 976 | /*jshint maxstatements:20*/ |
991 | save = save || this.options.save; | 977 | save = save || this.options.save; |
992 | var total = this.testResults.passed + this.testResults.failed, statusText, style, result; | 978 | var failed = this.suites.countFailed(), |
993 | var exitStatus = ~~(status || (this.testResults.failed > 0 ? 1 : 0)); | 979 | passed = this.suites.countPassed(), |
980 | total = this.suites.countTotal(), | ||
981 | statusText, | ||
982 | style, | ||
983 | result, | ||
984 | exitStatus = ~~(status || (failed > 0 ? 1 : 0)); | ||
994 | if (total === 0) { | 985 | if (total === 0) { |
995 | statusText = this.options.failText; | 986 | statusText = this.options.failText; |
996 | style = 'RED_BAR'; | 987 | style = 'RED_BAR'; |
997 | result = f("%s Looks like you didn't run any test.", statusText); | 988 | result = f("%s Looks like you didn't run any test.", statusText); |
998 | } else { | 989 | } else { |
999 | if (this.testResults.failed > 0) { | 990 | if (failed > 0) { |
1000 | statusText = this.options.failText; | 991 | statusText = this.options.failText; |
1001 | style = 'RED_BAR'; | 992 | style = 'RED_BAR'; |
1002 | } else { | 993 | } else { |
... | @@ -1004,12 +995,12 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) { | ... | @@ -1004,12 +995,12 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) { |
1004 | style = 'GREEN_BAR'; | 995 | style = 'GREEN_BAR'; |
1005 | } | 996 | } |
1006 | result = f('%s %s tests executed in %ss, %d passed, %d failed.', | 997 | result = f('%s %s tests executed in %ss, %d passed, %d failed.', |
1007 | statusText, total, utils.ms2seconds(this.calculateSuiteDuration()), | 998 | statusText, total, utils.ms2seconds(this.suites.calculateDuration()), |
1008 | this.testResults.passed, this.testResults.failed); | 999 | passed, failed); |
1009 | } | 1000 | } |
1010 | this.casper.echo(result, style, this.options.pad); | 1001 | this.casper.echo(result, style, this.options.pad); |
1011 | if (this.testResults.failed > 0) { | 1002 | if (failed > 0) { |
1012 | this.renderFailureDetails(this.testResults.failures); | 1003 | this.renderFailureDetails(); |
1013 | } | 1004 | } |
1014 | if (save) { | 1005 | if (save) { |
1015 | this.saveResults(save); | 1006 | this.saveResults(save); |
... | @@ -1053,12 +1044,15 @@ Tester.prototype.runSuites = function runSuites() { | ... | @@ -1053,12 +1044,15 @@ Tester.prototype.runSuites = function runSuites() { |
1053 | }); | 1044 | }); |
1054 | 1045 | ||
1055 | if (testFiles.length === 0) { | 1046 | if (testFiles.length === 0) { |
1056 | this.bar(f("No test file found in %s, aborting.", Array.prototype.slice.call(arguments)), "RED_BAR"); | 1047 | this.bar(f("No test file found in %s, aborting.", |
1048 | Array.prototype.slice.call(arguments)), "RED_BAR"); | ||
1057 | this.casper.exit(1); | 1049 | this.casper.exit(1); |
1058 | } | 1050 | } |
1051 | |||
1059 | self.currentSuiteNum = 0; | 1052 | self.currentSuiteNum = 0; |
1060 | self.currentTestStartTime = new Date(); | 1053 | self.currentTestStartTime = new Date(); |
1061 | self.lastAssertTime = 0; | 1054 | self.lastAssertTime = 0; |
1055 | |||
1062 | var interval = setInterval(function _check(self) { | 1056 | var interval = setInterval(function _check(self) { |
1063 | if (self.running) { | 1057 | if (self.running) { |
1064 | return; | 1058 | return; |
... | @@ -1066,13 +1060,9 @@ Tester.prototype.runSuites = function runSuites() { | ... | @@ -1066,13 +1060,9 @@ Tester.prototype.runSuites = function runSuites() { |
1066 | if (self.currentSuiteNum === testFiles.length) { | 1060 | if (self.currentSuiteNum === testFiles.length) { |
1067 | self.emit('tests.complete'); | 1061 | self.emit('tests.complete'); |
1068 | clearInterval(interval); | 1062 | clearInterval(interval); |
1069 | self.exporter.setSuiteDuration(self.calculateSuiteDuration()); | ||
1070 | } else { | 1063 | } else { |
1071 | self.runTest(testFiles[self.currentSuiteNum]); | 1064 | self.runTest(testFiles[self.currentSuiteNum]); |
1072 | self.exporter.setSuiteDuration(self.calculateSuiteDuration()); | ||
1073 | self.currentSuiteNum++; | 1065 | self.currentSuiteNum++; |
1074 | self.passesTime = []; | ||
1075 | self.failuresTime = []; | ||
1076 | } | 1066 | } |
1077 | }, 100, this); | 1067 | }, 100, this); |
1078 | }; | 1068 | }; |
... | @@ -1092,16 +1082,14 @@ Tester.prototype.runTest = function runTest(testFile) { | ... | @@ -1092,16 +1082,14 @@ Tester.prototype.runTest = function runTest(testFile) { |
1092 | /** | 1082 | /** |
1093 | * Saves results to file. | 1083 | * Saves results to file. |
1094 | * | 1084 | * |
1095 | * @param String filename Target file path. | 1085 | * @param String filename Target file path. |
1096 | */ | 1086 | */ |
1097 | Tester.prototype.saveResults = function saveResults(filepath) { | 1087 | Tester.prototype.saveResults = function saveResults(filepath) { |
1098 | "use strict"; | 1088 | "use strict"; |
1099 | // FIXME: looks like phantomjs has a pb with fs.isWritable https://groups.google.com/forum/#!topic/casperjs/hcUdwgGZOrU | 1089 | var exporter = require('xunit').create(); |
1100 | // if (!fs.isWritable(filepath)) { | 1090 | exporter.setResults(this.suites); |
1101 | // throw new CasperError(f('Path %s is not writable.', filepath)); | ||
1102 | // } | ||
1103 | try { | 1091 | try { |
1104 | fs.write(filepath, this.exporter.getXML(), 'w'); | 1092 | fs.write(filepath, exporter.getXML(), 'w'); |
1105 | this.casper.echo(f('Result log stored in %s', filepath), 'INFO', 80); | 1093 | this.casper.echo(f('Result log stored in %s', filepath), 'INFO', 80); |
1106 | } catch (e) { | 1094 | } catch (e) { |
1107 | this.casper.echo(f('Unable to write results to %s: %s', filepath, e), 'ERROR', 80); | 1095 | this.casper.echo(f('Unable to write results to %s: %s', filepath, e), 'ERROR', 80); |
... | @@ -1127,17 +1115,184 @@ Tester.prototype.testEquals = Tester.prototype.testEqual = function testEquals(v | ... | @@ -1127,17 +1115,184 @@ Tester.prototype.testEquals = Tester.prototype.testEqual = function testEquals(v |
1127 | * @param Error|String error The error | 1115 | * @param Error|String error The error |
1128 | * @param String file Test file where the error occurred | 1116 | * @param String file Test file where the error occurred |
1129 | * @param Number line Line number (optional) | 1117 | * @param Number line Line number (optional) |
1118 | * @param Array backtrace Error stack trace (optional) | ||
1130 | */ | 1119 | */ |
1131 | Tester.prototype.uncaughtError = function uncaughtError(error, file, line) { | 1120 | Tester.prototype.uncaughtError = function uncaughtError(error, file, line, backtrace) { |
1132 | "use strict"; | 1121 | "use strict"; |
1133 | return this.processAssertionResult({ | 1122 | return this.processAssertionResult({ |
1134 | success: false, | 1123 | success: false, |
1135 | type: "uncaughtError", | 1124 | type: "uncaughtError", |
1136 | file: file, | 1125 | file: file, |
1137 | line: ~~line || "unknown", | 1126 | line: ~~line, |
1138 | message: utils.isObject(error) ? error.message : error, | 1127 | message: utils.isObject(error) ? error.message : error, |
1139 | values: { | 1128 | values: { |
1140 | error: error | 1129 | error: error, |
1130 | stack: backtrace | ||
1141 | } | 1131 | } |
1142 | }); | 1132 | }); |
1143 | }; | 1133 | }; |
1134 | |||
1135 | /** | ||
1136 | * Test suites array. | ||
1137 | * | ||
1138 | */ | ||
1139 | function TestSuite() {} | ||
1140 | TestSuite.prototype = []; | ||
1141 | exports.TestSuite = TestSuite; | ||
1142 | |||
1143 | /** | ||
1144 | * Returns the number of tests. | ||
1145 | * | ||
1146 | * @return Number | ||
1147 | */ | ||
1148 | TestSuite.prototype.countTotal = function countTotal() { | ||
1149 | "use strict"; | ||
1150 | return this.countPassed() + this.countFailed(); | ||
1151 | }; | ||
1152 | |||
1153 | /** | ||
1154 | * Returns the number of failed tests. | ||
1155 | * | ||
1156 | * @return Number | ||
1157 | */ | ||
1158 | TestSuite.prototype.countFailed = function countFailed() { | ||
1159 | "use strict"; | ||
1160 | return this.map(function(result) { | ||
1161 | return result.failed; | ||
1162 | }).reduce(function(a, b) { | ||
1163 | return a + b; | ||
1164 | }); | ||
1165 | }; | ||
1166 | |||
1167 | /** | ||
1168 | * Returns the number of succesful tests. | ||
1169 | * | ||
1170 | * @return Number | ||
1171 | */ | ||
1172 | TestSuite.prototype.countPassed = function countPassed() { | ||
1173 | "use strict"; | ||
1174 | return this.map(function(result) { | ||
1175 | return result.passed; | ||
1176 | }).reduce(function(a, b) { | ||
1177 | return a + b; | ||
1178 | }); | ||
1179 | }; | ||
1180 | |||
1181 | /** | ||
1182 | * Returns all failures from this suite. | ||
1183 | * | ||
1184 | * @return Array | ||
1185 | */ | ||
1186 | TestSuite.prototype.getAllFailures = function getAllFailures() { | ||
1187 | "use strict"; | ||
1188 | var failures = []; | ||
1189 | this.forEach(function(result) { | ||
1190 | failures = failures.concat(result.failures); | ||
1191 | }); | ||
1192 | return failures; | ||
1193 | }; | ||
1194 | |||
1195 | /** | ||
1196 | * Returns all succesful tests from this suite. | ||
1197 | * | ||
1198 | * @return Array | ||
1199 | */ | ||
1200 | TestSuite.prototype.getAllPasses = function getAllPasses() { | ||
1201 | "use strict"; | ||
1202 | var passes = []; | ||
1203 | this.forEach(function(result) { | ||
1204 | passes = passes.concat(result.passes); | ||
1205 | }); | ||
1206 | return passes; | ||
1207 | }; | ||
1208 | |||
1209 | /** | ||
1210 | * Returns all results from this suite. | ||
1211 | * | ||
1212 | * @return Array | ||
1213 | */ | ||
1214 | TestSuite.prototype.getAllResults = function getAllResults() { | ||
1215 | "use strict"; | ||
1216 | return this.getAllPasses().concat(this.getAllFailures()); | ||
1217 | }; | ||
1218 | |||
1219 | /** | ||
1220 | * Computes the sum of all durations of the tests which were executed in the | ||
1221 | * current suite. | ||
1222 | * | ||
1223 | * @return Number | ||
1224 | */ | ||
1225 | TestSuite.prototype.calculateDuration = function calculateDuration() { | ||
1226 | "use strict"; | ||
1227 | return this.getAllResults().map(function(result) { | ||
1228 | return result.time; | ||
1229 | }).reduce(function add(a, b) { | ||
1230 | return a + b; | ||
1231 | }, 0); | ||
1232 | }; | ||
1233 | |||
1234 | /** | ||
1235 | * Test suite results object. | ||
1236 | * | ||
1237 | * @param Object options | ||
1238 | */ | ||
1239 | function TestSuiteResult(options) { | ||
1240 | "use strict"; | ||
1241 | this.name = options && options.name; | ||
1242 | this.file = options && options.file; | ||
1243 | this.assertions = 0; | ||
1244 | this.passed = 0; | ||
1245 | this.failed = 0; | ||
1246 | this.passes = []; | ||
1247 | this.failures = []; | ||
1248 | } | ||
1249 | exports.TestSuiteResult = TestSuiteResult; | ||
1250 | |||
1251 | /** | ||
1252 | * Adds a success record and its execution time to their associated stacks. | ||
1253 | * | ||
1254 | * @param Object success | ||
1255 | * @param Number time | ||
1256 | */ | ||
1257 | TestSuiteResult.prototype.addSuccess = function addSuccess(success, time) { | ||
1258 | "use strict"; | ||
1259 | success.suite = this.name; | ||
1260 | success.time = time; | ||
1261 | this.passes.push(success); | ||
1262 | this.assertions++; | ||
1263 | this.passed++; | ||
1264 | }; | ||
1265 | |||
1266 | /** | ||
1267 | * Adds a failure record and its execution time to their associated stacks. | ||
1268 | * | ||
1269 | * @param Object failure | ||
1270 | * @param Number time | ||
1271 | */ | ||
1272 | TestSuiteResult.prototype.addFailure = function addFailure(failure, time) { | ||
1273 | "use strict"; | ||
1274 | failure.suite = this.name; | ||
1275 | failure.time = time; | ||
1276 | this.failures.push(failure); | ||
1277 | this.assertions++; | ||
1278 | this.failed++; | ||
1279 | }; | ||
1280 | |||
1281 | /** | ||
1282 | * Computes total duration for this suite. | ||
1283 | * | ||
1284 | * @return Number | ||
1285 | */ | ||
1286 | TestSuiteResult.prototype.calculateDuration = function calculateDuration() { | ||
1287 | "use strict"; | ||
1288 | function add(a, b) { | ||
1289 | return a + b; | ||
1290 | } | ||
1291 | var passedTimes = this.passes.map(function(success) { | ||
1292 | return ~~success.time; | ||
1293 | }).reduce(add, 0); | ||
1294 | var failedTimes = this.failures.map(function(failure) { | ||
1295 | return ~~failure.time; | ||
1296 | }).reduce(add, 0); | ||
1297 | return passedTimes + failedTimes; | ||
1298 | }; | ... | ... |
... | @@ -200,6 +200,43 @@ function format(f) { | ... | @@ -200,6 +200,43 @@ function format(f) { |
200 | exports.format = format; | 200 | exports.format = format; |
201 | 201 | ||
202 | /** | 202 | /** |
203 | * Formats a test value. | ||
204 | * | ||
205 | * @param Mixed value | ||
206 | * @return String | ||
207 | */ | ||
208 | function formatTestValue(value, name) { | ||
209 | "use strict"; | ||
210 | var formatted = ''; | ||
211 | if (value instanceof Error) { | ||
212 | formatted += value.message + '\n'; | ||
213 | if (value.stack) { | ||
214 | formatted += indent(value.stack, 12, '#'); | ||
215 | } | ||
216 | } else if (name === 'stack') { | ||
217 | if (isArray(value)) { | ||
218 | formatted += value.map(function(entry) { | ||
219 | return format('in %s() in %s:%d', (entry.function || "anonymous"), entry.file, entry.line); | ||
220 | }).join('\n'); | ||
221 | } else { | ||
222 | formatted += 'not provided'; | ||
223 | } | ||
224 | } else { | ||
225 | try { | ||
226 | formatted += serialize(value); | ||
227 | } catch (e) { | ||
228 | try { | ||
229 | formatted += serialize(value.toString()); | ||
230 | } catch (e2) { | ||
231 | formatted += '(unserializable value)'; | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | return formatted; | ||
236 | } | ||
237 | exports.formatTestValue = formatTestValue; | ||
238 | |||
239 | /** | ||
203 | * Retrieves the value of an Object foreign property using a dot-separated | 240 | * Retrieves the value of an Object foreign property using a dot-separated |
204 | * path string. | 241 | * path string. |
205 | * | 242 | * |
... | @@ -226,6 +263,22 @@ function getPropertyPath(obj, path) { | ... | @@ -226,6 +263,22 @@ function getPropertyPath(obj, path) { |
226 | exports.getPropertyPath = getPropertyPath; | 263 | exports.getPropertyPath = getPropertyPath; |
227 | 264 | ||
228 | /** | 265 | /** |
266 | * Indents a string. | ||
267 | * | ||
268 | * @param String string | ||
269 | * @param Number nchars | ||
270 | * @param String prefix | ||
271 | * @return String | ||
272 | */ | ||
273 | function indent(string, nchars, prefix) { | ||
274 | "use strict"; | ||
275 | return string.split('\n').map(function(line) { | ||
276 | return (prefix || '') + new Array(nchars).join(' ') + line; | ||
277 | }).join('\n'); | ||
278 | } | ||
279 | exports.indent = indent; | ||
280 | |||
281 | /** | ||
229 | * Inherit the prototype methods from one constructor into another. | 282 | * Inherit the prototype methods from one constructor into another. |
230 | * | 283 | * |
231 | * @param {function} ctor Constructor function which needs to inherit the | 284 | * @param {function} ctor Constructor function which needs to inherit the |
... | @@ -295,7 +348,7 @@ exports.isClipRect = isClipRect; | ... | @@ -295,7 +348,7 @@ exports.isClipRect = isClipRect; |
295 | function isFalsy(subject) { | 348 | function isFalsy(subject) { |
296 | "use strict"; | 349 | "use strict"; |
297 | /*jshint eqeqeq:false*/ | 350 | /*jshint eqeqeq:false*/ |
298 | return subject == new Function('return false;')(); | 351 | return !subject; |
299 | } | 352 | } |
300 | exports.isFalsy = isFalsy; | 353 | exports.isFalsy = isFalsy; |
301 | /** | 354 | /** |
... | @@ -392,7 +445,7 @@ exports.isString = isString; | ... | @@ -392,7 +445,7 @@ exports.isString = isString; |
392 | function isTruthy(subject) { | 445 | function isTruthy(subject) { |
393 | "use strict"; | 446 | "use strict"; |
394 | /*jshint eqeqeq:false*/ | 447 | /*jshint eqeqeq:false*/ |
395 | return subject == new Function('return true;')(); | 448 | return !!subject; |
396 | } | 449 | } |
397 | exports.isTruthy = isTruthy; | 450 | exports.isTruthy = isTruthy; |
398 | 451 | ... | ... |
... | @@ -80,76 +80,75 @@ exports.create = function create() { | ... | @@ -80,76 +80,75 @@ exports.create = function create() { |
80 | */ | 80 | */ |
81 | function XUnitExporter() { | 81 | function XUnitExporter() { |
82 | "use strict"; | 82 | "use strict"; |
83 | this._xml = utils.node('testsuite'); | 83 | this.results = undefined; |
84 | this._xml = utils.node('testsuites'); | ||
84 | this._xml.toString = function toString() { | 85 | this._xml.toString = function toString() { |
85 | return this.outerHTML; // ouch | 86 | return '<?xml version="1.0" encoding="UTF-8"?>' + this.outerHTML; // ouch |
86 | }; | 87 | }; |
87 | } | 88 | } |
88 | exports.XUnitExporter = XUnitExporter; | 89 | exports.XUnitExporter = XUnitExporter; |
89 | 90 | ||
90 | /** | 91 | /** |
91 | * Adds a successful test result. | 92 | * Retrieves generated XML object - actually an HTMLElement. |
92 | * | ||
93 | * @param String classname | ||
94 | * @param String name | ||
95 | * @param Number duration Test duration in milliseconds | ||
96 | */ | ||
97 | XUnitExporter.prototype.addSuccess = function addSuccess(classname, name, duration) { | ||
98 | "use strict"; | ||
99 | var snode = utils.node('testcase', { | ||
100 | classname: generateClassName(classname), | ||
101 | name: name | ||
102 | }); | ||
103 | if (duration !== undefined) { | ||
104 | snode.setAttribute('time', utils.ms2seconds(duration)); | ||
105 | } | ||
106 | this._xml.appendChild(snode); | ||
107 | }; | ||
108 | |||
109 | /** | ||
110 | * Adds a failed test result. | ||
111 | * | 93 | * |
112 | * @param String classname | 94 | * @return HTMLElement |
113 | * @param String name | ||
114 | * @param String message | ||
115 | * @param String type | ||
116 | * @param Number duration Test duration in milliseconds | ||
117 | */ | 95 | */ |
118 | XUnitExporter.prototype.addFailure = function addFailure(classname, name, message, type, duration) { | 96 | XUnitExporter.prototype.getXML = function getXML() { |
119 | "use strict"; | 97 | "use strict"; |
120 | var fnode = utils.node('testcase', { | 98 | if (!(this.results instanceof require('tester').TestSuite)) { |
121 | classname: generateClassName(classname), | 99 | throw new CasperError('Results not set, cannot get XML.'); |
122 | name: name | ||
123 | }); | ||
124 | if (duration !== undefined) { | ||
125 | fnode.setAttribute('time', utils.ms2seconds(duration)); | ||
126 | } | 100 | } |
127 | var failure = utils.node('failure', { | 101 | this.results.forEach(function(result) { |
128 | type: type || "unknown" | 102 | var suiteNode = utils.node('testsuite', { |
129 | }); | 103 | name: result.name, |
130 | failure.appendChild(document.createTextNode(message || "no message left")); | 104 | tests: result.assertions, |
131 | fnode.appendChild(failure); | 105 | failures: result.failed, |
132 | this._xml.appendChild(fnode); | 106 | time: utils.ms2seconds(result.calculateDuration()), |
107 | 'package': generateClassName(result.file), | ||
108 | }); | ||
109 | result.passes.forEach(function(success) { | ||
110 | var testCase = utils.node('testcase', { | ||
111 | name: success.message || success.standard, | ||
112 | classname: generateClassName(success.file), | ||
113 | time: utils.ms2seconds(~~success.time) | ||
114 | }); | ||
115 | suiteNode.appendChild(testCase); | ||
116 | }); | ||
117 | result.failures.forEach(function(failure) { | ||
118 | var testCase = utils.node('testcase', { | ||
119 | name: failure.message || failure.standard, | ||
120 | classname: generateClassName(failure.file), | ||
121 | time: utils.ms2seconds(~~failure.time) | ||
122 | }); | ||
123 | var failureNode = utils.node('failure', { | ||
124 | type: failure.type || "failure" | ||
125 | }); | ||
126 | failureNode.appendChild(document.createTextNode(failure.message || "no message left")); | ||
127 | if (failure.values && failure.values.error instanceof Error) { | ||
128 | var errorNode = utils.node('error', { | ||
129 | type: utils.betterTypeOf(failure.values.error) | ||
130 | }); | ||
131 | errorNode.appendChild(document.createTextNode(failure.values.error.stack)); | ||
132 | testCase.appendChild(errorNode); | ||
133 | } | ||
134 | testCase.appendChild(failureNode); | ||
135 | suiteNode.appendChild(testCase); | ||
136 | }); | ||
137 | this._xml.appendChild(suiteNode); | ||
138 | }.bind(this)); | ||
139 | this._xml.setAttribute('duration', utils.ms2seconds(this.results.calculateDuration())); | ||
140 | return this._xml; | ||
133 | }; | 141 | }; |
134 | 142 | ||
135 | /** | 143 | /** |
136 | * Adds test suite duration | 144 | * Sets test results. |
137 | * | 145 | * |
138 | * @param Number duration Test duration in milliseconds | 146 | * @param TestSuite results |
139 | */ | 147 | */ |
140 | XUnitExporter.prototype.setSuiteDuration = function setSuiteDuration(duration) { | 148 | XUnitExporter.prototype.setResults = function setResults(results) { |
141 | "use strict"; | 149 | "use strict"; |
142 | if (!isNaN(duration)) { | 150 | if (!(results instanceof require('tester').TestSuite)) { |
143 | this._xml.setAttribute("time", utils.ms2seconds(duration)); | 151 | throw new CasperError('Invalid results type.'); |
144 | } | 152 | } |
145 | }; | 153 | return this.results = results; |
146 | |||
147 | /** | ||
148 | * Retrieves generated XML object - actually an HTMLElement. | ||
149 | * | ||
150 | * @return HTMLElement | ||
151 | */ | ||
152 | XUnitExporter.prototype.getXML = function getXML() { | ||
153 | "use strict"; | ||
154 | return this._xml; | ||
155 | }; | 154 | }; | ... | ... |
... | @@ -25,7 +25,17 @@ casper.withFrame('frame2', function() { | ... | @@ -25,7 +25,17 @@ casper.withFrame('frame2', function() { |
25 | this.test.assertTitle('CasperJS frame 3'); | 25 | this.test.assertTitle('CasperJS frame 3'); |
26 | }); | 26 | }); |
27 | 27 | ||
28 | casper.withFrame(0, function() { | ||
29 | this.test.assertTitle('CasperJS frame 1'); | ||
30 | this.test.assertExists("#f1"); | ||
31 | this.test.assertDoesntExist("#f2"); | ||
32 | }); | ||
33 | |||
34 | casper.withFrame(1, function() { | ||
35 | this.test.assertTitle('CasperJS frame 3'); | ||
36 | }); | ||
37 | |||
28 | casper.run(function() { | 38 | casper.run(function() { |
29 | this.test.assertTitle('CasperJS test frames'); | 39 | this.test.assertTitle('CasperJS test frames'); |
30 | this.test.done(10); | 40 | this.test.done(14); |
31 | }); | 41 | }); | ... | ... |
... | @@ -47,7 +47,7 @@ casper.thenOpen('tests/site/index.html', function() { | ... | @@ -47,7 +47,7 @@ casper.thenOpen('tests/site/index.html', function() { |
47 | t.assertTruthy('1', 'Tester.assertTruthy() works as expected'); | 47 | t.assertTruthy('1', 'Tester.assertTruthy() works as expected'); |
48 | 48 | ||
49 | t.comment('Tester.assertFalsy()'); | 49 | t.comment('Tester.assertFalsy()'); |
50 | t.assertFalsy('0', 'Tester.assertFalsy() works as expected'); | 50 | t.assertFalsy('', 'Tester.assertFalsy() works as expected'); |
51 | 51 | ||
52 | t.comment('Tester.assertNot()'); | 52 | t.comment('Tester.assertNot()'); |
53 | t.assertNot(false, 'Tester.assertNot() works as expected'); | 53 | t.assertNot(false, 'Tester.assertNot() works as expected'); |
... | @@ -200,27 +200,6 @@ casper.reload(function() { | ... | @@ -200,27 +200,6 @@ casper.reload(function() { |
200 | t.assertField('checklist[]', [], 'Tester.assertField() works as expected with check lists'); | 200 | t.assertField('checklist[]', [], 'Tester.assertField() works as expected with check lists'); |
201 | }); | 201 | }); |
202 | 202 | ||
203 | casper.then(function() { | ||
204 | t.comment('Tester.getFailures()'); | ||
205 | t.assertEquals(typeof t.getFailures().length, "number", "Tester.getFailures() works as expected"); | ||
206 | |||
207 | var passCount = t.getPasses().length; | ||
208 | t.comment('Tester.getPasses()'); | ||
209 | t.assertEquals(1, 1, "Rogue assertEquals pass case"); | ||
210 | t.assertEquals(t.getPasses().length, passCount + 1, "Tester.getPasses() works as expected"); | ||
211 | }); | ||
212 | |||
213 | casper.then(function() { | ||
214 | t.comment('Tester.calculateSuiteDuration()'); | ||
215 | function add(a, b) { | ||
216 | return a + b; | ||
217 | } | ||
218 | var passedTime = t.getPassesTime().reduce(add, 0), | ||
219 | failedTime = t.getFailuresTime().reduce(add, 0), | ||
220 | calculatedSum = t.calculateSuiteDuration(); | ||
221 | t.assertEquals(calculatedSum, passedTime + failedTime, "Tester.calculateSuiteDuration() works as expected") | ||
222 | }); | ||
223 | |||
224 | casper.run(function() { | 203 | casper.run(function() { |
225 | t.done(59); | 204 | t.done(55); |
226 | }); | 205 | }); | ... | ... |
... | @@ -4,8 +4,7 @@ var utils = require('utils'), | ... | @@ -4,8 +4,7 @@ var utils = require('utils'), |
4 | t = casper.test, | 4 | t = casper.test, |
5 | x = require('casper').selectXPath; | 5 | x = require('casper').selectXPath; |
6 | 6 | ||
7 | t.comment('betterTypeOf()'); | 7 | casper.test.begin('utils.betterTypeOf() tests', function(casper) { |
8 | (function() { | ||
9 | var testCases = [ | 8 | var testCases = [ |
10 | {subject: 1, expected: 'number'}, | 9 | {subject: 1, expected: 'number'}, |
11 | {subject: '1', expected: 'string'}, | 10 | {subject: '1', expected: 'string'}, |
... | @@ -19,13 +18,13 @@ t.comment('betterTypeOf()'); | ... | @@ -19,13 +18,13 @@ t.comment('betterTypeOf()'); |
19 | {subject: new RegExp(), expected: 'regexp'} | 18 | {subject: new RegExp(), expected: 'regexp'} |
20 | ]; | 19 | ]; |
21 | testCases.forEach(function(testCase) { | 20 | testCases.forEach(function(testCase) { |
22 | t.assertEquals(utils.betterTypeOf(testCase.subject), testCase.expected, | 21 | this.assertEquals(utils.betterTypeOf(testCase.subject), testCase.expected, |
23 | require('utils').format('betterTypeOf() detects expected type "%s"', testCase.subject)); | 22 | utils.format('betterTypeOf() detects expected type "%s"', testCase.expected)); |
24 | }); | 23 | }.bind(this)); |
25 | })(); | 24 | this.done(testCases.length); |
25 | }); | ||
26 | 26 | ||
27 | t.comment('cleanUrl()'); | 27 | casper.test.begin('utils.cleanUrl() tests', function(casper) { |
28 | (function() { | ||
29 | var testCases = { | 28 | var testCases = { |
30 | 'http://google.com/': 'http://google.com/', | 29 | 'http://google.com/': 'http://google.com/', |
31 | 'http://google.com': 'http://google.com/', | 30 | 'http://google.com': 'http://google.com/', |
... | @@ -39,47 +38,47 @@ t.comment('cleanUrl()'); | ... | @@ -39,47 +38,47 @@ t.comment('cleanUrl()'); |
39 | '/100': '/100' | 38 | '/100': '/100' |
40 | }; | 39 | }; |
41 | for (var testCase in testCases) { | 40 | for (var testCase in testCases) { |
42 | t.assertEquals(utils.cleanUrl(testCase), testCases[testCase], 'cleanUrl() cleans an URL'); | 41 | this.assertEquals(utils.cleanUrl(testCase), testCases[testCase], 'cleanUrl() cleans an URL'); |
43 | } | 42 | } |
44 | })(); | 43 | this.done(Object.keys(testCases).length); |
44 | }); | ||
45 | 45 | ||
46 | t.comment('clone()'); | 46 | casper.test.begin('utils.clone() tests', function(casper) { |
47 | (function() { | ||
48 | var a = {a: 1, b: 2, c: [1, 2]}; | 47 | var a = {a: 1, b: 2, c: [1, 2]}; |
49 | t.assertEquals(utils.clone(a), a); | 48 | this.assertEquals(utils.clone(a), a); |
50 | var b = [1, 2, 3, a]; | 49 | var b = [1, 2, 3, a]; |
51 | t.assertEquals(utils.clone(b), b); | 50 | this.assertEquals(utils.clone(b), b); |
52 | })(); | 51 | this.done(2); |
52 | }); | ||
53 | 53 | ||
54 | t.comment('equals()'); | 54 | casper.test.begin('equals() tests', function(casper) { |
55 | (function() { | 55 | this.assert(utils.equals(null, null), 'equals() null equality'); |
56 | t.assert(utils.equals(null, null), 'equals() null equality'); | 56 | this.assertNot(utils.equals(null, undefined), 'equals() null vs. undefined inequality'); |
57 | t.assertNot(utils.equals(null, undefined), 'equals() null vs. undefined inequality'); | 57 | this.assert(utils.equals("hi", "hi"), 'equals() string equality'); |
58 | t.assert(utils.equals("hi", "hi"), 'equals() string equality'); | 58 | this.assertNot(utils.equals("hi", "ih"), 'equals() string inequality'); |
59 | t.assertNot(utils.equals("hi", "ih"), 'equals() string inequality'); | 59 | this.assert(utils.equals(5, 5), 'equals() number equality'); |
60 | t.assert(utils.equals(5, 5), 'equals() number equality'); | 60 | this.assertNot(utils.equals("5", 5), 'equals() number equality without implicit cast'); |
61 | t.assertNot(utils.equals("5", 5), 'equals() number equality without implicit cast'); | 61 | this.assert(utils.equals(5, 5.0), 'equals() number equality with cast'); |
62 | t.assert(utils.equals(5, 5.0), 'equals() number equality with cast'); | 62 | this.assertNot(utils.equals(5, 10), 'equals() number inequality'); |
63 | t.assertNot(utils.equals(5, 10), 'equals() number inequality'); | 63 | this.assert(utils.equals([], []), 'equals() empty array equality'); |
64 | t.assert(utils.equals([], []), 'equals() empty array equality'); | 64 | this.assert(utils.equals([1,2], [1,2]), 'equals() array equality'); |
65 | t.assert(utils.equals([1,2], [1,2]), 'equals() array equality'); | 65 | this.assert(utils.equals([1,2,[1,2,function(){}]], [1,2,[1,2,function(){}]]), 'equals() complex array equality'); |
66 | t.assert(utils.equals([1,2,[1,2,function(){}]], [1,2,[1,2,function(){}]]), 'equals() complex array equality'); | 66 | this.assertNot(utils.equals([1,2,[1,2,function(a){}]], [1,2,[1,2,function(b){}]]), 'equals() complex array inequality'); |
67 | t.assertNot(utils.equals([1,2,[1,2,function(a){}]], [1,2,[1,2,function(b){}]]), 'equals() complex array inequality'); | 67 | this.assertNot(utils.equals([1,2], [2,1]), 'equals() shuffled array inequality'); |
68 | t.assertNot(utils.equals([1,2], [2,1]), 'equals() shuffled array inequality'); | 68 | this.assertNot(utils.equals([1,2], [1,2,3]), 'equals() array length inequality'); |
69 | t.assertNot(utils.equals([1,2], [1,2,3]), 'equals() array length inequality'); | 69 | this.assert(utils.equals({}, {}), 'equals() empty object equality'); |
70 | t.assert(utils.equals({}, {}), 'equals() empty object equality'); | 70 | this.assert(utils.equals({a:1,b:2}, {a:1,b:2}), 'equals() object length equality'); |
71 | t.assert(utils.equals({a:1,b:2}, {a:1,b:2}), 'equals() object length equality'); | 71 | this.assert(utils.equals({a:1,b:2}, {b:2,a:1}), 'equals() shuffled object keys equality'); |
72 | t.assert(utils.equals({a:1,b:2}, {b:2,a:1}), 'equals() shuffled object keys equality'); | 72 | this.assertNot(utils.equals({a:1,b:2}, {a:1,b:3}), 'equals() object inequality'); |
73 | t.assertNot(utils.equals({a:1,b:2}, {a:1,b:3}), 'equals() object inequality'); | 73 | this.assert(utils.equals({1:{name:"bob",age:28}, 2:{name:"john",age:26}}, {1:{name:"bob",age:28}, 2:{name:"john",age:26}}), 'equals() complex object equality'); |
74 | t.assert(utils.equals({1:{name:"bob",age:28}, 2:{name:"john",age:26}}, {1:{name:"bob",age:28}, 2:{name:"john",age:26}}), 'equals() complex object equality'); | 74 | this.assertNot(utils.equals({1:{name:"bob",age:28}, 2:{name:"john",age:26}}, {1:{name:"bob",age:28}, 2:{name:"john",age:27}}), 'equals() complex object inequality'); |
75 | t.assertNot(utils.equals({1:{name:"bob",age:28}, 2:{name:"john",age:26}}, {1:{name:"bob",age:28}, 2:{name:"john",age:27}}), 'equals() complex object inequality'); | 75 | this.assert(utils.equals(function(x){return x;}, function(x){return x;}), 'equals() function equality'); |
76 | t.assert(utils.equals(function(x){return x;}, function(x){return x;}), 'equals() function equality'); | 76 | this.assertNot(utils.equals(function(x){return x;}, function(y){return y+2;}), 'equals() function inequality'); |
77 | t.assertNot(utils.equals(function(x){return x;}, function(y){return y+2;}), 'equals() function inequality'); | 77 | this.assert(utils.equals([{a:1, b:2}, {c:3, d:4}], [{a:1, b:2}, {c:3, d:4}]), 'equals() arrays of objects'); |
78 | t.assert(utils.equals([{a:1, b:2}, {c:3, d:4}], [{a:1, b:2}, {c:3, d:4}]), 'equals() arrays of objects'); | 78 | this.done(23); |
79 | })(); | 79 | }); |
80 | 80 | ||
81 | t.comment('fileExt()'); | 81 | casper.test.begin('fileExt() tests', function() { |
82 | (function() { | ||
83 | var testCases = { | 82 | var testCases = { |
84 | 'foo.ext': 'ext', | 83 | 'foo.ext': 'ext', |
85 | 'FOO.EXT': 'ext', | 84 | 'FOO.EXT': 'ext', |
... | @@ -88,27 +87,25 @@ t.comment('fileExt()'); | ... | @@ -88,27 +87,25 @@ t.comment('fileExt()'); |
88 | 'toto.': '', | 87 | 'toto.': '', |
89 | ' plop.ext ': 'ext' | 88 | ' plop.ext ': 'ext' |
90 | }; | 89 | }; |
91 | |||
92 | for (var testCase in testCases) { | 90 | for (var testCase in testCases) { |
93 | t.assertEquals(utils.fileExt(testCase), testCases[testCase], 'fileExt() extract file extension'); | 91 | this.assertEquals(utils.fileExt(testCase), testCases[testCase], 'fileExt() extract file extension'); |
94 | } | 92 | } |
95 | })(); | 93 | this.done(Object.keys(testCases).length); |
94 | }); | ||
96 | 95 | ||
97 | t.comment('fillBlanks()'); | 96 | casper.test.begin('fillBlanks() tests', function() { |
98 | (function() { | ||
99 | var testCases = { | 97 | var testCases = { |
100 | 'foo': 'foo ', | 98 | 'foo': 'foo ', |
101 | ' foo bar ': ' foo bar ', | 99 | ' foo bar ': ' foo bar ', |
102 | ' foo bar ': ' foo bar ' | 100 | ' foo bar ': ' foo bar ' |
103 | }; | 101 | }; |
104 | |||
105 | for (var testCase in testCases) { | 102 | for (var testCase in testCases) { |
106 | t.assertEquals(utils.fillBlanks(testCase, 10), testCases[testCase], 'fillBlanks() fills blanks'); | 103 | this.assertEquals(utils.fillBlanks(testCase, 10), testCases[testCase], 'fillBlanks() fills blanks'); |
107 | } | 104 | } |
108 | })(); | 105 | this.done(Object.keys(testCases).length); |
106 | }); | ||
109 | 107 | ||
110 | t.comment('getPropertyPath()'); | 108 | casper.test.begin('getPropertyPath() tests', function() { |
111 | (function() { | ||
112 | var testCases = [ | 109 | var testCases = [ |
113 | { | 110 | { |
114 | input: utils.getPropertyPath({}, 'a.b.c'), | 111 | input: utils.getPropertyPath({}, 'a.b.c'), |
... | @@ -140,19 +137,19 @@ t.comment('getPropertyPath()'); | ... | @@ -140,19 +137,19 @@ t.comment('getPropertyPath()'); |
140 | } | 137 | } |
141 | ]; | 138 | ]; |
142 | testCases.forEach(function(testCase) { | 139 | testCases.forEach(function(testCase) { |
143 | t.assertEquals(testCase.input, testCase.output, 'getPropertyPath() gets a property using a path'); | 140 | this.assertEquals(testCase.input, testCase.output, 'getPropertyPath() gets a property using a path'); |
144 | }); | 141 | }.bind(this)); |
145 | })(); | 142 | this.done(testCases.length); |
143 | }); | ||
146 | 144 | ||
147 | t.comment('isArray()'); | 145 | casper.test.begin('isArray() tests', function() { |
148 | (function() { | 146 | this.assertEquals(utils.isArray([]), true, 'isArray() checks for an Array'); |
149 | t.assertEquals(utils.isArray([]), true, 'isArray() checks for an Array'); | 147 | this.assertEquals(utils.isArray({}), false, 'isArray() checks for an Array'); |
150 | t.assertEquals(utils.isArray({}), false, 'isArray() checks for an Array'); | 148 | this.assertEquals(utils.isArray("foo"), false, 'isArray() checks for an Array'); |
151 | t.assertEquals(utils.isArray("foo"), false, 'isArray() checks for an Array'); | 149 | this.done(3); |
152 | })(); | 150 | }); |
153 | 151 | ||
154 | t.comment('isClipRect()'); | 152 | casper.test.begin('isClipRect() tests', function() { |
155 | (function() { | ||
156 | var testCases = [ | 153 | var testCases = [ |
157 | [{}, false], | 154 | [{}, false], |
158 | [{top: 2}, false], | 155 | [{top: 2}, false], |
... | @@ -160,14 +157,13 @@ t.comment('isClipRect()'); | ... | @@ -160,14 +157,13 @@ t.comment('isClipRect()'); |
160 | [{top: 2, left: 2, height: 2, width: 2}, true], | 157 | [{top: 2, left: 2, height: 2, width: 2}, true], |
161 | [{top: 2, left: 2, width: 2, height: new Date()}, false] | 158 | [{top: 2, left: 2, width: 2, height: new Date()}, false] |
162 | ]; | 159 | ]; |
163 | |||
164 | testCases.forEach(function(testCase) { | 160 | testCases.forEach(function(testCase) { |
165 | t.assertEquals(utils.isClipRect(testCase[0]), testCase[1], 'isClipRect() checks for a ClipRect'); | 161 | this.assertEquals(utils.isClipRect(testCase[0]), testCase[1], 'isClipRect() checks for a ClipRect'); |
166 | }); | 162 | }.bind(this)); |
167 | })(); | 163 | this.done(testCases.length); |
164 | }); | ||
168 | 165 | ||
169 | t.comment('isHTTPResource()'); | 166 | casper.test.begin('isHTTPResource() tests', function() { |
170 | (function() { | ||
171 | var testCases = [ | 167 | var testCases = [ |
172 | [{}, false], | 168 | [{}, false], |
173 | [{url: 'file:///var/www/i.html'}, false], | 169 | [{url: 'file:///var/www/i.html'}, false], |
... | @@ -176,26 +172,25 @@ t.comment('isHTTPResource()'); | ... | @@ -176,26 +172,25 @@ t.comment('isHTTPResource()'); |
176 | [{url: 'HTTP://plop.com/'}, true], | 172 | [{url: 'HTTP://plop.com/'}, true], |
177 | [{url: 'https://plop.com/'}, true] | 173 | [{url: 'https://plop.com/'}, true] |
178 | ]; | 174 | ]; |
179 | |||
180 | testCases.forEach(function(testCase) { | 175 | testCases.forEach(function(testCase) { |
181 | t.assertEquals(utils.isHTTPResource(testCase[0]), testCase[1], 'isHTTPResource() checks for an HTTP resource'); | 176 | this.assertEquals(utils.isHTTPResource(testCase[0]), testCase[1], 'isHTTPResource() checks for an HTTP resource'); |
182 | }); | 177 | }.bind(this)); |
183 | })(); | 178 | this.done(Object.keys(testCases).length); |
179 | }); | ||
184 | 180 | ||
185 | t.comment('isObject()'); | 181 | casper.test.begin('isObject() tests', function() { |
186 | (function() { | 182 | this.assertEquals(utils.isObject({}), true, 'isObject() checks for an Object'); |
187 | t.assertEquals(utils.isObject({}), true, 'isObject() checks for an Object'); | 183 | this.assertEquals(utils.isObject([]), true, 'isObject() checks for an Object'); |
188 | t.assertEquals(utils.isObject([]), true, 'isObject() checks for an Object'); | 184 | this.assertEquals(utils.isObject(1), false, 'isObject() checks for an Object'); |
189 | t.assertEquals(utils.isObject(1), false, 'isObject() checks for an Object'); | 185 | this.assertEquals(utils.isObject("1"), false, 'isObject() checks for an Object'); |
190 | t.assertEquals(utils.isObject("1"), false, 'isObject() checks for an Object'); | 186 | this.assertEquals(utils.isObject(function(){}), false, 'isObject() checks for an Object'); |
191 | t.assertEquals(utils.isObject(function(){}), false, 'isObject() checks for an Object'); | 187 | this.assertEquals(utils.isObject(new Function('return {};')()), true, 'isObject() checks for an Object'); |
192 | t.assertEquals(utils.isObject(new Function('return {};')()), true, 'isObject() checks for an Object'); | 188 | this.assertEquals(utils.isObject(require('webpage').create()), true, 'isObject() checks for an Object'); |
193 | t.assertEquals(utils.isObject(require('webpage').create()), true, 'isObject() checks for an Object'); | 189 | this.assertEquals(utils.isObject(null), false, 'isObject() checks for an Object'); |
194 | t.assertEquals(utils.isObject(null), false, 'isObject() checks for an Object'); | 190 | this.done(8); |
195 | })(); | 191 | }); |
196 | 192 | ||
197 | t.comment('isValidSelector()'); | 193 | casper.test.begin('isValidSelector() tests', function() { |
198 | (function() { | ||
199 | t.assertEquals(utils.isValidSelector({}), false, 'isValidSelector() checks for a valid selector'); | 194 | t.assertEquals(utils.isValidSelector({}), false, 'isValidSelector() checks for a valid selector'); |
200 | t.assertEquals(utils.isValidSelector(""), false, 'isValidSelector() checks for a valid selector'); | 195 | t.assertEquals(utils.isValidSelector(""), false, 'isValidSelector() checks for a valid selector'); |
201 | t.assertEquals(utils.isValidSelector("a"), true, 'isValidSelector() checks for a valid selector'); | 196 | t.assertEquals(utils.isValidSelector("a"), true, 'isValidSelector() checks for a valid selector'); |
... | @@ -219,18 +214,18 @@ t.comment('isValidSelector()'); | ... | @@ -219,18 +214,18 @@ t.comment('isValidSelector()'); |
219 | type: "css3", | 214 | type: "css3", |
220 | path: "a" | 215 | path: "a" |
221 | }), false, 'isValidSelector() checks for a valid selector'); | 216 | }), false, 'isValidSelector() checks for a valid selector'); |
222 | })(); | 217 | this.done(10); |
218 | }); | ||
223 | 219 | ||
224 | t.comment('isWebPage()'); | 220 | casper.test.begin('isWebPage() tests', function() { |
225 | (function() { | ||
226 | var pageModule = require('webpage'); | 221 | var pageModule = require('webpage'); |
227 | t.assertEquals(utils.isWebPage(pageModule), false, 'isWebPage() checks for a WebPage instance'); | 222 | this.assertEquals(utils.isWebPage(pageModule), false, 'isWebPage() checks for a WebPage instance'); |
228 | t.assertEquals(utils.isWebPage(pageModule.create()), true, 'isWebPage() checks for a WebPage instance'); | 223 | this.assertEquals(utils.isWebPage(pageModule.create()), true, 'isWebPage() checks for a WebPage instance'); |
229 | t.assertEquals(utils.isWebPage(null), false, 'isWebPage() checks for a WebPage instance'); | 224 | this.assertEquals(utils.isWebPage(null), false, 'isWebPage() checks for a WebPage instance'); |
230 | })(); | 225 | this.done(3); |
226 | }); | ||
231 | 227 | ||
232 | t.comment('isJsFile()'); | 228 | casper.test.begin('isJsFile() tests', function() { |
233 | (function() { | ||
234 | var testCases = { | 229 | var testCases = { |
235 | '': false, | 230 | '': false, |
236 | 'toto.png': false, | 231 | 'toto.png': false, |
... | @@ -238,14 +233,13 @@ t.comment('isJsFile()'); | ... | @@ -238,14 +233,13 @@ t.comment('isJsFile()'); |
238 | 'gniii.coffee': true, | 233 | 'gniii.coffee': true, |
239 | 'script.js': true | 234 | 'script.js': true |
240 | }; | 235 | }; |
241 | |||
242 | for (var testCase in testCases) { | 236 | for (var testCase in testCases) { |
243 | t.assertEquals(utils.isJsFile(testCase), testCases[testCase], 'isJsFile() checks for js file'); | 237 | this.assertEquals(utils.isJsFile(testCase), testCases[testCase], 'isJsFile() checks for js file'); |
244 | } | 238 | } |
245 | })(); | 239 | this.done(Object.keys(testCases).length); |
240 | }); | ||
246 | 241 | ||
247 | t.comment('mergeObjects()'); | 242 | casper.test.begin('mergeObjects() tests', function() { |
248 | (function() { | ||
249 | var testCases = [ | 243 | var testCases = [ |
250 | { | 244 | { |
251 | obj1: {a: 1}, obj2: {b: 2}, merged: {a: 1, b: 2} | 245 | obj1: {a: 1}, obj2: {b: 2}, merged: {a: 1, b: 2} |
... | @@ -269,20 +263,18 @@ t.comment('mergeObjects()'); | ... | @@ -269,20 +263,18 @@ t.comment('mergeObjects()'); |
269 | } | 263 | } |
270 | } | 264 | } |
271 | ]; | 265 | ]; |
272 | |||
273 | testCases.forEach(function(testCase) { | 266 | testCases.forEach(function(testCase) { |
274 | t.assertEquals(utils.mergeObjects(testCase.obj1, testCase.obj2), testCase.merged, 'mergeObjects() can merge objects'); | 267 | this.assertEquals(utils.mergeObjects(testCase.obj1, testCase.obj2), testCase.merged, 'mergeObjects() can merge objects'); |
275 | }); | 268 | }.bind(this)); |
276 | })(); | 269 | this.done(testCases.length); |
270 | }); | ||
277 | 271 | ||
278 | t.comment('objectValues()'); | 272 | casper.test.begin('objectValues() tests', function() { |
279 | (function() { | 273 | this.assertEquals(utils.objectValues({}), [], 'objectValues() can extract object values'); |
280 | t.assertEquals(utils.objectValues({}), [], 'objectValues() can extract object values'); | 274 | this.assertEquals(utils.objectValues({a: 1, b: 2}), [1, 2], 'objectValues() can extract object values'); |
281 | t.assertEquals(utils.objectValues({a: 1, b: 2}), [1, 2], 'objectValues() can extract object values'); | 275 | }); |
282 | })(); | ||
283 | 276 | ||
284 | t.comment('unique()'); | 277 | casper.test.begin('unique() tests', function() { |
285 | (function() { | ||
286 | var testCases = [ | 278 | var testCases = [ |
287 | { | 279 | { |
288 | input: [1,2,3], | 280 | input: [1,2,3], |
... | @@ -302,8 +294,7 @@ t.comment('unique()'); | ... | @@ -302,8 +294,7 @@ t.comment('unique()'); |
302 | } | 294 | } |
303 | ]; | 295 | ]; |
304 | testCases.forEach(function(testCase) { | 296 | testCases.forEach(function(testCase) { |
305 | t.assertEquals(utils.unique(testCase.input), testCase.output, 'unique() computes unique values of an array'); | 297 | this.assertEquals(utils.unique(testCase.input), testCase.output, 'unique() computes unique values of an array'); |
306 | }); | 298 | }.bind(this)); |
307 | })(); | 299 | this.done(testCases.length); |
308 | 300 | }); | |
309 | t.done(112); | ... | ... |
1 | /*global casper*/ | 1 | /*global casper*/ |
2 | /*jshint strict:false*/ | 2 | /*jshint strict:false*/ |
3 | casper.test.comment('phantom.Casper.XUnitExporter'); | 3 | var tester = require('tester'); |
4 | var testpage = require('webpage').create(); | ||
4 | 5 | ||
5 | var xunit = require('xunit').create(); | 6 | casper.test.begin('XUnitReporter() initialization', function suite() { |
6 | xunit.addSuccess('foo', 'bar'); | 7 | var xunit = require('xunit').create(); |
7 | casper.test.assertMatch(xunit.getXML(), | 8 | var results = new tester.TestSuite(); |
8 | /<testcase classname="foo" name="bar"/, | 9 | xunit.setResults(results); |
9 | 'XUnitExporter.addSuccess() adds a successful testcase'); | 10 | this.assertTruthy(xunit.getXML()); |
10 | xunit.addFailure('bar', 'baz', 'wrong', 'chucknorriz'); | 11 | this.done(1); |
11 | casper.test.assertMatch(xunit.getXML(), | 12 | }); |
12 | /<testcase classname="bar" name="baz"><failure type="chucknorriz">wrong/, | ||
13 | 'XUnitExporter.addFailure() adds a failed testcase'); | ||
14 | 13 | ||
15 | // named classname | 14 | casper.test.begin('XUnitReporter() can hold test suites', function suite() { |
16 | xunit = require('xunit').create(); | 15 | var xunit = require('xunit').create(); |
17 | xunit.addSuccess(require('fs').workingDirectory + '/plop.js', 'It worked'); | 16 | var results = new tester.TestSuite(); |
18 | casper.test.assertMatch(xunit.getXML(), | 17 | var suite1 = new tester.TestSuiteResult({ |
19 | /<testcase classname="(.*)plop" name="It worked"/, | 18 | name: 'foo', |
20 | 'XUnitExporter.addSuccess() handles class name'); | 19 | file: '/foo' |
21 | xunit.addSuccess(require('fs').workingDirectory + '/plip.js', 'Failure'); | 20 | }); |
22 | casper.test.assertMatch(xunit.getXML(), | 21 | results.push(suite1); |
23 | /<testcase classname="(.*)plip" name="Failure"/, | 22 | var suite2 = new tester.TestSuiteResult({ |
24 | 'XUnitExporter.addFailure() handles class name'); | 23 | name: 'bar', |
24 | file: '/bar' | ||
25 | }); | ||
26 | results.push(suite2); | ||
27 | xunit.setResults(results); | ||
28 | casper.start().setContent(xunit.getXML()); | ||
29 | this.assertEvalEquals(function() { | ||
30 | return __utils__.findAll('testsuite').length; | ||
31 | }, 2); | ||
32 | this.assertExists('testsuites[duration]'); | ||
33 | this.assertExists('testsuite[name="foo"][package="foo"]'); | ||
34 | this.assertExists('testsuite[name="bar"][package="bar"]'); | ||
35 | this.done(4); | ||
36 | }); | ||
25 | 37 | ||
26 | // named with time | 38 | casper.test.begin('XUnitReporter() can hold a suite with a succesful test', function suite() { |
27 | xunit = require('xunit').create(); | 39 | var xunit = require('xunit').create(); |
28 | xunit.addSuccess('foo', 'It worked', 1024); | 40 | var results = new tester.TestSuite(); |
29 | casper.test.assertMatch(xunit.getXML(), | 41 | var suite1 = new tester.TestSuiteResult({ |
30 | /<testcase classname="foo" name="It worked" time="(.*)"/, | 42 | name: 'foo', |
31 | 'XUnitExporter.addSuccess() writes duration of test'); | 43 | file: '/foo' |
32 | xunit.addFailure('bar', 'baz', 'wrong', 'chucknorriz', 1024); | 44 | }); |
33 | casper.test.assertMatch(xunit.getXML(), | 45 | suite1.addSuccess({ |
34 | /<testcase classname="bar" name="baz" time="(.*)"><failure type="chucknorriz">wrong/, | 46 | success: true, |
35 | 'XUnitExporter.addFailure() adds a failed testcase with duration'); | 47 | type: "footype", |
48 | message: "footext", | ||
49 | file: "/foo" | ||
50 | }); | ||
51 | results.push(suite1); | ||
52 | xunit.setResults(results); | ||
53 | casper.start().setContent(xunit.getXML()); | ||
54 | this.assertExists('testsuite[name="foo"][package="foo"][tests="1"][failures="0"] testcase[name="footext"]'); | ||
55 | casper.test.done(1); | ||
56 | }); | ||
36 | 57 | ||
37 | // named with time | 58 | casper.test.begin('XUnitReporter() can handle a failed test', function suite() { |
38 | xunit = require('xunit').create(); | 59 | var xunit = require('xunit').create(); |
39 | casper.test.assertMatch(xunit.getXML(), | 60 | var results = new tester.TestSuite(); |
40 | /<testsuite>/, | 61 | var suite1 = new tester.TestSuiteResult({ |
41 | 'XUnitExporter.create() created <testsuite> without time'); | 62 | name: 'foo', |
42 | xunit.setSuiteDuration(1024); | 63 | file: '/foo' |
43 | casper.test.assertMatch(xunit.getXML(), | 64 | }); |
44 | /<testsuite time="1.024">/, | 65 | suite1.addFailure({ |
45 | 'XUnitExporter.setSuiteDuration() sets time in seconds'); | 66 | success: false, |
67 | type: "footype", | ||
68 | message: "footext", | ||
69 | file: "/foo" | ||
70 | }); | ||
71 | results.push(suite1); | ||
72 | xunit.setResults(results); | ||
73 | casper.start().setContent(xunit.getXML()); | ||
74 | this.assertExists('testsuite[name="foo"][package="foo"][tests="1"][failures="1"] testcase[name="footext"] failure[type="footype"]'); | ||
75 | casper.test.done(1); | ||
76 | }); | ||
46 | 77 | ||
47 | casper.test.done(8); | ... | ... |
-
Please register or sign in to post a comment