jasmine-spiratest
Version:
This reporter will integrate JasmineJS with Inflectra's ALM suite. It will create a test run in Spira for each test spec executed in Jasmine. ### Don't have Spira? If you haven't tried out one of our products, you can get a 30 day free trial for our flags
247 lines (212 loc) • 7.66 kB
JavaScript
var http = require('http');
var https = require('https');
const spiraServiceUrl = "/Services/v6_0/RestService.svc/";
module.exports = SpiraReporter;
/**
* Where all executed test runs are put before they are posted to Spira. Here is the format:
* {
* testCaseId: int,
* testName: string
* stackTrace: string
* statusId: int
* startDate: string
* message: string
* releaseId: int
* testSetId: int
* }
*/
var allTestRuns = [];
/**
* Credentials for accessing Spira
*/
var credentials = {};
/**
* The last posted test run. Used to avoid POSTing duplicates
*/
var lastPosted = {};
/**
*
* @param params Either a string containing an absolute directory to a json file containing
* Spira credentials, or an object in the same format as the file
*/
function SpiraReporter(params) {
//make sure user has given all the essentials
if (params.hasOwnProperty("url") && params.hasOwnProperty("username")
&& params.hasOwnProperty("token") && params.hasOwnProperty("projectId")) {
credentials.url = params.url;
credentials.username = params.username;
credentials.token = params.token;
credentials.projectId = params.projectId;
}
else {
//'yell' at them
console.error("-- SPIRA ERROR --");
console.error("Please make sure you have the 'url', 'username'," +
" 'token', and 'projectId' fields defined. This integration" +
" will not work without them.");
}
//make sure the user has test cases taken care of
if (params.hasOwnProperty("testCases")) {
credentials.testCases = {};
if (params.testCases.hasOwnProperty("default")) {
credentials.testCases.default = params.testCases.default;
}
else {
console.error("-- SPIRA ERROR --");
console.error("Please Make sure you have the 'default'" +
" field within the 'testCases' object. ");
}
//process unique test case names
for (var property in params.testCases) {
if (property != "default" && params.testCases.hasOwnProperty(property)) {
//remove special characters and spaces and assign to the credentials
credentials.testCases[compressName(property)] = params.testCases[property];
}
}
}
else {
console.error("-- SPIRA ERROR --");
console.error("Please make sure you have a field called 'testCases'");
}
//nonessential properties
if (params.hasOwnProperty("releaseId")) {
credentials.releaseId = params.releaseId;
}
if (params.hasOwnProperty("testSetId")) {
credentials.testSetId = params.testSetId;
}
}
/**
* Remove the spaces, special characters, and punctuation from the given string.
* Used for assigning test cases to individual specs (the it call)
* @param {string} name
*/
function compressName(name) {
return name.toLowerCase().replace(/[^a-z0-9]/ig, "")
}
SpiraReporter.prototype.jasmineDone = async (suiteInfo, done) => {
//actually send stuff up
await postTestRuns();
//done();
}
SpiraReporter.prototype.specDone = (result) => {
//avoid storing duplicates
if (result.id != lastPosted.id) {
lastPosted = result;
var now = new Date().getTime();
var newTestRun = {
testCaseId: credentials.testCases.default,
testName: result.description,
stackTrace: '',
statusId: -1,
startDate: now - result.duration,
endDate: now,
message: ""
}
//assign an individual test case
for (var property in credentials.testCases) {
if (property != "default" && credentials.testCases.hasOwnProperty(property)) {
if (compressName(result.description) == property) {
newTestRun.testCaseId = credentials.testCases[property];
}
}
}
//populate the stack trace from all failed tests
result.failedExpectations.forEach(e => {
newTestRun.stackTrace += e.stack;
});
if (result.status == "passed") {
//2 is passed in Spira
newTestRun.statusId = 2;
newTestRun.message = "Test Succeeded";
}
else if (result.status == "failed") {
//1 is failed in Spira
newTestRun.statusId = 1;
newTestRun.message = "Test Failed";
}
//handle optional release and test set ID's
if (credentials.hasOwnProperty("releaseId")) {
newTestRun.releaseId = credentials.releaseId;
}
if (credentials.hasOwnProperty("testSetId")) {
newTestRun.testSetId = credentials.testSetId;
}
allTestRuns.push(newTestRun);
}
}
/**
* Post all test runs in the allTestRuns array
*/
async function postTestRuns() {
return new Promise(resolve => {
//we will submit all test runs at once
var url = credentials.url + spiraServiceUrl + "projects/" + credentials.projectId
+ "/test-runs/record?username=" + credentials.username
+ "&api-key=" + credentials.token;
var protocol = http.request;
if (url.startsWith("https")) {
protocol = https.request;
//cut the https:// out of the url
url = url.substring(8);
}
else if (url.startsWith("http")) {
//cut out the http:// out of the url
url = url.substring(7);
}
var path = url.substring(url.indexOf("/"));
url = url.substring(0, url.length - path.length);
var options = {
host: url,
path: path,
method: "POST",
headers: {
"Content-Type": "application/json",
"accept": "application/json"
}
}
//used to tell how many POST requests were actually made
var numRequestsMade = 0;
//tabulate our data into something Spira can read and POST it
allTestRuns.forEach(e => {
var run = {
//1 for plain text
TestRunFormatId: 1,
TestCaseId: e.testCaseId,
RunnerTestName: e.testName,
RunnerName: "JasmineJS",
RunnerMessage: e.message,
RunnerStackTrace: e.stackTrace,
ExecutionStatusId: e.statusId,
StartDate: new Date(e.startDate),
EndDate: new Date(e.endDate)
}
//handle optional release and test set ID's
if (e.hasOwnProperty("releaseId")) {
run.ReleaseId = e.releaseId;
}
if (e.hasOwnProperty("testSetId")) {
run.TestSetId = e.testSetId;
}
//open the POST request
var request = protocol(options, (res) => {
// console.log(res.statusCode + " : " + res.statusMessage);
res.on('data', chunk => {
numRequestsMade++;
// console.log("RETURN: " + chunk)
if (numRequestsMade == allTestRuns.length) {
//empty array for next suite.
allTestRuns = [];
resolve();
}
})
});
request.on("error", e => {
console.log("Spira Error " + e);
})
//actually send the data
request.write(JSON.stringify(run));
request.end();
});
});
}