UNPKG

7.46 kBJavaScriptView Raw
1(function(global) {
2 var exportObject;
3
4 if (typeof module !== "undefined" && module.exports) {
5 exportObject = exports;
6 } else {
7 exportObject = global.jasmineReporters = global.jasmineReporters || {};
8 }
9
10 function elapsed(start, end) { return (end - start); }
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 isPassed(obj) { return obj.status === "passed"; }
15 function extend(dupe, obj) { // performs a shallow copy of all props of `obj` onto `dupe`
16 for (var prop in obj) {
17 if (obj.hasOwnProperty(prop)) {
18 dupe[prop] = obj[prop];
19 }
20 }
21 return dupe;
22 }
23
24 /**
25 * Basic reporter that outputs spec results for the AppVeyor build system
26 *
27 * Usage:
28 *
29 * jasmine.getEnv().addReporter(new jasmineReporters.AppVeyorReporter(options));
30 *
31 * @param {object} [options]
32 * @param {number} [options.batchSize] spec batch size to report to AppVeyor (default: 50)
33 * @param {number} [options.verbosity] meaningful values are 0 through 2; anything
34 * greater than 2 is treated as 2 (default: 0)
35 * @param {boolean} [options.color] print in color or not (default: true)
36 */
37 var DEFAULT_BATCHSIZE = 50,
38 DEFAULT_VERBOSITY = 0,
39 DEFAULT_COLOR = true,
40 ATTRIBUTES_TO_ANSI = {
41 "off": 0,
42 "bold": 1,
43 "red": 31,
44 "green": 32,
45 "yellow": 33,
46 "blue": 34,
47 "magenta": 35,
48 "cyan": 36
49 };
50
51 exportObject.AppVeyorReporter = function(options) {
52 var self = this;
53
54 self.options = options || {};
55 self.batchSize = typeof self.options.batchSize === "number" ? self.options.batchSize : DEFAULT_BATCHSIZE;
56 self.verbosity = typeof self.options.verbosity === "number" ? self.options.verbosity : DEFAULT_VERBOSITY;
57 self.color = typeof self.options.color === "boolean" ? self.options.color : DEFAULT_COLOR;
58
59 self.unreportedSpecs = [];
60
61 setApi();
62
63 var __specs = {};
64 // add or get excisting spec from __specs dictionary
65 function getSpec(spec) {
66 __specs[spec.id] = extend(__specs[spec.id] || {}, spec);
67 return __specs[spec.id];
68 }
69
70 // set API host information
71 function setApi() {
72 self.api = {};
73 if(process && process.env && process.env.APPVEYOR_API_URL) {
74 var fullUrl = process.env.APPVEYOR_API_URL;
75
76 var urlParts = fullUrl.split("/")[2].split(":");
77 self.api = {
78 host: urlParts[0],
79 port: urlParts[1],
80 endpoint: "/api/tests/batch"
81 };
82 }
83 else {
84 throw Error("Not running in AppVeyor environment");
85 }
86 }
87
88 // log object to handle verbosity
89 var log = {
90 info: function(str) {
91 if(self.verbosity > 0) {
92 log.logOutput(str);
93 }
94 },
95 debug: function(str) {
96 if(self.verbosity > 1) {
97 log.logOutput(str);
98 }
99 },
100 logOutput: function(str) {
101 var con = global.console || console;
102 if (con && con.log) {
103 con.log(str);
104 }
105 }
106 };
107
108 function inColor(string, color) {
109 var color_attributes = color && color.split("+"),
110 ansi_string = "",
111 i;
112
113 if (!string || !string.length) {
114 return "";
115 }
116
117 if (!self.color || !color_attributes) {
118 return string;
119 }
120
121 for(i = 0; i < color_attributes.length; i++) {
122 ansi_string += "\u001b[" + ATTRIBUTES_TO_ANSI[color_attributes[i]] + "m";
123 }
124 ansi_string += string + "\u001b[" + ATTRIBUTES_TO_ANSI["off"] + "m";
125
126 return ansi_string;
127 }
128
129 // post batch to AppVeyor API
130 function postSpecsToAppVeyor() {
131 log.info(inColor("Posting spec batch to AppVeyor API", "magenta"));
132
133 var postData = JSON.stringify(self.unreportedSpecs);
134
135 var options = {
136 host: self.api.host,
137 path: self.api.endpoint,
138 port: self.api.port,
139 method: "POST",
140 headers: {
141 "Content-Type": "application/json"
142 }
143 };
144
145 var http = require("http");
146 var req = http.request(options, function(res) {
147 log.debug(inColor(" STATUS: " + res.statusCode, "yellow"));
148 log.debug(inColor(" HEADERS: " + JSON.stringify(res.headers), "yellow"));
149 res.setEncoding("utf8");
150
151 res.on("data", function (chunk) {
152 log.debug(inColor(" BODY: " + chunk, "yellow"));
153 });
154
155 res.on("end", function() {
156 log.debug(inColor(" RESPONSE END", "yellow"));
157 });
158 });
159
160 req.on("error", function(e) {
161 log.debug(inColor("API request error: " + e.message, "red"));
162 });
163
164 req.write(postData);
165 req.end();
166
167 self.unreportedSpecs = [];
168 }
169
170 // detect spec outcome and return AppVeyor literals
171 function getOutcome(spec) {
172 var outcome = "None";
173
174 if(isFailed(spec)) {
175 outcome = "Failed";
176 }
177
178 if(isDisabled(spec)) {
179 outcome = "Ignored";
180 }
181
182 if(isSkipped(spec)) {
183 outcome = "Skipped";
184 }
185
186 if(isPassed(spec)) {
187 outcome = "Passed";
188 }
189
190 return outcome;
191 }
192
193 // map jasmine spec to AppVeyor test result
194 function mapSpecToResult(spec) {
195 var firstFailedExpectation = spec.failedExpectations[0] || {};
196
197 var result = {
198 testName: spec.fullName,
199 testFramework: "jasmine2",
200 durationMilliseconds: elapsed(spec.__startTime, spec.__endTime),
201
202 outcome: getOutcome(spec),
203 ErrorMessage: firstFailedExpectation.message,
204 ErrorStackTrace: firstFailedExpectation.stack
205 };
206
207 return result;
208 }
209
210 self.specStarted = function(spec) {
211 spec = getSpec(spec);
212 spec.__startTime = new Date();
213 };
214
215 self.specDone = function(spec) {
216 spec = getSpec(spec);
217 spec.__endTime = new Date();
218
219 var avr = mapSpecToResult(spec);
220
221 self.unreportedSpecs.push(avr);
222
223 if(self.unreportedSpecs.length > self.batchSize) {
224 postSpecsToAppVeyor();
225 }
226 };
227
228 self.jasmineDone = function() {
229 if(self.unreportedSpecs.length > 0) {
230 postSpecsToAppVeyor();
231 }
232
233 // this is so phantomjs-testrunner.js can tell if we're done executing
234 exportObject.endTime = new Date();
235 };
236 };
237})(this);