1 var assert = require('assert');
2 var Kareem = require('../');
4 /* Much like [hooks](https://npmjs.org/package/hooks), kareem lets you define
5 * pre and post hooks: pre hooks are called before a given function executes.
6 * Unlike hooks, kareem stores hooks and other internal state in a separate
7 * object, rather than relying on inheritance. Furthermore, kareem exposes
8 * an `execPre()` function that allows you to execute your pre hooks when
9 * appropriate, giving you more fine-grained control over your function hooks.
11 describe('pre hooks', function() {
14 beforeEach(function() {
18 it('runs without any hooks specified', function(done) {
19 hooks.execPre('cook', null, function() {
24 /* pre hook functions take one parameter, a "done" function that you execute
25 * when your pre hook is finished.
27 it('runs basic serial pre hooks', function(done) {
30 hooks.pre('cook', function(done) {
35 hooks.execPre('cook', null, function() {
36 assert.equal(1, count);
41 it('can run multipe pre hooks', function(done) {
45 hooks.pre('cook', function(done) {
50 hooks.pre('cook', function(done) {
55 hooks.execPre('cook', null, function() {
56 assert.equal(1, count1);
57 assert.equal(1, count2);
62 /* If your pre hook function takes no parameters, its assumed to be
65 it('can run fully synchronous pre hooks', function(done) {
69 hooks.pre('cook', function() {
73 hooks.pre('cook', function() {
77 hooks.execPre('cook', null, function(error) {
78 assert.equal(null, error);
79 assert.equal(1, count1);
80 assert.equal(1, count2);
85 /* Pre save hook functions are bound to the second parameter to `execPre()`
87 it('properly attaches context to pre hooks', function(done) {
88 hooks.pre('cook', function(done) {
93 hooks.pre('cook', function(done) {
98 var obj = { bacon: 0, eggs: 0 };
100 // In the pre hooks, `this` will refer to `obj`
101 hooks.execPre('cook', obj, function(error) {
102 assert.equal(null, error);
103 assert.equal(3, obj.bacon);
104 assert.equal(4, obj.eggs);
109 /* Like the hooks module, you can declare "async" pre hooks - these take two
110 * parameters, the functions `next()` and `done()`. `next()` passes control to
111 * the next pre hook, but the underlying function won't be called until all
112 * async pre hooks have called `done()`.
114 it('can execute parallel (async) pre hooks', function(done) {
115 hooks.pre('cook', true, function(next, done) {
118 setTimeout(function() {
123 hooks.pre('cook', true, function(next, done) {
126 setTimeout(function() {
132 hooks.pre('cook', function(next) {
133 this.waffles = false;
137 var obj = { bacon: 0, eggs: 0 };
139 hooks.execPre('cook', obj, function() {
140 assert.equal(3, obj.bacon);
141 assert.equal(4, obj.eggs);
142 assert.equal(false, obj.waffles);
148 describe('post hooks', function() {
151 beforeEach(function() {
152 hooks = new Kareem();
155 it('runs without any hooks specified', function(done) {
156 hooks.execPost('cook', null, [1], function(error, eggs) {
157 assert.ifError(error);
158 assert.equal(1, eggs);
163 it('executes with parameters passed in', function(done) {
164 hooks.post('cook', function(eggs, bacon, callback) {
165 assert.equal(1, eggs);
166 assert.equal(2, bacon);
170 hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) {
171 assert.ifError(error);
172 assert.equal(1, eggs);
173 assert.equal(2, bacon);
178 it('can use synchronous post hooks', function(done) {
181 hooks.post('cook', function(eggs, bacon) {
183 assert.equal(1, eggs);
184 assert.equal(2, bacon);
187 hooks.post('cook', function(eggs, bacon, callback) {
188 execed.second = true;
189 assert.equal(1, eggs);
190 assert.equal(2, bacon);
194 hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) {
195 assert.ifError(error);
196 assert.equal(2, Object.keys(execed).length);
197 assert.ok(execed.first);
198 assert.ok(execed.second);
199 assert.equal(1, eggs);
200 assert.equal(2, bacon);
206 describe('wrap()', function() {
209 beforeEach(function() {
210 hooks = new Kareem();
213 it('wraps pre and post calls into one call', function(done) {
214 hooks.pre('cook', true, function(next, done) {
217 setTimeout(function() {
222 hooks.pre('cook', true, function(next, done) {
225 setTimeout(function() {
231 hooks.pre('cook', function(next) {
232 this.waffles = false;
236 hooks.post('cook', function(obj) {
240 var obj = { bacon: 0, eggs: 0 };
243 args.push(function(error, result) {
244 assert.ifError(error);
245 assert.equal(null, error);
246 assert.equal(3, obj.bacon);
247 assert.equal(4, obj.eggs);
248 assert.equal(false, obj.waffles);
249 assert.equal('no', obj.tofu);
251 assert.equal(obj, result);
257 function(o, callback) {
258 assert.equal(3, obj.bacon);
259 assert.equal(4, obj.eggs);
260 assert.equal(false, obj.waffles);
261 assert.equal(undefined, obj.tofu);
269 describe('createWrapper()', function() {
272 beforeEach(function() {
273 hooks = new Kareem();
276 it('wraps wrap() into a callable function', function(done) {
277 hooks.pre('cook', true, function(next, done) {
280 setTimeout(function() {
285 hooks.pre('cook', true, function(next, done) {
288 setTimeout(function() {
294 hooks.pre('cook', function(next) {
295 this.waffles = false;
299 hooks.post('cook', function(obj) {
303 var obj = { bacon: 0, eggs: 0 };
305 var cook = hooks.createWrapper(
307 function(o, callback) {
308 assert.equal(3, obj.bacon);
309 assert.equal(4, obj.eggs);
310 assert.equal(false, obj.waffles);
311 assert.equal(undefined, obj.tofu);
316 cook(obj, function(error, result) {
317 assert.ifError(error);
318 assert.equal(3, obj.bacon);
319 assert.equal(4, obj.eggs);
320 assert.equal(false, obj.waffles);
321 assert.equal('no', obj.tofu);
323 assert.equal(obj, result);
329 describe('clone()', function() {
330 it('clones a Kareem object', function() {
331 var k1 = new Kareem();
332 k1.pre('cook', function() {});
333 k1.post('cook', function() {});
336 assert.deepEqual(['cook'], Object.keys(k2._pres));
337 assert.deepEqual(['cook'], Object.keys(k2._posts));