Merged branch '1.1-dev'
Showing
8 changed files
with
203 additions
and
127 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 | ... | ... |
This diff is collapsed.
Click to expand it.
... | @@ -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 | }); | ... | ... |
This diff is collapsed.
Click to expand it.
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