UNPKG

@sap_oss/wdio-qmate-service

Version:

[![REUSE status](https://api.reuse.software/badge/github.com/SAP/wdio-qmate-service)](https://api.reuse.software/info/github.com/SAP/wdio-qmate-service)[![Node.js CI](https://github.com/SAP/wdio-qmate-service/actions/workflows/node.js.yml/badge.svg)](http

156 lines 7.26 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FunctionModule = void 0; const verboseLogger_1 = require("../../helper/verboseLogger"); const errorHandler_1 = __importDefault(require("../../helper/errorHandler")); /** * @class function * @memberof util */ class FunctionModule { vlf = new verboseLogger_1.VerboseLoggerFactory("util", "function"); ErrorHandler = new errorHandler_1.default(); maxCurrentRetries = 3; // =================================== MAIN =================================== /** * @function retry * @memberOf util.function * @description Retries the passed function n times with a specific interval until it executed successfully. * @param {Function} fct - The function to retry. * @param {Array} args - An array of the arguments passed to the function. * @param {Integer} [retries=3] - The number of retries. Can be set in config for all functions under "params" - "stepsRetries". * @param {Integer} [interval=5000] - The interval of the retries (ms). Can be set in config for all functions under "params" - "stepRetriesIntervals". * @param {Object} [scope=null] - The function scope. Defaults is the global object. * @example await util.function.retry(ui5.userInteraction.fill, [selector, value], 4, 10000); * @example await util.function.retry(async () => { * await ui5.userInteraction.fill(selector, "ABC"); * }, [], 2, 30000); */ // NOTE: Don't set default values since they will be calculated with "_getRetryProperties". async retry(fct, args, retries, interval, scope = null) { const vl = this.vlf.initLog(this.retry); vl.log(`${retries} retries were configured`); const res = await this._getRetryProperties(retries, interval); this.maxCurrentRetries = res.retries; await this._retry(fct, args, res.retries, res.interval, scope); } /** * @function executeOptional * @memberOf util.function * @description Executes the given function optionally. If it fails, a promise will be returned anyway. * @param {Function} fct - The function to execute. * @param {Array} args - An array of the arguments passed to the function. * @example await util.function.executeOptional(ui5.userInteraction.fill, [selector, value]); * @example await util.function.executeOptional(async () => { * await ui5.userInteraction.fill(selector, "ABC"); * }, []); */ async executeOptional(fct, args = []) { const vl = this.vlf.initLog(this.retry); try { await fct.apply(this, args); } catch (e) { if (fct.name) { util.console.info(`Optional function '${fct.name}' not executed, continue ...`); } else { util.console.info(`Optional anonymous function not executed, continue ...`); } return Promise.resolve(); } } // =================================== HELPER =================================== /** * @function mapWdioErrorToQmateErrorMessage * @memberOf util.function * @private * @description Maps Wdio Error to Qmate Error Message * @param {Error} wdioError - The wdio error * @param {string} action - An action performed upon the element ("click", "fill") * @example await util.function.mapWdioErrorToQmateErrorMessage(error, "click"); */ async mapWdioErrorToQmateErrorMessage(wdioError, action) { const errorMessage = wdioError.message; let qmateMessage = ""; if (action === "fill") { if (errorMessage.match(new RegExp(/(invalid element state|element not interactable)/))) { qmateMessage = `Function fill failed. Element can not be filled - make sure that the selector matches input \n\n` + wdioError.stack; } } else if (action === "click") { if (errorMessage.match(new RegExp(/is not clickable at point/))) { const reg = new RegExp(/(?<=Element <.* )(.*)(?=>...<)/).exec(errorMessage); const foundAttributes = reg ? reg[0] : undefined; let elementAttributes = foundAttributes; if (reg && foundAttributes) { if (foundAttributes.includes("id=")) { // @ts-ignore elementAttributes = foundAttributes.match(new RegExp(/(?=id)(.*)(?<=")/)); } else if (foundAttributes.includes("class=")) { // @ts-ignore elementAttributes = foundAttributes.match(new RegExp(/(?=class)(.*)(?<=")/)); } } if (wdioError && wdioError.stack && elementAttributes) { qmateMessage = `Element with attribute(s) ${elementAttributes[0]} is hidden by another element \n\n` + wdioError.stack; } else { qmateMessage = "Error clicking element \n\n" + wdioError; } } } return qmateMessage; } // =================================== HELPER =================================== async _getRetryProperties(retries, interval) { const vl = this.vlf.initLog(this._getRetryProperties); const res = { retries: retries, interval: interval }; if (res.retries === undefined) { res.retries = browser.config.params.stepsRetries; if (res.retries === undefined) { res.retries = 3; } } if (res.interval === undefined) { res.interval = browser.config.params.stepRetriesIntervals; if (res.interval === undefined) { res.interval = 5000; } } vl.log(`Got retry properties: ${res}`); return res; } async _retry(fct, args, retries, interval, scope = null) { const vl = this.vlf.initLog(this._retry); try { vl.log(`Executing ${fct.name ? fct.name : "anonymous"} function via retry mechanism`); return await fct.apply(scope, args); } catch (e) { let errorMessage = e.message; errorMessage = errorMessage ? errorMessage.trim().includes("failed with:") ? errorMessage.substring(errorMessage.search("failed with:") + 12) : errorMessage : ""; retries = retries - 1; if (retries < 0) { this.ErrorHandler.logException(e, `Retries done. Failed to execute the function:${errorMessage}`); } await browser.pause(interval); util.console.log(`Retrying function again (${this.maxCurrentRetries - retries}/${this.maxCurrentRetries})`); await this._retry(fct, args, retries, interval, scope); } } } exports.FunctionModule = FunctionModule; exports.default = new FunctionModule(); //# sourceMappingURL=function.js.map