allure-cucumberjs
Version:
Allure Cucumber.JS integration
478 lines (475 loc) • 21.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _cucumber = require("@cucumber/cucumber");
var _messages = require("@cucumber/messages");
var _nodePath = require("node:path");
var _allureJsCommons = require("allure-js-commons");
var _sdk = require("allure-js-commons/sdk");
var _reporter = require("allure-js-commons/sdk/reporter");
var _legacy = require("./legacy.js");
var _utils = require("./utils.js");
var _excluded = ["resultsDir", "links", "labels"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
class AllureCucumberReporter extends _cucumber.Formatter {
constructor(options) {
super(options);
_defineProperty(this, "afterHooks", {});
_defineProperty(this, "beforeHooks", {});
_defineProperty(this, "linksConfigs", {});
_defineProperty(this, "labelsConfigs", []);
_defineProperty(this, "allureRuntime", void 0);
_defineProperty(this, "documentMap", new Map());
_defineProperty(this, "scenarioMap", new Map());
_defineProperty(this, "stepMap", new Map());
_defineProperty(this, "testStepMap", new Map());
_defineProperty(this, "pickleStepMap", new Map());
_defineProperty(this, "pickleMap", new Map());
_defineProperty(this, "testCaseMap", new Map());
_defineProperty(this, "testCaseStartedMap", new Map());
_defineProperty(this, "testResultUuids", new Map());
_defineProperty(this, "scopeUuids", new Map());
_defineProperty(this, "fixtureUuids", new Map());
var _ref = options.parsedArgvOptions,
{
resultsDir,
links,
labels
} = _ref,
rest = _objectWithoutProperties(_ref, _excluded);
this.allureRuntime = new _reporter.ReporterRuntime(_objectSpread({
writer: (0, _reporter.createDefaultWriter)({
resultsDir
}),
links
}, rest));
this.linksConfigs = links || {};
this.labelsConfigs = labels || [];
options.eventBroadcaster.on("envelope", this.parseEnvelope.bind(this));
this.beforeHooks = options.supportCodeLibrary.beforeTestCaseHookDefinitions.reduce((acc, hook) => Object.assign(acc, {
[hook.id]: hook
}), {});
this.afterHooks = options.supportCodeLibrary.afterTestCaseHookDefinitions.reduce((acc, hook) => Object.assign(acc, {
[hook.id]: hook
}), {});
// set AllureCucumberWorld for single thread mode
if (options.supportCodeLibrary.World === _cucumber.World) {
// @ts-ignore
// noinspection JSConstantReassignment
options.supportCodeLibrary.World = _legacy.AllureCucumberWorld;
}
}
get tagsIgnorePatterns() {
var {
labelsConfigs,
linksConfigs
} = this;
var linkConfigEntries = Object.entries(linksConfigs).map(_ref2 => {
var [, v] = _ref2;
return v;
});
return [...labelsConfigs, ...linkConfigEntries].flatMap(_ref3 => {
var {
pattern
} = _ref3;
return pattern;
});
}
parseEnvelope(envelope) {
switch (true) {
case !!envelope.gherkinDocument:
this.onGherkinDocument(envelope.gherkinDocument);
break;
case !!envelope.pickle:
this.onPickle(envelope.pickle);
break;
case !!envelope.testCase:
this.onTestCase(envelope.testCase);
break;
case !!envelope.testCaseStarted:
this.onTestCaseStarted(envelope.testCaseStarted);
break;
case !!envelope.testCaseFinished:
this.onTestCaseFinished(envelope.testCaseFinished);
break;
case !!envelope.attachment:
this.onAttachment(envelope.attachment);
break;
case !!envelope.testStepStarted:
this.onTestStepStarted(envelope.testStepStarted);
break;
case !!envelope.testStepFinished:
this.onTestStepFinished(envelope.testStepFinished);
break;
case !!envelope.testRunFinished:
this.onTestRunFinished();
break;
}
}
parseTagsLabels(tags) {
var labels = [];
if (this.labelsConfigs.length === 0) {
return labels;
}
this.labelsConfigs.forEach(matcher => {
var matchedTags = tags.filter(tag => matcher.pattern.some(pattern => pattern.test(tag.name)));
var matchedLabels = matchedTags.map(tag => {
var tagValue = tag.name.replace(/^@\S+:/, "");
return {
name: matcher.name,
value: tagValue
};
});
labels.push(...matchedLabels);
});
return labels;
}
parsePickleTags(tags) {
return tags.filter(tag => !this.tagsIgnorePatterns.some(pattern => pattern.test(tag.name))).map(tag => ({
name: _allureJsCommons.LabelName.TAG,
value: tag.name
}));
}
parseTagsLinks(tags) {
var tagKeyRe = /^@\S+=/;
var links = [];
if (Object.keys(this.linksConfigs).length === 0) {
return links;
}
Object.entries(this.linksConfigs).forEach(_ref4 => {
var [type, matcher] = _ref4;
var matchedTags = tags.filter(tag => matcher.pattern.some(pattern => pattern.test(tag.name)));
var matchedLinks = matchedTags.map(tag => {
var tagValue = tag.name.replace(tagKeyRe, "");
return {
url: (0, _reporter.applyLinkTemplate)(matcher.urlTemplate, tagValue) || tagValue,
type
};
});
links.push(...matchedLinks);
});
return links;
}
parseStatus(stepResult) {
var error = this.exceptionToError(stepResult.message, stepResult.exception);
switch (stepResult.status) {
case _messages.TestStepResultStatus.FAILED:
return error ? (0, _sdk.getStatusFromError)(error) : _allureJsCommons.Status.FAILED;
case _messages.TestStepResultStatus.PASSED:
return _allureJsCommons.Status.PASSED;
case _messages.TestStepResultStatus.SKIPPED:
case _messages.TestStepResultStatus.PENDING:
return _allureJsCommons.Status.SKIPPED;
default:
return undefined;
}
}
onRule(data) {
var _data$children;
(_data$children = data.children) === null || _data$children === void 0 || _data$children.forEach(c => {
if (c.scenario) {
this.onScenario(c.scenario);
}
});
}
onGherkinDocument(data) {
var _data$feature;
if (data.uri) {
this.documentMap.set(data.uri, data);
}
(_data$feature = data.feature) === null || _data$feature === void 0 || (_data$feature = _data$feature.children) === null || _data$feature === void 0 || _data$feature.forEach(c => {
if (c.rule) {
this.onRule(c.rule);
} else if (c.scenario) {
this.onScenario(c.scenario);
}
});
}
onScenario(data) {
this.scenarioMap.set(data.id, data);
data.steps.forEach(step => this.stepMap.set(step.id, step));
}
onPickle(data) {
this.pickleMap.set(data.id, data);
data.steps.forEach(ps => this.pickleStepMap.set(ps.id, ps));
}
onTestCase(data) {
this.testCaseMap.set(data.id, data);
data.testSteps.forEach(ts => this.testStepMap.set(ts.id, ts));
}
onTestCaseStarted(data) {
var _scenario$name,
_doc$feature,
_doc$feature2,
_doc$feature3,
_doc$feature4,
_this = this;
var testCase = this.testCaseMap.get(data.testCaseId);
var pickle = this.pickleMap.get(testCase.pickleId);
var doc = this.documentMap.get(pickle.uri);
var [scenarioId, ...astIds] = pickle.astNodeIds;
var scenario = this.scenarioMap.get(scenarioId);
var posixPath = (0, _utils.getPosixPathRelativeToProjectRoot)(pickle);
var fullName = "".concat(posixPath, "#").concat(pickle.name);
var testCaseId = (0, _reporter.md5)("".concat(posixPath, "#").concat((_scenario$name = scenario === null || scenario === void 0 ? void 0 : scenario.name) !== null && _scenario$name !== void 0 ? _scenario$name : pickle.name));
var result = {
name: pickle.name,
description: ((scenario === null || scenario === void 0 ? void 0 : scenario.description) || (doc === null || doc === void 0 || (_doc$feature = doc.feature) === null || _doc$feature === void 0 ? void 0 : _doc$feature.description) || "").trim(),
labels: [],
links: [],
start: _messages.TimeConversion.timestampToMillisecondsSinceEpoch(data.timestamp),
testCaseId,
fullName
};
result.labels.push(...(0, _reporter.getEnvironmentLabels)());
result.labels.push((0, _reporter.getLanguageLabel)(), (0, _reporter.getFrameworkLabel)("cucumberjs"), (0, _reporter.getPackageLabel)((0, _utils.getPathRelativeToProjectRoot)(pickle)), (0, _reporter.getHostLabel)(), (0, _reporter.getThreadLabel)(data.workerId));
if (doc !== null && doc !== void 0 && doc.feature) {
result.labels.push({
name: _allureJsCommons.LabelName.FEATURE,
value: doc.feature.name
});
}
var pickleLabels = this.parsePickleTags(pickle.tags || []);
var featureLabels = this.parseTagsLabels((doc === null || doc === void 0 || (_doc$feature2 = doc.feature) === null || _doc$feature2 === void 0 ? void 0 : _doc$feature2.tags) || []);
var featureLinks = this.parseTagsLinks((doc === null || doc === void 0 || (_doc$feature3 = doc.feature) === null || _doc$feature3 === void 0 ? void 0 : _doc$feature3.tags) || []);
var scenarioLabels = this.parseTagsLabels((scenario === null || scenario === void 0 ? void 0 : scenario.tags) || []);
var scenarioLinks = this.parseTagsLinks((scenario === null || scenario === void 0 ? void 0 : scenario.tags) || []);
// remove feature file name from the title path
result.titlePath = posixPath.split("/").slice(0, -1).concat([doc === null || doc === void 0 || (_doc$feature4 = doc.feature) === null || _doc$feature4 === void 0 ? void 0 : _doc$feature4.name].filter(Boolean));
result.labels.push(...featureLabels, ...scenarioLabels, ...pickleLabels);
result.links.push(...featureLinks, ...scenarioLinks);
var scopeUuid = this.allureRuntime.startScope();
this.scopeUuids.set(data.id, scopeUuid);
var testUuid = this.allureRuntime.startTest(result, [scopeUuid]);
this.testResultUuids.set(data.id, testUuid);
this.testCaseStartedMap.set(data.id, data);
if (!(scenario !== null && scenario !== void 0 && scenario.examples)) {
return;
}
var _loop = function _loop() {
var _example$tableHeader, _example$tableBody;
var exampleName = example !== null && example !== void 0 && example.name ? "Examples: ".concat(example.name) : "Examples";
var parameterNames = example === null || example === void 0 || (_example$tableHeader = example.tableHeader) === null || _example$tableHeader === void 0 ? void 0 : _example$tableHeader.cells.map(cell => cell.value);
var csvDataTableHeader = (parameterNames === null || parameterNames === void 0 ? void 0 : parameterNames.join(",")) || "";
var currentRow = example === null || example === void 0 || (_example$tableBody = example.tableBody) === null || _example$tableBody === void 0 ? void 0 : _example$tableBody.find(tb => astIds.includes(tb.id));
if (currentRow) {
var parameters = currentRow.cells.map((cell, index) => {
var paramName = parameterNames && parameterNames.length > index ? parameterNames[index] : "arg".concat(index);
var paramValue = cell.value;
return {
name: paramName,
value: paramValue
};
});
_this.allureRuntime.updateTest(testUuid, tr => tr.parameters = [...tr.parameters, ...parameters]);
}
var csvDataTableBody = (example === null || example === void 0 ? void 0 : example.tableBody.map(row => row.cells.map(cell => cell.value).join(",")).join("\n")) || "";
if (!csvDataTableHeader && !csvDataTableBody) {
return 1; // continue
}
var csvDataTable = "".concat(csvDataTableHeader, "\n").concat(csvDataTableBody, "\n");
_this.allureRuntime.writeAttachment(testUuid, null, exampleName, Buffer.from(csvDataTable, "utf-8"), {
contentType: _allureJsCommons.ContentType.CSV,
fileExtension: ".csv"
});
};
for (var example of scenario.examples) {
if (_loop()) continue;
}
}
onTestCaseFinished(data) {
var testUuid = this.testResultUuids.get(data.testCaseStartedId);
if (!testUuid) {
return;
}
this.allureRuntime.updateTest(testUuid, result => {
var _step$status;
var step = (0, _reporter.getWorstTestStepResult)(result.steps);
result.status = (_step$status = step === null || step === void 0 ? void 0 : step.status) !== null && _step$status !== void 0 ? _step$status : _allureJsCommons.Status.PASSED;
result.stage = _allureJsCommons.Stage.FINISHED;
if (step) {
if (step.status === undefined) {
result.statusDetails = {
message: "The test doesn't have an implementation."
};
} else {
result.statusDetails = _objectSpread(_objectSpread({}, result.statusDetails), step.statusDetails);
}
}
});
this.allureRuntime.stopTest(testUuid, {
stop: _messages.TimeConversion.timestampToMillisecondsSinceEpoch(data.timestamp)
});
this.allureRuntime.writeTest(testUuid);
this.testResultUuids.delete(data.testCaseStartedId);
var scopeUuid = this.scopeUuids.get(data.testCaseStartedId);
if (scopeUuid) {
this.allureRuntime.writeScope(scopeUuid);
this.scopeUuids.delete(data.testCaseStartedId);
}
}
onTestStepStarted(data) {
var _stepPickle$argument;
var testUuid = this.testResultUuids.get(data.testCaseStartedId);
var step = this.testStepMap.get(data.testStepId);
if (step.hookId) {
var scopeUuid = this.scopeUuids.get(data.testCaseStartedId);
if (!scopeUuid) {
return;
}
var beforeHook = step.hookId && this.beforeHooks[step.hookId];
var afterHook = step.hookId && this.afterHooks[step.hookId];
var type = beforeHook ? "before" : afterHook ? "after" : undefined;
if (!type) {
return;
}
var name = beforeHook ? beforeHook.name : afterHook ? afterHook.name : "hook";
if (name === "ALLURE_FIXTURE_IGNORE") {
return;
}
var fixtureUuid = this.allureRuntime.startFixture(scopeUuid, type, {
name,
stage: _allureJsCommons.Stage.RUNNING,
start: _messages.TimeConversion.timestampToMillisecondsSinceEpoch(data.timestamp)
});
if (fixtureUuid) {
this.fixtureUuids.set(data.testCaseStartedId, fixtureUuid);
}
return;
}
if (!step.pickleStepId) {
return;
}
var stepPickle = this.pickleStepMap.get(step.pickleStepId);
if (!stepPickle) {
return;
}
var stepKeyword = stepPickle.astNodeIds.map(astNodeId => this.stepMap.get(astNodeId)).map(stepAstNode => stepAstNode === null || stepAstNode === void 0 ? void 0 : stepAstNode.keyword).find(keyword => keyword !== undefined) || "";
var stepUuid = this.allureRuntime.startStep(testUuid, undefined, _objectSpread(_objectSpread({}, (0, _reporter.createStepResult)()), {}, {
name: "".concat(stepKeyword).concat(stepPickle.text),
start: _messages.TimeConversion.timestampToMillisecondsSinceEpoch(data.timestamp)
}));
if (!((_stepPickle$argument = stepPickle.argument) !== null && _stepPickle$argument !== void 0 && _stepPickle$argument.dataTable)) {
return;
}
var csvDataTable = stepPickle.argument.dataTable.rows.reduce((acc, row) => "".concat(acc + row.cells.map(cell => cell.value).join(","), "\n"), "");
this.allureRuntime.writeAttachment(testUuid, stepUuid, "Data table", Buffer.from(csvDataTable, "utf-8"), {
contentType: _allureJsCommons.ContentType.CSV,
fileExtension: ".csv"
});
}
onTestStepFinished(data) {
var step = this.testStepMap.get(data.testStepId);
if (!step) {
return;
}
var status = this.parseStatus(data.testStepResult);
var stage = status !== _allureJsCommons.Status.SKIPPED ? _allureJsCommons.Stage.FINISHED : _allureJsCommons.Stage.PENDING;
var error = this.exceptionToError(data.testStepResult.message, data.testStepResult.exception);
if (step.hookId) {
var fixtureUuid = this.fixtureUuids.get(data.testCaseStartedId);
if (!fixtureUuid) {
return;
}
this.allureRuntime.updateFixture(fixtureUuid, r => {
r.stage = stage;
r.status = status;
if (error) {
r.statusDetails = _objectSpread(_objectSpread({}, r.statusDetails), (0, _sdk.getMessageAndTraceFromError)(error));
}
});
this.allureRuntime.stopFixture(fixtureUuid, {
stop: _messages.TimeConversion.timestampToMillisecondsSinceEpoch(data.timestamp)
});
this.fixtureUuids.delete(data.testCaseStartedId);
return;
}
var testUuid = this.testResultUuids.get(data.testCaseStartedId);
var currentStep = this.allureRuntime.currentStep(testUuid);
if (!currentStep) {
return;
}
this.allureRuntime.updateStep(currentStep, r => {
r.status = status;
r.stage = stage;
if (status === undefined) {
r.statusDetails = {
message: "The step doesn't have an implementation."
};
return;
}
if (error) {
r.statusDetails = _objectSpread(_objectSpread({}, r.statusDetails), (0, _sdk.getMessageAndTraceFromError)(error));
}
});
this.allureRuntime.stopStep(currentStep, {
stop: _messages.TimeConversion.timestampToMillisecondsSinceEpoch(data.timestamp)
});
}
onAttachment(message) {
var _message$fileName;
if (!message.testCaseStartedId) {
return;
}
var fixtureUuid = this.fixtureUuids.get(message.testCaseStartedId);
var testUuid = this.testResultUuids.get(message.testCaseStartedId);
var rootUuid = fixtureUuid !== null && fixtureUuid !== void 0 ? fixtureUuid : testUuid;
if (!rootUuid) {
return;
}
if (message.mediaType === "application/vnd.allure.skipcucumber+json") {
if (testUuid) {
this.allureRuntime.updateTest(testUuid, result => {
result.labels.push({
name: "ALLURE_TESTPLAN_SKIP",
value: "true"
});
});
}
return;
}
if (message.mediaType === _reporter.ALLURE_RUNTIME_MESSAGE_CONTENT_TYPE) {
var parsedMessage = JSON.parse(message.body);
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
this.allureRuntime.applyRuntimeMessages(rootUuid, Array.isArray(parsedMessage) ? parsedMessage : [parsedMessage]);
return;
}
var encoding = message.contentEncoding === _messages.AttachmentContentEncoding.BASE64 ? "base64" : "utf-8";
this.allureRuntime.applyRuntimeMessages(rootUuid, [{
type: "attachment_content",
data: {
name: (_message$fileName = message.fileName) !== null && _message$fileName !== void 0 ? _message$fileName : "Attachment",
content: Buffer.from(message.body, encoding).toString("base64"),
encoding: "base64",
contentType: message.mediaType,
fileExtension: message.fileName ? (0, _nodePath.extname)(message.fileName) : undefined,
wrapInStep: true
}
}]);
}
onTestRunFinished() {
this.allureRuntime.writeCategoriesDefinitions();
this.allureRuntime.writeEnvironmentInfo();
}
exceptionToError(message, exception) {
if (!exception) {
return;
}
return {
message: message !== null && message !== void 0 ? message : exception.message,
stack: exception.stackTrace,
name: exception.type
};
}
}
exports.default = AllureCucumberReporter;
module.exports = exports.default;
//# sourceMappingURL=reporter.js.map