UNPKG

cypress-xray-plugin

Version:

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

218 lines (217 loc) 8.79 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AxiosRestClient = void 0; const axios_1 = require("axios"); const form_data_1 = __importDefault(require("form-data")); const files_1 = require("../../util/files"); const logging_1 = require("../../util/logging"); const string_1 = require("../../util/string"); const time_1 = require("../../util/time"); class AxiosRestClient { constructor(axios, options) { var _a; this.axios = axios; this.options = options; this.createdLogFiles = new Map(); this.lastRequestTime = undefined; if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.debug) { this.axios.interceptors.request.use((request) => { this.logRequest(request); return request; }); this.axios.interceptors.response.use((response) => { this.logResponse(response); return response; }); } this.axios.interceptors.request.use((request) => request, (error) => { this.logError("outbound", error); return Promise.reject(error instanceof Error ? error : new Error((0, string_1.unknownToString)(error))); }); this.axios.interceptors.response.use((response) => response, (error) => { this.logError("inbound", error); return Promise.reject(error instanceof Error ? error : new Error((0, string_1.unknownToString)(error))); }); } async get(url, config) { var _a; await this.delayIfNeeded(); const progressInterval = this.startResponseInterval(url); try { return await this.axios.get(url, { ...(_a = this.options) === null || _a === void 0 ? void 0 : _a.http, ...config, }); } finally { clearInterval(progressInterval); } } async post(url, data, config) { var _a; await this.delayIfNeeded(); const progressInterval = this.startResponseInterval(url); try { return await this.axios.post(url, data, { ...(_a = this.options) === null || _a === void 0 ? void 0 : _a.http, ...config, }); } finally { clearInterval(progressInterval); } } async put(url, data, config) { var _a; await this.delayIfNeeded(); const progressInterval = this.startResponseInterval(url); try { return await this.axios.put(url, data, { ...(_a = this.options) === null || _a === void 0 ? void 0 : _a.http, ...config, }); } finally { clearInterval(progressInterval); } } logRequest(request) { var _a; const method = (_a = request.method) === null || _a === void 0 ? void 0 : _a.toUpperCase(); const url = request.url; let prefix = dateToTimestamp(new Date()); if (method) { prefix = `${prefix}_${method}`; } if (url) { prefix = `${prefix}_${url}`; } const filename = `${this.appendSuffix((0, files_1.normalizedFilename)(`${prefix}_request`))}.json`; if (request.data instanceof form_data_1.default) { const formData = request.data; const chunks = []; let bytesRead = 0; const listener = (chunk) => { var _a, _b; bytesRead += chunk.length; if (bytesRead > Math.floor(1024 * 1024 * ((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.fileSizeLimit) !== null && _b !== void 0 ? _b : 50))) { chunks.push("[... omitted due to file size]"); formData.off("data", listener); return; } chunks.push(chunk); }; formData.on("data", listener); formData.on("end", () => { const resolvedFilename = logging_1.LOG.logToFile(JSON.stringify({ body: chunks.map((chunk) => chunk.toString("utf-8")).join(""), headers: request.headers, params: request.params, url: url, }, null, 2), filename); logging_1.LOG.message("debug", `Request: ${resolvedFilename}`); }); } else { const resolvedFilename = logging_1.LOG.logToFile(JSON.stringify({ body: request.data, headers: request.headers, params: request.params, url: url, }, null, 2), filename); logging_1.LOG.message("debug", `Request: ${resolvedFilename}`); } } logResponse(response) { var _a; const request = response.request; const method = (_a = request.method) === null || _a === void 0 ? void 0 : _a.toUpperCase(); const url = response.config.url; let prefix = dateToTimestamp(new Date()); if (method) { prefix = `${prefix}_${method}`; } if (url) { prefix = `${prefix}_${url}`; } const filename = `${this.appendSuffix((0, files_1.normalizedFilename)(`${prefix}_response`))}.json`; const resolvedFilename = logging_1.LOG.logToFile(JSON.stringify({ data: response.data, headers: response.headers, status: response.status, statusText: response.statusText, }, null, 2), filename); logging_1.LOG.message("debug", `Response: ${resolvedFilename}`); } logError(direction, error) { var _a, _b, _c; let data; let prefix = dateToTimestamp(new Date()); if ((0, axios_1.isAxiosError)(error)) { const method = (_b = (_a = error.config) === null || _a === void 0 ? void 0 : _a.method) === null || _b === void 0 ? void 0 : _b.toUpperCase(); const url = (_c = error.config) === null || _c === void 0 ? void 0 : _c.url; if (method) { prefix = `${prefix}_${method}`; } if (url) { prefix = `${prefix}_${url}`; } data = error.toJSON(); } else { data = error; } const filename = `${this.appendSuffix((0, files_1.normalizedFilename)(`${prefix}_${direction === "inbound" ? "response" : "request"}`))}.json`; const resolvedFilename = logging_1.LOG.logToFile(JSON.stringify(data, null, 2), filename); logging_1.LOG.message("debug", `${direction === "inbound" ? "Response" : "Request"}: ${resolvedFilename}`); } startResponseInterval(url) { return (0, time_1.startInterval)((totalTime) => { logging_1.LOG.message("info", `Waiting for ${url} to respond... (${(totalTime / 1000).toString()} seconds)`); }); } appendSuffix(filename) { const filenameCount = this.createdLogFiles.get(filename); if (filenameCount) { this.createdLogFiles.set(filename, filenameCount + 1); return `${filename}_${filenameCount.toString()}`; } else { this.createdLogFiles.set(filename, 1); return filename; } } async delayIfNeeded() { var _a, _b; // We specifically do not use axios interceptors here because we would need to handle // connection timeouts, ECONNRESET etc. otherwise (I think). if ((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.rateLimiting) === null || _b === void 0 ? void 0 : _b.requestsPerSecond) { const interval = 1000 / this.options.rateLimiting.requestsPerSecond; const now = Date.now(); let nextRequestTime; if (this.lastRequestTime) { nextRequestTime = Math.max(this.lastRequestTime + interval, now); } else { nextRequestTime = now; } this.lastRequestTime = nextRequestTime; const delay = nextRequestTime - now; if (delay > 0) { await new Promise((resolve) => { setTimeout(resolve, delay); }); } } } } exports.AxiosRestClient = AxiosRestClient; function dateToTimestamp(date) { return `${date.getHours().toString().padStart(2, "0")}_${date .getMinutes() .toString() .padStart(2, "0")}_${date.getSeconds().toString().padStart(2, "0")}`; }