Socket
Socket
Sign inDemoInstall

js-reporters

Package Overview
Dependencies
0
Maintainers
4
Versions
9
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.2.3 to 2.0.0

dist/index.html

95

CHANGELOG.md

@@ -0,58 +1,69 @@

Changelog for the [js-reporters](https://www.npmjs.com/package/js-reporters) package. See [spec/](./spec/cri-draft.adoc) for the CRI standard.
2.0.0 / 2021-04-04
==================
This release provides a simplified spec, with various properties and features removed. Overall the new spec is considered narrower than the previous one. Existing reporters that support old producers should naturally support new producers as well. Existing producers can choose to remain unchanged or to remove older portions in a future release.
### Added
* Add SummaryReporter implementation.
### Changed
* Spec: Rewrite current proposal into a formal specification at [spec/](./spec/cri-draft.adoc). (Timo Tijhof)
* Spec: Remove "todo" from Assertion event data. [#119](https://github.com/js-reporters/js-reporters/pull/119)
* Spec: Remove "tests" and "childSuites" from SuiteStart and SuiteEnd event data.
* Spec: Prefer `null` instead of `undefined` for optional fields.
* TapReporter: Improve formatting of multi-line strings. [#109](https://github.com/js-reporters/js-reporters/issues/109)
### Fixed
* TapReporter: Fix support objects with cycles, avoiding uncaught errors. (Zachary Mulgrew) [#104](https://github.com/js-reporters/js-reporters/issues/104)
* TapReporter: Defend against mocked `console` object. [#125](https://github.com/js-reporters/js-reporters/issues/125)
* MochaAdapter: Fix support for Mocha 8, due to changes in `STATE_PENDING`. [#116](https://github.com/js-reporters/js-reporters/issues/116)
### Removed
* Remove support for Node.js 8 and older. This release requires Node.js 10 or later. (Browser support has not changed and remains IE 9+, see [README](./README.md#runtime-support).)
* Helpers: Remove the `Assertion`, `Test`, and `Suite` classes.
* Helpers: Remove `collectSuite{Start,StartData,EndData}` methods.
1.2.3 / 2020-09-07
==================
* Helpers: Correct spelling in `autoRegister()` error message. (P. Roebuck) [#108](https://github.com/js-reporters/js-reporters/issues/108)
* Reporter: Align `actual` with `expected` in TapReporter. (Robert Jackson) [#107](https://github.com/js-reporters/js-reporters/pull/107)
* Reporter: Revert "Fix YAML output in TAP reporter". [#110](https://github.com/js-reporters/js-reporters/issues/110)
### Changed
* TapReporter: Align `actual` with `expected` in TAP output. (Robert Jackson) [#107](https://github.com/js-reporters/js-reporters/pull/107)
### Fixed
* Helpers: Correct spelling in `autoRegister()` error message. (P. Roebuck) [#108](https://github.com/js-reporters/js-reporters/issues/108)
* TapReporter: Revert "Fix YAML syntax". [#110](https://github.com/js-reporters/js-reporters/issues/110)
1.2.2 / 2019-05-13
==================
* Reporter: Fix YAML output in TAP reporter. [#110](https://github.com/js-reporters/js-reporters/issues/110)
### Fixed
* TapReporter: Fix YAML syntax. (jeberger) [#110](https://github.com/js-reporters/js-reporters/issues/110)
1.2.1 / 2017-07-04
==================
* Reporter: Print "actual:", "expected:" even if they are undefined
* Reporter: Drop accidentally committed console.warn()
* Readme: Use canonical path to QUnit repository (#99)
* Readme: Add note about potential assertion memory leaks
* Readme: Improve formatting of bullets
* Release: Add documentation for release process
### Changed
* TapReporter: Print "actual:", "expected:" even if undefined. (Martin Olsson)
### Fixed
* TapReporter: Drop accidentally committed `console.warn()` statement. (Martin Olsson)
1.2.0 / 2017-03-22
==================
* Testing: Update Node versions on Travis
* TapReporter: Further improve information and styling
* Deps: Explicitly include webpack to fulfill peerDep
* Data: Add todo data and update tests
* TapReporter: Update with more information and support todo tests
* README: Specify data for todo tests
* README: update
* Helpers: add create functions
* Index.js: add comma
* README: update spec with start and end
* All: break Suite and Test into start and end objects
* Deps: lock Jasmine version
* Helpers: update Jasmine adapter instantiation.
* Helpers: export each helper function
* Testing: use global instead of GLOBAL in helpers
* Testing: unit testing also in the browser with help of karma
* Docs: update autoRegister description
* Docs: add API section
* Helpers: change export
* Helpers: update error message
* Testing: add before and after hooks for helpers
* Helpers: add docs to the autoRegister function
* Testing: finish unit tests for the autoRegister function
* Testing: add unit tests for autoRegister function
* Bundling: export autoRegister function
* Helpers: add autoregister function
* Deps: restore Jasmine to last versions.
* Testing: update failing versions
* Deps: set jasmine to the last working version
* Deps: remove jasmine-core
* JasmineAdapter: fix reporter adding
* README: add first example
### Added
* TapReporter: Improve TAP information and styling. (Florentin Simion)
* TapReporter: Support todo test in TAP reporter. (Trent Willis)
* Docs: Add API docs for the js-reporters package. (Florentin Simion)

@@ -1,235 +0,285 @@

/**
* JsReporters 1.2.3
* https://github.com/js-reporters
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: Thu Sep 10 2020
*/
/*! JsReporters 2.0.0 | Copyright JS Reporters https://github.com/js-reporters/ | https://opensource.org/licenses/MIT */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.JsReporters = factory());
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.JsReporters = factory());
}(this, (function () { 'use strict';
function interopDefault(ex) {
return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex;
}
function _typeof(obj) {
"@babel/helpers - typeof";
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) {
return typeof obj;
};
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
return _typeof(obj);
}
var asyncGenerator = function () {
function AwaitValue(value) {
this.value = value;
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function AsyncGenerator(gen) {
var front, back;
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function send(key, arg) {
return new Promise(function (resolve, reject) {
var request = {
key: key,
arg: arg,
resolve: resolve,
reject: reject,
next: null
};
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
if (back) {
back = back.next = request;
} else {
front = back = request;
resume(key, arg);
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
function resume(key, arg) {
try {
var result = gen[key](arg);
var value = result.value;
return obj;
}
if (value instanceof AwaitValue) {
Promise.resolve(value.value).then(function (arg) {
resume("next", arg);
}, function (arg) {
resume("throw", arg);
});
} else {
settle(result.done ? "return" : "normal", result.value);
}
} catch (err) {
settle("throw", err);
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
function settle(type, value) {
switch (type) {
case "return":
front.resolve({
value: value,
done: true
});
break;
return keys;
}
case "throw":
front.reject(value);
break;
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
default:
front.resolve({
value: value,
done: false
});
break;
}
front = front.next;
if (front) {
resume(front.key, front.arg);
if (i % 2) {
ownKeys(Object(source), true).forEach(function (key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
back = null;
ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
this._invoke = send;
return target;
}
if (typeof gen.return !== "function") {
this.return = undefined;
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
if (typeof Symbol === "function" && Symbol.asyncIterator) {
AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
return this;
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
AsyncGenerator.prototype.next = function (arg) {
return this._invoke("next", arg);
};
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
AsyncGenerator.prototype.throw = function (arg) {
return this._invoke("throw", arg);
};
return _setPrototypeOf(o, p);
}
AsyncGenerator.prototype.return = function (arg) {
return this._invoke("return", arg);
};
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
return {
wrap: function (fn) {
return function () {
return new AsyncGenerator(fn.apply(this, arguments));
};
},
await: function (value) {
return new AwaitValue(value);
try {
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
return true;
} catch (e) {
return false;
}
};
}();
}
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
function _possibleConstructorReturn(self, call) {
if (call && (typeof call === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized(self);
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
function _iterableToArray(iter) {
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}
var events = createCommonjsModule(function (module) {
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var R = (typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === 'object' ? Reflect : null;
var ReflectApply = R && typeof R.apply === 'function' ? R.apply : function ReflectApply(target, receiver, args) {
return Function.prototype.apply.call(target, receiver, args);
};
var ReflectOwnKeys;
if (R && typeof R.ownKeys === 'function') {
ReflectOwnKeys = R.ownKeys;
} else if (Object.getOwnPropertySymbols) {
ReflectOwnKeys = function ReflectOwnKeys(target) {
return Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target));
};
} else {
ReflectOwnKeys = function ReflectOwnKeys(target) {
return Object.getOwnPropertyNames(target);
};
}
function ProcessEmitWarning(warning) {
if (console && console.warn) console.warn(warning);
}
var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
return value !== value;
};
function EventEmitter() {
this._events = this._events || {};
this._maxListeners = this._maxListeners || undefined;
EventEmitter.init.call(this);
}
module.exports = EventEmitter;
// Backwards-compat with node 0.10.x
var events = EventEmitter;
var once_1 = once; // Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;
// By default EventEmitters will print a warning if more than 10 listeners are
EventEmitter.prototype._eventsCount = 0;
EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
EventEmitter.defaultMaxListeners = 10;
// Obviously not all Emitters should be limited to 10. This function allows
var defaultMaxListeners = 10;
function checkListener(listener) {
if (typeof listener !== 'function') {
throw new TypeError('The "listener" argument must be of type Function. Received type ' + _typeof(listener));
}
}
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
enumerable: true,
get: function get() {
return defaultMaxListeners;
},
set: function set(arg) {
if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
}
defaultMaxListeners = arg;
}
});
EventEmitter.init = function () {
if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) {
this._events = Object.create(null);
this._eventsCount = 0;
}
this._maxListeners = this._maxListeners || undefined;
}; // Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function (n) {
if (!isNumber(n) || n < 0 || isNaN(n)) throw TypeError('n must be a positive number');
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
}
this._maxListeners = n;

@@ -239,50 +289,50 @@ return this;

EventEmitter.prototype.emit = function (type) {
var er, handler, len, args, i, listeners;
function _getMaxListeners(that) {
if (that._maxListeners === undefined) return EventEmitter.defaultMaxListeners;
return that._maxListeners;
}
if (!this._events) this._events = {};
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
return _getMaxListeners(this);
};
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events.error || isObject(this._events.error) && !this._events.error.length) {
er = arguments[1];
if (er instanceof Error) {
throw er; // Unhandled 'error' event
} else {
// At least give some kind of context to the user
var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
err.context = er;
throw err;
}
}
EventEmitter.prototype.emit = function emit(type) {
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
handler = this._events[type];
var doError = type === 'error';
var events = this._events;
if (events !== undefined) doError = doError && events.error === undefined;else if (!doError) return false; // If there is no 'error' event listener then throw.
if (isUndefined(handler)) return false;
if (doError) {
var er;
if (args.length > 0) er = args[0];
if (isFunction(handler)) {
switch (arguments.length) {
// fast cases
case 1:
handler.call(this);
break;
case 2:
handler.call(this, arguments[1]);
break;
case 3:
handler.call(this, arguments[1], arguments[2]);
break;
// slower
default:
args = Array.prototype.slice.call(arguments, 1);
handler.apply(this, args);
if (er instanceof Error) {
// Note: The comments on the `throw` lines are intentional, they show
// up in Node's output if this results in an unhandled exception.
throw er; // Unhandled 'error' event
} // At least give some kind of context to the user
var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
err.context = er;
throw err; // Unhandled 'error' event
}
var handler = events[type];
if (handler === undefined) return false;
if (typeof handler === 'function') {
ReflectApply(handler, this, args);
} else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i) {
ReflectApply(listeners[i], this, args);
}
} else if (isObject(handler)) {
args = Array.prototype.slice.call(arguments, 1);
listeners = handler.slice();
len = listeners.length;
for (i = 0; i < len; i++) {
listeners[i].apply(this, args);
}
}

@@ -293,40 +343,60 @@

EventEmitter.prototype.addListener = function (type, listener) {
function _addListener(target, type, listener, prepend) {
var m;
var events;
var existing;
checkListener(listener);
events = target._events;
if (!isFunction(listener)) throw TypeError('listener must be a function');
if (events === undefined) {
events = target._events = Object.create(null);
target._eventsCount = 0;
} else {
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (events.newListener !== undefined) {
target.emit('newListener', type, listener.listener ? listener.listener : listener); // Re-assign `events` because a newListener handler could have caused the
// this._events to be assigned to a new object
if (!this._events) this._events = {};
events = target._events;
}
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (this._events.newListener) this.emit('newListener', type, isFunction(listener.listener) ? listener.listener : listener);
existing = events[type];
}
if (!this._events[type])
if (existing === undefined) {
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;else if (isObject(this._events[type]))
// If we've already got an array, just append.
this._events[type].push(listener);else
// Adding the second element, need to change to array.
this._events[type] = [this._events[type], listener];
// Check for listener leak
if (isObject(this._events[type]) && !this._events[type].warned) {
if (!isUndefined(this._maxListeners)) {
m = this._maxListeners;
existing = events[type] = listener;
++target._eventsCount;
} else {
if (typeof existing === 'function') {
// Adding the second element, need to change to array.
existing = events[type] = prepend ? [listener, existing] : [existing, listener]; // If we've already got an array, just append.
} else if (prepend) {
existing.unshift(listener);
} else {
m = EventEmitter.defaultMaxListeners;
}
existing.push(listener);
} // Check for listener leak
if (m && m > 0 && this._events[type].length > m) {
this._events[type].warned = true;
console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length);
if (typeof console.trace === 'function') {
// not supported in IE 10
console.trace();
}
m = _getMaxListeners(target);
if (m > 0 && existing.length > m && !existing.warned) {
existing.warned = true; // No error code for this since it is a Warning
// eslint-disable-next-line no-restricted-syntax
var w = new Error('Possible EventEmitter memory leak detected. ' + existing.length + ' ' + String(type) + ' listeners ' + 'added. Use emitter.setMaxListeners() to ' + 'increase limit');
w.name = 'MaxListenersExceededWarning';
w.emitter = target;
w.type = type;
w.count = existing.length;
ProcessEmitWarning(w);
}
}
return this;
return target;
}
EventEmitter.prototype.addListener = function addListener(type, listener) {
return _addListener(this, type, listener, false);
};

@@ -336,40 +406,61 @@

EventEmitter.prototype.once = function (type, listener) {
if (!isFunction(listener)) throw TypeError('listener must be a function');
EventEmitter.prototype.prependListener = function prependListener(type, listener) {
return _addListener(this, type, listener, true);
};
var fired = false;
function g() {
this.removeListener(type, g);
if (!fired) {
fired = true;
listener.apply(this, arguments);
}
function onceWrapper() {
if (!this.fired) {
this.target.removeListener(this.type, this.wrapFn);
this.fired = true;
if (arguments.length === 0) return this.listener.call(this.target);
return this.listener.apply(this.target, arguments);
}
}
g.listener = listener;
this.on(type, g);
function _onceWrap(target, type, listener) {
var state = {
fired: false,
wrapFn: undefined,
target: target,
type: type,
listener: listener
};
var wrapped = onceWrapper.bind(state);
wrapped.listener = listener;
state.wrapFn = wrapped;
return wrapped;
}
EventEmitter.prototype.once = function once(type, listener) {
checkListener(listener);
this.on(type, _onceWrap(this, type, listener));
return this;
};
// emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = function (type, listener) {
var list, position, length, i;
EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) {
checkListener(listener);
this.prependListener(type, _onceWrap(this, type, listener));
return this;
}; // Emits a 'removeListener' event if and only if the listener was removed.
if (!isFunction(listener)) throw TypeError('listener must be a function');
if (!this._events || !this._events[type]) return this;
EventEmitter.prototype.removeListener = function removeListener(type, listener) {
var list, events, position, i, originalListener;
checkListener(listener);
events = this._events;
if (events === undefined) return this;
list = events[type];
if (list === undefined) return this;
list = this._events[type];
length = list.length;
position = -1;
if (list === listener || list.listener === listener) {
if (--this._eventsCount === 0) this._events = Object.create(null);else {
delete events[type];
if (events.removeListener) this.emit('removeListener', type, list.listener || listener);
}
} else if (typeof list !== 'function') {
position = -1;
if (list === listener || isFunction(list.listener) && list.listener === listener) {
delete this._events[type];
if (this._events.removeListener) this.emit('removeListener', type, listener);
} else if (isObject(list)) {
for (i = length; i-- > 0;) {
if (list[i] === listener || list[i].listener && list[i].listener === listener) {
for (i = list.length - 1; i >= 0; i--) {
if (list[i] === listener || list[i].listener === listener) {
originalListener = list[i].listener;
position = i;

@@ -381,11 +472,7 @@ break;

if (position < 0) return this;
if (list.length === 1) {
list.length = 0;
delete this._events[type];
} else {
list.splice(position, 1);
if (position === 0) list.shift();else {
spliceOne(list, position);
}
if (this._events.removeListener) this.emit('removeListener', type, listener);
if (list.length === 1) events[type] = list[0];
if (events.removeListener !== undefined) this.emit('removeListener', type, originalListener || listener);
}

@@ -396,35 +483,47 @@

EventEmitter.prototype.removeAllListeners = function (type) {
var key, listeners;
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
if (!this._events) return this;
EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) {
var listeners, events, i;
events = this._events;
if (events === undefined) return this; // not listening for removeListener, no need to emit
// not listening for removeListener, no need to emit
if (!this._events.removeListener) {
if (arguments.length === 0) this._events = {};else if (this._events[type]) delete this._events[type];
if (events.removeListener === undefined) {
if (arguments.length === 0) {
this._events = Object.create(null);
this._eventsCount = 0;
} else if (events[type] !== undefined) {
if (--this._eventsCount === 0) this._events = Object.create(null);else delete events[type];
}
return this;
}
} // emit removeListener for all listeners on all events
// emit removeListener for all listeners on all events
if (arguments.length === 0) {
for (key in this._events) {
var keys = Object.keys(events);
var key;
for (i = 0; i < keys.length; ++i) {
key = keys[i];
if (key === 'removeListener') continue;
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = {};
this._events = Object.create(null);
this._eventsCount = 0;
return this;
}
listeners = this._events[type];
listeners = events[type];
if (isFunction(listeners)) {
if (typeof listeners === 'function') {
this.removeListener(type, listeners);
} else if (listeners) {
} else if (listeners !== undefined) {
// LIFO order
while (listeners.length) {
this.removeListener(type, listeners[listeners.length - 1]);
for (i = listeners.length - 1; i >= 0; i--) {
this.removeListener(type, listeners[i]);
}
}
delete this._events[type];

@@ -434,1257 +533,1424 @@ return this;

EventEmitter.prototype.listeners = function (type) {
var ret;
if (!this._events || !this._events[type]) ret = [];else if (isFunction(this._events[type])) ret = [this._events[type]];else ret = this._events[type].slice();
return ret;
function _listeners(target, type, unwrap) {
var events = target._events;
if (events === undefined) return [];
var evlistener = events[type];
if (evlistener === undefined) return [];
if (typeof evlistener === 'function') return unwrap ? [evlistener.listener || evlistener] : [evlistener];
return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
}
EventEmitter.prototype.listeners = function listeners(type) {
return _listeners(this, type, true);
};
EventEmitter.prototype.listenerCount = function (type) {
if (this._events) {
var evlistener = this._events[type];
if (isFunction(evlistener)) return 1;else if (evlistener) return evlistener.length;
}
return 0;
EventEmitter.prototype.rawListeners = function rawListeners(type) {
return _listeners(this, type, false);
};
EventEmitter.listenerCount = function (emitter, type) {
return emitter.listenerCount(type);
if (typeof emitter.listenerCount === 'function') {
return emitter.listenerCount(type);
} else {
return listenerCount.call(emitter, type);
}
};
function isFunction(arg) {
return typeof arg === 'function';
}
EventEmitter.prototype.listenerCount = listenerCount;
function isNumber(arg) {
return typeof arg === 'number';
}
function listenerCount(type) {
var events = this._events;
function isObject(arg) {
return (typeof arg === 'undefined' ? 'undefined' : _typeof(arg)) === 'object' && arg !== null;
}
if (events !== undefined) {
var evlistener = events[type];
function isUndefined(arg) {
return arg === void 0;
if (typeof evlistener === 'function') {
return 1;
} else if (evlistener !== undefined) {
return evlistener.length;
}
}
return 0;
}
});
var EventEmitter = interopDefault(events);
EventEmitter.prototype.eventNames = function eventNames() {
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
};
function getAllTests(suite) {
var childSuiteTests = suite.childSuites.map(function (childSuite) {
return getAllTests(childSuite);
}).reduce(function (allTests, a) {
return allTests.concat(a);
}, []);
function arrayClone(arr, n) {
var copy = new Array(n);
return suite.tests.concat(childSuiteTests);
}
for (var i = 0; i < n; ++i) {
copy[i] = arr[i];
}
function getRuntime(suite) {
if (suite.status === 'skipped' || suite.status === undefined) {
return undefined;
return copy;
}
return getAllTests(suite).map(function (test) {
return test.status === 'skipped' ? 0 : test.runtime;
}).reduce(function (sum, testRuntime) {
return sum + testRuntime;
}, 0);
}
function spliceOne(list, index) {
for (; index + 1 < list.length; index++) {
list[index] = list[index + 1];
}
function getStatus(suite) {
var passed = 0;
var failed = 0;
var skipped = 0;
var todo = 0;
var tests = getAllTests(suite);
list.pop();
}
for (var i = 0; i < tests.length; i++) {
var test = tests[i];
function unwrapListeners(arr) {
var ret = new Array(arr.length);
// If a suite contains a test whose status is still undefined,
// there is no final status for the suite as well.
if (test.status === undefined) {
return undefined;
} else if (test.status === 'passed') {
passed++;
} else if (test.status === 'skipped') {
skipped++;
} else if (test.status === 'todo') {
todo++;
} else {
failed++;
for (var i = 0; i < ret.length; ++i) {
ret[i] = arr[i].listener || arr[i];
}
}
if (failed > 0) {
return 'failed';
} else if (skipped > 0 && passed === 0) {
return 'skipped';
} else if (todo > 0 && passed === 0) {
return 'todo';
} else {
return 'passed';
return ret;
}
}
function getSuiteStartTestCounts(suite) {
var tests = getAllTests(suite);
function once(emitter, name) {
return new Promise(function (resolve, reject) {
function errorListener(err) {
emitter.removeListener(name, resolver);
reject(err);
}
return {
total: tests.length
};
}
function resolver() {
if (typeof emitter.removeListener === 'function') {
emitter.removeListener('error', errorListener);
}
function getSuiteEndTestCounts(suite) {
var tests = getAllTests(suite);
resolve([].slice.call(arguments));
}
eventTargetAgnosticAddListener(emitter, name, resolver, {
once: true
});
return {
passed: tests.filter(function (test) {
return test.status === 'passed';
}).length,
failed: tests.filter(function (test) {
return test.status === 'failed';
}).length,
skipped: tests.filter(function (test) {
return test.status === 'skipped';
}).length,
todo: tests.filter(function (test) {
return test.status === 'todo';
}).length,
total: tests.length
};
}
var Assertion =
/**
* @param {Boolean} passed
* @param {*} actual
* @param {*} expected
* @param {String} message
* @param {String|undefined} stack
* @param {Boolean} todo
*/
function Assertion(passed, actual, expected, message, stack, todo) {
classCallCheck(this, Assertion);
this.passed = passed;
this.actual = actual;
this.expected = expected;
this.message = message;
this.stack = stack;
this.todo = todo;
};
var TestStart =
/**
* @param {String} name
* @param {String} suiteName
* @param {String[]} fullName
*/
function TestStart(name, suiteName, fullName) {
classCallCheck(this, TestStart);
this.name = name;
this.suiteName = suiteName;
this.fullName = fullName;
};
var TestEnd =
/**
* @param {String} name
* @param {String} suiteName
* @param {String[]} fullName
* @param {String} status
* @param {Number} runtime
* @param {Assertion[]} errors
* @param {Assertion[]} assertions
*/
function TestEnd(name, suiteName, fullName, status, runtime, errors, assertions) {
classCallCheck(this, TestEnd);
this.name = name;
this.suiteName = suiteName;
this.fullName = fullName;
this.status = status;
this.runtime = runtime;
this.errors = errors;
this.assertions = assertions;
};
var SuiteStart =
/**
* @param {String} name
* @param {String[]} fullName
* @param {Test[]} tests
* @param {Suite[]} childSuites
*/
function SuiteStart(name, fullName, tests, childSuites, testCounts) {
classCallCheck(this, SuiteStart);
this.name = name;
this.fullName = fullName;
this.tests = tests;
this.childSuites = childSuites;
this.testCounts = getSuiteStartTestCounts(this);
};
var SuiteEnd =
/**
* @param {String} name
* @param {String[]} fullName
* @param {Test[]} tests
* @param {Suite[]} childSuites
* @param {String} status
* @param {Object} testCounts
* @param {Number} testCounts.passed
* @param {Number} testCounts.failed
* @param {Number} testCounts.skipped
* @param {Number} testCounts.total
* @param {Number} runtime
*/
function SuiteEnd(name, fullName, tests, childSuites, status, testCounts, runtime) {
classCallCheck(this, SuiteEnd);
this.name = name;
this.fullName = fullName;
this.tests = tests;
this.childSuites = childSuites;
this.status = status || getStatus(this);
this.testCounts = testCounts || getSuiteEndTestCounts(this);
this.runtime = runtime || getRuntime(this);
};
var MochaAdapter = function (_EventEmitter) {
inherits(MochaAdapter, _EventEmitter);
function MochaAdapter(mocha) {
classCallCheck(this, MochaAdapter);
var _this = possibleConstructorReturn(this, (MochaAdapter.__proto__ || Object.getPrototypeOf(MochaAdapter)).call(this));
_this.mocha = mocha;
_this.origReporter = mocha._reporter;
mocha.reporter(function (runner) {
_this.runner = runner;
// eslint-disable-next-line no-unused-vars
var origReporterInstance = new (_this.origReporter.bind(_this.mocha, _this.runner))();
runner.on('start', _this.onStart.bind(_this));
runner.on('suite', _this.onSuite.bind(_this));
runner.on('test', _this.onTest.bind(_this));
runner.on('pending', _this.onPending.bind(_this));
runner.on('fail', _this.onFail.bind(_this));
runner.on('test end', _this.onTestEnd.bind(_this));
runner.on('suite end', _this.onSuiteEnd.bind(_this));
runner.on('end', _this.onEnd.bind(_this));
if (name !== 'error') {
addErrorHandlerIfEventEmitter(emitter, errorListener, {
once: true
});
}
});
return _this;
}
createClass(MochaAdapter, [{
key: 'convertToSuiteStart',
value: function convertToSuiteStart(mochaSuite) {
return new SuiteStart(mochaSuite.title, this.buildSuiteFullName(mochaSuite), mochaSuite.tests.map(this.convertTest.bind(this)), mochaSuite.suites.map(this.convertToSuiteStart.bind(this)));
function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
if (typeof emitter.on === 'function') {
eventTargetAgnosticAddListener(emitter, 'error', handler, flags);
}
}, {
key: 'convertToSuiteEnd',
value: function convertToSuiteEnd(mochaSuite) {
return new SuiteEnd(mochaSuite.title, this.buildSuiteFullName(mochaSuite), mochaSuite.tests.map(this.convertTest.bind(this)), mochaSuite.suites.map(this.convertToSuiteEnd.bind(this)));
}
}, {
key: 'convertTest',
value: function convertTest(mochaTest) {
var suiteName;
var fullName;
}
if (!mochaTest.parent.root) {
suiteName = mochaTest.parent.title;
fullName = this.buildSuiteFullName(mochaTest.parent);
// Add also the test name.
fullName.push(mochaTest.title);
function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
if (typeof emitter.on === 'function') {
if (flags.once) {
emitter.once(name, listener);
} else {
fullName = [mochaTest.title];
emitter.on(name, listener);
}
} else if (typeof emitter.addEventListener === 'function') {
// EventTarget does not have `error` event semantics like Node
// EventEmitters, we do not listen for `error` events here.
emitter.addEventListener(name, function wrapListener(arg) {
// IE does not have builtin `{ once: true }` support so we
// have to do it manually.
if (flags.once) {
emitter.removeEventListener(name, wrapListener);
}
// If the test has the errors attached a "test end" must be emitted, else
// a "test start".
if (mochaTest.errors !== undefined) {
var status = mochaTest.state === undefined ? 'skipped' : mochaTest.state;
var errors = [];
listener(arg);
});
} else {
throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + _typeof(emitter));
}
}
events.once = once_1;
mochaTest.errors.forEach(function (error) {
errors.push(new Assertion(false, error.actual, error.expected, error.message || error.toString(), error.stack));
});
function aggregateTests(all) {
var testCounts = {
passed: all.filter(function (test) {
return test.status === 'passed';
}).length,
failed: all.filter(function (test) {
return test.status === 'failed';
}).length,
skipped: all.filter(function (test) {
return test.status === 'skipped';
}).length,
todo: all.filter(function (test) {
return test.status === 'todo';
}).length,
total: all.length
};
var status = testCounts.failed ? 'failed' : 'passed';
var runtime = 0;
all.forEach(function (test) {
runtime += test.runtime || 0;
});
return {
status: status,
testCounts: testCounts,
runtime: runtime
};
}
// Test end, for the assertions property pass an empty array.
return new TestEnd(mochaTest.title, suiteName, fullName, status, mochaTest.duration, errors, errors);
}
function createTestStart$1(testEnd) {
return {
name: testEnd.name,
suiteName: testEnd.suiteName,
fullName: testEnd.fullName.slice()
};
}
// Test start.
return new TestStart(mochaTest.title, suiteName, fullName);
}
var helpers = {
aggregateTests: aggregateTests,
createTestStart: createTestStart$1
};
/**
* Builds an array with the names of nested suites.
*/
/**
* Known limitations:
*
* - Due to ordering issues with nested modules on QUnit < 2.2, this adapter
* buffers events and only emits them after the run has completed.
* See <https://github.com/js-reporters/js-reporters/pull/60>
*/
}, {
key: 'buildSuiteFullName',
value: function buildSuiteFullName(mochaSuite) {
var fullName = [];
var parent = mochaSuite.parent;
var QUnitAdapter_1 = /*#__PURE__*/function (_EventEmitter) {
_inherits(QUnitAdapter, _EventEmitter);
if (!mochaSuite.root) {
fullName.push(mochaSuite.title);
}
var _super = _createSuper(QUnitAdapter);
while (parent && !parent.root) {
fullName.unshift(parent.title);
parent = parent.parent;
}
function QUnitAdapter(QUnit) {
var _this;
return fullName;
}
}, {
key: 'onStart',
value: function onStart() {
var globalSuiteStart = this.convertToSuiteStart(this.runner.suite);
globalSuiteStart.name = undefined;
_classCallCheck(this, QUnitAdapter);
this.emit('runStart', globalSuiteStart);
}
}, {
key: 'onSuite',
value: function onSuite(mochaSuite) {
if (!mochaSuite.root) {
this.emit('suiteStart', this.convertToSuiteStart(mochaSuite));
}
}
}, {
key: 'onTest',
value: function onTest(mochaTest) {
this.errors = [];
_this = _super.call(this);
_this.QUnit = QUnit;
_this.testEnds = {};
_this.moduleEnds = [];
_this.delim = ' > ';
_this.totalBegin = null; // Ordered lists
this.emit('testStart', this.convertTest(mochaTest));
_this.globalTests = null;
_this.globalModules = null;
QUnit.begin(_this.onBegin.bind(_assertThisInitialized(_this)));
QUnit.log(_this.onLog.bind(_assertThisInitialized(_this)));
QUnit.testDone(_this.onTestDone.bind(_assertThisInitialized(_this)));
QUnit.done(_this.onDone.bind(_assertThisInitialized(_this)));
return _this;
}
/**
* Emits the start of pending tests, because Mocha does not emit skipped tests
* on its "test" event.
*/
_createClass(QUnitAdapter, [{
key: "prepTestEnd",
value: function prepTestEnd(suiteName, parentNames, details) {
var testEnd = this.testEnds[details.testId] = {
name: details.name,
suiteName: suiteName,
fullName: [].concat(_toConsumableArray(parentNames), [details.name]),
// Placeholders, populated by onTestDone() and onLog()
status: null,
runtime: null,
errors: [],
assertions: []
};
return testEnd;
}
}, {
key: "processModule",
value: function processModule(qunitModule) {
var _this2 = this;
}, {
key: 'onPending',
value: function onPending(mochaTest) {
this.emit('testStart', this.convertTest(mochaTest));
}
}, {
key: 'onFail',
value: function onFail(test, error) {
this.errors.push(error);
}
}, {
key: 'onTestEnd',
value: function onTestEnd(mochaTest) {
// Save the errors on Mocha's test object, because when the suite that
// contains this test is emitted on the "suiteEnd" event, it should contain
// also this test with all its details (errors, status, runtime). Runtime
// and status are already attached to the test, but the errors don't.
mochaTest.errors = this.errors;
this.emit('testEnd', this.convertTest(mochaTest));
}
}, {
key: 'onSuiteEnd',
value: function onSuiteEnd(mochaSuite) {
if (!mochaSuite.root) {
this.emit('suiteEnd', this.convertToSuiteEnd(mochaSuite));
var fullName = qunitModule.name.split(this.delim);
var name = fullName.slice(-1)[0];
var childTests = qunitModule.tests.map(function (details) {
return _this2.prepTestEnd(name, fullName, details);
});
return {
suiteEnd: {
name: name,
fullName: fullName,
// Placeholders, populated by emitTests()
status: null,
runtime: null
},
childTests: childTests,
childModules: []
};
}
}
}, {
key: 'onEnd',
value: function onEnd() {
var globalSuiteEnd = this.convertToSuiteEnd(this.runner.suite);
globalSuiteEnd.name = undefined;
}, {
key: "processEverything",
value: function processEverything() {
var _this3 = this;
this.emit('runEnd', globalSuiteEnd);
}
}]);
return MochaAdapter;
}(EventEmitter);
var modules; // Access QUnit internals to get all modules and tests,
// working around missing event data.
// First, find any global tests.
/**
* Limitations:
* - Errors in afterAll are ignored.
*/
if (this.QUnit.config.modules.length > 0 && this.QUnit.config.modules[0].name === '') {
this.globalTests = this.QUnit.config.modules[0].tests.map(function (details) {
return _this3.prepTestEnd(null, [], details);
});
modules = this.QUnit.config.modules.slice(1);
} else {
this.globalTests = [];
modules = this.QUnit.config.modules;
} // Prepare all suiteEnd leafs
var JasmineAdapter = function (_EventEmitter) {
inherits(JasmineAdapter, _EventEmitter);
function JasmineAdapter(jasmine) {
classCallCheck(this, JasmineAdapter);
modules = modules.map(this.processModule.bind(this)); // For CRI, each module will be represented as a wrapper test
var _this = possibleConstructorReturn(this, (JasmineAdapter.__proto__ || Object.getPrototypeOf(JasmineAdapter)).call(this));
this.totalBegin = Object.keys(this.testEnds).length + modules.length; // If a module has a composed name, its name will be the last part of the full name
// and its parent name will be the one right before it. Search for the parent
// module and add the current module to it as a child, among the test leafs.
_this.jasmine = jasmine;
// NodeJS/browser
_this.env = jasmine.env || jasmine.getEnv();
_this.suites = {};
_this.tests = {};
var globalModules = [];
modules.forEach(function (mod) {
if (mod.suiteEnd.fullName.length > 1) {
var parentFullName = mod.suiteEnd.fullName.slice(0, -1);
modules.forEach(function (otherMod) {
if (otherMod.suiteEnd.fullName.join(_this3.delim) === parentFullName.join(_this3.delim)) {
otherMod.childModules.push(mod);
}
});
} else {
globalModules.push(mod);
}
});
this.globalModules = globalModules;
}
}, {
key: "emitTests",
value: function emitTests() {
var _this4 = this;
var reporter = {
jasmineStarted: _this.onJasmineStarted.bind(_this),
specDone: _this.onSpecDone.bind(_this),
specStarted: _this.onSpecStarted.bind(_this),
suiteStarted: _this.onSuiteStarted.bind(_this),
suiteDone: _this.onSuiteDone.bind(_this),
jasmineDone: _this.onJasmineDone.bind(_this)
this.globalTests.forEach(function (testEnd) {
_this4.emit('testStart', helpers.createTestStart(testEnd));
// For NodeJS env use the "addReporter" function from the node package.
};if (_this.jasmine.addReporter) {
_this.jasmine.addReporter(reporter);
} else {
// For browser env use the "addReporter" function from the jasmine-core.
_this.env.addReporter(reporter);
}
return _this;
}
_this4.emit('testEnd', testEnd);
});
createClass(JasmineAdapter, [{
key: 'createAssertion',
value: function createAssertion(expectation) {
var stack = expectation.stack !== '' ? expectation.stack : undefined;
var emitModule = function emitModule(mod) {
_this4.emit('suiteStart', {
name: mod.suiteEnd.name,
fullName: mod.suiteEnd.fullName.slice()
});
return new Assertion(expectation.passed, expectation.actual, expectation.expected, expectation.message, stack);
}
}, {
key: 'saveTestDetails',
value: function saveTestDetails(jasmineSpec) {
var _this2 = this;
mod.childTests.forEach(function (testEnd) {
_this4.emit('testStart', helpers.createTestStart(testEnd));
var test = this.tests[jasmineSpec.id];
_this4.emit('testEnd', testEnd);
});
mod.childModules.forEach(function (child) {
return emitModule(child);
}); // This is non-recursive and can be because we emit modules in the original
// depth-first execution order. We fill in the status/runtime placeholders
// for the suiteEnd object of a nested module, and then later a parent module
// follows and sees that child suiteEnd object by reference and can propagate
// and aggregate the information further.
test.errors = [];
test.assertions = [];
var helperData = helpers.aggregateTests([].concat(_toConsumableArray(mod.childTests), _toConsumableArray(mod.childModules.map(function (child) {
return child.suiteEnd;
}))));
mod.suiteEnd.status = helperData.status;
mod.suiteEnd.runtime = helperData.runtime;
jasmineSpec.failedExpectations.forEach(function (expectation) {
test.errors.push(_this2.createAssertion(expectation));
test.assertions.push(_this2.createAssertion(expectation));
});
_this4.moduleEnds.push(mod.suiteEnd);
jasmineSpec.passedExpectations.forEach(function (expectation) {
test.assertions.push(_this2.createAssertion(expectation));
});
_this4.emit('suiteEnd', mod.suiteEnd);
};
if (jasmineSpec.status === 'pending') {
test.status = 'skipped';
} else {
test.status = jasmineSpec.status;
test.runtime = new Date() - this.startTime;
this.globalModules.forEach(emitModule);
}
}
}, {
key: 'isJasmineGlobalSuite',
value: function isJasmineGlobalSuite(suite) {
return suite.description === 'Jasmine__TopLevel__Suite';
}
}, {
key: "onBegin",
value: function onBegin(details) {
this.processEverything();
this.emit('runStart', {
name: null,
testCounts: {
total: this.totalBegin
}
});
}
}, {
key: "onLog",
value: function onLog(details) {
var assertion = {
passed: details.result,
actual: details.actual,
expected: details.expected,
message: details.message,
stack: details.source || null
};
/**
* Jasmine provides details about childSuites and tests only in the structure
* returned by "this.env.topSuite()".
*
* This function creates the global suite for the runStart event, as also
* saves the created suites and tests compliant with the CRI standard in an
* object using as key their unique ids provided by Jasmine.
*/
if (this.testEnds[details.testId]) {
if (!details.result) {
this.testEnds[details.testId].errors.push(assertion);
}
}, {
key: 'createGlobalSuite',
value: function createGlobalSuite(jasmineSuite, fullName) {
var _this3 = this;
var childSuites = [];
var tests = [];
var isGlobalSuite = this.isJasmineGlobalSuite(jasmineSuite);
if (!isGlobalSuite) {
fullName.push(jasmineSuite.description);
this.testEnds[details.testId].assertions.push(assertion);
}
}
}, {
key: "onTestDone",
value: function onTestDone(details) {
var testEnd = this.testEnds[details.testId];
jasmineSuite.children.forEach(function (child) {
if (child.id.indexOf('suite') === 0) {
childSuites.push(_this3.createGlobalSuite(child, fullName));
if (details.failed > 0) {
testEnd.status = 'failed';
} else if (details.skipped) {
testEnd.status = 'skipped';
} else {
var test = void 0;
var suiteName = !isGlobalSuite ? jasmineSuite.description : undefined;
testEnd.status = 'passed';
} // QUnit uses 0 instead of null for runtime of skipped tests.
fullName.push(child.description);
test = new TestEnd(child.description, suiteName, fullName.slice());
if (!details.skipped) {
testEnd.runtime = details.runtime;
} else {
testEnd.runtime = null;
}
}
}, {
key: "onDone",
value: function onDone(details) {
this.emitTests();
fullName.pop();
var allTests = _toConsumableArray(this.moduleEnds);
tests.push(test);
_this3.tests[child.id] = test;
for (var testId in this.testEnds) {
allTests.push(this.testEnds[testId]);
}
});
var name = !isGlobalSuite ? jasmineSuite.description : undefined;
var suite = new SuiteStart(name, fullName.slice(), tests, childSuites);
var helperData = helpers.aggregateTests(allTests);
this.emit('runEnd', {
name: null,
status: helperData.status,
testCounts: helperData.testCounts,
runtime: details.runtime || null
});
}
}]);
this.suites[jasmineSuite.id] = suite;
return QUnitAdapter;
}(events);
fullName.pop();
/**
* Known limitations:
*
* - Errors in afterAll are ignored.
*/
return suite;
}
}, {
key: 'onJasmineStarted',
value: function onJasmineStarted() {
this.globalSuite = this.createGlobalSuite(this.env.topSuite(), []);
this.emit('runStart', createSuiteStart(this.globalSuite));
}
}, {
key: 'onSpecStarted',
value: function onSpecStarted(details) {
this.startTime = new Date();
this.emit('testStart', createTestStart(this.tests[details.id]));
}
}, {
key: 'onSpecDone',
value: function onSpecDone(details) {
this.saveTestDetails(details);
this.emit('testEnd', createTestEnd(this.tests[details.id]));
}
}, {
key: 'onSuiteStarted',
value: function onSuiteStarted(details) {
this.emit('suiteStart', createSuiteStart(this.suites[details.id]));
}
}, {
key: 'onSuiteDone',
value: function onSuiteDone(details) {
this.emit('suiteEnd', createSuiteEnd(this.suites[details.id]));
}
}, {
key: 'onJasmineDone',
value: function onJasmineDone() {
this.emit('runEnd', createSuiteEnd(this.globalSuite));
}
}]);
return JasmineAdapter;
}(EventEmitter);
var JasmineAdapter_1 = /*#__PURE__*/function (_EventEmitter) {
_inherits(JasmineAdapter, _EventEmitter);
/* global QUnit, mocha, jasmine */
var _super = _createSuper(JasmineAdapter);
/**
* Auto registers the adapter for the respective testing framework and
* returns the runner for event listening.
*/
function autoRegister() {
var runner;
function JasmineAdapter(jasmine) {
var _this;
if (QUnit) {
runner = new QUnitAdapter(QUnit);
} else if (mocha) {
runner = new MochaAdapter(mocha);
} else if (jasmine) {
runner = new JasmineAdapter(jasmine);
} else {
throw new Error('Failed to register js-reporters adapter. Supported ' + 'frameworks are: QUnit, Mocha, Jasmine');
}
_classCallCheck(this, JasmineAdapter);
return runner;
}
_this = _super.call(this); // NodeJS or browser
function createSuiteStart(suite) {
return new SuiteStart(suite.name, suite.fullName.slice(), suite.tests.map(createTestStart), suite.childSuites.map(createSuiteStart));
}
_this.env = jasmine.env || jasmine.getEnv();
_this.suiteChildren = {};
_this.suiteEnds = [];
_this.suiteStarts = {};
_this.testStarts = {};
_this.testEnds = {}; // See <https://jasmine.github.io/api/3.6/Reporter.html>
function createSuiteEnd(suite) {
return new SuiteEnd(suite.name, suite.fullName.slice(), suite.tests.map(createTestEnd), suite.childSuites.map(createSuiteEnd));
}
var reporter = {
jasmineStarted: _this.onJasmineStarted.bind(_assertThisInitialized(_this)),
specDone: _this.onSpecDone.bind(_assertThisInitialized(_this)),
specStarted: _this.onSpecStarted.bind(_assertThisInitialized(_this)),
suiteStarted: _this.onSuiteStarted.bind(_assertThisInitialized(_this)),
suiteDone: _this.onSuiteDone.bind(_assertThisInitialized(_this)),
jasmineDone: _this.onJasmineDone.bind(_assertThisInitialized(_this))
};
function createTestStart(test) {
return new TestStart(test.name, test.suiteName, test.fullName.slice());
}
if (jasmine.addReporter) {
// For Node.js, use the method from jasmine-npm
jasmine.addReporter(reporter);
} else {
// For browser, use the method from jasmine-core
_this.env.addReporter(reporter);
}
function createTestEnd(test) {
return new TestEnd(test.name, test.suiteName, test.fullName.slice(), test.status, test.runtime, test.errors.slice(), test.assertions.slice());
}
return _this;
}
var QUnitAdapter = function (_EventEmitter) {
inherits(QUnitAdapter, _EventEmitter);
_createClass(JasmineAdapter, [{
key: "createAssertion",
value: function createAssertion(expectation) {
return {
passed: expectation.passed,
actual: expectation.actual,
expected: expectation.expected,
message: expectation.message,
stack: expectation.stack !== '' ? expectation.stack : null
};
}
}, {
key: "createTestEnd",
value: function createTestEnd(testStart, result) {
var _this2 = this;
function QUnitAdapter(QUnit) {
classCallCheck(this, QUnitAdapter);
var errors = result.failedExpectations.map(function (expectation) {
return _this2.createAssertion(expectation);
});
var assertions = errors.concat(result.passedExpectations.map(function (expectation) {
return _this2.createAssertion(expectation);
}));
return {
name: testStart.name,
suiteName: testStart.suiteName,
fullName: testStart.fullName.slice(),
status: result.status === 'pending' ? 'skipped' : result.status,
// TODO: Jasmine 3.4+ has result.duration, use it.
// Note that result.duration uses 0 instead of null for a 'skipped' test.
runtime: result.status === 'pending' ? null : new Date() - this.startTime,
errors: errors,
assertions: assertions
};
}
/**
* Traverse the Jasmine structured returned by `this.env.topSuite()`
* in order to extract the child-parent relations and full names.
*
*/
var _this = possibleConstructorReturn(this, (QUnitAdapter.__proto__ || Object.getPrototypeOf(QUnitAdapter)).call(this));
}, {
key: "processSuite",
value: function processSuite(result, parentNames, parentIds) {
var _this3 = this;
_this.QUnit = QUnit;
_this.tests = {};
_this.delim = ' > ';
var isGlobalSuite = result.description === 'Jasmine__TopLevel__Suite';
var name = isGlobalSuite ? null : result.description;
var fullName = parentNames.slice();
QUnit.begin(_this.onBegin.bind(_this));
QUnit.testStart(_this.onTestStart.bind(_this));
QUnit.log(_this.onLog.bind(_this));
QUnit.testDone(_this.onTestDone.bind(_this));
QUnit.done(_this.onDone.bind(_this));
return _this;
}
if (!isGlobalSuite) {
fullName.push(name);
}
createClass(QUnitAdapter, [{
key: 'convertModule',
value: function convertModule(qunitModule) {
var _this2 = this;
parentIds.push(result.id);
this.suiteChildren[result.id] = [];
result.children.forEach(function (child) {
if (child.id.indexOf('suite') === 0) {
_this3.suiteStarts[child.id] = {
name: child.description,
fullName: [].concat(_toConsumableArray(fullName), [child.description])
};
var fullName = qunitModule.name.split(this.delim).filter(function (value) {
return value !== '';
});
var childSuites = [];
_this3.processSuite(child, fullName.slice(), parentIds.slice());
} else {
_this3.testStarts[child.id] = {
name: child.description,
suiteName: name,
fullName: [].concat(_toConsumableArray(fullName), [child.description])
}; // Update flat list of test children
return new SuiteStart(qunitModule.name, fullName.slice(), qunitModule.tests.map(function (qunitTest) {
var indexStart = qunitModule.name.lastIndexOf(_this2.delim);
parentIds.forEach(function (id) {
_this3.suiteChildren[id].push(child.id);
});
}
});
}
}, {
key: "createSuiteEnd",
value: function createSuiteEnd(testStart, result) {
var _this4 = this;
indexStart = indexStart === -1 ? 0 : indexStart + _this2.delim.length;
fullName.push(qunitTest.name);
var tests = this.suiteChildren[result.id].map(function (testId) {
return _this4.testEnds[testId];
});
var helperData = helpers.aggregateTests(tests);
return {
name: testStart.name,
fullName: testStart.fullName,
// Jasmine has result.status, but does not propagate 'todo' or 'skipped'
status: helperData.status,
runtime: result.duration || helperData.runtime
};
}
}, {
key: "onJasmineStarted",
value: function onJasmineStarted() {
this.processSuite(this.env.topSuite(), [], []);
var total = 0;
this.env.topSuite().children.forEach(function countChild(child) {
total++;
var suiteName = qunitModule.name.substring(indexStart);
var test = new TestEnd(qunitTest.name, suiteName, fullName.slice());
if (child.id.indexOf('suite') === 0) {
child.children.forEach(countChild);
}
});
this.emit('runStart', {
name: null,
testCounts: {
total: total
}
});
}
}, {
key: "onSuiteStarted",
value: function onSuiteStarted(result) {
this.emit('suiteStart', this.suiteStarts[result.id]);
}
}, {
key: "onSpecStarted",
value: function onSpecStarted(result) {
this.startTime = new Date();
this.emit('testStart', this.testStarts[result.id]);
}
}, {
key: "onSpecDone",
value: function onSpecDone(result) {
this.testEnds[result.id] = this.createTestEnd(this.testStarts[result.id], result);
this.emit('testEnd', this.testEnds[result.id]);
}
}, {
key: "onSuiteDone",
value: function onSuiteDone(result) {
var suiteEnd = this.createSuiteEnd(this.suiteStarts[result.id], result);
this.suiteEnds.push(suiteEnd);
this.emit('suiteEnd', suiteEnd);
}
}, {
key: "onJasmineDone",
value: function onJasmineDone(doneInfo) {
var _this5 = this;
_this2.tests[qunitTest.testId] = test;
fullName.pop();
var topSuite = this.env.topSuite();
var tests = this.suiteChildren[topSuite.id].map(function (testId) {
return _this5.testEnds[testId];
});
var helperData = helpers.aggregateTests([].concat(_toConsumableArray(tests), _toConsumableArray(this.suiteEnds)));
this.emit('runEnd', {
name: null,
status: helperData.status,
testCounts: helperData.testCounts,
runtime: helperData.runtime
});
}
}]);
return test;
}), childSuites);
}
}, {
key: 'saveTestDetails',
value: function saveTestDetails(qunitTest) {
var test = this.tests[qunitTest.testId];
return JasmineAdapter;
}(events);
test.errors = this.errors;
test.assertions = this.assertions;
var MochaAdapter_1 = /*#__PURE__*/function (_EventEmitter) {
_inherits(MochaAdapter, _EventEmitter);
if (qunitTest.failed > 0) {
test.status = 'failed';
} else if (qunitTest.skipped) {
test.status = 'skipped';
} else {
test.status = 'passed';
}
var _super = _createSuper(MochaAdapter);
// Workaround for QUnit skipped tests runtime which is a Number.
if (test.status !== 'skipped') {
test.runtime = qunitTest.runtime;
} else {
test.runtime = undefined;
}
}
}, {
key: 'createGlobalSuite',
value: function createGlobalSuite() {
var _this3 = this;
function MochaAdapter(mocha) {
var _this;
var topLevelSuites = [];
var globalSuite;
var modules;
_classCallCheck(this, MochaAdapter);
// Access QUnit internals to get all suites and tests, working around
// missing event data.
_this = _super.call(this);
_this.errors = null;
_this.finalRuntime = 0;
_this.finalCounts = {
passed: 0,
failed: 0,
skipped: 0,
todo: 0,
total: 0
}; // Mocha will instantiate the given function as a class, even if you only need a callback.
// As such, it can't be an arrow function as those throw TypeError when instantiated.
// Create the global suite first.
if (this.QUnit.config.modules.length > 0 && this.QUnit.config.modules[0].name === '') {
globalSuite = this.convertModule(this.QUnit.config.modules[0]);
globalSuite.name = undefined;
var self = _assertThisInitialized(_this);
// The suiteName of global tests must be undefined.
globalSuite.tests.forEach(function (test) {
test.suiteName = undefined;
});
mocha.reporter(function (runner) {
self.runner = runner;
runner.on('start', self.onStart.bind(self));
runner.on('suite', self.onSuite.bind(self));
runner.on('test', self.onTest.bind(self));
runner.on('pending', self.onPending.bind(self));
runner.on('fail', self.onFail.bind(self));
runner.on('test end', self.onTestEnd.bind(self));
runner.on('suite end', self.onSuiteEnd.bind(self));
runner.on('end', self.onEnd.bind(self));
});
return _this;
}
modules = this.QUnit.config.modules.slice(1);
} else {
globalSuite = new SuiteStart(undefined, [], [], []);
modules = this.QUnit.config.modules;
_createClass(MochaAdapter, [{
key: "convertToSuiteStart",
value: function convertToSuiteStart(mochaSuite) {
return {
name: mochaSuite.title,
fullName: this.titlePath(mochaSuite)
};
}
}, {
key: "convertToSuiteEnd",
value: function convertToSuiteEnd(mochaSuite) {
var tests = mochaSuite.tests.map(this.convertTest.bind(this));
var childSuites = mochaSuite.suites.map(this.convertToSuiteEnd.bind(this));
var helperData = helpers.aggregateTests([].concat(_toConsumableArray(tests), _toConsumableArray(childSuites)));
return {
name: mochaSuite.title,
fullName: this.titlePath(mochaSuite),
status: helperData.status,
runtime: helperData.runtime
};
}
}, {
key: "convertTest",
value: function convertTest(mochaTest) {
var suiteName;
var fullName;
// Build a list with all suites.
var suites = modules.map(this.convertModule.bind(this));
if (!mochaTest.parent.root) {
suiteName = mochaTest.parent.title;
fullName = this.titlePath(mochaTest.parent); // Add also the test name.
// Iterate through the whole suites and check if they have composed names,
// like "suiteName1 > suiteName2 > ... > suiteNameN".
//
// If a suite has a composed name, its name will be the last in the sequence
// and its parent name will be the one right before it. Search the parent
// suite after its name and then add the suite with the composed name to the
// childSuites.
//
// If a suite does not have a composed name, add it to the topLevelSuites,
// this means that this suite is the direct child of the global suite.
suites.forEach(function (suite) {
var indexEnd = suite.name.lastIndexOf(_this3.delim);
fullName.push(mochaTest.title);
} else {
suiteName = null;
fullName = [mochaTest.title];
}
if (indexEnd !== -1) {
// Find the ' > ' characters that appears before the parent name.
var indexStart = suite.name.substring(0, indexEnd).lastIndexOf(_this3.delim);
// If it is -1, the parent suite name starts at 0, else escape
// this characters ' > '.
indexStart = indexStart === -1 ? 0 : indexStart + _this3.delim.length;
if (mochaTest.errors !== undefined) {
// If the test has the 'errors' property, this is a "test end".
var errors = mochaTest.errors.map(function (error) {
return {
passed: false,
actual: error.actual,
expected: error.expected,
message: error.message || error.toString(),
stack: error.stack
};
}); // Mocha 8.0 introduced STATE_PENDING
// https://github.com/js-reporters/js-reporters/issues/116
var parentSuiteName = suite.name.substring(indexStart, indexEnd);
var status = mochaTest.state === undefined || mochaTest.state === 'pending' ? 'skipped' : mochaTest.state;
var runtime = mochaTest.duration === undefined ? null : mochaTest.duration;
return {
name: mochaTest.title,
suiteName: suiteName,
fullName: fullName,
status: status,
runtime: runtime,
errors: errors,
assertions: errors
};
} else {
// It is a "test start".
return {
name: mochaTest.title,
suiteName: suiteName,
fullName: fullName
};
}
}
}, {
key: "titlePath",
value: function titlePath(mochaSuite) {
if (mochaSuite.titlePath) {
// Mocha 4.0+ has Suite#titlePath()
return mochaSuite.titlePath();
}
// Keep only the name of the suite itself.
suite.name = suite.name.substring(indexEnd + _this3.delim.length);
var fullName = [];
suites.forEach(function (parentSuite) {
if (parentSuite.name === parentSuiteName) {
parentSuite.childSuites.push(suite);
}
});
} else {
topLevelSuites.push(suite);
if (!mochaSuite.root) {
fullName.push(mochaSuite.title);
}
});
globalSuite.childSuites = topLevelSuites;
var parent = mochaSuite.parent;
return globalSuite;
}
}, {
key: 'createAssertion',
value: function createAssertion(qunitTest) {
return new Assertion(qunitTest.result, qunitTest.actual, qunitTest.expected, qunitTest.message, qunitTest.source || undefined);
}
}, {
key: 'emitData',
value: function emitData(suite) {
var _this4 = this;
while (parent && !parent.root) {
fullName.unshift(parent.title);
parent = parent.parent;
}
suite.tests.forEach(function (test) {
_this4.emit('testStart', createTestStart(test));
_this4.emit('testEnd', createTestEnd(test));
});
return fullName;
}
}, {
key: "onStart",
value: function onStart() {
// total is all tests + all suites
// each suite gets a CRI "test" wrapper
var total = this.runner.suite.total();
this.runner.suite.suites.forEach(function addSuites(suite) {
total++;
suite.suites.forEach(addSuites);
});
this.emit('runStart', {
name: null,
testCounts: {
total: total
}
});
}
}, {
key: "onSuite",
value: function onSuite(mochaSuite) {
if (!mochaSuite.root) {
this.emit('suiteStart', this.convertToSuiteStart(mochaSuite));
}
}
}, {
key: "onTest",
value: function onTest(mochaTest) {
this.errors = [];
this.emit('testStart', this.convertTest(mochaTest));
}
/**
* Mocha emits skipped tests here instead of on the "test" event.
*/
suite.childSuites.forEach(function (childSuite) {
_this4.emit('suiteStart', createSuiteStart(childSuite));
_this4.emitData(childSuite);
_this4.emit('suiteEnd', createSuiteEnd(childSuite));
});
}
}, {
key: 'onBegin',
value: function onBegin() {
this.globalSuite = this.createGlobalSuite();
}
}, {
key: 'onTestStart',
value: function onTestStart(details) {
this.errors = [];
this.assertions = [];
}
}, {
key: 'onLog',
value: function onLog(details) {
if (!details.result) {
this.errors.push(this.createAssertion(details));
}, {
key: "onPending",
value: function onPending(mochaTest) {
this.emit('testStart', this.convertTest(mochaTest));
}
}, {
key: "onFail",
value: function onFail(test, error) {
this.errors.push(error);
}
}, {
key: "onTestEnd",
value: function onTestEnd(mochaTest) {
// Save the errors on Mocha's test object, because when the suite that
// contains this test is emitted on the "suiteEnd" event, it should also
// contain this test with all its details (errors, status, runtime). Runtime
// and status are already attached to the test, but the errors are not.
mochaTest.errors = this.errors;
var testEnd = this.convertTest(mochaTest);
this.emit('testEnd', testEnd);
this.finalCounts.total++;
this.finalCounts[testEnd.status]++;
this.finalRuntime += testEnd.runtime || 0;
}
}, {
key: "onSuiteEnd",
value: function onSuiteEnd(mochaSuite) {
if (!mochaSuite.root) {
var suiteEnd = this.convertToSuiteEnd(mochaSuite);
this.emit('suiteEnd', suiteEnd);
this.finalCounts.total++;
this.finalCounts[suiteEnd.status]++;
this.finalRuntime += suiteEnd.runtime || 0;
}
}
}, {
key: "onEnd",
value: function onEnd(details) {
this.emit('runEnd', {
name: null,
status: this.finalCounts.failed > 0 ? 'failed' : 'passed',
testCounts: this.finalCounts,
runtime: this.finalRuntime
});
}
}]);
this.assertions.push(this.createAssertion(details));
}
}, {
key: 'onTestDone',
value: function onTestDone(details) {
this.saveTestDetails(details);
}
}, {
key: 'onDone',
value: function onDone() {
this.emit('runStart', createSuiteStart(this.globalSuite));
this.emitData(this.globalSuite);
this.emit('runEnd', createSuiteEnd(this.globalSuite));
}
}]);
return QUnitAdapter;
}(EventEmitter);
return MochaAdapter;
}(events);
var index$2 = createCommonjsModule(function (module) {
'use strict';
var FORCE_COLOR,
NODE_DISABLE_COLORS,
NO_COLOR,
TERM,
isTTY = true;
var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
if (typeof process !== 'undefined') {
var _process$env = process.env;
FORCE_COLOR = _process$env.FORCE_COLOR;
NODE_DISABLE_COLORS = _process$env.NODE_DISABLE_COLORS;
NO_COLOR = _process$env.NO_COLOR;
TERM = _process$env.TERM;
isTTY = process.stdout && process.stdout.isTTY;
}
module.exports = function (str) {
if (typeof str !== 'string') {
throw new TypeError('Expected a string');
}
var $ = {
enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== 'dumb' && (FORCE_COLOR != null && FORCE_COLOR !== '0' || isTTY),
// modifiers
reset: init(0, 0),
bold: init(1, 22),
dim: init(2, 22),
italic: init(3, 23),
underline: init(4, 24),
inverse: init(7, 27),
hidden: init(8, 28),
strikethrough: init(9, 29),
// colors
black: init(30, 39),
red: init(31, 39),
green: init(32, 39),
yellow: init(33, 39),
blue: init(34, 39),
magenta: init(35, 39),
cyan: init(36, 39),
white: init(37, 39),
gray: init(90, 39),
grey: init(90, 39),
// background colors
bgBlack: init(40, 49),
bgRed: init(41, 49),
bgGreen: init(42, 49),
bgYellow: init(43, 49),
bgBlue: init(44, 49),
bgMagenta: init(45, 49),
bgCyan: init(46, 49),
bgWhite: init(47, 49)
};
return str.replace(matchOperatorsRe, '\\$&');
};
});
function run(arr, str) {
var i = 0,
tmp,
beg = '',
end = '';
var index$3 = interopDefault(index$2);
for (; i < arr.length; i++) {
tmp = arr[i];
beg += tmp.open;
end += tmp.close;
var require$$4 = Object.freeze({
default: index$3
});
if (!!~str.indexOf(tmp.close)) {
str = str.replace(tmp.rgx, tmp.close + tmp.open);
}
}
var index$4 = createCommonjsModule(function (module) {
'use strict';
return beg + str + end;
}
function assembleStyles() {
var styles = {
modifiers: {
reset: [0, 0],
bold: [1, 22], // 21 isn't widely supported and 22 does the same thing
dim: [2, 22],
italic: [3, 23],
underline: [4, 24],
inverse: [7, 27],
hidden: [8, 28],
strikethrough: [9, 29]
},
colors: {
black: [30, 39],
red: [31, 39],
green: [32, 39],
yellow: [33, 39],
blue: [34, 39],
magenta: [35, 39],
cyan: [36, 39],
white: [37, 39],
gray: [90, 39]
},
bgColors: {
bgBlack: [40, 49],
bgRed: [41, 49],
bgGreen: [42, 49],
bgYellow: [43, 49],
bgBlue: [44, 49],
bgMagenta: [45, 49],
bgCyan: [46, 49],
bgWhite: [47, 49]
}
};
function chain(has, keys) {
var ctx = {
has: has,
keys: keys
};
ctx.reset = $.reset.bind(ctx);
ctx.bold = $.bold.bind(ctx);
ctx.dim = $.dim.bind(ctx);
ctx.italic = $.italic.bind(ctx);
ctx.underline = $.underline.bind(ctx);
ctx.inverse = $.inverse.bind(ctx);
ctx.hidden = $.hidden.bind(ctx);
ctx.strikethrough = $.strikethrough.bind(ctx);
ctx.black = $.black.bind(ctx);
ctx.red = $.red.bind(ctx);
ctx.green = $.green.bind(ctx);
ctx.yellow = $.yellow.bind(ctx);
ctx.blue = $.blue.bind(ctx);
ctx.magenta = $.magenta.bind(ctx);
ctx.cyan = $.cyan.bind(ctx);
ctx.white = $.white.bind(ctx);
ctx.gray = $.gray.bind(ctx);
ctx.grey = $.grey.bind(ctx);
ctx.bgBlack = $.bgBlack.bind(ctx);
ctx.bgRed = $.bgRed.bind(ctx);
ctx.bgGreen = $.bgGreen.bind(ctx);
ctx.bgYellow = $.bgYellow.bind(ctx);
ctx.bgBlue = $.bgBlue.bind(ctx);
ctx.bgMagenta = $.bgMagenta.bind(ctx);
ctx.bgCyan = $.bgCyan.bind(ctx);
ctx.bgWhite = $.bgWhite.bind(ctx);
return ctx;
}
// fix humans
styles.colors.grey = styles.colors.gray;
function init(open, close) {
var blk = {
open: "\x1B[".concat(open, "m"),
close: "\x1B[".concat(close, "m"),
rgx: new RegExp("\\x1b\\[".concat(close, "m"), 'g')
};
return function (txt) {
if (this !== void 0 && this.has !== void 0) {
!!~this.has.indexOf(open) || (this.has.push(open), this.keys.push(blk));
return txt === void 0 ? this : $.enabled ? run(this.keys, txt + '') : txt + '';
}
Object.keys(styles).forEach(function (groupName) {
var group = styles[groupName];
return txt === void 0 ? chain([open], [blk]) : $.enabled ? run([blk], txt + '') : txt + '';
};
}
Object.keys(group).forEach(function (styleName) {
var style = group[styleName];
var kleur = $;
styles[styleName] = group[styleName] = {
open: '\x1B[' + style[0] + 'm',
close: '\x1B[' + style[1] + 'm'
};
});
var hasOwn$1 = Object.hasOwnProperty;
/**
* Format a given value into YAML.
*
* YAML is a superset of JSON that supports all the same data
* types and syntax, and more. As such, it is always possible
* to fallback to JSON.stringfify, but we generally avoid
* that to make output easier to read for humans.
*
* Supported data types:
*
* - null
* - boolean
* - number
* - string
* - array
* - object
*
* Anything else (including NaN, Infinity, and undefined)
* must be described in strings, for display purposes.
*
* Note that quotes are optional in YAML strings if the
* strings are "simple", and as such we generally prefer
* that for improved readability. We output strings in
* one of three ways:
*
* - bare unquoted text, for simple one-line strings.
* - JSON (quoted text), for complex one-line strings.
* - YAML Block, for complex multi-line strings.
*
* Objects with cyclical references will be stringifed as
* "[Circular]" as they cannot otherwise be represented.
*/
Object.defineProperty(styles, groupName, {
value: group,
enumerable: false
});
});
function prettyYamlValue(value) {
var indent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 4;
return styles;
}
if (value === undefined) {
// Not supported in JSON/YAML, turn into string
// and let the below output it as bare string.
value = String(value);
} // Support IE 9-11: Use isFinite instead of ES6 Number.isFinite
Object.defineProperty(module, 'exports', {
enumerable: true,
get: assembleStyles
});
});
var index$5 = interopDefault(index$4);
if (typeof value === 'number' && !isFinite(value)) {
// Turn NaN and Infinity into simple strings.
// Paranoia: Don't return directly just in case there's
// a way to add special characters here.
value = String(value);
}
var require$$3 = Object.freeze({
default: index$5
});
if (typeof value === 'number') {
// Simple numbers
return JSON.stringify(value);
}
var index$8 = createCommonjsModule(function (module) {
'use strict';
if (typeof value === 'string') {
// If any of these match, then we can't output it
// as bare unquoted text, because that would either
// cause data loss or invalid YAML syntax.
//
// - Quotes, escapes, line breaks, or JSON-like stuff.
var rSpecialJson = /['"\\/[{}\]\r\n]/; // - Characters that are special at the start of a YAML value
module.exports = function () {
return (/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]/g
);
};
});
var rSpecialYaml = /[-?:,[\]{}#&*!|=>'"%@`]/; // - Leading or trailing whitespace.
var index$9 = interopDefault(index$8);
var rUntrimmed = /(^\s|\s$)/; // - Ambiguous as YAML number, e.g. '2', '-1.2', '.2', or '2_000'
var require$$0 = Object.freeze({
default: index$9
});
var rNumerical = /^[\d._-]+$/; // - Ambiguous as YAML bool.
// Use case-insensitive match, although technically only
// fully-lower, fully-upper, or uppercase-first would be ambiguous.
// e.g. true/True/TRUE, but not tRUe.
var index$6 = createCommonjsModule(function (module) {
'use strict';
var rBool = /^(true|false|y|n|yes|no|on|off)$/i; // Is this a complex string?
var ansiRegex = interopDefault(require$$0)();
if (value === '' || rSpecialJson.test(value) || rSpecialYaml.test(value[0]) || rUntrimmed.test(value) || rNumerical.test(value) || rBool.test(value)) {
if (!/\n/.test(value)) {
// Complex one-line string, use JSON (quoted string)
return JSON.stringify(value);
} // See also <https://yaml-multiline.info/>
// Support IE 9-11: Avoid ES6 String#repeat
module.exports = function (str) {
return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
};
});
var index$7 = interopDefault(index$6);
var prefix = new Array(indent + 1).join(' ');
var trailingLinebreakMatch = value.match(/\n+$/);
var trailingLinebreaks = trailingLinebreakMatch ? trailingLinebreakMatch[0].length : 0;
var require$$2 = Object.freeze({
default: index$7
});
if (trailingLinebreaks === 1) {
// Use the most straight-forward "Block" string in YAML
// without any "Chomping" indicators.
var lines = value // Ignore the last new line, since we'll get that one for free
// with the straight-forward Block syntax.
.replace(/\n$/, '').split('\n').map(function (line) {
return prefix + line;
});
return '|\n' + lines.join('\n');
} else {
// This has either no trailing new lines, or more than 1.
// Use |+ so that YAML parsers will preserve it exactly.
var _lines = value.split('\n').map(function (line) {
return prefix + line;
});
var index$10 = createCommonjsModule(function (module) {
'use strict';
return '|+\n' + _lines.join('\n');
}
} else {
// Simple string, use bare unquoted text
return value;
}
} // Handle null, boolean, array, and object
var ansiRegex = interopDefault(require$$0);
var re = new RegExp(ansiRegex().source); // remove the `g` flag
module.exports = re.test.bind(re);
});
var index$11 = interopDefault(index$10);
return JSON.stringify(decycledShallowClone(value), null, 2);
}
/**
* Creates a shallow clone of an object where cycles have
* been replaced with "[Circular]".
*/
var require$$1 = Object.freeze({
default: index$11
});
var index$12 = createCommonjsModule(function (module) {
'use strict';
function decycledShallowClone(object) {
var ancestors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var argv = process.argv;
if (ancestors.indexOf(object) !== -1) {
return '[Circular]';
}
var terminator = argv.indexOf('--');
var hasFlag = function hasFlag(flag) {
flag = '--' + flag;
var pos = argv.indexOf(flag);
return pos !== -1 && (terminator !== -1 ? pos < terminator : true);
};
var clone;
var type = Object.prototype.toString.call(object).replace(/^\[.+\s(.+?)]$/, '$1').toLowerCase();
module.exports = function () {
if ('FORCE_COLOR' in process.env) {
return true;
}
switch (type) {
case 'array':
ancestors.push(object);
clone = object.map(function (element) {
return decycledShallowClone(element, ancestors);
});
ancestors.pop();
break;
if (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) {
return false;
}
case 'object':
ancestors.push(object);
clone = {};
Object.keys(object).forEach(function (key) {
clone[key] = decycledShallowClone(object[key], ancestors);
});
ancestors.pop();
break;
if (hasFlag('color') || hasFlag('colors') || hasFlag('color=true') || hasFlag('color=always')) {
return true;
}
default:
clone = object;
}
if (process.stdout && !process.stdout.isTTY) {
return false;
}
return clone;
}
if (process.platform === 'win32') {
return true;
}
var TapReporter_1 = /*#__PURE__*/function () {
function TapReporter(runner) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if ('COLORTERM' in process.env) {
return true;
}
_classCallCheck(this, TapReporter);
if (process.env.TERM === 'dumb') {
return false;
}
// Cache references to console methods to ensure we can report failures
// from tests tests that mock the console object itself.
// https://github.com/js-reporters/js-reporters/issues/125
this.log = options.log || console.log.bind(console);
this.testCount = 0;
runner.on('runStart', this.onRunStart.bind(this));
runner.on('testEnd', this.onTestEnd.bind(this));
runner.on('runEnd', this.onRunEnd.bind(this));
}
if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) {
return true;
}
_createClass(TapReporter, [{
key: "onRunStart",
value: function onRunStart(globalSuite) {
this.log('TAP version 13');
}
}, {
key: "onTestEnd",
value: function onTestEnd(test) {
var _this = this;
return false;
}();
});
this.testCount = this.testCount + 1;
var index$13 = interopDefault(index$12);
if (test.status === 'passed') {
this.log("ok ".concat(this.testCount, " ").concat(test.fullName.join(' > ')));
} else if (test.status === 'skipped') {
this.log(kleur.yellow("ok ".concat(this.testCount, " # SKIP ").concat(test.fullName.join(' > '))));
} else if (test.status === 'todo') {
this.log(kleur.cyan("not ok ".concat(this.testCount, " # TODO ").concat(test.fullName.join(' > '))));
test.errors.forEach(function (error) {
return _this.logError(error, 'todo');
});
} else {
this.log(kleur.red("not ok ".concat(this.testCount, " ").concat(test.fullName.join(' > '))));
test.errors.forEach(function (error) {
return _this.logError(error);
});
}
}
}, {
key: "onRunEnd",
value: function onRunEnd(globalSuite) {
this.log("1..".concat(globalSuite.testCounts.total));
this.log("# pass ".concat(globalSuite.testCounts.passed));
this.log(kleur.yellow("# skip ".concat(globalSuite.testCounts.skipped)));
this.log(kleur.cyan("# todo ".concat(globalSuite.testCounts.todo)));
this.log(kleur.red("# fail ".concat(globalSuite.testCounts.failed)));
}
}, {
key: "logError",
value: function logError(error, severity) {
var out = ' ---';
out += "\n message: ".concat(prettyYamlValue(error.message || 'failed'));
out += "\n severity: ".concat(prettyYamlValue(severity || 'failed'));
var require$$0$1 = Object.freeze({
default: index$13
});
if (hasOwn$1.call(error, 'actual')) {
out += "\n actual : ".concat(prettyYamlValue(error.actual));
}
var index$1 = createCommonjsModule(function (module) {
'use strict';
if (hasOwn$1.call(error, 'expected')) {
out += "\n expected: ".concat(prettyYamlValue(error.expected));
}
var escapeStringRegexp = interopDefault(require$$4);
var ansiStyles = interopDefault(require$$3);
var stripAnsi = interopDefault(require$$2);
var hasAnsi = interopDefault(require$$1);
var supportsColor = interopDefault(require$$0$1);
var defineProps = Object.defineProperties;
var isSimpleWindowsTerm = process.platform === 'win32' && !/^xterm/i.test(process.env.TERM);
if (error.stack) {
// Since stacks aren't user generated, take a bit of liberty by
// adding a trailing new line to allow a straight-forward YAML Blocks.
out += "\n stack: ".concat(prettyYamlValue(error.stack + '\n'));
}
function Chalk(options) {
// detect mode if not set manually
this.enabled = !options || options.enabled === undefined ? supportsColor : options.enabled;
}
out += '\n ...';
this.log(out);
}
}], [{
key: "init",
value: function init(runner) {
return new TapReporter(runner);
}
}]);
// use bright blue on Windows as the normal blue color is illegible
if (isSimpleWindowsTerm) {
ansiStyles.blue.open = '\x1B[94m';
}
return TapReporter;
}();
var styles = function () {
var ret = {};
var ConsoleReporter_1 = /*#__PURE__*/function () {
function ConsoleReporter(runner) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
Object.keys(ansiStyles).forEach(function (key) {
ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');
_classCallCheck(this, ConsoleReporter);
ret[key] = {
get: function get() {
return build.call(this, this._styles.concat(key));
}
};
});
// Cache references to console methods to ensure we can report failures
// from tests tests that mock the console object itself.
// https://github.com/js-reporters/js-reporters/issues/125
this.log = options.log || console.log.bind(console);
runner.on('runStart', this.onRunStart.bind(this));
runner.on('testStart', this.onTestStart.bind(this));
runner.on('testEnd', this.onTestEnd.bind(this));
runner.on('runEnd', this.onRunEnd.bind(this));
}
return ret;
}();
_createClass(ConsoleReporter, [{
key: "onRunStart",
value: function onRunStart(runStart) {
this.log('runStart', runStart);
}
}, {
key: "onTestStart",
value: function onTestStart(test) {
this.log('testStart', test);
}
}, {
key: "onTestEnd",
value: function onTestEnd(test) {
this.log('testEnd', test);
}
}, {
key: "onRunEnd",
value: function onRunEnd(runEnd) {
this.log('runEnd', runEnd);
}
}], [{
key: "init",
value: function init(runner) {
return new ConsoleReporter(runner);
}
}]);
var proto = defineProps(function chalk() {}, styles);
return ConsoleReporter;
}();
function build(_styles) {
var builder = function builder() {
return applyStyle.apply(builder, arguments);
};
var hasOwn = Object.hasOwnProperty;
builder._styles = _styles;
builder.enabled = this.enabled;
// __proto__ is used because we must return a function, but there is
// no way to create a function with a different prototype.
/* eslint-disable no-proto */
builder.__proto__ = proto;
var SummaryReporter_1 = /*#__PURE__*/function (_EventEmitter) {
_inherits(SummaryReporter, _EventEmitter);
return builder;
}
var _super = _createSuper(SummaryReporter);
function applyStyle() {
// support varags, but simply cast to string in case there's only one arg
var args = arguments;
var argsLen = args.length;
var str = argsLen !== 0 && String(arguments[0]);
function SummaryReporter(runner) {
var _this;
if (argsLen > 1) {
// don't slice `arguments`, it prevents v8 optimizations
for (var a = 1; a < argsLen; a++) {
str += ' ' + args[a];
}
}
_classCallCheck(this, SummaryReporter);
if (!this.enabled || !str) {
return str;
}
_this = _super.call(this);
_this.top = {
name: null,
tests: [],
status: null,
testCounts: null,
runtime: null
}; // Map of full name to test objects
var nestedStyles = this._styles;
var i = nestedStyles.length;
_this.attachedTests = {}; // Map of full name to array of children test objects
// Turns out that on Windows dimmed gray text becomes invisible in cmd.exe,
// see https://github.com/chalk/chalk/issues/58
// If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop.
var originalDim = ansiStyles.dim.open;
if (isSimpleWindowsTerm && (nestedStyles.indexOf('gray') !== -1 || nestedStyles.indexOf('grey') !== -1)) {
ansiStyles.dim.open = '';
}
_this.detachedChildren = {};
_this.summary = null;
runner.on('suiteEnd', function (suiteEnd) {
var ownFull = suiteEnd.fullName.join('>');
var suiteName = suiteEnd.fullName.length >= 2 ? suiteEnd.fullName.slice(-2, -1)[0] : null;
var parentFull = suiteEnd.fullName.length > 1 ? suiteEnd.fullName.slice(0, -1).join('>') : null;
var children;
while (i--) {
var code = ansiStyles[nestedStyles[i]];
if (hasOwn.call(_this.detachedChildren, ownFull)) {
children = _this.detachedChildren[ownFull];
delete _this.detachedChildren[ownFull];
} else {
children = [];
}
// Replace any instances already present with a re-opening code
// otherwise only the part of the string until said closing code
// will be colored, and the rest will simply be 'plain'.
str = code.open + str.replace(code.closeRe, code.open) + code.close;
}
var test = _objectSpread2(_objectSpread2({}, suiteEnd), {}, {
suiteName: suiteName,
errors: [],
assertions: [],
tests: children
});
// Reset the original 'dim' if we changed it to work around the Windows dimmed gray issue.
ansiStyles.dim.open = originalDim;
if (parentFull === null) {
_this.top.tests.push(test);
} else if (hasOwn.call(_this.attachedTests, parentFull)) {
_this.attachedTests[parentFull].tests.push(test);
} else if (hasOwn.call(_this.detachedChildren, parentFull)) {
_this.detachedChildren[parentFull].push(test);
} else {
_this.detachedChildren[parentFull] = [test];
}
return str;
}
_this.attachedTests[ownFull] = test;
});
runner.on('testEnd', function (testEnd) {
var ownFull = testEnd.fullName.join('>');
var parentFull = testEnd.fullName.length > 1 ? testEnd.fullName.slice(0, -1).join('>') : null;
var children;
function init() {
var ret = {};
if (hasOwn.call(_this.detachedChildren, ownFull)) {
children = _this.detachedChildren[ownFull];
delete _this.detachedChildren[ownFull];
} else {
children = [];
}
Object.keys(styles).forEach(function (name) {
ret[name] = {
get: function get() {
return build.call(this, [name]);
}
};
});
var test = _objectSpread2(_objectSpread2({}, testEnd), {}, {
tests: children
});
return ret;
}
if (parentFull === null) {
_this.top.tests.push(test);
} else if (hasOwn.call(_this.attachedTests, parentFull)) {
_this.attachedTests[parentFull].tests.push(test);
} else if (hasOwn.call(_this.detachedChildren, parentFull)) {
_this.detachedChildren[parentFull].push(test);
} else {
_this.detachedChildren[parentFull] = [test];
}
defineProps(Chalk.prototype, init());
_this.attachedTests[ownFull] = test;
});
runner.once('runEnd', function (runEnd) {
_this.top.name = runEnd.name;
_this.top.status = runEnd.status;
_this.top.testCounts = runEnd.testCounts;
_this.top.runtime = runEnd.runtime;
_this.summary = _this.top;
var problems = Object.keys(_this.detachedChildren).join(', ');
module.exports = new Chalk();
module.exports.styles = ansiStyles;
module.exports.hasColor = hasAnsi;
module.exports.stripColor = stripAnsi;
module.exports.supportsColor = supportsColor;
});
if (problems.length) {
console.error('detachedChildren:', problems);
}
var chalk = interopDefault(index$1);
_this.top = null;
_this.attachedTests = null;
_this.detachedChildren = null;
var TapReporter = function () {
function TapReporter(runner) {
classCallCheck(this, TapReporter);
this.testCount = 0;
runner.on('runStart', this.onRunStart.bind(this));
runner.on('testEnd', this.onTestEnd.bind(this));
runner.on('runEnd', this.onRunEnd.bind(this));
}
createClass(TapReporter, [{
key: 'onRunStart',
value: function onRunStart(globalSuite) {
console.log('TAP version 13');
_this.emit('summary', _this.summary);
});
return _this;
}
}, {
key: 'onTestEnd',
value: function onTestEnd(test) {
var _this = this;
this.testCount = this.testCount + 1;
_createClass(SummaryReporter, [{
key: "getSummary",
value:
/**
* Get the summary via callback or Promise.
*
* @param {Function} [callback]
* @param {null|Error} [callback.err]
* @param {Object} [callback.summary]
* @return {undefined|Promise}
*/
function getSummary(callback) {
var _this2 = this;
if (test.status === 'passed') {
console.log('ok ' + this.testCount + ' ' + test.fullName.join(' > '));
} else if (test.status === 'skipped') {
console.log(chalk.yellow('ok ' + this.testCount + ' # SKIP ' + test.fullName.join(' > ')));
} else if (test.status === 'todo') {
console.log(chalk.cyan('not ok ' + this.testCount + ' # TODO ' + test.fullName.join(' > ')));
test.errors.forEach(function (error) {
return _this.logError(error, 'todo');
});
} else {
console.log(chalk.red('not ok ' + this.testCount + ' ' + test.fullName.join(' > ')));
test.errors.forEach(function (error) {
return _this.logError(error);
});
if (callback) {
if (this.summary) {
callback(null, this.summary);
} else {
this.once('summary', function (summary) {
callback(null, summary);
});
}
} else {
// Support IE 9-11: Only reference 'Promise' (which we don't polyfill) when needed.
// If the user doesn't use this reporter, or only its callback signature, then it should
// work in older browser as well.
return new Promise(function (resolve) {
if (_this2.summary) {
resolve(_this2.summary);
} else {
_this2.once('summary', function (summary) {
resolve(summary);
});
}
});
}
}
}
}, {
key: 'onRunEnd',
value: function onRunEnd(globalSuite) {
console.log('1..' + globalSuite.testCounts.total);
console.log('# pass ' + globalSuite.testCounts.passed);
console.log(chalk.yellow('# skip ' + globalSuite.testCounts.skipped));
console.log(chalk.cyan('# todo ' + globalSuite.testCounts.todo));
console.log(chalk.red('# fail ' + globalSuite.testCounts.failed));
}
}, {
key: 'logError',
value: function logError(error, severity) {
console.log(' ---');
console.log(' message: "' + (error.message || 'failed') + '"');
console.log(' severity: ' + (severity || 'failed'));
if (error.hasOwnProperty('actual')) {
var actualStr = error.actual !== undefined ? JSON.stringify(error.actual, null, 2) : 'undefined';
console.log(' actual : ' + actualStr);
}], [{
key: "init",
value: function init(runner) {
return new SummaryReporter(runner);
}
}]);
if (error.hasOwnProperty('expected')) {
var expectedStr = error.expected !== undefined ? JSON.stringify(error.expected, null, 2) : 'undefined';
console.log(' expected: ' + expectedStr);
}
return SummaryReporter;
}(events);
if (error.stack) {
console.log(' stack: ' + error.stack);
}
/* global QUnit, mocha, jasmine */
/**
* Auto registers the adapter for the respective testing framework and
* returns the runner for event listening.
*/
console.log(' ...');
function autoRegister$1() {
var runner;
if (QUnit) {
runner = new QUnitAdapter_1(QUnit);
} else if (mocha) {
runner = new MochaAdapter_1(mocha);
} else if (jasmine) {
runner = new JasmineAdapter_1(jasmine);
} else {
throw new Error('Failed to register js-reporters adapter. Supported ' + 'frameworks are: QUnit, Mocha, Jasmine');
}
}], [{
key: 'init',
value: function init(runner) {
return new TapReporter(runner);
}
}]);
return TapReporter;
}();
// TODO: finish grouping once suiteStart is implemented
var hasGrouping = 'group' in console && 'groupEnd' in console;
var ConsoleReporter = function () {
function ConsoleReporter(runner) {
classCallCheck(this, ConsoleReporter);
runner.on('runStart', this.onRunStart);
runner.on('suiteStart', this.onSuiteStart);
runner.on('testStart', this.onTestStart);
runner.on('testEnd', this.onTestEnd);
runner.on('suiteEnd', this.onSuiteEnd);
runner.on('runEnd', this.onRunEnd);
return runner;
}
createClass(ConsoleReporter, [{
key: 'onRunStart',
value: function onRunStart(suite) {
console.log('runStart', suite);
}
}, {
key: 'onSuiteStart',
value: function onSuiteStart(suite) {
if (hasGrouping) {
console.group(suite.name);
}
console.log('suiteStart', suite);
}
}, {
key: 'onTestStart',
value: function onTestStart(test) {
console.log('testStart', test);
}
}, {
key: 'onTestEnd',
value: function onTestEnd(test) {
console.log('testEnd', test);
}
}, {
key: 'onSuiteEnd',
value: function onSuiteEnd(suite) {
console.log('suiteEnd', suite);
if (hasGrouping) {
console.groupEnd();
}
}
}, {
key: 'onRunEnd',
value: function onRunEnd(globalSuite) {
console.log('runEnd', globalSuite);
}
}], [{
key: 'init',
value: function init(runner) {
return new ConsoleReporter(runner);
}
}]);
return ConsoleReporter;
}();
var auto = {
autoRegister: autoRegister$1
};
var index = {
QUnitAdapter: QUnitAdapter,
JasmineAdapter: JasmineAdapter,
MochaAdapter: MochaAdapter,
TapReporter: TapReporter,
ConsoleReporter: ConsoleReporter,
Assertion: Assertion,
TestStart: TestStart,
TestEnd: TestEnd,
SuiteStart: SuiteStart,
SuiteEnd: SuiteEnd,
createSuiteStart: createSuiteStart,
createTestStart: createTestStart,
createTestEnd: createTestEnd,
createSuiteEnd: createSuiteEnd,
autoRegister: autoRegister
};
var createTestStart = helpers.createTestStart;
var autoRegister = auto.autoRegister;
var jsReporters = {
QUnitAdapter: QUnitAdapter_1,
JasmineAdapter: JasmineAdapter_1,
MochaAdapter: MochaAdapter_1,
TapReporter: TapReporter_1,
ConsoleReporter: ConsoleReporter_1,
SummaryReporter: SummaryReporter_1,
EventEmitter: events,
createTestStart: createTestStart,
autoRegister: autoRegister
};
return index;
return jsReporters;
})));
})));
{
"name": "js-reporters",
"version": "1.2.3",
"description": "common reporter interface for javascript testing frameworks",
"version": "2.0.0",
"description": "Common reporter interface for JavaScript testing frameworks.",
"main": "dist/js-reporters.js",
"files": [
"dist/"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/js-reporters/js-reporters.git"
"url": "https://github.com/js-reporters/js-reporters.git"
},
"engines": {
"node": ">=10"
},
"scripts": {
"build": "rollup -c",
"prepare": "npm run build",
"pretest": "npm run build",
"test": "standard && npm run test-unit && npm run test-integration",
"test-unit": "mocha --recursive test/unit/ && npm run test-browser",
"lint": "semistandard",
"test": "npm run test-unit && npm run test-integration && npm run test-browser && npm run lint",
"test-unit": "qunit 'test/unit/*.js'",
"test-integration": "qunit test/integration/adapters.js",
"test-browser": "karma start",
"test-integration": "mocha test/integration/adapters.js",
"test-versions": "mocha test/versions/versions.js"
"test-browser-sauce": "karma start karma.conf.sauce.js",
"test-versions": "qunit test/versions/versions.js",
"coverage": "nyc qunit 'test/unit/*.js' test/integration/adapters.js",
"coveralls": "npm run coverage && cat coverage/lcov.info | coveralls"
},
"devDependencies": {
"babel-core": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-plugin-external-helpers": "^6.8.0",
"babel-plugin-transform-runtime": "^6.12.0",
"babel-preset-es2015": "^6.14.0",
"babel-runtime": "^6.11.6",
"chai": "^3.5.0",
"chalk": "^1.1.3",
"commitplease": "^2.2.3",
"events": "^1.1.0",
"jasmine": "2.5.1",
"karma": "^1.2.0",
"karma-chai": "^0.1.0",
"karma-mocha": "^1.1.1",
"karma-phantomjs-launcher": "^1.0.2",
"karma-sinon": "^1.0.5",
"karma-webpack": "^1.8.0",
"mocha": "^2.4.5",
"qunitjs": "^2.0.0-rc1",
"rollup": "^0.34.1",
"rollup-plugin-babel": "^2.6.1",
"rollup-plugin-commonjs": "^3.3.1",
"rollup-plugin-node-resolve": "^1.7.2",
"sinon": "^1.17.4",
"sinon-chai": "^2.8.0",
"standard": "^6.0.8",
"webpack": "^1.0.0"
"@babel/core": "7.13.14",
"@babel/preset-env": "7.13.12",
"@rollup/plugin-babel": "5.3.0",
"@rollup/plugin-commonjs": "18.0.0",
"@rollup/plugin-node-resolve": "11.2.1",
"coveralls": "3.1.0",
"events": "3.3.0",
"jasmine": "3.7.0",
"karma": "5.2.3",
"karma-chrome-launcher": "3.1.0",
"karma-firefox-launcher": "2.1.0",
"karma-qunit": "4.1.2",
"karma-rollup-preprocessor": "7.0.7",
"karma-sauce-launcher": "4.3.5",
"kleur": "4.1.4",
"mocha": "8.3.2",
"nyc": "15.1.0",
"qunit": "2.14.1",
"qunitjs": "1.23.1",
"rimraf": "3.0.2",
"rollup": "2.44.0",
"semistandard": "16.0.0",
"semver": "7.3.5",
"sinon": "1.17.4"
},
"commitplease": {
"components": [
"Build",
"Changelog",
"Readme",
"Release",
"Reporter",
"Test",
"Docs"
]
"nyc": {
"include": [
"lib/**"
],
"reporter": [
"text",
"html",
"lcovonly"
],
"report-dir": "coverage"
}
}
# js-reporters
[![Build Status](https://travis-ci.org/js-reporters/js-reporters.svg?branch=master)](https://travis-ci.org/js-reporters/js-reporters)
[![npm](https://img.shields.io/npm/dm/js-reporters.svg?maxAge=2592000)](https://www.npmjs.com/package/js-reporters)
[![npm](https://img.shields.io/npm/v/js-reporters.svg?maxAge=2592000)](https://www.npmjs.com/package/js-reporters)
[![npm](https://img.shields.io/npm/l/js-reporters.svg?maxAge=2592000)](https://www.npmjs.com/package/js-reporters)
[![Chat on Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/js-reporters/js-reporters)
[![Build Status](https://travis-ci.com/js-reporters/js-reporters.svg?branch=main)](https://travis-ci.com/js-reporters/js-reporters)
[![Coverage Status](https://coveralls.io/repos/github/js-reporters/js-reporters/badge.svg?branch=main)](https://coveralls.io/github/js-reporters/js-reporters?branch=main)
[![npm](https://img.shields.io/npm/dm/js-reporters.svg)](https://www.npmjs.com/package/js-reporters)
[![npm](https://img.shields.io/npm/v/js-reporters.svg)](https://www.npmjs.com/package/js-reporters)
The Common Reporter Interface (CRI) for JavaScript Unit Testing Frameworks.
The Common Reporter Interface (CRI) for JavaScript Testing Frameworks.

@@ -14,151 +15,61 @@ | Avoid this: | Do this: |

## Centralized Discussions
## Specification
https://github.com/js-reporters/js-reporters/issues/
**See [Common Reporter Interface](spec/cri-draft.adoc) for the latest version of the specification.**
## Background
See also:
We on the [QUnit](http://qunitjs.com/) team have been [discussing](https://github.com/qunitjs/qunit/issues/531) the possibility of working with other JS test frameworks, especially those that can be run client-side (e.g. Mocha, Jasmine, Intern, Buster, etc.), to agree upon a "Common Reporter Interface" so that we could hopefully share Reporter plugins between testing frameworks. This would also benefit high-level consumers of the frameworks such as Karma, BrowserStack, SauceLabs, Testling, etc.
* [example](docs/example.md), illustrates how reporting works in practice.
* [frameworks](docs/frameworks.md), studies various popular testing frameworks.
* **[Integrations](#integrations)**, a list of real-world implementations.
This would most likely come in the form of:
Help with AsciiDoc (used for the standard document):
- a common Reporter API/Interface, e.g.
- an EventEmitter interface (`.on(...)`/`.off(...)`) _**OR**_ an object with standard "hook" properties
- _maybe_ a standard-ish way to register a Reporter, e.g. `MyLib.addReporter(x)`, `MyLib.reporter = x;`, etc.
- a minimum viable set of standardly-named events
- an associated standard set of data/details provided for each event
- a minimum viable set of standard test status types (e.g. pass, fail, skip, todo, pending, etc.)
- updating all participating test frameworks to support this new common Reporter interface
* [AsciiDoc Syntax Quick Reference](https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/)
* [AsciiDoc User Manual](https://asciidoctor.org/docs/user-manual/)
* [AsciiDoc cheatsheet](https://powerman.name/doc/asciidoc)
Would _you_ be interested in discussing this with us further? Please join in!
## Background
## Draft Proposal
In 2014, the [QUnit](https://qunitjs.com/) team started [discussing](https://github.com/qunitjs/qunit/issues/531) the possibility of interoperability between JavaScript testing frameworks such as QUnit, Mocha, Jasmine, Intern, Buster, etc. The "Common Reporter Interface" would be an allow integrations for output formats and communication bridges to be shared between frameworks. This would also benefit high-level consumers of these frameworks such as Karma, BrowserStack, SauceLabs, Testling, by having a standard machine-readable interface.
### Event Names
Our mission is to deliver:
Based on the discussion in [#1](https://github.com/js-reporters/js-reporters/issues/1#issuecomment-54841874), this is the suggested _minimum_ set of event names to be triggered by a testing framework, to be consumed by reporters or other testing tools.
- a common JavaScript API, e.g. based on EventEmitter featuring `.on()` and `.off()`.
- a minimum viable set of events with standardized event names and event data.
- a minimum viable set of concepts behind those events to allow consumers to set expectations (e.g. define what "pass", "fail", "skip", "todo", and "pending" mean).
- work with participating testing frameworks to support the Common Reporter Interface.
- `runStart`: Indicates the beginning of a testsuite, triggered just once.
- `suiteStart`: Triggered at the start of each group of tests within a testsuite.
- `testStart`: Triggered at the start of each test.
- `testEnd`: Triggered at the end of each test.
- `suiteEnd`: Triggered at the end of each group of tests within a testsuite.
- `runEnd`: Indicates the end of a testsuite, triggered just once.
Would _you_ be interested in discussing this with us further? Please join in!
#### Selection Criteria
* [Join the Chat room](https://gitter.im/js-reporters/js-reporters)
* [Browse open issues](https://github.com/js-reporters/js-reporters/issues/)
* [Help frameworks and runners implement the spec](#cross-project-coordination)
The criteria for picking these event names included:
## js-reporters Package
- These use the most common terms across a selection of frameworks, as gathered in [#1](https://github.com/js-reporters/js-reporters/issues/1#issuecomment-54841874)
- It uses names that are valid JavaScript identifiers, which allows using those as keys in JSON and avoids the need to quote keys in regular JS objects or function calls.
- It doesn't overlap with any known existing events, so introducing these could be done in parallel to the existing API in each framework, optionally deprecating and eventually removing the previous API.
### Usage
#### Reporting Order
The recommended **reporting order** for emitting the aformentioned events with their related data should be done in **source order**. Please note that execution order is different from reporting order, that's why we don't assume any specific execution order, but we recommend whatever is higher up in the source file should be emitted first.
For more background check [#62](https://github.com/js-reporters/js-reporters/issues/62).
### Event Data
Based on the discussion in [#12](https://github.com/js-reporters/js-reporters/issues/12#issuecomment-120483356), there are two basic data structures: **Suites** and **Tests**. A test represents an atomic test/spec/`it()`. A suite contains tests and optionally other suites.
The structures have been divided in two parts, a start part and an end part:
- SuiteStart
- SuiteEnd
- TestStart
- TestEnd
For `testStart` and `testEnd`, the corresponding TestStart, respectively TestEnd, object is passed to the reporter. The same applies to `suiteStart` and `suiteEnd` where the matching SuiteStart/SuiteEnd object is passed to the reporter. For `runStart` and `runEnd` a "global" suite object is passed to the reporter, this suite wraps all other top-level user defined suites as its child suites, it will be reffered to as `globalSuite`.
The data structures are defined as follows:
- **SuiteStart**: `Object` - A SuiteStart is a collection of test-starts and potentially other suite-starts, emitted before the suite have been executed, which means before executing any of its tests and child suites.
- **name**: `String|undefined` - name of the suite, will be `undefined` only for the `globalSuite`.
- **fullname**: `Array` - array of strings containing the name of the suite and the names of all its suites ancestors.
- **tests**: `Array` - array containing all tests that directly belong to the suite (but not to a child suite).
- **childSuites**: `Array` - array with all direct subsuites.
- **testCounts**: `Object` - contains the total number of tests in the suite, including the tests of the child suites.
- **total**: `Number` - total number of tests
- **SuiteEnd**: `Object` - A SuiteEnd is a collection of test-ends and potentially other suite-ends, emitted after the suite has been executed, which means that all its tests and child suites have been also executed. **In addition** to the properties of `SuiteStart`, `SuiteEnd` also has the following properties:
- **status**: `String` - summarized status of the suite.
- `failed`, if at least one test in the suite or in its child suites has failed.
- `skipped`, if all tests in the suite and in its child suites are skipped (and there is at least one skipped test).
- `todo`, if all tests in the suite and in its child suites are todo (and there is at least one todo test).
- `passed`, if there is at least one passed test in the suite or in its child suites and all other tests are skipped or todo, or if there are no tests in the suite.
- **testCounts**: `Object` - contains how many tests have passed, failed etc. including the tests of child suites.
- **passed**: `Number` - number of passed tests.
- **failed**: `Number` - number of failed tests.
- **skipped**: `Number` - number of skipped tests.
- **todo**: `Number` - number of todo tests.
- **total**: `Number` - total number of tests, the sum of the above properties must equal this one.
- **runtime**: `Number` - execution time of the whole suite in milliseconds (including child suites).
The above `suite properties` apply also for the `globalSuite`.
- **TestStart**: `Object` - A test-start holds basic information on a single test/spec before its execution.
- **name**: `String` - name of the test.
- **suiteName**: `String` - name of the suite the test belongs to.
- **fullName**: `Array` - array of strings containing the name of the test and the names of all its suites ancestors.1
- **TestEnd**: `Object` - A test-end holds basic information on a single test/spec after its execution.
- **name**: `String` - name of the test.
- **suiteName**: `String` - name of the suite the test belongs to.
- **fullName**: `Array` - array of strings containing the name of the test and the names of all its suites ancestors.
- **status**: `String` - result of the test. Can be:
- `passed`, if all assertions have passed.
- `failed`, if at least one assertion has failed or if the test is todo and all assertions passed.
- `skipped`, if the test is disabled and wasn't executed.
- `todo`, if the test is todo and at least one assertion failed.*
- **runtime**: `Number` - execution time in milliseconds.
- **errors**: `Array` - array containing all errors, i.e failed Assertions. It will contain at least one error for failed statuses and it will be empty for statuses other than failed.
- **assertions**: `Array` - array of Assertions containing all assertions passed and failed, for a skipped test there will be an empty array. Frameworks that don't track passed assertions can always provide an empty array for passed tests. In that case, for failed tests this should match the errors property.
_*For more info about todo tests, please refer to the [QUnit documentation for todo tests](https://api.qunitjs.com/QUnit.todo/) and the [TAP 13 specification on the todo directive](https://testanything.org/tap-version-13-specification.html#directives)_.
Based on the discussion in [#79](https://github.com/js-reporters/js-reporters/issues/79), js-reporters establishes also a minimum set of properties for the emitted assertions, failed or passed:
- **Assertion**: `Object` - An object which contains information of a single assertion/expectation.
- **passed**: `Boolean` - `true` for a passed assertion, `failed` for a failed assertion.
- **actual**: `*` - the actual value passed to the assertion, should coincide with `expected` for passed assertions.
- **expected**: `*` - the expected value passed to the assertion, should coincide with `actual` for passed assertions.
- **message**: `String` - a description.
- **stack**: `String|undefined` - represents the stack trace for a failed assertion, for a `passed` one it is `undefined`.
- **todo**: `Boolean` - whether this assertion was part of a todo test
Additional properties (not defined here) can be added to the Assertion object. If Assertion objects are included in the Test and Suite objects defined above, it is recommended to remove the `actual` and `expected` values after `TestEnd` occurs to avoid leaking memory.
## Details
For details please check out the [docs](docs) and especially the [example](docs/example.md) which presents a testsuite and its reporting data based on the standard presented above.
For implementation examples please check [Usage of the adapters](#usage-of-the-adapters) and [Integrations](#integrations).
## Usage of the adapters
Listen to the events and receive the emitted data:
```js
// Attach one of the exiting adapters.
var runner = JsReporters.autoRegister();
// Use automatic discovery of the framework adapter.
const runner = JsReporters.autoRegister();
// Listen to the same events for any testing framework.
runner.on('testEnd', function(test) {
console.log('Test %s has errors:', test.fullname.join(' '), test.errors);
// Listen to standard events, from any testing framework.
runner.on('testEnd', (test) => {
console.log('Test %s has errors:', test.fullName.join(' '), test.errors);
});
runner.on('runEnd', function(globalSuite) {
var testCounts = globalSuite.testCounts;
runner.on('runEnd', (run) => {
const counts = run.testCounts;
console.log('Testsuite status: %s', globalSuite.status);
console.log('Testsuite status: %s', run.status);
console.log('Total %d tests: %d passed, %d failed, %d skipped',
testCounts.total,
testCounts.passed,
testCounts.failed,
testCounts.skipped);
console.log('Total duration: %d', globalSuite.runtime);
counts.total,
counts.passed,
counts.failed,
counts.skipped
);
console.log('Total duration: %d', run.runtime);
});

@@ -170,7 +81,27 @@

## API
### Runtime support
* Internet Explorer 9+
* Edge 15+ (Legacy)
* Edge 80+ (Chromium-based)
* Safari 9+
* Firefox 45+
* Chrome 58+
* Node.js 10+
### Adapter support
| Testing framework | Supported | Last checked | Unresolved
|--|--|--|--
| QUnit | 1.20+ | ✅ `qunit@2.14.1` (Apr 2021) | –
| Jasmine | 2.1+ | ✅ `jasmine@3.7.0` (Apr 2021) | –
| Mocha | 1.18+ | ✅ `mocha@8.3.2` (Apr 2021) | –
See also [past issues](test/versions/failing-versions.js).
### API
**autoRegister()**
Auto registers one of the existing adapters by checking for existing testing frameworks in the global scope and returns the runner to attach event listeners. If no framework is found, it will throw an `Error`.
Automatically detects which testing framework you use and attaches any adapters as needed, and returns a compatible runner object. If no framework is found, it will throw an `Error`.

@@ -183,33 +114,35 @@ ```js

- [browserstack-runner](https://github.com/browserstack/browserstack-runner/blob/master/lib/_patch/reporter.js)
Runners:
## Differences
* [QUnit](https://qunitjs.com/), natively since [QUnit 2.2](https://github.com/qunitjs/qunit/releases/2.2.0).
* Jasmine, via [js-reporters JasmineAdapter](lib/adapters/JasmineAdapter.js).
* Mocha, via [js-reporters MochaAdapter](lib/adapters/MochaAdapter.js).
This section is dedicated to explain the limitations of the adapters in respect to the standard.
Reporters:
The only limitation is the emitting order, which is not done in source order:
* [TAP](lib/reporters/TapReporter), implements the [Test Anything Protocol](https://testanything.org/) for command-line output.
* [browserstack-runner](https://github.com/browserstack/browserstack-runner/blob/0.9.1/lib/_patch/reporter.js), runs JavaScript unit tests remotely in multiple browsers, summarize the results by browser, and fail or pass the continuous integration build accordingly.
* _Add your own, and let us know!_
- Jasmine: the emitting order of the tests will be the one from Jasmine
- Mocha: the emitting order of the tests will be the one from Mocha
- QUnit: the emitting order is done in suite order, which means if there is a suite that contains tests and other suites, it emits the start of the suite and then emits its tests and only after it emits the other suites, even if the tests were the last in source order
## Cross-project coordination
If you want to know more about each testing framework and about their emitting order, please checkout the [frameworks](docs/frameworks.md) document.
Testing frameworks:
## Cross-Reference Issues
* [QUnit issue](https://github.com/qunitjs/qunit/issues/531) (Done!)
* [Mocha issue](https://github.com/visionmedia/mocha/issues/1326) (pending…)
* [Jasmine issue](https://github.com/pivotal/jasmine/issues/659) (pending…)
* [Intern issue](https://github.com/theintern/intern/issues/257) (pending…)
* [Vows issue](https://github.com/flatiron/vows/issues/313) (pending…)
* [Buster issue](https://github.com/busterjs/buster/issues/419) (Discontinued.)
* [Nodeunit issue](https://github.com/caolan/nodeunit/issues/276) (Discontinued.)
### Unit Testing Frameworks
Reporters and proxy layers:
- https://github.com/qunitjs/qunit/issues/531 (original discussion)
- https://github.com/visionmedia/mocha/issues/1326
- https://github.com/pivotal/jasmine/issues/659
- https://github.com/theintern/intern/issues/257
- https://github.com/busterjs/buster/issues/419
- https://github.com/caolan/nodeunit/issues/276
- https://github.com/flatiron/vows/issues/313
* [BrowserStack](https://github.com/browserstack/browserstack-runner/issues/92) (Done!)
* [Karma](https://github.com/karma-runner/karma/issues/1183) (pending…)
* [grunt-saucelabs](https://github.com/axemclion/grunt-saucelabs/issues/164) (pending…)
* [Testling](https://github.com/substack/testling/issues/93) (pending…)
### Consuming Services
## Credits
- https://github.com/browserstack/browserstack-runner/issues/92
- https://github.com/axemclion/grunt-saucelabs/issues/164
- https://github.com/karma-runner/karma/issues/1183
- https://github.com/substack/testling/issues/93
[![Testing Powered By SauceLabs](https://opensource.saucelabs.com/images/opensauce/powered-by-saucelabs-badge-gray.png?sanitize=true "Testing Powered By SauceLabs")](https://saucelabs.com)

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc