ende 0.5.20 → 0.5.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. data/component.json +1 -1
  3. data/components/indefinido/indemma/master/.gitignore +17 -0
  4. data/components/indefinido/indemma/master/.ruby-gemset +1 -0
  5. data/components/indefinido/indemma/master/.ruby-version +1 -0
  6. data/components/indefinido/indemma/master/Gemfile +12 -0
  7. data/components/indefinido/indemma/master/Guardfile +39 -0
  8. data/components/indefinido/indemma/master/History.md +0 -0
  9. data/components/indefinido/indemma/master/Readme.md +445 -0
  10. data/components/indefinido/indemma/master/build/development.js +26123 -0
  11. data/components/indefinido/indemma/master/build/release.js +16741 -0
  12. data/components/indefinido/indemma/master/build/test.js +26123 -0
  13. data/components/indefinido/indemma/master/component.json +1 -1
  14. data/components/indefinido/indemma/master/components/chaijs/assertion-error/1.0.0/component.json +18 -0
  15. data/components/indefinido/indemma/master/components/chaijs/assertion-error/1.0.0/index.js +110 -0
  16. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/.gitignore +22 -0
  17. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/.mailmap +1 -0
  18. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/.npmignore +14 -0
  19. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/.travis.yml +14 -0
  20. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/CONTRIBUTING.md +173 -0
  21. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/History.md +895 -0
  22. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/Makefile +93 -0
  23. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/README.md +99 -0
  24. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/ReleaseNotes.md +482 -0
  25. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/bower.json +27 -0
  26. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/chai.js +4782 -0
  27. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/component.json +50 -0
  28. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/index.js +1 -0
  29. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/karma.conf.js +28 -0
  30. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/karma.sauce.js +41 -0
  31. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/assertion.js +130 -0
  32. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/config.js +50 -0
  33. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/core/assertions.js +1314 -0
  34. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/interface/assert.js +1056 -0
  35. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/interface/expect.js +12 -0
  36. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/interface/should.js +78 -0
  37. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/addChainableMethod.js +111 -0
  38. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/addMethod.js +43 -0
  39. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/addProperty.js +40 -0
  40. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/flag.js +32 -0
  41. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getActual.js +18 -0
  42. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getEnumerableProperties.js +25 -0
  43. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getMessage.js +49 -0
  44. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getName.js +20 -0
  45. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getPathValue.js +102 -0
  46. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getProperties.js +35 -0
  47. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/index.js +114 -0
  48. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/inspect.js +320 -0
  49. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/objDisplay.js +49 -0
  50. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/overwriteChainableMethod.js +53 -0
  51. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/overwriteMethod.js +51 -0
  52. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/overwriteProperty.js +54 -0
  53. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/test.js +26 -0
  54. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/transferFlags.js +44 -0
  55. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/type.js +45 -0
  56. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai.js +87 -0
  57. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/package.json +42 -0
  58. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/sauce.browsers.js +128 -0
  59. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/support/sauce/sauce_connect_block.sh +7 -0
  60. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/support/sauce/sauce_connect_setup.sh +53 -0
  61. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/assert.js +638 -0
  62. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/auth/.gitkeep +0 -0
  63. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/bootstrap/index.js +22 -0
  64. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/bootstrap/karma.js +22 -0
  65. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/configuration.js +133 -0
  66. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/display/errors.js +14 -0
  67. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/display/message.js +47 -0
  68. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/expect.js +814 -0
  69. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/globalShould.js +15 -0
  70. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/plugins.js +24 -0
  71. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/should.js +744 -0
  72. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/utilities.js +309 -0
  73. data/components/indefinido/indemma/master/components/chaijs/deep-eql/0.1.3/component.json +20 -0
  74. data/components/indefinido/indemma/master/components/chaijs/deep-eql/0.1.3/lib/eql.js +257 -0
  75. data/components/indefinido/indemma/master/components/chaijs/type-detect/0.1.1/component.json +18 -0
  76. data/components/indefinido/indemma/master/components/chaijs/type-detect/0.1.1/lib/type.js +142 -0
  77. data/components/indefinido/indemma/master/components/component/bind/1.0.0/component.json +14 -0
  78. data/components/indefinido/indemma/master/components/component/bind/1.0.0/index.js +23 -0
  79. data/components/indefinido/indemma/master/components/component/jquery/1.0.0/component.json +10 -0
  80. data/components/indefinido/indemma/master/components/component/jquery/1.0.0/index.js +10308 -0
  81. data/components/indefinido/indemma/master/components/component/type/1.0.0/component.json +20 -0
  82. data/components/indefinido/indemma/master/components/component/type/1.0.0/index.js +32 -0
  83. data/components/indefinido/indemma/master/components/indefinido/advisable/master/component.json +21 -0
  84. data/components/indefinido/indemma/master/components/indefinido/advisable/master/index.js +1 -0
  85. data/components/indefinido/indemma/master/components/indefinido/advisable/master/lib/advisable.js +60 -0
  86. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/component.json +39 -0
  87. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/index.js +1 -0
  88. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/adapters/rivets.js +40 -0
  89. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/legacy/notifierable.js +145 -0
  90. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/legacy/schedulerable.js +147 -0
  91. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/lookup.js +38 -0
  92. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/observable/keypath_observer.js +38 -0
  93. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/observable/observation.js +45 -0
  94. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/observable/selection.js +57 -0
  95. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/observable/self_observer.js +38 -0
  96. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/observable.js +97 -0
  97. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/platform.js +12 -0
  98. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/vendor/observe-js/observe.js +1631 -0
  99. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/vendor/shims/accessors-legacy.js +92 -0
  100. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/vendor/shims/accessors.js +248 -0
  101. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/vendor/shims/array.indexOf.js +8 -0
  102. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/vendor/shims/object.create.js +77 -0
  103. data/components/indefinido/indemma/master/components/pluma/assimilate/0.4.0/component.json +25 -0
  104. data/components/indefinido/indemma/master/components/pluma/assimilate/0.4.0/dist/assimilate.js +127 -0
  105. data/components/indefinido/indemma/master/karma.conf.js +75 -0
  106. data/components/indefinido/indemma/master/lib/record/associable.js +4 -2
  107. data/components/indefinido/indemma/master/lib/record/dirtyable.js +1 -1
  108. data/components/indefinido/indemma/master/package.json +9 -0
  109. data/components/indefinido/indemma/master/spec/record/associable_spec.js +211 -0
  110. data/components/indefinido/indemma/master/spec/record/dirtyable_spec.js +57 -0
  111. data/components/indefinido/indemma/master/spec/record/maid_spec.js +40 -0
  112. data/components/indefinido/indemma/master/spec/record/persistable_spec.js +46 -0
  113. data/components/indefinido/indemma/master/spec/record/queryable_spec.js +39 -0
  114. data/components/indefinido/indemma/master/spec/record/resource_spec.js +93 -0
  115. data/components/indefinido/indemma/master/spec/record/rest_spec.js +32 -0
  116. data/components/indefinido/indemma/master/spec/record/restfulable_spec.js +346 -0
  117. data/components/indefinido/indemma/master/spec/record/scopable_spec.js +242 -0
  118. data/components/indefinido/indemma/master/spec/record/storable_spec.js +44 -0
  119. data/components/indefinido/indemma/master/spec/record/translationable.js +28 -0
  120. data/components/indefinido/indemma/master/spec/record/validatable_spec.js +142 -0
  121. data/components/indefinido/indemma/master/spec/record/validations/associated_spec.js +43 -0
  122. data/components/indefinido/indemma/master/spec/record/validations/confirmation_spec.js +36 -0
  123. data/components/indefinido/indemma/master/spec/record/validations/cpf_spec.js +34 -0
  124. data/components/indefinido/indemma/master/spec/record/validations/presence_spec.js +28 -0
  125. data/components/indefinido/indemma/master/spec/record/validations/remote_spec.js +87 -0
  126. data/components/indefinido/indemma/master/spec/record/validations/type_spec.js +48 -0
  127. data/components/indefinido/indemma/master/spec/record_spec.js +49 -0
  128. data/components/indefinido/indemma/master/spec/spec_helper.js +15 -0
  129. data/components/indefinido/indemma/master/spec/support/value_objects/phone.js +45 -0
  130. data/components/indefinido/indemma/master/src/lib/extensions/rivets.coffee +17 -0
  131. data/components/indefinido/indemma/master/src/lib/record/associable.coffee +419 -0
  132. data/components/indefinido/indemma/master/src/lib/record/dirtyable.coffee +47 -0
  133. data/components/indefinido/indemma/master/src/lib/record/errors.coffee +20 -0
  134. data/components/indefinido/indemma/master/src/lib/record/maid.coffee +16 -0
  135. data/components/indefinido/indemma/master/src/lib/record/persistable.coffee +34 -0
  136. data/components/indefinido/indemma/master/src/lib/record/queryable.coffee +29 -0
  137. data/components/indefinido/indemma/master/src/lib/record/resource.coffee +107 -0
  138. data/components/indefinido/indemma/master/src/lib/record/rest.coffee +34 -0
  139. data/components/indefinido/indemma/master/src/lib/record/restfulable.coffee +487 -0
  140. data/components/indefinido/indemma/master/src/lib/record/scopable.coffee +279 -0
  141. data/components/indefinido/indemma/master/src/lib/record/storable.coffee +49 -0
  142. data/components/indefinido/indemma/master/src/lib/record/translationable.coffee +18 -0
  143. data/components/indefinido/indemma/master/src/lib/record/validatable.coffee +241 -0
  144. data/components/indefinido/indemma/master/src/lib/record/validations/associated.coffee +34 -0
  145. data/components/indefinido/indemma/master/src/lib/record/validations/confirmation.coffee +17 -0
  146. data/components/indefinido/indemma/master/src/lib/record/validations/cpf.coffee +57 -0
  147. data/components/indefinido/indemma/master/src/lib/record/validations/presence.coffee +16 -0
  148. data/components/indefinido/indemma/master/src/lib/record/validations/remote.coffee +61 -0
  149. data/components/indefinido/indemma/master/src/lib/record/validations/type.coffee +31 -0
  150. data/components/indefinido/indemma/master/src/lib/record/validations/validatorable.coffee +5 -0
  151. data/components/indefinido/indemma/master/src/lib/record.coffee +143 -0
  152. data/components/indefinido/indemma/master/src/spec/record/associable_spec.coffee +205 -0
  153. data/components/indefinido/indemma/master/src/spec/record/dirtyable_spec.coffee +47 -0
  154. data/components/indefinido/indemma/master/src/spec/record/maid_spec.coffee +34 -0
  155. data/components/indefinido/indemma/master/src/spec/record/persistable_spec.coffee +39 -0
  156. data/components/indefinido/indemma/master/src/spec/record/queryable_spec.coffee +33 -0
  157. data/components/indefinido/indemma/master/src/spec/record/resource_spec.coffee +69 -0
  158. data/components/indefinido/indemma/master/src/spec/record/rest_spec.coffee +22 -0
  159. data/components/indefinido/indemma/master/src/spec/record/restfulable_spec.coffee +257 -0
  160. data/components/indefinido/indemma/master/src/spec/record/scopable_spec.coffee +227 -0
  161. data/components/indefinido/indemma/master/src/spec/record/storable_spec.coffee +39 -0
  162. data/components/indefinido/indemma/master/src/spec/record/translationable.coffee +19 -0
  163. data/components/indefinido/indemma/master/src/spec/record/validatable_spec.coffee +127 -0
  164. data/components/indefinido/indemma/master/src/spec/record/validations/associated_spec.coffee +35 -0
  165. data/components/indefinido/indemma/master/src/spec/record/validations/confirmation_spec.coffee +25 -0
  166. data/components/indefinido/indemma/master/src/spec/record/validations/cpf_spec.coffee +27 -0
  167. data/components/indefinido/indemma/master/src/spec/record/validations/presence_spec.coffee +24 -0
  168. data/components/indefinido/indemma/master/src/spec/record/validations/remote_spec.coffee +74 -0
  169. data/components/indefinido/indemma/master/src/spec/record/validations/type_spec.coffee +33 -0
  170. data/components/indefinido/indemma/master/src/spec/record_spec.coffee +29 -0
  171. data/components/indefinido/indemma/master/src/spec/spec_helper.coffee +11 -0
  172. data/components/indefinido/indemma/master/src/spec/support/value_objects/phone.coffee +30 -0
  173. data/components/indefinido/indemma/master/vendor/object/mixin.js +196 -0
  174. data/components/indefinido/indemma/master/vendor/spec/sinon/assert.js +199 -0
  175. data/components/indefinido/indemma/master/vendor/spec/sinon/behavior.js +334 -0
  176. data/components/indefinido/indemma/master/vendor/spec/sinon/call.js +205 -0
  177. data/components/indefinido/indemma/master/vendor/spec/sinon/collection.js +155 -0
  178. data/components/indefinido/indemma/master/vendor/spec/sinon/match.js +245 -0
  179. data/components/indefinido/indemma/master/vendor/spec/sinon/mock.js +451 -0
  180. data/components/indefinido/indemma/master/vendor/spec/sinon/sandbox.js +144 -0
  181. data/components/indefinido/indemma/master/vendor/spec/sinon/spy.js +413 -0
  182. data/components/indefinido/indemma/master/vendor/spec/sinon/stub.js +161 -0
  183. data/components/indefinido/indemma/master/vendor/spec/sinon/test.js +77 -0
  184. data/components/indefinido/indemma/master/vendor/spec/sinon/test_case.js +99 -0
  185. data/components/indefinido/indemma/master/vendor/spec/sinon/util/event.js +94 -0
  186. data/components/indefinido/indemma/master/vendor/spec/sinon/util/fake_server.js +212 -0
  187. data/components/indefinido/indemma/master/vendor/spec/sinon/util/fake_server_with_clock.js +83 -0
  188. data/components/indefinido/indemma/master/vendor/spec/sinon/util/fake_timers.js +405 -0
  189. data/components/indefinido/indemma/master/vendor/spec/sinon/util/fake_xdomain_request.js +206 -0
  190. data/components/indefinido/indemma/master/vendor/spec/sinon/util/fake_xml_http_request.js +575 -0
  191. data/components/indefinido/indemma/master/vendor/spec/sinon/util/timers_ie.js +31 -0
  192. data/components/indefinido/indemma/master/vendor/spec/sinon/util/xdr_ie.js +14 -0
  193. data/components/indefinido/indemma/master/vendor/spec/sinon/util/xhr_ie.js +19 -0
  194. data/components/indefinido/indemma/master/vendor/spec/sinon.js +383 -0
  195. data/lib/assets/javascripts/value_objects/phone.js.coffee +3 -1
  196. data/lib/assets/javascripts/widgets/viewer/plugins/scopable.js.coffee +5 -5
  197. data/lib/ende/version.rb +1 -1
  198. data/vendor/assets/components/ende_build.css +4 -4
  199. data/vendor/assets/components/ende_build.js +7974 -7889
  200. metadata +191 -5
  201. data/vendor/assets/component/build.css +0 -112
  202. data/vendor/assets/components/build.css +0 -112
  203. data/vendor/assets/components/indemma_with_none.js +0 -30553
@@ -0,0 +1,1314 @@
1
+ /*!
2
+ * chai
3
+ * http://chaijs.com
4
+ * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
5
+ * MIT Licensed
6
+ */
7
+
8
+ module.exports = function (chai, _) {
9
+ var Assertion = chai.Assertion
10
+ , toString = Object.prototype.toString
11
+ , flag = _.flag;
12
+
13
+ /**
14
+ * ### Language Chains
15
+ *
16
+ * The following are provided as chainable getters to
17
+ * improve the readability of your assertions. They
18
+ * do not provide testing capabilities unless they
19
+ * have been overwritten by a plugin.
20
+ *
21
+ * **Chains**
22
+ *
23
+ * - to
24
+ * - be
25
+ * - been
26
+ * - is
27
+ * - that
28
+ * - and
29
+ * - has
30
+ * - have
31
+ * - with
32
+ * - at
33
+ * - of
34
+ * - same
35
+ *
36
+ * @name language chains
37
+ * @api public
38
+ */
39
+
40
+ [ 'to', 'be', 'been'
41
+ , 'is', 'and', 'has', 'have'
42
+ , 'with', 'that', 'at'
43
+ , 'of', 'same' ].forEach(function (chain) {
44
+ Assertion.addProperty(chain, function () {
45
+ return this;
46
+ });
47
+ });
48
+
49
+ /**
50
+ * ### .not
51
+ *
52
+ * Negates any of assertions following in the chain.
53
+ *
54
+ * expect(foo).to.not.equal('bar');
55
+ * expect(goodFn).to.not.throw(Error);
56
+ * expect({ foo: 'baz' }).to.have.property('foo')
57
+ * .and.not.equal('bar');
58
+ *
59
+ * @name not
60
+ * @api public
61
+ */
62
+
63
+ Assertion.addProperty('not', function () {
64
+ flag(this, 'negate', true);
65
+ });
66
+
67
+ /**
68
+ * ### .deep
69
+ *
70
+ * Sets the `deep` flag, later used by the `equal` and
71
+ * `property` assertions.
72
+ *
73
+ * expect(foo).to.deep.equal({ bar: 'baz' });
74
+ * expect({ foo: { bar: { baz: 'quux' } } })
75
+ * .to.have.deep.property('foo.bar.baz', 'quux');
76
+ *
77
+ * @name deep
78
+ * @api public
79
+ */
80
+
81
+ Assertion.addProperty('deep', function () {
82
+ flag(this, 'deep', true);
83
+ });
84
+
85
+ /**
86
+ * ### .a(type)
87
+ *
88
+ * The `a` and `an` assertions are aliases that can be
89
+ * used either as language chains or to assert a value's
90
+ * type.
91
+ *
92
+ * // typeof
93
+ * expect('test').to.be.a('string');
94
+ * expect({ foo: 'bar' }).to.be.an('object');
95
+ * expect(null).to.be.a('null');
96
+ * expect(undefined).to.be.an('undefined');
97
+ *
98
+ * // language chain
99
+ * expect(foo).to.be.an.instanceof(Foo);
100
+ *
101
+ * @name a
102
+ * @alias an
103
+ * @param {String} type
104
+ * @param {String} message _optional_
105
+ * @api public
106
+ */
107
+
108
+ function an (type, msg) {
109
+ if (msg) flag(this, 'message', msg);
110
+ type = type.toLowerCase();
111
+ var obj = flag(this, 'object')
112
+ , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
113
+
114
+ this.assert(
115
+ type === _.type(obj)
116
+ , 'expected #{this} to be ' + article + type
117
+ , 'expected #{this} not to be ' + article + type
118
+ );
119
+ }
120
+
121
+ Assertion.addChainableMethod('an', an);
122
+ Assertion.addChainableMethod('a', an);
123
+
124
+ /**
125
+ * ### .include(value)
126
+ *
127
+ * The `include` and `contain` assertions can be used as either property
128
+ * based language chains or as methods to assert the inclusion of an object
129
+ * in an array or a substring in a string. When used as language chains,
130
+ * they toggle the `contain` flag for the `keys` assertion.
131
+ *
132
+ * expect([1,2,3]).to.include(2);
133
+ * expect('foobar').to.contain('foo');
134
+ * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
135
+ *
136
+ * @name include
137
+ * @alias contain
138
+ * @param {Object|String|Number} obj
139
+ * @param {String} message _optional_
140
+ * @api public
141
+ */
142
+
143
+ function includeChainingBehavior () {
144
+ flag(this, 'contains', true);
145
+ }
146
+
147
+ function include (val, msg) {
148
+ if (msg) flag(this, 'message', msg);
149
+ var obj = flag(this, 'object');
150
+ var expected = false;
151
+ if (_.type(obj) === 'array' && _.type(val) === 'object') {
152
+ for (var i in obj) {
153
+ if (_.eql(obj[i], val)) {
154
+ expected = true;
155
+ break;
156
+ }
157
+ }
158
+ } else if (_.type(val) === 'object') {
159
+ if (!flag(this, 'negate')) {
160
+ for (var k in val) new Assertion(obj).property(k, val[k]);
161
+ return;
162
+ }
163
+ var subset = {}
164
+ for (var k in val) subset[k] = obj[k]
165
+ expected = _.eql(subset, val);
166
+ } else {
167
+ expected = obj && ~obj.indexOf(val)
168
+ }
169
+ this.assert(
170
+ expected
171
+ , 'expected #{this} to include ' + _.inspect(val)
172
+ , 'expected #{this} to not include ' + _.inspect(val));
173
+ }
174
+
175
+ Assertion.addChainableMethod('include', include, includeChainingBehavior);
176
+ Assertion.addChainableMethod('contain', include, includeChainingBehavior);
177
+
178
+ /**
179
+ * ### .ok
180
+ *
181
+ * Asserts that the target is truthy.
182
+ *
183
+ * expect('everthing').to.be.ok;
184
+ * expect(1).to.be.ok;
185
+ * expect(false).to.not.be.ok;
186
+ * expect(undefined).to.not.be.ok;
187
+ * expect(null).to.not.be.ok;
188
+ *
189
+ * @name ok
190
+ * @api public
191
+ */
192
+
193
+ Assertion.addProperty('ok', function () {
194
+ this.assert(
195
+ flag(this, 'object')
196
+ , 'expected #{this} to be truthy'
197
+ , 'expected #{this} to be falsy');
198
+ });
199
+
200
+ /**
201
+ * ### .true
202
+ *
203
+ * Asserts that the target is `true`.
204
+ *
205
+ * expect(true).to.be.true;
206
+ * expect(1).to.not.be.true;
207
+ *
208
+ * @name true
209
+ * @api public
210
+ */
211
+
212
+ Assertion.addProperty('true', function () {
213
+ this.assert(
214
+ true === flag(this, 'object')
215
+ , 'expected #{this} to be true'
216
+ , 'expected #{this} to be false'
217
+ , this.negate ? false : true
218
+ );
219
+ });
220
+
221
+ /**
222
+ * ### .false
223
+ *
224
+ * Asserts that the target is `false`.
225
+ *
226
+ * expect(false).to.be.false;
227
+ * expect(0).to.not.be.false;
228
+ *
229
+ * @name false
230
+ * @api public
231
+ */
232
+
233
+ Assertion.addProperty('false', function () {
234
+ this.assert(
235
+ false === flag(this, 'object')
236
+ , 'expected #{this} to be false'
237
+ , 'expected #{this} to be true'
238
+ , this.negate ? true : false
239
+ );
240
+ });
241
+
242
+ /**
243
+ * ### .null
244
+ *
245
+ * Asserts that the target is `null`.
246
+ *
247
+ * expect(null).to.be.null;
248
+ * expect(undefined).not.to.be.null;
249
+ *
250
+ * @name null
251
+ * @api public
252
+ */
253
+
254
+ Assertion.addProperty('null', function () {
255
+ this.assert(
256
+ null === flag(this, 'object')
257
+ , 'expected #{this} to be null'
258
+ , 'expected #{this} not to be null'
259
+ );
260
+ });
261
+
262
+ /**
263
+ * ### .undefined
264
+ *
265
+ * Asserts that the target is `undefined`.
266
+ *
267
+ * expect(undefined).to.be.undefined;
268
+ * expect(null).to.not.be.undefined;
269
+ *
270
+ * @name undefined
271
+ * @api public
272
+ */
273
+
274
+ Assertion.addProperty('undefined', function () {
275
+ this.assert(
276
+ undefined === flag(this, 'object')
277
+ , 'expected #{this} to be undefined'
278
+ , 'expected #{this} not to be undefined'
279
+ );
280
+ });
281
+
282
+ /**
283
+ * ### .exist
284
+ *
285
+ * Asserts that the target is neither `null` nor `undefined`.
286
+ *
287
+ * var foo = 'hi'
288
+ * , bar = null
289
+ * , baz;
290
+ *
291
+ * expect(foo).to.exist;
292
+ * expect(bar).to.not.exist;
293
+ * expect(baz).to.not.exist;
294
+ *
295
+ * @name exist
296
+ * @api public
297
+ */
298
+
299
+ Assertion.addProperty('exist', function () {
300
+ this.assert(
301
+ null != flag(this, 'object')
302
+ , 'expected #{this} to exist'
303
+ , 'expected #{this} to not exist'
304
+ );
305
+ });
306
+
307
+
308
+ /**
309
+ * ### .empty
310
+ *
311
+ * Asserts that the target's length is `0`. For arrays, it checks
312
+ * the `length` property. For objects, it gets the count of
313
+ * enumerable keys.
314
+ *
315
+ * expect([]).to.be.empty;
316
+ * expect('').to.be.empty;
317
+ * expect({}).to.be.empty;
318
+ *
319
+ * @name empty
320
+ * @api public
321
+ */
322
+
323
+ Assertion.addProperty('empty', function () {
324
+ var obj = flag(this, 'object')
325
+ , expected = obj;
326
+
327
+ if (Array.isArray(obj) || 'string' === typeof object) {
328
+ expected = obj.length;
329
+ } else if (typeof obj === 'object') {
330
+ expected = Object.keys(obj).length;
331
+ }
332
+
333
+ this.assert(
334
+ !expected
335
+ , 'expected #{this} to be empty'
336
+ , 'expected #{this} not to be empty'
337
+ );
338
+ });
339
+
340
+ /**
341
+ * ### .arguments
342
+ *
343
+ * Asserts that the target is an arguments object.
344
+ *
345
+ * function test () {
346
+ * expect(arguments).to.be.arguments;
347
+ * }
348
+ *
349
+ * @name arguments
350
+ * @alias Arguments
351
+ * @api public
352
+ */
353
+
354
+ function checkArguments () {
355
+ var obj = flag(this, 'object')
356
+ , type = Object.prototype.toString.call(obj);
357
+ this.assert(
358
+ '[object Arguments]' === type
359
+ , 'expected #{this} to be arguments but got ' + type
360
+ , 'expected #{this} to not be arguments'
361
+ );
362
+ }
363
+
364
+ Assertion.addProperty('arguments', checkArguments);
365
+ Assertion.addProperty('Arguments', checkArguments);
366
+
367
+ /**
368
+ * ### .equal(value)
369
+ *
370
+ * Asserts that the target is strictly equal (`===`) to `value`.
371
+ * Alternately, if the `deep` flag is set, asserts that
372
+ * the target is deeply equal to `value`.
373
+ *
374
+ * expect('hello').to.equal('hello');
375
+ * expect(42).to.equal(42);
376
+ * expect(1).to.not.equal(true);
377
+ * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
378
+ * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
379
+ *
380
+ * @name equal
381
+ * @alias equals
382
+ * @alias eq
383
+ * @alias deep.equal
384
+ * @param {Mixed} value
385
+ * @param {String} message _optional_
386
+ * @api public
387
+ */
388
+
389
+ function assertEqual (val, msg) {
390
+ if (msg) flag(this, 'message', msg);
391
+ var obj = flag(this, 'object');
392
+ if (flag(this, 'deep')) {
393
+ return this.eql(val);
394
+ } else {
395
+ this.assert(
396
+ val === obj
397
+ , 'expected #{this} to equal #{exp}'
398
+ , 'expected #{this} to not equal #{exp}'
399
+ , val
400
+ , this._obj
401
+ , true
402
+ );
403
+ }
404
+ }
405
+
406
+ Assertion.addMethod('equal', assertEqual);
407
+ Assertion.addMethod('equals', assertEqual);
408
+ Assertion.addMethod('eq', assertEqual);
409
+
410
+ /**
411
+ * ### .eql(value)
412
+ *
413
+ * Asserts that the target is deeply equal to `value`.
414
+ *
415
+ * expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
416
+ * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
417
+ *
418
+ * @name eql
419
+ * @alias eqls
420
+ * @param {Mixed} value
421
+ * @param {String} message _optional_
422
+ * @api public
423
+ */
424
+
425
+ function assertEql(obj, msg) {
426
+ if (msg) flag(this, 'message', msg);
427
+ this.assert(
428
+ _.eql(obj, flag(this, 'object'))
429
+ , 'expected #{this} to deeply equal #{exp}'
430
+ , 'expected #{this} to not deeply equal #{exp}'
431
+ , obj
432
+ , this._obj
433
+ , true
434
+ );
435
+ }
436
+
437
+ Assertion.addMethod('eql', assertEql);
438
+ Assertion.addMethod('eqls', assertEql);
439
+
440
+ /**
441
+ * ### .above(value)
442
+ *
443
+ * Asserts that the target is greater than `value`.
444
+ *
445
+ * expect(10).to.be.above(5);
446
+ *
447
+ * Can also be used in conjunction with `length` to
448
+ * assert a minimum length. The benefit being a
449
+ * more informative error message than if the length
450
+ * was supplied directly.
451
+ *
452
+ * expect('foo').to.have.length.above(2);
453
+ * expect([ 1, 2, 3 ]).to.have.length.above(2);
454
+ *
455
+ * @name above
456
+ * @alias gt
457
+ * @alias greaterThan
458
+ * @param {Number} value
459
+ * @param {String} message _optional_
460
+ * @api public
461
+ */
462
+
463
+ function assertAbove (n, msg) {
464
+ if (msg) flag(this, 'message', msg);
465
+ var obj = flag(this, 'object');
466
+ if (flag(this, 'doLength')) {
467
+ new Assertion(obj, msg).to.have.property('length');
468
+ var len = obj.length;
469
+ this.assert(
470
+ len > n
471
+ , 'expected #{this} to have a length above #{exp} but got #{act}'
472
+ , 'expected #{this} to not have a length above #{exp}'
473
+ , n
474
+ , len
475
+ );
476
+ } else {
477
+ this.assert(
478
+ obj > n
479
+ , 'expected #{this} to be above ' + n
480
+ , 'expected #{this} to be at most ' + n
481
+ );
482
+ }
483
+ }
484
+
485
+ Assertion.addMethod('above', assertAbove);
486
+ Assertion.addMethod('gt', assertAbove);
487
+ Assertion.addMethod('greaterThan', assertAbove);
488
+
489
+ /**
490
+ * ### .least(value)
491
+ *
492
+ * Asserts that the target is greater than or equal to `value`.
493
+ *
494
+ * expect(10).to.be.at.least(10);
495
+ *
496
+ * Can also be used in conjunction with `length` to
497
+ * assert a minimum length. The benefit being a
498
+ * more informative error message than if the length
499
+ * was supplied directly.
500
+ *
501
+ * expect('foo').to.have.length.of.at.least(2);
502
+ * expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
503
+ *
504
+ * @name least
505
+ * @alias gte
506
+ * @param {Number} value
507
+ * @param {String} message _optional_
508
+ * @api public
509
+ */
510
+
511
+ function assertLeast (n, msg) {
512
+ if (msg) flag(this, 'message', msg);
513
+ var obj = flag(this, 'object');
514
+ if (flag(this, 'doLength')) {
515
+ new Assertion(obj, msg).to.have.property('length');
516
+ var len = obj.length;
517
+ this.assert(
518
+ len >= n
519
+ , 'expected #{this} to have a length at least #{exp} but got #{act}'
520
+ , 'expected #{this} to have a length below #{exp}'
521
+ , n
522
+ , len
523
+ );
524
+ } else {
525
+ this.assert(
526
+ obj >= n
527
+ , 'expected #{this} to be at least ' + n
528
+ , 'expected #{this} to be below ' + n
529
+ );
530
+ }
531
+ }
532
+
533
+ Assertion.addMethod('least', assertLeast);
534
+ Assertion.addMethod('gte', assertLeast);
535
+
536
+ /**
537
+ * ### .below(value)
538
+ *
539
+ * Asserts that the target is less than `value`.
540
+ *
541
+ * expect(5).to.be.below(10);
542
+ *
543
+ * Can also be used in conjunction with `length` to
544
+ * assert a maximum length. The benefit being a
545
+ * more informative error message than if the length
546
+ * was supplied directly.
547
+ *
548
+ * expect('foo').to.have.length.below(4);
549
+ * expect([ 1, 2, 3 ]).to.have.length.below(4);
550
+ *
551
+ * @name below
552
+ * @alias lt
553
+ * @alias lessThan
554
+ * @param {Number} value
555
+ * @param {String} message _optional_
556
+ * @api public
557
+ */
558
+
559
+ function assertBelow (n, msg) {
560
+ if (msg) flag(this, 'message', msg);
561
+ var obj = flag(this, 'object');
562
+ if (flag(this, 'doLength')) {
563
+ new Assertion(obj, msg).to.have.property('length');
564
+ var len = obj.length;
565
+ this.assert(
566
+ len < n
567
+ , 'expected #{this} to have a length below #{exp} but got #{act}'
568
+ , 'expected #{this} to not have a length below #{exp}'
569
+ , n
570
+ , len
571
+ );
572
+ } else {
573
+ this.assert(
574
+ obj < n
575
+ , 'expected #{this} to be below ' + n
576
+ , 'expected #{this} to be at least ' + n
577
+ );
578
+ }
579
+ }
580
+
581
+ Assertion.addMethod('below', assertBelow);
582
+ Assertion.addMethod('lt', assertBelow);
583
+ Assertion.addMethod('lessThan', assertBelow);
584
+
585
+ /**
586
+ * ### .most(value)
587
+ *
588
+ * Asserts that the target is less than or equal to `value`.
589
+ *
590
+ * expect(5).to.be.at.most(5);
591
+ *
592
+ * Can also be used in conjunction with `length` to
593
+ * assert a maximum length. The benefit being a
594
+ * more informative error message than if the length
595
+ * was supplied directly.
596
+ *
597
+ * expect('foo').to.have.length.of.at.most(4);
598
+ * expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
599
+ *
600
+ * @name most
601
+ * @alias lte
602
+ * @param {Number} value
603
+ * @param {String} message _optional_
604
+ * @api public
605
+ */
606
+
607
+ function assertMost (n, msg) {
608
+ if (msg) flag(this, 'message', msg);
609
+ var obj = flag(this, 'object');
610
+ if (flag(this, 'doLength')) {
611
+ new Assertion(obj, msg).to.have.property('length');
612
+ var len = obj.length;
613
+ this.assert(
614
+ len <= n
615
+ , 'expected #{this} to have a length at most #{exp} but got #{act}'
616
+ , 'expected #{this} to have a length above #{exp}'
617
+ , n
618
+ , len
619
+ );
620
+ } else {
621
+ this.assert(
622
+ obj <= n
623
+ , 'expected #{this} to be at most ' + n
624
+ , 'expected #{this} to be above ' + n
625
+ );
626
+ }
627
+ }
628
+
629
+ Assertion.addMethod('most', assertMost);
630
+ Assertion.addMethod('lte', assertMost);
631
+
632
+ /**
633
+ * ### .within(start, finish)
634
+ *
635
+ * Asserts that the target is within a range.
636
+ *
637
+ * expect(7).to.be.within(5,10);
638
+ *
639
+ * Can also be used in conjunction with `length` to
640
+ * assert a length range. The benefit being a
641
+ * more informative error message than if the length
642
+ * was supplied directly.
643
+ *
644
+ * expect('foo').to.have.length.within(2,4);
645
+ * expect([ 1, 2, 3 ]).to.have.length.within(2,4);
646
+ *
647
+ * @name within
648
+ * @param {Number} start lowerbound inclusive
649
+ * @param {Number} finish upperbound inclusive
650
+ * @param {String} message _optional_
651
+ * @api public
652
+ */
653
+
654
+ Assertion.addMethod('within', function (start, finish, msg) {
655
+ if (msg) flag(this, 'message', msg);
656
+ var obj = flag(this, 'object')
657
+ , range = start + '..' + finish;
658
+ if (flag(this, 'doLength')) {
659
+ new Assertion(obj, msg).to.have.property('length');
660
+ var len = obj.length;
661
+ this.assert(
662
+ len >= start && len <= finish
663
+ , 'expected #{this} to have a length within ' + range
664
+ , 'expected #{this} to not have a length within ' + range
665
+ );
666
+ } else {
667
+ this.assert(
668
+ obj >= start && obj <= finish
669
+ , 'expected #{this} to be within ' + range
670
+ , 'expected #{this} to not be within ' + range
671
+ );
672
+ }
673
+ });
674
+
675
+ /**
676
+ * ### .instanceof(constructor)
677
+ *
678
+ * Asserts that the target is an instance of `constructor`.
679
+ *
680
+ * var Tea = function (name) { this.name = name; }
681
+ * , Chai = new Tea('chai');
682
+ *
683
+ * expect(Chai).to.be.an.instanceof(Tea);
684
+ * expect([ 1, 2, 3 ]).to.be.instanceof(Array);
685
+ *
686
+ * @name instanceof
687
+ * @param {Constructor} constructor
688
+ * @param {String} message _optional_
689
+ * @alias instanceOf
690
+ * @api public
691
+ */
692
+
693
+ function assertInstanceOf (constructor, msg) {
694
+ if (msg) flag(this, 'message', msg);
695
+ var name = _.getName(constructor);
696
+ this.assert(
697
+ flag(this, 'object') instanceof constructor
698
+ , 'expected #{this} to be an instance of ' + name
699
+ , 'expected #{this} to not be an instance of ' + name
700
+ );
701
+ };
702
+
703
+ Assertion.addMethod('instanceof', assertInstanceOf);
704
+ Assertion.addMethod('instanceOf', assertInstanceOf);
705
+
706
+ /**
707
+ * ### .property(name, [value])
708
+ *
709
+ * Asserts that the target has a property `name`, optionally asserting that
710
+ * the value of that property is strictly equal to `value`.
711
+ * If the `deep` flag is set, you can use dot- and bracket-notation for deep
712
+ * references into objects and arrays.
713
+ *
714
+ * // simple referencing
715
+ * var obj = { foo: 'bar' };
716
+ * expect(obj).to.have.property('foo');
717
+ * expect(obj).to.have.property('foo', 'bar');
718
+ *
719
+ * // deep referencing
720
+ * var deepObj = {
721
+ * green: { tea: 'matcha' }
722
+ * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
723
+ * };
724
+
725
+ * expect(deepObj).to.have.deep.property('green.tea', 'matcha');
726
+ * expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
727
+ * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
728
+ *
729
+ * You can also use an array as the starting point of a `deep.property`
730
+ * assertion, or traverse nested arrays.
731
+ *
732
+ * var arr = [
733
+ * [ 'chai', 'matcha', 'konacha' ]
734
+ * , [ { tea: 'chai' }
735
+ * , { tea: 'matcha' }
736
+ * , { tea: 'konacha' } ]
737
+ * ];
738
+ *
739
+ * expect(arr).to.have.deep.property('[0][1]', 'matcha');
740
+ * expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
741
+ *
742
+ * Furthermore, `property` changes the subject of the assertion
743
+ * to be the value of that property from the original object. This
744
+ * permits for further chainable assertions on that property.
745
+ *
746
+ * expect(obj).to.have.property('foo')
747
+ * .that.is.a('string');
748
+ * expect(deepObj).to.have.property('green')
749
+ * .that.is.an('object')
750
+ * .that.deep.equals({ tea: 'matcha' });
751
+ * expect(deepObj).to.have.property('teas')
752
+ * .that.is.an('array')
753
+ * .with.deep.property('[2]')
754
+ * .that.deep.equals({ tea: 'konacha' });
755
+ *
756
+ * @name property
757
+ * @alias deep.property
758
+ * @param {String} name
759
+ * @param {Mixed} value (optional)
760
+ * @param {String} message _optional_
761
+ * @returns value of property for chaining
762
+ * @api public
763
+ */
764
+
765
+ Assertion.addMethod('property', function (name, val, msg) {
766
+ if (msg) flag(this, 'message', msg);
767
+
768
+ var descriptor = flag(this, 'deep') ? 'deep property ' : 'property '
769
+ , negate = flag(this, 'negate')
770
+ , obj = flag(this, 'object')
771
+ , value = flag(this, 'deep')
772
+ ? _.getPathValue(name, obj)
773
+ : obj[name];
774
+
775
+ if (negate && undefined !== val) {
776
+ if (undefined === value) {
777
+ msg = (msg != null) ? msg + ': ' : '';
778
+ throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
779
+ }
780
+ } else {
781
+ this.assert(
782
+ undefined !== value
783
+ , 'expected #{this} to have a ' + descriptor + _.inspect(name)
784
+ , 'expected #{this} to not have ' + descriptor + _.inspect(name));
785
+ }
786
+
787
+ if (undefined !== val) {
788
+ this.assert(
789
+ val === value
790
+ , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
791
+ , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
792
+ , val
793
+ , value
794
+ );
795
+ }
796
+
797
+ flag(this, 'object', value);
798
+ });
799
+
800
+
801
+ /**
802
+ * ### .ownProperty(name)
803
+ *
804
+ * Asserts that the target has an own property `name`.
805
+ *
806
+ * expect('test').to.have.ownProperty('length');
807
+ *
808
+ * @name ownProperty
809
+ * @alias haveOwnProperty
810
+ * @param {String} name
811
+ * @param {String} message _optional_
812
+ * @api public
813
+ */
814
+
815
+ function assertOwnProperty (name, msg) {
816
+ if (msg) flag(this, 'message', msg);
817
+ var obj = flag(this, 'object');
818
+ this.assert(
819
+ obj.hasOwnProperty(name)
820
+ , 'expected #{this} to have own property ' + _.inspect(name)
821
+ , 'expected #{this} to not have own property ' + _.inspect(name)
822
+ );
823
+ }
824
+
825
+ Assertion.addMethod('ownProperty', assertOwnProperty);
826
+ Assertion.addMethod('haveOwnProperty', assertOwnProperty);
827
+
828
+ /**
829
+ * ### .length(value)
830
+ *
831
+ * Asserts that the target's `length` property has
832
+ * the expected value.
833
+ *
834
+ * expect([ 1, 2, 3]).to.have.length(3);
835
+ * expect('foobar').to.have.length(6);
836
+ *
837
+ * Can also be used as a chain precursor to a value
838
+ * comparison for the length property.
839
+ *
840
+ * expect('foo').to.have.length.above(2);
841
+ * expect([ 1, 2, 3 ]).to.have.length.above(2);
842
+ * expect('foo').to.have.length.below(4);
843
+ * expect([ 1, 2, 3 ]).to.have.length.below(4);
844
+ * expect('foo').to.have.length.within(2,4);
845
+ * expect([ 1, 2, 3 ]).to.have.length.within(2,4);
846
+ *
847
+ * @name length
848
+ * @alias lengthOf
849
+ * @param {Number} length
850
+ * @param {String} message _optional_
851
+ * @api public
852
+ */
853
+
854
+ function assertLengthChain () {
855
+ flag(this, 'doLength', true);
856
+ }
857
+
858
+ function assertLength (n, msg) {
859
+ if (msg) flag(this, 'message', msg);
860
+ var obj = flag(this, 'object');
861
+ new Assertion(obj, msg).to.have.property('length');
862
+ var len = obj.length;
863
+
864
+ this.assert(
865
+ len == n
866
+ , 'expected #{this} to have a length of #{exp} but got #{act}'
867
+ , 'expected #{this} to not have a length of #{act}'
868
+ , n
869
+ , len
870
+ );
871
+ }
872
+
873
+ Assertion.addChainableMethod('length', assertLength, assertLengthChain);
874
+ Assertion.addMethod('lengthOf', assertLength, assertLengthChain);
875
+
876
+ /**
877
+ * ### .match(regexp)
878
+ *
879
+ * Asserts that the target matches a regular expression.
880
+ *
881
+ * expect('foobar').to.match(/^foo/);
882
+ *
883
+ * @name match
884
+ * @param {RegExp} RegularExpression
885
+ * @param {String} message _optional_
886
+ * @api public
887
+ */
888
+
889
+ Assertion.addMethod('match', function (re, msg) {
890
+ if (msg) flag(this, 'message', msg);
891
+ var obj = flag(this, 'object');
892
+ this.assert(
893
+ re.exec(obj)
894
+ , 'expected #{this} to match ' + re
895
+ , 'expected #{this} not to match ' + re
896
+ );
897
+ });
898
+
899
+ /**
900
+ * ### .string(string)
901
+ *
902
+ * Asserts that the string target contains another string.
903
+ *
904
+ * expect('foobar').to.have.string('bar');
905
+ *
906
+ * @name string
907
+ * @param {String} string
908
+ * @param {String} message _optional_
909
+ * @api public
910
+ */
911
+
912
+ Assertion.addMethod('string', function (str, msg) {
913
+ if (msg) flag(this, 'message', msg);
914
+ var obj = flag(this, 'object');
915
+ new Assertion(obj, msg).is.a('string');
916
+
917
+ this.assert(
918
+ ~obj.indexOf(str)
919
+ , 'expected #{this} to contain ' + _.inspect(str)
920
+ , 'expected #{this} to not contain ' + _.inspect(str)
921
+ );
922
+ });
923
+
924
+
925
+ /**
926
+ * ### .keys(key1, [key2], [...])
927
+ *
928
+ * Asserts that the target has exactly the given keys, or
929
+ * asserts the inclusion of some keys when using the
930
+ * `include` or `contain` modifiers.
931
+ *
932
+ * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);
933
+ * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');
934
+ *
935
+ * @name keys
936
+ * @alias key
937
+ * @param {String...|Array} keys
938
+ * @api public
939
+ */
940
+
941
+ function assertKeys (keys) {
942
+ var obj = flag(this, 'object')
943
+ , str
944
+ , ok = true;
945
+
946
+ keys = keys instanceof Array
947
+ ? keys
948
+ : Array.prototype.slice.call(arguments);
949
+
950
+ if (!keys.length) throw new Error('keys required');
951
+
952
+ var actual = Object.keys(obj)
953
+ , len = keys.length;
954
+
955
+ // Inclusion
956
+ ok = keys.every(function(key){
957
+ return ~actual.indexOf(key);
958
+ });
959
+
960
+ // Strict
961
+ if (!flag(this, 'negate') && !flag(this, 'contains')) {
962
+ ok = ok && keys.length == actual.length;
963
+ }
964
+
965
+ // Key string
966
+ if (len > 1) {
967
+ keys = keys.map(function(key){
968
+ return _.inspect(key);
969
+ });
970
+ var last = keys.pop();
971
+ str = keys.join(', ') + ', and ' + last;
972
+ } else {
973
+ str = _.inspect(keys[0]);
974
+ }
975
+
976
+ // Form
977
+ str = (len > 1 ? 'keys ' : 'key ') + str;
978
+
979
+ // Have / include
980
+ str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
981
+
982
+ // Assertion
983
+ this.assert(
984
+ ok
985
+ , 'expected #{this} to ' + str
986
+ , 'expected #{this} to not ' + str
987
+ );
988
+ }
989
+
990
+ Assertion.addMethod('keys', assertKeys);
991
+ Assertion.addMethod('key', assertKeys);
992
+
993
+ /**
994
+ * ### .throw(constructor)
995
+ *
996
+ * Asserts that the function target will throw a specific error, or specific type of error
997
+ * (as determined using `instanceof`), optionally with a RegExp or string inclusion test
998
+ * for the error's message.
999
+ *
1000
+ * var err = new ReferenceError('This is a bad function.');
1001
+ * var fn = function () { throw err; }
1002
+ * expect(fn).to.throw(ReferenceError);
1003
+ * expect(fn).to.throw(Error);
1004
+ * expect(fn).to.throw(/bad function/);
1005
+ * expect(fn).to.not.throw('good function');
1006
+ * expect(fn).to.throw(ReferenceError, /bad function/);
1007
+ * expect(fn).to.throw(err);
1008
+ * expect(fn).to.not.throw(new RangeError('Out of range.'));
1009
+ *
1010
+ * Please note that when a throw expectation is negated, it will check each
1011
+ * parameter independently, starting with error constructor type. The appropriate way
1012
+ * to check for the existence of a type of error but for a message that does not match
1013
+ * is to use `and`.
1014
+ *
1015
+ * expect(fn).to.throw(ReferenceError)
1016
+ * .and.not.throw(/good function/);
1017
+ *
1018
+ * @name throw
1019
+ * @alias throws
1020
+ * @alias Throw
1021
+ * @param {ErrorConstructor} constructor
1022
+ * @param {String|RegExp} expected error message
1023
+ * @param {String} message _optional_
1024
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
1025
+ * @returns error for chaining (null if no error)
1026
+ * @api public
1027
+ */
1028
+
1029
+ function assertThrows (constructor, errMsg, msg) {
1030
+ if (msg) flag(this, 'message', msg);
1031
+ var obj = flag(this, 'object');
1032
+ new Assertion(obj, msg).is.a('function');
1033
+
1034
+ var thrown = false
1035
+ , desiredError = null
1036
+ , name = null
1037
+ , thrownError = null;
1038
+
1039
+ if (arguments.length === 0) {
1040
+ errMsg = null;
1041
+ constructor = null;
1042
+ } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
1043
+ errMsg = constructor;
1044
+ constructor = null;
1045
+ } else if (constructor && constructor instanceof Error) {
1046
+ desiredError = constructor;
1047
+ constructor = null;
1048
+ errMsg = null;
1049
+ } else if (typeof constructor === 'function') {
1050
+ name = constructor.prototype.name || constructor.name;
1051
+ if (name === 'Error' && constructor !== Error) {
1052
+ name = (new constructor()).name;
1053
+ }
1054
+ } else {
1055
+ constructor = null;
1056
+ }
1057
+
1058
+ try {
1059
+ obj();
1060
+ } catch (err) {
1061
+ // first, check desired error
1062
+ if (desiredError) {
1063
+ this.assert(
1064
+ err === desiredError
1065
+ , 'expected #{this} to throw #{exp} but #{act} was thrown'
1066
+ , 'expected #{this} to not throw #{exp}'
1067
+ , (desiredError instanceof Error ? desiredError.toString() : desiredError)
1068
+ , (err instanceof Error ? err.toString() : err)
1069
+ );
1070
+
1071
+ flag(this, 'object', err);
1072
+ return this;
1073
+ }
1074
+
1075
+ // next, check constructor
1076
+ if (constructor) {
1077
+ this.assert(
1078
+ err instanceof constructor
1079
+ , 'expected #{this} to throw #{exp} but #{act} was thrown'
1080
+ , 'expected #{this} to not throw #{exp} but #{act} was thrown'
1081
+ , name
1082
+ , (err instanceof Error ? err.toString() : err)
1083
+ );
1084
+
1085
+ if (!errMsg) {
1086
+ flag(this, 'object', err);
1087
+ return this;
1088
+ }
1089
+ }
1090
+
1091
+ // next, check message
1092
+ var message = 'object' === _.type(err) && "message" in err
1093
+ ? err.message
1094
+ : '' + err;
1095
+
1096
+ if ((message != null) && errMsg && errMsg instanceof RegExp) {
1097
+ this.assert(
1098
+ errMsg.exec(message)
1099
+ , 'expected #{this} to throw error matching #{exp} but got #{act}'
1100
+ , 'expected #{this} to throw error not matching #{exp}'
1101
+ , errMsg
1102
+ , message
1103
+ );
1104
+
1105
+ flag(this, 'object', err);
1106
+ return this;
1107
+ } else if ((message != null) && errMsg && 'string' === typeof errMsg) {
1108
+ this.assert(
1109
+ ~message.indexOf(errMsg)
1110
+ , 'expected #{this} to throw error including #{exp} but got #{act}'
1111
+ , 'expected #{this} to throw error not including #{act}'
1112
+ , errMsg
1113
+ , message
1114
+ );
1115
+
1116
+ flag(this, 'object', err);
1117
+ return this;
1118
+ } else {
1119
+ thrown = true;
1120
+ thrownError = err;
1121
+ }
1122
+ }
1123
+
1124
+ var actuallyGot = ''
1125
+ , expectedThrown = name !== null
1126
+ ? name
1127
+ : desiredError
1128
+ ? '#{exp}' //_.inspect(desiredError)
1129
+ : 'an error';
1130
+
1131
+ if (thrown) {
1132
+ actuallyGot = ' but #{act} was thrown'
1133
+ }
1134
+
1135
+ this.assert(
1136
+ thrown === true
1137
+ , 'expected #{this} to throw ' + expectedThrown + actuallyGot
1138
+ , 'expected #{this} to not throw ' + expectedThrown + actuallyGot
1139
+ , (desiredError instanceof Error ? desiredError.toString() : desiredError)
1140
+ , (thrownError instanceof Error ? thrownError.toString() : thrownError)
1141
+ );
1142
+
1143
+ flag(this, 'object', thrownError);
1144
+ };
1145
+
1146
+ Assertion.addMethod('throw', assertThrows);
1147
+ Assertion.addMethod('throws', assertThrows);
1148
+ Assertion.addMethod('Throw', assertThrows);
1149
+
1150
+ /**
1151
+ * ### .respondTo(method)
1152
+ *
1153
+ * Asserts that the object or class target will respond to a method.
1154
+ *
1155
+ * Klass.prototype.bar = function(){};
1156
+ * expect(Klass).to.respondTo('bar');
1157
+ * expect(obj).to.respondTo('bar');
1158
+ *
1159
+ * To check if a constructor will respond to a static function,
1160
+ * set the `itself` flag.
1161
+ *
1162
+ * Klass.baz = function(){};
1163
+ * expect(Klass).itself.to.respondTo('baz');
1164
+ *
1165
+ * @name respondTo
1166
+ * @param {String} method
1167
+ * @param {String} message _optional_
1168
+ * @api public
1169
+ */
1170
+
1171
+ Assertion.addMethod('respondTo', function (method, msg) {
1172
+ if (msg) flag(this, 'message', msg);
1173
+ var obj = flag(this, 'object')
1174
+ , itself = flag(this, 'itself')
1175
+ , context = ('function' === _.type(obj) && !itself)
1176
+ ? obj.prototype[method]
1177
+ : obj[method];
1178
+
1179
+ this.assert(
1180
+ 'function' === typeof context
1181
+ , 'expected #{this} to respond to ' + _.inspect(method)
1182
+ , 'expected #{this} to not respond to ' + _.inspect(method)
1183
+ );
1184
+ });
1185
+
1186
+ /**
1187
+ * ### .itself
1188
+ *
1189
+ * Sets the `itself` flag, later used by the `respondTo` assertion.
1190
+ *
1191
+ * function Foo() {}
1192
+ * Foo.bar = function() {}
1193
+ * Foo.prototype.baz = function() {}
1194
+ *
1195
+ * expect(Foo).itself.to.respondTo('bar');
1196
+ * expect(Foo).itself.not.to.respondTo('baz');
1197
+ *
1198
+ * @name itself
1199
+ * @api public
1200
+ */
1201
+
1202
+ Assertion.addProperty('itself', function () {
1203
+ flag(this, 'itself', true);
1204
+ });
1205
+
1206
+ /**
1207
+ * ### .satisfy(method)
1208
+ *
1209
+ * Asserts that the target passes a given truth test.
1210
+ *
1211
+ * expect(1).to.satisfy(function(num) { return num > 0; });
1212
+ *
1213
+ * @name satisfy
1214
+ * @param {Function} matcher
1215
+ * @param {String} message _optional_
1216
+ * @api public
1217
+ */
1218
+
1219
+ Assertion.addMethod('satisfy', function (matcher, msg) {
1220
+ if (msg) flag(this, 'message', msg);
1221
+ var obj = flag(this, 'object');
1222
+ this.assert(
1223
+ matcher(obj)
1224
+ , 'expected #{this} to satisfy ' + _.objDisplay(matcher)
1225
+ , 'expected #{this} to not satisfy' + _.objDisplay(matcher)
1226
+ , this.negate ? false : true
1227
+ , matcher(obj)
1228
+ );
1229
+ });
1230
+
1231
+ /**
1232
+ * ### .closeTo(expected, delta)
1233
+ *
1234
+ * Asserts that the target is equal `expected`, to within a +/- `delta` range.
1235
+ *
1236
+ * expect(1.5).to.be.closeTo(1, 0.5);
1237
+ *
1238
+ * @name closeTo
1239
+ * @param {Number} expected
1240
+ * @param {Number} delta
1241
+ * @param {String} message _optional_
1242
+ * @api public
1243
+ */
1244
+
1245
+ Assertion.addMethod('closeTo', function (expected, delta, msg) {
1246
+ if (msg) flag(this, 'message', msg);
1247
+ var obj = flag(this, 'object');
1248
+ this.assert(
1249
+ Math.abs(obj - expected) <= delta
1250
+ , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
1251
+ , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
1252
+ );
1253
+ });
1254
+
1255
+ function isSubsetOf(subset, superset, cmp) {
1256
+ return subset.every(function(elem) {
1257
+ if (!cmp) return superset.indexOf(elem) !== -1;
1258
+
1259
+ return superset.some(function(elem2) {
1260
+ return cmp(elem, elem2);
1261
+ });
1262
+ })
1263
+ }
1264
+
1265
+ /**
1266
+ * ### .members(set)
1267
+ *
1268
+ * Asserts that the target is a superset of `set`,
1269
+ * or that the target and `set` have the same strictly-equal (===) members.
1270
+ * Alternately, if the `deep` flag is set, set members are compared for deep
1271
+ * equality.
1272
+ *
1273
+ * expect([1, 2, 3]).to.include.members([3, 2]);
1274
+ * expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
1275
+ *
1276
+ * expect([4, 2]).to.have.members([2, 4]);
1277
+ * expect([5, 2]).to.not.have.members([5, 2, 1]);
1278
+ *
1279
+ * expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);
1280
+ *
1281
+ * @name members
1282
+ * @param {Array} set
1283
+ * @param {String} message _optional_
1284
+ * @api public
1285
+ */
1286
+
1287
+ Assertion.addMethod('members', function (subset, msg) {
1288
+ if (msg) flag(this, 'message', msg);
1289
+ var obj = flag(this, 'object');
1290
+
1291
+ new Assertion(obj).to.be.an('array');
1292
+ new Assertion(subset).to.be.an('array');
1293
+
1294
+ var cmp = flag(this, 'deep') ? _.eql : undefined;
1295
+
1296
+ if (flag(this, 'contains')) {
1297
+ return this.assert(
1298
+ isSubsetOf(subset, obj, cmp)
1299
+ , 'expected #{this} to be a superset of #{act}'
1300
+ , 'expected #{this} to not be a superset of #{act}'
1301
+ , obj
1302
+ , subset
1303
+ );
1304
+ }
1305
+
1306
+ this.assert(
1307
+ isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp)
1308
+ , 'expected #{this} to have the same members as #{act}'
1309
+ , 'expected #{this} to not have the same members as #{act}'
1310
+ , obj
1311
+ , subset
1312
+ );
1313
+ });
1314
+ };