UNPKG

17.7 kBJavaScriptView Raw
1"use strict";
2var __assign = (this && this.__assign) || function () {
3 __assign = Object.assign || function(t) {
4 for (var s, i = 1, n = arguments.length; i < n; i++) {
5 s = arguments[i];
6 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 t[p] = s[p];
8 }
9 return t;
10 };
11 return __assign.apply(this, arguments);
12};
13var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15 return new (P || (P = Promise))(function (resolve, reject) {
16 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19 step((generator = generator.apply(thisArg, _arguments || [])).next());
20 });
21};
22var __generator = (this && this.__generator) || function (thisArg, body) {
23 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25 function verb(n) { return function (v) { return step([n, v]); }; }
26 function step(op) {
27 if (f) throw new TypeError("Generator is already executing.");
28 while (_) try {
29 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30 if (y = 0, t) op = [op[0] & 2, t.value];
31 switch (op[0]) {
32 case 0: case 1: t = op; break;
33 case 4: _.label++; return { value: op[1], done: false };
34 case 5: _.label++; y = op[1]; op = [0]; continue;
35 case 7: op = _.ops.pop(); _.trys.pop(); continue;
36 default:
37 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41 if (t[2]) _.ops.pop();
42 _.trys.pop(); continue;
43 }
44 op = body.call(thisArg, _);
45 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47 }
48};
49Object.defineProperty(exports, "__esModule", { value: true });
50var pad = require("pad");
51var querystring_1 = require("querystring");
52var actionLoading_1 = require("./actionLoading");
53var diagramDrawing_1 = require("./diagramDrawing");
54var logging_1 = require("./logging");
55var ActionType_1 = require("./model/ActionType");
56var TestResult_1 = require("./model/TestResult");
57var scenarioLoading_1 = require("./scenarioLoading");
58var yamlParsing_1 = require("./yamlParsing");
59var RESULTS = new Map();
60var OUT_DIR = '';
61// increase the pixel-size (width/height) limit of PlantUML (the default is 4096 which is not enough for some diagrams)
62process.env.PLANTUML_LIMIT_SIZE = '16384';
63/**
64 * @deprecated since 1.8.0, use {@link runMultipleScenariosWithConfig} instead
65 */
66exports.runMultipleSceanriosWithConfig = function (actionDir, outDir, envConfigDir, runConfig, scenarioPaths) {
67 if (outDir === void 0) { outDir = 'out'; }
68 return exports.runMultipleScenariosWithConfig(actionDir, outDir, envConfigDir, runConfig, scenarioPaths);
69};
70exports.runMultipleScenariosWithConfig = function (actionDir, outDir, envConfigDir, runConfig, scenarioPaths) {
71 if (outDir === void 0) { outDir = 'out'; }
72 exports.runMultipleScenariosWithConfigAsync(actionDir, outDir, envConfigDir, runConfig, scenarioPaths).then(function (result) {
73 if (!result)
74 process.exit(1);
75 });
76};
77exports.runMultipleScenariosWithConfigAsync = function (actionDir, outDir, envConfigDir, runConfig, scenarioPaths) {
78 if (outDir === void 0) { outDir = 'out'; }
79 return __awaiter(void 0, void 0, void 0, function () {
80 var _a, numberOfScenariosRunInParallel, _b, environmentNameToBeUsed, _c, drawDiagrams, envConfig, actions_1, resultPromises_1, results, e_1;
81 return __generator(this, function (_d) {
82 switch (_d.label) {
83 case 0:
84 // TODO: global variables should be avoided
85 RESULTS.clear();
86 _a = runConfig.numberOfScenariosRunInParallel, numberOfScenariosRunInParallel = _a === void 0 ? 10 : _a, _b = runConfig.environmentNameToBeUsed, environmentNameToBeUsed = _b === void 0 ? 'none' : _b, _c = runConfig.drawDiagrams, drawDiagrams = _c === void 0 ? true : _c;
87 _d.label = 1;
88 case 1:
89 _d.trys.push([1, 3, , 4]);
90 if (typeof scenarioPaths === 'undefined' ||
91 scenarioPaths.length === 0) {
92 logging_1.getLogger().error('Please provide correct path(s) to the SCENARIO file!');
93 process.exit(1);
94 }
95 if (typeof actionDir === 'undefined' || actionDir === '') {
96 logging_1.getLogger().error('Please provide correct path to the ACTION files!');
97 process.exit(1);
98 }
99 logging_1.getLogger('setup').info("RUNNING: scenario(s): " + scenarioPaths + " (actions: " + actionDir + ", out: " + outDir + ", envDir: " + envConfigDir + ", numberOfScenariosRunInParallel: " + numberOfScenariosRunInParallel + ", environmentNameToBeUsed: " + environmentNameToBeUsed + ")");
100 OUT_DIR = outDir;
101 envConfig = envConfigDir
102 ? yamlParsing_1.loadYamlConfiguration(envConfigDir + "/" + environmentNameToBeUsed + ".yaml")
103 : {};
104 logging_1.getLogger('setup').debug("Using '" + environmentNameToBeUsed + "' configuration: " + querystring_1.stringify(envConfig));
105 actions_1 = actionLoading_1.loadAllActions(actionDir, envConfig);
106 logging_1.getLogger('setup').debug("Successfully loaded " + actions_1.length + " actions");
107 resultPromises_1 = [];
108 scenarioPaths.forEach(function (scenarioPath) {
109 logging_1.getLogger('setup').debug("Loading: " + scenarioPath + " ...");
110 var scenarios = scenarioPath.endsWith('yaml')
111 ? scenarioLoading_1.loadScenariosById(scenarioPath, actions_1)
112 : scenarioLoading_1.loadAllScenarios(scenarioPath, actions_1);
113 logging_1.getLogger('setup').debug("Successfully loaded " + scenarios.length + " scenario(s): " + scenarioPath);
114 resultPromises_1.push(processScenarios(scenarios, numberOfScenariosRunInParallel, drawDiagrams));
115 });
116 return [4 /*yield*/, Promise.all(resultPromises_1)];
117 case 2:
118 results = _d.sent();
119 return [2 /*return*/, results.every(function (result) { return result; })];
120 case 3:
121 e_1 = _d.sent();
122 logging_1.getLogger('setup').error(e_1);
123 return [2 /*return*/, false];
124 case 4: return [2 /*return*/];
125 }
126 });
127 });
128};
129/**
130 * @deprecated since 1.5.0, use {@link runMultipleSceanriosWithConfig} or
131 * {@link runMultipleSceanriosWithConfigAsync} instead
132 */
133exports.runScenario = function (scenarioPath, actionDir, outDir, envConfigFile) {
134 if (outDir === void 0) { outDir = 'out'; }
135 exports.runMultipleSceanriosWithConfig(actionDir, outDir, envConfigFile.substring(0, envConfigFile.length - 12) /* substracting '/config.yaml' from the string */, { environmentNameToBeUsed: 'config' }, [scenarioPath]);
136};
137function processScenarios(scenarios, numberOfScenariosRunInParallel, drawDiagrams) {
138 return __awaiter(this, void 0, void 0, function () {
139 var i;
140 return __generator(this, function (_a) {
141 switch (_a.label) {
142 case 0:
143 i = 0;
144 _a.label = 1;
145 case 1:
146 if (!(i < scenarios.length)) return [3 /*break*/, 4];
147 // eslint-disable-next-line no-await-in-loop
148 return [4 /*yield*/, Promise.all(scenarios
149 .slice(i, i + numberOfScenariosRunInParallel)
150 .map(invokeActionsSynchronously))];
151 case 2:
152 // eslint-disable-next-line no-await-in-loop
153 _a.sent();
154 _a.label = 3;
155 case 3:
156 i += numberOfScenariosRunInParallel;
157 return [3 /*break*/, 1];
158 case 4:
159 printResults();
160 return [2 /*return*/, generateDiagramsAndDetermineSuccess(drawDiagrams)];
161 }
162 });
163 });
164}
165function invokeActionsSynchronously(scenario) {
166 return __awaiter(this, void 0, void 0, function () {
167 var scenarioName, ctx, MSG_WIDTH, timeDiffInMs, successful, actionsToCancel, actionsToAwaitAtEnd, handleError, _loop_1, _i, _a, action;
168 return __generator(this, function (_b) {
169 switch (_b.label) {
170 case 0:
171 scenarioName = scenario.name;
172 RESULTS.set(scenarioName, []);
173 ctx = { scenario: scenarioName };
174 MSG_WIDTH = 100;
175 logging_1.getLogger(scenarioName).debug(pad(MSG_WIDTH, '#', '#'), ctx);
176 logging_1.getLogger(scenarioName).debug(pad("#### (S): " + scenarioName + ": " + scenario.description + " ", MSG_WIDTH, '#'), ctx);
177 logging_1.getLogger(scenarioName).debug(pad(MSG_WIDTH, '#', '#'), ctx);
178 diagramDrawing_1.initDiagramCreation(scenarioName);
179 timeDiffInMs = function (stop) {
180 return (stop[0] * 1e9 + stop[1]) * 1e-6;
181 };
182 successful = true;
183 actionsToCancel = [];
184 actionsToAwaitAtEnd = [];
185 handleError = function (reason, action, start, context) {
186 var duration = timeDiffInMs(process.hrtime(start)).toFixed(2);
187 var scenarioResults = RESULTS.get(scenarioName);
188 if (scenarioResults)
189 scenarioResults.push(new TestResult_1.TestResult(action.description, duration, false, action.allowFailure));
190 if (reason)
191 logging_1.getLogger(scenario.name).error(reason instanceof Error
192 ? reason.toString()
193 : JSON.stringify(reason), context);
194 logging_1.getLogger(scenario.name).info(pad(MSG_WIDTH, " Time: " + duration + " ms ###########", '#'), context);
195 if (action.allowFailure !== true) {
196 successful = false;
197 }
198 };
199 _loop_1 = function (action) {
200 var context_1, start, actionCallback, actionPromise;
201 return __generator(this, function (_a) {
202 switch (_a.label) {
203 case 0:
204 if (!successful) {
205 // after first ERROR skip further actions unless 'Action#invokeEvenOnFail' is set to TRUE
206 if (!action.invokeEvenOnFail)
207 return [2 /*return*/, "continue"];
208 }
209 context_1 = __assign(__assign({}, ctx), { action: action.name });
210 logging_1.getLogger(scenarioName).info(pad("#### (A): " + action.description + " ", MSG_WIDTH, '#'), context_1);
211 start = process.hrtime();
212 actionCallback = action.invoke(scenario);
213 actionPromise = actionCallback.promise
214 .then(function (result) {
215 var duration = timeDiffInMs(process.hrtime(start)).toFixed(2);
216 var scenarioResults = RESULTS.get(scenarioName);
217 if (scenarioResults)
218 scenarioResults.push(new TestResult_1.TestResult(action.description, duration, true, action.allowFailure));
219 if (result)
220 logging_1.getLogger(scenario.name).debug(JSON.stringify(result), context_1);
221 logging_1.getLogger(scenario.name).info(pad(MSG_WIDTH, " Time: " + duration + " ms ###########", '#'), context_1);
222 })
223 .catch(function (reason) { return handleError(reason, action, start, context_1); });
224 if (action.type === ActionType_1.ActionType.WEBSOCKET ||
225 action.type === ActionType_1.ActionType.AMQP_LISTEN) {
226 actionsToCancel.push(actionCallback);
227 }
228 if (!(action.type === ActionType_1.ActionType.MQTT ||
229 action.type === ActionType_1.ActionType.WEBSOCKET ||
230 action.type === ActionType_1.ActionType.AMQP_LISTEN)) return [3 /*break*/, 1];
231 actionsToAwaitAtEnd.push(actionPromise);
232 return [3 /*break*/, 3];
233 case 1: return [4 /*yield*/, actionPromise];
234 case 2:
235 _a.sent(); // eslint-disable-line no-await-in-loop
236 _a.label = 3;
237 case 3: return [2 /*return*/];
238 }
239 });
240 };
241 _i = 0, _a = scenario.actions;
242 _b.label = 1;
243 case 1:
244 if (!(_i < _a.length)) return [3 /*break*/, 4];
245 action = _a[_i];
246 return [5 /*yield**/, _loop_1(action)];
247 case 2:
248 _b.sent();
249 _b.label = 3;
250 case 3:
251 _i++;
252 return [3 /*break*/, 1];
253 case 4:
254 // stop all async running actions
255 actionsToCancel.forEach(function (callback) { return callback.cancel(); });
256 return [4 /*yield*/, Promise.all(actionsToAwaitAtEnd)];
257 case 5:
258 _b.sent();
259 return [2 /*return*/];
260 }
261 });
262 });
263}
264function printResults() {
265 RESULTS.forEach(function (result, scenario) {
266 var ctx = { scenario: scenario };
267 var MSG_WIDTH = 100;
268 logging_1.getLogger(scenario).info(pad("#### SUMMARY: " + scenario + " ", MSG_WIDTH, '#'), ctx);
269 result.forEach(function (res) {
270 if (res.successful) {
271 logging_1.getLogger(scenario).info(" OK: " + pad(res.action, 50) + " " + res.duration + " ms", ctx);
272 }
273 else if (res.allowFailure) {
274 logging_1.getLogger(scenario).info("IGN: " + pad(res.action, 50) + " " + res.duration + " ms", ctx);
275 }
276 else {
277 logging_1.getLogger(scenario).info("NOK: " + pad(res.action, 50) + " " + res.duration + " ms", ctx);
278 }
279 });
280 logging_1.getLogger(scenario).info(pad(MSG_WIDTH, '#', '#'), ctx);
281 });
282}
283function generateDiagramsAndDetermineSuccess(drawDiagrams) {
284 return __awaiter(this, void 0, void 0, function () {
285 var anyError, diagrams;
286 return __generator(this, function (_a) {
287 switch (_a.label) {
288 case 0:
289 anyError = false;
290 diagrams = [];
291 RESULTS.forEach(function (results, scenario) {
292 if (drawDiagrams) {
293 diagrams.push(diagramDrawing_1.generateSequenceDiagram(scenario));
294 }
295 anyError =
296 anyError || results.some(function (result) { return result.isConsideredFailure(); });
297 });
298 return [4 /*yield*/, Promise.all(diagrams)];
299 case 1:
300 _a.sent();
301 return [2 /*return*/, !anyError];
302 }
303 });
304 });
305}
306exports.OUTPUT_DIR = function () { return OUT_DIR; };