allure-jest
Version:
Allure Jest integration
364 lines (360 loc) • 16.3 kB
JavaScript
var _excluded = ["resultsDir"];
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 _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
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); }
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
import { relative, sep } from "node:path";
import { env } from "node:process";
import * as allure from "allure-js-commons";
import { Stage, Status } from "allure-js-commons";
import { serialize } from "allure-js-commons/sdk";
import { extractMetadataFromString, getMessageAndTraceFromError, getStatusFromError } from "allure-js-commons/sdk";
import { ReporterRuntime, createDefaultWriter, getEnvironmentLabels, getFrameworkLabel, getHostLabel, getLanguageLabel, getPackageLabel, getPosixPath, getSuiteLabels, getThreadLabel, parseTestPlan } from "allure-js-commons/sdk/reporter";
import { setGlobalTestRuntime } from "allure-js-commons/sdk/runtime";
import { AllureJestTestRuntime } from "./AllureJestTestRuntime.js";
import { getTestId, getTestPath, isTestPresentInTestPlan, last, shouldHookBeSkipped } from "./utils.js";
var createJestEnvironment = Base => {
var _Class_brand;
// @ts-expect-error (ts(2545)) Incorrect assumption about a mixin class: https://github.com/microsoft/TypeScript/issues/37142
return _Class_brand = /*#__PURE__*/new WeakSet(), class extends Base {
// config is AllureJestConfig in Jest v28 or greater. In older versions
// it's AllureJestProjectConfig. See https://github.com/jestjs/jest/pull/12461
constructor(config, context) {
super(config, context);
_classPrivateMethodInitSpec(this, _Class_brand);
_defineProperty(this, "testPath", void 0);
_defineProperty(this, "testPlan", void 0);
_defineProperty(this, "runtime", void 0);
_defineProperty(this, "runContext", {
executables: [],
steps: [],
scopes: [],
skippedTestsFullNamesByTestPlan: []
});
_defineProperty(this, "handleTestEvent", event => {
switch (event.name) {
case "hook_start":
_assertClassBrand(_Class_brand, this, _handleHookStart).call(this, event.hook);
break;
case "hook_success":
_assertClassBrand(_Class_brand, this, _handleHookPass).call(this, event.hook);
break;
case "hook_failure":
_assertClassBrand(_Class_brand, this, _handleHookFail).call(this, event.hook, event.error);
break;
case "run_describe_start":
_assertClassBrand(_Class_brand, this, _handleSuiteStart).call(this);
break;
case "run_describe_finish":
_assertClassBrand(_Class_brand, this, _handleSuiteEnd).call(this);
break;
case "test_start":
_assertClassBrand(_Class_brand, this, _handleTestScopeStart).call(this);
break;
case "test_fn_start":
_assertClassBrand(_Class_brand, this, _handleTestStart).call(this, event.test);
break;
case "test_fn_success":
_assertClassBrand(_Class_brand, this, _handleTestPass).call(this, event.test);
break;
case "test_fn_failure":
_assertClassBrand(_Class_brand, this, _handleTestFail).call(this, event.test);
break;
case "test_done":
_assertClassBrand(_Class_brand, this, _handleTestScopeStop).call(this, event.test);
break;
case "test_skip":
_assertClassBrand(_Class_brand, this, _handleTestSkip).call(this, event.test);
break;
case "test_todo":
_assertClassBrand(_Class_brand, this, _handleTestTodo).call(this, event.test);
break;
case "run_finish":
_assertClassBrand(_Class_brand, this, _handleRunFinish).call(this);
break;
default:
break;
}
});
var projectConfig = "projectConfig" in config ? config.projectConfig : config;
var _ref = (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.testEnvironmentOptions) || {},
{
resultsDir
} = _ref,
restConfig = _objectWithoutProperties(_ref, _excluded);
this.runtime = new ReporterRuntime(_objectSpread(_objectSpread({}, restConfig), {}, {
writer: createDefaultWriter({
resultsDir
})
}));
this.testPath = relative(projectConfig.rootDir, context.testPath);
this.testPlan = parseTestPlan();
// @ts-ignore
var testRuntime = new AllureJestTestRuntime(this, this.global);
// @ts-ignore
this.global.allure = allure;
setGlobalTestRuntime(testRuntime);
}
setup() {
return super.setup();
}
teardown() {
return super.teardown();
}
handleAllureRuntimeMessage(message) {
var executableUuid = last(this.runContext.executables);
this.runtime.applyRuntimeMessages(executableUuid, [message]);
}
};
function _getTestFullName(test) {
var testTitle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : test.name;
var newTestSuitePath = getTestPath(test.parent);
var newTestPath = newTestSuitePath.concat(testTitle);
var newTestId = getTestId(newTestPath);
return "".concat(getPosixPath(this.testPath), "#").concat(newTestId);
}
function _handleSuiteStart() {
_assertClassBrand(_Class_brand, this, _startScope).call(this);
}
function _handleSuiteEnd() {
_assertClassBrand(_Class_brand, this, _stopScope).call(this);
}
function _handleHookStart(hook) {
if (shouldHookBeSkipped(hook)) {
return;
}
var scopeUuid = last(this.runContext.scopes);
var fixtureUuid = this.runtime.startFixture(scopeUuid, /after/i.test(hook.type) ? "after" : "before", {
name: hook.type
});
this.runContext.executables.push(fixtureUuid);
}
function _handleHookPass(hook) {
if (shouldHookBeSkipped(hook)) {
return;
}
var fixtureUuid = this.runContext.executables.pop();
this.runtime.updateFixture(fixtureUuid, r => {
r.status = Status.PASSED;
r.stage = Stage.FINISHED;
});
this.runtime.stopFixture(fixtureUuid);
}
function _handleHookFail(hook, error) {
if (shouldHookBeSkipped(hook)) {
return;
}
var fixtureUuid = this.runContext.executables.pop();
var status = typeof error === "string" ? Status.BROKEN : getStatusFromError(error);
this.runtime.updateFixture(fixtureUuid, r => {
r.status = status;
r.statusDetails = {
message: typeof error === "string" ? error : error.message,
trace: typeof error === "string" ? undefined : error.stack
};
r.stage = Stage.FINISHED;
});
this.runtime.stopFixture(fixtureUuid);
}
function _handleTestStart(test) {
var _test$startedAt;
var fsPath = this.testPath.split(sep);
var newTestSuitePath = getTestPath(test.parent);
var titlePath = fsPath.concat(newTestSuitePath);
var {
cleanTitle,
labels,
links
} = extractMetadataFromString(test.name);
var newTestFullName = _assertClassBrand(_Class_brand, this, _getTestFullName).call(this, test, cleanTitle);
if (this.testPlan && !isTestPresentInTestPlan(newTestFullName, this.testPlan)) {
test.mode = "skip";
this.runContext.skippedTestsFullNamesByTestPlan.push(newTestFullName);
return;
}
var testUuid = this.runtime.startTest({
name: cleanTitle,
fullName: newTestFullName,
start: (_test$startedAt = test.startedAt) !== null && _test$startedAt !== void 0 ? _test$startedAt : undefined,
stage: Stage.RUNNING,
labels: [getLanguageLabel(), getFrameworkLabel("jest"), getPackageLabel(this.testPath), getHostLabel(), getThreadLabel(env.JEST_WORKER_ID), ...getEnvironmentLabels(), ...getSuiteLabels(newTestSuitePath), ...labels],
titlePath,
links
}, this.runContext.scopes);
this.runContext.executables.push(testUuid);
return testUuid;
}
function _handleTestScopeStart() {
_assertClassBrand(_Class_brand, this, _startScope).call(this);
}
function _handleTestScopeStop(test) {
var testUuid = this.runContext.executables.pop();
if (testUuid) {
var _tr, _tr2;
var {
details
} = _assertClassBrand(_Class_brand, this, _statusAndDetails).call(this, test.errors);
var tr;
this.runtime.updateTest(testUuid, result => {
tr = result;
});
// hook failure, finish as skipped
if (((_tr = tr) === null || _tr === void 0 ? void 0 : _tr.status) === undefined && ((_tr2 = tr) === null || _tr2 === void 0 ? void 0 : _tr2.stage) === Stage.RUNNING) {
this.runtime.updateTest(testUuid, result => {
result.stage = Stage.FINISHED;
result.status = Status.SKIPPED;
result.statusDetails = _objectSpread(_objectSpread({}, result.statusDetails), details);
});
}
this.runtime.writeTest(testUuid);
}
_assertClassBrand(_Class_brand, this, _stopScope).call(this);
}
function _startScope() {
var scopeUuid = this.runtime.startScope();
this.runContext.scopes.push(scopeUuid);
}
function _stopScope() {
var scopeUuid = this.runContext.scopes.pop();
if (!scopeUuid) {
return;
}
this.runtime.writeScope(scopeUuid);
}
function _handleTestPass(test) {
var _test$duration;
var testUuid = _assertClassBrand(_Class_brand, this, _currentExecutable).call(this);
if (!testUuid) {
return;
}
// @ts-ignore
var {
suppressedErrors = []
} = this.global.expect.getState();
var statusAndDetails = _assertClassBrand(_Class_brand, this, _statusAndDetails).call(this, suppressedErrors);
this.runtime.updateTest(testUuid, result => {
result.stage = Stage.FINISHED;
result.status = statusAndDetails.status;
result.statusDetails = _objectSpread(_objectSpread({}, result.statusDetails), statusAndDetails.details);
});
this.runtime.stopTest(testUuid, {
duration: (_test$duration = test.duration) !== null && _test$duration !== void 0 ? _test$duration : 0
});
}
function _handleTestFail(test) {
var _test$duration2;
var testUuid = _assertClassBrand(_Class_brand, this, _currentExecutable).call(this);
if (!testUuid) {
return;
}
var {
status,
details
} = _assertClassBrand(_Class_brand, this, _statusAndDetails).call(this, test.errors);
this.runtime.updateTest(testUuid, result => {
result.stage = Stage.FINISHED;
result.status = status;
result.statusDetails = _objectSpread(_objectSpread({}, result.statusDetails), details);
});
this.runtime.stopTest(testUuid, {
duration: (_test$duration2 = test.duration) !== null && _test$duration2 !== void 0 ? _test$duration2 : 0
});
}
function _handleTestSkip(test) {
var newTestFullName = _assertClassBrand(_Class_brand, this, _getTestFullName).call(this, test);
if (this.runContext.skippedTestsFullNamesByTestPlan.includes(newTestFullName)) {
return;
}
// noinspection JSPotentiallyInvalidUsageOfThis
var testUuid = _assertClassBrand(_Class_brand, this, _handleTestStart).call(this, test);
if (!testUuid) {
return;
}
this.runtime.updateTest(testUuid, result => {
result.stage = Stage.FINISHED;
result.status = Status.SKIPPED;
});
// noinspection JSPotentiallyInvalidUsageOfThis
_assertClassBrand(_Class_brand, this, _handleTestScopeStop).call(this, test);
}
function _handleTestTodo(test) {
// noinspection JSPotentiallyInvalidUsageOfThis
var testUuid = _assertClassBrand(_Class_brand, this, _handleTestStart).call(this, test);
if (!testUuid) {
return;
}
this.runtime.updateTest(testUuid, result => {
result.stage = Stage.FINISHED;
result.status = Status.SKIPPED;
result.statusDetails = {
message: "TODO"
};
});
// noinspection JSPotentiallyInvalidUsageOfThis
_assertClassBrand(_Class_brand, this, _handleTestScopeStop).call(this, test);
}
function _handleRunFinish() {
this.runtime.writeEnvironmentInfo();
this.runtime.writeCategoriesDefinitions();
}
function _currentExecutable() {
if (this.runContext.executables.length === 0) {
return undefined;
}
return this.runContext.executables[this.runContext.executables.length - 1];
}
function _statusAndDetails(errors) {
if (errors.length === 0) {
return {
status: Status.PASSED,
details: {}
};
}
// jest collects all errors, but we need to report the first one because it's a reason why the test has been failed
var [error] = errors;
var hasMultipleErrors = Array.isArray(error);
var exception = hasMultipleErrors ? error[0] : error;
var firstError = _assertClassBrand(_Class_brand, this, _convertToError).call(this, exception);
// in case user throws non-Error type, the first exception is the user-thrown object,
// while the second one is provided by jest and has correct stack trace
if (hasMultipleErrors && error.length > 1) {
var secondError = _assertClassBrand(_Class_brand, this, _convertToError).call(this, error[1]);
if (!firstError.message) {
firstError.message = secondError.message;
}
if (!firstError.stack) {
firstError.stack = secondError.stack;
}
}
var details = getMessageAndTraceFromError(firstError);
var status = getStatusFromError(firstError);
return {
status,
details
};
}
function _convertToError(exception) {
if (!exception) {
return {};
}
// user may throw an object as well
if (typeof exception !== "object" || !("stack" in exception)) {
return {
message: serialize(exception)
};
}
var prototypeDescriptors = Object.getOwnPropertyDescriptors(Object.getPrototypeOf(exception));
var protoClone = Object.create(null, prototypeDescriptors);
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
var clone = Object.create(protoClone, Object.getOwnPropertyDescriptors(exception));
return clone;
}
};
export { createJestEnvironment };
//# sourceMappingURL=environmentFactory.js.map