-
Notifications
You must be signed in to change notification settings - Fork 2
/
XunitReporter.coffee
168 lines (125 loc) · 3.69 KB
/
XunitReporter.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
{MochaRunner} = require("meteor/practicalmeteor:mocha")
{ConsoleReporter} = require("meteor/practicalmeteor:mocha-console-runner")
class XUnitReporter extends ConsoleReporter
@VERSION: "0.1.0"
xUnitPrefix: "##_meteor_magic##xunit: "
constructor:(@clientRunner, @serverRunner, @options)->
@clientTests = []
@serverTests = []
# ConsoleReporter exposes global variables that indicates when the tests has finished,
# so we register the event to print the test suite before ConsoleReporter register its event
MochaRunner.on "end all", => @printTestSuite()
super(@clientRunner, @serverRunner, @options)
###
Overwrite from ConsoleReporter
###
registerRunnerEvents:(where)->
super(where)
@[where + "Runner"].on 'pending', (test) =>
@[where+"Tests"].push test
@[where + "Runner"].on 'pass', (test) =>
@[where+"Tests"].push test
@[where + "Runner"].on 'fail', (test) =>
@[where+"Tests"].push test
printTestSuite: ->
testSuite = {
name: 'Mocha Tests'
tests: @stats.total
failures: @stats.failures
errors: @stats.failures
timestamp: (new Date).toUTCString()
time: @stats.duration/ 1000 or 0
skipped: @stats.pending
}
@write @createTag('testsuite', testSuite, false)
@clientTests.forEach (test) =>
@printTestCase test, "Client"
@serverTests.forEach (test) =>
@printTestCase test, "Server"
@write '</testsuite>'
###*
# HTML tag helper.
#
# @param name
# @param attrs
# @param close
# @param content
# @return {string}
###
createTag: (name, attrs = {}, close, content) ->
end = if close then '/>' else '>'
pairs = []
tag = undefined
for key of attrs
if Object.prototype.hasOwnProperty.call(attrs, key)
pairs.push key + '="' + @escape(attrs[key]) + '"'
tag = '<' + name + (if pairs.length then ' ' + pairs.join(' ') else '') + end
if content
tag += content + '</' + name + end
return tag
###*
# Return cdata escaped CDATA `str`.
###
cdata: (str) ->
'<![CDATA[' + @escape(str) + ']]>'
###*
# Override done to close the stream (if it's a file).
#
# @param failures
# @param {Function} fn
###
done:(failures, fn) ->
fn failures
###*
# Write out the given line.
#
# @param {string} line
###
write:(line) ->
console.log @xUnitPrefix + line
###*
# Output tag for the given `test.`
#
# @param {Test} test
###
printTestCase:(test, where) ->
attrs =
classname: "#{where} #{test.parent.fullTitle()}"
name: test.title
time: test.duration / 1000 or 0
if test.state == 'failed'
err = test.err
stack = @escapeStack(err.stack)
@write @createTag('testcase', attrs, false, @createTag('failure', {}, false, @cdata(@escape(err.message) + '\n' + stack)))
else if test.pending
@write @createTag('testcase', attrs, false, @createTag('skipped', {}, true))
else
@write @createTag('testcase', attrs, true)
return
###*
# Escape special characters in the given string of html.
#
# @api private
# @param {string} html
# @return {string}
###
escape: (html) ->
String(html)
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/</g, '<')
.replace />/g, '>'
###*
# For each line add the @xUnitPrefix and escape special characters in the given string of html.
#
# @api private
# @param {string} stack
# @return {string}
###
escapeStack: (stack = "")->
return stack.split("\n")
.map( (s) => @xUnitPrefix + @escape(s))
.join("\n")
module.exports.XUnitReporter = XUnitReporter
module.exports.runTests = ->
MochaRunner.setReporter(XUnitReporter)