jest-allure2-reporter
Version:
Idiomatic Jest reporter for Allure Framework
253 lines • 11.7 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.JestAllure2Reporter = void 0;
const tslib_1 = require("tslib");
const node_path_1 = tslib_1.__importDefault(require("node:path"));
const reporter_1 = tslib_1.__importDefault(require("jest-metadata/reporter"));
const options_1 = require("../options");
const metadata_1 = require("../metadata");
const utils_1 = require("../utils");
const logger_1 = require("../logger");
const fallbacks = tslib_1.__importStar(require("./fallbacks"));
const postProcessMetadata_1 = require("./postProcessMetadata");
const allureCommons_1 = require("./allureCommons");
const resolveTestItem_1 = require("./resolveTestItem");
const NOT_INITIALIZED = null;
const __TID = (0, logger_1.optimizeForTracing)((test) => ({
tid: ['jest-allure2-reporter', test ? test.path : 'run'],
}));
const __TID_NAME = (0, logger_1.optimizeForTracing)((test, testCaseResult) => ({
tid: ['jest-allure2-reporter', test.path],
fullName: testCaseResult.fullName,
}));
class JestAllure2Reporter extends reporter_1.default {
_globalConfig;
_options;
_globalContext = NOT_INITIALIZED;
_writer = NOT_INITIALIZED;
_config = NOT_INITIALIZED;
_globalMetadataProxy = NOT_INITIALIZED;
_taskQueue = new utils_1.DeferredTaskQueue({
getThreadName: (item) => item.test.path,
getPayloadKey: (item) => item.testInvocationMetadata,
execute: (item) => logger_1.log.trace.complete(__TID_NAME(item.test, item.testCaseResult), item.testCaseResult.title, () => this.#writeTestResult(item)),
});
constructor(globalConfig, options) {
super(globalConfig);
this._globalConfig = globalConfig;
this._options = options;
}
async #init() {
this._config = await (0, options_1.resolveOptions)(this._globalConfig.rootDir, this._options);
this._writer = await (0, options_1.resolveWriter)(this._globalConfig.rootDir, this._config);
await this._writer.init?.();
const testRunMetadata = _a.query.globalMetadata();
this._globalMetadataProxy = new metadata_1.AllureMetadataProxy(testRunMetadata);
this._globalMetadataProxy.set('config', {
resultsDir: this._config.resultsDir,
overwrite: this._config.overwrite,
attachments: this._config.attachments,
injectGlobals: this._config.injectGlobals,
});
}
async #attempt(name, function_) {
try {
await function_.call(this);
}
catch (error) {
logger_1.log.error(error, `Caught unhandled error in JestAllure2Reporter#${name}`);
}
}
async #attemptSync(name, function_) {
try {
function_.call(this);
}
catch (error) {
logger_1.log.error(error, `Caught unhandled error in JestAllure2Reporter#${name}`);
}
}
async onRunStart(aggregatedResult, options) {
await super.onRunStart(aggregatedResult, options);
const attemptRunStart = this.#attempt.bind(this, 'onRunStart()', this.#onRunStart);
logger_1.log.trace.begin(__TID(), 'jest-allure2-reporter');
await logger_1.log.trace.complete(__TID(), 'init', this.#init.bind(this));
await logger_1.log.trace.complete(__TID(), 'onRunStart', attemptRunStart);
}
async #onRunStart() {
const reporterConfig = this._config;
const allureWriter = this._writer;
const globalContext = {
$: {},
globalConfig: this._globalConfig,
reporterConfig,
value: undefined,
};
globalContext.$ = await (0, resolveTestItem_1.resolvePromisedItem)(globalContext, reporterConfig.helpers, '$');
if (reporterConfig.sourceCode.enabled) {
const { factories, options, plugins } = reporterConfig.sourceCode;
const maybePlugins = await Promise.all(Object.entries(factories).map(async ([key, factory]) => factory({
...globalContext,
value: options[key],
})));
plugins.push(...(0, utils_1.compactArray)(maybePlugins));
}
this._globalContext = globalContext;
const environment = await reporterConfig.environment(globalContext);
if (environment) {
await allureWriter.writeEnvironmentInfo((0, utils_1.stringifyValues)(environment));
}
const executor = await reporterConfig.executor(globalContext);
if (executor) {
await allureWriter.writeExecutorInfo(executor);
}
const categories = await reporterConfig.categories(globalContext);
if (categories) {
await allureWriter.writeCategories(categories);
}
}
async onTestFileStart(test) {
super.onTestFileStart(test);
const execute = this.#onTestFileStart.bind(this, test);
const attempt = this.#attemptSync.bind(this, 'onTestFileStart()', execute);
const testPath = node_path_1.default.relative(this._globalConfig.rootDir, test.path);
logger_1.log.trace.begin(__TID(test), testPath);
await logger_1.log.trace.complete(__TID(test), 'onTestFileStart', attempt);
}
async #onTestFileStart(test) {
await utils_1.FileNavigatorCache.instance.scanSourcemap(test.path);
const rawMetadata = _a.query.test(test);
const testFileMetadata = new metadata_1.AllureMetadataProxy(rawMetadata);
fallbacks.onTestFileStart(test, testFileMetadata);
}
onTestCaseStart(test, testCaseResult) {
super.onTestCaseStart(test, testCaseResult);
this._taskQueue.startPending(test.path);
}
onTestCaseResult(test, testCaseResult) {
super.onTestCaseResult(test, testCaseResult);
const testEntryMetadata = _a.query.testCaseResult(testCaseResult);
const testInvocationMetadata = testEntryMetadata.lastInvocation;
fallbacks.onTestCaseResult(test, testCaseResult, new metadata_1.AllureMetadataProxy(testInvocationMetadata));
this._taskQueue.enqueue({
test,
testCaseResult,
testInvocationMetadata,
});
}
async #writeTestResult({ test, testCaseResult, testInvocationMetadata }) {
await this.#scanSourceMaps(test.path);
await (0, postProcessMetadata_1.postProcessMetadata)(this._globalContext, testInvocationMetadata);
const squasher = new metadata_1.MetadataSquasher();
const testCaseContext = {
...this._globalContext,
filePath: node_path_1.default.relative(this._globalConfig.rootDir, test.path).split(node_path_1.default.sep),
result: {},
testCase: testCaseResult,
testCaseMetadata: squasher.testInvocation(testInvocationMetadata),
testFileMetadata: squasher.testFile(testInvocationMetadata.file),
testRunMetadata: this._globalMetadataProxy.get(),
value: undefined,
};
const allureTest = await (0, resolveTestItem_1.resolvePromisedTestCase)(testCaseContext, this._config.testCase);
if (!allureTest) {
return;
}
const invocationIndex = testInvocationMetadata.definition.invocations.indexOf(testInvocationMetadata);
await (0, allureCommons_1.writeTest)({
resultsDir: this._config.resultsDir,
containerName: `${testCaseResult.fullName} (${invocationIndex})`,
writer: this._writer,
test: allureTest,
});
}
async onTestFileResult(test, testResult, aggregatedResult) {
super.onTestFileResult(test, testResult, aggregatedResult);
const execute = this.#onTestFileResult.bind(this, test, testResult);
const attempt = this.#attempt.bind(this, 'onTestFileResult()', execute);
await logger_1.log.trace.complete(__TID(test), 'onTestFileResult', attempt);
logger_1.log.trace.end(__TID(test));
}
async #onTestFileResult(test, testResult) {
const rawMetadata = _a.query.test(test);
const testFileMetadata = new metadata_1.AllureMetadataProxy(rawMetadata);
fallbacks.onTestFileResult(test, testFileMetadata);
for (const testCaseResult of testResult.testResults) {
const invocations = _a.query.testCaseResult(testCaseResult).invocations || [];
for (const testInvocationMetadata of invocations) {
this._taskQueue.enqueue({
test,
testCaseResult,
testInvocationMetadata,
});
}
}
await this._taskQueue.awaitCompletion();
const config = this._config;
const squasher = new metadata_1.MetadataSquasher();
const globalMetadataProxy = this._globalMetadataProxy;
const testFileContext = {
...this._globalContext,
filePath: node_path_1.default.relative(this._globalConfig.rootDir, testResult.testFilePath).split(node_path_1.default.sep),
result: {},
testFile: testResult,
testFileMetadata: squasher.testFile(_a.query.testResult(testResult)),
testRunMetadata: globalMetadataProxy.get(),
value: undefined,
};
const allureFileTest = await (0, resolveTestItem_1.resolvePromisedTestCase)(testFileContext, config.testFile);
if (allureFileTest) {
await (0, allureCommons_1.writeTest)({
resultsDir: config.resultsDir,
containerName: `${testResult.testFilePath}`,
writer: this._writer,
test: allureFileTest,
});
}
}
async onRunComplete(testContexts, aggregatedResult) {
await super.onRunComplete(testContexts, aggregatedResult);
const execute = this.#onRunComplete.bind(this, aggregatedResult);
const attempt = this.#attempt.bind(this, 'onRunComplete()', execute);
await logger_1.log.trace.complete(__TID(), 'onRunComplete', attempt);
await logger_1.log.trace.end(__TID());
}
async #onRunComplete(aggregatedResult) {
const globalMetadataProxy = this._globalMetadataProxy;
globalMetadataProxy.set('stop', Date.now());
const allureWriter = this._writer;
const config = this._config;
const globalContext = this._globalContext;
const testRunContext = {
...globalContext,
aggregatedResult,
result: {},
testRunMetadata: globalMetadataProxy.get(),
value: undefined,
};
const allureRunTest = await (0, resolveTestItem_1.resolvePromisedTestCase)(testRunContext, config.testRun);
if (allureRunTest) {
await (0, allureCommons_1.writeTest)({
resultsDir: config.resultsDir,
containerName: `Test Run (${process.pid})`,
writer: allureWriter,
test: allureRunTest,
});
}
await allureWriter.cleanup?.();
}
// Executing this once per file should be enough to scan source maps of auxiliary files
#scanSourceMaps = (0, utils_1.memoize)(async (_testPath) => {
const globalMetadataProxy = this._globalMetadataProxy;
const loadedFiles = globalMetadataProxy
.get('loadedFiles', [])
.filter(utils_1.FileNavigatorCache.instance.hasScannedSourcemap);
if (loadedFiles.length === 0) {
return;
}
return Promise.all(loadedFiles.map(utils_1.FileNavigatorCache.instance.scanSourcemap));
});
}
exports.JestAllure2Reporter = JestAllure2Reporter;
_a = JestAllure2Reporter;
//# sourceMappingURL=JestAllure2Reporter.js.map