Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for user-provided runId #4

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"scripts": {
"tsc": "tsc",
"clean": "rimraf dist",
"test": "mocha dist/test",
"test": "mocha --require dotenv/config dist/test",
"build": "npm run clean && npm run tsc"
},
"dependencies": {
Expand All @@ -40,6 +40,8 @@
"@types/mocha": "^2.2.36",
"@types/node": "^6.0.58",
"chai": "^3.5.0",
"dotenv": "^5.0.0",
"mocha": "^5.0.1",
"rimraf": "^2.5.4",
"typescript": "^2.1.4"
}
Expand Down
16 changes: 14 additions & 2 deletions src/lib/mocha-testrail-reporter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {reporters} from 'mocha';
import {TestRail} from "./testrail";
import {titleToCaseIds} from "./shared";
import {Status, TestRailResult} from "./testrail.interface";
import {Status, TestRailResult, TestRailOptions} from "./testrail.interface";


export class MochaTestRailReporter extends reporters.Spec {
Expand All @@ -19,7 +19,7 @@ export class MochaTestRailReporter extends reporters.Spec {
this.validate(reporterOptions, 'username');
this.validate(reporterOptions, 'password');
this.validate(reporterOptions, 'projectId');
this.validate(reporterOptions, 'suiteId');
this.validateEither(reporterOptions, ['suiteId', 'runId']);

runner.on('start', () => {
});
Expand Down Expand Up @@ -108,4 +108,16 @@ ${this.out.join('\n')}
throw new Error(`Missing ${name} value. Please update --reporter-options in mocha.opts`);
}
}

private validateEither(options: TestRailOptions, names: string[]) {
if (options == null) {
throw new Error("Missing --reporter-options in mocha.opts");
}

if (!names.reduce((previousValue, currentValue) => {
return previousValue || options[currentValue] != null
}, false)) {
throw new Error(`Missing either options of: ${names.join(", ")}. Please update --reporter-options in mocha.opts`);
}
}
}
3 changes: 2 additions & 1 deletion src/lib/testrail.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ export interface TestRailOptions {
username: string,
password: string,
projectId: number,
suiteId: number,
runId?: number,
suiteId?: number,
assignedToId?: number,
}

Expand Down
34 changes: 21 additions & 13 deletions src/lib/testrail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,31 +79,39 @@ export class TestRail {

/**
* Publishes results of execution of an automated test run
* @param {string} name
* @param {string} description
* @param {string} name New test run name. Only applicable when runID is not specified
* @param {string} description New test run description. Only applicable when runID is not specified
* @param {TestRailResult[]} results
* @param {Function} callback
*/
public publish(name: string, description: string, results: TestRailResult[], callback?: Function): void {
console.log(`Publishing ${results.length} test result(s) to ${this.base}`);

this._post(`add_run/${this.options.projectId}`, {
"suite_id": this.options.suiteId,
"name": name,
"description": description,
"assignedto_id": this.options.assignedToId,
"include_all": true
}, (body) => {
const runId = body.id
console.log(`Results published to ${this.base}?/runs/view/${runId}`)
this._post(`add_results_for_cases/${runId}`, {
let self = this;
let p = this.options.runId? Promise.resolve(this.options.runId): new Promise((resolve, reject) => {
self._post(`add_run/${self.options.projectId}`, {
"suite_id": self.options.suiteId,
"name": name,
"description": description,
"assignedto_id": self.options.assignedToId,
"include_all": true
}, (body) => {
resolve(body.id);
}, (err) => {
reject(err);
})
})

p.then((runId) => {
console.log(`Results published to ${self.base}?/runs/view/${runId}`)
self._post(`add_results_for_cases/${runId}`, {
results: results
}, (body) => {
// execute callback if specified
if (callback) {
callback();
}
})
});
})
}
}
68 changes: 68 additions & 0 deletions src/test/helpers/mock-runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Adapted from: https://github.com/michaelleeallen/mocha-junit-reporter/blob/master/test/helpers/mock-runner.js
*/
'use strict';

import {EventEmitter} from 'events';
const util = require('util');

export class Runner extends EventEmitter {
_currentSuite: any;
constructor() {
super()
}

public start() {
this.emit('start');
}

public end() {
this.emit('end');
};

public startSuite(suite: any) {
suite.suites = suite.suites || [];
suite.tests = suite.tests || [];

if (this._currentSuite) {
suite.parent = this._currentSuite;
}

this._currentSuite = suite;
this.emit('suite', suite);
}

public pass(test) {
this.emit('pass', test);
this.endTest();
};

public fail(test, reason) {
this.emit('fail', test, reason);
this.endTest();
};

public pending(test) {
this.emit('pending', test);
this.endTest();
};

public endTest() {
this.emit('end test');
};
}

export class Test {
private title;
private duration;
private fullTitle;
private slow;
constructor(fullTitle, title, duration?) {
this.title = title;
this.duration = duration;
this.fullTitle = function() {
return fullTitle;
};
this.slow = function() {};
}
}
103 changes: 103 additions & 0 deletions src/test/reporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
let Reporter = require("../../index.js");
import { Runner, Test } from "./helpers/mock-runner";
const assert = require("assert");

describe("Reporter", () => {
let runner;

function executeTestRunner(options) {
options = options || {};
options.invalidChar = options.invalidChar || "";
options.title = options.title || "Foo Bar module";
options.root = typeof options.root !== "undefined" ? options.root : false;
runner.start();

runner.startSuite({
title: options.title,
root: options.root,
tests: [1, 2]
});

if (!options.skipPassedTests) {
runner.pass(new Test("Foo can weez the juice", "can weez the juice", 1));
}

runner.fail(
new Test("Bar can narfle the garthog", "can narfle the garthog", 1),
{
stack:
options.invalidChar +
"expected garthog to be dead" +
options.invalidChar
}
);

runner.fail(
new Test("Baz can behave like a flandip", "can behave like a flandip", 1),
{
name: "BazError",
message:
"expected baz to be masher, a hustler, an uninvited grasper of cone"
}
);

runner.startSuite({
title: "Another suite!",
tests: [1]
});

runner.pass(new Test("Another suite", "works", 4));

if (options && options.includePending) {
runner.startSuite({
title: "Pending suite!",
tests: [1]
});
runner.pending(new Test("Pending suite", "pending"));
}

runner.end();
}

function createReporter(options) {
options = options || {};
return new Reporter(runner, { reporterOptions: options });
}

beforeEach(function() {
runner = new Runner();
});

it("Requires either suiteID or runId", () => {
let testFunc = function() {
createReporter({
domain: process.env.DOMAIN,
username: process.env.USERNAME,
password: process.env.PASSWORD,
projectId: process.env.PROJECT_ID
});
executeTestRunner({});
};

assert.throws(
testFunc,
/Error: Missing either options of: suiteId, runId. Please update --reporter-options in mocha.opts/
);
});

it("Requires projectId", () => {
let testFunc = function() {
createReporter({
domain: process.env.DOMAIN,
username: process.env.USERNAME,
password: process.env.PASSWORD
});
executeTestRunner({});
};

assert.throws(
testFunc,
/Missing projectId value. Please update --reporter-options in mocha.opts/
);
});
});
41 changes: 33 additions & 8 deletions src/test/testrail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,39 @@ import {TestRail} from "../lib/testrail";
import {TestRailResult, TestRailCase, Status} from "../lib/testrail.interface";

describe("TestRail API", () => {
it("Publish test run", (done) => {
it("Publish test run on current Run ID", (done) => {
let testRail = new TestRail({
domain: process.env.DOMAIN,
username: process.env.USERNAME,
password: process.env.PASSWORD,
projectId: 10,
suiteId: 104,
// assignedToId: 2,
projectId: process.env.PROJECT_ID,
runId: process.env.RUN_ID
});

testRail.publish("Unit Test of mocha-testrail-reporter", "Unit Test of mocha-testrail-reporter", [{
case_id: process.env.CASE_1,
status_id: Status.Passed,
comment: "Passing...."
}, {
case_id: process.env.CASE_2,
status_id: Status.Passed
}, {
case_id: process.env.CASE_3,
status_id: Status.Passed
}, {
case_id: process.env.CASE_4,
status_id: Status.Failed,
comment: "Failure...."
}], done);
});

it("Publish test run on new Run ID", (done) => {
let testRail = new TestRail({
domain: process.env.DOMAIN,
username: process.env.USERNAME,
password: process.env.PASSWORD,
projectId: process.env.PROJECT_ID,
suiteId: process.env.SUITE_ID,
});

testRail.fetchCases({type_id: [3], priority_id: [4]}, (cases: TestRailCase[]) => {
Expand All @@ -21,17 +46,17 @@ describe("TestRail API", () => {
});

testRail.publish("Unit Test of mocha-testrail-reporter", "Unit Test of mocha-testrail-reporter", [{
case_id: 3033,
case_id: process.env.CASE_ID_1,
status_id: Status.Passed,
comment: "Passing...."
}, {
case_id: 3034,
case_id: process.env.CASE_ID_2,
status_id: Status.Passed
}, {
case_id: 3035,
case_id: process.env.CASE_ID_3,
status_id: Status.Passed
}, {
case_id: 3036,
case_id: process.env.CASE_ID_4,
status_id: Status.Failed,
comment: "Failure...."
}], done);
Expand Down
6 changes: 5 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
"noImplicitAny": false,
"pretty": true,
"outDir": "dist",
"typeRoots": ["node_modules/@types"]
"typeRoots": ["node_modules/@types"],
"lib": [
"dom",
"es2016"
],
},
"exclude": [
"node_modules",
Expand Down