should.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Should
  3. * Copyright(c) 2010-2014 TJ Holowaychuk <tj@vision-media.ca>
  4. * MIT Licensed
  5. */
  6. var util = require('./util');
  7. /**
  8. * Our function should
  9. *
  10. * @param {*} obj Object to assert
  11. * @returns {should.Assertion} Returns new Assertion for beginning assertion chain
  12. * @example
  13. *
  14. * var should = require('should');
  15. * should('abc').be.a.String();
  16. */
  17. var should = function should(obj) {
  18. return (new should.Assertion(obj));
  19. };
  20. should.AssertionError = require('./assertion-error');
  21. should.Assertion = require('./assertion');
  22. should.format = util.format;
  23. should.type = require('should-type');
  24. should.util = util;
  25. /**
  26. * Object with configuration.
  27. * It contains such properties:
  28. * * `checkProtoEql` boolean - Affect if `.eql` will check objects prototypes
  29. * Also it can contain options for should-format.
  30. *
  31. * @type {Object}
  32. * @memberOf should
  33. * @static
  34. * @example
  35. *
  36. * var a = { a: 10 }, b = Object.create(null);
  37. * b.a = 10;
  38. *
  39. * a.should.be.eql(b);
  40. * //not throws
  41. *
  42. * should.config.checkProtoEql = true;
  43. * a.should.be.eql(b);
  44. * //throws AssertionError: expected { a: 10 } to equal { a: 10 } (because A and B have different prototypes)
  45. */
  46. should.config = require('./config');
  47. //Expose should to external world.
  48. exports = module.exports = should;
  49. /**
  50. * Allow to extend given prototype with should property using given name. This getter will **unwrap** all standard wrappers like `Number`, `Boolean`, `String`.
  51. * Using `should(obj)` is the equivalent of using `obj.should` with known issues (like nulls and method calls etc).
  52. *
  53. * @param {string} [propertyName] Name of property to add. Default is `'should'`.
  54. * @param {Object} [proto] Prototype to extend with. Default is `Object.prototype`.
  55. * @memberOf should
  56. * @returns {{ name: string, descriptor: Object, proto: Object }} Descriptor enough to return all back
  57. * @static
  58. * @example
  59. *
  60. * var prev = should.extend('must', Object.prototype);
  61. *
  62. * 'abc'.must.startWith('a');
  63. *
  64. * var should = should.noConflict(prev);
  65. * should.not.exist(Object.prototype.must);
  66. */
  67. should.extend = function(propertyName, proto) {
  68. propertyName = propertyName || 'should';
  69. proto = proto || Object.prototype;
  70. var prevDescriptor = Object.getOwnPropertyDescriptor(proto, propertyName);
  71. Object.defineProperty(proto, propertyName, {
  72. set: function() {
  73. },
  74. get: function() {
  75. return should(util.isWrapperType(this) ? this.valueOf() : this);
  76. },
  77. configurable: true
  78. });
  79. return { name: propertyName, descriptor: prevDescriptor, proto: proto };
  80. };
  81. /**
  82. * Delete previous extension. If `desc` missing it will remove default extension.
  83. *
  84. * @param {{ name: string, descriptor: Object, proto: Object }} [desc] Returned from `should.extend` object
  85. * @memberOf should
  86. * @returns {Function} Returns should function
  87. * @static
  88. * @example
  89. *
  90. * var should = require('should').noConflict();
  91. *
  92. * should(Object.prototype).not.have.property('should');
  93. *
  94. * var prev = should.extend('must', Object.prototype);
  95. * 'abc'.must.startWith('a');
  96. * should.noConflict(prev);
  97. *
  98. * should(Object.prototype).not.have.property('must');
  99. */
  100. should.noConflict = function(desc) {
  101. desc = desc || should._prevShould;
  102. if(desc) {
  103. delete desc.proto[desc.name];
  104. if(desc.descriptor) {
  105. Object.defineProperty(desc.proto, desc.name, desc.descriptor);
  106. }
  107. }
  108. return should;
  109. };
  110. /**
  111. * Simple utility function for a bit more easier should assertion extension
  112. * @param {Function} f So called plugin function. It should accept 2 arguments: `should` function and `Assertion` constructor
  113. * @memberOf should
  114. * @returns {Function} Returns `should` function
  115. * @static
  116. * @example
  117. *
  118. * should.use(function(should, Assertion) {
  119. * Assertion.add('asset', function() {
  120. * this.params = { operator: 'to be asset' };
  121. *
  122. * this.obj.should.have.property('id').which.is.a.Number();
  123. * this.obj.should.have.property('path');
  124. * })
  125. * })
  126. */
  127. should.use = function(f) {
  128. f(should, should.Assertion);
  129. return this;
  130. };
  131. should
  132. .use(require('./ext/assert'))
  133. .use(require('./ext/chain'))
  134. .use(require('./ext/bool'))
  135. .use(require('./ext/number'))
  136. .use(require('./ext/eql'))
  137. .use(require('./ext/type'))
  138. .use(require('./ext/string'))
  139. .use(require('./ext/property'))
  140. .use(require('./ext/error'))
  141. .use(require('./ext/match'))
  142. .use(require('./ext/contain'));