jasmine-bamboo-reporter
Version:
A reporter for Jasmine which produces a report compatible with Atlassian Bamboo Mocha Test Parser.
178 lines • 5.41 kB
JavaScript
// src/index.ts
import fs from "fs";
function format(result) {
const msg = [];
let counter = 1;
let formatted;
if (result.failedExpectations.length === 1) {
formatted = "1 Failure: ";
} else {
formatted = `${result.failedExpectations.length} Failures: `;
}
result.failedExpectations.forEach(function iterator(expectation) {
msg.push(`${counter}. : ${expectation.message}`);
counter++;
});
formatted += msg.join("\n");
return formatted;
}
function shallowMerge(obj1, obj2) {
const mergedObj = {};
Object.keys(obj1).forEach(function iterator(key) {
if (!obj2[key]) {
mergedObj[key] = obj1[key];
} else {
mergedObj[key] = obj2[key];
}
});
return mergedObj;
}
function sleep(ms) {
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
}
function acquireLock(lockPath, waitMs) {
const deadline = Date.now() + waitMs;
for (; ; ) {
try {
fs.closeSync(fs.openSync(lockPath, "wx"));
return true;
} catch (err) {
if (err.code !== "EEXIST") {
throw err;
}
if (Date.now() >= deadline) {
return false;
}
sleep(100);
}
}
}
function releaseLock(lockPath) {
try {
fs.unlinkSync(lockPath);
} catch (err) {
if (err.code !== "ENOENT") {
throw err;
}
}
}
var Reporter = class {
options;
spec;
specStart;
output;
constructor(opts) {
const defaultOpts = {
file: "jasmine.json",
beautify: true,
indentationLevel: 4
};
this.options = shallowMerge(
defaultOpts,
typeof opts === "object" ? opts : {}
);
this.spec = {};
this.specStart = 0;
this.output = {
stats: {
suites: 0,
tests: 0,
passes: 0,
pending: 0,
failures: 0,
start: 0,
// this is the overall time for everything. - all suites.
end: 0,
duration: 0,
time: 0
// bamboo + mocha seem to be using "time", not duration.
},
failures: [],
passes: [],
skipped: []
};
}
suiteDone() {
this.output.stats.suites++;
}
specStarted() {
this.specStart = /* @__PURE__ */ new Date();
}
specDone(result) {
this.spec.duration = Math.floor(
(Date.now() - this.specStart.getTime()) / 1e3
);
this.spec.time = this.spec.duration;
this.spec.title = result.fullName;
this.spec.fullTitle = result.description;
this.output.stats.tests++;
if (result.status === "passed") {
this.output.stats.passes++;
this.output.passes.push(this.spec);
} else if (result.status === "failed") {
this.output.stats.failures++;
this.spec.error = format(result);
this.output.failures.push(this.spec);
} else {
this.output.stats.pending++;
this.output.skipped.push(this.spec);
}
this.spec = {};
}
jasmineStarted() {
this.output.stats.start = /* @__PURE__ */ new Date();
}
mergeOutput(previous) {
this.output.stats.suites = this.output.stats.suites + previous.stats.suites;
this.output.stats.tests = this.output.stats.tests + previous.stats.tests;
this.output.stats.passes = this.output.stats.passes + previous.stats.passes;
this.output.stats.pending = this.output.stats.pending + previous.stats.pending;
this.output.stats.failures = this.output.stats.failures + previous.stats.failures;
this.output.start = previous.start;
this.output.failures = this.output.failures.concat(previous.failures);
this.output.passes = this.output.passes.concat(previous.passes);
this.output.skipped = this.output.skipped.concat(previous.skipped);
}
// jasmineDone gets called multiple times, once for each process (thread) we are executing. Normally this would
// just be one thread, but protractor can "shard" tests which really just runs multiple processes with one
// to rule them all.
//
// Since that code is running in separate processes, it isn't easy to use a global/static class variable to
// handle a single instance of the jasmine reporter - nor is it easy to aggregate the results. So the trick here
// is to lock, read any file that exists, merge, write results to file, and then release lock.
jasmineDone() {
const lockname = `${this.options.file}.lock`;
this.output.stats.end = /* @__PURE__ */ new Date();
if (!acquireLock(lockname, 2e3)) {
console.error(
`Jasmine bamboo reporter unable to acquire a file lock for ${lockname}`
);
return;
}
try {
if (fs.existsSync(this.options.file)) {
const raw = fs.readFileSync(this.options.file, { encoding: "utf8" });
const previous = JSON.parse(raw);
this.mergeOutput(previous);
}
this.output.stats.duration = Math.floor(
(this.output.stats.end.getTime() - this.output.stats.start.getTime()) / 1e3
);
this.output.stats.time = this.output.stats.duration;
const resultsOutput = this.options.beautify ? JSON.stringify(this.output, null, this.options.indentationLevel) : JSON.stringify(this.output);
fs.writeFileSync(this.options.file, resultsOutput);
} finally {
try {
releaseLock(lockname);
} catch {
console.error(
`Jasmine bamboo reporter could not unlock file ${lockname}`
);
}
}
}
};
export {
Reporter as default
};
//# sourceMappingURL=index.mjs.map