1 | (function (factory) {
|
2 | if (typeof module === "object" && typeof module.exports === "object") {
|
3 | var v = factory(require, exports);
|
4 | if (v !== undefined) module.exports = v;
|
5 | }
|
6 | else if (typeof define === "function" && define.amd) {
|
7 | define(["require", "exports", "tslib", "chai", "@theintern/common", "../Suite", "../common/ErrorFormatter", "../common/path", "../common/util", "../interfaces/object", "../interfaces/tdd", "../interfaces/bdd", "../interfaces/benchmark", "../common/console"], factory);
|
8 | }
|
9 | })(function (require, exports) {
|
10 | "use strict";
|
11 | Object.defineProperty(exports, "__esModule", { value: true });
|
12 | var tslib_1 = require("tslib");
|
13 | var chai = tslib_1.__importStar(require("chai"));
|
14 | var common_1 = require("@theintern/common");
|
15 | var Suite_1 = tslib_1.__importDefault(require("../Suite"));
|
16 | var ErrorFormatter_1 = tslib_1.__importDefault(require("../common/ErrorFormatter"));
|
17 | var path_1 = require("../common/path");
|
18 | var util_1 = require("../common/util");
|
19 | var object_1 = require("../interfaces/object");
|
20 | var tdd_1 = require("../interfaces/tdd");
|
21 | var bdd_1 = require("../interfaces/bdd");
|
22 | var benchmark_1 = require("../interfaces/benchmark");
|
23 | var console = tslib_1.__importStar(require("../common/console"));
|
24 | var BaseExecutor = (function () {
|
25 | function BaseExecutor(options) {
|
26 | var _this = this;
|
27 | this._hasSuiteErrors = false;
|
28 | this._hasTestErrors = false;
|
29 | this._hasEmittedErrors = false;
|
30 | this._config = {
|
31 | bail: false,
|
32 | baseline: false,
|
33 | benchmark: false,
|
34 | browser: {
|
35 | plugins: [],
|
36 | reporters: [],
|
37 | suites: []
|
38 | },
|
39 | coverageVariable: '__coverage__',
|
40 | debug: false,
|
41 | defaultTimeout: 30000,
|
42 | filterErrorStack: false,
|
43 | grep: new RegExp(''),
|
44 | loader: { script: 'default' },
|
45 | name: 'intern',
|
46 | node: {
|
47 | plugins: [],
|
48 | reporters: [],
|
49 | suites: []
|
50 | },
|
51 | plugins: [],
|
52 | reporters: [],
|
53 | sessionId: '',
|
54 | suites: []
|
55 | };
|
56 | this._reportersInitialized = false;
|
57 | this._events = [];
|
58 | this._listeners = {};
|
59 | this._reporters = [];
|
60 | this._plugins = {};
|
61 | this._loadingPlugins = [];
|
62 | this.registerInterface('object', object_1.getInterface(this));
|
63 | this.registerInterface('tdd', tdd_1.getInterface(this));
|
64 | this.registerInterface('bdd', bdd_1.getInterface(this));
|
65 | this.registerInterface('benchmark', benchmark_1.getInterface(this));
|
66 | this.registerPlugin('chai', function () { return chai; });
|
67 | if (options) {
|
68 | this.configure(options);
|
69 | }
|
70 | this._rootSuite = new Suite_1.default({ executor: this });
|
71 | this.on('suiteEnd', function (suite) {
|
72 | if (suite.error) {
|
73 | _this._hasSuiteErrors = true;
|
74 | }
|
75 | if (!suite.hasParent && !suite.sessionId) {
|
76 | return _this._emitCoverage('unit tests');
|
77 | }
|
78 | });
|
79 | this.on('testEnd', function (test) {
|
80 | if (test.error) {
|
81 | _this._hasTestErrors = true;
|
82 | }
|
83 | });
|
84 | }
|
85 | Object.defineProperty(BaseExecutor.prototype, "config", {
|
86 | get: function () {
|
87 | return this._config;
|
88 | },
|
89 | enumerable: false,
|
90 | configurable: true
|
91 | });
|
92 | Object.defineProperty(BaseExecutor.prototype, "suites", {
|
93 | get: function () {
|
94 | return [this._rootSuite];
|
95 | },
|
96 | enumerable: false,
|
97 | configurable: true
|
98 | });
|
99 | BaseExecutor.prototype.formatError = function (error, options) {
|
100 | if (!this._errorFormatter) {
|
101 | this._errorFormatter = new ErrorFormatter_1.default(this);
|
102 | }
|
103 | return this._errorFormatter.format(error, options);
|
104 | };
|
105 | BaseExecutor.prototype.addSuite = function (factory) {
|
106 | factory(this._rootSuite);
|
107 | };
|
108 | BaseExecutor.prototype.configure = function (options) {
|
109 | var _this = this;
|
110 | Object.keys(options).forEach(function (option) {
|
111 | var key = option;
|
112 | _this._processOption(key, options[key]);
|
113 | });
|
114 | };
|
115 | BaseExecutor.prototype.emit = function (eventName, data) {
|
116 | var _this = this;
|
117 | if (eventName === 'error') {
|
118 | this._hasEmittedErrors = true;
|
119 | }
|
120 | if (eventName === 'log' && !this.config.debug) {
|
121 | return common_1.Task.resolve();
|
122 | }
|
123 | if (!this._reportersInitialized) {
|
124 | this._events.push({ eventName: eventName, data: data });
|
125 | return common_1.Task.resolve();
|
126 | }
|
127 | var handleListenerError = function (error) {
|
128 | if (eventName === 'error') {
|
129 | console.error(_this.formatError(error));
|
130 | }
|
131 | else {
|
132 | return _this.emit('error', error);
|
133 | }
|
134 | };
|
135 | var error;
|
136 | if (eventName === 'error') {
|
137 | error = data;
|
138 | }
|
139 | var notifications = [];
|
140 | var listeners = this._listeners[eventName];
|
141 | if (listeners && listeners.length > 0) {
|
142 | for (var _i = 0, listeners_1 = listeners; _i < listeners_1.length; _i++) {
|
143 | var listener = listeners_1[_i];
|
144 | notifications.push(common_1.Task.resolve(listener(data)).catch(handleListenerError));
|
145 | }
|
146 | }
|
147 | var starListeners = this._listeners['*'];
|
148 | if (starListeners && starListeners.length > 0) {
|
149 | var starEvent = { name: eventName, data: data };
|
150 | for (var _a = 0, starListeners_1 = starListeners; _a < starListeners_1.length; _a++) {
|
151 | var listener = starListeners_1[_a];
|
152 | notifications.push(common_1.Task.resolve(listener(starEvent)).catch(handleListenerError));
|
153 | }
|
154 | }
|
155 | if (notifications.length === 0) {
|
156 | if (error && error instanceof Error) {
|
157 | console.error(this.formatError(error));
|
158 | error.reported = true;
|
159 | }
|
160 | else if (eventName === 'warning') {
|
161 | console.warn("WARNING: " + data);
|
162 | }
|
163 | else if (eventName === 'deprecated') {
|
164 | var message = data;
|
165 | console.warn("WARNING: " + message.original + " is deprecated, use " + message.replacement + " instead.");
|
166 | }
|
167 | return common_1.Task.resolve();
|
168 | }
|
169 | return common_1.Task.all(notifications)
|
170 | .then(function () { return undefined; })
|
171 | .finally(function () {
|
172 | if (error && error instanceof Error) {
|
173 | error.reported = true;
|
174 | }
|
175 | });
|
176 | };
|
177 | BaseExecutor.prototype.getInterface = function (name) {
|
178 | return this.getPlugin("interface." + name);
|
179 | };
|
180 | BaseExecutor.prototype.getPlugin = function (type, name) {
|
181 | var pluginName = typeof name === 'undefined' ? type : type + "." + name;
|
182 | if (!(pluginName in this._plugins)) {
|
183 | throw new Error("A plugin named \"" + pluginName + "\" has not been registered");
|
184 | }
|
185 | return this._plugins[pluginName];
|
186 | };
|
187 | BaseExecutor.prototype.log = function () {
|
188 | var args = [];
|
189 | for (var _i = 0; _i < arguments.length; _i++) {
|
190 | args[_i] = arguments[_i];
|
191 | }
|
192 | if (this.config.debug) {
|
193 | var message = args
|
194 | .map(function (arg) {
|
195 | var type = typeof arg;
|
196 | if (type === 'string') {
|
197 | return arg;
|
198 | }
|
199 | if (type === 'function' || arg instanceof RegExp) {
|
200 | return arg.toString();
|
201 | }
|
202 | if (arg instanceof Error) {
|
203 | arg = {
|
204 | name: arg.name,
|
205 | message: arg.message,
|
206 | stack: arg.stack
|
207 | };
|
208 | }
|
209 | try {
|
210 | return JSON.stringify(arg);
|
211 | }
|
212 | catch (error) {
|
213 | return arg.toString();
|
214 | }
|
215 | })
|
216 | .join(' ');
|
217 | return this.emit('log', message);
|
218 | }
|
219 | else {
|
220 | return common_1.Task.resolve();
|
221 | }
|
222 | };
|
223 | BaseExecutor.prototype.on = function (eventName, listener) {
|
224 | var _eventName;
|
225 | if (typeof listener === 'undefined') {
|
226 | listener = eventName;
|
227 | _eventName = '*';
|
228 | }
|
229 | else {
|
230 | _eventName = eventName;
|
231 | }
|
232 | var listeners = this._listeners[_eventName];
|
233 | if (!listeners) {
|
234 | listeners = this._listeners[_eventName] = [];
|
235 | }
|
236 | if (listeners.indexOf(listener) === -1) {
|
237 | listeners.push(listener);
|
238 | }
|
239 | var handle = {
|
240 | destroy: function () {
|
241 | this.destroy = function () { };
|
242 | util_1.pullFromArray(listeners, listener);
|
243 | }
|
244 | };
|
245 | return handle;
|
246 | };
|
247 | BaseExecutor.prototype.registerInterface = function (name, iface) {
|
248 | this.registerPlugin("interface." + name, function () { return iface; });
|
249 | };
|
250 | BaseExecutor.prototype.registerLoader = function (init) {
|
251 | var options = this._loaderOptions ? common_1.duplicate(this._loaderOptions) : {};
|
252 | this._loaderInit = Promise.resolve(init(options));
|
253 | };
|
254 | BaseExecutor.prototype.registerPlugin = function (type, name, init) {
|
255 | var pluginName = typeof init === 'undefined' ? type : type + "." + name;
|
256 | var pluginInit = typeof init === 'undefined' ? name : init;
|
257 | var options = this._loadingPluginOptions;
|
258 | var result = options ? pluginInit(common_1.duplicate(options)) : pluginInit();
|
259 | if (common_1.isPromiseLike(result)) {
|
260 | this._loadingPlugins.push({
|
261 | name: pluginName,
|
262 | init: new common_1.Task(function (resolve, reject) { return result.then(function (value) { return resolve(value); }, reject); }, function () {
|
263 | common_1.isTask(result) && result.cancel();
|
264 | })
|
265 | });
|
266 | }
|
267 | else {
|
268 | this._assignPlugin(pluginName, result);
|
269 | }
|
270 | };
|
271 | BaseExecutor.prototype.registerReporter = function (name, init) {
|
272 | this.registerPlugin('reporter', name, function () { return init; });
|
273 | };
|
274 | BaseExecutor.prototype.run = function () {
|
275 | var _this = this;
|
276 | if (!this._runTask) {
|
277 | var runError_1;
|
278 | try {
|
279 | this._runTask = this._resolveConfig();
|
280 | if (this.config.showConfig) {
|
281 | this._runTask = this._runTask
|
282 | .then(function () {
|
283 | var sort = function (value) {
|
284 | if (Array.isArray(value)) {
|
285 | value = value.map(sort).sort();
|
286 | }
|
287 | else if (typeof value === 'object' &&
|
288 | value.constructor === Object) {
|
289 | var newObj_1 = {};
|
290 | Object.keys(value)
|
291 | .sort()
|
292 | .forEach(function (key) {
|
293 | newObj_1[key] = sort(value[key]);
|
294 | });
|
295 | value = newObj_1;
|
296 | }
|
297 | return value;
|
298 | };
|
299 | console.log(JSON.stringify(sort(_this.config), function (_key, value) {
|
300 | if (value instanceof RegExp) {
|
301 | return value.toString();
|
302 | }
|
303 | return value;
|
304 | }, ' '));
|
305 | })
|
306 | .catch(function (error) {
|
307 | console.error(_this.formatError(error));
|
308 | throw error;
|
309 | });
|
310 | }
|
311 | else {
|
312 | var currentTask_1;
|
313 | this._runTask = this._runTask
|
314 | .then(function () { return _this._loadPlugins(); })
|
315 | .then(function () { return _this._loadLoader(); })
|
316 | .then(function () { return _this._loadPluginsWithLoader(); })
|
317 | .then(function () { return _this._initReporters(); })
|
318 | .then(function () { return _this._loadSuites(); })
|
319 | .then(function () { return _this._beforeRun(); })
|
320 | .then(function (skipTests) {
|
321 | if (skipTests) {
|
322 | return;
|
323 | }
|
324 | var outerTask;
|
325 | var testingTask;
|
326 | currentTask_1 = new common_1.Task(function (resolve, reject) {
|
327 | outerTask = _this.emit('beforeRun')
|
328 | .then(function () {
|
329 | return _this.emit('runStart')
|
330 | .then(function () { return (testingTask = _this._runTests()); })
|
331 | .catch(function (error) {
|
332 | runError_1 = error;
|
333 | return _this.emit('error', error);
|
334 | })
|
335 | .finally(function () { return _this.emit('runEnd'); });
|
336 | })
|
337 | .finally(function () { return _this.emit('afterRun'); })
|
338 | .then(resolve, reject);
|
339 | }, function () {
|
340 | if (testingTask) {
|
341 | testingTask.cancel();
|
342 | }
|
343 | if (outerTask) {
|
344 | outerTask.cancel();
|
345 | }
|
346 | });
|
347 | return currentTask_1;
|
348 | })
|
349 | .finally(function () {
|
350 | _this._reportersInitialized = true;
|
351 | return _this._drainEventQueue();
|
352 | })
|
353 | .finally(function () { return _this._afterRun(); })
|
354 | .finally(function () {
|
355 | if (currentTask_1) {
|
356 | currentTask_1.cancel();
|
357 | }
|
358 | })
|
359 | .catch(function (error) {
|
360 | return _this.emit('error', error).finally(function () {
|
361 | throw runError_1 || error;
|
362 | });
|
363 | })
|
364 | .then(function () {
|
365 | if (runError_1) {
|
366 | throw runError_1;
|
367 | }
|
368 | var message = '';
|
369 | if (_this._hasSuiteErrors) {
|
370 | message = 'One or more suite errors occurred during testing';
|
371 | }
|
372 | else if (_this._hasTestErrors) {
|
373 | message = 'One or more tests failed';
|
374 | }
|
375 | else if (_this._hasEmittedErrors) {
|
376 | message = 'An error was emitted';
|
377 | }
|
378 | if (message) {
|
379 | var error = new Error(message);
|
380 | error.reported = true;
|
381 | throw error;
|
382 | }
|
383 | });
|
384 | }
|
385 | }
|
386 | catch (error) {
|
387 | this._runTask = this.emit('error', error).then(function () {
|
388 | return common_1.Task.reject(error);
|
389 | });
|
390 | }
|
391 | }
|
392 | return this._runTask;
|
393 | };
|
394 | BaseExecutor.prototype._afterRun = function () {
|
395 | return common_1.Task.resolve();
|
396 | };
|
397 | BaseExecutor.prototype._assignPlugin = function (name, plugin) {
|
398 | if (name.indexOf('reporter.') === 0 && typeof plugin !== 'function') {
|
399 | throw new Error('A reporter plugin must be a constructor');
|
400 | }
|
401 | this._plugins[name] = plugin;
|
402 | };
|
403 | BaseExecutor.prototype._beforeRun = function () {
|
404 | var _a = this.config, bail = _a.bail, grep = _a.grep, name = _a.name, sessionId = _a.sessionId, defaultTimeout = _a.defaultTimeout;
|
405 | this._rootSuite.bail = bail;
|
406 | this._rootSuite.grep = grep;
|
407 | this._rootSuite.name = name;
|
408 | this._rootSuite.sessionId = sessionId;
|
409 | this._rootSuite.timeout = defaultTimeout;
|
410 | return common_1.Task.resolve(false);
|
411 | };
|
412 | BaseExecutor.prototype._initReporters = function () {
|
413 | var config = this.config;
|
414 | var envReporters = config[this.environment].reporters;
|
415 | var baseReporters = config.reporters.filter(function (reporter) {
|
416 | return !envReporters.some(function (envReporter) { return envReporter.name === reporter.name; });
|
417 | });
|
418 | for (var _i = 0, _a = tslib_1.__spreadArray(tslib_1.__spreadArray([], baseReporters), envReporters); _i < _a.length; _i++) {
|
419 | var reporter = _a[_i];
|
420 | var initializer = this.getPlugin('reporter', reporter.name);
|
421 | if (!initializer) {
|
422 | throw new Error("A reporter named " + reporter.name + " hasn't been registered");
|
423 | }
|
424 | if (typeof initializer !== 'function') {
|
425 | throw new Error("The reporter " + reporter.name + " isn't a valid initializer");
|
426 | }
|
427 | this._reporters.push(initializer(reporter.options));
|
428 | }
|
429 | this._reportersInitialized = true;
|
430 | return this._drainEventQueue();
|
431 | };
|
432 | BaseExecutor.prototype._drainEventQueue = function () {
|
433 | var _this = this;
|
434 | var task = common_1.Task.resolve();
|
435 | var _loop_1 = function () {
|
436 | var event_1 = this_1._events.shift();
|
437 | task = task.then(function () {
|
438 | return _this.emit(event_1.eventName, event_1.data);
|
439 | });
|
440 | };
|
441 | var this_1 = this;
|
442 | while (this._events.length > 0) {
|
443 | _loop_1();
|
444 | }
|
445 | return task;
|
446 | };
|
447 | BaseExecutor.prototype._emitCoverage = function (source) {
|
448 | var coverage = common_1.global[this.config.coverageVariable];
|
449 | if (coverage) {
|
450 | return this.emit('coverage', {
|
451 | coverage: coverage,
|
452 | source: source,
|
453 | sessionId: this.config.sessionId
|
454 | });
|
455 | }
|
456 | };
|
457 | BaseExecutor.prototype._loadLoader = function () {
|
458 | var _this = this;
|
459 | if (this._loaderInit) {
|
460 | return this._loaderInit.then(function (loader) {
|
461 | _this._loader = loader;
|
462 | });
|
463 | }
|
464 | else {
|
465 | var config = this.config;
|
466 | var loader = config[this.environment].loader || config.loader;
|
467 | var script_1 = loader.script;
|
468 | switch (script_1) {
|
469 | case 'default':
|
470 | case 'dojo':
|
471 | case 'dojo2':
|
472 | case 'esm':
|
473 | case 'systemjs':
|
474 | script_1 = config.internPath + "loaders/" + script_1 + ".js";
|
475 | }
|
476 | this._loaderOptions = loader.options || {};
|
477 | return this.loadScript(script_1)
|
478 | .then(function () {
|
479 | if (!_this._loaderInit) {
|
480 | throw new Error("Loader script " + script_1 + " did not register a loader callback");
|
481 | }
|
482 | return _this._loaderInit;
|
483 | })
|
484 | .then(function (loader) {
|
485 | _this._loader = loader;
|
486 | });
|
487 | }
|
488 | };
|
489 | BaseExecutor.prototype._loadPluginsWithLoader = function () {
|
490 | var _this = this;
|
491 | var scripts = tslib_1.__spreadArray(tslib_1.__spreadArray([], this.config.plugins), this.config[this.environment].plugins).filter(function (plugin) { return plugin.useLoader; });
|
492 | return this._loadScripts(scripts, function (script) { return _this._loader([script]); });
|
493 | };
|
494 | BaseExecutor.prototype._loadPlugins = function () {
|
495 | var _this = this;
|
496 | var scripts = tslib_1.__spreadArray(tslib_1.__spreadArray([], this.config.plugins), this.config[this.environment].plugins).filter(function (plugin) { return !plugin.useLoader; });
|
497 | return this._loadScripts(scripts, function (script) { return _this.loadScript(script); });
|
498 | };
|
499 | BaseExecutor.prototype._loadScripts = function (scripts, loader) {
|
500 | var _this = this;
|
501 | return scripts
|
502 | .reduce(function (previous, script) {
|
503 | if (typeof script === 'string') {
|
504 | return previous.then(function () { return loader(script); });
|
505 | }
|
506 | else {
|
507 | return previous
|
508 | .then(function () {
|
509 | _this._loadingPluginOptions = script.options;
|
510 | })
|
511 | .then(function () { return loader(script.script); })
|
512 | .then(function () {
|
513 | _this._loadingPluginOptions = undefined;
|
514 | });
|
515 | }
|
516 | }, common_1.Task.resolve())
|
517 | .then(function () {
|
518 | return common_1.Task.all(_this._loadingPlugins.map(function (entry) { return entry.init; })).then(function (plugins) {
|
519 | plugins.forEach(function (plugin, index) {
|
520 | _this._assignPlugin(_this._loadingPlugins[index].name, plugin);
|
521 | });
|
522 | });
|
523 | });
|
524 | };
|
525 | BaseExecutor.prototype._loadSuites = function () {
|
526 | var _this = this;
|
527 | var suites = this.config[this.environment].suites;
|
528 | return common_1.Task.resolve(this._loader(suites)).then(function () {
|
529 | _this.log('Loaded suites:', suites);
|
530 | });
|
531 | };
|
532 | BaseExecutor.prototype._processOption = function (key, value) {
|
533 | util_1.processOption(key, value, this.config, this);
|
534 | };
|
535 | BaseExecutor.prototype._resolveConfig = function () {
|
536 | var config = this.config;
|
537 | if (config.internPath != null) {
|
538 | config.internPath = path_1.normalizePathEnding(config.internPath);
|
539 | }
|
540 | else {
|
541 | config.internPath = '';
|
542 | }
|
543 | if (config.benchmark) {
|
544 | config.benchmarkConfig = common_1.deepMixin({
|
545 | mode: config.baseline ? 'baseline' : 'test',
|
546 | id: 'Benchmark',
|
547 | filename: 'baseline.json',
|
548 | thresholds: {
|
549 | warn: { rme: 3, mean: 5 },
|
550 | fail: { rme: 6, mean: 10 }
|
551 | },
|
552 | verbosity: 0
|
553 | }, config.benchmarkConfig || {});
|
554 | }
|
555 | return common_1.Task.resolve();
|
556 | };
|
557 | BaseExecutor.prototype._runTests = function () {
|
558 | return this._rootSuite.run();
|
559 | };
|
560 | return BaseExecutor;
|
561 | }());
|
562 | exports.default = BaseExecutor;
|
563 | });
|
564 |
|
\ | No newline at end of file |