Merged branch '1.1-dev'
Showing
8 changed files
with
663 additions
and
430 deletions
... | @@ -10,26 +10,26 @@ oncletom | ... | @@ -10,26 +10,26 @@ oncletom |
10 | hannyu | 10 | hannyu |
11 | Chris Lorenzo | 11 | Chris Lorenzo |
12 | Victor Yap | 12 | Victor Yap |
13 | Rob Barreca | ||
14 | Tyler Ritchie | ||
13 | nrabinowitz | 15 | nrabinowitz |
14 | pborreli | 16 | pborreli |
15 | Rob Barreca | 17 | Dave Lee |
16 | Andrew Childs | 18 | Andrew Childs |
17 | Solomon White | 19 | Solomon White |
18 | reina.sweet | 20 | reina.sweet |
19 | Dave Lee | ||
20 | Reina Sweet | 21 | Reina Sweet |
22 | Jan Schaumann | ||
21 | Elmar Langholz | 23 | Elmar Langholz |
22 | Jason Funk | 24 | Clochix |
23 | Donovan Hutchinson | 25 | Donovan Hutchinson |
24 | Julien Moulin | 26 | Julien Moulin |
25 | Michael Geers | 27 | Michael Geers |
26 | Jan Schaumann | 28 | Jason Funk |
27 | Clochix | 29 | Vladimir Chizhov |
28 | Raphaël Benitte | ||
29 | Tim Bunce | ||
30 | alfetopito | ||
31 | jean-philippe serafin | 30 | jean-philippe serafin |
32 | snkashis | 31 | snkashis |
32 | Rafael | ||
33 | Andrew de Andrade | 33 | Andrew de Andrade |
34 | Ben Lowery | 34 | Ben Lowery |
35 | Chris Winters | 35 | Chris Winters |
... | @@ -48,6 +48,8 @@ Mathieu Agopian | ... | @@ -48,6 +48,8 @@ Mathieu Agopian |
48 | Mehdi Kabab | 48 | Mehdi Kabab |
49 | Mikko Peltonen | 49 | Mikko Peltonen |
50 | Pascal Borreli | 50 | Pascal Borreli |
51 | Rafael | ||
52 | Rafael Garcia | 51 | Rafael Garcia |
52 | Raphaël Benitte | ||
53 | Tim Bunce | ||
54 | alfetopito | ||
53 | ``` | 55 | ``` | ... | ... |
... | @@ -1370,6 +1370,19 @@ Casper.prototype.sendKeys = function(selector, keys, options) { | ... | @@ -1370,6 +1370,19 @@ Casper.prototype.sendKeys = function(selector, keys, options) { |
1370 | }; | 1370 | }; |
1371 | 1371 | ||
1372 | /** | 1372 | /** |
1373 | * Sets current page content. | ||
1374 | * | ||
1375 | * @param String content Desired page content | ||
1376 | * @return Casper | ||
1377 | */ | ||
1378 | Casper.prototype.setContent = function setContent(content) { | ||
1379 | "use strict"; | ||
1380 | this.checkStarted(); | ||
1381 | this.page.content = content; | ||
1382 | return this; | ||
1383 | }; | ||
1384 | |||
1385 | /** | ||
1373 | * Sets current WebPage instance the credentials for HTTP authentication. | 1386 | * Sets current WebPage instance the credentials for HTTP authentication. |
1374 | * | 1387 | * |
1375 | * @param String username | 1388 | * @param String username | ... | ... |
... | @@ -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); |
... | @@ -63,81 +70,51 @@ var Tester = function Tester(casper, options) { | ... | @@ -63,81 +70,51 @@ var Tester = function Tester(casper, options) { |
63 | this.aborted = false; | 70 | this.aborted = false; |
64 | this.executed = 0; | 71 | this.executed = 0; |
65 | this.currentTestFile = null; | 72 | this.currentTestFile = null; |
73 | this.currentTestStartTime = null; | ||
74 | this.currentSuite = undefined; | ||
66 | this.currentSuiteNum = 0; | 75 | this.currentSuiteNum = 0; |
67 | this.exporter = require('xunit').create(); | 76 | this.lastAssertTime = 0; |
68 | this.loadIncludes = { | 77 | this.loadIncludes = { |
69 | includes: [], | 78 | includes: [], |
70 | pre: [], | 79 | pre: [], |
71 | post: [] | 80 | post: [] |
72 | }; | 81 | }; |
82 | this.queue = []; | ||
73 | this.running = false; | 83 | this.running = false; |
74 | this.suites = []; | 84 | this.started = false; |
85 | this.suites = new TestSuite(); | ||
75 | this.options = utils.mergeObjects({ | 86 | this.options = utils.mergeObjects({ |
76 | failFast: false, // terminates a suite as soon as a test fails? | 87 | failFast: false, // terminates a suite as soon as a test fails? |
77 | failText: "FAIL", // text to use for a successful test | 88 | failText: "FAIL", // text to use for a succesful test |
78 | passText: "PASS", // text to use for a failed test | 89 | passText: "PASS", // text to use for a failed test |
79 | pad: 80 , // maximum number of chars for a result line | 90 | pad: 80 , // maximum number of chars for a result line |
80 | warnText: "WARN" // text to use for a dubious test | 91 | warnText: "WARN" // text to use for a dubious test |
81 | }, options); | 92 | }, options); |
82 | 93 | ||
83 | // properties | ||
84 | this.testResults = { | ||
85 | passed: 0, | ||
86 | failed: 0, | ||
87 | passes: [], | ||
88 | failures: [], | ||
89 | passesTime: [], | ||
90 | failuresTime: [] | ||
91 | }; | ||
92 | |||
93 | // measuring test duration | ||
94 | this.currentTestStartTime = null; | ||
95 | this.lastAssertTime = 0; | ||
96 | |||
97 | this.configure(); | 94 | this.configure(); |
98 | 95 | ||
99 | this.on('success', function onSuccess(success) { | 96 | this.on('success', function onSuccess(success) { |
100 | this.testResults.passes.push(success); | ||
101 | var timeElapsed = new Date() - this.currentTestStartTime; | 97 | var timeElapsed = new Date() - this.currentTestStartTime; |
102 | this.testResults.passesTime.push(timeElapsed - this.lastAssertTime); | 98 | this.currentSuite.addSuccess(success, timeElapsed - this.lastAssertTime); |
103 | this.exporter.addSuccess(fs.absolute(success.file), success.message || success.standard, timeElapsed - this.lastAssertTime); | ||
104 | this.lastAssertTime = timeElapsed; | 99 | this.lastAssertTime = timeElapsed; |
105 | }); | 100 | }); |
106 | 101 | ||
107 | this.on('fail', function onFail(failure) { | 102 | this.on('fail', function onFail(failure) { |
108 | // export | 103 | // export |
109 | var timeElapsed = new Date() - this.currentTestStartTime; | 104 | var valueKeys = Object.keys(failure.values), |
110 | this.testResults.failuresTime.push(timeElapsed - this.lastAssertTime); | 105 | timeElapsed = new Date() - this.currentTestStartTime; |
111 | this.exporter.addFailure( | 106 | this.currentSuite.addFailure(failure, timeElapsed - this.lastAssertTime); |
112 | fs.absolute(failure.file), | ||
113 | failure.message || failure.standard, | ||
114 | failure.standard || "test failed", | ||
115 | failure.type || "unknown", | ||
116 | (timeElapsed - this.lastAssertTime) | ||
117 | ); | ||
118 | this.lastAssertTime = timeElapsed; | 107 | this.lastAssertTime = timeElapsed; |
119 | this.testResults.failures.push(failure); | ||
120 | |||
121 | // special printing | 108 | // special printing |
122 | if (failure.type) { | 109 | if (failure.type) { |
123 | this.comment(' type: ' + failure.type); | 110 | this.comment(' type: ' + failure.type); |
124 | } | 111 | } |
125 | if (failure.values && Object.keys(failure.values).length > 0) { | 112 | if (!failure.values || valueKeys.length === 0) { |
126 | for (var name in failure.values) { | 113 | return; |
127 | var comment = ' ' + name + ': '; | ||
128 | var value = failure.values[name]; | ||
129 | try { | ||
130 | comment += utils.serialize(failure.values[name]); | ||
131 | } catch (e) { | ||
132 | try { | ||
133 | comment += utils.serialize(failure.values[name].toString()); | ||
134 | } catch (e2) { | ||
135 | comment += '(unserializable value)'; | ||
136 | } | ||
137 | } | ||
138 | this.comment(comment); | ||
139 | } | ||
140 | } | 114 | } |
115 | valueKeys.forEach(function(name) { | ||
116 | this.comment(f(' %s: %s', name, utils.formatTestValue(failure.values[name], name))); | ||
117 | }.bind(this)); | ||
141 | }); | 118 | }); |
142 | 119 | ||
143 | // casper events | 120 | // casper events |
... | @@ -156,7 +133,7 @@ var Tester = function Tester(casper, options) { | ... | @@ -156,7 +133,7 @@ var Tester = function Tester(casper, options) { |
156 | line = backtrace[0].line; | 133 | line = backtrace[0].line; |
157 | } catch (e) {} | 134 | } catch (e) {} |
158 | } | 135 | } |
159 | self.uncaughtError(msg, self.currentTestFile, line); | 136 | self.uncaughtError(msg, self.currentTestFile, line, backtrace); |
160 | self.done(); | 137 | self.done(); |
161 | }); | 138 | }); |
162 | 139 | ||
... | @@ -186,16 +163,17 @@ exports.Tester = Tester; | ... | @@ -186,16 +163,17 @@ exports.Tester = Tester; |
186 | * @param Object|null context Assertion context object (Optional) | 163 | * @param Object|null context Assertion context object (Optional) |
187 | * @return Object An assertion result object | 164 | * @return Object An assertion result object |
188 | */ | 165 | */ |
189 | Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, message, context) { | 166 | Tester.prototype.assert = |
167 | Tester.prototype.assertTrue = function assert(subject, message, context) { | ||
190 | "use strict"; | 168 | "use strict"; |
191 | this.executed++; | 169 | this.executed++; |
192 | return this.processAssertionResult(utils.mergeObjects({ | 170 | return this.processAssertionResult(utils.mergeObjects({ |
193 | success: subject === true, | 171 | success: subject === true, |
194 | type: "assert", | 172 | type: "assert", |
195 | standard: "Subject is strictly true", | 173 | standard: "Subject is strictly true", |
196 | message: message, | 174 | message: message, |
197 | file: this.currentTestFile, | 175 | file: this.currentTestFile, |
198 | values: { | 176 | values: { |
199 | subject: utils.getPropertyPath(context, 'values.subject') || subject | 177 | subject: utils.getPropertyPath(context, 'values.subject') || subject |
200 | } | 178 | } |
201 | }, context || {})); | 179 | }, context || {})); |
... | @@ -209,12 +187,13 @@ Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, | ... | @@ -209,12 +187,13 @@ Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, |
209 | * @param String message Test description (Optional) | 187 | * @param String message Test description (Optional) |
210 | * @return Object An assertion result object | 188 | * @return Object An assertion result object |
211 | */ | 189 | */ |
212 | Tester.prototype.assertEquals = Tester.prototype.assertEqual = function assertEquals(subject, expected, message) { | 190 | Tester.prototype.assertEquals = |
191 | Tester.prototype.assertEqual = function assertEquals(subject, expected, message) { | ||
213 | "use strict"; | 192 | "use strict"; |
214 | return this.assert(this.testEquals(subject, expected), message, { | 193 | return this.assert(utils.equals(subject, expected), message, { |
215 | type: "assertEquals", | 194 | type: "assertEquals", |
216 | standard: "Subject equals the expected value", | 195 | standard: "Subject equals the expected value", |
217 | values: { | 196 | values: { |
218 | subject: subject, | 197 | subject: subject, |
219 | expected: expected | 198 | expected: expected |
220 | } | 199 | } |
... | @@ -232,9 +211,9 @@ Tester.prototype.assertEquals = Tester.prototype.assertEqual = function assertEq | ... | @@ -232,9 +211,9 @@ Tester.prototype.assertEquals = Tester.prototype.assertEqual = function assertEq |
232 | Tester.prototype.assertNotEquals = function assertNotEquals(subject, shouldnt, message) { | 211 | Tester.prototype.assertNotEquals = function assertNotEquals(subject, shouldnt, message) { |
233 | "use strict"; | 212 | "use strict"; |
234 | return this.assert(!this.testEquals(subject, shouldnt), message, { | 213 | return this.assert(!this.testEquals(subject, shouldnt), message, { |
235 | type: "assertNotEquals", | 214 | type: "assertNotEquals", |
236 | standard: "Subject doesn't equal what it shouldn't be", | 215 | standard: "Subject doesn't equal what it shouldn't be", |
237 | values: { | 216 | values: { |
238 | subject: subject, | 217 | subject: subject, |
239 | shouldnt: shouldnt | 218 | shouldnt: shouldnt |
240 | } | 219 | } |
... | @@ -246,13 +225,15 @@ Tester.prototype.assertNotEquals = function assertNotEquals(subject, shouldnt, m | ... | @@ -246,13 +225,15 @@ Tester.prototype.assertNotEquals = function assertNotEquals(subject, shouldnt, m |
246 | * | 225 | * |
247 | * @param Function fn A function to be evaluated in remote DOM | 226 | * @param Function fn A function to be evaluated in remote DOM |
248 | * @param String message Test description | 227 | * @param String message Test description |
249 | * @param Object params Object/Array containing the parameters to inject into the function (optional) | 228 | * @param Object params Object/Array containing the parameters to inject into |
229 | * the function (optional) | ||
250 | * @return Object An assertion result object | 230 | * @return Object An assertion result object |
251 | */ | 231 | */ |
252 | Tester.prototype.assertEval = Tester.prototype.assertEvaluate = function assertEval(fn, message, params) { | 232 | Tester.prototype.assertEval = |
233 | Tester.prototype.assertEvaluate = function assertEval(fn, message, params) { | ||
253 | "use strict"; | 234 | "use strict"; |
254 | return this.assert(this.casper.evaluate(fn, params), message, { | 235 | return this.assert(this.casper.evaluate(fn, params), message, { |
255 | type: "assertEval", | 236 | type: "assertEval", |
256 | standard: "Evaluated function returns true", | 237 | standard: "Evaluated function returns true", |
257 | values: { | 238 | values: { |
258 | fn: fn, | 239 | fn: fn, |
... | @@ -268,16 +249,18 @@ Tester.prototype.assertEval = Tester.prototype.assertEvaluate = function assertE | ... | @@ -268,16 +249,18 @@ Tester.prototype.assertEval = Tester.prototype.assertEvaluate = function assertE |
268 | * @param Function fn The function to be evaluated in remote DOM | 249 | * @param Function fn The function to be evaluated in remote DOM |
269 | * @param Boolean expected The expected value | 250 | * @param Boolean expected The expected value |
270 | * @param String|null message Test description | 251 | * @param String|null message Test description |
271 | * @param Object|null params Object containing the parameters to inject into the function (optional) | 252 | * @param Object|null params Object containing the parameters to inject into the |
253 | * function (optional) | ||
272 | * @return Object An assertion result object | 254 | * @return Object An assertion result object |
273 | */ | 255 | */ |
274 | Tester.prototype.assertEvalEquals = Tester.prototype.assertEvalEqual = function assertEvalEquals(fn, expected, message, params) { | 256 | Tester.prototype.assertEvalEquals = |
257 | Tester.prototype.assertEvalEqual = function assertEvalEquals(fn, expected, message, params) { | ||
275 | "use strict"; | 258 | "use strict"; |
276 | var subject = this.casper.evaluate(fn, params); | 259 | var subject = this.casper.evaluate(fn, params); |
277 | return this.assert(this.testEquals(subject, expected), message, { | 260 | return this.assert(utils.equals(subject, expected), message, { |
278 | type: "assertEvalEquals", | 261 | type: "assertEvalEquals", |
279 | standard: "Evaluated function returns the expected value", | 262 | standard: "Evaluated function returns the expected value", |
280 | values: { | 263 | values: { |
281 | fn: fn, | 264 | fn: fn, |
282 | params: params, | 265 | params: params, |
283 | subject: subject, | 266 | subject: subject, |
... | @@ -299,13 +282,13 @@ Tester.prototype.assertField = function assertField(inputName, expected, messag | ... | @@ -299,13 +282,13 @@ Tester.prototype.assertField = function assertField(inputName, expected, messag |
299 | var actual = this.casper.evaluate(function(inputName) { | 282 | var actual = this.casper.evaluate(function(inputName) { |
300 | return __utils__.getFieldValue(inputName); | 283 | return __utils__.getFieldValue(inputName); |
301 | }, inputName); | 284 | }, inputName); |
302 | return this.assert(this.testEquals(actual, expected), message, { | 285 | return this.assert(utils.equals(actual, expected), message, { |
303 | type: 'assertField', | 286 | type: 'assertField', |
304 | standard: f('"%s" input field has the value "%s"', inputName, expected), | 287 | standard: f('"%s" input field has the value "%s"', inputName, expected), |
305 | values: { | 288 | values: { |
306 | inputName: inputName, | 289 | inputName: inputName, |
307 | actual: actual, | 290 | actual: actual, |
308 | expected: expected | 291 | expected: expected |
309 | } | 292 | } |
310 | }); | 293 | }); |
311 | }; | 294 | }; |
... | @@ -318,7 +301,10 @@ Tester.prototype.assertField = function assertField(inputName, expected, messag | ... | @@ -318,7 +301,10 @@ Tester.prototype.assertField = function assertField(inputName, expected, messag |
318 | * @param String message Test description | 301 | * @param String message Test description |
319 | * @return Object An assertion result object | 302 | * @return Object An assertion result object |
320 | */ | 303 | */ |
321 | Tester.prototype.assertExists = Tester.prototype.assertExist = Tester.prototype.assertSelectorExists = Tester.prototype.assertSelectorExist = function assertExists(selector, message) { | 304 | Tester.prototype.assertExists = |
305 | Tester.prototype.assertExist = | ||
306 | Tester.prototype.assertSelectorExists = | ||
307 | Tester.prototype.assertSelectorExist = function assertExists(selector, message) { | ||
322 | "use strict"; | 308 | "use strict"; |
323 | return this.assert(this.casper.exists(selector), message, { | 309 | return this.assert(this.casper.exists(selector), message, { |
324 | type: "assertExists", | 310 | type: "assertExists", |
... | @@ -337,7 +323,8 @@ Tester.prototype.assertExists = Tester.prototype.assertExist = Tester.prototype. | ... | @@ -337,7 +323,8 @@ Tester.prototype.assertExists = Tester.prototype.assertExist = Tester.prototype. |
337 | * @param String message Test description | 323 | * @param String message Test description |
338 | * @return Object An assertion result object | 324 | * @return Object An assertion result object |
339 | */ | 325 | */ |
340 | Tester.prototype.assertDoesntExist = Tester.prototype.assertNotExists = function assertDoesntExist(selector, message) { | 326 | Tester.prototype.assertDoesntExist = |
327 | Tester.prototype.assertNotExists = function assertDoesntExist(selector, message) { | ||
341 | "use strict"; | 328 | "use strict"; |
342 | return this.assert(!this.casper.exists(selector), message, { | 329 | return this.assert(!this.casper.exists(selector), message, { |
343 | type: "assertDoesntExist", | 330 | type: "assertDoesntExist", |
... | @@ -358,7 +345,7 @@ Tester.prototype.assertDoesntExist = Tester.prototype.assertNotExists = function | ... | @@ -358,7 +345,7 @@ Tester.prototype.assertDoesntExist = Tester.prototype.assertNotExists = function |
358 | Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) { | 345 | Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) { |
359 | "use strict"; | 346 | "use strict"; |
360 | var currentHTTPStatus = this.casper.currentHTTPStatus; | 347 | var currentHTTPStatus = this.casper.currentHTTPStatus; |
361 | return this.assert(this.testEquals(this.casper.currentHTTPStatus, status), message, { | 348 | return this.assert(utils.equals(this.casper.currentHTTPStatus, status), message, { |
362 | type: "assertHttpStatus", | 349 | type: "assertHttpStatus", |
363 | standard: f("HTTP status code is: %s", status), | 350 | standard: f("HTTP status code is: %s", status), |
364 | values: { | 351 | values: { |
... | @@ -376,7 +363,8 @@ Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) { | ... | @@ -376,7 +363,8 @@ Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) { |
376 | * @param String message Test description | 363 | * @param String message Test description |
377 | * @return Object An assertion result object | 364 | * @return Object An assertion result object |
378 | */ | 365 | */ |
379 | Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertMatch(subject, pattern, message) { | 366 | Tester.prototype.assertMatch = |
367 | Tester.prototype.assertMatches = function assertMatch(subject, pattern, message) { | ||
380 | "use strict"; | 368 | "use strict"; |
381 | if (utils.betterTypeOf(pattern) !== "regexp") { | 369 | if (utils.betterTypeOf(pattern) !== "regexp") { |
382 | throw new CasperError('Invalid regexp.'); | 370 | throw new CasperError('Invalid regexp.'); |
... | @@ -398,7 +386,8 @@ Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertM | ... | @@ -398,7 +386,8 @@ Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertM |
398 | * @param String message Test description | 386 | * @param String message Test description |
399 | * @return Object An assertion result object | 387 | * @return Object An assertion result object |
400 | */ | 388 | */ |
401 | Tester.prototype.assertNot = Tester.prototype.assertFalse = function assertNot(condition, message) { | 389 | Tester.prototype.assertNot = |
390 | Tester.prototype.assertFalse = function assertNot(condition, message) { | ||
402 | "use strict"; | 391 | "use strict"; |
403 | return this.assert(!condition, message, { | 392 | return this.assert(!condition, message, { |
404 | type: "assertNot", | 393 | type: "assertNot", |
... | @@ -416,7 +405,8 @@ Tester.prototype.assertNot = Tester.prototype.assertFalse = function assertNot(c | ... | @@ -416,7 +405,8 @@ Tester.prototype.assertNot = Tester.prototype.assertFalse = function assertNot(c |
416 | * @param String message Test description | 405 | * @param String message Test description |
417 | * @return Object An assertion result object | 406 | * @return Object An assertion result object |
418 | */ | 407 | */ |
419 | Tester.prototype.assertNotVisible = Tester.prototype.assertInvisible = function assertNotVisible(selector, message) { | 408 | Tester.prototype.assertNotVisible = |
409 | Tester.prototype.assertInvisible = function assertNotVisible(selector, message) { | ||
420 | "use strict"; | 410 | "use strict"; |
421 | return this.assert(!this.casper.visible(selector), message, { | 411 | return this.assert(!this.casper.visible(selector), message, { |
422 | type: "assertVisible", | 412 | type: "assertVisible", |
... | @@ -436,7 +426,9 @@ Tester.prototype.assertNotVisible = Tester.prototype.assertInvisible = function | ... | @@ -436,7 +426,9 @@ Tester.prototype.assertNotVisible = Tester.prototype.assertInvisible = function |
436 | * @param String message Test description | 426 | * @param String message Test description |
437 | * @return Object An assertion result object | 427 | * @return Object An assertion result object |
438 | */ | 428 | */ |
439 | Tester.prototype.assertRaises = Tester.prototype.assertRaise = Tester.prototype.assertThrows = function assertRaises(fn, args, message) { | 429 | Tester.prototype.assertRaises = |
430 | Tester.prototype.assertRaise = | ||
431 | Tester.prototype.assertThrows = function assertRaises(fn, args, message) { | ||
440 | "use strict"; | 432 | "use strict"; |
441 | var context = { | 433 | var context = { |
442 | type: "assertRaises", | 434 | type: "assertRaises", |
... | @@ -461,7 +453,8 @@ Tester.prototype.assertRaises = Tester.prototype.assertRaise = Tester.prototype. | ... | @@ -461,7 +453,8 @@ Tester.prototype.assertRaises = Tester.prototype.assertRaise = Tester.prototype. |
461 | * @param String message Test description | 453 | * @param String message Test description |
462 | * @return Object An assertion result object | 454 | * @return Object An assertion result object |
463 | */ | 455 | */ |
464 | Tester.prototype.assertResourceExists = Tester.prototype.assertResourceExist = function assertResourceExists(test, message) { | 456 | Tester.prototype.assertResourceExists = |
457 | Tester.prototype.assertResourceExist = function assertResourceExists(test, message) { | ||
465 | "use strict"; | 458 | "use strict"; |
466 | return this.assert(this.casper.resourceExists(test), message, { | 459 | return this.assert(this.casper.resourceExists(test), message, { |
467 | type: "assertResourceExists", | 460 | type: "assertResourceExists", |
... | @@ -479,7 +472,8 @@ Tester.prototype.assertResourceExists = Tester.prototype.assertResourceExist = f | ... | @@ -479,7 +472,8 @@ Tester.prototype.assertResourceExists = Tester.prototype.assertResourceExist = f |
479 | * @param String message Test description | 472 | * @param String message Test description |
480 | * @return Object An assertion result object | 473 | * @return Object An assertion result object |
481 | */ | 474 | */ |
482 | Tester.prototype.assertTextDoesntExist = Tester.prototype.assertTextDoesntExist = function assertTextDoesntExist(text, message) { | 475 | Tester.prototype.assertTextDoesntExist = |
476 | Tester.prototype.assertTextDoesntExist = function assertTextDoesntExist(text, message) { | ||
483 | "use strict"; | 477 | "use strict"; |
484 | var textFound = (this.casper.evaluate(function _evaluate() { | 478 | var textFound = (this.casper.evaluate(function _evaluate() { |
485 | return document.body.textContent || document.body.innerText; | 479 | return document.body.textContent || document.body.innerText; |
... | @@ -500,7 +494,8 @@ Tester.prototype.assertTextDoesntExist = Tester.prototype.assertTextDoesntExist | ... | @@ -500,7 +494,8 @@ Tester.prototype.assertTextDoesntExist = Tester.prototype.assertTextDoesntExist |
500 | * @param String message Test description | 494 | * @param String message Test description |
501 | * @return Object An assertion result object | 495 | * @return Object An assertion result object |
502 | */ | 496 | */ |
503 | Tester.prototype.assertTextExists = Tester.prototype.assertTextExist = function assertTextExists(text, message) { | 497 | Tester.prototype.assertTextExists = |
498 | Tester.prototype.assertTextExist = function assertTextExists(text, message) { | ||
504 | "use strict"; | 499 | "use strict"; |
505 | var textFound = (this.casper.evaluate(function _evaluate() { | 500 | var textFound = (this.casper.evaluate(function _evaluate() { |
506 | return document.body.textContent || document.body.innerText; | 501 | return document.body.textContent || document.body.innerText; |
... | @@ -525,9 +520,9 @@ Tester.prototype.assertTruthy = function assertTruthy(subject, message) { | ... | @@ -525,9 +520,9 @@ Tester.prototype.assertTruthy = function assertTruthy(subject, message) { |
525 | "use strict"; | 520 | "use strict"; |
526 | /*jshint eqeqeq:false*/ | 521 | /*jshint eqeqeq:false*/ |
527 | return this.assert(utils.isTruthy(subject), message, { | 522 | return this.assert(utils.isTruthy(subject), message, { |
528 | type: "assertTruthy", | 523 | type: "assertTruthy", |
529 | standard: "Subject is truthy", | 524 | standard: "Subject is truthy", |
530 | values: { | 525 | values: { |
531 | subject: subject | 526 | subject: subject |
532 | } | 527 | } |
533 | }); | 528 | }); |
... | @@ -544,9 +539,9 @@ Tester.prototype.assertFalsy = function assertFalsy(subject, message) { | ... | @@ -544,9 +539,9 @@ Tester.prototype.assertFalsy = function assertFalsy(subject, message) { |
544 | "use strict"; | 539 | "use strict"; |
545 | /*jshint eqeqeq:false*/ | 540 | /*jshint eqeqeq:false*/ |
546 | return this.assert(utils.isFalsy(subject), message, { | 541 | return this.assert(utils.isFalsy(subject), message, { |
547 | type: "assertFalsy", | 542 | type: "assertFalsy", |
548 | standard: "Subject is falsy", | 543 | standard: "Subject is falsy", |
549 | values: { | 544 | values: { |
550 | subject: subject | 545 | subject: subject |
551 | } | 546 | } |
552 | }); | 547 | }); |
... | @@ -560,7 +555,8 @@ Tester.prototype.assertFalsy = function assertFalsy(subject, message) { | ... | @@ -560,7 +555,8 @@ Tester.prototype.assertFalsy = function assertFalsy(subject, message) { |
560 | * @param String message Test description | 555 | * @param String message Test description |
561 | * @return Object An assertion result object | 556 | * @return Object An assertion result object |
562 | */ | 557 | */ |
563 | Tester.prototype.assertSelectorHasText = Tester.prototype.assertSelectorContains = function assertSelectorHasText(selector, text, message) { | 558 | Tester.prototype.assertSelectorHasText = |
559 | Tester.prototype.assertSelectorContains = function assertSelectorHasText(selector, text, message) { | ||
564 | "use strict"; | 560 | "use strict"; |
565 | var textFound = this.casper.fetchText(selector).indexOf(text) !== -1; | 561 | var textFound = this.casper.fetchText(selector).indexOf(text) !== -1; |
566 | return this.assert(textFound, message, { | 562 | return this.assert(textFound, message, { |
... | @@ -581,7 +577,8 @@ Tester.prototype.assertSelectorHasText = Tester.prototype.assertSelectorContains | ... | @@ -581,7 +577,8 @@ Tester.prototype.assertSelectorHasText = Tester.prototype.assertSelectorContains |
581 | * @param String message Test description | 577 | * @param String message Test description |
582 | * @return Object An assertion result object | 578 | * @return Object An assertion result object |
583 | */ | 579 | */ |
584 | Tester.prototype.assertSelectorDoesntHaveText = Tester.prototype.assertSelectorDoesntContain = function assertSelectorDoesntHaveText(selector, text, message) { | 580 | Tester.prototype.assertSelectorDoesntHaveText = |
581 | Tester.prototype.assertSelectorDoesntContain = function assertSelectorDoesntHaveText(selector, text, message) { | ||
585 | "use strict"; | 582 | "use strict"; |
586 | var textFound = this.casper.fetchText(selector).indexOf(text) === -1; | 583 | var textFound = this.casper.fetchText(selector).indexOf(text) === -1; |
587 | return this.assert(textFound, message, { | 584 | return this.assert(textFound, message, { |
... | @@ -604,7 +601,7 @@ Tester.prototype.assertSelectorDoesntHaveText = Tester.prototype.assertSelectorD | ... | @@ -604,7 +601,7 @@ Tester.prototype.assertSelectorDoesntHaveText = Tester.prototype.assertSelectorD |
604 | Tester.prototype.assertTitle = function assertTitle(expected, message) { | 601 | Tester.prototype.assertTitle = function assertTitle(expected, message) { |
605 | "use strict"; | 602 | "use strict"; |
606 | var currentTitle = this.casper.getTitle(); | 603 | var currentTitle = this.casper.getTitle(); |
607 | return this.assert(this.testEquals(currentTitle, expected), message, { | 604 | return this.assert(utils.equals(currentTitle, expected), message, { |
608 | type: "assertTitle", | 605 | type: "assertTitle", |
609 | standard: f('Page title is: "%s"', expected), | 606 | standard: f('Page title is: "%s"', expected), |
610 | values: { | 607 | values: { |
... | @@ -621,7 +618,8 @@ Tester.prototype.assertTitle = function assertTitle(expected, message) { | ... | @@ -621,7 +618,8 @@ Tester.prototype.assertTitle = function assertTitle(expected, message) { |
621 | * @param String message Test description | 618 | * @param String message Test description |
622 | * @return Object An assertion result object | 619 | * @return Object An assertion result object |
623 | */ | 620 | */ |
624 | Tester.prototype.assertTitleMatch = Tester.prototype.assertTitleMatches = function assertTitleMatch(pattern, message) { | 621 | Tester.prototype.assertTitleMatch = |
622 | Tester.prototype.assertTitleMatches = function assertTitleMatch(pattern, message) { | ||
625 | "use strict"; | 623 | "use strict"; |
626 | if (utils.betterTypeOf(pattern) !== "regexp") { | 624 | if (utils.betterTypeOf(pattern) !== "regexp") { |
627 | throw new CasperError('Invalid regexp.'); | 625 | throw new CasperError('Invalid regexp.'); |
... | @@ -648,7 +646,7 @@ Tester.prototype.assertTitleMatch = Tester.prototype.assertTitleMatches = functi | ... | @@ -648,7 +646,7 @@ Tester.prototype.assertTitleMatch = Tester.prototype.assertTitleMatches = functi |
648 | Tester.prototype.assertType = function assertType(subject, type, message) { | 646 | Tester.prototype.assertType = function assertType(subject, type, message) { |
649 | "use strict"; | 647 | "use strict"; |
650 | var actual = utils.betterTypeOf(subject); | 648 | var actual = utils.betterTypeOf(subject); |
651 | return this.assert(this.testEquals(actual, type), message, { | 649 | return this.assert(utils.equals(actual, type), message, { |
652 | type: "assertType", | 650 | type: "assertType", |
653 | standard: f('Subject type is: "%s"', type), | 651 | standard: f('Subject type is: "%s"', type), |
654 | values: { | 652 | values: { |
... | @@ -668,7 +666,8 @@ Tester.prototype.assertType = function assertType(subject, type, message) { | ... | @@ -668,7 +666,8 @@ Tester.prototype.assertType = function assertType(subject, type, message) { |
668 | * @param String message Test description | 666 | * @param String message Test description |
669 | * @return Object An assertion result object | 667 | * @return Object An assertion result object |
670 | */ | 668 | */ |
671 | Tester.prototype.assertUrlMatch = Tester.prototype.assertUrlMatches = function assertUrlMatch(pattern, message) { | 669 | Tester.prototype.assertUrlMatch = |
670 | Tester.prototype.assertUrlMatches = function assertUrlMatch(pattern, message) { | ||
672 | "use strict"; | 671 | "use strict"; |
673 | var currentUrl = this.casper.getCurrentUrl(), | 672 | var currentUrl = this.casper.getCurrentUrl(), |
674 | patternType = utils.betterTypeOf(pattern), | 673 | patternType = utils.betterTypeOf(pattern), |
... | @@ -718,16 +717,30 @@ Tester.prototype.bar = function bar(text, style) { | ... | @@ -718,16 +717,30 @@ Tester.prototype.bar = function bar(text, style) { |
718 | }; | 717 | }; |
719 | 718 | ||
720 | /** | 719 | /** |
721 | * Retrieves the sum of all durations of the tests which were | 720 | * Starts a suite. |
722 | * executed in the current suite | ||
723 | * | 721 | * |
724 | * @return Number duration of all tests executed until now (in the current suite) | 722 | * @param String description Test suite description |
723 | * @param Function suiteFn Suite function | ||
725 | */ | 724 | */ |
726 | Tester.prototype.calculateSuiteDuration = function calculateSuiteDuration() { | 725 | Tester.prototype.begin = function begin(description, suiteFn) { |
727 | "use strict"; | 726 | "use strict"; |
728 | return this.testResults.passesTime.concat(this.testResults.failuresTime).reduce(function add(a, b) { | 727 | if (this.started && this.running) { |
729 | return a + b; | 728 | return this.queue.push(arguments); |
730 | }, 0); | 729 | } |
730 | description = description || "Untitled suite in " + this.currentTestFile; | ||
731 | this.comment(description); | ||
732 | this.currentSuite = new TestSuiteResult({ | ||
733 | name: description, | ||
734 | file: this.currentTestFile | ||
735 | }); | ||
736 | this.executed = 0; | ||
737 | this.running = this.started = true; | ||
738 | try { | ||
739 | suiteFn.call(this, this, this.casper); | ||
740 | } catch (e) { | ||
741 | this.uncaughtError(e, this.currentTestFile, e.line); | ||
742 | this.done(); | ||
743 | } | ||
731 | }; | 744 | }; |
732 | 745 | ||
733 | /** | 746 | /** |
... | @@ -784,11 +797,39 @@ Tester.prototype.configure = function configure() { | ... | @@ -784,11 +797,39 @@ Tester.prototype.configure = function configure() { |
784 | Tester.prototype.done = function done(planned) { | 797 | Tester.prototype.done = function done(planned) { |
785 | "use strict"; | 798 | "use strict"; |
786 | if (planned > 0 && planned !== this.executed) { | 799 | if (planned > 0 && planned !== this.executed) { |
787 | this.fail(f('%s: %d tests planned, %d tests executed', | 800 | this.dubious(planned, this.executed); |
788 | this.currentTestFile, planned, this.executed)); | 801 | } |
802 | if (this.currentSuite) { | ||
803 | this.suites.push(this.currentSuite); | ||
804 | this.currentSuite = undefined; | ||
805 | this.executed = 0; | ||
789 | } | 806 | } |
790 | this.emit('test.done'); | 807 | this.emit('test.done'); |
791 | this.running = false; | 808 | this.running = this.started = false; |
809 | var nextTest = this.queue.shift(); | ||
810 | if (nextTest) { | ||
811 | this.begin.apply(this, nextTest); | ||
812 | } | ||
813 | }; | ||
814 | |||
815 | /** | ||
816 | * Marks a test as dubious, when the number of planned tests doesn't match the | ||
817 | * number of actually executed one. | ||
818 | * | ||
819 | * @param String message | ||
820 | */ | ||
821 | Tester.prototype.dubious = function dubious(planned, executed) { | ||
822 | "use strict"; | ||
823 | var message = f('%d tests planned, %d tests executed', planned, executed); | ||
824 | return this.assert(false, message, { | ||
825 | type: "dubious", | ||
826 | standard: message, | ||
827 | message: message, | ||
828 | values: { | ||
829 | planned: planned, | ||
830 | executed: executed | ||
831 | } | ||
832 | }); | ||
792 | }; | 833 | }; |
793 | 834 | ||
794 | /** | 835 | /** |
... | @@ -874,57 +915,6 @@ Tester.prototype.formatMessage = function formatMessage(message, style) { | ... | @@ -874,57 +915,6 @@ Tester.prototype.formatMessage = function formatMessage(message, style) { |
874 | }; | 915 | }; |
875 | 916 | ||
876 | /** | 917 | /** |
877 | * Retrieves current failure data and all failed cases. | ||
878 | * | ||
879 | * @return Object casedata An object containg information about cases | ||
880 | * @return Number casedata.length The number of failed cases | ||
881 | * @return Array casedata.cases An array of all the failed case objects | ||
882 | */ | ||
883 | Tester.prototype.getFailures = function getFailures() { | ||
884 | "use strict"; | ||
885 | return { | ||
886 | length: this.testResults.failed, | ||
887 | cases: this.testResults.failures | ||
888 | }; | ||
889 | }; | ||
890 | |||
891 | /** | ||
892 | * Retrieves current passed data and all passed cases. | ||
893 | * | ||
894 | * @return Object casedata An object containg information about cases | ||
895 | * @return Number casedata.length The number of passed cases | ||
896 | * @return Array casedata.cases An array of all the passed case objects | ||
897 | */ | ||
898 | Tester.prototype.getPasses = function getPasses() { | ||
899 | "use strict"; | ||
900 | return { | ||
901 | length: this.testResults.passed, | ||
902 | cases: this.testResults.passes | ||
903 | }; | ||
904 | }; | ||
905 | |||
906 | /** | ||
907 | * Retrieves the array where all the durations of failed tests are stored | ||
908 | * | ||
909 | * @return Array durations of failed tests | ||
910 | */ | ||
911 | Tester.prototype.getFailuresTime = function getFailuresTime() { | ||
912 | "use strict"; | ||
913 | return this.testResults.failuresTime; | ||
914 | } | ||
915 | |||
916 | /** | ||
917 | * Retrieves the array where all the durations of passed tests are stored | ||
918 | * | ||
919 | * @return Array durations of passed tests | ||
920 | */ | ||
921 | Tester.prototype.getPassesTime = function getPassesTime() { | ||
922 | "use strict"; | ||
923 | return this.testResults.passesTime; | ||
924 | } | ||
925 | |||
926 | |||
927 | /** | ||
928 | * Writes an info-style formatted message to stdout. | 918 | * Writes an info-style formatted message to stdout. |
929 | * | 919 | * |
930 | * @param String message | 920 | * @param String message |
... | @@ -935,7 +925,7 @@ Tester.prototype.info = function info(message) { | ... | @@ -935,7 +925,7 @@ Tester.prototype.info = function info(message) { |
935 | }; | 925 | }; |
936 | 926 | ||
937 | /** | 927 | /** |
938 | * Adds a successful test entry to the stack. | 928 | * Adds a succesful test entry to the stack. |
939 | * | 929 | * |
940 | * @param String message | 930 | * @param String message |
941 | */ | 931 | */ |
... | @@ -956,7 +946,13 @@ Tester.prototype.pass = function pass(message) { | ... | @@ -956,7 +946,13 @@ Tester.prototype.pass = function pass(message) { |
956 | */ | 946 | */ |
957 | Tester.prototype.processAssertionResult = function processAssertionResult(result) { | 947 | Tester.prototype.processAssertionResult = function processAssertionResult(result) { |
958 | "use strict"; | 948 | "use strict"; |
959 | var eventName= 'success', | 949 | if (!this.currentSuite) { |
950 | this.currentSuite = new TestSuiteResult({ | ||
951 | name: "Untitled suite in " + this.currentTestFile, | ||
952 | file: this.currentTestFile | ||
953 | }); | ||
954 | } | ||
955 | var eventName = 'success', | ||
960 | message = result.message || result.standard, | 956 | message = result.message || result.standard, |
961 | style = 'INFO', | 957 | style = 'INFO', |
962 | status = this.options.passText; | 958 | status = this.options.passText; |
... | @@ -964,10 +960,8 @@ Tester.prototype.processAssertionResult = function processAssertionResult(result | ... | @@ -964,10 +960,8 @@ Tester.prototype.processAssertionResult = function processAssertionResult(result |
964 | eventName = 'fail'; | 960 | eventName = 'fail'; |
965 | style = 'RED_BAR'; | 961 | style = 'RED_BAR'; |
966 | status = this.options.failText; | 962 | status = this.options.failText; |
967 | this.testResults.failed++; | ||
968 | } else { | ||
969 | this.testResults.passed++; | ||
970 | } | 963 | } |
964 | style = result.type === "dubious" ? "WARN_BAR" : style; | ||
971 | this.casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' ')); | 965 | this.casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' ')); |
972 | this.emit(eventName, result); | 966 | this.emit(eventName, result); |
973 | if (this.options.failFast && !result.success) { | 967 | if (this.options.failFast && !result.success) { |
... | @@ -979,21 +973,22 @@ Tester.prototype.processAssertionResult = function processAssertionResult(result | ... | @@ -979,21 +973,22 @@ Tester.prototype.processAssertionResult = function processAssertionResult(result |
979 | /** | 973 | /** |
980 | * Renders a detailed report for each failed test. | 974 | * Renders a detailed report for each failed test. |
981 | * | 975 | * |
982 | * @param Array failures | ||
983 | */ | 976 | */ |
984 | Tester.prototype.renderFailureDetails = function renderFailureDetails(failures) { | 977 | Tester.prototype.renderFailureDetails = function renderFailureDetails() { |
985 | "use strict"; | 978 | "use strict"; |
979 | var failures = this.suites.getAllFailures(); | ||
986 | if (failures.length === 0) { | 980 | if (failures.length === 0) { |
987 | return; | 981 | return; |
988 | } | 982 | } |
989 | this.casper.echo(f("\nDetails for the %d failed test%s:\n", failures.length, failures.length > 1 ? "s" : ""), "PARAMETER"); | 983 | this.casper.echo(f("\nDetails for the %d failed test%s:\n", |
984 | failures.length, failures.length > 1 ? "s" : ""), "PARAMETER"); | ||
990 | failures.forEach(function _forEach(failure) { | 985 | failures.forEach(function _forEach(failure) { |
991 | var type, message, line; | 986 | this.casper.echo(f('In %s%s', failure.file, ~~failure.line ? ':' + ~~failure.line : '')); |
992 | type = failure.type || "unknown"; | 987 | if (failure.suite) { |
993 | line = ~~failure.line; | 988 | this.casper.echo(f(' %s', failure.suite), "PARAMETER"); |
994 | message = failure.message; | 989 | } |
995 | this.casper.echo(f('In %s:%s', failure.file, line)); | 990 | this.casper.echo(f(' %s: %s', failure.type || "unknown", |
996 | this.casper.echo(f(' %s: %s', type, message || failure.standard || "(no message was entered)"), "COMMENT"); | 991 | failure.message || failure.standard || "(no message was entered)"), "COMMENT"); |
997 | }.bind(this)); | 992 | }.bind(this)); |
998 | }; | 993 | }; |
999 | 994 | ||
... | @@ -1006,14 +1001,19 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) { | ... | @@ -1006,14 +1001,19 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) { |
1006 | "use strict"; | 1001 | "use strict"; |
1007 | /*jshint maxstatements:20*/ | 1002 | /*jshint maxstatements:20*/ |
1008 | save = save || this.options.save; | 1003 | save = save || this.options.save; |
1009 | var total = this.testResults.passed + this.testResults.failed, statusText, style, result; | 1004 | var failed = this.suites.countFailed(), |
1010 | var exitStatus = ~~(status || (this.testResults.failed > 0 ? 1 : 0)); | 1005 | passed = this.suites.countPassed(), |
1006 | total = this.suites.countTotal(), | ||
1007 | statusText, | ||
1008 | style, | ||
1009 | result, | ||
1010 | exitStatus = ~~(status || (failed > 0 ? 1 : 0)); | ||
1011 | if (total === 0) { | 1011 | if (total === 0) { |
1012 | statusText = this.options.warnText; | 1012 | statusText = this.options.warnText; |
1013 | style = 'WARN_BAR'; | 1013 | style = 'WARN_BAR'; |
1014 | result = f("%s Looks like you didn't run any test.", statusText); | 1014 | result = f("%s Looks like you didn't run any test.", statusText); |
1015 | } else { | 1015 | } else { |
1016 | if (this.testResults.failed > 0) { | 1016 | if (failed > 0) { |
1017 | statusText = this.options.failText; | 1017 | statusText = this.options.failText; |
1018 | style = 'RED_BAR'; | 1018 | style = 'RED_BAR'; |
1019 | } else { | 1019 | } else { |
... | @@ -1021,12 +1021,12 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) { | ... | @@ -1021,12 +1021,12 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) { |
1021 | style = 'GREEN_BAR'; | 1021 | style = 'GREEN_BAR'; |
1022 | } | 1022 | } |
1023 | result = f('%s %s tests executed in %ss, %d passed, %d failed.', | 1023 | result = f('%s %s tests executed in %ss, %d passed, %d failed.', |
1024 | statusText, total, utils.ms2seconds(this.calculateSuiteDuration()), | 1024 | statusText, total, utils.ms2seconds(this.suites.calculateDuration()), |
1025 | this.testResults.passed, this.testResults.failed); | 1025 | passed, failed); |
1026 | } | 1026 | } |
1027 | this.casper.echo(result, style, this.options.pad); | 1027 | this.casper.echo(result, style, this.options.pad); |
1028 | if (this.testResults.failed > 0) { | 1028 | if (failed > 0) { |
1029 | this.renderFailureDetails(this.testResults.failures); | 1029 | this.renderFailureDetails(); |
1030 | } | 1030 | } |
1031 | if (save) { | 1031 | if (save) { |
1032 | this.saveResults(save); | 1032 | this.saveResults(save); |
... | @@ -1070,12 +1070,15 @@ Tester.prototype.runSuites = function runSuites() { | ... | @@ -1070,12 +1070,15 @@ Tester.prototype.runSuites = function runSuites() { |
1070 | }); | 1070 | }); |
1071 | 1071 | ||
1072 | if (testFiles.length === 0) { | 1072 | if (testFiles.length === 0) { |
1073 | this.bar(f("No test file found in %s, aborting.", Array.prototype.slice.call(arguments)), "RED_BAR"); | 1073 | this.bar(f("No test file found in %s, aborting.", |
1074 | Array.prototype.slice.call(arguments)), "RED_BAR"); | ||
1074 | this.casper.exit(1); | 1075 | this.casper.exit(1); |
1075 | } | 1076 | } |
1077 | |||
1076 | self.currentSuiteNum = 0; | 1078 | self.currentSuiteNum = 0; |
1077 | self.currentTestStartTime = new Date(); | 1079 | self.currentTestStartTime = new Date(); |
1078 | self.lastAssertTime = 0; | 1080 | self.lastAssertTime = 0; |
1081 | |||
1079 | var interval = setInterval(function _check(self) { | 1082 | var interval = setInterval(function _check(self) { |
1080 | if (self.running) { | 1083 | if (self.running) { |
1081 | return; | 1084 | return; |
... | @@ -1083,14 +1086,10 @@ Tester.prototype.runSuites = function runSuites() { | ... | @@ -1083,14 +1086,10 @@ Tester.prototype.runSuites = function runSuites() { |
1083 | if (self.currentSuiteNum === testFiles.length || self.aborted) { | 1086 | if (self.currentSuiteNum === testFiles.length || self.aborted) { |
1084 | self.emit('tests.complete'); | 1087 | self.emit('tests.complete'); |
1085 | clearInterval(interval); | 1088 | clearInterval(interval); |
1086 | self.exporter.setSuiteDuration(self.calculateSuiteDuration()); | ||
1087 | self.aborted = false; | 1089 | self.aborted = false; |
1088 | } else { | 1090 | } else { |
1089 | self.runTest(testFiles[self.currentSuiteNum]); | 1091 | self.runTest(testFiles[self.currentSuiteNum]); |
1090 | self.exporter.setSuiteDuration(self.calculateSuiteDuration()); | ||
1091 | self.currentSuiteNum++; | 1092 | self.currentSuiteNum++; |
1092 | self.passesTime = []; | ||
1093 | self.failuresTime = []; | ||
1094 | } | 1093 | } |
1095 | }, 100, this); | 1094 | }, 100, this); |
1096 | }; | 1095 | }; |
... | @@ -1110,16 +1109,14 @@ Tester.prototype.runTest = function runTest(testFile) { | ... | @@ -1110,16 +1109,14 @@ Tester.prototype.runTest = function runTest(testFile) { |
1110 | /** | 1109 | /** |
1111 | * Saves results to file. | 1110 | * Saves results to file. |
1112 | * | 1111 | * |
1113 | * @param String filename Target file path. | 1112 | * @param String filename Target file path. |
1114 | */ | 1113 | */ |
1115 | Tester.prototype.saveResults = function saveResults(filepath) { | 1114 | Tester.prototype.saveResults = function saveResults(filepath) { |
1116 | "use strict"; | 1115 | "use strict"; |
1117 | // FIXME: looks like phantomjs has a pb with fs.isWritable https://groups.google.com/forum/#!topic/casperjs/hcUdwgGZOrU | 1116 | var exporter = require('xunit').create(); |
1118 | // if (!fs.isWritable(filepath)) { | 1117 | exporter.setResults(this.suites); |
1119 | // throw new CasperError(f('Path %s is not writable.', filepath)); | ||
1120 | // } | ||
1121 | try { | 1118 | try { |
1122 | fs.write(filepath, this.exporter.getXML(), 'w'); | 1119 | fs.write(filepath, exporter.getXML(), 'w'); |
1123 | this.casper.echo(f('Result log stored in %s', filepath), 'INFO', 80); | 1120 | this.casper.echo(f('Result log stored in %s', filepath), 'INFO', 80); |
1124 | } catch (e) { | 1121 | } catch (e) { |
1125 | this.casper.echo(f('Unable to write results to %s: %s', filepath, e), 'ERROR', 80); | 1122 | this.casper.echo(f('Unable to write results to %s: %s', filepath, e), 'ERROR', 80); |
... | @@ -1145,17 +1142,185 @@ Tester.prototype.testEquals = Tester.prototype.testEqual = function testEquals(v | ... | @@ -1145,17 +1142,185 @@ Tester.prototype.testEquals = Tester.prototype.testEqual = function testEquals(v |
1145 | * @param Error|String error The error | 1142 | * @param Error|String error The error |
1146 | * @param String file Test file where the error occurred | 1143 | * @param String file Test file where the error occurred |
1147 | * @param Number line Line number (optional) | 1144 | * @param Number line Line number (optional) |
1145 | * @param Array backtrace Error stack trace (optional) | ||
1148 | */ | 1146 | */ |
1149 | Tester.prototype.uncaughtError = function uncaughtError(error, file, line) { | 1147 | Tester.prototype.uncaughtError = function uncaughtError(error, file, line, backtrace) { |
1150 | "use strict"; | 1148 | "use strict"; |
1149 | // XXX: this is NOT an assertion scratch that | ||
1151 | return this.processAssertionResult({ | 1150 | return this.processAssertionResult({ |
1152 | success: false, | 1151 | success: false, |
1153 | type: "uncaughtError", | 1152 | type: "uncaughtError", |
1154 | file: file, | 1153 | file: file, |
1155 | line: ~~line || "unknown", | 1154 | line: ~~line, |
1156 | message: utils.isObject(error) ? error.message : error, | 1155 | message: utils.isObject(error) ? error.message : error, |
1157 | values: { | 1156 | values: { |
1158 | error: error | 1157 | error: error, |
1158 | stack: backtrace | ||
1159 | } | 1159 | } |
1160 | }); | 1160 | }); |
1161 | }; | 1161 | }; |
1162 | |||
1163 | /** | ||
1164 | * Test suites array. | ||
1165 | * | ||
1166 | */ | ||
1167 | function TestSuite() {} | ||
1168 | TestSuite.prototype = []; | ||
1169 | exports.TestSuite = TestSuite; | ||
1170 | |||
1171 | /** | ||
1172 | * Returns the number of tests. | ||
1173 | * | ||
1174 | * @return Number | ||
1175 | */ | ||
1176 | TestSuite.prototype.countTotal = function countTotal() { | ||
1177 | "use strict"; | ||
1178 | return this.countPassed() + this.countFailed(); | ||
1179 | }; | ||
1180 | |||
1181 | /** | ||
1182 | * Returns the number of failed tests. | ||
1183 | * | ||
1184 | * @return Number | ||
1185 | */ | ||
1186 | TestSuite.prototype.countFailed = function countFailed() { | ||
1187 | "use strict"; | ||
1188 | return this.map(function(result) { | ||
1189 | return result.failed; | ||
1190 | }).reduce(function(a, b) { | ||
1191 | return a + b; | ||
1192 | }, 0); | ||
1193 | }; | ||
1194 | |||
1195 | /** | ||
1196 | * Returns the number of succesful tests. | ||
1197 | * | ||
1198 | * @return Number | ||
1199 | */ | ||
1200 | TestSuite.prototype.countPassed = function countPassed() { | ||
1201 | "use strict"; | ||
1202 | return this.map(function(result) { | ||
1203 | return result.passed; | ||
1204 | }).reduce(function(a, b) { | ||
1205 | return a + b; | ||
1206 | }, 0); | ||
1207 | }; | ||
1208 | |||
1209 | /** | ||
1210 | * Returns all failures from this suite. | ||
1211 | * | ||
1212 | * @return Array | ||
1213 | */ | ||
1214 | TestSuite.prototype.getAllFailures = function getAllFailures() { | ||
1215 | "use strict"; | ||
1216 | var failures = []; | ||
1217 | this.forEach(function(result) { | ||
1218 | failures = failures.concat(result.failures); | ||
1219 | }); | ||
1220 | return failures; | ||
1221 | }; | ||
1222 | |||
1223 | /** | ||
1224 | * Returns all succesful tests from this suite. | ||
1225 | * | ||
1226 | * @return Array | ||
1227 | */ | ||
1228 | TestSuite.prototype.getAllPasses = function getAllPasses() { | ||
1229 | "use strict"; | ||
1230 | var passes = []; | ||
1231 | this.forEach(function(result) { | ||
1232 | passes = passes.concat(result.passes); | ||
1233 | }); | ||
1234 | return passes; | ||
1235 | }; | ||
1236 | |||
1237 | /** | ||
1238 | * Returns all results from this suite. | ||
1239 | * | ||
1240 | * @return Array | ||
1241 | */ | ||
1242 | TestSuite.prototype.getAllResults = function getAllResults() { | ||
1243 | "use strict"; | ||
1244 | return this.getAllPasses().concat(this.getAllFailures()); | ||
1245 | }; | ||
1246 | |||
1247 | /** | ||
1248 | * Computes the sum of all durations of the tests which were executed in the | ||
1249 | * current suite. | ||
1250 | * | ||
1251 | * @return Number | ||
1252 | */ | ||
1253 | TestSuite.prototype.calculateDuration = function calculateDuration() { | ||
1254 | "use strict"; | ||
1255 | return this.getAllResults().map(function(result) { | ||
1256 | return result.time; | ||
1257 | }).reduce(function add(a, b) { | ||
1258 | return a + b; | ||
1259 | }, 0); | ||
1260 | }; | ||
1261 | |||
1262 | /** | ||
1263 | * Test suite results object. | ||
1264 | * | ||
1265 | * @param Object options | ||
1266 | */ | ||
1267 | function TestSuiteResult(options) { | ||
1268 | "use strict"; | ||
1269 | this.name = options && options.name; | ||
1270 | this.file = options && options.file; | ||
1271 | this.assertions = 0; | ||
1272 | this.passed = 0; | ||
1273 | this.failed = 0; | ||
1274 | this.passes = []; | ||
1275 | this.failures = []; | ||
1276 | } | ||
1277 | exports.TestSuiteResult = TestSuiteResult; | ||
1278 | |||
1279 | /** | ||
1280 | * Adds a success record and its execution time to their associated stacks. | ||
1281 | * | ||
1282 | * @param Object success | ||
1283 | * @param Number time | ||
1284 | */ | ||
1285 | TestSuiteResult.prototype.addSuccess = function addSuccess(success, time) { | ||
1286 | "use strict"; | ||
1287 | success.suite = this.name; | ||
1288 | success.time = time; | ||
1289 | this.passes.push(success); | ||
1290 | this.assertions++; | ||
1291 | this.passed++; | ||
1292 | }; | ||
1293 | |||
1294 | /** | ||
1295 | * Adds a failure record and its execution time to their associated stacks. | ||
1296 | * | ||
1297 | * @param Object failure | ||
1298 | * @param Number time | ||
1299 | */ | ||
1300 | TestSuiteResult.prototype.addFailure = function addFailure(failure, time) { | ||
1301 | "use strict"; | ||
1302 | failure.suite = this.name; | ||
1303 | failure.time = time; | ||
1304 | this.failures.push(failure); | ||
1305 | this.assertions++; | ||
1306 | this.failed++; | ||
1307 | }; | ||
1308 | |||
1309 | /** | ||
1310 | * Computes total duration for this suite. | ||
1311 | * | ||
1312 | * @return Number | ||
1313 | */ | ||
1314 | TestSuiteResult.prototype.calculateDuration = function calculateDuration() { | ||
1315 | "use strict"; | ||
1316 | function add(a, b) { | ||
1317 | return a + b; | ||
1318 | } | ||
1319 | var passedTimes = this.passes.map(function(success) { | ||
1320 | return ~~success.time; | ||
1321 | }).reduce(add, 0); | ||
1322 | var failedTimes = this.failures.map(function(failure) { | ||
1323 | return ~~failure.time; | ||
1324 | }).reduce(add, 0); | ||
1325 | return passedTimes + failedTimes; | ||
1326 | }; | ... | ... |
... | @@ -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 | ... | ... |
... | @@ -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 | }; | ... | ... |
... | @@ -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() { |
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() { |
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() { |
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() { |
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,19 @@ t.comment('mergeObjects()'); | ... | @@ -269,20 +263,19 @@ 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 | this.done(2); |
282 | })(); | 276 | }); |
283 | 277 | ||
284 | t.comment('unique()'); | 278 | casper.test.begin('unique() tests', function() { |
285 | (function() { | ||
286 | var testCases = [ | 279 | var testCases = [ |
287 | { | 280 | { |
288 | input: [1,2,3], | 281 | input: [1,2,3], |
... | @@ -302,8 +295,7 @@ t.comment('unique()'); | ... | @@ -302,8 +295,7 @@ t.comment('unique()'); |
302 | } | 295 | } |
303 | ]; | 296 | ]; |
304 | testCases.forEach(function(testCase) { | 297 | testCases.forEach(function(testCase) { |
305 | t.assertEquals(utils.unique(testCase.input), testCase.output, 'unique() computes unique values of an array'); | 298 | this.assertEquals(utils.unique(testCase.input), testCase.output, 'unique() computes unique values of an array'); |
306 | }); | 299 | }.bind(this)); |
307 | })(); | 300 | this.done(testCases.length); |
308 | 301 | }); | |
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, |
46 | 67 | type: "footype", | |
47 | casper.test.done(8); | 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 | this.assertEquals(casper.getElementInfo('failure[type="footype"]').text, 'footext'); | ||
76 | casper.test.done(2); | ||
77 | }); | ... | ... |
-
Please register or sign in to post a comment