UNPKG

cypress-xray-plugin

Version:

A Cypress plugin for uploading test results to Xray (test management for Jira)

190 lines (181 loc) 9.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConvertCypressTestsCommand = void 0; const node_path_1 = require("node:path"); const semver_1 = require("semver"); const status_1 = require("../../../../../types/cypress/status"); const base64_1 = require("../../../../../util/base64"); const dedent_1 = require("../../../../../util/dedent"); const errors_1 = require("../../../../../util/errors"); const files_1 = require("../../../../../util/files"); const time_1 = require("../../../../../util/time"); const command_1 = require("../../../../command"); const converter_1 = require("./util/converter"); const status_conversion_1 = require("./util/status-conversion"); class ConvertCypressTestsCommand extends command_1.Command { constructor(parameters, logger, results) { super(parameters, logger); this.results = results; } async computeResult() { const results = await this.results.compute(); const version = (0, semver_1.lt)(results.cypressVersion, "13.0.0") ? "<13" : ">=13"; const convertedTests = this.convertTestRuns(results, version); const runsByKey = new Map(); for (const convertedTest of convertedTests) { if (convertedTest.issueKey === null) { this.logger.message("warning", (0, dedent_1.dedent)(` ${convertedTest.spec.filepath} Test: ${convertedTest.title} Skipping result upload. Caused by: ${(0, errors_1.errorMessage)((0, errors_1.missingTestKeyInTestTitleError)(convertedTest.title, this.parameters.projectKey))} `)); } else { const runs = runsByKey.get(convertedTest.issueKey); if (runs) { runs.push(convertedTest); } else { runsByKey.set(convertedTest.issueKey, [convertedTest]); } } } const xrayTests = []; for (const [issueKey, testRuns] of runsByKey) { xrayTests.push(this.getTest(testRuns, issueKey)); } if (xrayTests.length === 0) { throw new Error("Failed to convert Cypress tests into Xray tests: No Cypress tests to upload"); } return [xrayTests[0], ...xrayTests.slice(1)]; } convertTestRuns(runResults, version) { const cypressRuns = runResults.runs.filter((run) => !this.parameters.featureFileExtension || !run.spec.relative.endsWith(this.parameters.featureFileExtension)); if (cypressRuns.length === 0) { throw new Error("Failed to extract test run data: Only Cucumber tests were executed"); } const converter = version === "<13" ? new converter_1.RunConverterV12(this.parameters.projectKey, cypressRuns) : new converter_1.RunConverterLatest(this.parameters.projectKey, cypressRuns, this.parameters.screenshotCollection.getScreenshots()); const conversions = converter.getConversions({ onlyLastAttempt: this.parameters.uploadLastAttempt, }); const testRunData = []; for (const conversion of conversions) { if (conversion.kind === "error") { this.logger.message("warning", (0, dedent_1.dedent)(` Test: ${conversion.title} Skipping result upload. Caused by: ${(0, errors_1.errorMessage)(conversion.error)} `)); } else { testRunData.push(conversion); } } if (this.parameters.uploadScreenshots) { this.addScreenshotEvidence(testRunData, converter); } return testRunData; } addScreenshotEvidence(conversions, converter) { const testIssueKeys = conversions .map((conversion) => conversion.issueKey) .filter((key) => key !== null); for (const issueKey of new Set(testIssueKeys)) { const screenshots = converter.getScreenshots(issueKey, { onlyLastAttempt: this.parameters.uploadLastAttempt, }); for (const screenshot of screenshots) { let filename = (0, node_path_1.basename)(screenshot); if (this.parameters.normalizeScreenshotNames) { filename = (0, files_1.normalizedFilename)(filename); } this.parameters.evidenceCollection.addEvidence(issueKey, { contentType: `image/${(0, node_path_1.extname)(screenshot).replace(".", "")}`, data: (0, base64_1.encodeFile)(screenshot), filename: filename, }); } } for (const screenshot of converter.getNonAttributableScreenshots({ onlyLastAttempt: this.parameters.uploadLastAttempt, })) { const screenshotName = (0, node_path_1.parse)(screenshot).name; this.logger.message("warning", (0, dedent_1.dedent)(` ${screenshot} Screenshot cannot be attributed to a test and will not be uploaded. To upload screenshots, include test issue keys anywhere in their name: cy.screenshot("${this.parameters.projectKey}-123 ${screenshotName}") `)); } } getTest(runs, issueKey) { const xrayTest = { finish: (0, time_1.truncateIsoTime)((0, time_1.latestDate)(...runs.map((test) => new Date(test.startedAt.getTime() + test.duration))).toISOString()), start: (0, time_1.truncateIsoTime)((0, time_1.earliestDate)(...runs.map((test) => test.startedAt)).toISOString()), status: this.getXrayStatus(runs), testKey: issueKey, }; const evidence = this.getXrayEvidence(issueKey); if (evidence.length > 0) { xrayTest.evidence = evidence; } if (runs.length > 1) { const iterations = []; for (const iteration of runs) { const definedParameters = this.parameters.iterationParameterCollection.getIterationParameters(issueKey, iteration.title); iterations.push({ parameters: [ { name: "iteration", value: (iterations.length + 1).toString(), }, ...Object.entries(definedParameters).map(([key, value]) => { return { name: key, value: value, }; }), ], status: (0, status_conversion_1.getXrayStatus)(iteration.status, this.parameters.useCloudStatusFallback === true, this.parameters.xrayStatus), }); } xrayTest.iterations = iterations; } return xrayTest; } getXrayStatus(tests) { const statuses = tests.map((test) => test.status); if (statuses.length > 1) { const passed = statuses.filter((s) => s === status_1.CypressStatus.PASSED).length; const failed = statuses.filter((s) => s === status_1.CypressStatus.FAILED).length; const pending = statuses.filter((s) => s === status_1.CypressStatus.PENDING).length; const skipped = statuses.filter((s) => s === status_1.CypressStatus.SKIPPED).length; if (this.parameters.xrayStatus.aggregate) { return this.parameters.xrayStatus.aggregate({ failed, passed, pending, skipped }); } if (passed > 0 && failed === 0 && skipped === 0) { return (0, status_conversion_1.getXrayStatus)(status_1.CypressStatus.PASSED, this.parameters.useCloudStatusFallback === true, this.parameters.xrayStatus); } if (passed === 0 && failed === 0 && skipped === 0 && pending > 0) { return (0, status_conversion_1.getXrayStatus)(status_1.CypressStatus.PENDING, this.parameters.useCloudStatusFallback === true, this.parameters.xrayStatus); } if (skipped > 0) { return (0, status_conversion_1.getXrayStatus)(status_1.CypressStatus.SKIPPED, this.parameters.useCloudStatusFallback === true, this.parameters.xrayStatus); } return (0, status_conversion_1.getXrayStatus)(status_1.CypressStatus.FAILED, this.parameters.useCloudStatusFallback === true, this.parameters.xrayStatus); } return (0, status_conversion_1.getXrayStatus)(statuses[0], this.parameters.useCloudStatusFallback === true, this.parameters.xrayStatus); } getXrayEvidence(issueKey) { const evidence = []; this.parameters.evidenceCollection .getEvidence(issueKey) .forEach((item) => evidence.push(item)); return evidence; } } exports.ConvertCypressTestsCommand = ConvertCypressTestsCommand;