'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(); }); }); it('handles sync errors in pre if there are more hooks', function(done) { var execed = {}; hooks.pre('cook', function() { execed.first = true; throw new Error('Oops!'); }); hooks.pre('cook', function() { execed.second = true; }); hooks.execPre('cook', null, function(err) { assert.ok(err); assert.ok(execed.first); assert.equal(err.message, 'Oops!'); 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); }); }); });