UNPKG

intern

Version:

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

542 lines 21.8 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", "@theintern/common", "./Deferred", "./Test", "./common/util", "./common/time"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isSuite = void 0; var tslib_1 = require("tslib"); var common_1 = require("@theintern/common"); var Deferred_1 = tslib_1.__importDefault(require("./Deferred")); var Test_1 = require("./Test"); var util_1 = require("./common/util"); var time_1 = require("./common/time"); var Suite = (function () { function Suite(options) { var _this = this; this.publishAfterSetup = false; this.tests = []; Object.keys(options) .filter(function (key) { return key !== 'tests'; }) .forEach(function (option) { var key = option; _this[key] = options[key]; }); if (options.tests) { options.tests.forEach(function (suiteOrTest) { return _this.add(suiteOrTest); }); } if (!this.name && this.parent) { throw new Error('A non-root Suite must have a name'); } } Object.defineProperty(Suite.prototype, "bail", { get: function () { return this._bail || (this.parent && this.parent.bail); }, set: function (value) { this._bail = value; }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "executor", { get: function () { return (this.parent && this.parent.executor) || this._executor; }, set: function (value) { if (this._executor) { var error = new Error('An executor may only be set once per suite'); error.name = 'AlreadyAssigned'; throw error; } this._executor = value; }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "grep", { get: function () { return this._grep || (this.parent && this.parent.grep) || /.*/; }, set: function (value) { this._grep = value; this._applyGrepToChildren(); }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "name", { get: function () { return this._name; }, set: function (value) { this._name = value; this._applyGrepToChildren(); }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "id", { get: function () { var name = []; var suite = this; do { suite.name != null && name.unshift(suite.name); } while ((suite = suite.parent)); return name.join(' - '); }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "parentId", { get: function () { var parent = this.parent; if (parent) { return parent.id; } }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "remote", { get: function () { return this.parent && this.parent.remote ? this.parent.remote : this._remote; }, set: function (value) { if (this._remote) { throw new Error('AlreadyAssigned: remote may only be set once per suite'); } this._remote = value; }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "sessionId", { get: function () { if (this.parent) { return this.parent.sessionId; } if (this._sessionId) { return this._sessionId; } if (this.remote) { return this.remote.session.sessionId; } return ''; }, set: function (value) { this._sessionId = value; }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "numTests", { get: function () { return this.tests.reduce(function (numTests, suiteOrTest) { if (isSuite(suiteOrTest)) { return numTests + suiteOrTest.numTests; } return numTests + 1; }, 0); }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "numPassedTests", { get: function () { return this.tests.reduce(function (numPassedTests, suiteOrTest) { if (isSuite(suiteOrTest)) { return numPassedTests + suiteOrTest.numPassedTests; } else if (suiteOrTest.hasPassed) { return numPassedTests + 1; } return numPassedTests; }, 0); }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "numFailedTests", { get: function () { return this.tests.reduce(function (numFailedTests, suiteOrTest) { if (isSuite(suiteOrTest)) { return numFailedTests + suiteOrTest.numFailedTests; } else if (suiteOrTest.error) { return numFailedTests + 1; } return numFailedTests; }, 0); }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "numSkippedTests", { get: function () { return this.tests.reduce(function (numSkippedTests, suiteOrTest) { if (isSuite(suiteOrTest)) { return numSkippedTests + suiteOrTest.numSkippedTests; } else if (suiteOrTest.skipped) { return numSkippedTests + 1; } return numSkippedTests; }, 0); }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "hasParent", { get: function () { return Boolean(this.parent); }, enumerable: false, configurable: true }); Object.defineProperty(Suite.prototype, "timeout", { get: function () { if (this._timeout != null) { return this._timeout; } if (this.parent) { return this.parent.timeout; } return 30000; }, set: function (value) { this._timeout = value; }, enumerable: false, configurable: true }); Suite.prototype.add = function (suiteOrTest) { if (!Test_1.isTest(suiteOrTest) && !isSuite(suiteOrTest)) { throw new Error('Tried to add invalid suite or test'); } if (suiteOrTest.parent != null && suiteOrTest.parent !== this) { throw new Error('This Suite or Test already belongs to another parent'); } this.tests.forEach(function (existingSuiteOrTest) { if (existingSuiteOrTest.name === suiteOrTest.name) { throw new Error("A suite or test named \"" + suiteOrTest.name + "\" has already been added"); } }); suiteOrTest.parent = this; this.tests.push(suiteOrTest); this._applyGrepToSuiteOrTest(suiteOrTest); if (Test_1.isTest(suiteOrTest)) { this.executor.emit('testAdd', suiteOrTest); } else { this.executor.emit('suiteAdd', suiteOrTest); } }; Suite.prototype._applyGrepToSuiteOrTest = function (suiteOrTest) { if (suiteOrTest instanceof Suite) { suiteOrTest._applyGrepToChildren(); } else { var grepSkipReason = 'grep'; if (suiteOrTest.skipped === grepSkipReason) { suiteOrTest.skipped = undefined; } if (!this.grep.test(suiteOrTest.id)) { suiteOrTest.skipped = grepSkipReason; } } }; Suite.prototype._applyGrepToChildren = function () { var _this = this; this.tests.forEach(function (suiteOrTest) { return _this._applyGrepToSuiteOrTest(suiteOrTest); }); }; Suite.prototype.run = function () { var _this = this; var startTime; var start = function () { return _this.executor.emit('suiteStart', _this).then(function () { startTime = time_1.now(); }); }; var end = function () { _this.timeElapsed = time_1.now() - startTime; return _this.executor.emit('suiteEnd', _this); }; var allTestsSkipped = this.numTests === this.numSkippedTests; var runLifecycleMethod = function (suite, name, test) { var result; if (!_this._executor && allTestsSkipped) { return common_1.Task.resolve(); } return new common_1.Task(function (resolve, reject) { var dfd; var timeout; suite.async = function (_timeout) { timeout = _timeout; var _dfd = new Deferred_1.default(); dfd = _dfd; suite.async = function () { return _dfd; }; return _dfd; }; var suiteFunc = suite[name]; result = suiteFunc && (test ? suiteFunc.call(suite, test, suite) : suiteFunc.call(suite, suite)); if (dfd) { var _dfd_1 = dfd; if (timeout) { var timer_1 = time_1.setTimeout(function () { var error = new Error("Timeout reached on " + suite.id + "#" + name); error.name = 'TimeoutError'; _dfd_1.reject(error); }, timeout); _dfd_1.promise .catch(function (_error) { }) .then(function () { return timer_1 && time_1.clearTimeout(timer_1); }); } if (common_1.isPromiseLike(result)) { result.then(function () { return _dfd_1.resolve(); }, function (error) { return _dfd_1.reject(error); }); } result = dfd.promise; } if (common_1.isPromiseLike(result)) { result.then(function () { return resolve(); }, reject); } else { resolve(); } }, function () { if (common_1.isTask(result)) { result.cancel(); } }) .finally(function () { suite.async = undefined; }) .catch(function (error) { if (error !== Test_1.SKIP) { if (test) { test.suiteError = error; } if (!_this.error) { _this.executor.log('Suite errored with non-skip error', error); error.lifecycleMethod = name; _this.error = error; } throw error; } }); }; var before = function () { return runLifecycleMethod(_this, 'before'); }; var after = function () { return runLifecycleMethod(_this, 'after'); }; this.error = undefined; this.timeElapsed = 0; var task; var runTask; try { task = this.publishAfterSetup ? before().then(start) : start().then(before); } catch (error) { return common_1.Task.reject(error); } return task .then(function () { var runTestLifecycle = function (name, test) { var methodQueue = []; var suite = _this; do { if (name === 'beforeEach') { methodQueue.push(suite); } else { methodQueue.unshift(suite); } } while ((suite = suite.parent)); var currentMethod; return new common_1.Task(function (resolve, reject) { var firstError; var handleError = function (error) { if (name === 'afterEach') { firstError = firstError || error; next(); } else { reject(error); } }; var next = function () { var suite = methodQueue.pop(); if (!suite) { firstError ? reject(firstError) : resolve(); return; } currentMethod = runLifecycleMethod(suite, name, test).then(next, handleError); }; next(); }, function () { methodQueue.splice(0, methodQueue.length); if (currentMethod) { currentMethod.cancel(); } }); }; var i = 0; var tests = _this.tests; var current; runTask = new common_1.Task(function (resolve, reject) { var firstError; var testTask; var next = function () { var test = tests[i++]; if (!test) { firstError ? reject(firstError) : resolve(); return; } var handleError = function (error) { if (error && error.relatedTest == null) { error.relatedTest = test; } }; var runTest = function () { var result = test.run().catch(function (error) { handleError(error); }); testTask = new common_1.Task(function (resolve) { result.then(resolve); }, function () { result.cancel(); }); return testTask; }; if (_this.skipped != null) { test.skipped = _this.skipped; } if (isSuite(test)) { current = runTest(); } else { if (test.skipped != null) { current = _this.executor.emit('testEnd', test); } else { current = runTestLifecycle('beforeEach', test) .then(function () { if (test.skipped != null) { return _this.executor.emit('testEnd', test); } else { return runTest(); } }) .finally(function () { if (testTask) { testTask.cancel(); } testTask = undefined; return runTestLifecycle('afterEach', test); }) .catch(function (error) { firstError = firstError || error; return handleError(error); }); } } current.then(function () { var skipRestOfSuite = function () { _this.skipped = _this.skipped != null ? _this.skipped : BAIL_REASON; }; if (isSuite(test) && test.skipped === BAIL_REASON) { skipRestOfSuite(); } else if (test.error && _this.bail) { skipRestOfSuite(); } next(); }); }; next(); }, function () { i = Infinity; if (current) { current.cancel(); } }); return runTask; }) .finally(function () { if (runTask) { runTask.cancel(); } }) .finally(function () { return (_this.publishAfterSetup ? end() : after()); }) .finally(function () { return (_this.publishAfterSetup ? after() : end()); }); }; Suite.prototype.skip = function (message) { if (message === void 0) { message = 'suite skipped'; } this.skipped = message; throw Test_1.SKIP; }; Suite.prototype.toJSON = function () { var _this = this; var json = { hasParent: Boolean(this.parent), tests: this.tests.map(function (test) { return test.toJSON(); }) }; var properties = [ 'name', 'id', 'parentId', 'sessionId', 'timeElapsed', 'numTests', 'numPassedTests', 'numFailedTests', 'numSkippedTests', 'skipped' ]; properties.forEach(function (key) { var value = _this[key]; if (typeof value !== 'undefined') { json[key] = value; } }); if (this.error) { json.error = util_1.errorToJSON(this.error); if (this.error.relatedTest && this.error.relatedTest !== this) { json.error.relatedTest = this.error.relatedTest.toJSON(); } } return json; }; return Suite; }()); exports.default = Suite; function isSuite(value) { return Array.isArray(value.tests) && typeof value.hasParent === 'boolean'; } exports.isSuite = isSuite; var BAIL_REASON = 'bailed'; }); //# sourceMappingURL=Suite.js.map