@wdio/junit-reporter
Advanced tools
Comparing version 5.18.0 to 5.18.3
@@ -23,3 +23,3 @@ "use strict"; | ||
onRunnerEnd(runner) { | ||
const xml = this.prepareXml(runner); | ||
const xml = this.buildJunitXml(runner); | ||
this.write(xml); | ||
@@ -32,43 +32,50 @@ } | ||
prepareXml(runner) { | ||
const builder = _junitReportBuilder.default.newBuilder(); | ||
addFailedHooks(suite) { | ||
const failedHooks = suite.hooks.filter(hook => hook.error && (hook.title === '"before all" hook' || hook.title === '"after all" hook')); | ||
failedHooks.forEach(hook => { | ||
const { | ||
title, | ||
_duration, | ||
error, | ||
state | ||
} = hook; | ||
suite.tests.push({ | ||
_duration, | ||
title, | ||
error, | ||
state, | ||
output: [] | ||
}); | ||
}); | ||
return suite; | ||
} | ||
const packageName = this.options.packageName ? `${runner.sanitizedCapabilities}-${this.options.packageName}` : runner.sanitizedCapabilities; | ||
addCucumberFeatureToBuilder(builder, runner, specFileName, suite) { | ||
const featureName = this.prepareName(suite.title); | ||
for (let suiteKey of Object.keys(this.suites)) { | ||
if (suiteKey.match(/^"before all"/)) { | ||
continue; | ||
} | ||
if (suite.type === 'feature') { | ||
const feature = builder.testSuite().name(featureName).timestamp(suite.start).time(suite._duration / 1000).property('specId', 0).property(this.suiteTitleLabel, suite.title).property('capabilities', runner.sanitizedCapabilities).property(this.fileNameLabel, specFileName.replace(process.cwd(), '.')); | ||
this.activeFeature = feature; | ||
this.activeFeatureName = featureName; | ||
} else if (this.activeFeature) { | ||
let scenario = suite; | ||
const testName = this.prepareName(suite.title); | ||
const testCase = this.activeFeature.testCase().className(`${this.packageName}.${this.activeFeatureName}`).name(`${this.activeFeatureName}.${testName}`).time(scenario._duration / 1000); | ||
scenario = this.addFailedHooks(scenario); | ||
let stepsOutput = ''; | ||
let isFailing = false; | ||
const specFileName = runner.specs[0]; | ||
const suite = this.suites[suiteKey]; | ||
const suiteName = this.prepareName(suite.title); | ||
const testSuite = builder.testSuite().name(suiteName).timestamp(suite.start).time(suite._duration / 1000).property('specId', 0).property('suiteName', suite.title).property('capabilities', runner.sanitizedCapabilities).property('file', specFileName.replace(process.cwd(), '.')); | ||
const failedHooks = suite.hooks.filter(hook => hook.error && (hook.title === '"before all" hook' || hook.title === '"after all" hook')); | ||
failedHooks.forEach(hook => { | ||
const { | ||
title, | ||
_duration, | ||
error, | ||
state | ||
} = hook; | ||
suite.tests.push({ | ||
_duration, | ||
title, | ||
error, | ||
state, | ||
output: [] | ||
}); | ||
}); | ||
for (let stepKey of Object.keys(scenario.tests)) { | ||
if (stepKey !== 'undefined') { | ||
let stepEmoji = '✅'; | ||
const step = scenario.tests[stepKey]; | ||
for (let testKey of Object.keys(suite.tests)) { | ||
if (testKey !== 'undefined') { | ||
const test = suite.tests[testKey]; | ||
const testName = this.prepareName(test.title); | ||
const testCase = testSuite.testCase().className(`${packageName}.${suiteName}`).name(testName).time(test._duration / 1000); | ||
if (step.state === 'pending' || step.state === 'skipped') { | ||
if (!isFailing) { | ||
testCase.skipped(); | ||
} | ||
if (test.state === 'pending' || test.state === 'skipped') { | ||
testCase.skipped(); | ||
} else if (test.state === 'failed') { | ||
if (test.error) { | ||
stepEmoji = '⚠️'; | ||
} else if (step.state === 'failed') { | ||
if (step.error) { | ||
if (this.options.errorOptions) { | ||
@@ -78,20 +85,97 @@ const errorOptions = this.options.errorOptions; | ||
for (const key of Object.keys(errorOptions)) { | ||
testCase[key](test.error[errorOptions[key]]); | ||
testCase[key](step.error[errorOptions[key]]); | ||
} | ||
} else { | ||
testCase.error(test.error.message); | ||
testCase.error(step.error.message); | ||
} | ||
testCase.standardError(`\n${test.error.stack}\n`); | ||
testCase.standardError(`\n${step.error.stack}\n`); | ||
} else { | ||
testCase.error(); | ||
} | ||
isFailing = true; | ||
stepEmoji = '❗'; | ||
} | ||
const output = this.getStandardOutput(test); | ||
if (output) testCase.standardOutput(`\n${output}\n`); | ||
const output = this.getStandardOutput(step); | ||
stepsOutput += output ? stepEmoji + ' ' + step.title : stepEmoji + ' ' + step.title + '\n' + output; | ||
} | ||
} | ||
testCase.standardOutput(`\n${stepsOutput}\n`); | ||
} | ||
return builder; | ||
} | ||
addSuiteToBuilder(builder, runner, specFileName, suite) { | ||
const suiteName = this.prepareName(suite.title); | ||
let testSuite = builder.testSuite().name(suiteName).timestamp(suite.start).time(suite._duration / 1000).property('specId', 0).property(this.suiteTitleLabel, suite.title).property('capabilities', runner.sanitizedCapabilities).property(this.fileNameLabel, specFileName.replace(process.cwd(), '.')); | ||
suite = this.addFailedHooks(suite); | ||
for (let testKey of Object.keys(suite.tests)) { | ||
if (testKey !== 'undefined') { | ||
const test = suite.tests[testKey]; | ||
const testName = this.prepareName(test.title); | ||
const testCase = testSuite.testCase().className(`${this.packageName}.${suiteName}`).name(testName).time(test._duration / 1000); | ||
if (test.state === 'pending' || test.state === 'skipped') { | ||
testCase.skipped(); | ||
} else if (test.state === 'failed') { | ||
if (test.error) { | ||
if (this.options.errorOptions) { | ||
const errorOptions = this.options.errorOptions; | ||
for (const key of Object.keys(errorOptions)) { | ||
testCase[key](test.error[errorOptions[key]]); | ||
} | ||
} else { | ||
testCase.error(test.error.message); | ||
} | ||
testCase.standardError(`\n${test.error.stack}\n`); | ||
} else { | ||
testCase.error(); | ||
} | ||
} | ||
const output = this.getStandardOutput(test); | ||
if (output) testCase.standardOutput(`\n${output}\n`); | ||
} | ||
} | ||
return builder; | ||
} | ||
buildJunitXml(runner) { | ||
let builder = _junitReportBuilder.default.newBuilder(); | ||
this.packageName = this.options.packageName ? `${runner.sanitizedCapabilities}-${this.options.packageName}` : runner.sanitizedCapabilities; | ||
this.isCucumberFrameworkRunner = runner.config.framework === 'cucumber'; | ||
if (this.isCucumberFrameworkRunner) { | ||
this.packageName = `CucumberJUnitReport-${this.packageName}`; | ||
this.suiteTitleLabel = 'featureName'; | ||
this.fileNameLabel = 'featureFile'; | ||
} else { | ||
this.suiteTitleLabel = 'suiteName'; | ||
this.fileNameLabel = 'file'; | ||
} | ||
for (let suiteKey of Object.keys(this.suites)) { | ||
if (suiteKey.match(/^"before all"/)) { | ||
continue; | ||
} | ||
const specFileName = runner.specs[0]; | ||
const suite = this.suites[suiteKey]; | ||
if (this.isCucumberFrameworkRunner) { | ||
builder = this.addCucumberFeatureToBuilder(builder, runner, specFileName, suite); | ||
} else { | ||
builder = this.addSuiteToBuilder(builder, runner, specFileName, suite); | ||
} | ||
} | ||
return builder.build(); | ||
@@ -98,0 +182,0 @@ } |
{ | ||
"name": "@wdio/junit-reporter", | ||
"version": "5.18.0", | ||
"version": "5.18.3", | ||
"description": "A WebdriverIO reporter that creates Jenkins compatible XML based JUnit reports", | ||
@@ -49,3 +49,3 @@ "author": "Christian Bromann <christian@saucelabs.com>", | ||
}, | ||
"gitHead": "ced463759829bf15175f9c6d4561515cb09401dc" | ||
"gitHead": "802e2ad7e62094451d142abb05a301780e07b985" | ||
} |
17893
215