UNPKG

playwright-trx-reporter

Version:

TRX reporter for playwright

209 lines (208 loc) 8.16 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MultiTrxsBuilder = exports.SingleTrxBuilder = void 0; const fs_1 = __importDefault(require("fs")); const TestRunBuilder_1 = require("./TestRunBuilder"); const trxModel_1 = require("./trxModel"); const assert_1 = require("./assert"); const utils_1 = require("./utils"); function mergeAllSuitesToTestRunBuilder(testRunsBuilder, suite, options) { for (const projectSuite of suite.suites) { for (const fileSuite of projectSuite.suites) { mergeFileOrGroupSuite(testRunsBuilder, fileSuite, options); } } } function mergeFileOrGroupSuite(testRunsBuilder, suite, options) { if (suite.allTests().length === 0) { return; } suite.tests.forEach((test) => { mergeTestCase(testRunsBuilder, test, options); }); suite.suites.forEach((subSuite) => { mergeFileOrGroupSuite(testRunsBuilder, subSuite, options); }); } function mergeTestCase(testRunsBuilder, test, options) { const { ownerAnnotation, priorityAnnotation } = options; const trxUnitTestResults = buildTrxUnitTestResultByPwTestCase(test); // TODO: use `formatTestTitle`? // remove root title, which is just empty // remove current test name const classNameForJs = test.titlePath().slice(1).slice(0, -1).join(TestRunBuilder_1.NAME_SPLITTER); const owner = getFromAnnotationByType(test.annotations, ownerAnnotation); const priority = Number(getFromAnnotationByType(test.annotations, priorityAnnotation)) || undefined; trxUnitTestResults.forEach((trxResult, index) => { const testRunBuilder = testRunsBuilder.getOrCreateTestRunBuilder(index); testRunBuilder.addTestResult(trxResult, { testDefinitionAdditionalInfo: { owner, priority, fileLocation: test.location.file, className: classNameForJs, }, }); }); } function buildTrxUnitTestResultByPwTestCase(test) { // TODO: assert test.results is sorted by retry index. return test.results.map((result) => buildTrxUnitTestResultByPwTestResult(test, result)); } // TODO: copy from playwright implementation, so that it would be easy to migrate function formatMs2TimeSpanString(ms) { return new Date(ms).toISOString().slice(11, 23); } function buildTrxUnitTestResultByPwTestResult(test, result) { const endTime = new Date(result.startTime); endTime.setMilliseconds(result.startTime.getMilliseconds() + result.duration); const unitTestResult = new trxModel_1.UnitTestResultType({ $computerName: utils_1.computerName, $testId: (0, utils_1.convertPwId2Uuid)(test.id), $testListId: TestRunBuilder_1.RESULT_NOT_IN_A_LIST_ID, $testName: test.titlePath().slice(1).join(TestRunBuilder_1.NAME_SPLITTER), $testType: trxModel_1.UNIT_TEST_TYPE, $duration: formatMs2TimeSpanString(result.duration), $startTime: result.startTime.toISOString(), $endTime: endTime.toISOString(), $executionId: (0, utils_1.createUuid)(), $outcome: pwOutcome2TrxOutcome(result.status), }); bindAttachment(unitTestResult, test, result); bindOutput(unitTestResult, test, result); return unitTestResult; } function bindOutput(unitTestResult, test, result) { var _a, _b; // TODO: in which condition errors will have multi errors? // the test catch the error? let errorInfoMessage; let errorInfoStackTrace; if ((_a = result.error) === null || _a === void 0 ? void 0 : _a.stack) { const { stack } = result.error; const firstStackLine = stack.indexOf('\n at '); errorInfoMessage = `${stack.slice(0, firstStackLine)}`; errorInfoStackTrace = `\n${(_b = result.error.snippet) !== null && _b !== void 0 ? _b : ''}\n${stack.slice(firstStackLine)}`; } const stdOutString = getStringFromStdStream(result.stdout); const stdErrString = getStringFromStdStream(result.stderr); const errorInfo = (errorInfoMessage || errorInfoStackTrace) ? { Message: errorInfoMessage, StackTrace: errorInfoStackTrace, } : undefined; if (stdOutString || stdErrString || errorInfo) { unitTestResult.Output = { StdOut: stdOutString, StdErr: stdErrString, ErrorInfo: errorInfo, }; } } function bindAttachment(unitTestResult, test, result) { const attachmentPaths = []; for (const attachment of result.attachments) { const attachmentPath = attachment.path; if (attachmentPath) { if (fs_1.default.existsSync(attachmentPath)) { attachmentPaths.push(attachmentPath); } else { console.warn(`File path "${attachmentPath}" is not found for Attachment "${attachment.name}"`); } } } if (attachmentPaths.length !== 0) { unitTestResult.ResultFiles = { ResultFile: attachmentPaths.map((p) => ({ $path: p })), }; } } function getStringFromStdStream(stdStream) { return stdStream.map((i) => i.toString()).join(); } function pwOutcome2TrxOutcome(outcome) { switch (outcome) { case 'failed': return trxModel_1.TestOutcome.Failed; case 'interrupted': return trxModel_1.TestOutcome.Aborted; case 'passed': return trxModel_1.TestOutcome.Passed; case 'timedOut': return trxModel_1.TestOutcome.Timeout; case 'skipped': return trxModel_1.TestOutcome.NotExecuted; default: (0, assert_1.assertNever)(outcome); } } function getFromAnnotationByType(annotations, type) { for (let index = annotations.length - 1; index >= 0; index -= 1) { const annotation = annotations[index]; if (annotation.type === type) { return annotation.description; } } } function createDummyTestRunBuilderOption(options) { return Object.assign(Object.assign({}, options), { id: (0, utils_1.createUuid)(), startTime: (new Date()).toISOString(), endTime: (new Date()).toISOString() }); } class SingleTrxWriterTestRunsBuilder { constructor(_options) { this._options = _options; this._builders = []; } getOrCreateTestRunBuilder(testResultIndex) { if (!this._builders[0]) { const finalOption = this._options; const newBuilder = new TestRunBuilder_1.TestRunBuilder(finalOption); this._builders[0] = newBuilder; } return this._builders[0]; } build() { return this._builders.map((b) => b.build()); } } class MultiTrxWriterTestRunsBuilder { constructor(_options) { this._options = _options; this._builders = []; } getOrCreateTestRunBuilder(testResultIndex) { if (!this._builders[testResultIndex]) { const finalOption = testResultIndex === 0 ? this._options : createDummyTestRunBuilderOption(this._options); const newBuilder = new TestRunBuilder_1.TestRunBuilder(finalOption); this._builders[testResultIndex] = newBuilder; } return this._builders[testResultIndex]; } build() { return this._builders.map((b) => b.build()); } } /** * The test cases are written into only one trx file. */ class SingleTrxBuilder { analytics(rootSuite, options) { const b = new SingleTrxWriterTestRunsBuilder(options.testRunBuilderOptions); mergeAllSuitesToTestRunBuilder(b, rootSuite, options); return b.build(); } } exports.SingleTrxBuilder = SingleTrxBuilder; /** * The trx cases might be written into multi trx files. */ class MultiTrxsBuilder { analytics(rootSuite, options) { const b = new MultiTrxWriterTestRunsBuilder(options.testRunBuilderOptions); mergeAllSuitesToTestRunBuilder(b, rootSuite, options); return b.build(); } } exports.MultiTrxsBuilder = MultiTrxsBuilder;