UNPKG

intern

Version:

Intern. A next-generation code testing stack for JavaScript.

564 lines 25.5 kB
(function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { 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); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var chai = tslib_1.__importStar(require("chai")); var common_1 = require("@theintern/common"); var Suite_1 = tslib_1.__importDefault(require("../Suite")); var ErrorFormatter_1 = tslib_1.__importDefault(require("../common/ErrorFormatter")); var path_1 = require("../common/path"); var util_1 = require("../common/util"); var object_1 = require("../interfaces/object"); var tdd_1 = require("../interfaces/tdd"); var bdd_1 = require("../interfaces/bdd"); var benchmark_1 = require("../interfaces/benchmark"); var console = tslib_1.__importStar(require("../common/console")); var BaseExecutor = (function () { function BaseExecutor(options) { var _this = this; this._hasSuiteErrors = false; this._hasTestErrors = false; this._hasEmittedErrors = false; this._config = { bail: false, baseline: false, benchmark: false, browser: { plugins: [], reporters: [], suites: [] }, coverageVariable: '__coverage__', debug: false, defaultTimeout: 30000, filterErrorStack: false, grep: new RegExp(''), loader: { script: 'default' }, name: 'intern', node: { plugins: [], reporters: [], suites: [] }, plugins: [], reporters: [], sessionId: '', suites: [] }; this._reportersInitialized = false; this._events = []; this._listeners = {}; this._reporters = []; this._plugins = {}; this._loadingPlugins = []; this.registerInterface('object', object_1.getInterface(this)); this.registerInterface('tdd', tdd_1.getInterface(this)); this.registerInterface('bdd', bdd_1.getInterface(this)); this.registerInterface('benchmark', benchmark_1.getInterface(this)); this.registerPlugin('chai', function () { return chai; }); if (options) { this.configure(options); } this._rootSuite = new Suite_1.default({ executor: this }); this.on('suiteEnd', function (suite) { if (suite.error) { _this._hasSuiteErrors = true; } if (!suite.hasParent && !suite.sessionId) { return _this._emitCoverage('unit tests'); } }); this.on('testEnd', function (test) { if (test.error) { _this._hasTestErrors = true; } }); } Object.defineProperty(BaseExecutor.prototype, "config", { get: function () { return this._config; }, enumerable: false, configurable: true }); Object.defineProperty(BaseExecutor.prototype, "suites", { get: function () { return [this._rootSuite]; }, enumerable: false, configurable: true }); BaseExecutor.prototype.formatError = function (error, options) { if (!this._errorFormatter) { this._errorFormatter = new ErrorFormatter_1.default(this); } return this._errorFormatter.format(error, options); }; BaseExecutor.prototype.addSuite = function (factory) { factory(this._rootSuite); }; BaseExecutor.prototype.configure = function (options) { var _this = this; Object.keys(options).forEach(function (option) { var key = option; _this._processOption(key, options[key]); }); }; BaseExecutor.prototype.emit = function (eventName, data) { var _this = this; if (eventName === 'error') { this._hasEmittedErrors = true; } if (eventName === 'log' && !this.config.debug) { return common_1.Task.resolve(); } if (!this._reportersInitialized) { this._events.push({ eventName: eventName, data: data }); return common_1.Task.resolve(); } var handleListenerError = function (error) { if (eventName === 'error') { console.error(_this.formatError(error)); } else { return _this.emit('error', error); } }; var error; if (eventName === 'error') { error = data; } var notifications = []; var listeners = this._listeners[eventName]; if (listeners && listeners.length > 0) { for (var _i = 0, listeners_1 = listeners; _i < listeners_1.length; _i++) { var listener = listeners_1[_i]; notifications.push(common_1.Task.resolve(listener(data)).catch(handleListenerError)); } } var starListeners = this._listeners['*']; if (starListeners && starListeners.length > 0) { var starEvent = { name: eventName, data: data }; for (var _a = 0, starListeners_1 = starListeners; _a < starListeners_1.length; _a++) { var listener = starListeners_1[_a]; notifications.push(common_1.Task.resolve(listener(starEvent)).catch(handleListenerError)); } } if (notifications.length === 0) { if (error && error instanceof Error) { console.error(this.formatError(error)); error.reported = true; } else if (eventName === 'warning') { console.warn("WARNING: " + data); } else if (eventName === 'deprecated') { var message = data; console.warn("WARNING: " + message.original + " is deprecated, use " + message.replacement + " instead."); } return common_1.Task.resolve(); } return common_1.Task.all(notifications) .then(function () { return undefined; }) .finally(function () { if (error && error instanceof Error) { error.reported = true; } }); }; BaseExecutor.prototype.getInterface = function (name) { return this.getPlugin("interface." + name); }; BaseExecutor.prototype.getPlugin = function (type, name) { var pluginName = typeof name === 'undefined' ? type : type + "." + name; if (!(pluginName in this._plugins)) { throw new Error("A plugin named \"" + pluginName + "\" has not been registered"); } return this._plugins[pluginName]; }; BaseExecutor.prototype.log = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (this.config.debug) { var message = args .map(function (arg) { var type = typeof arg; if (type === 'string') { return arg; } if (type === 'function' || arg instanceof RegExp) { return arg.toString(); } if (arg instanceof Error) { arg = { name: arg.name, message: arg.message, stack: arg.stack }; } try { return JSON.stringify(arg); } catch (error) { return arg.toString(); } }) .join(' '); return this.emit('log', message); } else { return common_1.Task.resolve(); } }; BaseExecutor.prototype.on = function (eventName, listener) { var _eventName; if (typeof listener === 'undefined') { listener = eventName; _eventName = '*'; } else { _eventName = eventName; } var listeners = this._listeners[_eventName]; if (!listeners) { listeners = this._listeners[_eventName] = []; } if (listeners.indexOf(listener) === -1) { listeners.push(listener); } var handle = { destroy: function () { this.destroy = function () { }; util_1.pullFromArray(listeners, listener); } }; return handle; }; BaseExecutor.prototype.registerInterface = function (name, iface) { this.registerPlugin("interface." + name, function () { return iface; }); }; BaseExecutor.prototype.registerLoader = function (init) { var options = this._loaderOptions ? common_1.duplicate(this._loaderOptions) : {}; this._loaderInit = Promise.resolve(init(options)); }; BaseExecutor.prototype.registerPlugin = function (type, name, init) { var pluginName = typeof init === 'undefined' ? type : type + "." + name; var pluginInit = typeof init === 'undefined' ? name : init; var options = this._loadingPluginOptions; var result = options ? pluginInit(common_1.duplicate(options)) : pluginInit(); if (common_1.isPromiseLike(result)) { this._loadingPlugins.push({ name: pluginName, init: new common_1.Task(function (resolve, reject) { return result.then(function (value) { return resolve(value); }, reject); }, function () { common_1.isTask(result) && result.cancel(); }) }); } else { this._assignPlugin(pluginName, result); } }; BaseExecutor.prototype.registerReporter = function (name, init) { this.registerPlugin('reporter', name, function () { return init; }); }; BaseExecutor.prototype.run = function () { var _this = this; if (!this._runTask) { var runError_1; try { this._runTask = this._resolveConfig(); if (this.config.showConfig) { this._runTask = this._runTask .then(function () { var sort = function (value) { if (Array.isArray(value)) { value = value.map(sort).sort(); } else if (typeof value === 'object' && value.constructor === Object) { var newObj_1 = {}; Object.keys(value) .sort() .forEach(function (key) { newObj_1[key] = sort(value[key]); }); value = newObj_1; } return value; }; console.log(JSON.stringify(sort(_this.config), function (_key, value) { if (value instanceof RegExp) { return value.toString(); } return value; }, ' ')); }) .catch(function (error) { console.error(_this.formatError(error)); throw error; }); } else { var currentTask_1; this._runTask = this._runTask .then(function () { return _this._loadPlugins(); }) .then(function () { return _this._loadLoader(); }) .then(function () { return _this._loadPluginsWithLoader(); }) .then(function () { return _this._initReporters(); }) .then(function () { return _this._loadSuites(); }) .then(function () { return _this._beforeRun(); }) .then(function (skipTests) { if (skipTests) { return; } var outerTask; var testingTask; currentTask_1 = new common_1.Task(function (resolve, reject) { outerTask = _this.emit('beforeRun') .then(function () { return _this.emit('runStart') .then(function () { return (testingTask = _this._runTests()); }) .catch(function (error) { runError_1 = error; return _this.emit('error', error); }) .finally(function () { return _this.emit('runEnd'); }); }) .finally(function () { return _this.emit('afterRun'); }) .then(resolve, reject); }, function () { if (testingTask) { testingTask.cancel(); } if (outerTask) { outerTask.cancel(); } }); return currentTask_1; }) .finally(function () { _this._reportersInitialized = true; return _this._drainEventQueue(); }) .finally(function () { return _this._afterRun(); }) .finally(function () { if (currentTask_1) { currentTask_1.cancel(); } }) .catch(function (error) { return _this.emit('error', error).finally(function () { throw runError_1 || error; }); }) .then(function () { if (runError_1) { throw runError_1; } var message = ''; if (_this._hasSuiteErrors) { message = 'One or more suite errors occurred during testing'; } else if (_this._hasTestErrors) { message = 'One or more tests failed'; } else if (_this._hasEmittedErrors) { message = 'An error was emitted'; } if (message) { var error = new Error(message); error.reported = true; throw error; } }); } } catch (error) { this._runTask = this.emit('error', error).then(function () { return common_1.Task.reject(error); }); } } return this._runTask; }; BaseExecutor.prototype._afterRun = function () { return common_1.Task.resolve(); }; BaseExecutor.prototype._assignPlugin = function (name, plugin) { if (name.indexOf('reporter.') === 0 && typeof plugin !== 'function') { throw new Error('A reporter plugin must be a constructor'); } this._plugins[name] = plugin; }; BaseExecutor.prototype._beforeRun = function () { var _a = this.config, bail = _a.bail, grep = _a.grep, name = _a.name, sessionId = _a.sessionId, defaultTimeout = _a.defaultTimeout; this._rootSuite.bail = bail; this._rootSuite.grep = grep; this._rootSuite.name = name; this._rootSuite.sessionId = sessionId; this._rootSuite.timeout = defaultTimeout; return common_1.Task.resolve(false); }; BaseExecutor.prototype._initReporters = function () { var config = this.config; var envReporters = config[this.environment].reporters; var baseReporters = config.reporters.filter(function (reporter) { return !envReporters.some(function (envReporter) { return envReporter.name === reporter.name; }); }); for (var _i = 0, _a = tslib_1.__spreadArray(tslib_1.__spreadArray([], baseReporters), envReporters); _i < _a.length; _i++) { var reporter = _a[_i]; var initializer = this.getPlugin('reporter', reporter.name); if (!initializer) { throw new Error("A reporter named " + reporter.name + " hasn't been registered"); } if (typeof initializer !== 'function') { throw new Error("The reporter " + reporter.name + " isn't a valid initializer"); } this._reporters.push(initializer(reporter.options)); } this._reportersInitialized = true; return this._drainEventQueue(); }; BaseExecutor.prototype._drainEventQueue = function () { var _this = this; var task = common_1.Task.resolve(); var _loop_1 = function () { var event_1 = this_1._events.shift(); task = task.then(function () { return _this.emit(event_1.eventName, event_1.data); }); }; var this_1 = this; while (this._events.length > 0) { _loop_1(); } return task; }; BaseExecutor.prototype._emitCoverage = function (source) { var coverage = common_1.global[this.config.coverageVariable]; if (coverage) { return this.emit('coverage', { coverage: coverage, source: source, sessionId: this.config.sessionId }); } }; BaseExecutor.prototype._loadLoader = function () { var _this = this; if (this._loaderInit) { return this._loaderInit.then(function (loader) { _this._loader = loader; }); } else { var config = this.config; var loader = config[this.environment].loader || config.loader; var script_1 = loader.script; switch (script_1) { case 'default': case 'dojo': case 'dojo2': case 'esm': case 'systemjs': script_1 = config.internPath + "loaders/" + script_1 + ".js"; } this._loaderOptions = loader.options || {}; return this.loadScript(script_1) .then(function () { if (!_this._loaderInit) { throw new Error("Loader script " + script_1 + " did not register a loader callback"); } return _this._loaderInit; }) .then(function (loader) { _this._loader = loader; }); } }; BaseExecutor.prototype._loadPluginsWithLoader = function () { var _this = this; var scripts = tslib_1.__spreadArray(tslib_1.__spreadArray([], this.config.plugins), this.config[this.environment].plugins).filter(function (plugin) { return plugin.useLoader; }); return this._loadScripts(scripts, function (script) { return _this._loader([script]); }); }; BaseExecutor.prototype._loadPlugins = function () { var _this = this; var scripts = tslib_1.__spreadArray(tslib_1.__spreadArray([], this.config.plugins), this.config[this.environment].plugins).filter(function (plugin) { return !plugin.useLoader; }); return this._loadScripts(scripts, function (script) { return _this.loadScript(script); }); }; BaseExecutor.prototype._loadScripts = function (scripts, loader) { var _this = this; return scripts .reduce(function (previous, script) { if (typeof script === 'string') { return previous.then(function () { return loader(script); }); } else { return previous .then(function () { _this._loadingPluginOptions = script.options; }) .then(function () { return loader(script.script); }) .then(function () { _this._loadingPluginOptions = undefined; }); } }, common_1.Task.resolve()) .then(function () { return common_1.Task.all(_this._loadingPlugins.map(function (entry) { return entry.init; })).then(function (plugins) { plugins.forEach(function (plugin, index) { _this._assignPlugin(_this._loadingPlugins[index].name, plugin); }); }); }); }; BaseExecutor.prototype._loadSuites = function () { var _this = this; var suites = this.config[this.environment].suites; return common_1.Task.resolve(this._loader(suites)).then(function () { _this.log('Loaded suites:', suites); }); }; BaseExecutor.prototype._processOption = function (key, value) { util_1.processOption(key, value, this.config, this); }; BaseExecutor.prototype._resolveConfig = function () { var config = this.config; if (config.internPath != null) { config.internPath = path_1.normalizePathEnding(config.internPath); } else { config.internPath = ''; } if (config.benchmark) { config.benchmarkConfig = common_1.deepMixin({ mode: config.baseline ? 'baseline' : 'test', id: 'Benchmark', filename: 'baseline.json', thresholds: { warn: { rme: 3, mean: 5 }, fail: { rme: 6, mean: 10 } }, verbosity: 0 }, config.benchmarkConfig || {}); } return common_1.Task.resolve(); }; BaseExecutor.prototype._runTests = function () { return this._rootSuite.run(); }; return BaseExecutor; }()); exports.default = BaseExecutor; }); //# sourceMappingURL=Executor.js.map