Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

chai-spies-next

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

chai-spies-next - npm Package Compare versions

Comparing version 0.9.0 to 0.9.1

307

chai-spies.js

@@ -32,4 +32,152 @@ !function (context, definition) {

, i = _.inspect
, STATE_KEY = typeof Symbol === 'undefined' ? '__state' : Symbol('state')
, spyAmount = 0
, DEFAULT_SANDBOX = new Sandbox()
/**
* # Sandbox constructor (function)
*
* Initialize new Sandbox instance
*
* @returns new sandbox
* @api private
*/
function Sandbox() {
this[STATE_KEY] = {};
}
/**
* # Sandbox.on (function)
*
* Wraps an object method into spy assigned to sandbox. All calls will
* pass through to the original function.
*
* var spy = chai.spy.sandbox();
* var isArray = spy.on(Array, 'isArray');
*
* const array = []
* const spy = chai.spy.sandbox();
* const [push, pop] = spy.on(array, ['push', 'pop']);
*
* spy.on(array, 'push', returns => 1)
*
* @param {Object} object
* @param {String|String[]} method name or methods names to spy on
* @param {Function} [fn] mock implementation
* @returns created spy or created spies
* @api public
*/
Sandbox.prototype.on = function (object, methodName, fn) {
if (Array.isArray(methodName)) {
return methodName.map(function (name) {
return this.on(object, name, fn);
}, this);
}
var isMethod = typeof object[methodName] === 'function'
if (methodName in object && !isMethod) {
throw new Error([
'Unable to spy property "', methodName,
'". Only methods and non-existing properties can be spied.'
].join(''))
}
if (isMethod && object[methodName].__spy) {
throw new Error('"' + methodName + '" is already a spy')
}
var method = chai.spy('object.' + methodName, fn || object[methodName]);
var trackingId = ++spyAmount
this[STATE_KEY][trackingId] = method;
method.__spy.tracked = {
object: object
, methodName: methodName
, originalMethod: object[methodName]
, isOwnMethod: object.hasOwnProperty(methodName)
};
object[methodName] = method;
return method;
};
/**
* # Sandbox.restore (function)
*
* Restores previously wrapped object's method.
* Restores all spied objects of a sandbox if called without parameters.
*
* var spy = chai.spy.sandbox();
* var object = spy.on(Array, 'isArray');
* spy.restore(Array, 'isArray'); // or spy.restore();
*
* @param {Object} [object]
* @param {String|String[]} [methods] method name or method names
* @return {Sandbox} Sandbox instance
* @api public
*/
Sandbox.prototype.restore = function (object, methods) {
var hasFilter = Boolean(object && methods);
var sandbox = this;
if (methods && !Array.isArray(methods)) {
methods = [methods]
}
Object.keys(this[STATE_KEY]).some(function (spyId) {
var spy = sandbox[STATE_KEY][spyId];
var tracked = spy.__spy.tracked;
var isObjectSpied = !object || object === tracked.object;
var isMethodSpied = !methods || methods.indexOf(tracked.methodName) !== -1;
delete sandbox[STATE_KEY][spyId];
if (!isObjectSpied && !isMethodSpied) {
return false;
}
sandbox.restoreTrackedObject(spy);
if (hasFilter) {
return true;
}
});
return this;
};
/**
* # Sandbox.restoreTrackedObject (function)
*
* Restores tracked object's method
*
* var spy = chai.spy.sandbox();
* var isArray = spy.on(Array, 'isArray');
* spy.restoreTrackedObject(isArray);
*
* @param {Spy} spy
* @api private
*/
Sandbox.prototype.restoreTrackedObject = function (spy) {
var tracked = spy.__spy.tracked;
if (!tracked) {
throw new Error('It is not possible to restore a non-tracked spy.')
}
if (tracked.isOwnMethod) {
tracked.object[tracked.methodName] = tracked.originalMethod;
} else {
delete tracked.object[tracked.methodName];
}
spy.__spy.tracked = null;
};
/**
* # chai.spy (function)

@@ -82,6 +230,7 @@ *

proxy.toString = function toString() {
var l = this.__spy.calls.length;
var state = this.__spy;
var l = state.calls.length;
var s = "{ Spy";
if (this.__spy.name)
s += " '" + this.__spy.name + "'";
if (state.name)
s += " '" + state.name + "'";
if (l > 0)

@@ -92,20 +241,30 @@ s += ", " + l + " call" + (l > 1 ? 's' : '');

};
proxy.__spy = {
calls: []
, called: false
, name: name
};
return proxy;
}
/**
* # proxy.reset (function)
* # chai.spy.sandbox (function)
*
* Resets __spy object parameters for instantiation and reuse
* @returns proxy spy object
* Creates sandbox which allow to restore spied objects with spy.on.
* All calls will pass through to the original function.
*
* var spy = chai.spy.sandbox();
* var isArray = spy.on(Array, 'isArray');
*
* @param {Object} object
* @param {String} method name to spy on
* @returns passed object
* @api public
*/
proxy.reset = function() {
this.__spy = {
calls: []
, called: false
, name: name
};
return this;
}
return proxy.reset();
}
chai.spy.sandbox = function () {
return new Sandbox()
};

@@ -115,32 +274,31 @@ /**

*
* Wraps an object method into spy. All calls will
* pass through to the original function.
* The same as Sandbox.on.
* Assignes newly created spy to DEFAULT sandbox
*
* var spy = chai.spy.on(Array, 'isArray');
* var isArray = chai.spy.on(Array, 'isArray');
*
* @param {Object} object
* @param {...String} method names to spy on
* @returns passed object
* @see Sandbox.on
* @api public
*/
chai.spy.on = function (object) {
var methodNames = Array.prototype.slice.call(arguments, 1);
methodNames.forEach(function(methodName) {
object[methodName] = chai.spy(object[methodName]);
});
return object;
chai.spy.on = function () {
return DEFAULT_SANDBOX.on.apply(DEFAULT_SANDBOX, arguments)
};
/**
* # chai.spy.object (function)
* # chai.spy.interface (function)
*
* Creates an object with spied methods.
* Creates an object interface with spied methods.
*
* var object = chai.spy.object('Array', [ 'push', 'pop' ]);
* var events = chai.spy.interface('Events', ['trigger', 'on']);
*
* @param {String} [name] object name
* @param {String[]|Object} method names or method definitions
* var array = chai.spy.interface({
* push(item) {
* this.items = this.items || [];
* return this.items.push(item);
* }
* });
*
* @param {String|Object} name object or object name
* @param {String[]} [methods] method names
* @returns object with spied methods

@@ -150,15 +308,11 @@ * @api public

chai.spy.object = function (name, methods) {
chai.spy.interface = function (name, methods) {
var defs = {};
if (name && typeof name === 'object') {
methods = name;
name = 'object';
methods = Object.keys(name);
defs = name;
name = 'mock';
}
if (methods && !Array.isArray(methods)) {
defs = methods;
methods = Object.keys(methods);
}
return methods.reduce(function (object, methodName) {

@@ -171,2 +325,23 @@ object[methodName] = chai.spy(name + '.' + methodName, defs[methodName]);

/**
* # chai.spy.restore (function)
*
* The same as Sandbox.restore.
* Restores spy assigned to DEFAULT sandbox
*
* var array = []
* chai.spy.on(array, 'push');
* expect(array.push).to.be.spy // true
*
* chai.spy.restore()
* expect(array.push).to.be.spy // false
*
* @see Sandbox.restore
* @api public
*/
chai.spy.restore = function () {
return DEFAULT_SANDBOX.restore.apply(DEFAULT_SANDBOX, arguments)
};
/**
* # chai.spy.returns (function)

@@ -289,42 +464,36 @@ *

new Assertion(this._obj).to.be.spy;
var args = [].slice.call(arguments, 0)
var expArgs = [].slice.call(arguments, 0)
, calls = this._obj.__spy.calls
, always = _.flag(this, 'spy always')
, passed;
, passed = 0;
if (always) {
passed = 0
calls.forEach(function (call) {
var found = 0;
args.forEach(function (arg) {
for (var i = 0; i < call.length; i++) {
if (_.eql(call[i], arg)) found++;
calls.forEach(function (call) {
var actArgs = call.slice()
, found = 0;
expArgs.forEach(function (expArg) {
for (var i = 0; i < actArgs.length; i++) {
if (_.eql(actArgs[i], expArg)) {
found++;
actArgs.splice(i, 1);
break;
}
});
if (found === args.length) passed++;
}
});
if (found === expArgs.length) passed++;
});
if (always) {
this.assert(
passed === calls.length
, 'expected ' + this._obj + ' to have been always called with #{exp} but got ' + passed + ' out of ' + calls.length
, 'expected ' + this._his + ' to have not always been called with #{exp}'
, args
, 'expected ' + this._obj + ' to have not always been called with #{exp}'
, expArgs
);
} else {
passed = 0;
calls.forEach(function (call) {
var found = 0;
args.forEach(function (arg) {
for (var i = 0; i < call.length; i++) {
if (_.eql(call[i], arg)) found++;
}
});
if (found === args.length) passed++;
});
this.assert(
passed > 0
, 'expected ' + this._obj + ' to have been called with #{exp}'
, 'expected ' + this._his + ' to have not been called with #{exp} but got ' + passed + ' times'
, args
, 'expected ' + this._obj + ' to have not been called with #{exp} but got ' + passed + ' times'
, expArgs
);

@@ -331,0 +500,0 @@ }

@@ -15,3 +15,3 @@ {

],
"version": "0.9.0",
"version": "0.9.1",
"license": "MIT",

@@ -18,0 +18,0 @@ "repository": {

@@ -11,4 +11,4 @@ /*!

var folio = require('folio');
const folio = require('folio');
const path = require('path');
/*!

@@ -15,0 +15,0 @@ * Folio Definition

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc