UNPKG

allure-jest

Version:
403 lines (394 loc) 18.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createJestEnvironment = void 0; var _nodePath = require("node:path"); var _nodeProcess = require("node:process"); var _allureJsCommons = _interopRequireWildcard(require("allure-js-commons")); var allure = _allureJsCommons; var _sdk = require("allure-js-commons/sdk"); var _reporter = require("allure-js-commons/sdk/reporter"); var _runtime = require("allure-js-commons/sdk/runtime"); var _AllureJestTestRuntime = require("./AllureJestTestRuntime.js"); var _utils = require("./utils.js"); var _excluded = ["resultsDir"]; function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } 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"); } 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) { var _this$handleTestEvent; 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: [] }); var handleTestEvent = (_this$handleTestEvent = this.handleTestEvent) === null || _this$handleTestEvent === void 0 ? void 0 : _this$handleTestEvent.bind(this); // Preserve any event handler defined by the base or custom environment. this.handleTestEvent = (event, state) => { var handleAllureEvent = () => _assertClassBrand(_Class_brand, this, _handleTestEvent).call(this, event, state); // Keep Allure's lifecycle in sync even if the custom environment fails, // then rethrow the original error so Jest keeps its native behavior. try { var result = handleTestEvent === null || handleTestEvent === void 0 ? void 0 : handleTestEvent(event, state); if ((0, _sdk.isPromise)(result)) { return Promise.resolve(result).finally(handleAllureEvent); } } catch (error) { handleAllureEvent(); throw error; } handleAllureEvent(); }; 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 _reporter.ReporterRuntime(_objectSpread(_objectSpread({}, restConfig), {}, { writer: (0, _reporter.createDefaultWriter)({ resultsDir }) })); this.testPath = (0, _nodePath.relative)(projectConfig.rootDir, context.testPath); this.testPlan = (0, _reporter.parseTestPlan)(); // @ts-ignore var testRuntime = new _AllureJestTestRuntime.AllureJestTestRuntime(this, this.global); // @ts-ignore this.global.allure = allure; (0, _runtime.setGlobalTestRuntime)(testRuntime); } setup() { return super.setup(); } teardown() { return super.teardown(); } handleAllureRuntimeMessage(message) { var executableUuid = (0, _utils.last)(this.runContext.executables); if (executableUuid) { this.runtime.applyRuntimeMessages(executableUuid, [message]); } else { this.runtime.applyGlobalRuntimeMessages([message]); } } }; function _handleTestEvent(event, _state) { 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; } } function _getTestFullName(test) { var testTitle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : test.name; var newTestSuitePath = (0, _utils.getTestPath)(test.parent); var newTestPath = newTestSuitePath.concat(testTitle); var newTestId = (0, _utils.getTestId)(newTestPath); var projectName = (0, _reporter.getProjectName)(); var fullNamePath = (0, _reporter.getPosixPath)(this.testPath); var fullNameBase = projectName ? "".concat(projectName, ":").concat(fullNamePath) : fullNamePath; return "".concat(fullNameBase, "#").concat(newTestId); } function _handleSuiteStart() { _assertClassBrand(_Class_brand, this, _startScope).call(this); } function _handleSuiteEnd() { _assertClassBrand(_Class_brand, this, _stopScope).call(this); } function _handleHookStart(hook) { if ((0, _utils.shouldHookBeSkipped)(hook)) { return; } var scopeUuid = (0, _utils.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 ((0, _utils.shouldHookBeSkipped)(hook)) { return; } var fixtureUuid = this.runContext.executables.pop(); this.runtime.updateFixture(fixtureUuid, r => { r.status = _allureJsCommons.Status.PASSED; r.stage = _allureJsCommons.Stage.FINISHED; }); this.runtime.stopFixture(fixtureUuid); } function _handleHookFail(hook, error) { if ((0, _utils.shouldHookBeSkipped)(hook)) { return; } var fixtureUuid = this.runContext.executables.pop(); var status = typeof error === "string" ? _allureJsCommons.Status.BROKEN : (0, _sdk.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 = _allureJsCommons.Stage.FINISHED; }); this.runtime.stopFixture(fixtureUuid); } function _handleTestStart(test) { var _test$startedAt; var fsPath = this.testPath.split(_nodePath.sep); var newTestSuitePath = (0, _utils.getTestPath)(test.parent); var projectName = (0, _reporter.getProjectName)(); var baseTitlePath = fsPath.concat(newTestSuitePath); var titlePath = projectName ? [projectName, ...baseTitlePath] : baseTitlePath; var { cleanTitle, labels, links } = (0, _sdk.extractMetadataFromString)(test.name); var legacyTestId = (0, _utils.getTestId)(newTestSuitePath.concat(cleanTitle)); var legacyFullName = "".concat((0, _reporter.getPosixPath)(this.testPath), "#").concat(legacyTestId); var newTestFullName = _assertClassBrand(_Class_brand, this, _getTestFullName).call(this, test, cleanTitle); if (this.testPlan && !(0, _reporter.includedInTestPlan)(this.testPlan, { fullName: newTestFullName, tags: [test.name] })) { 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: _allureJsCommons.Stage.RUNNING, labels: [(0, _reporter.getLanguageLabel)(), (0, _reporter.getFrameworkLabel)("jest"), (0, _reporter.getPackageLabel)(this.testPath), (0, _reporter.getFallbackTestCaseIdLabel)((0, _reporter.md5)(legacyFullName)), (0, _reporter.getHostLabel)(), (0, _reporter.getThreadLabel)(_nodeProcess.env.JEST_WORKER_ID), ...(0, _reporter.getEnvironmentLabels)(), ...(0, _reporter.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 { status, details } = _assertClassBrand(_Class_brand, this, _statusAndDetails).call(this, test.errors); var tr; this.runtime.updateTest(testUuid, result => { tr = result; }); // hook failure, finish with the status reported by Jest if (((_tr = tr) === null || _tr === void 0 ? void 0 : _tr.status) === undefined && ((_tr2 = tr) === null || _tr2 === void 0 ? void 0 : _tr2.stage) === _allureJsCommons.Stage.RUNNING) { this.runtime.updateTest(testUuid, result => { result.stage = _allureJsCommons.Stage.FINISHED; result.status = status; 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 = _allureJsCommons.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 = _allureJsCommons.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 = _allureJsCommons.Stage.FINISHED; result.status = _allureJsCommons.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 = _allureJsCommons.Stage.FINISHED; result.status = _allureJsCommons.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: _allureJsCommons.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 = (0, _sdk.getMessageAndTraceFromError)(firstError); var status = (0, _sdk.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: (0, _sdk.serialize)(exception) }; } return exception; } }; exports.createJestEnvironment = createJestEnvironment; //# sourceMappingURL=environmentFactory.js.map