UNPKG

aiotests-playwright-reporter

Version:

AIO Tests reporter for reporting results from Playwright to AIO Tests

679 lines (678 loc) 31.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.reportTestResults = exports.validateAIOConfig = void 0; const AioTestsLogger_1 = __importDefault(require("./AioTestsLogger")); const axios_1 = __importStar(require("axios")); const fs_1 = __importDefault(require("fs")); const form_data_1 = __importDefault(require("form-data")); const baseUrl = "https://tcms.aiojiraapps.com/aio-tcms/api/v1"; const restVersion = "/rest/aio-tcms-api/1.0"; const rateLimitWaitTime = 60 * 1000; const apiTimeout = 45 * 1000; const CREATE_IF_ABSENT = "CREATE_IF_ABSENT"; const createNewCycleOptions = [true, false, "true", "false", CREATE_IF_ABSENT]; const bulkRequestBody = { testRuns: [] }; const browserKeyMap = new Map(); const browserBulkRequestMap = new Map(); let debugMode = false; let aioAPIClient; let isAttachmentAPIAvailable = null; let stopReporting = false; let allCaseKeys = []; let allFailedRuns = []; let bulkTestRunUpdate = false; let multiBrowser = false; function sleep(ms) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve) => setTimeout(resolve, ms)); }); } function initAPIClient(aioConfig) { debugMode = !!aioConfig.debugMode; AioTestsLogger_1.default.setDebugMode(debugMode); AioTestsLogger_1.default.debug("Debug Mode is set to true"); if (aioConfig.cloud || process.env.AIO_API_KEY) { if (!aioConfig.cloud.apiKey && !process.env.AIO_API_KEY) { AioTestsLogger_1.default.error('Cloud hosting config does not specify apiKey. Please add "cloud":{"apiKey":"auth token"}', debugMode); } else { let apiKey = process.env.AIO_API_KEY ? process.env.AIO_API_KEY : aioConfig.cloud.apiKey; aioAPIClient = axios_1.default.create({ baseURL: baseUrl, timeout: apiTimeout, headers: { Authorization: `AioAuth ${apiKey}` }, }); } return; } else if (aioConfig.hosted) { if (!!!aioConfig.hosted.jiraUrl) { AioTestsLogger_1.default.error('Server hosting config does not specify jiraUrl. Please add "server":{"jiraUrl":"https://companyhostedjira.com/jira"}'); } else { aioAPIClient = axios_1.default.create({ baseURL: aioConfig.hosted.jiraUrl + restVersion, timeout: apiTimeout, }); if (aioConfig.hosted.jiraUsername || process.env.JIRA_USERNAME) { let jUsername = process.env.JIRA_USERNAME ? process.env.JIRA_USERNAME : aioConfig.hosted.jiraUsername; let jPassword = process.env.JIRA_PASSWORD ? process.env.JIRA_PASSWORD : aioConfig.hosted.jiraPassword; aioAPIClient.defaults.auth = { username: jUsername, password: jPassword, }; } else if (aioConfig.hosted.jiraPAT || process.env.JIRA_PAT) { let jPAT = process.env.JIRA_PAT ? process.env.JIRA_PAT : aioConfig.hosted.jiraPAT; aioAPIClient.defaults.headers.common["Authorization"] = `Bearer ${jPAT}`; } else { AioTestsLogger_1.default.error("Server hosting config missing Jira username or PAT. " + ' Please set JIRA_USERNAME/JIRA_PASSWORD or JIRA_PAT as an environment variable or add "hosted":{"jiraUrl":"yoururl", "jiraUsername":"un", "jiraPassword":"pwd"}' + ' or "hosted":{"jiraUrl":"your url", "jiraPAT":"PAT token"} to config file'); aioAPIClient = null; } } return; } AioTestsLogger_1.default.error("No authentication information found. Please set AIO_API_KEY/JIRA_USERNAME/JIRA_PAT as an environment variable or " + 'add "cloud":{"apiKey":"auth token"} or "server":{"jiraServerUrl":"val"}) to config'); } const validateAIOConfig = (config, reportError) => { if (!!config.enableReporting) { if (!!!config.jiraProjectId && !!reportError) { AioTestsLogger_1.default.error("Jira Project Id is mandatory for AIO Tests Reporting.", true); return; } initAPIClient(config); if (!aioAPIClient) { AioTestsLogger_1.default.error("Please specify valid credentials to connect with AIO Tests."); return; } return config; } else { if (reportError) AioTestsLogger_1.default.error("AIO Tests reporting is not enabled. Please set env:{aioTests:{enableReporting:true}}", true); } return undefined; }; exports.validateAIOConfig = validateAIOConfig; const getOrCreateCycle = (aioConfig) => __awaiter(void 0, void 0, void 0, function* () { if (!aioAPIClient) { return Promise.resolve(); } AioTestsLogger_1.default.logStartEnd("Determining cycle to update"); if (!aioConfig.cycleDetails) { AioTestsLogger_1.default.error('Please specify cycleDetails in config. eg. "cycleDetails": {"cycleKey":"AT-CY-11"}', true); return Promise.resolve(); } else { let aioCycleConfig = aioConfig.cycleDetails; if (aioCycleConfig.createNewCycle && !createNewCycleOptions.includes(aioCycleConfig.createNewCycle)) { return Promise.resolve(`Invalid value for createNewCycle "${aioCycleConfig.createNewCycle}". Valid values include ${createNewCycleOptions}.`); } if ((!aioCycleConfig.createNewCycle || "false" === aioCycleConfig.createNewCycle) && aioCycleConfig.cycleKey) { aioCycleConfig["cycleKeyToReportTo"] = aioCycleConfig.cycleKey; return Promise.resolve(); } if (aioCycleConfig.createNewCycle === true || "true" === aioCycleConfig.createNewCycle || aioCycleConfig.createNewCycle === CREATE_IF_ABSENT) { let cycleTitle = aioCycleConfig.cycleName; let customFields = aioCycleConfig.customFields; if (!cycleTitle) { return Promise.resolve("createNewCycle is set to " + aioCycleConfig.createNewCycle + " in config. Please set cycleName."); } if (aioCycleConfig.createNewCycle === CREATE_IF_ABSENT) { let results = yield findExistingCycleThroughName(aioConfig); if (results === true) { AioTestsLogger_1.default.debug("Existing cycle found"); //Cycle found and set. return; } if (results !== false) { //Error while finding cycle. AioTestsLogger_1.default.log(results); return; } } AioTestsLogger_1.default.log("Creating cycle : " + cycleTitle); let folderCreationPromise = getOrCreateFolder(aioConfig.jiraProjectId, aioCycleConfig); return folderCreationPromise .then((folderCreationResponse) => __awaiter(void 0, void 0, void 0, function* () { AioTestsLogger_1.default.debug("Folder task resolved. Creating cycle."); let createCycleBody = { title: cycleTitle, customFields: customFields || null, }; if (folderCreationResponse) { createCycleBody.folder = folderCreationResponse.data; } if (aioCycleConfig.tasks && aioCycleConfig.tasks.length > 0 && Array.isArray(aioCycleConfig.tasks)) { let jiraTasks = aioCycleConfig.tasks.filter((f) => f && !!f.trim()); if (jiraTasks.length > 0) { createCycleBody.jiraTaskIDs = jiraTasks; } } AioTestsLogger_1.default.debug("Cycle endpoint " + "/project/" + aioConfig.jiraProjectId + "/testcycle/detail"); try { let response = yield aioAPIClient .post("/project/" + aioConfig.jiraProjectId + "/testcycle/detail", createCycleBody); aioCycleConfig["cycleKeyToReportTo"] = response.data.key; AioTestsLogger_1.default.log("Cycle created successfully : " + aioCycleConfig.cycleKeyToReportTo); } catch (error) { debugLogError(error); if (error.response) { if (error.response.status === 401 || error.response.status === 403) { return Promise.resolve("Authorization error. Please check credentials."); } else { return Promise.resolve(error.response.status + " : " + error.response.data); } } } })) .catch((error) => { debugLogError(error); if (error.response) { AioTestsLogger_1.default.error(error.response.status + " : " + error.response.data); } return Promise.resolve("Error in fetching or creating cycle folder. " + 'Please check format of folder, for eg. ["Cloud","Release1"]'); }); } return Promise.resolve('createNewCycle is false in config. Please specify a cycle key (eg. AT-CY-11) as "cycleKey":"AT-CY=11" or cycle name as "cycleName":"Regression release 1" '); } }); function getOrCreateFolder(jiraProjectId, aioCycleConfig) { return __awaiter(this, void 0, void 0, function* () { if (aioCycleConfig.folder && Array.isArray(aioCycleConfig.folder) && aioCycleConfig.folder.length > 0) { const userFolderHierarchy = aioCycleConfig.folder.filter((folder) => folder && folder.trim()); if (userFolderHierarchy.length > 0) { AioTestsLogger_1.default.log(`Creating or fetching folder: ${userFolderHierarchy}`); return aioAPIClient.put(`/project/${jiraProjectId}/testcycle/folder/hierarchy`, { folderHierarchy: userFolderHierarchy, }); } } else { AioTestsLogger_1.default.debug("No cycle folder information set."); } return Promise.resolve(); }); } function findExistingCycleThroughName(aioConfig) { return __awaiter(this, void 0, void 0, function* () { if (aioConfig.parallelBuild && aioConfig.parallelBuild.masterBuild === false) { let to = aioConfig.parallelBuild.waitForSeconds ? aioConfig.parallelBuild.waitForSeconds : 2; AioTestsLogger_1.default.log(`Waiting for ${to} seconds for master build to finish`); yield new Promise((resolve) => setTimeout(resolve, to * 1000)); } let body = { title: { comparisonType: "EXACT_MATCH", value: aioConfig.cycleDetails.cycleName.trim(), }, }; AioTestsLogger_1.default.log("Finding cycle with name : " + aioConfig.cycleDetails.cycleName.trim()); return aioAPIClient .post(`/project/${aioConfig.jiraProjectId}/testcycle/search`, body) .then(function (response) { var _a, _b; const items = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.items; if (items && items.length > 0) { aioConfig.cycleDetails["cycleKeyToReportTo"] = (_b = items[0]) === null || _b === void 0 ? void 0 : _b.key; return true; } else { return false; } }) .catch(function (error) { debugLogError(error); if (error.response) { if (error.response.status === 401 || error.response.status === 403) { return Promise.resolve("Authorization error. Please check credentials."); } else { return Promise.resolve(error.response.status + " : " + error.response.data); } } return Promise.resolve("An unknown error occurred while searching for the cycle."); }); }); } function getCustomFieldValueToUpdate(customFieldsToUpdate) { const cfUpdates = []; if (customFieldsToUpdate) { customFieldsToUpdate.forEach((cf) => { const data = { customValue: { name: cf.name, value: cf.value }, }; if (cf.operationType) { data.customFieldUpdateOperationType = cf.operationType; } cfUpdates.push(data); }); } return cfUpdates; } const replaceProjectNameForRunFields = (customFieldUpdates, projectName) => { if (customFieldUpdates == null) { return null; } return customFieldUpdates.map((customFieldUpdate) => replaceProjectName(customFieldUpdate, projectName)); }; const replaceProjectName = (customFieldUpdate, projectName) => { const { value } = customFieldUpdate.customValue; let newValue; if (typeof value === "string") { // Case: value is a string newValue = value.replace(/\$project/g, projectName); } else if (Array.isArray(value)) { if (value.every((item) => typeof item === "string")) { // Case: value is a string[] newValue = value.map((item) => item.replace(/\$project/g, projectName)); } else if (value.every((item) => typeof item === "object" && item !== null && "value" in item)) { // Case: value is a { value: string }[] newValue = value.map((item) => ({ value: item.value.replace(/\$project/g, projectName), })); } else { throw new Error("Invalid array structure in value field"); } } else if (typeof value === "object" && value !== null) { if ("value" in value) { // Case: value is { value: string } newValue = { value: value.value.replace(/\$project/g, projectName) }; } else { throw new Error("Invalid object structure in value field"); } } else { newValue = value; } return { customValue: { name: customFieldUpdate.customValue.name, value: newValue }, customFieldUpdateOperationType: customFieldUpdate.customFieldUpdateOperationType, }; }; function debugLogError(error) { if (debugMode) { AioTestsLogger_1.default.error("*** AIO Debug Mode Error Reporting ***"); AioTestsLogger_1.default.errorObj(error.message); if (error.response) { const status = error.response.status; const data = error.response.data; AioTestsLogger_1.default.errorObj(`${status} ${data}`); } else { AioTestsLogger_1.default.errorObj(error); } AioTestsLogger_1.default.error("*** AIO Debug Mode Error Reporting End ***"); } } function getAIORunStatus(playwrightStatus) { switch (playwrightStatus) { case "failed": return "Failed"; case "passed": return "Passed"; default: return "Not Run"; } } function uploadScreenshot(path, jiraProjectId, cyclekey, runId, trialCounter = 0) { return __awaiter(this, void 0, void 0, function* () { if (path) { const form = new form_data_1.default(); form.append("file", fs_1.default.createReadStream(path)); try { yield aioAPIClient.post(`/project/${jiraProjectId}/testcycle/${cyclekey}/testrun/${runId}/attachment`, form, { headers: form.getHeaders(), }); AioTestsLogger_1.default.log(`Screenshot uploaded: ${path}`); } catch (error) { if (error.response) { if (error.response.status === 429 && trialCounter < 3) { AioTestsLogger_1.default.log("Reached AIO rate limits. Pausing..."); yield sleep(rateLimitWaitTime); return uploadScreenshot(path, jiraProjectId, cyclekey, runId, trialCounter + 1); } else if (error.response.status === 404) { AioTestsLogger_1.default.error("Attachment API is not supported in the current API version and hence attachments could not be uploaded. Please upgrade to the latest version of AIO Tests."); isAttachmentAPIAvailable = false; } } else { if (error.data) { AioTestsLogger_1.default.error(error.data); } else { AioTestsLogger_1.default.error(error.code); } } } } }); } function initCycleDetails(aioConfig) { return __awaiter(this, void 0, void 0, function* () { try { const data = yield getOrCreateCycle(aioConfig); if (aioConfig.cycleDetails.cycleKeyToReportTo) { AioTestsLogger_1.default.log("Reporting results to cycle : " + aioConfig.cycleDetails.cycleKeyToReportTo); } else { stopReporting = true; if (typeof data === "string") { AioTestsLogger_1.default.error(data); } } } catch (err) { if (err instanceof Error) { AioTestsLogger_1.default.error("An error occurred: " + err.message); } else { AioTestsLogger_1.default.error("An unknown error occurred"); } stopReporting = true; } }); } const reportTestResults = function (config, testSummary, multiBrowsers) { return __awaiter(this, void 0, void 0, function* () { if (testSummary && testSummary.length) { yield initCycleDetails(config); if (!aioAPIClient || stopReporting) { return Promise.resolve(); } multiBrowser = multiBrowsers; const cfUpdates = config.runDetails ? getCustomFieldValueToUpdate(config.runDetails.customFieldsToUpdate) : null; let index = 0; const total = testSummary.length; AioTestsLogger_1.default.logStartEnd("Reporting results"); for (const { result, test } of testSummary) { const isLast = index === total - 1; yield reportSpecResults(config, result, test, cfUpdates); if (isLast && bulkTestRunUpdate) { yield bulkUpdateResult(config); } index++; } } else { AioTestsLogger_1.default.log("No case keys found in specs"); } }); }; exports.reportTestResults = reportTestResults; const reportSpecResults = function (config, results, testCase, cfUpdates) { return __awaiter(this, void 0, void 0, function* () { const testData = yield findResults(results, testCase); const passedCaseKeys = []; const failedCaseKeys = []; const targetKeys = results.status === "passed" ? passedCaseKeys : failedCaseKeys; targetKeys.push(...testData.keys()); allCaseKeys.push(...targetKeys); if (failedCaseKeys.length > 0) { AioTestsLogger_1.default.log("*".repeat(5) + " Updating failed cases " + "*".repeat(5)); try { yield postFailedResult(failedCaseKeys, testData, config, cfUpdates); } catch (err) { debugLogError(err); } } yield addDataForBulkUpdateResult(passedCaseKeys, testData, config, cfUpdates); }); }; function postFailedResult(failedCaseKeys, testData, config, cfUpdates) { return __awaiter(this, void 0, void 0, function* () { return failedCaseKeys.reduce((promiseChain, caseKey) => { const attemptData = testData.get(caseKey); return promiseChain.then(() => __awaiter(this, void 0, void 0, function* () { yield postResult(config, caseKey, attemptData, attemptData.screenshot, cfUpdates); })); }, Promise.resolve()); }); } function findResults(results, testCase) { return __awaiter(this, void 0, void 0, function* () { let testData = new Map(); let pattern = new RegExp("\\w+-TC-\\d+", "gi"); let tcKeys = []; let match; testCase.tags.forEach((tag) => { do { match = pattern.exec(tag); if (match) { tcKeys.push(match[0]); } } while (match != null); }); if (tcKeys.length) { tcKeys.forEach((tcKey) => { // @ts-ignore const comments = results.error || multiBrowser ? generateComments(testCase._projectId ? testCase._projectId : "", results.error) : null; // @ts-ignore testData.set(tcKey, { testId: tcKey, duration: results.duration / 1000, testStatus: getAIORunStatus(results.status), retires: results.retry, comments: comments, screenshot: results.attachments .filter((attachment) => attachment.contentType.startsWith("image")) .map((attachment) => attachment.path) .filter((path) => path !== undefined), // @ts-ignore browser: testCase._projectId }); }); } return testData; }); } function generateComments(browserName, error) { return [ multiBrowser ? `Browser: ${browserName}` : undefined, (error === null || error === void 0 ? void 0 : error.message) ? `Message: ${error.message}` : undefined, (error === null || error === void 0 ? void 0 : error.stack) ? `Stack: ${error.stack}` : undefined, ].filter(Boolean); } function addDataForBulkUpdateResult(passedCaseKeys, testDataMap, config, cfUpdates) { return __awaiter(this, void 0, void 0, function* () { for (const passedCaseKey of passedCaseKeys) { const testData = testDataMap.get(passedCaseKey); if (!testData) continue; const testRun = { testCaseKey: passedCaseKey, testRunStatus: testData.testStatus, effort: testData.duration, isAutomated: true, comments: testData.comments, customFieldValueToUpdate: config.runDetails ? replaceProjectNameForRunFields(cfUpdates, testData.browser) : cfUpdates, }; if (multiBrowser) { const existingRequest = browserBulkRequestMap.get(testData.browser); if (existingRequest) { existingRequest.testRuns.push(testRun); } else { browserBulkRequestMap.set(testData.browser, { testRuns: [testRun] }); } } else { bulkRequestBody.testRuns.push(testRun); } bulkTestRunUpdate = true; } }); } function bulkUpdateResult(aioConfig, trialCounter = 0) { var _a; return __awaiter(this, void 0, void 0, function* () { const { jiraProjectId, cycleDetails, addNewRun } = aioConfig; const url = `/project/${jiraProjectId}/testcycle/${cycleDetails.cycleKeyToReportTo}/bulk/testrun/update?createNewRun=${!!addNewRun}`; AioTestsLogger_1.default.log("*".repeat(5) + " Updating all passed cases " + "*".repeat(5)); AioTestsLogger_1.default.debug(`Reporting results in bulk: ${url}`); try { const processResponse = (response, browser) => { const { successCount, errorCount, errors } = response.data; AioTestsLogger_1.default.log(`Successfully reported ${successCount} passed cases${browser ? ` for browser: ${browser}` : ""}.`); if (errorCount > 0) { AioTestsLogger_1.default.error("Failures in reporting passed cases:"); Object.entries(errors).forEach(([key, error]) => { const errorMessage = error.message || "Unknown error"; AioTestsLogger_1.default.error(`${key}: ${errorMessage}`); }); } }; if (multiBrowser) { for (const [browser, bulkRequestBodyBrowser] of browserBulkRequestMap) { const response = yield aioAPIClient.post(url, bulkRequestBodyBrowser); processResponse(response, browser); } } else { const response = yield aioAPIClient.post(url, bulkRequestBody); processResponse(response); } } catch (err) { debugLogError(err); if (((_a = err.response) === null || _a === void 0 ? void 0 : _a.status) === 429 && trialCounter < 3) { AioTestsLogger_1.default.log("Reached AIO rate limits. Retrying..."); yield sleep(rateLimitWaitTime); return bulkUpdateResult(aioConfig, trialCounter + 1); } const errorMsg = err.response ? `Status Code - ${err.response.status}: ${JSON.stringify(err.response.data)}` : err.code; AioTestsLogger_1.default.error(`Error in bulk cases reporting: ${errorMsg}`); stopReporting = true; } }); } function postResult(aioConfig, caseKey, results, screenshots, cfUpdates, trialCounter = 0) { var _a; return __awaiter(this, void 0, void 0, function* () { const data = { testRunStatus: results.testStatus, effort: results.duration, isAutomated: true, comments: results.comments, customFieldValueToUpdate: aioConfig.runDetails ? replaceProjectNameForRunFields(cfUpdates, results.browser) : cfUpdates, }; const createNewRun = aioConfig.addNewRun; AioTestsLogger_1.default.debug(`Posting results to /project/${aioConfig.jiraProjectId}/testcycle/${aioConfig.cycleDetails.cycleKeyToReportTo}/testcase/${caseKey}/testrun?createNewRun=${createNewRun}`); try { const response = yield aioAPIClient.post(`/project/${aioConfig.jiraProjectId}/testcycle/${aioConfig.cycleDetails.cycleKeyToReportTo}/testcase/${caseKey}/testrun?createNewRun=${createNewRun}`, data); if (multiBrowser) { if (browserKeyMap.has(results.browser)) { (_a = browserKeyMap.get(results.browser)) === null || _a === void 0 ? void 0 : _a.push(response.data.ID); } else { browserKeyMap.set(results.browser, [response.data.ID]); } } else { allFailedRuns.push(response.data.ID); } AioTestsLogger_1.default.log(`Successfully reported ${caseKey} as ${data.testRunStatus} with runID ${response.data.ID}.`); const runId = response.data.ID; if (aioConfig.addAttachmentToFailedCases && data.testRunStatus.toLowerCase() === "failed" && (isAttachmentAPIAvailable || isAttachmentAPIAvailable == null)) { return yield uploadAttachments(aioConfig.jiraProjectId, aioConfig.cycleDetails.cycleKeyToReportTo, runId, screenshots); } } catch (err) { debugLogError(err); if ((0, axios_1.isAxiosError)(err) && err.response) { if (err.response.status === 429 && trialCounter < 3) { AioTestsLogger_1.default.log("Reached AIO rate limits. Pausing..."); yield sleep(rateLimitWaitTime); return postResult(aioConfig, caseKey, results, screenshots, cfUpdates, trialCounter + 1); } else { AioTestsLogger_1.default.error(`Error reporting ${caseKey} : Status Code - ${err.response.status} - ${err.response.data}`); } } else { AioTestsLogger_1.default.error(`Error in bulk cases reporting : ${err.message}`); } } }); } function uploadAttachments(jiraProjectId, cycleKey, runId, resultScreenshots) { return __awaiter(this, void 0, void 0, function* () { if (resultScreenshots) { return resultScreenshots.reduce((promise, screenshot) => __awaiter(this, void 0, void 0, function* () { yield promise; return uploadScreenshot(screenshot, jiraProjectId, cycleKey, runId); }), Promise.resolve()); } else { return Promise.resolve(); } }); }