UNPKG

@rxjs-stuff/marbles

Version:

A set of plugins that provide a natural feeling integration with Mocha and Chai for RxJS "marbles" testing.

129 lines 6.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.afterEach = exports.beforeEach = exports.assertDeepEqual = exports.chaiMarbles = void 0; const chai_1 = require("chai"); const rxjs_1 = require("rxjs"); const marbles_1 = require("@rxjs-stuff/marbles"); const chaiMarbles = (chai, utils) => { function getContext() { const context = utils.flag(exports.chaiMarbles, 'currentTest'); const marbles = context ? utils.flag(context, 'marblesHelpers') : undefined; return [marbles, context]; } utils.addMethod(chai.Assertion.prototype, 'subscribedWith', function (...subscriptionMarbles) { const obj = utils.flag(this, 'object'); const [marbles] = getContext(); if (rxjs_1.isObservable(obj)) { marbles.expectSubscriptions(marbles_1.wrapLogSubscriptions(marbles.scheduler, obj).subscriptions).toBe(subscriptionMarbles); } }); utils.addMethod(chai.Assertion.prototype, 'verifyError', function (callbackFn) { utils.flag(this, 'verifyError', callbackFn); }); utils.addMethod(chai.Assertion.prototype, 'marbleValues', function (values) { utils.flag(this, 'marbleValues', values); }); utils.addChainableMethod(chai.Assertion.prototype, 'subscription', function (subscriptionMarbles) { utils.flag(this, 'subscriptionMarbles', subscriptionMarbles); }); utils.addChainableMethod(chai.Assertion.prototype, 'originalContext', function (context) { utils.flag(this, 'originalContext', context); }); function observableErrorsAccessor(context) { return () => { const originalContext = utils.flag(context, 'originalContext'); const originalContextObservableErrors = originalContext ? utils.flag(originalContext, 'observableErrors') : undefined; if (originalContextObservableErrors) { return originalContextObservableErrors; } const observableErrors = utils.flag(context, 'observableErrors'); if (observableErrors) { return observableErrors; } const observableErrorsInit = []; utils.flag(context, 'observableErrors', observableErrorsInit); return observableErrorsInit; }; } utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) { return function equal(expected) { var _a; const obj = utils.flag(this, 'object'); const [marbles] = getContext(); if (marbles && rxjs_1.isObservable(obj) && typeof expected === 'string') { marbles_1.wrapLogSubscriptions(marbles.scheduler, obj); const subscription = utils.flag(this, 'subscriptionMarbles'); const marbleValues = utils.flag(this, 'marbleValues'); const getObservableErrors = observableErrorsAccessor(this); const observableErrors = getObservableErrors(); const errorHandledObservable = obj.pipe(marbles_1.collectErrors(observableErrors)); marbles.expectObservable(errorHandledObservable, subscription, this).toBe(expected, marbleValues); // gross hacky stuff to make the stack trace line up correctly const stackObj = { name: 'REPLACE_ME', }; Error.captureStackTrace(stackObj, utils.flag(this, 'ssfi')); utils.flag(this, 'marblesStackObj', stackObj); return; } const originalContext = utils.flag(this, 'originalContext'); if (originalContext) { const verifyError = (_a = utils.flag(originalContext, 'verifyError')) !== null && _a !== void 0 ? _a : utils.flag(this, 'verifyError'); try { utils.flag(this, 'message', utils.flag(originalContext, 'message')); const result = _super.call(this, expected); if (verifyError) { throw Object.assign(new Error(''), { _isMissingVerifyError: true }); } return result; } catch (err) { // even more gross hacky stuff to make the stack trace line up correctly const stackObj = utils.flag(originalContext, 'marblesStackObj'); const [, ...stackLines] = stackObj.stack.split('\n'); const [firstLine] = err.stack.split('\n'); const realStack = marbles_1.cleanStack(firstLine, ...stackLines); // show stack traces for errors collected from the test subject observable const getObservableErrors = observableErrorsAccessor(this); const observableErrors = getObservableErrors(); const observableErrorsStacks = observableErrors.reduce((result, error) => { if (result.length === 0) { result.push('\nThe observable completed with error(s):\n'); } result.push(marbles_1.cleanStack(error.stack || error.toString())); return result; }, []); const fullStack = [realStack, ...observableErrorsStacks].join('\n\n'); Object.assign(err, { stack: fullStack, }); if (verifyError && !err._isMissingVerifyError) { verifyError(err); return true; } throw err; } } return _super.call(this, expected); }; }); Object.assign(chai.Assertion.prototype, { __chai_marbles_wuz_here: true }); }; exports.chaiMarbles = chaiMarbles; const assertDeepEqual = (actual, expected, context) => { // FIXME: sometimes the diff doesn't show - is it with certain deeply nested objects? // Or specific to Uuid because it has certain stringifying implementations to fail the matcher, but don't // show a difference for inspection? chai_1.expect(actual).with.originalContext(context).to.deep.equal(expected); }; exports.assertDeepEqual = assertDeepEqual; const beforeEach = (helpers, context) => { chai_1.util.flag(exports.chaiMarbles, 'currentTest', context); chai_1.util.flag(context, 'marblesHelpers', helpers); }; exports.beforeEach = beforeEach; const afterEach = () => { chai_1.util.flag(exports.chaiMarbles, 'currentTest', undefined); }; exports.afterEach = afterEach; //# sourceMappingURL=chai-marbles.js.map