UNPKG

wct-mocha

Version:

Client-side library for testing web-components with Mocha.

254 lines 9.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * @license * Copyright (c) 2018 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt The complete set of authors may be found * at http://polymer.github.io/AUTHORS.txt The complete set of contributors may * be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by * Google as part of the polymer project is also subject to an additional IP * rights grant found at http://polymer.github.io/PATENTS.txt */ var normalization_js_1 = require("../stacktrace/normalization.js"); var util = require("../util.js"); var STACKY_CONFIG = { indent: ' ', locationStrip: [ /^https?:\/\/[^\/]+/, /\?.*$/, ], filter: function (line) { return !!line.location.match(/\/web-component-tester\/[^\/]+(\?.*)?$/); }, }; // https://github.com/visionmedia/mocha/blob/master/lib/runner.js#L36-46 var MOCHA_EVENTS = [ 'start', 'end', 'suite', 'suite end', 'test', 'test end', 'hook', 'hook end', 'pass', 'fail', 'pending', 'childRunner end' ]; // Until a suite has loaded, we assume this many tests in it. var ESTIMATED_TESTS_PER_SUITE = 3; /** * A Mocha-like reporter that combines the output of multiple Mocha suites. */ var MultiReporter = /** @class */ (function () { /** * @param numSuites The number of suites that will be run, in order to * estimate the total number of tests that will be performed. * @param reporters The set of reporters that * should receive the unified event stream. * @param parent The parent reporter, if present. */ function MultiReporter(numSuites, reporters, parent) { var _this = this; this.reporters = reporters.map(function (reporter) { return new reporter(_this); }); this.parent = parent; this.basePath = parent && parent.basePath || util.basePath(window.location); this.total = numSuites * ESTIMATED_TESTS_PER_SUITE; // Mocha reporters assume a stream of events, so we have to be careful to // only report on one runner at a time... this.currentRunner = null; // ...while we buffer events for any other active runners. this.pendingEvents = []; this.emit('start'); } /** * @return A reporter-like "class" for each child suite * that should be passed to `mocha.run`. */ MultiReporter.prototype.childReporter = function () { var _a; // The reporter is used as a constructor, so we can't depend on `this` being // properly bound. var self = this; return _a = /** @class */ (function () { function ChildReporter(runner) { runner.name = window.name; self.bindChildRunner(runner); } return ChildReporter; }()), _a.title = window.name, _a; }; /** Must be called once all runners have finished. */ MultiReporter.prototype.done = function () { this.complete = true; this.flushPendingEvents(); this.emit('end'); }; MultiReporter.prototype.epilogue = function () { }; /** * Emit a top level test that is not part of any suite managed by this * reporter. * * Helpful for reporting on global errors, loading issues, etc. * * @param title The title of the test. * @param error An error associated with this test. If falsy, test is * considered to be passing. * @param suiteTitle Title for the suite that's wrapping the test. * @param estimated If this test was included in the original * estimate of `numSuites`. */ MultiReporter.prototype.emitOutOfBandTest = function (title, error, suiteTitle, estimated) { util.debug('MultiReporter#emitOutOfBandTest(', arguments, ')'); var root = new Mocha.Suite(suiteTitle || ''); var test = new Mocha.Test(title, function () { return undefined; }); test.parent = root; test.state = error ? 'failed' : 'passed'; test.err = error; if (!estimated) { this.total = this.total + ESTIMATED_TESTS_PER_SUITE; } var runner = { total: 1 }; this.proxyEvent('start', runner); this.proxyEvent('suite', runner, root); this.proxyEvent('test', runner, test); if (error) { this.proxyEvent('fail', runner, test, error); } else { this.proxyEvent('pass', runner, test); } this.proxyEvent('test end', runner, test); this.proxyEvent('suite end', runner, root); this.proxyEvent('end', runner); }; /** * @param {!Location|string} location * @return {string} */ MultiReporter.prototype.suiteTitle = function (location) { var path = util.relativeLocation(location, this.basePath); path = util.cleanLocation(path); return path; }; // Internal Interface /** @param {!Mocha.runners.Base} runner The runner to listen to events for. */ MultiReporter.prototype.bindChildRunner = function (runner) { var _this = this; MOCHA_EVENTS.forEach(function (eventName) { runner.on(eventName, _this.proxyEvent.bind(_this, eventName, runner)); }); }; /** * Evaluates an event fired by `runner`, proxying it forward or buffering it. * * @param {string} eventName * @param {!Mocha.runners.Base} runner The runner that emitted this event. * @param {...*} var_args Any additional data passed as part of the event. */ MultiReporter.prototype.proxyEvent = function (eventName, runner) { var _extra = []; for (var _i = 2; _i < arguments.length; _i++) { _extra[_i - 2] = arguments[_i]; } var extraArgs = Array.prototype.slice.call(arguments, 2); if (this.complete) { console.warn('out of order Mocha event for ' + runner.name + ':', eventName, extraArgs); return; } if (this.currentRunner && runner !== this.currentRunner) { this.pendingEvents.push(Array.prototype.slice.call(arguments)); return; } util.debug('MultiReporter#proxyEvent(', arguments, ')'); // This appears to be a Mocha bug: Tests failed by passing an error to their // done function don't set `err` properly. // // TODO(nevir): Track down. if (eventName === 'fail' && !extraArgs[0].err) { extraArgs[0].err = extraArgs[1]; } if (eventName === 'start') { this.onRunnerStart(runner); } else if (eventName === 'end') { this.onRunnerEnd(runner); } else { this.cleanEvent(eventName, runner, extraArgs); this.emit.apply(this, [eventName].concat(extraArgs)); } }; /** * Cleans or modifies an event if needed. * * @param eventName * @param runner The runner that emitted this event. * @param extraArgs */ MultiReporter.prototype.cleanEvent = function (eventName, _runner, extraArgs) { // Suite hierarchy if (extraArgs[0]) { extraArgs[0] = this.showRootSuite(extraArgs[0]); } // Normalize errors if (eventName === 'fail') { extraArgs[1] = normalization_js_1.normalize(extraArgs[1], STACKY_CONFIG); } var extra0 = extraArgs[0]; if (extra0 && extra0.err) { extra0.err = normalization_js_1.normalize(extra0.err, STACKY_CONFIG); } }; /** * We like to show the root suite's title, which requires a little bit of * trickery in the suite hierarchy. * * @param {!Mocha.Runnable} node */ MultiReporter.prototype.showRootSuite = function (node) { var leaf = node = Object.create(node); while (node && node.parent) { var wrappedParent = Object.create(node.parent); node.parent = wrappedParent; node = wrappedParent; } node.root = false; return leaf; }; /** @param {!Mocha.runners.Base} runner */ MultiReporter.prototype.onRunnerStart = function (runner) { util.debug('MultiReporter#onRunnerStart:', runner.name); this.total = this.total - ESTIMATED_TESTS_PER_SUITE + runner.total; this.currentRunner = runner; }; /** @param {!Mocha.runners.Base} runner */ MultiReporter.prototype.onRunnerEnd = function (runner) { util.debug('MultiReporter#onRunnerEnd:', runner.name); this.currentRunner = null; this.flushPendingEvents(); }; /** * Flushes any buffered events and runs them through `proxyEvent`. This will * loop until all buffered runners are complete, or we have run out of * buffered events. */ MultiReporter.prototype.flushPendingEvents = function () { var _this = this; var events = this.pendingEvents; this.pendingEvents = []; events.forEach(function (eventArgs) { _this.proxyEvent.apply(_this, eventArgs); }); }; return MultiReporter; }()); exports.default = MultiReporter; //# sourceMappingURL=multi.js.map