summaryrefslogtreecommitdiffstats
path: root/node_modules/kareem/test
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/kareem/test')
-rw-r--r--node_modules/kareem/test/examples.test.js379
-rw-r--r--node_modules/kareem/test/misc.test.js71
-rw-r--r--node_modules/kareem/test/post.test.js198
-rw-r--r--node_modules/kareem/test/pre.test.js320
-rw-r--r--node_modules/kareem/test/wrap.test.js342
5 files changed, 1310 insertions, 0 deletions
diff --git a/node_modules/kareem/test/examples.test.js b/node_modules/kareem/test/examples.test.js
new file mode 100644
index 0000000..f120723
--- /dev/null
+++ b/node_modules/kareem/test/examples.test.js
@@ -0,0 +1,379 @@
+var assert = require('assert');
+var Kareem = require('../');
+
+/* Much like [hooks](https://npmjs.org/package/hooks), kareem lets you define
+ * pre and post hooks: pre hooks are called before a given function executes.
+ * Unlike hooks, kareem stores hooks and other internal state in a separate
+ * object, rather than relying on inheritance. Furthermore, kareem exposes
+ * an `execPre()` function that allows you to execute your pre hooks when
+ * appropriate, giving you more fine-grained control over your function hooks.
+ */
+describe('pre hooks', function() {
+ var hooks;
+
+ beforeEach(function() {
+ hooks = new Kareem();
+ });
+
+ it('runs without any hooks specified', function(done) {
+ hooks.execPre('cook', null, function() {
+ done();
+ });
+ });
+
+ /* pre hook functions take one parameter, a "done" function that you execute
+ * when your pre hook is finished.
+ */
+ it('runs basic serial pre hooks', function(done) {
+ var count = 0;
+
+ hooks.pre('cook', function(done) {
+ ++count;
+ done();
+ });
+
+ hooks.execPre('cook', null, function() {
+ assert.equal(1, count);
+ done();
+ });
+ });
+
+ it('can run multipe pre hooks', function(done) {
+ var count1 = 0;
+ var count2 = 0;
+
+ hooks.pre('cook', function(done) {
+ ++count1;
+ done();
+ });
+
+ hooks.pre('cook', function(done) {
+ ++count2;
+ done();
+ });
+
+ hooks.execPre('cook', null, function() {
+ assert.equal(1, count1);
+ assert.equal(1, count2);
+ done();
+ });
+ });
+
+ /* If your pre hook function takes no parameters, its assumed to be
+ * fully synchronous.
+ */
+ it('can run fully synchronous pre hooks', function(done) {
+ var count1 = 0;
+ var count2 = 0;
+
+ hooks.pre('cook', function() {
+ ++count1;
+ });
+
+ hooks.pre('cook', function() {
+ ++count2;
+ });
+
+ hooks.execPre('cook', null, function(error) {
+ assert.equal(null, error);
+ assert.equal(1, count1);
+ assert.equal(1, count2);
+ done();
+ });
+ });
+
+ /* Pre save hook functions are bound to the second parameter to `execPre()`
+ */
+ it('properly attaches context to pre hooks', function(done) {
+ hooks.pre('cook', function(done) {
+ this.bacon = 3;
+ done();
+ });
+
+ hooks.pre('cook', function(done) {
+ this.eggs = 4;
+ done();
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ // In the pre hooks, `this` will refer to `obj`
+ hooks.execPre('cook', obj, function(error) {
+ assert.equal(null, error);
+ assert.equal(3, obj.bacon);
+ assert.equal(4, obj.eggs);
+ done();
+ });
+ });
+
+ /* Like the hooks module, you can declare "async" pre hooks - these take two
+ * parameters, the functions `next()` and `done()`. `next()` passes control to
+ * the next pre hook, but the underlying function won't be called until all
+ * async pre hooks have called `done()`.
+ */
+ it('can execute parallel (async) pre hooks', function(done) {
+ hooks.pre('cook', true, function(next, done) {
+ this.bacon = 3;
+ next();
+ setTimeout(function() {
+ done();
+ }, 5);
+ });
+
+ hooks.pre('cook', true, function(next, done) {
+ next();
+ var _this = this;
+ setTimeout(function() {
+ _this.eggs = 4;
+ done();
+ }, 10);
+ });
+
+ hooks.pre('cook', function(next) {
+ this.waffles = false;
+ next();
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ hooks.execPre('cook', obj, function() {
+ assert.equal(3, obj.bacon);
+ assert.equal(4, obj.eggs);
+ assert.equal(false, obj.waffles);
+ done();
+ });
+ });
+
+ /* You can also return a promise from your pre hooks instead of calling
+ * `next()`. When the returned promise resolves, kareem will kick off the
+ * next middleware.
+ */
+ it('supports returning a promise', function(done) {
+ hooks.pre('cook', function() {
+ return new Promise(resolve => {
+ setTimeout(() => {
+ this.bacon = 3;
+ resolve();
+ }, 100);
+ });
+ });
+
+ var obj = { bacon: 0 };
+
+ hooks.execPre('cook', obj, function() {
+ assert.equal(3, obj.bacon);
+ done();
+ });
+ });
+});
+
+describe('post hooks', function() {
+ var hooks;
+
+ beforeEach(function() {
+ hooks = new Kareem();
+ });
+
+ it('runs without any hooks specified', function(done) {
+ hooks.execPost('cook', null, [1], function(error, eggs) {
+ assert.ifError(error);
+ assert.equal(1, eggs);
+ done();
+ });
+ });
+
+ it('executes with parameters passed in', function(done) {
+ hooks.post('cook', function(eggs, bacon, callback) {
+ assert.equal(1, eggs);
+ assert.equal(2, bacon);
+ callback();
+ });
+
+ hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) {
+ assert.ifError(error);
+ assert.equal(1, eggs);
+ assert.equal(2, bacon);
+ done();
+ });
+ });
+
+ it('can use synchronous post hooks', function(done) {
+ var execed = {};
+
+ hooks.post('cook', function(eggs, bacon) {
+ execed.first = true;
+ assert.equal(1, eggs);
+ assert.equal(2, bacon);
+ });
+
+ hooks.post('cook', function(eggs, bacon, callback) {
+ execed.second = true;
+ assert.equal(1, eggs);
+ assert.equal(2, bacon);
+ callback();
+ });
+
+ hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) {
+ assert.ifError(error);
+ assert.equal(2, Object.keys(execed).length);
+ assert.ok(execed.first);
+ assert.ok(execed.second);
+ assert.equal(1, eggs);
+ assert.equal(2, bacon);
+ done();
+ });
+ });
+});
+
+describe('wrap()', function() {
+ var hooks;
+
+ beforeEach(function() {
+ hooks = new Kareem();
+ });
+
+ it('wraps pre and post calls into one call', function(done) {
+ hooks.pre('cook', true, function(next, done) {
+ this.bacon = 3;
+ next();
+ setTimeout(function() {
+ done();
+ }, 5);
+ });
+
+ hooks.pre('cook', true, function(next, done) {
+ next();
+ var _this = this;
+ setTimeout(function() {
+ _this.eggs = 4;
+ done();
+ }, 10);
+ });
+
+ hooks.pre('cook', function(next) {
+ this.waffles = false;
+ next();
+ });
+
+ hooks.post('cook', function(obj) {
+ obj.tofu = 'no';
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ var args = [obj];
+ args.push(function(error, result) {
+ assert.ifError(error);
+ assert.equal(null, error);
+ assert.equal(3, obj.bacon);
+ assert.equal(4, obj.eggs);
+ assert.equal(false, obj.waffles);
+ assert.equal('no', obj.tofu);
+
+ assert.equal(obj, result);
+ done();
+ });
+
+ hooks.wrap(
+ 'cook',
+ function(o, callback) {
+ assert.equal(3, obj.bacon);
+ assert.equal(4, obj.eggs);
+ assert.equal(false, obj.waffles);
+ assert.equal(undefined, obj.tofu);
+ callback(null, o);
+ },
+ obj,
+ args);
+ });
+});
+
+describe('createWrapper()', function() {
+ var hooks;
+
+ beforeEach(function() {
+ hooks = new Kareem();
+ });
+
+ it('wraps wrap() into a callable function', function(done) {
+ hooks.pre('cook', true, function(next, done) {
+ this.bacon = 3;
+ next();
+ setTimeout(function() {
+ done();
+ }, 5);
+ });
+
+ hooks.pre('cook', true, function(next, done) {
+ next();
+ var _this = this;
+ setTimeout(function() {
+ _this.eggs = 4;
+ done();
+ }, 10);
+ });
+
+ hooks.pre('cook', function(next) {
+ this.waffles = false;
+ next();
+ });
+
+ hooks.post('cook', function(obj) {
+ obj.tofu = 'no';
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ var cook = hooks.createWrapper(
+ 'cook',
+ function(o, callback) {
+ assert.equal(3, obj.bacon);
+ assert.equal(4, obj.eggs);
+ assert.equal(false, obj.waffles);
+ assert.equal(undefined, obj.tofu);
+ callback(null, o);
+ },
+ obj);
+
+ cook(obj, function(error, result) {
+ assert.ifError(error);
+ assert.equal(3, obj.bacon);
+ assert.equal(4, obj.eggs);
+ assert.equal(false, obj.waffles);
+ assert.equal('no', obj.tofu);
+
+ assert.equal(obj, result);
+ done();
+ });
+ });
+});
+
+describe('clone()', function() {
+ it('clones a Kareem object', function() {
+ var k1 = new Kareem();
+ k1.pre('cook', function() {});
+ k1.post('cook', function() {});
+
+ var k2 = k1.clone();
+ assert.deepEqual(Array.from(k2._pres.keys()), ['cook']);
+ assert.deepEqual(Array.from(k2._posts.keys()), ['cook']);
+ });
+});
+
+describe('merge()', function() {
+ it('pulls hooks from another Kareem object', function() {
+ var k1 = new Kareem();
+ var test1 = function() {};
+ k1.pre('cook', test1);
+ k1.post('cook', function() {});
+
+ var k2 = new Kareem();
+ var test2 = function() {};
+ k2.pre('cook', test2);
+ var k3 = k2.merge(k1);
+ assert.equal(k3._pres.get('cook').length, 2);
+ assert.equal(k3._pres.get('cook')[0].fn, test2);
+ assert.equal(k3._pres.get('cook')[1].fn, test1);
+ assert.equal(k3._posts.get('cook').length, 1);
+ });
+});
diff --git a/node_modules/kareem/test/misc.test.js b/node_modules/kareem/test/misc.test.js
new file mode 100644
index 0000000..531b1d4
--- /dev/null
+++ b/node_modules/kareem/test/misc.test.js
@@ -0,0 +1,71 @@
+'use strict';
+
+const assert = require('assert');
+const Kareem = require('../');
+
+describe('hasHooks', function() {
+ it('returns false for toString (Automattic/mongoose#6538)', function() {
+ const k = new Kareem();
+ assert.ok(!k.hasHooks('toString'));
+ });
+});
+
+describe('merge', function() {
+ it('handles async pres if source doesnt have them', function() {
+ const k1 = new Kareem();
+ k1.pre('cook', true, function(next, done) {
+ execed.first = true;
+ setTimeout(
+ function() {
+ done('error!');
+ },
+ 5);
+
+ next();
+ });
+
+ assert.equal(k1._pres.get('cook').numAsync, 1);
+
+ const k2 = new Kareem();
+ const k3 = k2.merge(k1);
+ assert.equal(k3._pres.get('cook').numAsync, 1);
+ });
+});
+
+describe('filter', function() {
+ it('returns clone with only hooks that match `fn()`', function() {
+ const k1 = new Kareem();
+
+ k1.pre('update', { document: true }, f1);
+ k1.pre('update', { query: true }, f2);
+ k1.pre('remove', { document: true }, f3);
+
+ k1.post('update', { document: true }, f1);
+ k1.post('update', { query: true }, f2);
+ k1.post('remove', { document: true }, f3);
+
+ const k2 = k1.filter(hook => hook.document);
+ assert.equal(k2._pres.get('update').length, 1);
+ assert.equal(k2._pres.get('update')[0].fn, f1);
+ assert.equal(k2._pres.get('remove').length, 1);
+ assert.equal(k2._pres.get('remove')[0].fn, f3);
+
+ assert.equal(k2._posts.get('update').length, 1);
+ assert.equal(k2._posts.get('update')[0].fn, f1);
+ assert.equal(k2._posts.get('remove').length, 1);
+ assert.equal(k2._posts.get('remove')[0].fn, f3);
+
+ const k3 = k1.filter(hook => hook.query);
+ assert.equal(k3._pres.get('update').length, 1);
+ assert.equal(k3._pres.get('update')[0].fn, f2);
+ assert.ok(!k3._pres.has('remove'));
+
+ assert.equal(k3._posts.get('update').length, 1);
+ assert.equal(k3._posts.get('update')[0].fn, f2);
+ assert.ok(!k3._posts.has('remove'));
+
+ function f1() {}
+ function f2() {}
+ function f3() {}
+ });
+});
diff --git a/node_modules/kareem/test/post.test.js b/node_modules/kareem/test/post.test.js
new file mode 100644
index 0000000..b9a776d
--- /dev/null
+++ b/node_modules/kareem/test/post.test.js
@@ -0,0 +1,198 @@
+'use strict';
+
+const assert = require('assert');
+const Kareem = require('../');
+
+describe('execPost', function() {
+ var hooks;
+
+ beforeEach(function() {
+ hooks = new Kareem();
+ });
+
+ it('handles errors', function(done) {
+ hooks.post('cook', function(eggs, callback) {
+ callback('error!');
+ });
+
+ hooks.execPost('cook', null, [4], function(error, eggs) {
+ assert.equal('error!', error);
+ assert.ok(!eggs);
+ done();
+ });
+ });
+
+ it('unshift', function() {
+ var f1 = function() {};
+ var f2 = function() {};
+ hooks.post('cook', f1);
+ hooks.post('cook', f2, true);
+ assert.strictEqual(hooks._posts.get('cook')[0].fn, f2);
+ assert.strictEqual(hooks._posts.get('cook')[1].fn, f1);
+ });
+
+ it('arbitrary options', function() {
+ const f1 = function() {};
+ const f2 = function() {};
+ hooks.post('cook', { foo: 'bar' }, f1);
+ hooks.post('cook', { bar: 'baz' }, f2, true);
+ assert.equal(hooks._posts.get('cook')[1].foo, 'bar');
+ assert.equal(hooks._posts.get('cook')[0].bar, 'baz');
+ });
+
+ it('throws error if no function', function() {
+ assert.throws(() => hooks.post('test'), /got "undefined"/);
+ });
+
+ it('multiple posts', function(done) {
+ hooks.post('cook', function(eggs, callback) {
+ setTimeout(
+ function() {
+ callback();
+ },
+ 5);
+ });
+
+ hooks.post('cook', function(eggs, callback) {
+ setTimeout(
+ function() {
+ callback();
+ },
+ 5);
+ });
+
+ hooks.execPost('cook', null, [4], function(error, eggs) {
+ assert.ifError(error);
+ assert.equal(4, eggs);
+ done();
+ });
+ });
+
+ it('error posts', function(done) {
+ var called = {};
+ hooks.post('cook', function(eggs, callback) {
+ called.first = true;
+ callback();
+ });
+
+ hooks.post('cook', function(eggs, callback) {
+ called.second = true;
+ callback(new Error('fail'));
+ });
+
+ hooks.post('cook', function(eggs, callback) {
+ assert.ok(false);
+ });
+
+ hooks.post('cook', function(error, eggs, callback) {
+ called.fourth = true;
+ assert.equal(error.message, 'fail');
+ callback(new Error('fourth'));
+ });
+
+ hooks.post('cook', function(error, eggs, callback) {
+ called.fifth = true;
+ assert.equal(error.message, 'fourth');
+ callback(new Error('fifth'));
+ });
+
+ hooks.execPost('cook', null, [4], function(error, eggs) {
+ assert.ok(error);
+ assert.equal(error.message, 'fifth');
+ assert.deepEqual(called, {
+ first: true,
+ second: true,
+ fourth: true,
+ fifth: true
+ });
+ done();
+ });
+ });
+
+ it('error posts with initial error', function(done) {
+ var called = {};
+
+ hooks.post('cook', function(eggs, callback) {
+ assert.ok(false);
+ });
+
+ hooks.post('cook', function(error, eggs, callback) {
+ called.second = true;
+ assert.equal(error.message, 'fail');
+ callback(new Error('second'));
+ });
+
+ hooks.post('cook', function(error, eggs, callback) {
+ called.third = true;
+ assert.equal(error.message, 'second');
+ callback(new Error('third'));
+ });
+
+ hooks.post('cook', function(error, eggs, callback) {
+ called.fourth = true;
+ assert.equal(error.message, 'third');
+ callback();
+ });
+
+ var options = { error: new Error('fail') };
+ hooks.execPost('cook', null, [4], options, function(error, eggs) {
+ assert.ok(error);
+ assert.equal(error.message, 'third');
+ assert.deepEqual(called, {
+ second: true,
+ third: true,
+ fourth: true
+ });
+ done();
+ });
+ });
+
+ it('supports returning a promise', function(done) {
+ var calledPost = 0;
+
+ hooks.post('cook', function() {
+ return new Promise(resolve => {
+ setTimeout(() => {
+ ++calledPost;
+ resolve();
+ }, 100);
+ });
+ });
+
+ hooks.execPost('cook', null, [], {}, function(error) {
+ assert.ifError(error);
+ assert.equal(calledPost, 1);
+ done();
+ });
+ });
+});
+
+describe('execPostSync', function() {
+ var hooks;
+
+ beforeEach(function() {
+ hooks = new Kareem();
+ });
+
+ it('executes hooks synchronously', function() {
+ var execed = {};
+
+ hooks.post('cook', function() {
+ execed.first = true;
+ });
+
+ hooks.post('cook', function() {
+ execed.second = true;
+ });
+
+ hooks.execPostSync('cook', null);
+ assert.ok(execed.first);
+ assert.ok(execed.second);
+ });
+
+ it('works with no hooks specified', function() {
+ assert.doesNotThrow(function() {
+ hooks.execPostSync('cook', null);
+ });
+ });
+});
diff --git a/node_modules/kareem/test/pre.test.js b/node_modules/kareem/test/pre.test.js
new file mode 100644
index 0000000..d908d67
--- /dev/null
+++ b/node_modules/kareem/test/pre.test.js
@@ -0,0 +1,320 @@
+'use strict';
+
+const assert = require('assert');
+const Kareem = require('../');
+
+describe('execPre', function() {
+ var hooks;
+
+ beforeEach(function() {
+ hooks = new Kareem();
+ });
+
+ it('handles errors with multiple pres', function(done) {
+ var execed = {};
+
+ hooks.pre('cook', function(done) {
+ execed.first = true;
+ done();
+ });
+
+ hooks.pre('cook', function(done) {
+ execed.second = true;
+ done('error!');
+ });
+
+ hooks.pre('cook', function(done) {
+ execed.third = true;
+ done();
+ });
+
+ hooks.execPre('cook', null, function(err) {
+ assert.equal('error!', err);
+ assert.equal(2, Object.keys(execed).length);
+ assert.ok(execed.first);
+ assert.ok(execed.second);
+ done();
+ });
+ });
+
+ it('sync errors', function(done) {
+ var called = 0;
+
+ hooks.pre('cook', function(next) {
+ throw new Error('woops!');
+ });
+
+ hooks.pre('cook', function(next) {
+ ++called;
+ next();
+ });
+
+ hooks.execPre('cook', null, function(err) {
+ assert.equal(err.message, 'woops!');
+ assert.equal(called, 0);
+ done();
+ });
+ });
+
+ it('unshift', function() {
+ var f1 = function() {};
+ var f2 = function() {};
+ hooks.pre('cook', false, f1);
+ hooks.pre('cook', false, f2, null, true);
+ assert.strictEqual(hooks._pres.get('cook')[0].fn, f2);
+ assert.strictEqual(hooks._pres.get('cook')[1].fn, f1);
+ });
+
+ it('throws error if no function', function() {
+ assert.throws(() => hooks.pre('test'), /got "undefined"/);
+ });
+
+ it('arbitrary options', function() {
+ const f1 = function() {};
+ const f2 = function() {};
+ hooks.pre('cook', { foo: 'bar' }, f1);
+ hooks.pre('cook', { bar: 'baz' }, f2, null, true);
+ assert.equal(hooks._pres.get('cook')[1].foo, 'bar');
+ assert.equal(hooks._pres.get('cook')[0].bar, 'baz');
+ });
+
+ it('handles async errors', function(done) {
+ var execed = {};
+
+ hooks.pre('cook', true, function(next, done) {
+ execed.first = true;
+ setTimeout(
+ function() {
+ done('error!');
+ },
+ 5);
+
+ next();
+ });
+
+ hooks.pre('cook', true, function(next, done) {
+ execed.second = true;
+ setTimeout(
+ function() {
+ done('other error!');
+ },
+ 10);
+
+ next();
+ });
+
+ hooks.execPre('cook', null, function(err) {
+ assert.equal('error!', err);
+ assert.equal(2, Object.keys(execed).length);
+ assert.ok(execed.first);
+ assert.ok(execed.second);
+ done();
+ });
+ });
+
+ it('handles async errors in next()', function(done) {
+ var execed = {};
+
+ hooks.pre('cook', true, function(next, done) {
+ execed.first = true;
+ setTimeout(
+ function() {
+ done('other error!');
+ },
+ 15);
+
+ next();
+ });
+
+ hooks.pre('cook', true, function(next, done) {
+ execed.second = true;
+ setTimeout(
+ function() {
+ next('error!');
+ done('another error!');
+ },
+ 5);
+ });
+
+ hooks.execPre('cook', null, function(err) {
+ assert.equal('error!', err);
+ assert.equal(2, Object.keys(execed).length);
+ assert.ok(execed.first);
+ assert.ok(execed.second);
+ done();
+ });
+ });
+
+ it('handles async errors in next() when already done', function(done) {
+ var execed = {};
+
+ hooks.pre('cook', true, function(next, done) {
+ execed.first = true;
+ setTimeout(
+ function() {
+ done('other error!');
+ },
+ 5);
+
+ next();
+ });
+
+ hooks.pre('cook', true, function(next, done) {
+ execed.second = true;
+ setTimeout(
+ function() {
+ next('error!');
+ done('another error!');
+ },
+ 25);
+ });
+
+ hooks.execPre('cook', null, function(err) {
+ assert.equal('other error!', err);
+ assert.equal(2, Object.keys(execed).length);
+ assert.ok(execed.first);
+ assert.ok(execed.second);
+ done();
+ });
+ });
+
+ it('async pres with clone()', function(done) {
+ var execed = false;
+
+ hooks.pre('cook', true, function(next, done) {
+ execed = true;
+ setTimeout(
+ function() {
+ done();
+ },
+ 5);
+
+ next();
+ });
+
+ hooks.clone().execPre('cook', null, function(err) {
+ assert.ifError(err);
+ assert.ok(execed);
+ done();
+ });
+ });
+
+ it('returns correct error when async pre errors', function(done) {
+ var execed = {};
+
+ hooks.pre('cook', true, function(next, done) {
+ execed.first = true;
+ setTimeout(
+ function() {
+ done('other error!');
+ },
+ 5);
+
+ next();
+ });
+
+ hooks.pre('cook', function(next) {
+ execed.second = true;
+ setTimeout(
+ function() {
+ next('error!');
+ },
+ 15);
+ });
+
+ hooks.execPre('cook', null, function(err) {
+ assert.equal('other error!', err);
+ assert.equal(2, Object.keys(execed).length);
+ assert.ok(execed.first);
+ assert.ok(execed.second);
+ done();
+ });
+ });
+
+ it('lets async pres run when fully sync pres are done', function(done) {
+ var execed = {};
+
+ hooks.pre('cook', true, function(next, done) {
+ execed.first = true;
+ setTimeout(
+ function() {
+ done();
+ },
+ 5);
+
+ next();
+ });
+
+ hooks.pre('cook', function() {
+ execed.second = true;
+ });
+
+ hooks.execPre('cook', null, function(err) {
+ assert.ifError(err);
+ assert.equal(2, Object.keys(execed).length);
+ assert.ok(execed.first);
+ assert.ok(execed.second);
+ done();
+ });
+ });
+
+ it('allows passing arguments to the next pre', function(done) {
+ var execed = {};
+
+ hooks.pre('cook', function(next) {
+ execed.first = true;
+ next(null, 'test');
+ });
+
+ hooks.pre('cook', function(next, p) {
+ execed.second = true;
+ assert.equal(p, 'test');
+ next();
+ });
+
+ hooks.pre('cook', function(next, p) {
+ execed.third = true;
+ assert.ok(!p);
+ next();
+ });
+
+ hooks.execPre('cook', null, function(err) {
+ assert.ifError(err);
+ assert.equal(3, Object.keys(execed).length);
+ assert.ok(execed.first);
+ assert.ok(execed.second);
+ assert.ok(execed.third);
+ done();
+ });
+ });
+});
+
+describe('execPreSync', function() {
+ var hooks;
+
+ beforeEach(function() {
+ hooks = new Kareem();
+ });
+
+ it('executes hooks synchronously', function() {
+ var execed = {};
+
+ hooks.pre('cook', function() {
+ execed.first = true;
+ });
+
+ hooks.pre('cook', function() {
+ execed.second = true;
+ });
+
+ hooks.execPreSync('cook', null);
+ assert.ok(execed.first);
+ assert.ok(execed.second);
+ });
+
+ it('works with no hooks specified', function() {
+ assert.doesNotThrow(function() {
+ hooks.execPreSync('cook', null);
+ });
+ });
+});
diff --git a/node_modules/kareem/test/wrap.test.js b/node_modules/kareem/test/wrap.test.js
new file mode 100644
index 0000000..dd9196e
--- /dev/null
+++ b/node_modules/kareem/test/wrap.test.js
@@ -0,0 +1,342 @@
+var assert = require('assert');
+var Kareem = require('../');
+
+describe('wrap()', function() {
+ var hooks;
+
+ beforeEach(function() {
+ hooks = new Kareem();
+ });
+
+ it('handles pre errors', function(done) {
+ hooks.pre('cook', function(done) {
+ done('error!');
+ });
+
+ hooks.post('cook', function(obj) {
+ obj.tofu = 'no';
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ var args = [obj];
+ args.push(function(error, result) {
+ assert.equal('error!', error);
+ assert.ok(!result);
+ assert.equal(undefined, obj.tofu);
+ done();
+ });
+
+ hooks.wrap(
+ 'cook',
+ function(o, callback) {
+ // Should never get called
+ assert.ok(false);
+ callback(null, o);
+ },
+ obj,
+ args);
+ });
+
+ it('handles pre errors when no callback defined', function(done) {
+ hooks.pre('cook', function(done) {
+ done('error!');
+ });
+
+ hooks.post('cook', function(obj) {
+ obj.tofu = 'no';
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ var args = [obj];
+
+ hooks.wrap(
+ 'cook',
+ function(o, callback) {
+ // Should never get called
+ assert.ok(false);
+ callback(null, o);
+ },
+ obj,
+ args);
+
+ setTimeout(
+ function() {
+ done();
+ },
+ 25);
+ });
+
+ it('handles errors in wrapped function', function(done) {
+ hooks.pre('cook', function(done) {
+ done();
+ });
+
+ hooks.post('cook', function(obj) {
+ obj.tofu = 'no';
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ var args = [obj];
+ args.push(function(error, result) {
+ assert.equal('error!', error);
+ assert.ok(!result);
+ assert.equal(undefined, obj.tofu);
+ done();
+ });
+
+ hooks.wrap(
+ 'cook',
+ function(o, callback) {
+ callback('error!');
+ },
+ obj,
+ args);
+ });
+
+ it('handles errors in post', function(done) {
+ hooks.pre('cook', function(done) {
+ done();
+ });
+
+ hooks.post('cook', function(obj, callback) {
+ obj.tofu = 'no';
+ callback('error!');
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ var args = [obj];
+ args.push(function(error, result) {
+ assert.equal('error!', error);
+ assert.ok(!result);
+ assert.equal('no', obj.tofu);
+ done();
+ });
+
+ hooks.wrap(
+ 'cook',
+ function(o, callback) {
+ callback(null, o);
+ },
+ obj,
+ args);
+ });
+
+ it('defers errors to post hooks if enabled', function(done) {
+ hooks.pre('cook', function(done) {
+ done(new Error('fail'));
+ });
+
+ hooks.post('cook', function(error, res, callback) {
+ callback(new Error('another error occurred'));
+ });
+
+ var args = [];
+ args.push(function(error) {
+ assert.equal(error.message, 'another error occurred');
+ done();
+ });
+
+ hooks.wrap(
+ 'cook',
+ function(callback) {
+ assert.ok(false);
+ callback();
+ },
+ null,
+ args,
+ { useErrorHandlers: true, numCallbackParams: 1 });
+ });
+
+ it('error handlers with no callback', function(done) {
+ hooks.pre('cook', function(done) {
+ done(new Error('fail'));
+ });
+
+ hooks.post('cook', function(error, callback) {
+ assert.equal(error.message, 'fail');
+ done();
+ });
+
+ var args = [];
+
+ hooks.wrap(
+ 'cook',
+ function(callback) {
+ assert.ok(false);
+ callback();
+ },
+ null,
+ args,
+ { useErrorHandlers: true });
+ });
+
+ it('error handlers with no error', function(done) {
+ hooks.post('cook', function(error, callback) {
+ callback(new Error('another error occurred'));
+ });
+
+ var args = [];
+ args.push(function(error) {
+ assert.ifError(error);
+ done();
+ });
+
+ hooks.wrap(
+ 'cook',
+ function(callback) {
+ callback();
+ },
+ null,
+ args,
+ { useErrorHandlers: true });
+ });
+
+ it('works with no args', function(done) {
+ hooks.pre('cook', function(done) {
+ done();
+ });
+
+ hooks.post('cook', function(callback) {
+ obj.tofu = 'no';
+ callback();
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ var args = [];
+
+ hooks.wrap(
+ 'cook',
+ function(callback) {
+ callback(null);
+ },
+ obj,
+ args);
+
+ setTimeout(
+ function() {
+ assert.equal('no', obj.tofu);
+ done();
+ },
+ 25);
+ });
+
+ it('handles pre errors with no args', function(done) {
+ hooks.pre('cook', function(done) {
+ done('error!');
+ });
+
+ hooks.post('cook', function(callback) {
+ obj.tofu = 'no';
+ callback();
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ var args = [];
+
+ hooks.wrap(
+ 'cook',
+ function(callback) {
+ callback(null);
+ },
+ obj,
+ args);
+
+ setTimeout(
+ function() {
+ assert.equal(undefined, obj.tofu);
+ done();
+ },
+ 25);
+ });
+
+ it('handles wrapped function errors with no args', function(done) {
+ hooks.pre('cook', function(done) {
+ obj.waffles = false;
+ done();
+ });
+
+ hooks.post('cook', function(callback) {
+ obj.tofu = 'no';
+ callback();
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ var args = [];
+
+ hooks.wrap(
+ 'cook',
+ function(callback) {
+ callback('error!');
+ },
+ obj,
+ args);
+
+ setTimeout(
+ function() {
+ assert.equal(false, obj.waffles);
+ assert.equal(undefined, obj.tofu);
+ done();
+ },
+ 25);
+ });
+
+ it('handles post errors with no args', function(done) {
+ hooks.pre('cook', function(done) {
+ obj.waffles = false;
+ done();
+ });
+
+ hooks.post('cook', function(callback) {
+ obj.tofu = 'no';
+ callback('error!');
+ });
+
+ var obj = { bacon: 0, eggs: 0 };
+
+ var args = [];
+
+ hooks.wrap(
+ 'cook',
+ function(callback) {
+ callback();
+ },
+ obj,
+ args);
+
+ setTimeout(
+ function() {
+ assert.equal(false, obj.waffles);
+ assert.equal('no', obj.tofu);
+ done();
+ },
+ 25);
+ });
+
+ it('sync wrappers', function() {
+ var calledPre = 0;
+ var calledFn = 0;
+ var calledPost = 0;
+ hooks.pre('cook', function() {
+ ++calledPre;
+ });
+
+ hooks.post('cook', function() {
+ ++calledPost;
+ });
+
+ var wrapper = hooks.createWrapperSync('cook', function() { ++calledFn; });
+
+ wrapper();
+
+ assert.equal(calledPre, 1);
+ assert.equal(calledFn, 1);
+ assert.equal(calledPost, 1);
+ });
+});