]> git.cworth.org Git - obsolete/notmuch-web/blob - node_modules/express/node_modules/qs/support/should/lib/should.js
Install the "express" node module via npm
[obsolete/notmuch-web] / node_modules / express / node_modules / qs / support / should / lib / should.js
1
2 /*!
3  * Should
4  * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5  * MIT Licensed
6  */
7
8 /**
9  * Module dependencies.
10  */
11
12 var util = require('sys')
13   , assert = require('assert')
14   , AssertionError = assert.AssertionError
15   , eql = require('./eql')
16   , i = util.inspect;
17
18 /**
19  * Expose assert as should.
20  * 
21  * This allows you to do things like below
22  * without require()ing the assert module.
23  *
24  *    should.equal(foo.bar, undefined);
25  *
26  */
27
28 exports = module.exports = assert;
29
30 /**
31  * Library version.
32  */
33
34 exports.version = '0.0.4';
35
36 /**
37  * Expose api via `Object#should`.
38  *
39  * @api public
40  */
41
42 Object.defineProperty(Object.prototype, 'should', {
43   set: function(){},
44   get: function(){
45     return new Assertion(this);
46   }
47 });
48
49 /**
50  * Initialize a new `Assertion` with the given _obj_.
51  *
52  * @param {Mixed} obj
53  * @api private
54  */
55
56 var Assertion = exports.Assertion = function Assertion(obj) {
57   this.obj = obj;
58 };
59
60 /**
61  * Prototype.
62  */
63
64 Assertion.prototype = {
65
66   /**
67    * HACK: prevents double require() from failing.
68    */
69   
70   exports: exports,
71
72   /**
73    * Assert _expr_ with the given _msg_ and _negatedMsg_.
74    *
75    * @param {Boolean} expr
76    * @param {String} msg
77    * @param {String} negatedMsg
78    * @api private
79    */
80
81   assert: function(expr, msg, negatedMsg){
82     var msg = this.negate ? negatedMsg : msg
83       , ok = this.negate ? !expr : expr;
84     if (!ok) {
85       throw new AssertionError({
86           message: msg
87         , stackStartFunction: this.assert
88       });
89     }
90   },
91
92   /**
93    * Dummy getter.
94    *
95    * @api public
96    */
97   
98   get an() {
99     return this;
100   },
101   
102   /**
103    * Dummy getter.
104    *
105    * @api public
106    */
107   
108   get and() {
109     return this;
110   },
111   
112   /**
113    * Dummy getter.
114    *
115    * @api public
116    */
117   
118   get be() {
119     return this;
120   },
121
122   /**
123    * Dummy getter.
124    *
125    * @api public
126    */
127   
128   get have() {
129     return this;
130   },
131   
132   /**
133    * Dummy getter.
134    *
135    * @api public
136    */
137   
138   get with() {
139     return this;
140   },
141   
142   /**
143    * Inclusion modifier.
144    *
145    * @api public
146    */
147   
148   get include() {
149     this.includes = true;
150     return this;
151   },
152
153   /**
154    * Negation modifier.
155    *
156    * @api public
157    */
158   
159   get not() {
160     this.negate = true;
161     return this;
162   },
163   
164   /**
165    * Get object inspection string.
166    *
167    * @return {String}
168    * @api private
169    */
170   
171   get inspect() {
172     return i(this.obj);
173   },
174
175   /**
176    * Assert instanceof `Arguments`.
177    *
178    * @api public
179    */
180
181   get arguments() {
182     this.assert(
183         '[object Arguments]' == Object.prototype.toString.call(this.obj)
184       , 'expected ' + this.inspect + ' to be arguments'
185       , 'expected ' + this.inspect + ' to not be arguments');
186     return this;
187   },
188
189   /**
190    * Assert that an object is empty aka length of 0.
191    *
192    * @api public
193    */
194   
195   get empty() {
196     this.obj.should.have.property('length');
197     this.assert(
198         0 === this.obj.length
199       , 'expected ' + this.inspect + ' to be empty'
200       , 'expected ' + this.inspect + ' not to be empty');
201     return this;
202   },
203
204   /**
205    * Assert ok.
206    *
207    * @api public
208    */
209   
210   get ok() {
211     this.assert(
212         this.obj
213       , 'expected ' + this.inspect + ' to be truthy'
214       , 'expected ' + this.inspect + ' to be falsey');
215     return this;
216   },
217   
218   /**
219    * Assert true.
220    *
221    * @api public
222    */
223   
224   get true() {
225     this.assert(
226         true === this.obj
227       , 'expected ' + this.inspect + ' to be true'
228       , 'expected ' + this.inspect + ' not to be true');
229     return this;
230   },
231   
232   /**
233    * Assert false.
234    *
235    * @api public
236    */
237   
238   get false() {
239     this.assert(
240         false === this.obj
241       , 'expected ' + this.inspect + ' to be false'
242       , 'expected ' + this.inspect + ' not to be false');
243     return this;
244   },
245   
246   /**
247    * Assert equal. 
248    *
249    * @param {Mixed} val
250    * @api public
251    */
252   
253   eql: function(val){
254     this.assert(
255         eql(val, this.obj)
256       , 'expected ' + this.inspect + ' to equal ' + i(val)
257       , 'expected ' + this.inspect + ' to not equal ' + i(val));
258     return this;
259   },
260   
261   /**
262    * Assert strict equal. 
263    *
264    * @param {Mixed} val
265    * @api public
266    */
267   
268   equal: function(val){
269     this.assert(
270         val === this.obj
271       , 'expected ' + this.inspect + ' to equal ' + i(val)
272       , 'expected ' + this.inspect + ' to not equal ' + i(val));
273     return this;
274   },
275   
276   /**
277    * Assert within start to finish (inclusive). 
278    *
279    * @param {Number} start
280    * @param {Number} finish
281    * @api public
282    */
283   
284   within: function(start, finish){
285     var range = start + '..' + finish;
286     this.assert(
287         this.obj >= start && this.obj <= finish
288       , 'expected ' + this.inspect + ' to be within ' + range
289       , 'expected ' + this.inspect + ' to not be within ' + range);
290     return this;
291   },
292   
293   /**
294    * Assert typeof. 
295    *
296    * @api public
297    */
298   
299   a: function(type){
300     this.assert(
301         type == typeof this.obj
302       , 'expected ' + this.inspect + ' to be a ' + type
303       , 'expected ' + this.inspect + ' not to be a ' + type);
304     return this;
305   },
306   
307   /**
308    * Assert instanceof. 
309    *
310    * @api public
311    */
312   
313   instanceof: function(constructor){
314     var name = constructor.name;
315     this.assert(
316         this.obj instanceof constructor
317       , 'expected ' + this.inspect + ' to be an instance of ' + name
318       , 'expected ' + this.inspect + ' not to be an instance of ' + name);
319     return this;
320   },
321
322   /**
323    * Assert numeric value above _n_.
324    *
325    * @param {Number} n
326    * @api public
327    */
328   
329   above: function(n){
330     this.assert(
331         this.obj > n
332       , 'expected ' + this.inspect + ' to be above ' + n
333       , 'expected ' + this.inspect + ' to be below ' + n);
334     return this;
335   },
336   
337   /**
338    * Assert numeric value below _n_.
339    *
340    * @param {Number} n
341    * @api public
342    */
343   
344   below: function(n){
345     this.assert(
346         this.obj < n
347       , 'expected ' + this.inspect + ' to be below ' + n
348       , 'expected ' + this.inspect + ' to be above ' + n);
349     return this;
350   },
351   
352   /**
353    * Assert string value matches _regexp_.
354    *
355    * @param {RegExp} regexp
356    * @api public
357    */
358   
359   match: function(regexp){
360     this.assert(
361         regexp.exec(this.obj)
362       , 'expected ' + this.inspect + ' to match ' + regexp
363       , 'expected ' + this.inspect + ' not to match ' + regexp);
364     return this;
365   },
366   
367   /**
368    * Assert property "length" exists and has value of _n_.
369    *
370    * @param {Number} n
371    * @api public
372    */
373   
374   length: function(n){
375     this.obj.should.have.property('length');
376     var len = this.obj.length;
377     this.assert(
378         n == len
379       , 'expected ' + this.inspect + ' to have a length of ' + n + ' but got ' + len
380       , 'expected ' + this.inspect + ' to not have a length of ' + len);
381     return this;
382   },
383   
384   /**
385    * Assert substring.
386    *
387    * @param {String} str
388    * @api public
389    */
390
391   string: function(str){
392     this.obj.should.be.a('string');
393     this.assert(
394         ~this.obj.indexOf(str)
395       , 'expected ' + this.inspect + ' to include ' + i(str)
396       , 'expected ' + this.inspect + ' to not include ' + i(str));
397     return this;
398   },
399
400   /**
401    * Assert property _name_ exists, with optional _val_.
402    *
403    * @param {String} name
404    * @param {Mixed} val
405    * @api public
406    */
407   
408   property: function(name, val){
409     if (this.negate && undefined !== val) {
410       if (undefined === this.obj[name]) {
411         throw new Error(this.inspect + ' has no property ' + i(name));
412       }
413     } else {
414       this.assert(
415           undefined !== this.obj[name]
416         , 'expected ' + this.inspect + ' to have a property ' + i(name)
417         , 'expected ' + this.inspect + ' to not have a property ' + i(name));
418     }
419     
420     if (undefined !== val) {
421       this.assert(
422           val === this.obj[name]
423         , 'expected ' + this.inspect + ' to have a property ' + i(name)
424           + ' of ' + i(val) + ', but got ' + i(this.obj[name])
425         , 'expected ' + this.inspect + ' to not have a property ' + i(name) + ' of ' + i(val));
426     }
427
428     this.obj = this.obj[name];
429     return this;
430   },
431   
432   /**
433    * Assert own property _name_ exists.
434    *
435    * @param {String} name
436    * @api public
437    */
438   
439   ownProperty: function(name){
440     this.assert(
441         this.obj.hasOwnProperty(name)
442       , 'expected ' + this.inspect + ' to have own property ' + i(name)
443       , 'expected ' + this.inspect + ' to not have own property ' + i(name));
444     return this;
445   },
446
447   /**
448    * Assert that the array contains _obj_.
449    *
450    * @param {Mixed} obj
451    * @api public
452    */
453
454   contain: function(obj){
455     this.obj.should.be.an.instanceof(Array);
456     this.assert(
457         ~this.obj.indexOf(obj)
458       , 'expected ' + this.inspect + ' to contain ' + i(obj)
459       , 'expected ' + this.inspect + ' to not contain ' + i(obj));
460     return this;
461   },
462   
463   /**
464    * Assert exact keys or inclusion of keys by using
465    * the `.include` modifier.
466    *
467    * @param {Array|String ...} keys
468    * @api public
469    */
470   
471   keys: function(keys){
472     var str
473       , ok = true;
474
475     keys = keys instanceof Array
476       ? keys
477       : Array.prototype.slice.call(arguments);
478
479     if (!keys.length) throw new Error('keys required');
480
481     var actual = Object.keys(this.obj)
482       , len = keys.length;
483
484     // Inclusion
485     ok = keys.every(function(key){
486       return ~actual.indexOf(key);
487     });
488
489     // Strict
490     if (!this.negate && !this.includes) {
491       ok = ok && keys.length == actual.length;
492     }
493
494     // Key string
495     if (len > 1) {
496       keys = keys.map(function(key){
497         return i(key);
498       });
499       var last = keys.pop();
500       str = keys.join(', ') + ', and ' + last;
501     } else {
502       str = i(keys[0]);
503     }
504
505     // Form
506     str = (len > 1 ? 'keys ' : 'key ') + str;
507
508     // Have / include
509     str = (this.includes ? 'include ' : 'have ') + str;
510
511     // Assertion
512     this.assert(
513         ok
514       , 'expected ' + this.inspect + ' to ' + str
515       , 'expected ' + this.inspect + ' to not ' + str);
516
517     return this;
518   },
519
520   /**
521    * Assert that _method_ is a function.
522    *
523    * @param {String} method
524    * @api public
525    */
526
527   respondTo: function(method){
528     this.assert(
529       'function' == typeof this.obj[method]
530       , 'expected ' + this.inspect + ' to respond to ' + method + '()'
531       , 'expected ' + this.inspect + ' to not respond to ' + method + '()');
532     return this;
533   }
534 };
535
536 /**
537  * Aliases.
538  */
539
540 (function alias(name, as){
541   Assertion.prototype[as] = Assertion.prototype[name];
542   return alias;
543 })
544 ('length', 'lengthOf')
545 ('keys', 'key')
546 ('ownProperty', 'haveOwnProperty')
547 ('above', 'greaterThan')
548 ('below', 'lessThan');