aft-mocha-reporter
Advanced tools
Comparing version 9.0.0 to 10.0.0
{ | ||
"LogManager": { | ||
"level": "info", | ||
"plugins": [{ | ||
"name": "html-logging-plugin", | ||
"searchDirectory": "../", | ||
"options": { | ||
"level": "warn" | ||
} | ||
}, { | ||
"name": "filesystem-logging-plugin", | ||
"searchDirectory": "../", | ||
"options": { | ||
"includeResults": false, | ||
"level": "trace" | ||
} | ||
}] | ||
} | ||
"pluginNames": [ | ||
"html-reporting-plugin", | ||
"filesystem-reporting-plugin" | ||
], | ||
"pluginsSearchDir": "../", | ||
"logLevel": "debug" | ||
} |
/// <reference types="mocha" /> | ||
import { LogManager } from "aft-core"; | ||
import { AftConfig, Reporter } from "aft-core"; | ||
export declare class AftLog { | ||
private _logMgr; | ||
private _rep; | ||
readonly test: Mocha.Test; | ||
constructor(scope?: any); | ||
readonly aftCfg: AftConfig; | ||
constructor(scope?: any, aftCfg?: AftConfig); | ||
get fullTitle(): string; | ||
get logMgr(): LogManager; | ||
get reporter(): Reporter; | ||
dispose(): Promise<void>; | ||
} |
@@ -15,4 +15,5 @@ "use strict"; | ||
class AftLog { | ||
constructor(scope) { | ||
constructor(scope, aftCfg) { | ||
this.test = (scope === null || scope === void 0 ? void 0 : scope.test) || {}; | ||
this.aftCfg = aftCfg !== null && aftCfg !== void 0 ? aftCfg : aft_core_1.aftConfig; | ||
} | ||
@@ -28,11 +29,11 @@ get fullTitle() { | ||
} | ||
get logMgr() { | ||
if (!this._logMgr) { | ||
this._logMgr = new aft_core_1.LogManager({ logName: this.fullTitle }); | ||
get reporter() { | ||
if (!this._rep) { | ||
this._rep = new aft_core_1.Reporter(this.fullTitle, this.aftCfg); | ||
} | ||
return this._logMgr; | ||
return this._rep; | ||
} | ||
dispose() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.logMgr.dispose(); | ||
yield this.reporter.dispose(); | ||
}); | ||
@@ -39,0 +40,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { TestResult, TestStatus } from "aft-core"; | ||
import { TestResult, TestStatus, AftConfig, Func, Verifier, Class } from "aft-core"; | ||
import { AftLog } from "./aft-log"; | ||
@@ -8,4 +8,4 @@ /** | ||
export declare class AftTest extends AftLog { | ||
private _testcases; | ||
private _defects; | ||
private readonly _testcases; | ||
private readonly _buildMgr; | ||
/** | ||
@@ -16,12 +16,30 @@ * expects to be passed the scope from an executing Mocha | ||
*/ | ||
constructor(scope?: any); | ||
constructor(scope?: any, aftCfg?: AftConfig); | ||
/** | ||
* an array of test ID's parsed from the test title where test ID's | ||
* are expected to be in the surrounded by `[` and `]` like: `"[TESTID]"` | ||
*/ | ||
get testcases(): Array<string>; | ||
get defects(): Array<string>; | ||
pass(): Promise<void>; | ||
fail(err: any): Promise<void>; | ||
pending(): Promise<void>; | ||
/** | ||
* determines if any of the referenced Test Case ID's should be run according to the | ||
* loaded `TestExecutionPolicyPlugin` implementations' `shouldRun` methods | ||
* @returns `true` if test should be run, otherwise `false` | ||
*/ | ||
shouldRun(): Promise<boolean>; | ||
/** | ||
* creates a new {Verifier} that will run the passed in `assertion` if the `shouldRun` function | ||
* returns `true` otherwise it will bypass execution | ||
* @param assertion a function that performs test actions and will accept a {Verifier} instance | ||
* for use during the test actions' execution | ||
* @param verifierType an optional {Verifier} class to use instead of the base {Verifier} type | ||
* @returns a {Verifier} instance already configured with test cases, description, logger and config | ||
*/ | ||
verify<T extends Verifier>(assertion: Func<T, any>, verifierType?: Class<T>): T; | ||
protected _getVerifier<T extends Verifier>(verifierType?: Class<T>): T; | ||
/** | ||
* creates `ITestResult` objects for each `testId` and sends these | ||
* to the `LogManager.logResult` function | ||
* to the `Reporter.logResult` function | ||
* @param result an `IProcessingResult` returned from executing the | ||
@@ -28,0 +46,0 @@ * expectation |
@@ -15,3 +15,2 @@ "use strict"; | ||
const aft_log_1 = require("./aft-log"); | ||
const should_run_1 = require("./should-run"); | ||
const title_parser_1 = require("./title-parser"); | ||
@@ -28,20 +27,17 @@ /** | ||
*/ | ||
constructor(scope) { | ||
super(scope); | ||
constructor(scope, aftCfg) { | ||
super(scope, aftCfg); | ||
this._buildMgr = new aft_core_1.BuildInfoManager(this.aftCfg); | ||
this._testcases = title_parser_1.TitleParser.parseTestIds(this.fullTitle); | ||
} | ||
/** | ||
* an array of test ID's parsed from the test title where test ID's | ||
* are expected to be in the surrounded by `[` and `]` like: `"[TESTID]"` | ||
*/ | ||
get testcases() { | ||
if (!this._testcases) { | ||
this._testcases = title_parser_1.TitleParser.parseTestIds(this.fullTitle); | ||
} | ||
return this._testcases; | ||
} | ||
get defects() { | ||
if (!this._defects) { | ||
this._defects = title_parser_1.TitleParser.parseDefectIds(this.fullTitle); | ||
} | ||
return this._defects; | ||
} | ||
pass() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this._logResult('Passed'); | ||
yield this._logResult('passed'); | ||
}); | ||
@@ -53,3 +49,3 @@ } | ||
const stack = (err.stack) ? `\n${err.stack}` : ''; | ||
yield this._logResult('Failed', `${message}${stack}`); | ||
yield this._logResult('failed', `${message}${stack}`); | ||
}); | ||
@@ -59,27 +55,40 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this._logResult('Skipped', 'test skipped'); | ||
yield this._logResult('skipped', 'test skipped'); | ||
}); | ||
} | ||
/** | ||
* determines if any of the referenced Test Case ID's should be run according to the | ||
* loaded `TestExecutionPolicyPlugin` implementations' `shouldRun` methods | ||
* @returns `true` if test should be run, otherwise `false` | ||
*/ | ||
shouldRun() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let result = true; | ||
const should = yield Promise.all([ | ||
should_run_1.shouldRun.tests(...this.testcases), | ||
should_run_1.shouldRun.defects(...this.defects) | ||
]).catch((err) => __awaiter(this, void 0, void 0, function* () { | ||
yield this.logMgr.warn(err); | ||
return []; | ||
})); | ||
if (should === null || should === void 0 ? void 0 : should.length) { | ||
if (!should.map(s => s.success).reduce((prev, curr) => prev && curr)) { | ||
result = false; | ||
yield this.logMgr.warn(should.filter(s => !s.success).map(s => s.message).join('; ')); | ||
} | ||
} | ||
return result; | ||
const shouldRun = yield this._getVerifier(aft_core_1.Verifier).shouldRun(); | ||
return shouldRun.result; | ||
}); | ||
} | ||
/** | ||
* creates a new {Verifier} that will run the passed in `assertion` if the `shouldRun` function | ||
* returns `true` otherwise it will bypass execution | ||
* @param assertion a function that performs test actions and will accept a {Verifier} instance | ||
* for use during the test actions' execution | ||
* @param verifierType an optional {Verifier} class to use instead of the base {Verifier} type | ||
* @returns a {Verifier} instance already configured with test cases, description, logger and config | ||
*/ | ||
verify(assertion, verifierType) { | ||
return this._getVerifier(verifierType) | ||
.verify(assertion); | ||
} | ||
_getVerifier(verifierType) { | ||
verifierType !== null && verifierType !== void 0 ? verifierType : (verifierType = aft_core_1.Verifier); | ||
return new verifierType() | ||
.internals.usingReporter(this.reporter) | ||
.internals.usingAftConfig(this.aftCfg) | ||
.withDescription(this.fullTitle) | ||
.withTestIds(...this.testcases) | ||
.on('skipped', () => this.test.skip()); | ||
} | ||
/** | ||
* creates `ITestResult` objects for each `testId` and sends these | ||
* to the `LogManager.logResult` function | ||
* to the `Reporter.logResult` function | ||
* @param result an `IProcessingResult` returned from executing the | ||
@@ -91,3 +100,3 @@ * expectation | ||
try { | ||
status = status || 'Untested'; | ||
status = status || 'untested'; | ||
if (this.testcases.length) { | ||
@@ -110,6 +119,6 @@ this.testcases.forEach((testId) => __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
yield this.logMgr.logResult(result); | ||
yield this.reporter.submitResult(result); | ||
} | ||
catch (e) { | ||
yield this.logMgr.warn(`unable to log test result for test '${result.testId || result.resultId}' due to: ${e}`); | ||
yield this.reporter.warn(`unable to log test result for test '${result.testId || result.resultId}' due to: ${aft_core_1.Err.short(e)}`); | ||
} | ||
@@ -119,3 +128,3 @@ } | ||
finally { | ||
yield this.logMgr.dispose(); | ||
yield this.reporter.dispose(); | ||
} | ||
@@ -126,16 +135,16 @@ }); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
message = message || this.logMgr.logName; | ||
message = message || this.reporter.reporterName; | ||
switch (status) { | ||
case 'Blocked': | ||
case 'Retest': | ||
case 'Skipped': | ||
case 'Untested': | ||
yield this.logMgr.warn(message); | ||
case 'blocked': | ||
case 'retest': | ||
case 'skipped': | ||
case 'untested': | ||
yield this.reporter.warn(message); | ||
break; | ||
case 'Failed': | ||
yield this.logMgr.fail(message); | ||
case 'failed': | ||
yield this.reporter.fail(message); | ||
break; | ||
case 'Passed': | ||
case 'passed': | ||
default: | ||
yield this.logMgr.pass(message); | ||
yield this.reporter.pass(message); | ||
break; | ||
@@ -165,2 +174,3 @@ } | ||
let result = { | ||
testName: this.fullTitle, | ||
testId: testId, | ||
@@ -173,4 +183,4 @@ created: Date.now(), | ||
durationMs: this.test.duration, | ||
buildName: (yield aft_core_1.buildinfo.buildName()) || 'unknown', | ||
buildNumber: (yield aft_core_1.buildinfo.buildNumber()) || 'unknown' | ||
buildName: (yield this._buildMgr.buildName()) || 'unknown', | ||
buildNumber: (yield this._buildMgr.buildNumber()) || 'unknown' | ||
} | ||
@@ -177,0 +187,0 @@ }; |
@@ -12,13 +12,3 @@ export declare class TitleParser { | ||
static parseTestIds(title: string): Array<string>; | ||
/** | ||
* parses DefectIds from the passed in title. a DefectId | ||
* must be surrounded by square brackets and should take | ||
* the form of: | ||
* `some test <ID123> with multiple ids <Another>` where | ||
* `['ID123', 'Another']` would be returned | ||
* @param title the test full title to be parsed | ||
* @returns an array of DefectId strings or empty array | ||
*/ | ||
static parseDefectIds(title: string): Array<string>; | ||
private static _parseAll; | ||
} |
@@ -17,14 +17,2 @@ "use strict"; | ||
} | ||
/** | ||
* parses DefectIds from the passed in title. a DefectId | ||
* must be surrounded by square brackets and should take | ||
* the form of: | ||
* `some test <ID123> with multiple ids <Another>` where | ||
* `['ID123', 'Another']` would be returned | ||
* @param title the test full title to be parsed | ||
* @returns an array of DefectId strings or empty array | ||
*/ | ||
static parseDefectIds(title) { | ||
return this._parseAll(title, /\<([^\<\>]+)\>/gi); | ||
} | ||
static _parseAll(input, regex) { | ||
@@ -31,0 +19,0 @@ const results = new Array(); |
@@ -15,2 +15,3 @@ "use strict"; | ||
const sinon = require("sinon"); | ||
const aft_core_1 = require("aft-core"); | ||
describe('AftMochaReporter', () => { | ||
@@ -26,5 +27,5 @@ it('passes a Mocha Test to the test that can be used by AftLog', function () { | ||
(0, chai_1.expect)(t).to.exist; | ||
(0, chai_1.expect)(t.logMgr).to.exist; | ||
(0, chai_1.expect)(t.logMgr.logName).to.equal(t.fullTitle); | ||
yield t.logMgr.trace('sample log message'); | ||
(0, chai_1.expect)(t.reporter).to.exist; | ||
(0, chai_1.expect)(t.reporter.reporterName).to.equal(t.fullTitle); | ||
yield t.reporter.trace('sample log message'); | ||
}); | ||
@@ -47,9 +48,19 @@ }); | ||
(0, chai_1.expect)(t).to.exist; | ||
(0, chai_1.expect)(t.logMgr).to.exist; | ||
(0, chai_1.expect)(t.logMgr.logName).to.eql('AFT'); | ||
(0, chai_1.expect)(t.reporter).to.exist; | ||
(0, chai_1.expect)(t.reporter.reporterName).to.eql('AFT'); | ||
// NOTE: arrow functions have no `this` so `this.test.fullTitle` doesn't exist | ||
// expect(t.logMgr.logName).to.equal(t.fullTitle); | ||
yield t.logMgr.trace('sample log message from aft-mocha-reporter.spec with arrow function'); | ||
// expect(t.reporter.logName).to.equal(t.fullTitle); | ||
yield t.reporter.trace('sample log message from aft-mocha-reporter.spec with arrow function'); | ||
})); | ||
it('provides a Verifier instance for use in test control', function () { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.timeout(10000); | ||
const t = new src_1.AftTest(this); | ||
yield t.verify((v) => __awaiter(this, void 0, void 0, function* () { | ||
yield v.reporter.warn('returning logName'); | ||
return v.reporter.reporterName; | ||
})).returns((0, aft_core_1.equaling)(t.reporter.reporterName)); | ||
}); | ||
}); | ||
}); | ||
//# sourceMappingURL=aft-mocha-reporter.spec.js.map |
@@ -29,25 +29,3 @@ "use strict"; | ||
}); | ||
const ddata = [ | ||
{ title: '', expected: [] }, | ||
{ title: '<BUG-123>', expected: ['BUG-123'] }, | ||
{ title: 'foo <BUG-123>', expected: ['BUG-123'] }, | ||
{ title: '<BUG-123> foo', expected: ['BUG-123'] }, | ||
{ title: 'foo <BUG-123> foo', expected: ['BUG-123'] }, | ||
{ title: '<BUG-123> <BUG-234>', expected: ['BUG-123', 'BUG-234'] }, | ||
{ title: 'foo <BUG-123> <BUG-234>', expected: ['BUG-123', 'BUG-234'] }, | ||
{ title: '<BUG-123> foo <BUG-234>', expected: ['BUG-123', 'BUG-234'] }, | ||
{ title: '<BUG-123> <BUG-234> foo', expected: ['BUG-123', 'BUG-234'] }, | ||
{ title: 'foo <BUG-123> foo <BUG-234> foo', expected: ['BUG-123', 'BUG-234'] }, | ||
{ title: 'foo<BUG-123> foo<BUG-234>', expected: ['BUG-123', 'BUG-234'] }, | ||
{ title: 'foo<BUG-123><BUG-234>', expected: ['BUG-123', 'BUG-234'] }, | ||
{ title: '<BUG-123>foo <BUG-234>foo', expected: ['BUG-123', 'BUG-234'] }, | ||
{ title: 'Bug name 123', expected: [] }, | ||
{ title: 'foo [C1234] bar <BUG-123> baz', expected: ['BUG-123'] } | ||
]; | ||
ddata.forEach((d) => { | ||
it(`can parse defects from titles: '${d.title}'`, function () { | ||
expect(title_parser_1.TitleParser.parseDefectIds(d.title)).to.eql(d.expected); | ||
}); | ||
}); | ||
}); | ||
//# sourceMappingURL=title-parser.spec.js.map |
@@ -1,1 +0,1 @@ | ||
[["TitleParser can parse cases from titles: '[C1234]'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234"]}]],["TitleParser can parse cases from titles: 'foo [C1234]'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234"]}]],["TitleParser can parse cases from titles: '[C1234] foo'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234"]}]],["TitleParser can parse cases from titles: 'foo [C1234] foo'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234"]}]],["TitleParser can parse cases from titles: 'foo [C1234] bar <BUG-123> baz'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234"]}]],["TitleParser can parse defects from titles: 'foo [C1234] bar <BUG-123> baz'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234"]}]],["TitleParser can parse cases from titles: '[C1234] [C2345]'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"Passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: 'foo [C1234] [C2345]'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"Passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: '[C1234] foo [C2345]'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"Passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: '[C1234] [C2345] foo'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"Passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: 'foo [C1234] foo [C2345] foo'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"Passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: 'foo[C1234] foo[C2345]'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"Passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: 'foo[C1234][C2345]'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"Passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: '[C1234]foo [C2345]foo'",[{"testId":"C1234","status":"Passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"Passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: ''",[{"status":"Passed","logs":["pass - TitleParser can parse cases from titles: ''"]}]],["TitleParser can parse cases from titles: 'Case name 1234'",[{"status":"Passed","logs":["pass - TitleParser can parse cases from titles: 'Case name 1234'"]}]],["TitleParser can parse defects from titles: ''",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: ''"]}]],["TitleParser can parse defects from titles: '<BUG-123>'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: '<BUG-123>'"]}]],["TitleParser can parse defects from titles: 'foo <BUG-123>'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: 'foo <BUG-123>'"]}]],["TitleParser can parse defects from titles: '<BUG-123> foo'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: '<BUG-123> foo'"]}]],["TitleParser can parse defects from titles: 'foo <BUG-123> foo'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: 'foo <BUG-123> foo'"]}]],["TitleParser can parse defects from titles: '<BUG-123> <BUG-234>'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: '<BUG-123> <BUG-234>'"]}]],["TitleParser can parse defects from titles: 'foo <BUG-123> <BUG-234>'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: 'foo <BUG-123> <BUG-234>'"]}]],["TitleParser can parse defects from titles: '<BUG-123> foo <BUG-234>'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: '<BUG-123> foo <BUG-234>'"]}]],["TitleParser can parse defects from titles: '<BUG-123> <BUG-234> foo'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: '<BUG-123> <BUG-234> foo'"]}]],["TitleParser can parse defects from titles: 'foo <BUG-123> foo <BUG-234> foo'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: 'foo <BUG-123> foo <BUG-234> foo'"]}]],["TitleParser can parse defects from titles: 'foo<BUG-123> foo<BUG-234>'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: 'foo<BUG-123> foo<BUG-234>'"]}]],["TitleParser can parse defects from titles: 'foo<BUG-123><BUG-234>'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: 'foo<BUG-123><BUG-234>'"]}]],["TitleParser can parse defects from titles: '<BUG-123>foo <BUG-234>foo'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: '<BUG-123>foo <BUG-234>foo'"]}]],["TitleParser can parse defects from titles: 'Bug name 123'",[{"status":"Passed","logs":["pass - TitleParser can parse defects from titles: 'Bug name 123'"]}]],["AftMochaReporter passes a Mocha Test to the test that can be used by AftLog",[{"status":"Passed","logs":["pass - AftMochaReporter passes a Mocha Test to the test that can be used by AftLog"]}]],["AftMochaReporter can skip a test during execution",[{"status":"Skipped","logs":["warn - test skipped"]}]],["AftMochaReporter still works if using an arrow function",[{"status":"Passed","logs":["pass - AftMochaReporter still works if using an arrow function"]}]]] | ||
[["TitleParser can parse cases from titles: '[C1234]'",[{"testId":"C1234","status":"passed","logs":["pass - C1234"]}]],["TitleParser can parse cases from titles: 'foo [C1234]'",[{"testId":"C1234","status":"passed","logs":["pass - C1234"]}]],["TitleParser can parse cases from titles: '[C1234] foo'",[{"testId":"C1234","status":"passed","logs":["pass - C1234"]}]],["TitleParser can parse cases from titles: 'foo [C1234] foo'",[{"testId":"C1234","status":"passed","logs":["pass - C1234"]}]],["TitleParser can parse cases from titles: 'foo [C1234] bar <BUG-123> baz'",[{"testId":"C1234","status":"passed","logs":["pass - C1234"]}]],["AftMochaReporter provides a Verifier instance for use in test control",[{"status":"passed","logs":["warn - returning logName","pass - AftMochaReporter provides a Verifier instance for use in test control"]},{"status":"passed","logs":["pass - AftMochaReporter provides a Verifier instance for use in test control"]}]],["TitleParser can parse cases from titles: '[C1234] [C2345]'",[{"testId":"C1234","status":"passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: 'foo [C1234] [C2345]'",[{"testId":"C1234","status":"passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: '[C1234] foo [C2345]'",[{"testId":"C1234","status":"passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: '[C1234] [C2345] foo'",[{"testId":"C1234","status":"passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: 'foo [C1234] foo [C2345] foo'",[{"testId":"C1234","status":"passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: 'foo[C1234] foo[C2345]'",[{"testId":"C1234","status":"passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: 'foo[C1234][C2345]'",[{"testId":"C1234","status":"passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: '[C1234]foo [C2345]foo'",[{"testId":"C1234","status":"passed","logs":["pass - C1234","pass - C2345"]},{"testId":"C2345","status":"passed","logs":["pass - C1234","pass - C2345"]}]],["TitleParser can parse cases from titles: ''",[{"status":"passed","logs":["pass - TitleParser can parse cases from titles: ''"]}]],["TitleParser can parse cases from titles: 'Case name 1234'",[{"status":"passed","logs":["pass - TitleParser can parse cases from titles: 'Case name 1234'"]}]],["AftMochaReporter passes a Mocha Test to the test that can be used by AftLog",[{"status":"passed","logs":["pass - AftMochaReporter passes a Mocha Test to the test that can be used by AftLog"]}]],["AftMochaReporter can skip a test during execution",[{"status":"skipped","logs":["warn - test skipped"]}]],["AftMochaReporter still works if using an arrow function",[{"status":"passed","logs":["pass - AftMochaReporter still works if using an arrow function"]}]]] |
{ | ||
"name": "aft-mocha-reporter", | ||
"version": "9.0.0", | ||
"version": "10.0.0", | ||
"description": "Automated Functional Testing (AFT) Reporter for use with Mocha Test Framework", | ||
@@ -10,4 +10,4 @@ "main": "./dist/src/index.js", | ||
"build": "npm run clean && tsc --build", | ||
"test": "npm run build && mocha", | ||
"coverage": "nyc npm run test" | ||
"test": "npm run build && npx mocha", | ||
"coverage": "npm run build && nyc npx mocha" | ||
}, | ||
@@ -34,3 +34,3 @@ "repository": { | ||
"dependencies": { | ||
"aft-core": "^9.0.0", | ||
"aft-core": "^10.0.0", | ||
"mocha": "^10.0.0" | ||
@@ -42,4 +42,4 @@ }, | ||
"@types/sinon": "^10.0.12", | ||
"aft-logging-filesystem": "^9.0.0", | ||
"aft-logging-html": "^9.0.0", | ||
"aft-reporting-filesystem": "^10.0.0", | ||
"aft-reporting-html": "^10.0.0", | ||
"chai": "^4.3.6", | ||
@@ -52,3 +52,3 @@ "nyc": "^15.1.0", | ||
}, | ||
"gitHead": "3f91ae334e55378b543cfb0a24a28b224c25e2a9" | ||
"gitHead": "6287083181605ea01dc70b707ba39d21cac77771" | ||
} |
@@ -10,2 +10,3 @@ # AFT-Mocha-Reporter | ||
```json | ||
// .mocharc.json | ||
{ | ||
@@ -25,40 +26,41 @@ ... | ||
### `AftLog` | ||
the `AftLog` class provides access to an AFT `LogManager` instance for your currently executing spec file. you can use it like the following: | ||
the `AftLog` class provides access to an AFT `Reporter` instance for your currently executing spec file. you can use it like the following: | ||
> **!!WARNING!!** using arrow functions in your Spec definition **IS NOT SUPPORTED** if using `AftLog` because it removes the `this` scope | ||
```javascript | ||
describe('YourTestSuite', () => { | ||
it('allows you to log using AFT LogManager', async function() { | ||
it('allows you to log using AFT Reporter', async function() { | ||
const aft = new AftLog(this); | ||
await aft.logMgr.step('starting test...'); | ||
await aft.reporter.step('starting test...'); | ||
/* do some test things here */ | ||
await aft.logMgr.step('test is complete'); | ||
await aft.reporter.step('test is complete'); | ||
}); | ||
}); | ||
``` | ||
and which would output the following to your console and any AFT `LoggingPlugin` instances referenced in your `aftconfig.json` (assuming your test expectations all pass) | ||
and which would output the following to your console and any AFT `ReportingPlugin` instances referenced in your `aftconfig.json` (assuming your test expectations all pass) | ||
```text | ||
17:52:45 - [YourTestSuite allows you to log using AFT LogManager] - STEP - starting test... | ||
17:54:02 - [YourTestSuite allows you to log using AFT LogManager] - STEP - test is complete | ||
17:54:02 - [YourTestSuite allows you to log using AFT LogManager] - PASS - YourTestSuite allows you to log using AFT LogManager | ||
17:52:45 - [YourTestSuite allows you to log using AFT Reporter] - STEP - starting test... | ||
17:54:02 - [YourTestSuite allows you to log using AFT Reporter] - STEP - test is complete | ||
17:54:02 - [YourTestSuite allows you to log using AFT Reporter] - PASS - YourTestSuite allows you to log using AFT Reporter | ||
``` | ||
### `AftTest` | ||
the `AftTest` class extends from the `AftLog` adding the ability to parse the Spec name for any referenced Test or Defect IDs. each Test ID must be surrounded with square brackets `[ABC123]` and each Defect ID with less than and greater than symbols `<ABC123>`. additionally you can then call the `AftTest.shouldRun()` async function which will determine if your test should be run based on any AFT `TestCasePlugin` and `DefectPlugin` instances referenced in your `aftconfig.json` file. using the `AftTest` class would look like the following: | ||
the `AftTest` class extends from the `AftLog` adding the ability to parse the Spec name for any referenced Test. each Test ID must be surrounded with square brackets `[ABC123]`. you can then either directly call the `AftTest.shouldRun()` async function which will determine if your test should be run based on any AFT `TestExecutionPolicyPlugin` instances referenced in your `aftconfig.json` file or you can call `AftTest.verify(assertion)` which will perform the `AftTest.shouldRun()` call and mark the test as skipped if it should not be run. using the `AftTest` class would look like the following: | ||
> **!!WARNING!!** using arrow functions in your Spec definition **IS NOT SUPPORTED** if using `AftTest` because it removes the `this` scope | ||
```javascript | ||
describe('YourTestSuite', () => { | ||
it('can check if test [C1234] with known defect <BUG-123> should be run', async function() { | ||
it('can check if test [C1234] should be run', async function() { | ||
const aft = new AftTest(this); | ||
const shouldRun = await aft.shouldRun(); | ||
if (!shouldRun) { | ||
aft.test.skip(); | ||
} | ||
await aft.logMgr.error('we should never get here if C1234 should not be run or BUG-123 is open'); | ||
await aft.verify(async (v: Verifier) => { | ||
// `verify` calls `v.test.skip()` if should not be run | ||
await v.reporter.error('we should never get here if C1234 should not be run'); | ||
const result = await doStuff(); | ||
return result; | ||
}).returns(equaling('expected')); | ||
}); | ||
}); | ||
``` | ||
which would output the following to your console and any AFT `LoggingPlugin` instances referenced in your `aftconfig.json` if the test ID should not be run: | ||
which would output the following to your console and any AFT `ReportingPlugin` instances referenced in your `aftconfig.json` if the test ID should not be run: | ||
```text | ||
17:52:45 - [YourTestSuite can check if test [C1234] with known defect <BUG-123> should be run] - WARN - none of the supplied tests should be run: [C1234] | ||
17:52:45 - [YourTestSuite can check if test [C1234] with known defect <BUG-123> should be run] - WARN - test skipped | ||
17:52:45 - [YourTestSuite can check if test [C1234] should be run] - WARN - none of the supplied tests should be run: [C1234] | ||
17:52:45 - [YourTestSuite can check if test [C1234] should be run] - WARN - test skipped | ||
``` | ||
@@ -72,8 +74,5 @@ | ||
const aft = new AftTest(); | ||
await verify(() => { | ||
await aft.verify((v: Verifier) => { | ||
/* perform testing here */ | ||
}).withLogManager(aft.logMgr) | ||
.and.withTestIds(...aft.testcases) | ||
.and.withKnownDefectIds(...aft.defects) | ||
.returns(expected); | ||
}).returns(expected); | ||
``` |
@@ -1,10 +0,12 @@ | ||
import { FileSystemMap, LogManager } from "aft-core"; | ||
import { AftConfig, Reporter, aftConfig } from "aft-core"; | ||
export class AftLog { | ||
private _logMgr: LogManager; | ||
private _rep: Reporter; | ||
public readonly test: Mocha.Test; | ||
public readonly aftCfg: AftConfig; | ||
constructor(scope?: any) { | ||
constructor(scope?: any, aftCfg?: AftConfig) { | ||
this.test = scope?.test || {}; | ||
this.aftCfg = aftCfg ?? aftConfig; | ||
} | ||
@@ -20,12 +22,12 @@ | ||
get logMgr(): LogManager { | ||
if (!this._logMgr) { | ||
this._logMgr = new LogManager({logName: this.fullTitle}) | ||
get reporter(): Reporter { | ||
if (!this._rep) { | ||
this._rep = new Reporter(this.fullTitle, this.aftCfg); | ||
} | ||
return this._logMgr; | ||
return this._rep; | ||
} | ||
async dispose(): Promise<void> { | ||
await this.logMgr.dispose(); | ||
await this.reporter.dispose(); | ||
} | ||
} |
@@ -1,4 +0,3 @@ | ||
import { buildinfo, ProcessingResult, rand, TestResult, TestStatus } from "aft-core"; | ||
import { rand, TestResult, TestStatus, Err, AftConfig, BuildInfoManager, Func, Verifier, Class } from "aft-core"; | ||
import { AftLog } from "./aft-log"; | ||
import { shouldRun } from "./should-run"; | ||
import { TitleParser } from "./title-parser"; | ||
@@ -11,4 +10,4 @@ | ||
export class AftTest extends AftLog { | ||
private _testcases: Array<string>; | ||
private _defects: Array<string>; | ||
private readonly _testcases: Array<string>; | ||
private readonly _buildMgr: BuildInfoManager; | ||
@@ -20,22 +19,18 @@ /** | ||
*/ | ||
constructor(scope?: any) { | ||
super(scope); | ||
constructor(scope?: any, aftCfg?: AftConfig) { | ||
super(scope, aftCfg); | ||
this._buildMgr = new BuildInfoManager(this.aftCfg); | ||
this._testcases = TitleParser.parseTestIds(this.fullTitle); | ||
} | ||
/** | ||
* an array of test ID's parsed from the test title where test ID's | ||
* are expected to be in the surrounded by `[` and `]` like: `"[TESTID]"` | ||
*/ | ||
get testcases(): Array<string> { | ||
if (!this._testcases) { | ||
this._testcases = TitleParser.parseTestIds(this.fullTitle); | ||
} | ||
return this._testcases; | ||
} | ||
get defects(): Array<string> { | ||
if (!this._defects) { | ||
this._defects = TitleParser.parseDefectIds(this.fullTitle); | ||
} | ||
return this._defects; | ||
} | ||
async pass(): Promise<void> { | ||
await this._logResult('Passed'); | ||
await this._logResult('passed'); | ||
} | ||
@@ -46,27 +41,40 @@ | ||
const stack: string = (err.stack) ? `\n${err.stack}` : ''; | ||
await this._logResult('Failed', `${message}${stack}`); | ||
await this._logResult('failed', `${message}${stack}`); | ||
} | ||
async pending(): Promise<void> { | ||
await this._logResult('Skipped', 'test skipped'); | ||
await this._logResult('skipped', 'test skipped'); | ||
} | ||
/** | ||
* determines if any of the referenced Test Case ID's should be run according to the | ||
* loaded `TestExecutionPolicyPlugin` implementations' `shouldRun` methods | ||
* @returns `true` if test should be run, otherwise `false` | ||
*/ | ||
async shouldRun(): Promise<boolean> { | ||
let result: boolean = true; | ||
const shouldRun = await this._getVerifier(Verifier).shouldRun(); | ||
return shouldRun.result; | ||
} | ||
const should: Array<ProcessingResult> = await Promise.all([ | ||
shouldRun.tests(...this.testcases), | ||
shouldRun.defects(...this.defects) | ||
]).catch(async (err) => { | ||
await this.logMgr.warn(err); | ||
return []; | ||
}); | ||
if (should?.length) { | ||
if (!should.map(s => s.success).reduce((prev, curr) => prev && curr)) { | ||
result = false; | ||
await this.logMgr.warn(should.filter(s => !s.success).map(s => s.message).join('; ')); | ||
} | ||
} | ||
/** | ||
* creates a new {Verifier} that will run the passed in `assertion` if the `shouldRun` function | ||
* returns `true` otherwise it will bypass execution | ||
* @param assertion a function that performs test actions and will accept a {Verifier} instance | ||
* for use during the test actions' execution | ||
* @param verifierType an optional {Verifier} class to use instead of the base {Verifier} type | ||
* @returns a {Verifier} instance already configured with test cases, description, logger and config | ||
*/ | ||
verify<T extends Verifier>(assertion: Func<T, any>, verifierType?: Class<T>): T { | ||
return this._getVerifier<T>(verifierType) | ||
.verify(assertion) as T; | ||
} | ||
return result; | ||
protected _getVerifier<T extends Verifier>(verifierType?: Class<T>): T { | ||
verifierType ??= Verifier as Class<T>; | ||
return new verifierType() | ||
.internals.usingReporter(this.reporter) | ||
.internals.usingAftConfig(this.aftCfg) | ||
.withDescription(this.fullTitle) | ||
.withTestIds(...this.testcases) | ||
.on('skipped', () => this.test.skip()) as T; | ||
} | ||
@@ -76,9 +84,9 @@ | ||
* creates `ITestResult` objects for each `testId` and sends these | ||
* to the `LogManager.logResult` function | ||
* to the `Reporter.logResult` function | ||
* @param result an `IProcessingResult` returned from executing the | ||
* expectation | ||
*/ | ||
protected async _logResult(status: TestStatus, message?: string): Promise<void> { | ||
protected async _logResult(status: TestStatus, message?: string): Promise<void> { | ||
try { | ||
status = status || 'Untested'; | ||
status = status || 'untested'; | ||
if (this.testcases.length) { | ||
@@ -100,9 +108,9 @@ this.testcases.forEach(async (testId: string) => { | ||
try { | ||
await this.logMgr.logResult(result); | ||
await this.reporter.submitResult(result); | ||
} catch (e) { | ||
await this.logMgr.warn(`unable to log test result for test '${result.testId || result.resultId}' due to: ${e}`); | ||
await this.reporter.warn(`unable to log test result for test '${result.testId || result.resultId}' due to: ${Err.short(e)}`); | ||
} | ||
} | ||
} finally { | ||
await this.logMgr.dispose(); | ||
await this.reporter.dispose(); | ||
} | ||
@@ -112,16 +120,16 @@ } | ||
protected async _logMessage(status: TestStatus, message?: string): Promise<void> { | ||
message = message || this.logMgr.logName; | ||
message = message || this.reporter.reporterName; | ||
switch (status) { | ||
case 'Blocked': | ||
case 'Retest': | ||
case 'Skipped': | ||
case 'Untested': | ||
await this.logMgr.warn(message); | ||
case 'blocked': | ||
case 'retest': | ||
case 'skipped': | ||
case 'untested': | ||
await this.reporter.warn(message); | ||
break; | ||
case 'Failed': | ||
await this.logMgr.fail(message); | ||
case 'failed': | ||
await this.reporter.fail(message); | ||
break; | ||
case 'Passed': | ||
case 'passed': | ||
default: | ||
await this.logMgr.pass(message); | ||
await this.reporter.pass(message); | ||
break; | ||
@@ -148,2 +156,3 @@ } | ||
let result: TestResult = { | ||
testName: this.fullTitle, | ||
testId: testId, | ||
@@ -156,4 +165,4 @@ created: Date.now(), | ||
durationMs: this.test.duration, | ||
buildName: await buildinfo.buildName() || 'unknown', | ||
buildNumber: await buildinfo.buildNumber() || 'unknown' | ||
buildName: await this._buildMgr.buildName() || 'unknown', | ||
buildNumber: await this._buildMgr.buildNumber() || 'unknown' | ||
} | ||
@@ -160,0 +169,0 @@ }; |
@@ -15,15 +15,2 @@ export class TitleParser { | ||
/** | ||
* parses DefectIds from the passed in title. a DefectId | ||
* must be surrounded by square brackets and should take | ||
* the form of: | ||
* `some test <ID123> with multiple ids <Another>` where | ||
* `['ID123', 'Another']` would be returned | ||
* @param title the test full title to be parsed | ||
* @returns an array of DefectId strings or empty array | ||
*/ | ||
static parseDefectIds(title: string): Array<string> { | ||
return this._parseAll(title, /\<([^\<\>]+)\>/gi); | ||
} | ||
private static _parseAll(input: string, regex: RegExp): Array<string> { | ||
@@ -30,0 +17,0 @@ const results = new Array<string>(); |
import { expect } from "chai"; | ||
import { AftLog, AftTest } from "../src"; | ||
import * as sinon from "sinon"; | ||
import { Verifier, equaling } from "aft-core"; | ||
@@ -14,6 +15,6 @@ describe('AftMochaReporter', () => { | ||
expect(t).to.exist; | ||
expect(t.logMgr).to.exist; | ||
expect(t.logMgr.logName).to.equal(t.fullTitle); | ||
expect(t.reporter).to.exist; | ||
expect(t.reporter.reporterName).to.equal(t.fullTitle); | ||
await t.logMgr.trace('sample log message'); | ||
await t.reporter.trace('sample log message'); | ||
}); | ||
@@ -37,10 +38,19 @@ | ||
expect(t).to.exist; | ||
expect(t.logMgr).to.exist; | ||
expect(t.logMgr.logName).to.eql('AFT'); | ||
expect(t.reporter).to.exist; | ||
expect(t.reporter.reporterName).to.eql('AFT'); | ||
// NOTE: arrow functions have no `this` so `this.test.fullTitle` doesn't exist | ||
// expect(t.logMgr.logName).to.equal(t.fullTitle); | ||
// expect(t.reporter.logName).to.equal(t.fullTitle); | ||
await t.logMgr.trace('sample log message from aft-mocha-reporter.spec with arrow function'); | ||
await t.reporter.trace('sample log message from aft-mocha-reporter.spec with arrow function'); | ||
}); | ||
it('provides a Verifier instance for use in test control', async function() { | ||
this.timeout(10000); | ||
const t = new AftTest(this); | ||
await t.verify(async (v: Verifier) => { | ||
await v.reporter.warn('returning logName'); | ||
return v.reporter.reporterName; | ||
}).returns(equaling(t.reporter.reporterName)); | ||
}); | ||
}); |
@@ -28,25 +28,2 @@ import * as chai from 'chai'; | ||
}); | ||
const ddata = [ | ||
{title: '', expected: []}, | ||
{title: '<BUG-123>', expected: ['BUG-123']}, | ||
{title: 'foo <BUG-123>', expected: ['BUG-123']}, | ||
{title: '<BUG-123> foo', expected: ['BUG-123']}, | ||
{title: 'foo <BUG-123> foo', expected: ['BUG-123']}, | ||
{title: '<BUG-123> <BUG-234>', expected: ['BUG-123', 'BUG-234']}, | ||
{title: 'foo <BUG-123> <BUG-234>', expected: ['BUG-123', 'BUG-234']}, | ||
{title: '<BUG-123> foo <BUG-234>', expected: ['BUG-123', 'BUG-234']}, | ||
{title: '<BUG-123> <BUG-234> foo', expected: ['BUG-123', 'BUG-234']}, | ||
{title: 'foo <BUG-123> foo <BUG-234> foo', expected: ['BUG-123', 'BUG-234']}, | ||
{title: 'foo<BUG-123> foo<BUG-234>', expected: ['BUG-123', 'BUG-234']}, | ||
{title: 'foo<BUG-123><BUG-234>', expected: ['BUG-123', 'BUG-234']}, | ||
{title: '<BUG-123>foo <BUG-234>foo', expected: ['BUG-123', 'BUG-234']}, | ||
{title: 'Bug name 123', expected: []}, | ||
{title: 'foo [C1234] bar <BUG-123> baz', expected: ['BUG-123']} | ||
]; | ||
ddata.forEach((d) => { | ||
it(`can parse defects from titles: '${d.title}'`, function () { | ||
expect(TitleParser.parseDefectIds(d.title)).to.eql(d.expected); | ||
}); | ||
}); | ||
}); |
@@ -7,3 +7,8 @@ { | ||
}, | ||
"include": ["src", "test"] | ||
"include": ["src", "test"], | ||
"references": [ | ||
{ "path": "../aft-core" }, | ||
{ "path": "../aft-reporting-html" }, | ||
{ "path": "../aft-reporting-filesystem" } | ||
] | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
113817
58
828
75
+ Addedaft-core@10.3.0(transitive)
+ Addeddotenv@16.4.7(transitive)
+ Addeduuid@9.0.1(transitive)
- Removedaft-core@9.0.0(transitive)
- Removeduuid@8.3.2(transitive)
Updatedaft-core@^10.0.0