@apica-io/url-xi
Version:
URL Check for integrations and API monitoring
482 lines • 21.6 kB
JavaScript
"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