diff options
Diffstat (limited to 'node_modules/empower-core/lib')
-rw-r--r-- | node_modules/empower-core/lib/decorate.js | 66 | ||||
-rw-r--r-- | node_modules/empower-core/lib/decorator.js | 165 | ||||
-rw-r--r-- | node_modules/empower-core/lib/default-options.js | 35 | ||||
-rw-r--r-- | node_modules/empower-core/lib/define-properties.js | 16 |
4 files changed, 282 insertions, 0 deletions
diff --git a/node_modules/empower-core/lib/decorate.js b/node_modules/empower-core/lib/decorate.js new file mode 100644 index 000000000..2eb6f5f20 --- /dev/null +++ b/node_modules/empower-core/lib/decorate.js @@ -0,0 +1,66 @@ +'use strict'; + +var some = require('core-js/library/fn/array/some'); +var map = require('core-js/library/fn/array/map'); + +function decorate (callSpec, decorator) { + var numArgsToCapture = callSpec.numArgsToCapture; + + return function decoratedAssert () { + var context, message, hasMessage = false; + + // see: https://github.com/twada/empower-core/pull/8#issue-127859465 + // see: https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments + var args = new Array(arguments.length); + for(var i = 0; i < args.length; ++i) { + args[i] = arguments[i]; + } + + if (numArgsToCapture === (args.length - 1)) { + message = args.pop(); + hasMessage = true; + } + + var invocation = { + thisObj: this, + values: args, + message: message, + hasMessage: hasMessage + }; + + if (some(args, isCaptured)) { + invocation.values = map(args.slice(0, numArgsToCapture), function (arg) { + if (isNotCaptured(arg)) { + return arg; + } + if (!context) { + context = { + source: arg.source, + args: [] + }; + } + context.args.push({ + value: arg.powerAssertContext.value, + events: arg.powerAssertContext.events + }); + return arg.powerAssertContext.value; + }); + + return decorator.concreteAssert(callSpec, invocation, context); + } else { + return decorator.concreteAssert(callSpec, invocation); + } + }; +} + +function isNotCaptured (value) { + return !isCaptured(value); +} + +function isCaptured (value) { + return (typeof value === 'object') && + (value !== null) && + (typeof value.powerAssertContext !== 'undefined'); +} + +module.exports = decorate; diff --git a/node_modules/empower-core/lib/decorator.js b/node_modules/empower-core/lib/decorator.js new file mode 100644 index 000000000..678f47283 --- /dev/null +++ b/node_modules/empower-core/lib/decorator.js @@ -0,0 +1,165 @@ +'use strict'; + +var forEach = require('core-js/library/fn/array/for-each'); +var filter = require('core-js/library/fn/array/filter'); +var map = require('core-js/library/fn/array/map'); +var signature = require('call-signature'); +var decorate = require('./decorate'); +var keys = require('core-js/library/fn/object/keys'); + + +function Decorator (receiver, config) { + this.receiver = receiver; + this.config = config; + this.onError = config.onError; + this.onSuccess = config.onSuccess; + this.signatures = map(config.patterns, parse); + this.wrapOnlySignatures = map(config.wrapOnlyPatterns, parse); +} + +Decorator.prototype.enhancement = function () { + var that = this; + var container = this.container(); + var wrappedMethods = []; + + function attach(matcherSpec, enhanced) { + var matcher = matcherSpec.parsed; + var methodName = detectMethodName(matcher.callee); + if (typeof that.receiver[methodName] !== 'function' || wrappedMethods.indexOf(methodName) !== -1) { + return; + } + var callSpec = { + thisObj: that.receiver, + func: that.receiver[methodName], + numArgsToCapture: numberOfArgumentsToCapture(matcherSpec), + matcherSpec: matcherSpec, + enhanced: enhanced + }; + container[methodName] = callSpec.enhancedFunc = decorate(callSpec, that); + wrappedMethods.push(methodName); + } + + forEach(filter(this.signatures, methodCall), function (matcher) { + attach(matcher, true); + }); + + forEach(filter(this.wrapOnlySignatures, methodCall), function (matcher) { + attach(matcher, false); + }); + + return container; +}; + +Decorator.prototype.container = function () { + var basement = {}; + if (typeof this.receiver === 'function') { + var candidates = filter(this.signatures, functionCall); + var enhanced = true; + if (candidates.length === 0) { + enhanced = false; + candidates = filter(this.wrapOnlySignatures, functionCall); + } + if (candidates.length === 1) { + var callSpec = { + thisObj: null, + func: this.receiver, + numArgsToCapture: numberOfArgumentsToCapture(candidates[0]), + matcherSpec: candidates[0], + enhanced: enhanced + }; + basement = callSpec.enhancedFunc = decorate(callSpec, this); + } + } + return basement; +}; + +Decorator.prototype.concreteAssert = function (callSpec, invocation, context) { + var func = callSpec.func; + var thisObj = this.config.bindReceiver ? callSpec.thisObj : invocation.thisObj; + var enhanced = callSpec.enhanced; + var args = invocation.values; + var message = invocation.message; + var matcherSpec = callSpec.matcherSpec; + + if (context && typeof this.config.modifyMessageBeforeAssert === 'function') { + message = this.config.modifyMessageBeforeAssert({originalMessage: message, powerAssertContext: context}); + } + args = args.concat(message); + + var data = { + thisObj: invocation.thisObj, + assertionFunction: callSpec.enhancedFunc, + originalMessage: message, + defaultMessage: matcherSpec.defaultMessage, + matcherSpec: matcherSpec, + enhanced: enhanced, + args: args + }; + + if (context) { + data.powerAssertContext = context; + } + + return this._callFunc(func, thisObj, args, data); +}; + +// see: https://github.com/twada/empower-core/pull/8#issuecomment-173480982 +Decorator.prototype._callFunc = function (func, thisObj, args, data) { + var ret; + try { + ret = func.apply(thisObj, args); + } catch (e) { + data.assertionThrew = true; + data.error = e; + return this.onError.call(thisObj, data); + } + data.assertionThrew = false; + data.returnValue = ret; + return this.onSuccess.call(thisObj, data); +}; + +function numberOfArgumentsToCapture (matcherSpec) { + var matcher = matcherSpec.parsed; + var len = matcher.args.length; + var lastArg; + if (0 < len) { + lastArg = matcher.args[len - 1]; + if (lastArg.name === 'message' && lastArg.optional) { + len -= 1; + } + } + return len; +} + + +function detectMethodName (callee) { + if (callee.type === 'MemberExpression') { + return callee.member; + } + return null; +} + + +function functionCall (matcherSpec) { + return matcherSpec.parsed.callee.type === 'Identifier'; +} + + +function methodCall (matcherSpec) { + return matcherSpec.parsed.callee.type === 'MemberExpression'; +} + +function parse(matcherSpec) { + if (typeof matcherSpec === 'string') { + matcherSpec = {pattern: matcherSpec}; + } + var ret = {}; + forEach(keys(matcherSpec), function (key) { + ret[key] = matcherSpec[key]; + }); + ret.parsed = signature.parse(matcherSpec.pattern); + return ret; +} + + +module.exports = Decorator; diff --git a/node_modules/empower-core/lib/default-options.js b/node_modules/empower-core/lib/default-options.js new file mode 100644 index 000000000..77b0f5c05 --- /dev/null +++ b/node_modules/empower-core/lib/default-options.js @@ -0,0 +1,35 @@ +'use strict'; + +module.exports = function defaultOptions () { + return { + destructive: false, + bindReceiver: true, + onError: onError, + onSuccess: onSuccess, + patterns: [ + 'assert(value, [message])', + 'assert.ok(value, [message])', + 'assert.equal(actual, expected, [message])', + 'assert.notEqual(actual, expected, [message])', + 'assert.strictEqual(actual, expected, [message])', + 'assert.notStrictEqual(actual, expected, [message])', + 'assert.deepEqual(actual, expected, [message])', + 'assert.notDeepEqual(actual, expected, [message])', + 'assert.deepStrictEqual(actual, expected, [message])', + 'assert.notDeepStrictEqual(actual, expected, [message])' + ], + wrapOnlyPatterns: [] + }; +}; + +function onError (errorEvent) { + var e = errorEvent.error; + if (errorEvent.powerAssertContext && e.name === 'AssertionError') { + e.powerAssertContext = errorEvent.powerAssertContext; + } + throw e; +} + +function onSuccess(successEvent) { + return successEvent.returnValue; +} diff --git a/node_modules/empower-core/lib/define-properties.js b/node_modules/empower-core/lib/define-properties.js new file mode 100644 index 000000000..340c7f065 --- /dev/null +++ b/node_modules/empower-core/lib/define-properties.js @@ -0,0 +1,16 @@ +'use strict'; + +var defineProperty = require('core-js/library/fn/object/define-property'); +var forEach = require('core-js/library/fn/array/for-each'); +var keys = require('core-js/library/fn/object/keys'); + +module.exports = function defineProperties (obj, map) { + forEach(keys(map), function (name) { + defineProperty(obj, name, { + configurable: true, + enumerable: false, + value: map[name], + writable: true + }); + }); +}; |