1 | (function(global) {
|
2 | var UNDEFINED,
|
3 | exportObject;
|
4 |
|
5 | if (typeof module !== "undefined" && module.exports) {
|
6 | exportObject = exports;
|
7 | } else {
|
8 | exportObject = global.jasmineReporters = global.jasmineReporters || {};
|
9 | }
|
10 |
|
11 | function isFailed(obj) { return obj.status === "failed"; }
|
12 | function isSkipped(obj) { return obj.status === "pending"; }
|
13 | function isDisabled(obj) { return obj.status === "disabled"; }
|
14 | function pad(n) { return n < 10 ? "0"+n : n; }
|
15 | function padThree(n) { return n < 10 ? "00"+n : n < 100 ? "0"+n : n; }
|
16 | function extend(dupe, obj) {
|
17 | for (var prop in obj) {
|
18 | if (obj.hasOwnProperty(prop)) {
|
19 | dupe[prop] = obj[prop];
|
20 | }
|
21 | }
|
22 | return dupe;
|
23 | }
|
24 | function ISODateString(d) {
|
25 | return d.getUTCFullYear() + "-" +
|
26 | pad(d.getUTCMonth()+1) + "-" +
|
27 | pad(d.getUTCDate()) + "T" +
|
28 | pad(d.getUTCHours()) + ":" +
|
29 | pad(d.getUTCMinutes()) + ":" +
|
30 | pad(d.getUTCSeconds()) + "." +
|
31 |
|
32 | padThree(d.getUTCMilliseconds());
|
33 | }
|
34 | function log(str) {
|
35 | var con = global.console || console;
|
36 | if (con && con.log) {
|
37 | con.log(str);
|
38 | }
|
39 | }
|
40 |
|
41 |
|
42 | |
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 | exportObject.TeamCityReporter = function(options) {
|
50 | options = options || {};
|
51 | var self = this;
|
52 | self.started = false;
|
53 | self.finished = false;
|
54 |
|
55 | if(options.modifySuiteName && typeof options.modifySuiteName !== "function") {
|
56 | throw new Error('option "modifySuiteName" must be a function');
|
57 | }
|
58 |
|
59 | var delegates = {};
|
60 | delegates.modifySuiteName = options.modifySuiteName;
|
61 |
|
62 | var currentSuite = null,
|
63 |
|
64 | fakeFocusedSuite = {
|
65 | id: "focused",
|
66 | description: "focused specs",
|
67 | fullName: "focused specs"
|
68 | };
|
69 |
|
70 | var __suites = {}, __specs = {};
|
71 | function getSuite(suite) {
|
72 | __suites[suite.id] = extend(__suites[suite.id] || {}, suite);
|
73 | return __suites[suite.id];
|
74 | }
|
75 | function getSpec(spec) {
|
76 | __specs[spec.id] = extend(__specs[spec.id] || {}, spec);
|
77 | return __specs[spec.id];
|
78 | }
|
79 |
|
80 | self.jasmineStarted = function() {
|
81 | exportObject.startTime = new Date();
|
82 | self.started = true;
|
83 | tclog("progressStart 'Running Jasmine Tests'");
|
84 | };
|
85 | self.suiteStarted = function(suite) {
|
86 | suite = getSuite(suite);
|
87 | suite._parent = currentSuite;
|
88 | currentSuite = suite;
|
89 | tclog("testSuiteStarted", {
|
90 | name: suite.description
|
91 | });
|
92 | };
|
93 | self.specStarted = function(spec) {
|
94 | if (!currentSuite) {
|
95 |
|
96 | self.suiteStarted(fakeFocusedSuite);
|
97 | }
|
98 | spec = getSpec(spec);
|
99 | tclog("testStarted", {
|
100 | name: spec.description,
|
101 | captureStandardOutput: "true"
|
102 | });
|
103 | };
|
104 | self.specDone = function(spec) {
|
105 | spec = getSpec(spec);
|
106 | if (isSkipped(spec) || isDisabled(spec)) {
|
107 | tclog("testIgnored", {
|
108 | name: spec.description
|
109 | });
|
110 | }
|
111 |
|
112 |
|
113 | if (isFailed(spec) && spec.failedExpectations.length) {
|
114 | var failure = spec.failedExpectations[0];
|
115 | tclog("testFailed", {
|
116 | name: spec.description,
|
117 | message: failure.message,
|
118 | details: failure.stack
|
119 | });
|
120 | }
|
121 | tclog("testFinished", {
|
122 | name: spec.description
|
123 | });
|
124 | };
|
125 | self.suiteDone = function(suite) {
|
126 | suite = getSuite(suite);
|
127 | if (suite._parent === UNDEFINED) {
|
128 |
|
129 | self.suiteStarted(suite);
|
130 | }
|
131 | tclog("testSuiteFinished", {
|
132 | name: suite.description
|
133 | });
|
134 | currentSuite = suite._parent;
|
135 | };
|
136 | self.jasmineDone = function() {
|
137 | if (currentSuite) {
|
138 |
|
139 | self.suiteDone(fakeFocusedSuite);
|
140 | }
|
141 | tclog("progressFinish 'Running Jasmine Tests'");
|
142 |
|
143 | self.finished = true;
|
144 |
|
145 | exportObject.endTime = new Date();
|
146 | };
|
147 |
|
148 |
|
149 |
|
150 | function tclog(message, attrs) {
|
151 | var str = "##teamcity[" + message;
|
152 | if (typeof(attrs) === "object") {
|
153 | if (!("timestamp" in attrs)) {
|
154 | attrs.timestamp = new Date();
|
155 | }
|
156 | for (var prop in attrs) {
|
157 | if (attrs.hasOwnProperty(prop)) {
|
158 | if(delegates.modifySuiteName && message.indexOf("testSuite") === 0 && prop === "name") {
|
159 | attrs[prop] = delegates.modifySuiteName(attrs[prop]);
|
160 | }
|
161 | str += " " + prop + "='" + escapeTeamCityString(attrs[prop]) + "'";
|
162 | }
|
163 | }
|
164 | }
|
165 | str += "]";
|
166 | log(str);
|
167 | }
|
168 | };
|
169 |
|
170 | function escapeTeamCityString(str) {
|
171 | if(!str) {
|
172 | return "";
|
173 | }
|
174 | if (Object.prototype.toString.call(str) === "[object Date]") {
|
175 | return ISODateString(str);
|
176 | }
|
177 |
|
178 | return str.replace(/\|/g, "||")
|
179 | .replace(/'/g, "|'")
|
180 | .replace(/\n/g, "|n")
|
181 | .replace(/\r/g, "|r")
|
182 | .replace(/\u0085/g, "|x")
|
183 | .replace(/\u2028/g, "|l")
|
184 | .replace(/\u2029/g, "|p")
|
185 | .replace(/\[/g, "|[")
|
186 | .replace(/]/g, "|]");
|
187 | }
|
188 | })(this);
|