UNPKG

@apica-io/url-xi

Version:

URL Check for integrations and API monitoring

482 lines 21.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (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.PrePostProcessors = void 0; const vm = __importStar(require("vm2")); const testbase_1 = require("../lib/testbase"); const helpers = __importStar(require("../lib/helpers")); const api_1 = require("../lib/api"); const chai = __importStar(require("chai")); const jsonpath_plus_1 = require("jsonpath-plus"); const xpath_1 = __importDefault(require("xpath")); const xmldom_1 = __importDefault(require("xmldom")); const logger = __importStar(require("log4js")); const aws4_axios_1 = require("aws4-axios"); class PrePostProcessors extends testbase_1.TestBase { constructor(config, debug = false) { super(debug, 'PrePostProcessors'); this._authMethodInterceptor = -1; this._testConfig = config; this.expect = chai.expect; this.assert = chai.assert; this._scriptLogger = logger.getLogger('VM Script'); } setupAuthMethod(api, authMethod) { var _a, _b, _c, _d; if (this._authMethodInterceptor >= 0) { api.getApi().interceptors.request.eject(this._authMethodInterceptor); this._authMethodInterceptor = -1; } switch (authMethod.method) { case 'aws4sign': if (authMethod.aws4sign) { const awsInterceptor = (0, aws4_axios_1.aws4Interceptor)({ region: (_a = authMethod.aws4sign) === null || _a === void 0 ? void 0 : _a.region, service: (_b = authMethod.aws4sign) === null || _b === void 0 ? void 0 : _b.service, }, { accessKeyId: ((_c = authMethod.aws4sign) === null || _c === void 0 ? void 0 : _c.accessKeyId) || '', secretAccessKey: ((_d = authMethod.aws4sign) === null || _d === void 0 ? void 0 : _d.secretAccessKey) || '', }); this._authMethodInterceptor = api.getApi().interceptors.request.use(awsInterceptor); } break; case 'bearerToken': if (!authMethod.variableName) api.setRequestHeader('Authorization', ''); } } teardownAuthMethod(api, authMethod) { if (this._authMethodInterceptor >= 0) { api.getApi().interceptors.request.eject(this._authMethodInterceptor); this._authMethodInterceptor = -1; } switch (authMethod.method) { case 'bearerToken': if (authMethod.variableName) { const tokenValue = this._testConfig.getVariableValue(authMethod.variableName); if (tokenValue) api.setRequestHeader('Authorization', 'Bearer ' + tokenValue); } } } saveJavaScriptEval(value, exp, replaceVars) { let ok = true; if (replaceVars) { exp = this._testConfig.replaceWithVarValue(exp); value = this._testConfig.replaceWithVarValue(value); } try { if (exp.includes('while') || exp.includes('for')) throw `Invalid JS Evaluation ${exp}`; ok = eval(exp) ? true : false; } catch (error) { this._logger.debug(error); ok = false; } return ok; } transform(transformers) { transformers.forEach((transformer) => { const vars = transformer.target.split(','); const value = this._testConfig.replaceWithVarValue(transformer.source); switch (transformer.type) { case 'extract': const regExp = new RegExp(transformer.from || ''); const results = regExp.exec(value); if (results) { if (results.length === 1) { if (vars.length > 0) this._testConfig.setVariableValue(vars[0], results[0]); } else { for (let idx = 1; idx < results.length; idx++) { if (vars.length >= idx) { this._testConfig.setVariableValue(vars[idx - 1], results[idx]); } } } } break; case 'replace': if (transformer.from || transformer.to) { const newValue = value.replace(transformer.from || '', transformer.to || ''); for (let idx = 0; idx < vars.length; idx++) { this._testConfig.setVariableValue(vars[idx], newValue); } } else { for (let idx = 0; idx < vars.length; idx++) { this._testConfig.setVariableValue(vars[idx], value); } } } }); } validate(requestResult, assertions) { const results = []; assertions.forEach((assertion) => { let ok = false; const description = this._testConfig.replaceWithVarValue(assertion.description); let value = ''; if (assertion.value) value = this._testConfig.replaceWithVarValue(assertion.value); const result = { source: requestResult.name, description: description, status: 'info', value: value, expression: '', }; switch (assertion.type) { case 'javaScript': try { const s = this._testConfig.replaceWithVarValue(assertion.expression); result.expression = s; //ok = eval(s) ok = this.saveJavaScriptEval(value, s); } catch (error) { // eslint-disable-next-line no-empty } break; case 'regexp': try { const regexp = new RegExp(assertion.expression); result.expression = assertion.expression; ok = regexp.test(value); // eslint-disable-next-line no-empty } catch (error) { } break; case 'value': result.expression = assertion.expression; ok = value == result.expression; break; } this._logger.debug('assertion status=%s, value= [%s] expression= [%s], desc= %s', result.status, result.value, result.expression, result.description); if (!ok) result.status = assertion.failStep ? 'failure' : 'warning'; if (!(assertion === null || assertion === void 0 ? void 0 : assertion.reportFailOnly) || !ok) results.push(result); }); return results; } extractValues(extractors, response) { let value; const results = []; extractors.forEach((elem) => { value = undefined; try { const extractor = elem; const expression = this._testConfig.replaceWithVarValue(extractor.expression); this.setVar(extractor.variable, ''); switch (extractor.type) { case 'jsonpath': if (response.data) { //let jp = jsonPath.query(response.data, extractor.expression) const jp = (0, jsonpath_plus_1.JSONPath)({ path: expression, json: response.data, }); if (jp) { if (extractor.counter) value = jp.length; else if (extractor.index) value = Math.floor(Math.random() * jp.length); else if (extractor.array) value = jp; else value = jp[Math.floor(Math.random() * jp.length)]; } } break; case 'xpath': if (response.data) { const p = new xmldom_1.default.DOMParser(); const xml = p.parseFromString(response.data); const nodes = xpath_1.default.select(expression, xml); if (nodes) { if (extractor.counter) value = nodes.length; else if (extractor.index) value = Math.floor(Math.random() * nodes.length); else if (nodes.length) { if (Array.isArray(nodes)) { if (extractor.array) { const a = []; nodes.forEach((node) => { const x = node; a.push(x.nodeValue || x.data); }); value = a; } else { const ne = nodes[Math.floor(Math.random() * nodes.length)]; value = ne.nodeValue || ne.data; } } else { value = nodes; } } } } break; case 'regexp': if (response.data) { const regexp = new RegExp(expression, 'gm'); const arr = [...response.data.matchAll(regexp)]; if (arr) { if (extractor.counter) value = arr.length; else if (extractor.index) value = Math.floor(Math.random() * arr.length); else if (arr.length > 0) { if (extractor.array) { const a = []; arr.forEach((elem) => { a.push(elem.length > 1 ? elem.slice(1).join('') : elem[0]); }); value = a; } else { const elem = arr[Math.floor(Math.random() * arr.length)]; if (elem.length > 1) value = elem.slice(1).join(''); else value = elem[0]; } } } } break; case 'header': const headers = response === null || response === void 0 ? void 0 : response.headers; if (headers) value = headers[expression]; break; case 'cookie': break; } this._logger.debug('extractor type=%s expression=%s value=%s', extractor.type, extractor.expression, value); if (value !== undefined) { this._testConfig.setVariableValue(extractor.variable, value); } else if (extractor.notFoundError) { const result = {}; result.description = `Extractor for variable ${extractor.variable} failed. Type=${extractor.type}`; result.expression = extractor.expression; results.push(result); } } catch (error) { this._logger.error(error); } }); return results; } runBeforeScripts(test, step, request, requestConfig) { const results = []; if (test && test.scripts) { test.scripts.forEach((script) => { if (script.script) { if (step && script.scope === 'beforeEach') results.push(this.runBeforeScript(script)); else if (!step && script.scope === 'before') results.push(this.runBeforeScript(script)); } }); } if (step && step.scripts) { step.scripts.forEach((script) => { if (script.script) { if (request && script.scope === 'beforeEach') results.push(this.runBeforeScript(script, requestConfig)); else if (!request && script.scope === 'before') results.push(this.runBeforeScript(script)); } }); } if (request && request.scripts) { request.scripts.forEach((script) => { if (script.scope === 'before' && script.script) results.push(this.runBeforeScript(script, requestConfig)); }); } return results; } runAfterScripts(test, step, request, response, timings) { const results = []; if (test && test.scripts) { test.scripts.forEach((script) => { if (script.script) { if (step && script.scope === 'afterEach') results.push(this.runAfterScript(script, response, timings)); else if (!step && script.scope === 'after') results.push(this.runAfterScript(script, response, timings)); } }); } if (step && step.scripts) { step.scripts.forEach((script) => { if (script.script) { if (request && script.scope === 'afterEach') results.push(this.runAfterScript(script, response, timings)); else if (!request && script.scope === 'after') results.push(this.runAfterScript(script, response, timings)); } }); } if (request && request.scripts) { request.scripts.forEach((script) => { if (script.scope === 'after' && script.script) results.push(this.runAfterScript(script, response, timings)); }); } return results; } runBeforeScript(script, requestConfig) { var _a; // eslint-disable-next-line @typescript-eslint/no-this-alias const uxs = this; const options = { sandbox: { uxs: uxs, expect: chai.expect, assert: chai.assert, requestConfig: requestConfig || null, logger: this._scriptLogger, }, require: { external: true, root: '/', builtin: ((_a = script === null || script === void 0 ? void 0 : script.options) === null || _a === void 0 ? void 0 : _a.builtin) ? script.options.builtin : [], }, }; return this.runScript(script, options); } runAfterScript(script, response, timings) { var _a; // eslint-disable-next-line @typescript-eslint/no-this-alias const uxs = this; let responseBody = response && response.data ? response.data : null; const responseData = response && response.data ? response.data : null; const responseType = helpers.whatIsIt(responseBody); if (responseType === 'Object' || responseType === 'Array') responseBody = JSON.stringify(responseBody); const context = { sandbox: { uxs: uxs, expect: chai.expect, assert: chai.assert, logger: this._scriptLogger, responseBody: responseBody, responseData: responseData, responseType: responseType, timings: timings ? helpers.clone(timings) : undefined, }, require: { external: true, root: '/', builtin: ((_a = script === null || script === void 0 ? void 0 : script.options) === null || _a === void 0 ? void 0 : _a.builtin) ? script.options.builtin : [], }, }; const result = this.runScript(script, context); return result; } runScript(script, options) { this._logger.trace('Running script name=%s, scope=%s,compiled=%s', script.name, script.scope, script.compiledScript ? true : false); const result = { ok: true, returnValue: undefined, script: script, }; //options.wrapper='none' try { const logLog = (m, ...args) => { this._scriptLogger.info(m, args); }; const logInfo = (m, ...args) => { this._scriptLogger.info(m, args); }; const logDebug = (m, ...args) => { this._scriptLogger.debug(m, args); }; const logError = (m, ...args) => { this._scriptLogger.error(m, args); }; const theVM = new vm.NodeVM(options); theVM.on('console.log', logLog); theVM.on('console.info', logInfo); theVM.on('console.debug', logDebug); theVM.on('console.error', logError); if (script.compiledScript) { const vmExports = theVM.run(script.compiledScript); if (vmExports === null || vmExports === void 0 ? void 0 : vmExports.asyncError) { this._logger.info('Return value from vm ', vmExports.asyncError); } } else { throw 'No compiled script to run'; } } catch (error) { this._logger.error('Script:[%s] error=%s:%s', script.name, error.name, error.message); result.ok = false; result.error = error; result.returnValue = error.name; } return result; } getVar(key) { return this._testConfig.getVariableValue(key); } request(config) { return __awaiter(this, void 0, void 0, function* () { const api = new api_1.Api(); return yield api.request(config); }); } getMustacheExpression(expression) { return this._testConfig.replaceWithVarValue(expression); } setVar(key, value) { this._testConfig.setVariableValue(key, value); } getATS() { return this._testConfig.getATS(); } } exports.PrePostProcessors = PrePostProcessors; //# sourceMappingURL=prePostProcessors.js.map