epuber-stylus-source 0.54.8 → 0.56.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (465) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/Rakefile +1 -1
  4. data/VERSION +1 -1
  5. data/vendor/{History.md → Changelog.md} +50 -0
  6. data/vendor/Readme.md +37 -23
  7. data/vendor/bin/stylus +1 -2
  8. data/vendor/lib/convert/css.js +1 -1
  9. data/vendor/lib/functions/acos.js +20 -0
  10. data/vendor/lib/functions/asin.js +21 -0
  11. data/vendor/lib/functions/atan.js +21 -0
  12. data/vendor/lib/functions/convert-angle.js +19 -0
  13. data/vendor/lib/functions/index.js +3 -0
  14. data/vendor/lib/functions/url.js +5 -5
  15. data/vendor/lib/lexer.js +1 -1
  16. data/vendor/lib/middleware.js +1 -2
  17. data/vendor/lib/visitor/compiler.js +2 -2
  18. data/vendor/lib/visitor/deps-resolver.js +3 -0
  19. data/vendor/node_modules/{cliui/node_modules/ansi-regex → ansi-regex}/index.d.ts +0 -0
  20. data/vendor/node_modules/ansi-regex/index.js +4 -4
  21. data/vendor/node_modules/ansi-regex/package.json +53 -51
  22. data/vendor/node_modules/ansi-regex/readme.md +35 -3
  23. data/vendor/node_modules/assertion-error/History.md +24 -0
  24. data/vendor/node_modules/{mkdirp/LICENSE → assertion-error/README.md} +22 -2
  25. data/vendor/node_modules/assertion-error/index.d.ts +11 -0
  26. data/vendor/node_modules/assertion-error/index.js +116 -0
  27. data/vendor/node_modules/assertion-error/package.json +29 -0
  28. data/vendor/node_modules/camelcase/index.d.ts +5 -3
  29. data/vendor/node_modules/camelcase/index.js +40 -18
  30. data/vendor/node_modules/camelcase/package.json +1 -1
  31. data/vendor/node_modules/camelcase/readme.md +21 -5
  32. data/vendor/node_modules/chai/CODEOWNERS +1 -0
  33. data/vendor/node_modules/chai/CODE_OF_CONDUCT.md +58 -0
  34. data/vendor/node_modules/chai/CONTRIBUTING.md +218 -0
  35. data/vendor/node_modules/chai/History.md +1059 -0
  36. data/vendor/node_modules/{should-type-adaptors → chai}/LICENSE +1 -1
  37. data/vendor/node_modules/chai/README.md +212 -0
  38. data/vendor/node_modules/chai/ReleaseNotes.md +737 -0
  39. data/vendor/node_modules/chai/bower.json +26 -0
  40. data/vendor/node_modules/chai/chai.js +11464 -0
  41. data/vendor/node_modules/chai/index.js +1 -0
  42. data/vendor/node_modules/chai/index.mjs +14 -0
  43. data/vendor/node_modules/chai/karma.conf.js +34 -0
  44. data/vendor/node_modules/chai/karma.sauce.js +41 -0
  45. data/vendor/node_modules/chai/lib/chai/assertion.js +175 -0
  46. data/vendor/node_modules/chai/lib/chai/config.js +94 -0
  47. data/vendor/node_modules/chai/lib/chai/core/assertions.js +3853 -0
  48. data/vendor/node_modules/chai/lib/chai/interface/assert.js +3113 -0
  49. data/vendor/node_modules/chai/lib/chai/interface/expect.js +47 -0
  50. data/vendor/node_modules/chai/lib/chai/interface/should.js +219 -0
  51. data/vendor/node_modules/chai/lib/chai/utils/addChainableMethod.js +152 -0
  52. data/vendor/node_modules/chai/lib/chai/utils/addLengthGuard.js +60 -0
  53. data/vendor/node_modules/chai/lib/chai/utils/addMethod.js +68 -0
  54. data/vendor/node_modules/chai/lib/chai/utils/addProperty.js +72 -0
  55. data/vendor/node_modules/chai/lib/chai/utils/compareByInspect.js +31 -0
  56. data/vendor/node_modules/chai/lib/chai/utils/expectTypes.js +51 -0
  57. data/vendor/node_modules/chai/lib/chai/utils/flag.js +33 -0
  58. data/vendor/node_modules/chai/lib/chai/utils/getActual.js +20 -0
  59. data/vendor/node_modules/chai/lib/chai/utils/getEnumerableProperties.js +26 -0
  60. data/vendor/node_modules/chai/lib/chai/utils/getMessage.js +50 -0
  61. data/vendor/node_modules/chai/lib/chai/utils/getOperator.js +55 -0
  62. data/vendor/node_modules/chai/lib/chai/utils/getOwnEnumerableProperties.js +29 -0
  63. data/vendor/node_modules/chai/lib/chai/utils/getOwnEnumerablePropertySymbols.js +27 -0
  64. data/vendor/node_modules/chai/lib/chai/utils/getProperties.js +36 -0
  65. data/vendor/node_modules/chai/lib/chai/utils/index.js +178 -0
  66. data/vendor/node_modules/chai/lib/chai/utils/inspect.js +33 -0
  67. data/vendor/node_modules/chai/lib/chai/utils/isNaN.js +26 -0
  68. data/vendor/node_modules/chai/lib/chai/utils/isProxyEnabled.js +24 -0
  69. data/vendor/node_modules/chai/lib/chai/utils/objDisplay.js +50 -0
  70. data/vendor/node_modules/chai/lib/chai/utils/overwriteChainableMethod.js +69 -0
  71. data/vendor/node_modules/chai/lib/chai/utils/overwriteMethod.js +92 -0
  72. data/vendor/node_modules/chai/lib/chai/utils/overwriteProperty.js +92 -0
  73. data/vendor/node_modules/chai/lib/chai/utils/proxify.js +147 -0
  74. data/vendor/node_modules/chai/lib/chai/utils/test.js +28 -0
  75. data/vendor/node_modules/chai/lib/chai/utils/transferFlags.js +45 -0
  76. data/vendor/node_modules/chai/lib/chai.js +92 -0
  77. data/vendor/node_modules/chai/package.json +63 -0
  78. data/vendor/node_modules/chai/register-assert.js +1 -0
  79. data/vendor/node_modules/chai/register-expect.js +1 -0
  80. data/vendor/node_modules/chai/register-should.js +1 -0
  81. data/vendor/node_modules/chai/sauce.browsers.js +106 -0
  82. data/vendor/node_modules/chalk/package.json +1 -1
  83. data/vendor/node_modules/chalk/readme.md +7 -1
  84. data/vendor/node_modules/{source-map-url → check-error}/LICENSE +1 -3
  85. data/vendor/node_modules/check-error/README.md +207 -0
  86. data/vendor/node_modules/check-error/check-error.js +176 -0
  87. data/vendor/node_modules/check-error/index.js +172 -0
  88. data/vendor/node_modules/check-error/package.json +85 -0
  89. data/vendor/node_modules/chokidar/README.md +5 -4
  90. data/vendor/node_modules/chokidar/index.js +7 -1
  91. data/vendor/node_modules/chokidar/lib/constants.js +2 -0
  92. data/vendor/node_modules/chokidar/lib/fsevents-handler.js +2 -1
  93. data/vendor/node_modules/chokidar/lib/nodefs-handler.js +9 -1
  94. data/vendor/node_modules/chokidar/package.json +15 -8
  95. data/vendor/node_modules/chokidar/types/index.d.ts +4 -3
  96. data/vendor/node_modules/css/lib/stringify/source-map-support.js +10 -3
  97. data/vendor/node_modules/css/package.json +8 -9
  98. data/vendor/node_modules/debug/LICENSE +10 -9
  99. data/vendor/node_modules/debug/README.md +116 -3
  100. data/vendor/node_modules/debug/package.json +35 -19
  101. data/vendor/node_modules/debug/src/browser.js +194 -120
  102. data/vendor/node_modules/debug/src/common.js +274 -0
  103. data/vendor/node_modules/debug/src/index.js +4 -4
  104. data/vendor/node_modules/debug/src/node.js +174 -97
  105. data/vendor/node_modules/{resolve-url → deep-eql}/LICENSE +1 -3
  106. data/vendor/node_modules/deep-eql/README.md +116 -0
  107. data/vendor/node_modules/deep-eql/deep-eql.js +833 -0
  108. data/vendor/node_modules/deep-eql/index.js +455 -0
  109. data/vendor/node_modules/deep-eql/package.json +90 -0
  110. data/vendor/node_modules/{urix → get-func-name}/LICENSE +1 -3
  111. data/vendor/node_modules/get-func-name/README.md +123 -0
  112. data/vendor/node_modules/get-func-name/get-func-name.js +48 -0
  113. data/vendor/node_modules/get-func-name/index.js +44 -0
  114. data/vendor/node_modules/get-func-name/package.json +85 -0
  115. data/vendor/node_modules/glob/README.md +3 -0
  116. data/vendor/node_modules/glob/common.js +2 -0
  117. data/vendor/node_modules/glob/glob.js +4 -5
  118. data/vendor/node_modules/glob/package.json +2 -1
  119. data/vendor/node_modules/glob/sync.js +4 -5
  120. data/vendor/node_modules/{cliui/node_modules/is-fullwidth-code-point → is-fullwidth-code-point}/index.d.ts +0 -0
  121. data/vendor/node_modules/is-fullwidth-code-point/index.js +25 -21
  122. data/vendor/node_modules/is-fullwidth-code-point/license +4 -16
  123. data/vendor/node_modules/is-fullwidth-code-point/package.json +40 -43
  124. data/vendor/node_modules/is-fullwidth-code-point/readme.md +6 -6
  125. data/vendor/node_modules/is-glob/README.md +1 -1
  126. data/vendor/node_modules/is-glob/index.js +126 -24
  127. data/vendor/node_modules/is-glob/package.json +2 -2
  128. data/vendor/node_modules/is-unicode-supported/index.d.ts +14 -0
  129. data/vendor/node_modules/is-unicode-supported/index.js +13 -0
  130. data/vendor/node_modules/{cliui/node_modules/string-width → is-unicode-supported}/license +1 -1
  131. data/vendor/node_modules/is-unicode-supported/package.json +41 -0
  132. data/vendor/node_modules/is-unicode-supported/readme.md +35 -0
  133. data/vendor/node_modules/js-yaml/CHANGELOG.md +13 -0
  134. data/vendor/node_modules/js-yaml/README.md +1 -1
  135. data/vendor/node_modules/js-yaml/dist/js-yaml.js +90 -70
  136. data/vendor/node_modules/js-yaml/dist/js-yaml.min.js +2 -2
  137. data/vendor/node_modules/js-yaml/dist/js-yaml.mjs +84 -65
  138. data/vendor/node_modules/js-yaml/index.js +17 -0
  139. data/vendor/node_modules/js-yaml/lib/schema.js +9 -9
  140. data/vendor/node_modules/js-yaml/lib/type.js +1 -0
  141. data/vendor/node_modules/js-yaml/package.json +1 -1
  142. data/vendor/node_modules/jscoverage/node_modules/ms/index.js +152 -0
  143. data/vendor/node_modules/{should-format/LICENSE → jscoverage/node_modules/ms/license.md} +1 -2
  144. data/vendor/node_modules/jscoverage/node_modules/ms/package.json +37 -0
  145. data/vendor/node_modules/jscoverage/node_modules/ms/readme.md +51 -0
  146. data/vendor/node_modules/log-symbols/index.d.ts +2 -2
  147. data/vendor/node_modules/log-symbols/index.js +3 -4
  148. data/vendor/node_modules/log-symbols/package.json +7 -5
  149. data/vendor/node_modules/log-symbols/readme.md +3 -3
  150. data/vendor/node_modules/loupe/CHANGELOG.md +5 -0
  151. data/vendor/node_modules/{cliui/node_modules/strip-ansi/license → loupe/LICENSE} +2 -2
  152. data/vendor/node_modules/loupe/README.md +63 -0
  153. data/vendor/node_modules/loupe/index.js +195 -0
  154. data/vendor/node_modules/loupe/lib/arguments.js +7 -0
  155. data/vendor/node_modules/loupe/lib/array.js +20 -0
  156. data/vendor/node_modules/loupe/lib/bigint.js +7 -0
  157. data/vendor/node_modules/loupe/lib/class.js +18 -0
  158. data/vendor/node_modules/loupe/lib/date.js +8 -0
  159. data/vendor/node_modules/loupe/lib/error.js +34 -0
  160. data/vendor/node_modules/loupe/lib/function.js +10 -0
  161. data/vendor/node_modules/loupe/lib/helpers.js +177 -0
  162. data/vendor/node_modules/loupe/lib/html.js +40 -0
  163. data/vendor/node_modules/loupe/lib/map.js +27 -0
  164. data/vendor/node_modules/loupe/lib/number.js +18 -0
  165. data/vendor/node_modules/loupe/lib/object.js +31 -0
  166. data/vendor/node_modules/loupe/lib/promise.js +16 -0
  167. data/vendor/node_modules/loupe/lib/regexp.js +8 -0
  168. data/vendor/node_modules/loupe/lib/set.js +16 -0
  169. data/vendor/node_modules/loupe/lib/string.js +29 -0
  170. data/vendor/node_modules/loupe/lib/symbol.js +6 -0
  171. data/vendor/node_modules/loupe/lib/typedarray.js +45 -0
  172. data/vendor/node_modules/loupe/loupe.js +852 -0
  173. data/vendor/node_modules/loupe/package.json +141 -0
  174. data/vendor/node_modules/minimatch/README.md +22 -1
  175. data/vendor/node_modules/minimatch/minimatch.js +93 -69
  176. data/vendor/node_modules/minimatch/package.json +6 -3
  177. data/vendor/node_modules/mocha/LICENSE +1 -1
  178. data/vendor/node_modules/mocha/README.md +1 -1
  179. data/vendor/node_modules/mocha/bin/mocha +18 -27
  180. data/vendor/node_modules/mocha/browser-entry.js +27 -20
  181. data/vendor/node_modules/mocha/lib/browser/growl.js +5 -5
  182. data/vendor/node_modules/mocha/lib/browser/parse-query.js +1 -1
  183. data/vendor/node_modules/mocha/lib/browser/progress.js +6 -6
  184. data/vendor/node_modules/mocha/lib/cli/cli.js +3 -2
  185. data/vendor/node_modules/mocha/lib/cli/config.js +7 -12
  186. data/vendor/node_modules/mocha/lib/cli/lookup-files.js +2 -8
  187. data/vendor/node_modules/mocha/lib/cli/node-flags.js +2 -5
  188. data/vendor/node_modules/mocha/lib/cli/one-and-dones.js +1 -2
  189. data/vendor/node_modules/mocha/lib/cli/run-helpers.js +15 -15
  190. data/vendor/node_modules/mocha/lib/cli/run-option-metadata.js +4 -0
  191. data/vendor/node_modules/mocha/lib/cli/run.js +13 -1
  192. data/vendor/node_modules/mocha/lib/cli/watch-run.js +3 -6
  193. data/vendor/node_modules/mocha/lib/context.js +5 -5
  194. data/vendor/node_modules/mocha/lib/errors.js +3 -3
  195. data/vendor/node_modules/mocha/lib/hook.js +9 -3
  196. data/vendor/node_modules/mocha/lib/interfaces/bdd.js +23 -20
  197. data/vendor/node_modules/mocha/lib/interfaces/common.js +7 -7
  198. data/vendor/node_modules/mocha/lib/interfaces/exports.js +1 -1
  199. data/vendor/node_modules/mocha/lib/interfaces/qunit.js +7 -7
  200. data/vendor/node_modules/mocha/lib/interfaces/tdd.js +9 -9
  201. data/vendor/node_modules/mocha/lib/mocha.js +105 -99
  202. data/vendor/node_modules/mocha/lib/nodejs/buffered-worker-pool.js +17 -1
  203. data/vendor/node_modules/mocha/lib/nodejs/esm-utils.js +124 -0
  204. data/vendor/node_modules/mocha/lib/reporters/base.js +49 -35
  205. data/vendor/node_modules/mocha/lib/reporters/doc.js +4 -4
  206. data/vendor/node_modules/mocha/lib/reporters/dot.js +5 -5
  207. data/vendor/node_modules/mocha/lib/reporters/html.js +12 -12
  208. data/vendor/node_modules/mocha/lib/reporters/json-stream.js +4 -4
  209. data/vendor/node_modules/mocha/lib/reporters/json.js +35 -10
  210. data/vendor/node_modules/mocha/lib/reporters/landing.js +5 -5
  211. data/vendor/node_modules/mocha/lib/reporters/list.js +5 -5
  212. data/vendor/node_modules/mocha/lib/reporters/markdown.js +5 -5
  213. data/vendor/node_modules/mocha/lib/reporters/min.js +1 -1
  214. data/vendor/node_modules/mocha/lib/reporters/nyan.js +16 -16
  215. data/vendor/node_modules/mocha/lib/reporters/progress.js +3 -3
  216. data/vendor/node_modules/mocha/lib/reporters/spec.js +6 -6
  217. data/vendor/node_modules/mocha/lib/reporters/tap.js +17 -17
  218. data/vendor/node_modules/mocha/lib/reporters/xunit.js +9 -9
  219. data/vendor/node_modules/mocha/lib/runnable.js +21 -21
  220. data/vendor/node_modules/mocha/lib/runner.js +63 -61
  221. data/vendor/node_modules/mocha/lib/stats-collector.js +7 -7
  222. data/vendor/node_modules/mocha/lib/suite.js +46 -75
  223. data/vendor/node_modules/mocha/lib/test.js +5 -5
  224. data/vendor/node_modules/mocha/lib/utils.js +19 -114
  225. data/vendor/node_modules/mocha/mocha-es2018.js +19794 -0
  226. data/vendor/node_modules/mocha/mocha.js +8059 -6920
  227. data/vendor/node_modules/mocha/mocha.js.map +1 -1
  228. data/vendor/node_modules/mocha/node_modules/debug/LICENSE +10 -9
  229. data/vendor/node_modules/mocha/node_modules/debug/README.md +24 -1
  230. data/vendor/node_modules/mocha/node_modules/debug/package.json +6 -6
  231. data/vendor/node_modules/mocha/node_modules/debug/src/common.js +15 -2
  232. data/vendor/node_modules/{semver → mocha/node_modules/minimatch}/LICENSE +1 -1
  233. data/vendor/node_modules/mocha/node_modules/minimatch/README.md +230 -0
  234. data/vendor/node_modules/mocha/node_modules/minimatch/minimatch.js +908 -0
  235. data/vendor/node_modules/mocha/node_modules/minimatch/package.json +31 -0
  236. data/vendor/node_modules/mocha/package.json +66 -65
  237. data/vendor/node_modules/ms/index.js +29 -19
  238. data/vendor/node_modules/ms/package.json +6 -6
  239. data/vendor/node_modules/ms/readme.md +18 -9
  240. data/vendor/node_modules/nanoid/README.md +9 -473
  241. data/vendor/node_modules/nanoid/async/index.browser.cjs +34 -0
  242. data/vendor/node_modules/nanoid/async/index.browser.js +7 -43
  243. data/vendor/node_modules/nanoid/async/index.cjs +5 -41
  244. data/vendor/node_modules/nanoid/async/index.d.ts +7 -7
  245. data/vendor/node_modules/nanoid/async/index.js +5 -41
  246. data/vendor/node_modules/nanoid/async/index.native.js +5 -36
  247. data/vendor/node_modules/nanoid/async/package.json +2 -1
  248. data/vendor/node_modules/nanoid/bin/nanoid.cjs +52 -2
  249. data/vendor/node_modules/nanoid/index.browser.cjs +37 -0
  250. data/vendor/node_modules/nanoid/index.browser.js +5 -73
  251. data/vendor/node_modules/nanoid/index.cjs +14 -49
  252. data/vendor/node_modules/nanoid/index.d.ts +9 -6
  253. data/vendor/node_modules/nanoid/index.js +14 -49
  254. data/vendor/node_modules/nanoid/non-secure/index.cjs +3 -12
  255. data/vendor/node_modules/nanoid/non-secure/index.d.ts +8 -5
  256. data/vendor/node_modules/nanoid/non-secure/index.js +3 -12
  257. data/vendor/node_modules/nanoid/package.json +14 -10
  258. data/vendor/node_modules/nanoid/url-alphabet/index.cjs +1 -4
  259. data/vendor/node_modules/nanoid/url-alphabet/index.js +1 -4
  260. data/vendor/node_modules/pathval/CHANGELOG.md +18 -0
  261. data/vendor/node_modules/pathval/LICENSE +16 -0
  262. data/vendor/node_modules/pathval/README.md +147 -0
  263. data/vendor/node_modules/pathval/index.js +301 -0
  264. data/vendor/node_modules/pathval/package.json +80 -0
  265. data/vendor/node_modules/pathval/pathval.js +1 -0
  266. data/vendor/node_modules/picomatch/CHANGELOG.md +16 -0
  267. data/vendor/node_modules/picomatch/README.md +34 -17
  268. data/vendor/node_modules/picomatch/lib/parse.js +19 -6
  269. data/vendor/node_modules/picomatch/lib/picomatch.js +34 -31
  270. data/vendor/node_modules/picomatch/lib/scan.js +8 -2
  271. data/vendor/node_modules/picomatch/package.json +1 -1
  272. data/vendor/node_modules/readdirp/index.js +11 -6
  273. data/vendor/node_modules/readdirp/package.json +1 -1
  274. data/vendor/node_modules/serialize-javascript/README.md +2 -4
  275. data/vendor/node_modules/serialize-javascript/index.js +11 -2
  276. data/vendor/node_modules/serialize-javascript/package.json +2 -2
  277. data/vendor/node_modules/source-map-resolve/LICENSE +1 -1
  278. data/vendor/node_modules/source-map-resolve/changelog.md +6 -0
  279. data/vendor/node_modules/source-map-resolve/{lib/source-map-resolve-node.js → index.js} +48 -13
  280. data/vendor/node_modules/source-map-resolve/package.json +7 -14
  281. data/vendor/node_modules/source-map-resolve/readme.md +1 -39
  282. data/vendor/node_modules/{cliui/node_modules/string-width → string-width}/index.d.ts +0 -0
  283. data/vendor/node_modules/string-width/index.js +16 -5
  284. data/vendor/node_modules/string-width/package.json +11 -10
  285. data/vendor/node_modules/string-width/readme.md +15 -7
  286. data/vendor/node_modules/{cliui/node_modules/strip-ansi → strip-ansi}/index.d.ts +0 -0
  287. data/vendor/node_modules/strip-ansi/index.js +1 -1
  288. data/vendor/node_modules/strip-ansi/package.json +52 -50
  289. data/vendor/node_modules/strip-ansi/readme.md +12 -5
  290. data/vendor/node_modules/{fsevents → type-detect}/LICENSE +1 -4
  291. data/vendor/node_modules/type-detect/README.md +228 -0
  292. data/vendor/node_modules/type-detect/index.js +378 -0
  293. data/vendor/node_modules/type-detect/package.json +1 -0
  294. data/vendor/node_modules/type-detect/type-detect.js +388 -0
  295. data/vendor/node_modules/workerpool/HISTORY.md +42 -0
  296. data/vendor/node_modules/workerpool/README.md +11 -1
  297. data/vendor/node_modules/workerpool/dist/worker.js +9 -42
  298. data/vendor/node_modules/workerpool/dist/worker.js.map +1 -1
  299. data/vendor/node_modules/workerpool/dist/workerpool.js +117 -74
  300. data/vendor/node_modules/workerpool/dist/workerpool.js.map +1 -1
  301. data/vendor/node_modules/workerpool/dist/workerpool.min.js +1 -1
  302. data/vendor/node_modules/workerpool/dist/workerpool.min.js.LICENSE.txt +3 -3
  303. data/vendor/node_modules/workerpool/dist/workerpool.min.js.map +1 -1
  304. data/vendor/node_modules/workerpool/package.json +11 -11
  305. data/vendor/node_modules/workerpool/src/Pool.js +29 -4
  306. data/vendor/node_modules/workerpool/src/WorkerHandler.js +17 -4
  307. data/vendor/node_modules/workerpool/src/generated/embeddedWorker.js +1 -1
  308. data/vendor/node_modules/workerpool/src/header.js +1 -1
  309. data/vendor/node_modules/workerpool/src/types.js +2 -1
  310. data/vendor/package-lock.json +401 -664
  311. data/vendor/package.json +7 -9
  312. metadata +139 -175
  313. data/vendor/node_modules/cliui/node_modules/ansi-regex/index.js +0 -10
  314. data/vendor/node_modules/cliui/node_modules/ansi-regex/license +0 -9
  315. data/vendor/node_modules/cliui/node_modules/ansi-regex/package.json +0 -55
  316. data/vendor/node_modules/cliui/node_modules/ansi-regex/readme.md +0 -78
  317. data/vendor/node_modules/cliui/node_modules/is-fullwidth-code-point/index.js +0 -50
  318. data/vendor/node_modules/cliui/node_modules/is-fullwidth-code-point/license +0 -9
  319. data/vendor/node_modules/cliui/node_modules/is-fullwidth-code-point/package.json +0 -42
  320. data/vendor/node_modules/cliui/node_modules/is-fullwidth-code-point/readme.md +0 -39
  321. data/vendor/node_modules/cliui/node_modules/string-width/index.js +0 -47
  322. data/vendor/node_modules/cliui/node_modules/string-width/package.json +0 -56
  323. data/vendor/node_modules/cliui/node_modules/string-width/readme.md +0 -50
  324. data/vendor/node_modules/cliui/node_modules/strip-ansi/index.js +0 -4
  325. data/vendor/node_modules/cliui/node_modules/strip-ansi/package.json +0 -54
  326. data/vendor/node_modules/cliui/node_modules/strip-ansi/readme.md +0 -46
  327. data/vendor/node_modules/css-parse/Readme.md +0 -15
  328. data/vendor/node_modules/css-parse/index.js +0 -1
  329. data/vendor/node_modules/css-parse/package.json +0 -23
  330. data/vendor/node_modules/debug/CHANGELOG.md +0 -395
  331. data/vendor/node_modules/debug/Makefile +0 -58
  332. data/vendor/node_modules/debug/karma.conf.js +0 -70
  333. data/vendor/node_modules/debug/node.js +0 -1
  334. data/vendor/node_modules/debug/src/debug.js +0 -225
  335. data/vendor/node_modules/fsevents/README.md +0 -83
  336. data/vendor/node_modules/fsevents/fsevents.d.ts +0 -46
  337. data/vendor/node_modules/fsevents/fsevents.js +0 -82
  338. data/vendor/node_modules/fsevents/fsevents.node +0 -0
  339. data/vendor/node_modules/fsevents/package.json +0 -62
  340. data/vendor/node_modules/glob/changelog.md +0 -67
  341. data/vendor/node_modules/mkdirp/CHANGELOG.md +0 -15
  342. data/vendor/node_modules/mkdirp/bin/cmd.js +0 -68
  343. data/vendor/node_modules/mkdirp/index.js +0 -31
  344. data/vendor/node_modules/mkdirp/lib/find-made.js +0 -29
  345. data/vendor/node_modules/mkdirp/lib/mkdirp-manual.js +0 -64
  346. data/vendor/node_modules/mkdirp/lib/mkdirp-native.js +0 -39
  347. data/vendor/node_modules/mkdirp/lib/opts-arg.js +0 -23
  348. data/vendor/node_modules/mkdirp/lib/path-arg.js +0 -29
  349. data/vendor/node_modules/mkdirp/lib/use-native.js +0 -10
  350. data/vendor/node_modules/mkdirp/package.json +0 -44
  351. data/vendor/node_modules/mkdirp/readme.markdown +0 -266
  352. data/vendor/node_modules/mocha/CHANGELOG.md +0 -931
  353. data/vendor/node_modules/mocha/lib/esm-utils.js +0 -58
  354. data/vendor/node_modules/mocha/node_modules/glob/LICENSE +0 -21
  355. data/vendor/node_modules/mocha/node_modules/glob/README.md +0 -375
  356. data/vendor/node_modules/mocha/node_modules/glob/changelog.md +0 -67
  357. data/vendor/node_modules/mocha/node_modules/glob/common.js +0 -240
  358. data/vendor/node_modules/mocha/node_modules/glob/glob.js +0 -790
  359. data/vendor/node_modules/mocha/node_modules/glob/package.json +0 -46
  360. data/vendor/node_modules/mocha/node_modules/glob/sync.js +0 -486
  361. data/vendor/node_modules/nanoid/CHANGELOG.md +0 -241
  362. data/vendor/node_modules/nanoid/index.dev.js +0 -105
  363. data/vendor/node_modules/nanoid/index.prod.js +0 -105
  364. data/vendor/node_modules/resolve-url/bower.json +0 -15
  365. data/vendor/node_modules/resolve-url/changelog.md +0 -15
  366. data/vendor/node_modules/resolve-url/component.json +0 -15
  367. data/vendor/node_modules/resolve-url/package.json +0 -34
  368. data/vendor/node_modules/resolve-url/readme.md +0 -83
  369. data/vendor/node_modules/resolve-url/resolve-url.js +0 -47
  370. data/vendor/node_modules/resolve-url/test/resolve-url.js +0 -70
  371. data/vendor/node_modules/semver/CHANGELOG.md +0 -70
  372. data/vendor/node_modules/semver/README.md +0 -443
  373. data/vendor/node_modules/semver/bin/semver.js +0 -174
  374. data/vendor/node_modules/semver/package.json +0 -28
  375. data/vendor/node_modules/semver/range.bnf +0 -16
  376. data/vendor/node_modules/semver/semver.js +0 -1596
  377. data/vendor/node_modules/should/CONTRIBUTING.md +0 -14
  378. data/vendor/node_modules/should/History.md +0 -554
  379. data/vendor/node_modules/should/LICENSE +0 -20
  380. data/vendor/node_modules/should/Readme.md +0 -223
  381. data/vendor/node_modules/should/as-function.js +0 -2935
  382. data/vendor/node_modules/should/cjs/should.js +0 -2962
  383. data/vendor/node_modules/should/es6/should.js +0 -2958
  384. data/vendor/node_modules/should/package.json +0 -51
  385. data/vendor/node_modules/should/should.d.ts +0 -243
  386. data/vendor/node_modules/should/should.js +0 -4371
  387. data/vendor/node_modules/should-equal/LICENSE +0 -21
  388. data/vendor/node_modules/should-equal/README.md +0 -24
  389. data/vendor/node_modules/should-equal/cjs/should-equal.js +0 -333
  390. data/vendor/node_modules/should-equal/es6/should-equal.js +0 -329
  391. data/vendor/node_modules/should-equal/package.json +0 -38
  392. data/vendor/node_modules/should-format/README.md +0 -6
  393. data/vendor/node_modules/should-format/cjs/should-format.js +0 -532
  394. data/vendor/node_modules/should-format/es6/should-format.js +0 -528
  395. data/vendor/node_modules/should-format/package.json +0 -44
  396. data/vendor/node_modules/should-type/LICENSE +0 -22
  397. data/vendor/node_modules/should-type/README.md +0 -4
  398. data/vendor/node_modules/should-type/cjs/should-type.js +0 -263
  399. data/vendor/node_modules/should-type/es6/should-type.js +0 -261
  400. data/vendor/node_modules/should-type/package.json +0 -38
  401. data/vendor/node_modules/should-type-adaptors/README.md +0 -1
  402. data/vendor/node_modules/should-type-adaptors/cjs/should-type-adaptors.js +0 -288
  403. data/vendor/node_modules/should-type-adaptors/es6/should-type-adaptors.js +0 -272
  404. data/vendor/node_modules/should-type-adaptors/package.json +0 -43
  405. data/vendor/node_modules/should-util/LICENSE +0 -21
  406. data/vendor/node_modules/should-util/README.md +0 -2
  407. data/vendor/node_modules/should-util/cjs/should-util.js +0 -50
  408. data/vendor/node_modules/should-util/es6/should-util.js +0 -42
  409. data/vendor/node_modules/should-util/package.json +0 -40
  410. data/vendor/node_modules/source-map-resolve/lib/decode-uri-component.js +0 -8
  411. data/vendor/node_modules/source-map-resolve/lib/resolve-url.js +0 -9
  412. data/vendor/node_modules/source-map-resolve/source-map-resolve.js +0 -348
  413. data/vendor/node_modules/source-map-url/changelog.md +0 -57
  414. data/vendor/node_modules/source-map-url/package.json +0 -39
  415. data/vendor/node_modules/source-map-url/readme.md +0 -97
  416. data/vendor/node_modules/source-map-url/source-map-url.js +0 -57
  417. data/vendor/node_modules/urix/index.js +0 -17
  418. data/vendor/node_modules/urix/package.json +0 -25
  419. data/vendor/node_modules/urix/readme.md +0 -46
  420. data/vendor/node_modules/urix/test/index.js +0 -43
  421. data/vendor/node_modules/wide-align/LICENSE +0 -14
  422. data/vendor/node_modules/wide-align/README.md +0 -47
  423. data/vendor/node_modules/wide-align/align.js +0 -65
  424. data/vendor/node_modules/wide-align/package.json +0 -33
  425. data/vendor/node_modules/wrap-ansi/node_modules/ansi-regex/index.d.ts +0 -37
  426. data/vendor/node_modules/wrap-ansi/node_modules/ansi-regex/index.js +0 -10
  427. data/vendor/node_modules/wrap-ansi/node_modules/ansi-regex/license +0 -9
  428. data/vendor/node_modules/wrap-ansi/node_modules/ansi-regex/package.json +0 -55
  429. data/vendor/node_modules/wrap-ansi/node_modules/ansi-regex/readme.md +0 -78
  430. data/vendor/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/index.d.ts +0 -17
  431. data/vendor/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/index.js +0 -50
  432. data/vendor/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/license +0 -9
  433. data/vendor/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/package.json +0 -42
  434. data/vendor/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/readme.md +0 -39
  435. data/vendor/node_modules/wrap-ansi/node_modules/string-width/index.d.ts +0 -29
  436. data/vendor/node_modules/wrap-ansi/node_modules/string-width/index.js +0 -47
  437. data/vendor/node_modules/wrap-ansi/node_modules/string-width/license +0 -9
  438. data/vendor/node_modules/wrap-ansi/node_modules/string-width/package.json +0 -56
  439. data/vendor/node_modules/wrap-ansi/node_modules/string-width/readme.md +0 -50
  440. data/vendor/node_modules/wrap-ansi/node_modules/strip-ansi/index.d.ts +0 -17
  441. data/vendor/node_modules/wrap-ansi/node_modules/strip-ansi/index.js +0 -4
  442. data/vendor/node_modules/wrap-ansi/node_modules/strip-ansi/license +0 -9
  443. data/vendor/node_modules/wrap-ansi/node_modules/strip-ansi/package.json +0 -54
  444. data/vendor/node_modules/wrap-ansi/node_modules/strip-ansi/readme.md +0 -46
  445. data/vendor/node_modules/yargs/node_modules/ansi-regex/index.d.ts +0 -37
  446. data/vendor/node_modules/yargs/node_modules/ansi-regex/index.js +0 -10
  447. data/vendor/node_modules/yargs/node_modules/ansi-regex/license +0 -9
  448. data/vendor/node_modules/yargs/node_modules/ansi-regex/package.json +0 -55
  449. data/vendor/node_modules/yargs/node_modules/ansi-regex/readme.md +0 -78
  450. data/vendor/node_modules/yargs/node_modules/is-fullwidth-code-point/index.d.ts +0 -17
  451. data/vendor/node_modules/yargs/node_modules/is-fullwidth-code-point/index.js +0 -50
  452. data/vendor/node_modules/yargs/node_modules/is-fullwidth-code-point/license +0 -9
  453. data/vendor/node_modules/yargs/node_modules/is-fullwidth-code-point/package.json +0 -42
  454. data/vendor/node_modules/yargs/node_modules/is-fullwidth-code-point/readme.md +0 -39
  455. data/vendor/node_modules/yargs/node_modules/string-width/index.d.ts +0 -29
  456. data/vendor/node_modules/yargs/node_modules/string-width/index.js +0 -47
  457. data/vendor/node_modules/yargs/node_modules/string-width/license +0 -9
  458. data/vendor/node_modules/yargs/node_modules/string-width/package.json +0 -56
  459. data/vendor/node_modules/yargs/node_modules/string-width/readme.md +0 -50
  460. data/vendor/node_modules/yargs/node_modules/strip-ansi/index.d.ts +0 -17
  461. data/vendor/node_modules/yargs/node_modules/strip-ansi/index.js +0 -4
  462. data/vendor/node_modules/yargs/node_modules/strip-ansi/license +0 -9
  463. data/vendor/node_modules/yargs/node_modules/strip-ansi/package.json +0 -54
  464. data/vendor/node_modules/yargs/node_modules/strip-ansi/readme.md +0 -46
  465. data/vendor/test.js +0 -31
@@ -0,0 +1,3853 @@
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
+ , AssertionError = chai.AssertionError
11
+ , flag = _.flag;
12
+
13
+ /**
14
+ * ### Language Chains
15
+ *
16
+ * The following are provided as chainable getters to improve the readability
17
+ * of your assertions.
18
+ *
19
+ * **Chains**
20
+ *
21
+ * - to
22
+ * - be
23
+ * - been
24
+ * - is
25
+ * - that
26
+ * - which
27
+ * - and
28
+ * - has
29
+ * - have
30
+ * - with
31
+ * - at
32
+ * - of
33
+ * - same
34
+ * - but
35
+ * - does
36
+ * - still
37
+ * - also
38
+ *
39
+ * @name language chains
40
+ * @namespace BDD
41
+ * @api public
42
+ */
43
+
44
+ [ 'to', 'be', 'been', 'is'
45
+ , 'and', 'has', 'have', 'with'
46
+ , 'that', 'which', 'at', 'of'
47
+ , 'same', 'but', 'does', 'still', "also" ].forEach(function (chain) {
48
+ Assertion.addProperty(chain);
49
+ });
50
+
51
+ /**
52
+ * ### .not
53
+ *
54
+ * Negates all assertions that follow in the chain.
55
+ *
56
+ * expect(function () {}).to.not.throw();
57
+ * expect({a: 1}).to.not.have.property('b');
58
+ * expect([1, 2]).to.be.an('array').that.does.not.include(3);
59
+ *
60
+ * Just because you can negate any assertion with `.not` doesn't mean you
61
+ * should. With great power comes great responsibility. It's often best to
62
+ * assert that the one expected output was produced, rather than asserting
63
+ * that one of countless unexpected outputs wasn't produced. See individual
64
+ * assertions for specific guidance.
65
+ *
66
+ * expect(2).to.equal(2); // Recommended
67
+ * expect(2).to.not.equal(1); // Not recommended
68
+ *
69
+ * @name not
70
+ * @namespace BDD
71
+ * @api public
72
+ */
73
+
74
+ Assertion.addProperty('not', function () {
75
+ flag(this, 'negate', true);
76
+ });
77
+
78
+ /**
79
+ * ### .deep
80
+ *
81
+ * Causes all `.equal`, `.include`, `.members`, `.keys`, and `.property`
82
+ * assertions that follow in the chain to use deep equality instead of strict
83
+ * (`===`) equality. See the `deep-eql` project page for info on the deep
84
+ * equality algorithm: https://github.com/chaijs/deep-eql.
85
+ *
86
+ * // Target object deeply (but not strictly) equals `{a: 1}`
87
+ * expect({a: 1}).to.deep.equal({a: 1});
88
+ * expect({a: 1}).to.not.equal({a: 1});
89
+ *
90
+ * // Target array deeply (but not strictly) includes `{a: 1}`
91
+ * expect([{a: 1}]).to.deep.include({a: 1});
92
+ * expect([{a: 1}]).to.not.include({a: 1});
93
+ *
94
+ * // Target object deeply (but not strictly) includes `x: {a: 1}`
95
+ * expect({x: {a: 1}}).to.deep.include({x: {a: 1}});
96
+ * expect({x: {a: 1}}).to.not.include({x: {a: 1}});
97
+ *
98
+ * // Target array deeply (but not strictly) has member `{a: 1}`
99
+ * expect([{a: 1}]).to.have.deep.members([{a: 1}]);
100
+ * expect([{a: 1}]).to.not.have.members([{a: 1}]);
101
+ *
102
+ * // Target set deeply (but not strictly) has key `{a: 1}`
103
+ * expect(new Set([{a: 1}])).to.have.deep.keys([{a: 1}]);
104
+ * expect(new Set([{a: 1}])).to.not.have.keys([{a: 1}]);
105
+ *
106
+ * // Target object deeply (but not strictly) has property `x: {a: 1}`
107
+ * expect({x: {a: 1}}).to.have.deep.property('x', {a: 1});
108
+ * expect({x: {a: 1}}).to.not.have.property('x', {a: 1});
109
+ *
110
+ * @name deep
111
+ * @namespace BDD
112
+ * @api public
113
+ */
114
+
115
+ Assertion.addProperty('deep', function () {
116
+ flag(this, 'deep', true);
117
+ });
118
+
119
+ /**
120
+ * ### .nested
121
+ *
122
+ * Enables dot- and bracket-notation in all `.property` and `.include`
123
+ * assertions that follow in the chain.
124
+ *
125
+ * expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]');
126
+ * expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'});
127
+ *
128
+ * If `.` or `[]` are part of an actual property name, they can be escaped by
129
+ * adding two backslashes before them.
130
+ *
131
+ * expect({'.a': {'[b]': 'x'}}).to.have.nested.property('\\.a.\\[b\\]');
132
+ * expect({'.a': {'[b]': 'x'}}).to.nested.include({'\\.a.\\[b\\]': 'x'});
133
+ *
134
+ * `.nested` cannot be combined with `.own`.
135
+ *
136
+ * @name nested
137
+ * @namespace BDD
138
+ * @api public
139
+ */
140
+
141
+ Assertion.addProperty('nested', function () {
142
+ flag(this, 'nested', true);
143
+ });
144
+
145
+ /**
146
+ * ### .own
147
+ *
148
+ * Causes all `.property` and `.include` assertions that follow in the chain
149
+ * to ignore inherited properties.
150
+ *
151
+ * Object.prototype.b = 2;
152
+ *
153
+ * expect({a: 1}).to.have.own.property('a');
154
+ * expect({a: 1}).to.have.property('b');
155
+ * expect({a: 1}).to.not.have.own.property('b');
156
+ *
157
+ * expect({a: 1}).to.own.include({a: 1});
158
+ * expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2});
159
+ *
160
+ * `.own` cannot be combined with `.nested`.
161
+ *
162
+ * @name own
163
+ * @namespace BDD
164
+ * @api public
165
+ */
166
+
167
+ Assertion.addProperty('own', function () {
168
+ flag(this, 'own', true);
169
+ });
170
+
171
+ /**
172
+ * ### .ordered
173
+ *
174
+ * Causes all `.members` assertions that follow in the chain to require that
175
+ * members be in the same order.
176
+ *
177
+ * expect([1, 2]).to.have.ordered.members([1, 2])
178
+ * .but.not.have.ordered.members([2, 1]);
179
+ *
180
+ * When `.include` and `.ordered` are combined, the ordering begins at the
181
+ * start of both arrays.
182
+ *
183
+ * expect([1, 2, 3]).to.include.ordered.members([1, 2])
184
+ * .but.not.include.ordered.members([2, 3]);
185
+ *
186
+ * @name ordered
187
+ * @namespace BDD
188
+ * @api public
189
+ */
190
+
191
+ Assertion.addProperty('ordered', function () {
192
+ flag(this, 'ordered', true);
193
+ });
194
+
195
+ /**
196
+ * ### .any
197
+ *
198
+ * Causes all `.keys` assertions that follow in the chain to only require that
199
+ * the target have at least one of the given keys. This is the opposite of
200
+ * `.all`, which requires that the target have all of the given keys.
201
+ *
202
+ * expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd');
203
+ *
204
+ * See the `.keys` doc for guidance on when to use `.any` or `.all`.
205
+ *
206
+ * @name any
207
+ * @namespace BDD
208
+ * @api public
209
+ */
210
+
211
+ Assertion.addProperty('any', function () {
212
+ flag(this, 'any', true);
213
+ flag(this, 'all', false);
214
+ });
215
+
216
+ /**
217
+ * ### .all
218
+ *
219
+ * Causes all `.keys` assertions that follow in the chain to require that the
220
+ * target have all of the given keys. This is the opposite of `.any`, which
221
+ * only requires that the target have at least one of the given keys.
222
+ *
223
+ * expect({a: 1, b: 2}).to.have.all.keys('a', 'b');
224
+ *
225
+ * Note that `.all` is used by default when neither `.all` nor `.any` are
226
+ * added earlier in the chain. However, it's often best to add `.all` anyway
227
+ * because it improves readability.
228
+ *
229
+ * See the `.keys` doc for guidance on when to use `.any` or `.all`.
230
+ *
231
+ * @name all
232
+ * @namespace BDD
233
+ * @api public
234
+ */
235
+
236
+ Assertion.addProperty('all', function () {
237
+ flag(this, 'all', true);
238
+ flag(this, 'any', false);
239
+ });
240
+
241
+ /**
242
+ * ### .a(type[, msg])
243
+ *
244
+ * Asserts that the target's type is equal to the given string `type`. Types
245
+ * are case insensitive. See the `type-detect` project page for info on the
246
+ * type detection algorithm: https://github.com/chaijs/type-detect.
247
+ *
248
+ * expect('foo').to.be.a('string');
249
+ * expect({a: 1}).to.be.an('object');
250
+ * expect(null).to.be.a('null');
251
+ * expect(undefined).to.be.an('undefined');
252
+ * expect(new Error).to.be.an('error');
253
+ * expect(Promise.resolve()).to.be.a('promise');
254
+ * expect(new Float32Array).to.be.a('float32array');
255
+ * expect(Symbol()).to.be.a('symbol');
256
+ *
257
+ * `.a` supports objects that have a custom type set via `Symbol.toStringTag`.
258
+ *
259
+ * var myObj = {
260
+ * [Symbol.toStringTag]: 'myCustomType'
261
+ * };
262
+ *
263
+ * expect(myObj).to.be.a('myCustomType').but.not.an('object');
264
+ *
265
+ * It's often best to use `.a` to check a target's type before making more
266
+ * assertions on the same target. That way, you avoid unexpected behavior from
267
+ * any assertion that does different things based on the target's type.
268
+ *
269
+ * expect([1, 2, 3]).to.be.an('array').that.includes(2);
270
+ * expect([]).to.be.an('array').that.is.empty;
271
+ *
272
+ * Add `.not` earlier in the chain to negate `.a`. However, it's often best to
273
+ * assert that the target is the expected type, rather than asserting that it
274
+ * isn't one of many unexpected types.
275
+ *
276
+ * expect('foo').to.be.a('string'); // Recommended
277
+ * expect('foo').to.not.be.an('array'); // Not recommended
278
+ *
279
+ * `.a` accepts an optional `msg` argument which is a custom error message to
280
+ * show when the assertion fails. The message can also be given as the second
281
+ * argument to `expect`.
282
+ *
283
+ * expect(1).to.be.a('string', 'nooo why fail??');
284
+ * expect(1, 'nooo why fail??').to.be.a('string');
285
+ *
286
+ * `.a` can also be used as a language chain to improve the readability of
287
+ * your assertions.
288
+ *
289
+ * expect({b: 2}).to.have.a.property('b');
290
+ *
291
+ * The alias `.an` can be used interchangeably with `.a`.
292
+ *
293
+ * @name a
294
+ * @alias an
295
+ * @param {String} type
296
+ * @param {String} msg _optional_
297
+ * @namespace BDD
298
+ * @api public
299
+ */
300
+
301
+ function an (type, msg) {
302
+ if (msg) flag(this, 'message', msg);
303
+ type = type.toLowerCase();
304
+ var obj = flag(this, 'object')
305
+ , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
306
+
307
+ this.assert(
308
+ type === _.type(obj).toLowerCase()
309
+ , 'expected #{this} to be ' + article + type
310
+ , 'expected #{this} not to be ' + article + type
311
+ );
312
+ }
313
+
314
+ Assertion.addChainableMethod('an', an);
315
+ Assertion.addChainableMethod('a', an);
316
+
317
+ /**
318
+ * ### .include(val[, msg])
319
+ *
320
+ * When the target is a string, `.include` asserts that the given string `val`
321
+ * is a substring of the target.
322
+ *
323
+ * expect('foobar').to.include('foo');
324
+ *
325
+ * When the target is an array, `.include` asserts that the given `val` is a
326
+ * member of the target.
327
+ *
328
+ * expect([1, 2, 3]).to.include(2);
329
+ *
330
+ * When the target is an object, `.include` asserts that the given object
331
+ * `val`'s properties are a subset of the target's properties.
332
+ *
333
+ * expect({a: 1, b: 2, c: 3}).to.include({a: 1, b: 2});
334
+ *
335
+ * When the target is a Set or WeakSet, `.include` asserts that the given `val` is a
336
+ * member of the target. SameValueZero equality algorithm is used.
337
+ *
338
+ * expect(new Set([1, 2])).to.include(2);
339
+ *
340
+ * When the target is a Map, `.include` asserts that the given `val` is one of
341
+ * the values of the target. SameValueZero equality algorithm is used.
342
+ *
343
+ * expect(new Map([['a', 1], ['b', 2]])).to.include(2);
344
+ *
345
+ * Because `.include` does different things based on the target's type, it's
346
+ * important to check the target's type before using `.include`. See the `.a`
347
+ * doc for info on testing a target's type.
348
+ *
349
+ * expect([1, 2, 3]).to.be.an('array').that.includes(2);
350
+ *
351
+ * By default, strict (`===`) equality is used to compare array members and
352
+ * object properties. Add `.deep` earlier in the chain to use deep equality
353
+ * instead (WeakSet targets are not supported). See the `deep-eql` project
354
+ * page for info on the deep equality algorithm: https://github.com/chaijs/deep-eql.
355
+ *
356
+ * // Target array deeply (but not strictly) includes `{a: 1}`
357
+ * expect([{a: 1}]).to.deep.include({a: 1});
358
+ * expect([{a: 1}]).to.not.include({a: 1});
359
+ *
360
+ * // Target object deeply (but not strictly) includes `x: {a: 1}`
361
+ * expect({x: {a: 1}}).to.deep.include({x: {a: 1}});
362
+ * expect({x: {a: 1}}).to.not.include({x: {a: 1}});
363
+ *
364
+ * By default, all of the target's properties are searched when working with
365
+ * objects. This includes properties that are inherited and/or non-enumerable.
366
+ * Add `.own` earlier in the chain to exclude the target's inherited
367
+ * properties from the search.
368
+ *
369
+ * Object.prototype.b = 2;
370
+ *
371
+ * expect({a: 1}).to.own.include({a: 1});
372
+ * expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2});
373
+ *
374
+ * Note that a target object is always only searched for `val`'s own
375
+ * enumerable properties.
376
+ *
377
+ * `.deep` and `.own` can be combined.
378
+ *
379
+ * expect({a: {b: 2}}).to.deep.own.include({a: {b: 2}});
380
+ *
381
+ * Add `.nested` earlier in the chain to enable dot- and bracket-notation when
382
+ * referencing nested properties.
383
+ *
384
+ * expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'});
385
+ *
386
+ * If `.` or `[]` are part of an actual property name, they can be escaped by
387
+ * adding two backslashes before them.
388
+ *
389
+ * expect({'.a': {'[b]': 2}}).to.nested.include({'\\.a.\\[b\\]': 2});
390
+ *
391
+ * `.deep` and `.nested` can be combined.
392
+ *
393
+ * expect({a: {b: [{c: 3}]}}).to.deep.nested.include({'a.b[0]': {c: 3}});
394
+ *
395
+ * `.own` and `.nested` cannot be combined.
396
+ *
397
+ * Add `.not` earlier in the chain to negate `.include`.
398
+ *
399
+ * expect('foobar').to.not.include('taco');
400
+ * expect([1, 2, 3]).to.not.include(4);
401
+ *
402
+ * However, it's dangerous to negate `.include` when the target is an object.
403
+ * The problem is that it creates uncertain expectations by asserting that the
404
+ * target object doesn't have all of `val`'s key/value pairs but may or may
405
+ * not have some of them. It's often best to identify the exact output that's
406
+ * expected, and then write an assertion that only accepts that exact output.
407
+ *
408
+ * When the target object isn't even expected to have `val`'s keys, it's
409
+ * often best to assert exactly that.
410
+ *
411
+ * expect({c: 3}).to.not.have.any.keys('a', 'b'); // Recommended
412
+ * expect({c: 3}).to.not.include({a: 1, b: 2}); // Not recommended
413
+ *
414
+ * When the target object is expected to have `val`'s keys, it's often best to
415
+ * assert that each of the properties has its expected value, rather than
416
+ * asserting that each property doesn't have one of many unexpected values.
417
+ *
418
+ * expect({a: 3, b: 4}).to.include({a: 3, b: 4}); // Recommended
419
+ * expect({a: 3, b: 4}).to.not.include({a: 1, b: 2}); // Not recommended
420
+ *
421
+ * `.include` accepts an optional `msg` argument which is a custom error
422
+ * message to show when the assertion fails. The message can also be given as
423
+ * the second argument to `expect`.
424
+ *
425
+ * expect([1, 2, 3]).to.include(4, 'nooo why fail??');
426
+ * expect([1, 2, 3], 'nooo why fail??').to.include(4);
427
+ *
428
+ * `.include` can also be used as a language chain, causing all `.members` and
429
+ * `.keys` assertions that follow in the chain to require the target to be a
430
+ * superset of the expected set, rather than an identical set. Note that
431
+ * `.members` ignores duplicates in the subset when `.include` is added.
432
+ *
433
+ * // Target object's keys are a superset of ['a', 'b'] but not identical
434
+ * expect({a: 1, b: 2, c: 3}).to.include.all.keys('a', 'b');
435
+ * expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('a', 'b');
436
+ *
437
+ * // Target array is a superset of [1, 2] but not identical
438
+ * expect([1, 2, 3]).to.include.members([1, 2]);
439
+ * expect([1, 2, 3]).to.not.have.members([1, 2]);
440
+ *
441
+ * // Duplicates in the subset are ignored
442
+ * expect([1, 2, 3]).to.include.members([1, 2, 2, 2]);
443
+ *
444
+ * Note that adding `.any` earlier in the chain causes the `.keys` assertion
445
+ * to ignore `.include`.
446
+ *
447
+ * // Both assertions are identical
448
+ * expect({a: 1}).to.include.any.keys('a', 'b');
449
+ * expect({a: 1}).to.have.any.keys('a', 'b');
450
+ *
451
+ * The aliases `.includes`, `.contain`, and `.contains` can be used
452
+ * interchangeably with `.include`.
453
+ *
454
+ * @name include
455
+ * @alias contain
456
+ * @alias includes
457
+ * @alias contains
458
+ * @param {Mixed} val
459
+ * @param {String} msg _optional_
460
+ * @namespace BDD
461
+ * @api public
462
+ */
463
+
464
+ function SameValueZero(a, b) {
465
+ return (_.isNaN(a) && _.isNaN(b)) || a === b;
466
+ }
467
+
468
+ function includeChainingBehavior () {
469
+ flag(this, 'contains', true);
470
+ }
471
+
472
+ function include (val, msg) {
473
+ if (msg) flag(this, 'message', msg);
474
+
475
+ var obj = flag(this, 'object')
476
+ , objType = _.type(obj).toLowerCase()
477
+ , flagMsg = flag(this, 'message')
478
+ , negate = flag(this, 'negate')
479
+ , ssfi = flag(this, 'ssfi')
480
+ , isDeep = flag(this, 'deep')
481
+ , descriptor = isDeep ? 'deep ' : '';
482
+
483
+ flagMsg = flagMsg ? flagMsg + ': ' : '';
484
+
485
+ var included = false;
486
+
487
+ switch (objType) {
488
+ case 'string':
489
+ included = obj.indexOf(val) !== -1;
490
+ break;
491
+
492
+ case 'weakset':
493
+ if (isDeep) {
494
+ throw new AssertionError(
495
+ flagMsg + 'unable to use .deep.include with WeakSet',
496
+ undefined,
497
+ ssfi
498
+ );
499
+ }
500
+
501
+ included = obj.has(val);
502
+ break;
503
+
504
+ case 'map':
505
+ var isEql = isDeep ? _.eql : SameValueZero;
506
+ obj.forEach(function (item) {
507
+ included = included || isEql(item, val);
508
+ });
509
+ break;
510
+
511
+ case 'set':
512
+ if (isDeep) {
513
+ obj.forEach(function (item) {
514
+ included = included || _.eql(item, val);
515
+ });
516
+ } else {
517
+ included = obj.has(val);
518
+ }
519
+ break;
520
+
521
+ case 'array':
522
+ if (isDeep) {
523
+ included = obj.some(function (item) {
524
+ return _.eql(item, val);
525
+ })
526
+ } else {
527
+ included = obj.indexOf(val) !== -1;
528
+ }
529
+ break;
530
+
531
+ default:
532
+ // This block is for asserting a subset of properties in an object.
533
+ // `_.expectTypes` isn't used here because `.include` should work with
534
+ // objects with a custom `@@toStringTag`.
535
+ if (val !== Object(val)) {
536
+ throw new AssertionError(
537
+ flagMsg + 'the given combination of arguments ('
538
+ + objType + ' and '
539
+ + _.type(val).toLowerCase() + ')'
540
+ + ' is invalid for this assertion. '
541
+ + 'You can use an array, a map, an object, a set, a string, '
542
+ + 'or a weakset instead of a '
543
+ + _.type(val).toLowerCase(),
544
+ undefined,
545
+ ssfi
546
+ );
547
+ }
548
+
549
+ var props = Object.keys(val)
550
+ , firstErr = null
551
+ , numErrs = 0;
552
+
553
+ props.forEach(function (prop) {
554
+ var propAssertion = new Assertion(obj);
555
+ _.transferFlags(this, propAssertion, true);
556
+ flag(propAssertion, 'lockSsfi', true);
557
+
558
+ if (!negate || props.length === 1) {
559
+ propAssertion.property(prop, val[prop]);
560
+ return;
561
+ }
562
+
563
+ try {
564
+ propAssertion.property(prop, val[prop]);
565
+ } catch (err) {
566
+ if (!_.checkError.compatibleConstructor(err, AssertionError)) {
567
+ throw err;
568
+ }
569
+ if (firstErr === null) firstErr = err;
570
+ numErrs++;
571
+ }
572
+ }, this);
573
+
574
+ // When validating .not.include with multiple properties, we only want
575
+ // to throw an assertion error if all of the properties are included,
576
+ // in which case we throw the first property assertion error that we
577
+ // encountered.
578
+ if (negate && props.length > 1 && numErrs === props.length) {
579
+ throw firstErr;
580
+ }
581
+ return;
582
+ }
583
+
584
+ // Assert inclusion in collection or substring in a string.
585
+ this.assert(
586
+ included
587
+ , 'expected #{this} to ' + descriptor + 'include ' + _.inspect(val)
588
+ , 'expected #{this} to not ' + descriptor + 'include ' + _.inspect(val));
589
+ }
590
+
591
+ Assertion.addChainableMethod('include', include, includeChainingBehavior);
592
+ Assertion.addChainableMethod('contain', include, includeChainingBehavior);
593
+ Assertion.addChainableMethod('contains', include, includeChainingBehavior);
594
+ Assertion.addChainableMethod('includes', include, includeChainingBehavior);
595
+
596
+ /**
597
+ * ### .ok
598
+ *
599
+ * Asserts that the target is a truthy value (considered `true` in boolean context).
600
+ * However, it's often best to assert that the target is strictly (`===`) or
601
+ * deeply equal to its expected value.
602
+ *
603
+ * expect(1).to.equal(1); // Recommended
604
+ * expect(1).to.be.ok; // Not recommended
605
+ *
606
+ * expect(true).to.be.true; // Recommended
607
+ * expect(true).to.be.ok; // Not recommended
608
+ *
609
+ * Add `.not` earlier in the chain to negate `.ok`.
610
+ *
611
+ * expect(0).to.equal(0); // Recommended
612
+ * expect(0).to.not.be.ok; // Not recommended
613
+ *
614
+ * expect(false).to.be.false; // Recommended
615
+ * expect(false).to.not.be.ok; // Not recommended
616
+ *
617
+ * expect(null).to.be.null; // Recommended
618
+ * expect(null).to.not.be.ok; // Not recommended
619
+ *
620
+ * expect(undefined).to.be.undefined; // Recommended
621
+ * expect(undefined).to.not.be.ok; // Not recommended
622
+ *
623
+ * A custom error message can be given as the second argument to `expect`.
624
+ *
625
+ * expect(false, 'nooo why fail??').to.be.ok;
626
+ *
627
+ * @name ok
628
+ * @namespace BDD
629
+ * @api public
630
+ */
631
+
632
+ Assertion.addProperty('ok', function () {
633
+ this.assert(
634
+ flag(this, 'object')
635
+ , 'expected #{this} to be truthy'
636
+ , 'expected #{this} to be falsy');
637
+ });
638
+
639
+ /**
640
+ * ### .true
641
+ *
642
+ * Asserts that the target is strictly (`===`) equal to `true`.
643
+ *
644
+ * expect(true).to.be.true;
645
+ *
646
+ * Add `.not` earlier in the chain to negate `.true`. However, it's often best
647
+ * to assert that the target is equal to its expected value, rather than not
648
+ * equal to `true`.
649
+ *
650
+ * expect(false).to.be.false; // Recommended
651
+ * expect(false).to.not.be.true; // Not recommended
652
+ *
653
+ * expect(1).to.equal(1); // Recommended
654
+ * expect(1).to.not.be.true; // Not recommended
655
+ *
656
+ * A custom error message can be given as the second argument to `expect`.
657
+ *
658
+ * expect(false, 'nooo why fail??').to.be.true;
659
+ *
660
+ * @name true
661
+ * @namespace BDD
662
+ * @api public
663
+ */
664
+
665
+ Assertion.addProperty('true', function () {
666
+ this.assert(
667
+ true === flag(this, 'object')
668
+ , 'expected #{this} to be true'
669
+ , 'expected #{this} to be false'
670
+ , flag(this, 'negate') ? false : true
671
+ );
672
+ });
673
+
674
+ /**
675
+ * ### .false
676
+ *
677
+ * Asserts that the target is strictly (`===`) equal to `false`.
678
+ *
679
+ * expect(false).to.be.false;
680
+ *
681
+ * Add `.not` earlier in the chain to negate `.false`. However, it's often
682
+ * best to assert that the target is equal to its expected value, rather than
683
+ * not equal to `false`.
684
+ *
685
+ * expect(true).to.be.true; // Recommended
686
+ * expect(true).to.not.be.false; // Not recommended
687
+ *
688
+ * expect(1).to.equal(1); // Recommended
689
+ * expect(1).to.not.be.false; // Not recommended
690
+ *
691
+ * A custom error message can be given as the second argument to `expect`.
692
+ *
693
+ * expect(true, 'nooo why fail??').to.be.false;
694
+ *
695
+ * @name false
696
+ * @namespace BDD
697
+ * @api public
698
+ */
699
+
700
+ Assertion.addProperty('false', function () {
701
+ this.assert(
702
+ false === flag(this, 'object')
703
+ , 'expected #{this} to be false'
704
+ , 'expected #{this} to be true'
705
+ , flag(this, 'negate') ? true : false
706
+ );
707
+ });
708
+
709
+ /**
710
+ * ### .null
711
+ *
712
+ * Asserts that the target is strictly (`===`) equal to `null`.
713
+ *
714
+ * expect(null).to.be.null;
715
+ *
716
+ * Add `.not` earlier in the chain to negate `.null`. However, it's often best
717
+ * to assert that the target is equal to its expected value, rather than not
718
+ * equal to `null`.
719
+ *
720
+ * expect(1).to.equal(1); // Recommended
721
+ * expect(1).to.not.be.null; // Not recommended
722
+ *
723
+ * A custom error message can be given as the second argument to `expect`.
724
+ *
725
+ * expect(42, 'nooo why fail??').to.be.null;
726
+ *
727
+ * @name null
728
+ * @namespace BDD
729
+ * @api public
730
+ */
731
+
732
+ Assertion.addProperty('null', function () {
733
+ this.assert(
734
+ null === flag(this, 'object')
735
+ , 'expected #{this} to be null'
736
+ , 'expected #{this} not to be null'
737
+ );
738
+ });
739
+
740
+ /**
741
+ * ### .undefined
742
+ *
743
+ * Asserts that the target is strictly (`===`) equal to `undefined`.
744
+ *
745
+ * expect(undefined).to.be.undefined;
746
+ *
747
+ * Add `.not` earlier in the chain to negate `.undefined`. However, it's often
748
+ * best to assert that the target is equal to its expected value, rather than
749
+ * not equal to `undefined`.
750
+ *
751
+ * expect(1).to.equal(1); // Recommended
752
+ * expect(1).to.not.be.undefined; // Not recommended
753
+ *
754
+ * A custom error message can be given as the second argument to `expect`.
755
+ *
756
+ * expect(42, 'nooo why fail??').to.be.undefined;
757
+ *
758
+ * @name undefined
759
+ * @namespace BDD
760
+ * @api public
761
+ */
762
+
763
+ Assertion.addProperty('undefined', function () {
764
+ this.assert(
765
+ undefined === flag(this, 'object')
766
+ , 'expected #{this} to be undefined'
767
+ , 'expected #{this} not to be undefined'
768
+ );
769
+ });
770
+
771
+ /**
772
+ * ### .NaN
773
+ *
774
+ * Asserts that the target is exactly `NaN`.
775
+ *
776
+ * expect(NaN).to.be.NaN;
777
+ *
778
+ * Add `.not` earlier in the chain to negate `.NaN`. However, it's often best
779
+ * to assert that the target is equal to its expected value, rather than not
780
+ * equal to `NaN`.
781
+ *
782
+ * expect('foo').to.equal('foo'); // Recommended
783
+ * expect('foo').to.not.be.NaN; // Not recommended
784
+ *
785
+ * A custom error message can be given as the second argument to `expect`.
786
+ *
787
+ * expect(42, 'nooo why fail??').to.be.NaN;
788
+ *
789
+ * @name NaN
790
+ * @namespace BDD
791
+ * @api public
792
+ */
793
+
794
+ Assertion.addProperty('NaN', function () {
795
+ this.assert(
796
+ _.isNaN(flag(this, 'object'))
797
+ , 'expected #{this} to be NaN'
798
+ , 'expected #{this} not to be NaN'
799
+ );
800
+ });
801
+
802
+ /**
803
+ * ### .exist
804
+ *
805
+ * Asserts that the target is not strictly (`===`) equal to either `null` or
806
+ * `undefined`. However, it's often best to assert that the target is equal to
807
+ * its expected value.
808
+ *
809
+ * expect(1).to.equal(1); // Recommended
810
+ * expect(1).to.exist; // Not recommended
811
+ *
812
+ * expect(0).to.equal(0); // Recommended
813
+ * expect(0).to.exist; // Not recommended
814
+ *
815
+ * Add `.not` earlier in the chain to negate `.exist`.
816
+ *
817
+ * expect(null).to.be.null; // Recommended
818
+ * expect(null).to.not.exist; // Not recommended
819
+ *
820
+ * expect(undefined).to.be.undefined; // Recommended
821
+ * expect(undefined).to.not.exist; // Not recommended
822
+ *
823
+ * A custom error message can be given as the second argument to `expect`.
824
+ *
825
+ * expect(null, 'nooo why fail??').to.exist;
826
+ *
827
+ * The alias `.exists` can be used interchangeably with `.exist`.
828
+ *
829
+ * @name exist
830
+ * @alias exists
831
+ * @namespace BDD
832
+ * @api public
833
+ */
834
+
835
+ function assertExist () {
836
+ var val = flag(this, 'object');
837
+ this.assert(
838
+ val !== null && val !== undefined
839
+ , 'expected #{this} to exist'
840
+ , 'expected #{this} to not exist'
841
+ );
842
+ }
843
+
844
+ Assertion.addProperty('exist', assertExist);
845
+ Assertion.addProperty('exists', assertExist);
846
+
847
+ /**
848
+ * ### .empty
849
+ *
850
+ * When the target is a string or array, `.empty` asserts that the target's
851
+ * `length` property is strictly (`===`) equal to `0`.
852
+ *
853
+ * expect([]).to.be.empty;
854
+ * expect('').to.be.empty;
855
+ *
856
+ * When the target is a map or set, `.empty` asserts that the target's `size`
857
+ * property is strictly equal to `0`.
858
+ *
859
+ * expect(new Set()).to.be.empty;
860
+ * expect(new Map()).to.be.empty;
861
+ *
862
+ * When the target is a non-function object, `.empty` asserts that the target
863
+ * doesn't have any own enumerable properties. Properties with Symbol-based
864
+ * keys are excluded from the count.
865
+ *
866
+ * expect({}).to.be.empty;
867
+ *
868
+ * Because `.empty` does different things based on the target's type, it's
869
+ * important to check the target's type before using `.empty`. See the `.a`
870
+ * doc for info on testing a target's type.
871
+ *
872
+ * expect([]).to.be.an('array').that.is.empty;
873
+ *
874
+ * Add `.not` earlier in the chain to negate `.empty`. However, it's often
875
+ * best to assert that the target contains its expected number of values,
876
+ * rather than asserting that it's not empty.
877
+ *
878
+ * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended
879
+ * expect([1, 2, 3]).to.not.be.empty; // Not recommended
880
+ *
881
+ * expect(new Set([1, 2, 3])).to.have.property('size', 3); // Recommended
882
+ * expect(new Set([1, 2, 3])).to.not.be.empty; // Not recommended
883
+ *
884
+ * expect(Object.keys({a: 1})).to.have.lengthOf(1); // Recommended
885
+ * expect({a: 1}).to.not.be.empty; // Not recommended
886
+ *
887
+ * A custom error message can be given as the second argument to `expect`.
888
+ *
889
+ * expect([1, 2, 3], 'nooo why fail??').to.be.empty;
890
+ *
891
+ * @name empty
892
+ * @namespace BDD
893
+ * @api public
894
+ */
895
+
896
+ Assertion.addProperty('empty', function () {
897
+ var val = flag(this, 'object')
898
+ , ssfi = flag(this, 'ssfi')
899
+ , flagMsg = flag(this, 'message')
900
+ , itemsCount;
901
+
902
+ flagMsg = flagMsg ? flagMsg + ': ' : '';
903
+
904
+ switch (_.type(val).toLowerCase()) {
905
+ case 'array':
906
+ case 'string':
907
+ itemsCount = val.length;
908
+ break;
909
+ case 'map':
910
+ case 'set':
911
+ itemsCount = val.size;
912
+ break;
913
+ case 'weakmap':
914
+ case 'weakset':
915
+ throw new AssertionError(
916
+ flagMsg + '.empty was passed a weak collection',
917
+ undefined,
918
+ ssfi
919
+ );
920
+ case 'function':
921
+ var msg = flagMsg + '.empty was passed a function ' + _.getName(val);
922
+ throw new AssertionError(msg.trim(), undefined, ssfi);
923
+ default:
924
+ if (val !== Object(val)) {
925
+ throw new AssertionError(
926
+ flagMsg + '.empty was passed non-string primitive ' + _.inspect(val),
927
+ undefined,
928
+ ssfi
929
+ );
930
+ }
931
+ itemsCount = Object.keys(val).length;
932
+ }
933
+
934
+ this.assert(
935
+ 0 === itemsCount
936
+ , 'expected #{this} to be empty'
937
+ , 'expected #{this} not to be empty'
938
+ );
939
+ });
940
+
941
+ /**
942
+ * ### .arguments
943
+ *
944
+ * Asserts that the target is an `arguments` object.
945
+ *
946
+ * function test () {
947
+ * expect(arguments).to.be.arguments;
948
+ * }
949
+ *
950
+ * test();
951
+ *
952
+ * Add `.not` earlier in the chain to negate `.arguments`. However, it's often
953
+ * best to assert which type the target is expected to be, rather than
954
+ * asserting that it’s not an `arguments` object.
955
+ *
956
+ * expect('foo').to.be.a('string'); // Recommended
957
+ * expect('foo').to.not.be.arguments; // Not recommended
958
+ *
959
+ * A custom error message can be given as the second argument to `expect`.
960
+ *
961
+ * expect({}, 'nooo why fail??').to.be.arguments;
962
+ *
963
+ * The alias `.Arguments` can be used interchangeably with `.arguments`.
964
+ *
965
+ * @name arguments
966
+ * @alias Arguments
967
+ * @namespace BDD
968
+ * @api public
969
+ */
970
+
971
+ function checkArguments () {
972
+ var obj = flag(this, 'object')
973
+ , type = _.type(obj);
974
+ this.assert(
975
+ 'Arguments' === type
976
+ , 'expected #{this} to be arguments but got ' + type
977
+ , 'expected #{this} to not be arguments'
978
+ );
979
+ }
980
+
981
+ Assertion.addProperty('arguments', checkArguments);
982
+ Assertion.addProperty('Arguments', checkArguments);
983
+
984
+ /**
985
+ * ### .equal(val[, msg])
986
+ *
987
+ * Asserts that the target is strictly (`===`) equal to the given `val`.
988
+ *
989
+ * expect(1).to.equal(1);
990
+ * expect('foo').to.equal('foo');
991
+ *
992
+ * Add `.deep` earlier in the chain to use deep equality instead. See the
993
+ * `deep-eql` project page for info on the deep equality algorithm:
994
+ * https://github.com/chaijs/deep-eql.
995
+ *
996
+ * // Target object deeply (but not strictly) equals `{a: 1}`
997
+ * expect({a: 1}).to.deep.equal({a: 1});
998
+ * expect({a: 1}).to.not.equal({a: 1});
999
+ *
1000
+ * // Target array deeply (but not strictly) equals `[1, 2]`
1001
+ * expect([1, 2]).to.deep.equal([1, 2]);
1002
+ * expect([1, 2]).to.not.equal([1, 2]);
1003
+ *
1004
+ * Add `.not` earlier in the chain to negate `.equal`. However, it's often
1005
+ * best to assert that the target is equal to its expected value, rather than
1006
+ * not equal to one of countless unexpected values.
1007
+ *
1008
+ * expect(1).to.equal(1); // Recommended
1009
+ * expect(1).to.not.equal(2); // Not recommended
1010
+ *
1011
+ * `.equal` accepts an optional `msg` argument which is a custom error message
1012
+ * to show when the assertion fails. The message can also be given as the
1013
+ * second argument to `expect`.
1014
+ *
1015
+ * expect(1).to.equal(2, 'nooo why fail??');
1016
+ * expect(1, 'nooo why fail??').to.equal(2);
1017
+ *
1018
+ * The aliases `.equals` and `eq` can be used interchangeably with `.equal`.
1019
+ *
1020
+ * @name equal
1021
+ * @alias equals
1022
+ * @alias eq
1023
+ * @param {Mixed} val
1024
+ * @param {String} msg _optional_
1025
+ * @namespace BDD
1026
+ * @api public
1027
+ */
1028
+
1029
+ function assertEqual (val, msg) {
1030
+ if (msg) flag(this, 'message', msg);
1031
+ var obj = flag(this, 'object');
1032
+ if (flag(this, 'deep')) {
1033
+ var prevLockSsfi = flag(this, 'lockSsfi');
1034
+ flag(this, 'lockSsfi', true);
1035
+ this.eql(val);
1036
+ flag(this, 'lockSsfi', prevLockSsfi);
1037
+ } else {
1038
+ this.assert(
1039
+ val === obj
1040
+ , 'expected #{this} to equal #{exp}'
1041
+ , 'expected #{this} to not equal #{exp}'
1042
+ , val
1043
+ , this._obj
1044
+ , true
1045
+ );
1046
+ }
1047
+ }
1048
+
1049
+ Assertion.addMethod('equal', assertEqual);
1050
+ Assertion.addMethod('equals', assertEqual);
1051
+ Assertion.addMethod('eq', assertEqual);
1052
+
1053
+ /**
1054
+ * ### .eql(obj[, msg])
1055
+ *
1056
+ * Asserts that the target is deeply equal to the given `obj`. See the
1057
+ * `deep-eql` project page for info on the deep equality algorithm:
1058
+ * https://github.com/chaijs/deep-eql.
1059
+ *
1060
+ * // Target object is deeply (but not strictly) equal to {a: 1}
1061
+ * expect({a: 1}).to.eql({a: 1}).but.not.equal({a: 1});
1062
+ *
1063
+ * // Target array is deeply (but not strictly) equal to [1, 2]
1064
+ * expect([1, 2]).to.eql([1, 2]).but.not.equal([1, 2]);
1065
+ *
1066
+ * Add `.not` earlier in the chain to negate `.eql`. However, it's often best
1067
+ * to assert that the target is deeply equal to its expected value, rather
1068
+ * than not deeply equal to one of countless unexpected values.
1069
+ *
1070
+ * expect({a: 1}).to.eql({a: 1}); // Recommended
1071
+ * expect({a: 1}).to.not.eql({b: 2}); // Not recommended
1072
+ *
1073
+ * `.eql` accepts an optional `msg` argument which is a custom error message
1074
+ * to show when the assertion fails. The message can also be given as the
1075
+ * second argument to `expect`.
1076
+ *
1077
+ * expect({a: 1}).to.eql({b: 2}, 'nooo why fail??');
1078
+ * expect({a: 1}, 'nooo why fail??').to.eql({b: 2});
1079
+ *
1080
+ * The alias `.eqls` can be used interchangeably with `.eql`.
1081
+ *
1082
+ * The `.deep.equal` assertion is almost identical to `.eql` but with one
1083
+ * difference: `.deep.equal` causes deep equality comparisons to also be used
1084
+ * for any other assertions that follow in the chain.
1085
+ *
1086
+ * @name eql
1087
+ * @alias eqls
1088
+ * @param {Mixed} obj
1089
+ * @param {String} msg _optional_
1090
+ * @namespace BDD
1091
+ * @api public
1092
+ */
1093
+
1094
+ function assertEql(obj, msg) {
1095
+ if (msg) flag(this, 'message', msg);
1096
+ this.assert(
1097
+ _.eql(obj, flag(this, 'object'))
1098
+ , 'expected #{this} to deeply equal #{exp}'
1099
+ , 'expected #{this} to not deeply equal #{exp}'
1100
+ , obj
1101
+ , this._obj
1102
+ , true
1103
+ );
1104
+ }
1105
+
1106
+ Assertion.addMethod('eql', assertEql);
1107
+ Assertion.addMethod('eqls', assertEql);
1108
+
1109
+ /**
1110
+ * ### .above(n[, msg])
1111
+ *
1112
+ * Asserts that the target is a number or a date greater than the given number or date `n` respectively.
1113
+ * However, it's often best to assert that the target is equal to its expected
1114
+ * value.
1115
+ *
1116
+ * expect(2).to.equal(2); // Recommended
1117
+ * expect(2).to.be.above(1); // Not recommended
1118
+ *
1119
+ * Add `.lengthOf` earlier in the chain to assert that the target's `length`
1120
+ * or `size` is greater than the given number `n`.
1121
+ *
1122
+ * expect('foo').to.have.lengthOf(3); // Recommended
1123
+ * expect('foo').to.have.lengthOf.above(2); // Not recommended
1124
+ *
1125
+ * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended
1126
+ * expect([1, 2, 3]).to.have.lengthOf.above(2); // Not recommended
1127
+ *
1128
+ * Add `.not` earlier in the chain to negate `.above`.
1129
+ *
1130
+ * expect(2).to.equal(2); // Recommended
1131
+ * expect(1).to.not.be.above(2); // Not recommended
1132
+ *
1133
+ * `.above` accepts an optional `msg` argument which is a custom error message
1134
+ * to show when the assertion fails. The message can also be given as the
1135
+ * second argument to `expect`.
1136
+ *
1137
+ * expect(1).to.be.above(2, 'nooo why fail??');
1138
+ * expect(1, 'nooo why fail??').to.be.above(2);
1139
+ *
1140
+ * The aliases `.gt` and `.greaterThan` can be used interchangeably with
1141
+ * `.above`.
1142
+ *
1143
+ * @name above
1144
+ * @alias gt
1145
+ * @alias greaterThan
1146
+ * @param {Number} n
1147
+ * @param {String} msg _optional_
1148
+ * @namespace BDD
1149
+ * @api public
1150
+ */
1151
+
1152
+ function assertAbove (n, msg) {
1153
+ if (msg) flag(this, 'message', msg);
1154
+ var obj = flag(this, 'object')
1155
+ , doLength = flag(this, 'doLength')
1156
+ , flagMsg = flag(this, 'message')
1157
+ , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
1158
+ , ssfi = flag(this, 'ssfi')
1159
+ , objType = _.type(obj).toLowerCase()
1160
+ , nType = _.type(n).toLowerCase()
1161
+ , errorMessage
1162
+ , shouldThrow = true;
1163
+
1164
+ if (doLength && objType !== 'map' && objType !== 'set') {
1165
+ new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
1166
+ }
1167
+
1168
+ if (!doLength && (objType === 'date' && nType !== 'date')) {
1169
+ errorMessage = msgPrefix + 'the argument to above must be a date';
1170
+ } else if (nType !== 'number' && (doLength || objType === 'number')) {
1171
+ errorMessage = msgPrefix + 'the argument to above must be a number';
1172
+ } else if (!doLength && (objType !== 'date' && objType !== 'number')) {
1173
+ var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
1174
+ errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
1175
+ } else {
1176
+ shouldThrow = false;
1177
+ }
1178
+
1179
+ if (shouldThrow) {
1180
+ throw new AssertionError(errorMessage, undefined, ssfi);
1181
+ }
1182
+
1183
+ if (doLength) {
1184
+ var descriptor = 'length'
1185
+ , itemsCount;
1186
+ if (objType === 'map' || objType === 'set') {
1187
+ descriptor = 'size';
1188
+ itemsCount = obj.size;
1189
+ } else {
1190
+ itemsCount = obj.length;
1191
+ }
1192
+ this.assert(
1193
+ itemsCount > n
1194
+ , 'expected #{this} to have a ' + descriptor + ' above #{exp} but got #{act}'
1195
+ , 'expected #{this} to not have a ' + descriptor + ' above #{exp}'
1196
+ , n
1197
+ , itemsCount
1198
+ );
1199
+ } else {
1200
+ this.assert(
1201
+ obj > n
1202
+ , 'expected #{this} to be above #{exp}'
1203
+ , 'expected #{this} to be at most #{exp}'
1204
+ , n
1205
+ );
1206
+ }
1207
+ }
1208
+
1209
+ Assertion.addMethod('above', assertAbove);
1210
+ Assertion.addMethod('gt', assertAbove);
1211
+ Assertion.addMethod('greaterThan', assertAbove);
1212
+
1213
+ /**
1214
+ * ### .least(n[, msg])
1215
+ *
1216
+ * Asserts that the target is a number or a date greater than or equal to the given
1217
+ * number or date `n` respectively. However, it's often best to assert that the target is equal to
1218
+ * its expected value.
1219
+ *
1220
+ * expect(2).to.equal(2); // Recommended
1221
+ * expect(2).to.be.at.least(1); // Not recommended
1222
+ * expect(2).to.be.at.least(2); // Not recommended
1223
+ *
1224
+ * Add `.lengthOf` earlier in the chain to assert that the target's `length`
1225
+ * or `size` is greater than or equal to the given number `n`.
1226
+ *
1227
+ * expect('foo').to.have.lengthOf(3); // Recommended
1228
+ * expect('foo').to.have.lengthOf.at.least(2); // Not recommended
1229
+ *
1230
+ * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended
1231
+ * expect([1, 2, 3]).to.have.lengthOf.at.least(2); // Not recommended
1232
+ *
1233
+ * Add `.not` earlier in the chain to negate `.least`.
1234
+ *
1235
+ * expect(1).to.equal(1); // Recommended
1236
+ * expect(1).to.not.be.at.least(2); // Not recommended
1237
+ *
1238
+ * `.least` accepts an optional `msg` argument which is a custom error message
1239
+ * to show when the assertion fails. The message can also be given as the
1240
+ * second argument to `expect`.
1241
+ *
1242
+ * expect(1).to.be.at.least(2, 'nooo why fail??');
1243
+ * expect(1, 'nooo why fail??').to.be.at.least(2);
1244
+ *
1245
+ * The aliases `.gte` and `.greaterThanOrEqual` can be used interchangeably with
1246
+ * `.least`.
1247
+ *
1248
+ * @name least
1249
+ * @alias gte
1250
+ * @alias greaterThanOrEqual
1251
+ * @param {Number} n
1252
+ * @param {String} msg _optional_
1253
+ * @namespace BDD
1254
+ * @api public
1255
+ */
1256
+
1257
+ function assertLeast (n, msg) {
1258
+ if (msg) flag(this, 'message', msg);
1259
+ var obj = flag(this, 'object')
1260
+ , doLength = flag(this, 'doLength')
1261
+ , flagMsg = flag(this, 'message')
1262
+ , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
1263
+ , ssfi = flag(this, 'ssfi')
1264
+ , objType = _.type(obj).toLowerCase()
1265
+ , nType = _.type(n).toLowerCase()
1266
+ , errorMessage
1267
+ , shouldThrow = true;
1268
+
1269
+ if (doLength && objType !== 'map' && objType !== 'set') {
1270
+ new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
1271
+ }
1272
+
1273
+ if (!doLength && (objType === 'date' && nType !== 'date')) {
1274
+ errorMessage = msgPrefix + 'the argument to least must be a date';
1275
+ } else if (nType !== 'number' && (doLength || objType === 'number')) {
1276
+ errorMessage = msgPrefix + 'the argument to least must be a number';
1277
+ } else if (!doLength && (objType !== 'date' && objType !== 'number')) {
1278
+ var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
1279
+ errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
1280
+ } else {
1281
+ shouldThrow = false;
1282
+ }
1283
+
1284
+ if (shouldThrow) {
1285
+ throw new AssertionError(errorMessage, undefined, ssfi);
1286
+ }
1287
+
1288
+ if (doLength) {
1289
+ var descriptor = 'length'
1290
+ , itemsCount;
1291
+ if (objType === 'map' || objType === 'set') {
1292
+ descriptor = 'size';
1293
+ itemsCount = obj.size;
1294
+ } else {
1295
+ itemsCount = obj.length;
1296
+ }
1297
+ this.assert(
1298
+ itemsCount >= n
1299
+ , 'expected #{this} to have a ' + descriptor + ' at least #{exp} but got #{act}'
1300
+ , 'expected #{this} to have a ' + descriptor + ' below #{exp}'
1301
+ , n
1302
+ , itemsCount
1303
+ );
1304
+ } else {
1305
+ this.assert(
1306
+ obj >= n
1307
+ , 'expected #{this} to be at least #{exp}'
1308
+ , 'expected #{this} to be below #{exp}'
1309
+ , n
1310
+ );
1311
+ }
1312
+ }
1313
+
1314
+ Assertion.addMethod('least', assertLeast);
1315
+ Assertion.addMethod('gte', assertLeast);
1316
+ Assertion.addMethod('greaterThanOrEqual', assertLeast);
1317
+
1318
+ /**
1319
+ * ### .below(n[, msg])
1320
+ *
1321
+ * Asserts that the target is a number or a date less than the given number or date `n` respectively.
1322
+ * However, it's often best to assert that the target is equal to its expected
1323
+ * value.
1324
+ *
1325
+ * expect(1).to.equal(1); // Recommended
1326
+ * expect(1).to.be.below(2); // Not recommended
1327
+ *
1328
+ * Add `.lengthOf` earlier in the chain to assert that the target's `length`
1329
+ * or `size` is less than the given number `n`.
1330
+ *
1331
+ * expect('foo').to.have.lengthOf(3); // Recommended
1332
+ * expect('foo').to.have.lengthOf.below(4); // Not recommended
1333
+ *
1334
+ * expect([1, 2, 3]).to.have.length(3); // Recommended
1335
+ * expect([1, 2, 3]).to.have.lengthOf.below(4); // Not recommended
1336
+ *
1337
+ * Add `.not` earlier in the chain to negate `.below`.
1338
+ *
1339
+ * expect(2).to.equal(2); // Recommended
1340
+ * expect(2).to.not.be.below(1); // Not recommended
1341
+ *
1342
+ * `.below` accepts an optional `msg` argument which is a custom error message
1343
+ * to show when the assertion fails. The message can also be given as the
1344
+ * second argument to `expect`.
1345
+ *
1346
+ * expect(2).to.be.below(1, 'nooo why fail??');
1347
+ * expect(2, 'nooo why fail??').to.be.below(1);
1348
+ *
1349
+ * The aliases `.lt` and `.lessThan` can be used interchangeably with
1350
+ * `.below`.
1351
+ *
1352
+ * @name below
1353
+ * @alias lt
1354
+ * @alias lessThan
1355
+ * @param {Number} n
1356
+ * @param {String} msg _optional_
1357
+ * @namespace BDD
1358
+ * @api public
1359
+ */
1360
+
1361
+ function assertBelow (n, msg) {
1362
+ if (msg) flag(this, 'message', msg);
1363
+ var obj = flag(this, 'object')
1364
+ , doLength = flag(this, 'doLength')
1365
+ , flagMsg = flag(this, 'message')
1366
+ , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
1367
+ , ssfi = flag(this, 'ssfi')
1368
+ , objType = _.type(obj).toLowerCase()
1369
+ , nType = _.type(n).toLowerCase()
1370
+ , errorMessage
1371
+ , shouldThrow = true;
1372
+
1373
+ if (doLength && objType !== 'map' && objType !== 'set') {
1374
+ new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
1375
+ }
1376
+
1377
+ if (!doLength && (objType === 'date' && nType !== 'date')) {
1378
+ errorMessage = msgPrefix + 'the argument to below must be a date';
1379
+ } else if (nType !== 'number' && (doLength || objType === 'number')) {
1380
+ errorMessage = msgPrefix + 'the argument to below must be a number';
1381
+ } else if (!doLength && (objType !== 'date' && objType !== 'number')) {
1382
+ var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
1383
+ errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
1384
+ } else {
1385
+ shouldThrow = false;
1386
+ }
1387
+
1388
+ if (shouldThrow) {
1389
+ throw new AssertionError(errorMessage, undefined, ssfi);
1390
+ }
1391
+
1392
+ if (doLength) {
1393
+ var descriptor = 'length'
1394
+ , itemsCount;
1395
+ if (objType === 'map' || objType === 'set') {
1396
+ descriptor = 'size';
1397
+ itemsCount = obj.size;
1398
+ } else {
1399
+ itemsCount = obj.length;
1400
+ }
1401
+ this.assert(
1402
+ itemsCount < n
1403
+ , 'expected #{this} to have a ' + descriptor + ' below #{exp} but got #{act}'
1404
+ , 'expected #{this} to not have a ' + descriptor + ' below #{exp}'
1405
+ , n
1406
+ , itemsCount
1407
+ );
1408
+ } else {
1409
+ this.assert(
1410
+ obj < n
1411
+ , 'expected #{this} to be below #{exp}'
1412
+ , 'expected #{this} to be at least #{exp}'
1413
+ , n
1414
+ );
1415
+ }
1416
+ }
1417
+
1418
+ Assertion.addMethod('below', assertBelow);
1419
+ Assertion.addMethod('lt', assertBelow);
1420
+ Assertion.addMethod('lessThan', assertBelow);
1421
+
1422
+ /**
1423
+ * ### .most(n[, msg])
1424
+ *
1425
+ * Asserts that the target is a number or a date less than or equal to the given number
1426
+ * or date `n` respectively. However, it's often best to assert that the target is equal to its
1427
+ * expected value.
1428
+ *
1429
+ * expect(1).to.equal(1); // Recommended
1430
+ * expect(1).to.be.at.most(2); // Not recommended
1431
+ * expect(1).to.be.at.most(1); // Not recommended
1432
+ *
1433
+ * Add `.lengthOf` earlier in the chain to assert that the target's `length`
1434
+ * or `size` is less than or equal to the given number `n`.
1435
+ *
1436
+ * expect('foo').to.have.lengthOf(3); // Recommended
1437
+ * expect('foo').to.have.lengthOf.at.most(4); // Not recommended
1438
+ *
1439
+ * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended
1440
+ * expect([1, 2, 3]).to.have.lengthOf.at.most(4); // Not recommended
1441
+ *
1442
+ * Add `.not` earlier in the chain to negate `.most`.
1443
+ *
1444
+ * expect(2).to.equal(2); // Recommended
1445
+ * expect(2).to.not.be.at.most(1); // Not recommended
1446
+ *
1447
+ * `.most` accepts an optional `msg` argument which is a custom error message
1448
+ * to show when the assertion fails. The message can also be given as the
1449
+ * second argument to `expect`.
1450
+ *
1451
+ * expect(2).to.be.at.most(1, 'nooo why fail??');
1452
+ * expect(2, 'nooo why fail??').to.be.at.most(1);
1453
+ *
1454
+ * The aliases `.lte` and `.lessThanOrEqual` can be used interchangeably with
1455
+ * `.most`.
1456
+ *
1457
+ * @name most
1458
+ * @alias lte
1459
+ * @alias lessThanOrEqual
1460
+ * @param {Number} n
1461
+ * @param {String} msg _optional_
1462
+ * @namespace BDD
1463
+ * @api public
1464
+ */
1465
+
1466
+ function assertMost (n, msg) {
1467
+ if (msg) flag(this, 'message', msg);
1468
+ var obj = flag(this, 'object')
1469
+ , doLength = flag(this, 'doLength')
1470
+ , flagMsg = flag(this, 'message')
1471
+ , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
1472
+ , ssfi = flag(this, 'ssfi')
1473
+ , objType = _.type(obj).toLowerCase()
1474
+ , nType = _.type(n).toLowerCase()
1475
+ , errorMessage
1476
+ , shouldThrow = true;
1477
+
1478
+ if (doLength && objType !== 'map' && objType !== 'set') {
1479
+ new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
1480
+ }
1481
+
1482
+ if (!doLength && (objType === 'date' && nType !== 'date')) {
1483
+ errorMessage = msgPrefix + 'the argument to most must be a date';
1484
+ } else if (nType !== 'number' && (doLength || objType === 'number')) {
1485
+ errorMessage = msgPrefix + 'the argument to most must be a number';
1486
+ } else if (!doLength && (objType !== 'date' && objType !== 'number')) {
1487
+ var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
1488
+ errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
1489
+ } else {
1490
+ shouldThrow = false;
1491
+ }
1492
+
1493
+ if (shouldThrow) {
1494
+ throw new AssertionError(errorMessage, undefined, ssfi);
1495
+ }
1496
+
1497
+ if (doLength) {
1498
+ var descriptor = 'length'
1499
+ , itemsCount;
1500
+ if (objType === 'map' || objType === 'set') {
1501
+ descriptor = 'size';
1502
+ itemsCount = obj.size;
1503
+ } else {
1504
+ itemsCount = obj.length;
1505
+ }
1506
+ this.assert(
1507
+ itemsCount <= n
1508
+ , 'expected #{this} to have a ' + descriptor + ' at most #{exp} but got #{act}'
1509
+ , 'expected #{this} to have a ' + descriptor + ' above #{exp}'
1510
+ , n
1511
+ , itemsCount
1512
+ );
1513
+ } else {
1514
+ this.assert(
1515
+ obj <= n
1516
+ , 'expected #{this} to be at most #{exp}'
1517
+ , 'expected #{this} to be above #{exp}'
1518
+ , n
1519
+ );
1520
+ }
1521
+ }
1522
+
1523
+ Assertion.addMethod('most', assertMost);
1524
+ Assertion.addMethod('lte', assertMost);
1525
+ Assertion.addMethod('lessThanOrEqual', assertMost);
1526
+
1527
+ /**
1528
+ * ### .within(start, finish[, msg])
1529
+ *
1530
+ * Asserts that the target is a number or a date greater than or equal to the given
1531
+ * number or date `start`, and less than or equal to the given number or date `finish` respectively.
1532
+ * However, it's often best to assert that the target is equal to its expected
1533
+ * value.
1534
+ *
1535
+ * expect(2).to.equal(2); // Recommended
1536
+ * expect(2).to.be.within(1, 3); // Not recommended
1537
+ * expect(2).to.be.within(2, 3); // Not recommended
1538
+ * expect(2).to.be.within(1, 2); // Not recommended
1539
+ *
1540
+ * Add `.lengthOf` earlier in the chain to assert that the target's `length`
1541
+ * or `size` is greater than or equal to the given number `start`, and less
1542
+ * than or equal to the given number `finish`.
1543
+ *
1544
+ * expect('foo').to.have.lengthOf(3); // Recommended
1545
+ * expect('foo').to.have.lengthOf.within(2, 4); // Not recommended
1546
+ *
1547
+ * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended
1548
+ * expect([1, 2, 3]).to.have.lengthOf.within(2, 4); // Not recommended
1549
+ *
1550
+ * Add `.not` earlier in the chain to negate `.within`.
1551
+ *
1552
+ * expect(1).to.equal(1); // Recommended
1553
+ * expect(1).to.not.be.within(2, 4); // Not recommended
1554
+ *
1555
+ * `.within` accepts an optional `msg` argument which is a custom error
1556
+ * message to show when the assertion fails. The message can also be given as
1557
+ * the second argument to `expect`.
1558
+ *
1559
+ * expect(4).to.be.within(1, 3, 'nooo why fail??');
1560
+ * expect(4, 'nooo why fail??').to.be.within(1, 3);
1561
+ *
1562
+ * @name within
1563
+ * @param {Number} start lower bound inclusive
1564
+ * @param {Number} finish upper bound inclusive
1565
+ * @param {String} msg _optional_
1566
+ * @namespace BDD
1567
+ * @api public
1568
+ */
1569
+
1570
+ Assertion.addMethod('within', function (start, finish, msg) {
1571
+ if (msg) flag(this, 'message', msg);
1572
+ var obj = flag(this, 'object')
1573
+ , doLength = flag(this, 'doLength')
1574
+ , flagMsg = flag(this, 'message')
1575
+ , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
1576
+ , ssfi = flag(this, 'ssfi')
1577
+ , objType = _.type(obj).toLowerCase()
1578
+ , startType = _.type(start).toLowerCase()
1579
+ , finishType = _.type(finish).toLowerCase()
1580
+ , errorMessage
1581
+ , shouldThrow = true
1582
+ , range = (startType === 'date' && finishType === 'date')
1583
+ ? start.toISOString() + '..' + finish.toISOString()
1584
+ : start + '..' + finish;
1585
+
1586
+ if (doLength && objType !== 'map' && objType !== 'set') {
1587
+ new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
1588
+ }
1589
+
1590
+ if (!doLength && (objType === 'date' && (startType !== 'date' || finishType !== 'date'))) {
1591
+ errorMessage = msgPrefix + 'the arguments to within must be dates';
1592
+ } else if ((startType !== 'number' || finishType !== 'number') && (doLength || objType === 'number')) {
1593
+ errorMessage = msgPrefix + 'the arguments to within must be numbers';
1594
+ } else if (!doLength && (objType !== 'date' && objType !== 'number')) {
1595
+ var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
1596
+ errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
1597
+ } else {
1598
+ shouldThrow = false;
1599
+ }
1600
+
1601
+ if (shouldThrow) {
1602
+ throw new AssertionError(errorMessage, undefined, ssfi);
1603
+ }
1604
+
1605
+ if (doLength) {
1606
+ var descriptor = 'length'
1607
+ , itemsCount;
1608
+ if (objType === 'map' || objType === 'set') {
1609
+ descriptor = 'size';
1610
+ itemsCount = obj.size;
1611
+ } else {
1612
+ itemsCount = obj.length;
1613
+ }
1614
+ this.assert(
1615
+ itemsCount >= start && itemsCount <= finish
1616
+ , 'expected #{this} to have a ' + descriptor + ' within ' + range
1617
+ , 'expected #{this} to not have a ' + descriptor + ' within ' + range
1618
+ );
1619
+ } else {
1620
+ this.assert(
1621
+ obj >= start && obj <= finish
1622
+ , 'expected #{this} to be within ' + range
1623
+ , 'expected #{this} to not be within ' + range
1624
+ );
1625
+ }
1626
+ });
1627
+
1628
+ /**
1629
+ * ### .instanceof(constructor[, msg])
1630
+ *
1631
+ * Asserts that the target is an instance of the given `constructor`.
1632
+ *
1633
+ * function Cat () { }
1634
+ *
1635
+ * expect(new Cat()).to.be.an.instanceof(Cat);
1636
+ * expect([1, 2]).to.be.an.instanceof(Array);
1637
+ *
1638
+ * Add `.not` earlier in the chain to negate `.instanceof`.
1639
+ *
1640
+ * expect({a: 1}).to.not.be.an.instanceof(Array);
1641
+ *
1642
+ * `.instanceof` accepts an optional `msg` argument which is a custom error
1643
+ * message to show when the assertion fails. The message can also be given as
1644
+ * the second argument to `expect`.
1645
+ *
1646
+ * expect(1).to.be.an.instanceof(Array, 'nooo why fail??');
1647
+ * expect(1, 'nooo why fail??').to.be.an.instanceof(Array);
1648
+ *
1649
+ * Due to limitations in ES5, `.instanceof` may not always work as expected
1650
+ * when using a transpiler such as Babel or TypeScript. In particular, it may
1651
+ * produce unexpected results when subclassing built-in object such as
1652
+ * `Array`, `Error`, and `Map`. See your transpiler's docs for details:
1653
+ *
1654
+ * - ([Babel](https://babeljs.io/docs/usage/caveats/#classes))
1655
+ * - ([TypeScript](https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work))
1656
+ *
1657
+ * The alias `.instanceOf` can be used interchangeably with `.instanceof`.
1658
+ *
1659
+ * @name instanceof
1660
+ * @param {Constructor} constructor
1661
+ * @param {String} msg _optional_
1662
+ * @alias instanceOf
1663
+ * @namespace BDD
1664
+ * @api public
1665
+ */
1666
+
1667
+ function assertInstanceOf (constructor, msg) {
1668
+ if (msg) flag(this, 'message', msg);
1669
+
1670
+ var target = flag(this, 'object')
1671
+ var ssfi = flag(this, 'ssfi');
1672
+ var flagMsg = flag(this, 'message');
1673
+
1674
+ try {
1675
+ var isInstanceOf = target instanceof constructor;
1676
+ } catch (err) {
1677
+ if (err instanceof TypeError) {
1678
+ flagMsg = flagMsg ? flagMsg + ': ' : '';
1679
+ throw new AssertionError(
1680
+ flagMsg + 'The instanceof assertion needs a constructor but '
1681
+ + _.type(constructor) + ' was given.',
1682
+ undefined,
1683
+ ssfi
1684
+ );
1685
+ }
1686
+ throw err;
1687
+ }
1688
+
1689
+ var name = _.getName(constructor);
1690
+ if (name === null) {
1691
+ name = 'an unnamed constructor';
1692
+ }
1693
+
1694
+ this.assert(
1695
+ isInstanceOf
1696
+ , 'expected #{this} to be an instance of ' + name
1697
+ , 'expected #{this} to not be an instance of ' + name
1698
+ );
1699
+ };
1700
+
1701
+ Assertion.addMethod('instanceof', assertInstanceOf);
1702
+ Assertion.addMethod('instanceOf', assertInstanceOf);
1703
+
1704
+ /**
1705
+ * ### .property(name[, val[, msg]])
1706
+ *
1707
+ * Asserts that the target has a property with the given key `name`.
1708
+ *
1709
+ * expect({a: 1}).to.have.property('a');
1710
+ *
1711
+ * When `val` is provided, `.property` also asserts that the property's value
1712
+ * is equal to the given `val`.
1713
+ *
1714
+ * expect({a: 1}).to.have.property('a', 1);
1715
+ *
1716
+ * By default, strict (`===`) equality is used. Add `.deep` earlier in the
1717
+ * chain to use deep equality instead. See the `deep-eql` project page for
1718
+ * info on the deep equality algorithm: https://github.com/chaijs/deep-eql.
1719
+ *
1720
+ * // Target object deeply (but not strictly) has property `x: {a: 1}`
1721
+ * expect({x: {a: 1}}).to.have.deep.property('x', {a: 1});
1722
+ * expect({x: {a: 1}}).to.not.have.property('x', {a: 1});
1723
+ *
1724
+ * The target's enumerable and non-enumerable properties are always included
1725
+ * in the search. By default, both own and inherited properties are included.
1726
+ * Add `.own` earlier in the chain to exclude inherited properties from the
1727
+ * search.
1728
+ *
1729
+ * Object.prototype.b = 2;
1730
+ *
1731
+ * expect({a: 1}).to.have.own.property('a');
1732
+ * expect({a: 1}).to.have.own.property('a', 1);
1733
+ * expect({a: 1}).to.have.property('b');
1734
+ * expect({a: 1}).to.not.have.own.property('b');
1735
+ *
1736
+ * `.deep` and `.own` can be combined.
1737
+ *
1738
+ * expect({x: {a: 1}}).to.have.deep.own.property('x', {a: 1});
1739
+ *
1740
+ * Add `.nested` earlier in the chain to enable dot- and bracket-notation when
1741
+ * referencing nested properties.
1742
+ *
1743
+ * expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]');
1744
+ * expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]', 'y');
1745
+ *
1746
+ * If `.` or `[]` are part of an actual property name, they can be escaped by
1747
+ * adding two backslashes before them.
1748
+ *
1749
+ * expect({'.a': {'[b]': 'x'}}).to.have.nested.property('\\.a.\\[b\\]');
1750
+ *
1751
+ * `.deep` and `.nested` can be combined.
1752
+ *
1753
+ * expect({a: {b: [{c: 3}]}})
1754
+ * .to.have.deep.nested.property('a.b[0]', {c: 3});
1755
+ *
1756
+ * `.own` and `.nested` cannot be combined.
1757
+ *
1758
+ * Add `.not` earlier in the chain to negate `.property`.
1759
+ *
1760
+ * expect({a: 1}).to.not.have.property('b');
1761
+ *
1762
+ * However, it's dangerous to negate `.property` when providing `val`. The
1763
+ * problem is that it creates uncertain expectations by asserting that the
1764
+ * target either doesn't have a property with the given key `name`, or that it
1765
+ * does have a property with the given key `name` but its value isn't equal to
1766
+ * the given `val`. It's often best to identify the exact output that's
1767
+ * expected, and then write an assertion that only accepts that exact output.
1768
+ *
1769
+ * When the target isn't expected to have a property with the given key
1770
+ * `name`, it's often best to assert exactly that.
1771
+ *
1772
+ * expect({b: 2}).to.not.have.property('a'); // Recommended
1773
+ * expect({b: 2}).to.not.have.property('a', 1); // Not recommended
1774
+ *
1775
+ * When the target is expected to have a property with the given key `name`,
1776
+ * it's often best to assert that the property has its expected value, rather
1777
+ * than asserting that it doesn't have one of many unexpected values.
1778
+ *
1779
+ * expect({a: 3}).to.have.property('a', 3); // Recommended
1780
+ * expect({a: 3}).to.not.have.property('a', 1); // Not recommended
1781
+ *
1782
+ * `.property` changes the target of any assertions that follow in the chain
1783
+ * to be the value of the property from the original target object.
1784
+ *
1785
+ * expect({a: 1}).to.have.property('a').that.is.a('number');
1786
+ *
1787
+ * `.property` accepts an optional `msg` argument which is a custom error
1788
+ * message to show when the assertion fails. The message can also be given as
1789
+ * the second argument to `expect`. When not providing `val`, only use the
1790
+ * second form.
1791
+ *
1792
+ * // Recommended
1793
+ * expect({a: 1}).to.have.property('a', 2, 'nooo why fail??');
1794
+ * expect({a: 1}, 'nooo why fail??').to.have.property('a', 2);
1795
+ * expect({a: 1}, 'nooo why fail??').to.have.property('b');
1796
+ *
1797
+ * // Not recommended
1798
+ * expect({a: 1}).to.have.property('b', undefined, 'nooo why fail??');
1799
+ *
1800
+ * The above assertion isn't the same thing as not providing `val`. Instead,
1801
+ * it's asserting that the target object has a `b` property that's equal to
1802
+ * `undefined`.
1803
+ *
1804
+ * The assertions `.ownProperty` and `.haveOwnProperty` can be used
1805
+ * interchangeably with `.own.property`.
1806
+ *
1807
+ * @name property
1808
+ * @param {String} name
1809
+ * @param {Mixed} val (optional)
1810
+ * @param {String} msg _optional_
1811
+ * @returns value of property for chaining
1812
+ * @namespace BDD
1813
+ * @api public
1814
+ */
1815
+
1816
+ function assertProperty (name, val, msg) {
1817
+ if (msg) flag(this, 'message', msg);
1818
+
1819
+ var isNested = flag(this, 'nested')
1820
+ , isOwn = flag(this, 'own')
1821
+ , flagMsg = flag(this, 'message')
1822
+ , obj = flag(this, 'object')
1823
+ , ssfi = flag(this, 'ssfi')
1824
+ , nameType = typeof name;
1825
+
1826
+ flagMsg = flagMsg ? flagMsg + ': ' : '';
1827
+
1828
+ if (isNested) {
1829
+ if (nameType !== 'string') {
1830
+ throw new AssertionError(
1831
+ flagMsg + 'the argument to property must be a string when using nested syntax',
1832
+ undefined,
1833
+ ssfi
1834
+ );
1835
+ }
1836
+ } else {
1837
+ if (nameType !== 'string' && nameType !== 'number' && nameType !== 'symbol') {
1838
+ throw new AssertionError(
1839
+ flagMsg + 'the argument to property must be a string, number, or symbol',
1840
+ undefined,
1841
+ ssfi
1842
+ );
1843
+ }
1844
+ }
1845
+
1846
+ if (isNested && isOwn) {
1847
+ throw new AssertionError(
1848
+ flagMsg + 'The "nested" and "own" flags cannot be combined.',
1849
+ undefined,
1850
+ ssfi
1851
+ );
1852
+ }
1853
+
1854
+ if (obj === null || obj === undefined) {
1855
+ throw new AssertionError(
1856
+ flagMsg + 'Target cannot be null or undefined.',
1857
+ undefined,
1858
+ ssfi
1859
+ );
1860
+ }
1861
+
1862
+ var isDeep = flag(this, 'deep')
1863
+ , negate = flag(this, 'negate')
1864
+ , pathInfo = isNested ? _.getPathInfo(obj, name) : null
1865
+ , value = isNested ? pathInfo.value : obj[name];
1866
+
1867
+ var descriptor = '';
1868
+ if (isDeep) descriptor += 'deep ';
1869
+ if (isOwn) descriptor += 'own ';
1870
+ if (isNested) descriptor += 'nested ';
1871
+ descriptor += 'property ';
1872
+
1873
+ var hasProperty;
1874
+ if (isOwn) hasProperty = Object.prototype.hasOwnProperty.call(obj, name);
1875
+ else if (isNested) hasProperty = pathInfo.exists;
1876
+ else hasProperty = _.hasProperty(obj, name);
1877
+
1878
+ // When performing a negated assertion for both name and val, merely having
1879
+ // a property with the given name isn't enough to cause the assertion to
1880
+ // fail. It must both have a property with the given name, and the value of
1881
+ // that property must equal the given val. Therefore, skip this assertion in
1882
+ // favor of the next.
1883
+ if (!negate || arguments.length === 1) {
1884
+ this.assert(
1885
+ hasProperty
1886
+ , 'expected #{this} to have ' + descriptor + _.inspect(name)
1887
+ , 'expected #{this} to not have ' + descriptor + _.inspect(name));
1888
+ }
1889
+
1890
+ if (arguments.length > 1) {
1891
+ this.assert(
1892
+ hasProperty && (isDeep ? _.eql(val, value) : val === value)
1893
+ , 'expected #{this} to have ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
1894
+ , 'expected #{this} to not have ' + descriptor + _.inspect(name) + ' of #{act}'
1895
+ , val
1896
+ , value
1897
+ );
1898
+ }
1899
+
1900
+ flag(this, 'object', value);
1901
+ }
1902
+
1903
+ Assertion.addMethod('property', assertProperty);
1904
+
1905
+ function assertOwnProperty (name, value, msg) {
1906
+ flag(this, 'own', true);
1907
+ assertProperty.apply(this, arguments);
1908
+ }
1909
+
1910
+ Assertion.addMethod('ownProperty', assertOwnProperty);
1911
+ Assertion.addMethod('haveOwnProperty', assertOwnProperty);
1912
+
1913
+ /**
1914
+ * ### .ownPropertyDescriptor(name[, descriptor[, msg]])
1915
+ *
1916
+ * Asserts that the target has its own property descriptor with the given key
1917
+ * `name`. Enumerable and non-enumerable properties are included in the
1918
+ * search.
1919
+ *
1920
+ * expect({a: 1}).to.have.ownPropertyDescriptor('a');
1921
+ *
1922
+ * When `descriptor` is provided, `.ownPropertyDescriptor` also asserts that
1923
+ * the property's descriptor is deeply equal to the given `descriptor`. See
1924
+ * the `deep-eql` project page for info on the deep equality algorithm:
1925
+ * https://github.com/chaijs/deep-eql.
1926
+ *
1927
+ * expect({a: 1}).to.have.ownPropertyDescriptor('a', {
1928
+ * configurable: true,
1929
+ * enumerable: true,
1930
+ * writable: true,
1931
+ * value: 1,
1932
+ * });
1933
+ *
1934
+ * Add `.not` earlier in the chain to negate `.ownPropertyDescriptor`.
1935
+ *
1936
+ * expect({a: 1}).to.not.have.ownPropertyDescriptor('b');
1937
+ *
1938
+ * However, it's dangerous to negate `.ownPropertyDescriptor` when providing
1939
+ * a `descriptor`. The problem is that it creates uncertain expectations by
1940
+ * asserting that the target either doesn't have a property descriptor with
1941
+ * the given key `name`, or that it does have a property descriptor with the
1942
+ * given key `name` but it’s not deeply equal to the given `descriptor`. It's
1943
+ * often best to identify the exact output that's expected, and then write an
1944
+ * assertion that only accepts that exact output.
1945
+ *
1946
+ * When the target isn't expected to have a property descriptor with the given
1947
+ * key `name`, it's often best to assert exactly that.
1948
+ *
1949
+ * // Recommended
1950
+ * expect({b: 2}).to.not.have.ownPropertyDescriptor('a');
1951
+ *
1952
+ * // Not recommended
1953
+ * expect({b: 2}).to.not.have.ownPropertyDescriptor('a', {
1954
+ * configurable: true,
1955
+ * enumerable: true,
1956
+ * writable: true,
1957
+ * value: 1,
1958
+ * });
1959
+ *
1960
+ * When the target is expected to have a property descriptor with the given
1961
+ * key `name`, it's often best to assert that the property has its expected
1962
+ * descriptor, rather than asserting that it doesn't have one of many
1963
+ * unexpected descriptors.
1964
+ *
1965
+ * // Recommended
1966
+ * expect({a: 3}).to.have.ownPropertyDescriptor('a', {
1967
+ * configurable: true,
1968
+ * enumerable: true,
1969
+ * writable: true,
1970
+ * value: 3,
1971
+ * });
1972
+ *
1973
+ * // Not recommended
1974
+ * expect({a: 3}).to.not.have.ownPropertyDescriptor('a', {
1975
+ * configurable: true,
1976
+ * enumerable: true,
1977
+ * writable: true,
1978
+ * value: 1,
1979
+ * });
1980
+ *
1981
+ * `.ownPropertyDescriptor` changes the target of any assertions that follow
1982
+ * in the chain to be the value of the property descriptor from the original
1983
+ * target object.
1984
+ *
1985
+ * expect({a: 1}).to.have.ownPropertyDescriptor('a')
1986
+ * .that.has.property('enumerable', true);
1987
+ *
1988
+ * `.ownPropertyDescriptor` accepts an optional `msg` argument which is a
1989
+ * custom error message to show when the assertion fails. The message can also
1990
+ * be given as the second argument to `expect`. When not providing
1991
+ * `descriptor`, only use the second form.
1992
+ *
1993
+ * // Recommended
1994
+ * expect({a: 1}).to.have.ownPropertyDescriptor('a', {
1995
+ * configurable: true,
1996
+ * enumerable: true,
1997
+ * writable: true,
1998
+ * value: 2,
1999
+ * }, 'nooo why fail??');
2000
+ *
2001
+ * // Recommended
2002
+ * expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('a', {
2003
+ * configurable: true,
2004
+ * enumerable: true,
2005
+ * writable: true,
2006
+ * value: 2,
2007
+ * });
2008
+ *
2009
+ * // Recommended
2010
+ * expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('b');
2011
+ *
2012
+ * // Not recommended
2013
+ * expect({a: 1})
2014
+ * .to.have.ownPropertyDescriptor('b', undefined, 'nooo why fail??');
2015
+ *
2016
+ * The above assertion isn't the same thing as not providing `descriptor`.
2017
+ * Instead, it's asserting that the target object has a `b` property
2018
+ * descriptor that's deeply equal to `undefined`.
2019
+ *
2020
+ * The alias `.haveOwnPropertyDescriptor` can be used interchangeably with
2021
+ * `.ownPropertyDescriptor`.
2022
+ *
2023
+ * @name ownPropertyDescriptor
2024
+ * @alias haveOwnPropertyDescriptor
2025
+ * @param {String} name
2026
+ * @param {Object} descriptor _optional_
2027
+ * @param {String} msg _optional_
2028
+ * @namespace BDD
2029
+ * @api public
2030
+ */
2031
+
2032
+ function assertOwnPropertyDescriptor (name, descriptor, msg) {
2033
+ if (typeof descriptor === 'string') {
2034
+ msg = descriptor;
2035
+ descriptor = null;
2036
+ }
2037
+ if (msg) flag(this, 'message', msg);
2038
+ var obj = flag(this, 'object');
2039
+ var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name);
2040
+ if (actualDescriptor && descriptor) {
2041
+ this.assert(
2042
+ _.eql(descriptor, actualDescriptor)
2043
+ , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor)
2044
+ , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor)
2045
+ , descriptor
2046
+ , actualDescriptor
2047
+ , true
2048
+ );
2049
+ } else {
2050
+ this.assert(
2051
+ actualDescriptor
2052
+ , 'expected #{this} to have an own property descriptor for ' + _.inspect(name)
2053
+ , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name)
2054
+ );
2055
+ }
2056
+ flag(this, 'object', actualDescriptor);
2057
+ }
2058
+
2059
+ Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);
2060
+ Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);
2061
+
2062
+ /**
2063
+ * ### .lengthOf(n[, msg])
2064
+ *
2065
+ * Asserts that the target's `length` or `size` is equal to the given number
2066
+ * `n`.
2067
+ *
2068
+ * expect([1, 2, 3]).to.have.lengthOf(3);
2069
+ * expect('foo').to.have.lengthOf(3);
2070
+ * expect(new Set([1, 2, 3])).to.have.lengthOf(3);
2071
+ * expect(new Map([['a', 1], ['b', 2], ['c', 3]])).to.have.lengthOf(3);
2072
+ *
2073
+ * Add `.not` earlier in the chain to negate `.lengthOf`. However, it's often
2074
+ * best to assert that the target's `length` property is equal to its expected
2075
+ * value, rather than not equal to one of many unexpected values.
2076
+ *
2077
+ * expect('foo').to.have.lengthOf(3); // Recommended
2078
+ * expect('foo').to.not.have.lengthOf(4); // Not recommended
2079
+ *
2080
+ * `.lengthOf` accepts an optional `msg` argument which is a custom error
2081
+ * message to show when the assertion fails. The message can also be given as
2082
+ * the second argument to `expect`.
2083
+ *
2084
+ * expect([1, 2, 3]).to.have.lengthOf(2, 'nooo why fail??');
2085
+ * expect([1, 2, 3], 'nooo why fail??').to.have.lengthOf(2);
2086
+ *
2087
+ * `.lengthOf` can also be used as a language chain, causing all `.above`,
2088
+ * `.below`, `.least`, `.most`, and `.within` assertions that follow in the
2089
+ * chain to use the target's `length` property as the target. However, it's
2090
+ * often best to assert that the target's `length` property is equal to its
2091
+ * expected length, rather than asserting that its `length` property falls
2092
+ * within some range of values.
2093
+ *
2094
+ * // Recommended
2095
+ * expect([1, 2, 3]).to.have.lengthOf(3);
2096
+ *
2097
+ * // Not recommended
2098
+ * expect([1, 2, 3]).to.have.lengthOf.above(2);
2099
+ * expect([1, 2, 3]).to.have.lengthOf.below(4);
2100
+ * expect([1, 2, 3]).to.have.lengthOf.at.least(3);
2101
+ * expect([1, 2, 3]).to.have.lengthOf.at.most(3);
2102
+ * expect([1, 2, 3]).to.have.lengthOf.within(2,4);
2103
+ *
2104
+ * Due to a compatibility issue, the alias `.length` can't be chained directly
2105
+ * off of an uninvoked method such as `.a`. Therefore, `.length` can't be used
2106
+ * interchangeably with `.lengthOf` in every situation. It's recommended to
2107
+ * always use `.lengthOf` instead of `.length`.
2108
+ *
2109
+ * expect([1, 2, 3]).to.have.a.length(3); // incompatible; throws error
2110
+ * expect([1, 2, 3]).to.have.a.lengthOf(3); // passes as expected
2111
+ *
2112
+ * @name lengthOf
2113
+ * @alias length
2114
+ * @param {Number} n
2115
+ * @param {String} msg _optional_
2116
+ * @namespace BDD
2117
+ * @api public
2118
+ */
2119
+
2120
+ function assertLengthChain () {
2121
+ flag(this, 'doLength', true);
2122
+ }
2123
+
2124
+ function assertLength (n, msg) {
2125
+ if (msg) flag(this, 'message', msg);
2126
+ var obj = flag(this, 'object')
2127
+ , objType = _.type(obj).toLowerCase()
2128
+ , flagMsg = flag(this, 'message')
2129
+ , ssfi = flag(this, 'ssfi')
2130
+ , descriptor = 'length'
2131
+ , itemsCount;
2132
+
2133
+ switch (objType) {
2134
+ case 'map':
2135
+ case 'set':
2136
+ descriptor = 'size';
2137
+ itemsCount = obj.size;
2138
+ break;
2139
+ default:
2140
+ new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
2141
+ itemsCount = obj.length;
2142
+ }
2143
+
2144
+ this.assert(
2145
+ itemsCount == n
2146
+ , 'expected #{this} to have a ' + descriptor + ' of #{exp} but got #{act}'
2147
+ , 'expected #{this} to not have a ' + descriptor + ' of #{act}'
2148
+ , n
2149
+ , itemsCount
2150
+ );
2151
+ }
2152
+
2153
+ Assertion.addChainableMethod('length', assertLength, assertLengthChain);
2154
+ Assertion.addChainableMethod('lengthOf', assertLength, assertLengthChain);
2155
+
2156
+ /**
2157
+ * ### .match(re[, msg])
2158
+ *
2159
+ * Asserts that the target matches the given regular expression `re`.
2160
+ *
2161
+ * expect('foobar').to.match(/^foo/);
2162
+ *
2163
+ * Add `.not` earlier in the chain to negate `.match`.
2164
+ *
2165
+ * expect('foobar').to.not.match(/taco/);
2166
+ *
2167
+ * `.match` accepts an optional `msg` argument which is a custom error message
2168
+ * to show when the assertion fails. The message can also be given as the
2169
+ * second argument to `expect`.
2170
+ *
2171
+ * expect('foobar').to.match(/taco/, 'nooo why fail??');
2172
+ * expect('foobar', 'nooo why fail??').to.match(/taco/);
2173
+ *
2174
+ * The alias `.matches` can be used interchangeably with `.match`.
2175
+ *
2176
+ * @name match
2177
+ * @alias matches
2178
+ * @param {RegExp} re
2179
+ * @param {String} msg _optional_
2180
+ * @namespace BDD
2181
+ * @api public
2182
+ */
2183
+ function assertMatch(re, msg) {
2184
+ if (msg) flag(this, 'message', msg);
2185
+ var obj = flag(this, 'object');
2186
+ this.assert(
2187
+ re.exec(obj)
2188
+ , 'expected #{this} to match ' + re
2189
+ , 'expected #{this} not to match ' + re
2190
+ );
2191
+ }
2192
+
2193
+ Assertion.addMethod('match', assertMatch);
2194
+ Assertion.addMethod('matches', assertMatch);
2195
+
2196
+ /**
2197
+ * ### .string(str[, msg])
2198
+ *
2199
+ * Asserts that the target string contains the given substring `str`.
2200
+ *
2201
+ * expect('foobar').to.have.string('bar');
2202
+ *
2203
+ * Add `.not` earlier in the chain to negate `.string`.
2204
+ *
2205
+ * expect('foobar').to.not.have.string('taco');
2206
+ *
2207
+ * `.string` accepts an optional `msg` argument which is a custom error
2208
+ * message to show when the assertion fails. The message can also be given as
2209
+ * the second argument to `expect`.
2210
+ *
2211
+ * expect('foobar').to.have.string('taco', 'nooo why fail??');
2212
+ * expect('foobar', 'nooo why fail??').to.have.string('taco');
2213
+ *
2214
+ * @name string
2215
+ * @param {String} str
2216
+ * @param {String} msg _optional_
2217
+ * @namespace BDD
2218
+ * @api public
2219
+ */
2220
+
2221
+ Assertion.addMethod('string', function (str, msg) {
2222
+ if (msg) flag(this, 'message', msg);
2223
+ var obj = flag(this, 'object')
2224
+ , flagMsg = flag(this, 'message')
2225
+ , ssfi = flag(this, 'ssfi');
2226
+ new Assertion(obj, flagMsg, ssfi, true).is.a('string');
2227
+
2228
+ this.assert(
2229
+ ~obj.indexOf(str)
2230
+ , 'expected #{this} to contain ' + _.inspect(str)
2231
+ , 'expected #{this} to not contain ' + _.inspect(str)
2232
+ );
2233
+ });
2234
+
2235
+ /**
2236
+ * ### .keys(key1[, key2[, ...]])
2237
+ *
2238
+ * Asserts that the target object, array, map, or set has the given keys. Only
2239
+ * the target's own inherited properties are included in the search.
2240
+ *
2241
+ * When the target is an object or array, keys can be provided as one or more
2242
+ * string arguments, a single array argument, or a single object argument. In
2243
+ * the latter case, only the keys in the given object matter; the values are
2244
+ * ignored.
2245
+ *
2246
+ * expect({a: 1, b: 2}).to.have.all.keys('a', 'b');
2247
+ * expect(['x', 'y']).to.have.all.keys(0, 1);
2248
+ *
2249
+ * expect({a: 1, b: 2}).to.have.all.keys(['a', 'b']);
2250
+ * expect(['x', 'y']).to.have.all.keys([0, 1]);
2251
+ *
2252
+ * expect({a: 1, b: 2}).to.have.all.keys({a: 4, b: 5}); // ignore 4 and 5
2253
+ * expect(['x', 'y']).to.have.all.keys({0: 4, 1: 5}); // ignore 4 and 5
2254
+ *
2255
+ * When the target is a map or set, each key must be provided as a separate
2256
+ * argument.
2257
+ *
2258
+ * expect(new Map([['a', 1], ['b', 2]])).to.have.all.keys('a', 'b');
2259
+ * expect(new Set(['a', 'b'])).to.have.all.keys('a', 'b');
2260
+ *
2261
+ * Because `.keys` does different things based on the target's type, it's
2262
+ * important to check the target's type before using `.keys`. See the `.a` doc
2263
+ * for info on testing a target's type.
2264
+ *
2265
+ * expect({a: 1, b: 2}).to.be.an('object').that.has.all.keys('a', 'b');
2266
+ *
2267
+ * By default, strict (`===`) equality is used to compare keys of maps and
2268
+ * sets. Add `.deep` earlier in the chain to use deep equality instead. See
2269
+ * the `deep-eql` project page for info on the deep equality algorithm:
2270
+ * https://github.com/chaijs/deep-eql.
2271
+ *
2272
+ * // Target set deeply (but not strictly) has key `{a: 1}`
2273
+ * expect(new Set([{a: 1}])).to.have.all.deep.keys([{a: 1}]);
2274
+ * expect(new Set([{a: 1}])).to.not.have.all.keys([{a: 1}]);
2275
+ *
2276
+ * By default, the target must have all of the given keys and no more. Add
2277
+ * `.any` earlier in the chain to only require that the target have at least
2278
+ * one of the given keys. Also, add `.not` earlier in the chain to negate
2279
+ * `.keys`. It's often best to add `.any` when negating `.keys`, and to use
2280
+ * `.all` when asserting `.keys` without negation.
2281
+ *
2282
+ * When negating `.keys`, `.any` is preferred because `.not.any.keys` asserts
2283
+ * exactly what's expected of the output, whereas `.not.all.keys` creates
2284
+ * uncertain expectations.
2285
+ *
2286
+ * // Recommended; asserts that target doesn't have any of the given keys
2287
+ * expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd');
2288
+ *
2289
+ * // Not recommended; asserts that target doesn't have all of the given
2290
+ * // keys but may or may not have some of them
2291
+ * expect({a: 1, b: 2}).to.not.have.all.keys('c', 'd');
2292
+ *
2293
+ * When asserting `.keys` without negation, `.all` is preferred because
2294
+ * `.all.keys` asserts exactly what's expected of the output, whereas
2295
+ * `.any.keys` creates uncertain expectations.
2296
+ *
2297
+ * // Recommended; asserts that target has all the given keys
2298
+ * expect({a: 1, b: 2}).to.have.all.keys('a', 'b');
2299
+ *
2300
+ * // Not recommended; asserts that target has at least one of the given
2301
+ * // keys but may or may not have more of them
2302
+ * expect({a: 1, b: 2}).to.have.any.keys('a', 'b');
2303
+ *
2304
+ * Note that `.all` is used by default when neither `.all` nor `.any` appear
2305
+ * earlier in the chain. However, it's often best to add `.all` anyway because
2306
+ * it improves readability.
2307
+ *
2308
+ * // Both assertions are identical
2309
+ * expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); // Recommended
2310
+ * expect({a: 1, b: 2}).to.have.keys('a', 'b'); // Not recommended
2311
+ *
2312
+ * Add `.include` earlier in the chain to require that the target's keys be a
2313
+ * superset of the expected keys, rather than identical sets.
2314
+ *
2315
+ * // Target object's keys are a superset of ['a', 'b'] but not identical
2316
+ * expect({a: 1, b: 2, c: 3}).to.include.all.keys('a', 'b');
2317
+ * expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('a', 'b');
2318
+ *
2319
+ * However, if `.any` and `.include` are combined, only the `.any` takes
2320
+ * effect. The `.include` is ignored in this case.
2321
+ *
2322
+ * // Both assertions are identical
2323
+ * expect({a: 1}).to.have.any.keys('a', 'b');
2324
+ * expect({a: 1}).to.include.any.keys('a', 'b');
2325
+ *
2326
+ * A custom error message can be given as the second argument to `expect`.
2327
+ *
2328
+ * expect({a: 1}, 'nooo why fail??').to.have.key('b');
2329
+ *
2330
+ * The alias `.key` can be used interchangeably with `.keys`.
2331
+ *
2332
+ * @name keys
2333
+ * @alias key
2334
+ * @param {...String|Array|Object} keys
2335
+ * @namespace BDD
2336
+ * @api public
2337
+ */
2338
+
2339
+ function assertKeys (keys) {
2340
+ var obj = flag(this, 'object')
2341
+ , objType = _.type(obj)
2342
+ , keysType = _.type(keys)
2343
+ , ssfi = flag(this, 'ssfi')
2344
+ , isDeep = flag(this, 'deep')
2345
+ , str
2346
+ , deepStr = ''
2347
+ , actual
2348
+ , ok = true
2349
+ , flagMsg = flag(this, 'message');
2350
+
2351
+ flagMsg = flagMsg ? flagMsg + ': ' : '';
2352
+ var mixedArgsMsg = flagMsg + 'when testing keys against an object or an array you must give a single Array|Object|String argument or multiple String arguments';
2353
+
2354
+ if (objType === 'Map' || objType === 'Set') {
2355
+ deepStr = isDeep ? 'deeply ' : '';
2356
+ actual = [];
2357
+
2358
+ // Map and Set '.keys' aren't supported in IE 11. Therefore, use .forEach.
2359
+ obj.forEach(function (val, key) { actual.push(key) });
2360
+
2361
+ if (keysType !== 'Array') {
2362
+ keys = Array.prototype.slice.call(arguments);
2363
+ }
2364
+ } else {
2365
+ actual = _.getOwnEnumerableProperties(obj);
2366
+
2367
+ switch (keysType) {
2368
+ case 'Array':
2369
+ if (arguments.length > 1) {
2370
+ throw new AssertionError(mixedArgsMsg, undefined, ssfi);
2371
+ }
2372
+ break;
2373
+ case 'Object':
2374
+ if (arguments.length > 1) {
2375
+ throw new AssertionError(mixedArgsMsg, undefined, ssfi);
2376
+ }
2377
+ keys = Object.keys(keys);
2378
+ break;
2379
+ default:
2380
+ keys = Array.prototype.slice.call(arguments);
2381
+ }
2382
+
2383
+ // Only stringify non-Symbols because Symbols would become "Symbol()"
2384
+ keys = keys.map(function (val) {
2385
+ return typeof val === 'symbol' ? val : String(val);
2386
+ });
2387
+ }
2388
+
2389
+ if (!keys.length) {
2390
+ throw new AssertionError(flagMsg + 'keys required', undefined, ssfi);
2391
+ }
2392
+
2393
+ var len = keys.length
2394
+ , any = flag(this, 'any')
2395
+ , all = flag(this, 'all')
2396
+ , expected = keys;
2397
+
2398
+ if (!any && !all) {
2399
+ all = true;
2400
+ }
2401
+
2402
+ // Has any
2403
+ if (any) {
2404
+ ok = expected.some(function(expectedKey) {
2405
+ return actual.some(function(actualKey) {
2406
+ if (isDeep) {
2407
+ return _.eql(expectedKey, actualKey);
2408
+ } else {
2409
+ return expectedKey === actualKey;
2410
+ }
2411
+ });
2412
+ });
2413
+ }
2414
+
2415
+ // Has all
2416
+ if (all) {
2417
+ ok = expected.every(function(expectedKey) {
2418
+ return actual.some(function(actualKey) {
2419
+ if (isDeep) {
2420
+ return _.eql(expectedKey, actualKey);
2421
+ } else {
2422
+ return expectedKey === actualKey;
2423
+ }
2424
+ });
2425
+ });
2426
+
2427
+ if (!flag(this, 'contains')) {
2428
+ ok = ok && keys.length == actual.length;
2429
+ }
2430
+ }
2431
+
2432
+ // Key string
2433
+ if (len > 1) {
2434
+ keys = keys.map(function(key) {
2435
+ return _.inspect(key);
2436
+ });
2437
+ var last = keys.pop();
2438
+ if (all) {
2439
+ str = keys.join(', ') + ', and ' + last;
2440
+ }
2441
+ if (any) {
2442
+ str = keys.join(', ') + ', or ' + last;
2443
+ }
2444
+ } else {
2445
+ str = _.inspect(keys[0]);
2446
+ }
2447
+
2448
+ // Form
2449
+ str = (len > 1 ? 'keys ' : 'key ') + str;
2450
+
2451
+ // Have / include
2452
+ str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
2453
+
2454
+ // Assertion
2455
+ this.assert(
2456
+ ok
2457
+ , 'expected #{this} to ' + deepStr + str
2458
+ , 'expected #{this} to not ' + deepStr + str
2459
+ , expected.slice(0).sort(_.compareByInspect)
2460
+ , actual.sort(_.compareByInspect)
2461
+ , true
2462
+ );
2463
+ }
2464
+
2465
+ Assertion.addMethod('keys', assertKeys);
2466
+ Assertion.addMethod('key', assertKeys);
2467
+
2468
+ /**
2469
+ * ### .throw([errorLike], [errMsgMatcher], [msg])
2470
+ *
2471
+ * When no arguments are provided, `.throw` invokes the target function and
2472
+ * asserts that an error is thrown.
2473
+ *
2474
+ * var badFn = function () { throw new TypeError('Illegal salmon!'); };
2475
+ *
2476
+ * expect(badFn).to.throw();
2477
+ *
2478
+ * When one argument is provided, and it's an error constructor, `.throw`
2479
+ * invokes the target function and asserts that an error is thrown that's an
2480
+ * instance of that error constructor.
2481
+ *
2482
+ * var badFn = function () { throw new TypeError('Illegal salmon!'); };
2483
+ *
2484
+ * expect(badFn).to.throw(TypeError);
2485
+ *
2486
+ * When one argument is provided, and it's an error instance, `.throw` invokes
2487
+ * the target function and asserts that an error is thrown that's strictly
2488
+ * (`===`) equal to that error instance.
2489
+ *
2490
+ * var err = new TypeError('Illegal salmon!');
2491
+ * var badFn = function () { throw err; };
2492
+ *
2493
+ * expect(badFn).to.throw(err);
2494
+ *
2495
+ * When one argument is provided, and it's a string, `.throw` invokes the
2496
+ * target function and asserts that an error is thrown with a message that
2497
+ * contains that string.
2498
+ *
2499
+ * var badFn = function () { throw new TypeError('Illegal salmon!'); };
2500
+ *
2501
+ * expect(badFn).to.throw('salmon');
2502
+ *
2503
+ * When one argument is provided, and it's a regular expression, `.throw`
2504
+ * invokes the target function and asserts that an error is thrown with a
2505
+ * message that matches that regular expression.
2506
+ *
2507
+ * var badFn = function () { throw new TypeError('Illegal salmon!'); };
2508
+ *
2509
+ * expect(badFn).to.throw(/salmon/);
2510
+ *
2511
+ * When two arguments are provided, and the first is an error instance or
2512
+ * constructor, and the second is a string or regular expression, `.throw`
2513
+ * invokes the function and asserts that an error is thrown that fulfills both
2514
+ * conditions as described above.
2515
+ *
2516
+ * var err = new TypeError('Illegal salmon!');
2517
+ * var badFn = function () { throw err; };
2518
+ *
2519
+ * expect(badFn).to.throw(TypeError, 'salmon');
2520
+ * expect(badFn).to.throw(TypeError, /salmon/);
2521
+ * expect(badFn).to.throw(err, 'salmon');
2522
+ * expect(badFn).to.throw(err, /salmon/);
2523
+ *
2524
+ * Add `.not` earlier in the chain to negate `.throw`.
2525
+ *
2526
+ * var goodFn = function () {};
2527
+ *
2528
+ * expect(goodFn).to.not.throw();
2529
+ *
2530
+ * However, it's dangerous to negate `.throw` when providing any arguments.
2531
+ * The problem is that it creates uncertain expectations by asserting that the
2532
+ * target either doesn't throw an error, or that it throws an error but of a
2533
+ * different type than the given type, or that it throws an error of the given
2534
+ * type but with a message that doesn't include the given string. It's often
2535
+ * best to identify the exact output that's expected, and then write an
2536
+ * assertion that only accepts that exact output.
2537
+ *
2538
+ * When the target isn't expected to throw an error, it's often best to assert
2539
+ * exactly that.
2540
+ *
2541
+ * var goodFn = function () {};
2542
+ *
2543
+ * expect(goodFn).to.not.throw(); // Recommended
2544
+ * expect(goodFn).to.not.throw(ReferenceError, 'x'); // Not recommended
2545
+ *
2546
+ * When the target is expected to throw an error, it's often best to assert
2547
+ * that the error is of its expected type, and has a message that includes an
2548
+ * expected string, rather than asserting that it doesn't have one of many
2549
+ * unexpected types, and doesn't have a message that includes some string.
2550
+ *
2551
+ * var badFn = function () { throw new TypeError('Illegal salmon!'); };
2552
+ *
2553
+ * expect(badFn).to.throw(TypeError, 'salmon'); // Recommended
2554
+ * expect(badFn).to.not.throw(ReferenceError, 'x'); // Not recommended
2555
+ *
2556
+ * `.throw` changes the target of any assertions that follow in the chain to
2557
+ * be the error object that's thrown.
2558
+ *
2559
+ * var err = new TypeError('Illegal salmon!');
2560
+ * err.code = 42;
2561
+ * var badFn = function () { throw err; };
2562
+ *
2563
+ * expect(badFn).to.throw(TypeError).with.property('code', 42);
2564
+ *
2565
+ * `.throw` accepts an optional `msg` argument which is a custom error message
2566
+ * to show when the assertion fails. The message can also be given as the
2567
+ * second argument to `expect`. When not providing two arguments, always use
2568
+ * the second form.
2569
+ *
2570
+ * var goodFn = function () {};
2571
+ *
2572
+ * expect(goodFn).to.throw(TypeError, 'x', 'nooo why fail??');
2573
+ * expect(goodFn, 'nooo why fail??').to.throw();
2574
+ *
2575
+ * Due to limitations in ES5, `.throw` may not always work as expected when
2576
+ * using a transpiler such as Babel or TypeScript. In particular, it may
2577
+ * produce unexpected results when subclassing the built-in `Error` object and
2578
+ * then passing the subclassed constructor to `.throw`. See your transpiler's
2579
+ * docs for details:
2580
+ *
2581
+ * - ([Babel](https://babeljs.io/docs/usage/caveats/#classes))
2582
+ * - ([TypeScript](https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work))
2583
+ *
2584
+ * Beware of some common mistakes when using the `throw` assertion. One common
2585
+ * mistake is to accidentally invoke the function yourself instead of letting
2586
+ * the `throw` assertion invoke the function for you. For example, when
2587
+ * testing if a function named `fn` throws, provide `fn` instead of `fn()` as
2588
+ * the target for the assertion.
2589
+ *
2590
+ * expect(fn).to.throw(); // Good! Tests `fn` as desired
2591
+ * expect(fn()).to.throw(); // Bad! Tests result of `fn()`, not `fn`
2592
+ *
2593
+ * If you need to assert that your function `fn` throws when passed certain
2594
+ * arguments, then wrap a call to `fn` inside of another function.
2595
+ *
2596
+ * expect(function () { fn(42); }).to.throw(); // Function expression
2597
+ * expect(() => fn(42)).to.throw(); // ES6 arrow function
2598
+ *
2599
+ * Another common mistake is to provide an object method (or any stand-alone
2600
+ * function that relies on `this`) as the target of the assertion. Doing so is
2601
+ * problematic because the `this` context will be lost when the function is
2602
+ * invoked by `.throw`; there's no way for it to know what `this` is supposed
2603
+ * to be. There are two ways around this problem. One solution is to wrap the
2604
+ * method or function call inside of another function. Another solution is to
2605
+ * use `bind`.
2606
+ *
2607
+ * expect(function () { cat.meow(); }).to.throw(); // Function expression
2608
+ * expect(() => cat.meow()).to.throw(); // ES6 arrow function
2609
+ * expect(cat.meow.bind(cat)).to.throw(); // Bind
2610
+ *
2611
+ * Finally, it's worth mentioning that it's a best practice in JavaScript to
2612
+ * only throw `Error` and derivatives of `Error` such as `ReferenceError`,
2613
+ * `TypeError`, and user-defined objects that extend `Error`. No other type of
2614
+ * value will generate a stack trace when initialized. With that said, the
2615
+ * `throw` assertion does technically support any type of value being thrown,
2616
+ * not just `Error` and its derivatives.
2617
+ *
2618
+ * The aliases `.throws` and `.Throw` can be used interchangeably with
2619
+ * `.throw`.
2620
+ *
2621
+ * @name throw
2622
+ * @alias throws
2623
+ * @alias Throw
2624
+ * @param {Error|ErrorConstructor} errorLike
2625
+ * @param {String|RegExp} errMsgMatcher error message
2626
+ * @param {String} msg _optional_
2627
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
2628
+ * @returns error for chaining (null if no error)
2629
+ * @namespace BDD
2630
+ * @api public
2631
+ */
2632
+
2633
+ function assertThrows (errorLike, errMsgMatcher, msg) {
2634
+ if (msg) flag(this, 'message', msg);
2635
+ var obj = flag(this, 'object')
2636
+ , ssfi = flag(this, 'ssfi')
2637
+ , flagMsg = flag(this, 'message')
2638
+ , negate = flag(this, 'negate') || false;
2639
+ new Assertion(obj, flagMsg, ssfi, true).is.a('function');
2640
+
2641
+ if (errorLike instanceof RegExp || typeof errorLike === 'string') {
2642
+ errMsgMatcher = errorLike;
2643
+ errorLike = null;
2644
+ }
2645
+
2646
+ var caughtErr;
2647
+ try {
2648
+ obj();
2649
+ } catch (err) {
2650
+ caughtErr = err;
2651
+ }
2652
+
2653
+ // If we have the negate flag enabled and at least one valid argument it means we do expect an error
2654
+ // but we want it to match a given set of criteria
2655
+ var everyArgIsUndefined = errorLike === undefined && errMsgMatcher === undefined;
2656
+
2657
+ // If we've got the negate flag enabled and both args, we should only fail if both aren't compatible
2658
+ // See Issue #551 and PR #683@GitHub
2659
+ var everyArgIsDefined = Boolean(errorLike && errMsgMatcher);
2660
+ var errorLikeFail = false;
2661
+ var errMsgMatcherFail = false;
2662
+
2663
+ // Checking if error was thrown
2664
+ if (everyArgIsUndefined || !everyArgIsUndefined && !negate) {
2665
+ // We need this to display results correctly according to their types
2666
+ var errorLikeString = 'an error';
2667
+ if (errorLike instanceof Error) {
2668
+ errorLikeString = '#{exp}';
2669
+ } else if (errorLike) {
2670
+ errorLikeString = _.checkError.getConstructorName(errorLike);
2671
+ }
2672
+
2673
+ this.assert(
2674
+ caughtErr
2675
+ , 'expected #{this} to throw ' + errorLikeString
2676
+ , 'expected #{this} to not throw an error but #{act} was thrown'
2677
+ , errorLike && errorLike.toString()
2678
+ , (caughtErr instanceof Error ?
2679
+ caughtErr.toString() : (typeof caughtErr === 'string' ? caughtErr : caughtErr &&
2680
+ _.checkError.getConstructorName(caughtErr)))
2681
+ );
2682
+ }
2683
+
2684
+ if (errorLike && caughtErr) {
2685
+ // We should compare instances only if `errorLike` is an instance of `Error`
2686
+ if (errorLike instanceof Error) {
2687
+ var isCompatibleInstance = _.checkError.compatibleInstance(caughtErr, errorLike);
2688
+
2689
+ if (isCompatibleInstance === negate) {
2690
+ // These checks were created to ensure we won't fail too soon when we've got both args and a negate
2691
+ // See Issue #551 and PR #683@GitHub
2692
+ if (everyArgIsDefined && negate) {
2693
+ errorLikeFail = true;
2694
+ } else {
2695
+ this.assert(
2696
+ negate
2697
+ , 'expected #{this} to throw #{exp} but #{act} was thrown'
2698
+ , 'expected #{this} to not throw #{exp}' + (caughtErr && !negate ? ' but #{act} was thrown' : '')
2699
+ , errorLike.toString()
2700
+ , caughtErr.toString()
2701
+ );
2702
+ }
2703
+ }
2704
+ }
2705
+
2706
+ var isCompatibleConstructor = _.checkError.compatibleConstructor(caughtErr, errorLike);
2707
+ if (isCompatibleConstructor === negate) {
2708
+ if (everyArgIsDefined && negate) {
2709
+ errorLikeFail = true;
2710
+ } else {
2711
+ this.assert(
2712
+ negate
2713
+ , 'expected #{this} to throw #{exp} but #{act} was thrown'
2714
+ , 'expected #{this} to not throw #{exp}' + (caughtErr ? ' but #{act} was thrown' : '')
2715
+ , (errorLike instanceof Error ? errorLike.toString() : errorLike && _.checkError.getConstructorName(errorLike))
2716
+ , (caughtErr instanceof Error ? caughtErr.toString() : caughtErr && _.checkError.getConstructorName(caughtErr))
2717
+ );
2718
+ }
2719
+ }
2720
+ }
2721
+
2722
+ if (caughtErr && errMsgMatcher !== undefined && errMsgMatcher !== null) {
2723
+ // Here we check compatible messages
2724
+ var placeholder = 'including';
2725
+ if (errMsgMatcher instanceof RegExp) {
2726
+ placeholder = 'matching'
2727
+ }
2728
+
2729
+ var isCompatibleMessage = _.checkError.compatibleMessage(caughtErr, errMsgMatcher);
2730
+ if (isCompatibleMessage === negate) {
2731
+ if (everyArgIsDefined && negate) {
2732
+ errMsgMatcherFail = true;
2733
+ } else {
2734
+ this.assert(
2735
+ negate
2736
+ , 'expected #{this} to throw error ' + placeholder + ' #{exp} but got #{act}'
2737
+ , 'expected #{this} to throw error not ' + placeholder + ' #{exp}'
2738
+ , errMsgMatcher
2739
+ , _.checkError.getMessage(caughtErr)
2740
+ );
2741
+ }
2742
+ }
2743
+ }
2744
+
2745
+ // If both assertions failed and both should've matched we throw an error
2746
+ if (errorLikeFail && errMsgMatcherFail) {
2747
+ this.assert(
2748
+ negate
2749
+ , 'expected #{this} to throw #{exp} but #{act} was thrown'
2750
+ , 'expected #{this} to not throw #{exp}' + (caughtErr ? ' but #{act} was thrown' : '')
2751
+ , (errorLike instanceof Error ? errorLike.toString() : errorLike && _.checkError.getConstructorName(errorLike))
2752
+ , (caughtErr instanceof Error ? caughtErr.toString() : caughtErr && _.checkError.getConstructorName(caughtErr))
2753
+ );
2754
+ }
2755
+
2756
+ flag(this, 'object', caughtErr);
2757
+ };
2758
+
2759
+ Assertion.addMethod('throw', assertThrows);
2760
+ Assertion.addMethod('throws', assertThrows);
2761
+ Assertion.addMethod('Throw', assertThrows);
2762
+
2763
+ /**
2764
+ * ### .respondTo(method[, msg])
2765
+ *
2766
+ * When the target is a non-function object, `.respondTo` asserts that the
2767
+ * target has a method with the given name `method`. The method can be own or
2768
+ * inherited, and it can be enumerable or non-enumerable.
2769
+ *
2770
+ * function Cat () {}
2771
+ * Cat.prototype.meow = function () {};
2772
+ *
2773
+ * expect(new Cat()).to.respondTo('meow');
2774
+ *
2775
+ * When the target is a function, `.respondTo` asserts that the target's
2776
+ * `prototype` property has a method with the given name `method`. Again, the
2777
+ * method can be own or inherited, and it can be enumerable or non-enumerable.
2778
+ *
2779
+ * function Cat () {}
2780
+ * Cat.prototype.meow = function () {};
2781
+ *
2782
+ * expect(Cat).to.respondTo('meow');
2783
+ *
2784
+ * Add `.itself` earlier in the chain to force `.respondTo` to treat the
2785
+ * target as a non-function object, even if it's a function. Thus, it asserts
2786
+ * that the target has a method with the given name `method`, rather than
2787
+ * asserting that the target's `prototype` property has a method with the
2788
+ * given name `method`.
2789
+ *
2790
+ * function Cat () {}
2791
+ * Cat.prototype.meow = function () {};
2792
+ * Cat.hiss = function () {};
2793
+ *
2794
+ * expect(Cat).itself.to.respondTo('hiss').but.not.respondTo('meow');
2795
+ *
2796
+ * When not adding `.itself`, it's important to check the target's type before
2797
+ * using `.respondTo`. See the `.a` doc for info on checking a target's type.
2798
+ *
2799
+ * function Cat () {}
2800
+ * Cat.prototype.meow = function () {};
2801
+ *
2802
+ * expect(new Cat()).to.be.an('object').that.respondsTo('meow');
2803
+ *
2804
+ * Add `.not` earlier in the chain to negate `.respondTo`.
2805
+ *
2806
+ * function Dog () {}
2807
+ * Dog.prototype.bark = function () {};
2808
+ *
2809
+ * expect(new Dog()).to.not.respondTo('meow');
2810
+ *
2811
+ * `.respondTo` accepts an optional `msg` argument which is a custom error
2812
+ * message to show when the assertion fails. The message can also be given as
2813
+ * the second argument to `expect`.
2814
+ *
2815
+ * expect({}).to.respondTo('meow', 'nooo why fail??');
2816
+ * expect({}, 'nooo why fail??').to.respondTo('meow');
2817
+ *
2818
+ * The alias `.respondsTo` can be used interchangeably with `.respondTo`.
2819
+ *
2820
+ * @name respondTo
2821
+ * @alias respondsTo
2822
+ * @param {String} method
2823
+ * @param {String} msg _optional_
2824
+ * @namespace BDD
2825
+ * @api public
2826
+ */
2827
+
2828
+ function respondTo (method, msg) {
2829
+ if (msg) flag(this, 'message', msg);
2830
+ var obj = flag(this, 'object')
2831
+ , itself = flag(this, 'itself')
2832
+ , context = ('function' === typeof obj && !itself)
2833
+ ? obj.prototype[method]
2834
+ : obj[method];
2835
+
2836
+ this.assert(
2837
+ 'function' === typeof context
2838
+ , 'expected #{this} to respond to ' + _.inspect(method)
2839
+ , 'expected #{this} to not respond to ' + _.inspect(method)
2840
+ );
2841
+ }
2842
+
2843
+ Assertion.addMethod('respondTo', respondTo);
2844
+ Assertion.addMethod('respondsTo', respondTo);
2845
+
2846
+ /**
2847
+ * ### .itself
2848
+ *
2849
+ * Forces all `.respondTo` assertions that follow in the chain to behave as if
2850
+ * the target is a non-function object, even if it's a function. Thus, it
2851
+ * causes `.respondTo` to assert that the target has a method with the given
2852
+ * name, rather than asserting that the target's `prototype` property has a
2853
+ * method with the given name.
2854
+ *
2855
+ * function Cat () {}
2856
+ * Cat.prototype.meow = function () {};
2857
+ * Cat.hiss = function () {};
2858
+ *
2859
+ * expect(Cat).itself.to.respondTo('hiss').but.not.respondTo('meow');
2860
+ *
2861
+ * @name itself
2862
+ * @namespace BDD
2863
+ * @api public
2864
+ */
2865
+
2866
+ Assertion.addProperty('itself', function () {
2867
+ flag(this, 'itself', true);
2868
+ });
2869
+
2870
+ /**
2871
+ * ### .satisfy(matcher[, msg])
2872
+ *
2873
+ * Invokes the given `matcher` function with the target being passed as the
2874
+ * first argument, and asserts that the value returned is truthy.
2875
+ *
2876
+ * expect(1).to.satisfy(function(num) {
2877
+ * return num > 0;
2878
+ * });
2879
+ *
2880
+ * Add `.not` earlier in the chain to negate `.satisfy`.
2881
+ *
2882
+ * expect(1).to.not.satisfy(function(num) {
2883
+ * return num > 2;
2884
+ * });
2885
+ *
2886
+ * `.satisfy` accepts an optional `msg` argument which is a custom error
2887
+ * message to show when the assertion fails. The message can also be given as
2888
+ * the second argument to `expect`.
2889
+ *
2890
+ * expect(1).to.satisfy(function(num) {
2891
+ * return num > 2;
2892
+ * }, 'nooo why fail??');
2893
+ *
2894
+ * expect(1, 'nooo why fail??').to.satisfy(function(num) {
2895
+ * return num > 2;
2896
+ * });
2897
+ *
2898
+ * The alias `.satisfies` can be used interchangeably with `.satisfy`.
2899
+ *
2900
+ * @name satisfy
2901
+ * @alias satisfies
2902
+ * @param {Function} matcher
2903
+ * @param {String} msg _optional_
2904
+ * @namespace BDD
2905
+ * @api public
2906
+ */
2907
+
2908
+ function satisfy (matcher, msg) {
2909
+ if (msg) flag(this, 'message', msg);
2910
+ var obj = flag(this, 'object');
2911
+ var result = matcher(obj);
2912
+ this.assert(
2913
+ result
2914
+ , 'expected #{this} to satisfy ' + _.objDisplay(matcher)
2915
+ , 'expected #{this} to not satisfy' + _.objDisplay(matcher)
2916
+ , flag(this, 'negate') ? false : true
2917
+ , result
2918
+ );
2919
+ }
2920
+
2921
+ Assertion.addMethod('satisfy', satisfy);
2922
+ Assertion.addMethod('satisfies', satisfy);
2923
+
2924
+ /**
2925
+ * ### .closeTo(expected, delta[, msg])
2926
+ *
2927
+ * Asserts that the target is a number that's within a given +/- `delta` range
2928
+ * of the given number `expected`. However, it's often best to assert that the
2929
+ * target is equal to its expected value.
2930
+ *
2931
+ * // Recommended
2932
+ * expect(1.5).to.equal(1.5);
2933
+ *
2934
+ * // Not recommended
2935
+ * expect(1.5).to.be.closeTo(1, 0.5);
2936
+ * expect(1.5).to.be.closeTo(2, 0.5);
2937
+ * expect(1.5).to.be.closeTo(1, 1);
2938
+ *
2939
+ * Add `.not` earlier in the chain to negate `.closeTo`.
2940
+ *
2941
+ * expect(1.5).to.equal(1.5); // Recommended
2942
+ * expect(1.5).to.not.be.closeTo(3, 1); // Not recommended
2943
+ *
2944
+ * `.closeTo` accepts an optional `msg` argument which is a custom error
2945
+ * message to show when the assertion fails. The message can also be given as
2946
+ * the second argument to `expect`.
2947
+ *
2948
+ * expect(1.5).to.be.closeTo(3, 1, 'nooo why fail??');
2949
+ * expect(1.5, 'nooo why fail??').to.be.closeTo(3, 1);
2950
+ *
2951
+ * The alias `.approximately` can be used interchangeably with `.closeTo`.
2952
+ *
2953
+ * @name closeTo
2954
+ * @alias approximately
2955
+ * @param {Number} expected
2956
+ * @param {Number} delta
2957
+ * @param {String} msg _optional_
2958
+ * @namespace BDD
2959
+ * @api public
2960
+ */
2961
+
2962
+ function closeTo(expected, delta, msg) {
2963
+ if (msg) flag(this, 'message', msg);
2964
+ var obj = flag(this, 'object')
2965
+ , flagMsg = flag(this, 'message')
2966
+ , ssfi = flag(this, 'ssfi');
2967
+
2968
+ new Assertion(obj, flagMsg, ssfi, true).is.a('number');
2969
+ if (typeof expected !== 'number' || typeof delta !== 'number') {
2970
+ flagMsg = flagMsg ? flagMsg + ': ' : '';
2971
+ var deltaMessage = delta === undefined ? ", and a delta is required" : "";
2972
+ throw new AssertionError(
2973
+ flagMsg + 'the arguments to closeTo or approximately must be numbers' + deltaMessage,
2974
+ undefined,
2975
+ ssfi
2976
+ );
2977
+ }
2978
+
2979
+ this.assert(
2980
+ Math.abs(obj - expected) <= delta
2981
+ , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
2982
+ , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
2983
+ );
2984
+ }
2985
+
2986
+ Assertion.addMethod('closeTo', closeTo);
2987
+ Assertion.addMethod('approximately', closeTo);
2988
+
2989
+ // Note: Duplicates are ignored if testing for inclusion instead of sameness.
2990
+ function isSubsetOf(subset, superset, cmp, contains, ordered) {
2991
+ if (!contains) {
2992
+ if (subset.length !== superset.length) return false;
2993
+ superset = superset.slice();
2994
+ }
2995
+
2996
+ return subset.every(function(elem, idx) {
2997
+ if (ordered) return cmp ? cmp(elem, superset[idx]) : elem === superset[idx];
2998
+
2999
+ if (!cmp) {
3000
+ var matchIdx = superset.indexOf(elem);
3001
+ if (matchIdx === -1) return false;
3002
+
3003
+ // Remove match from superset so not counted twice if duplicate in subset.
3004
+ if (!contains) superset.splice(matchIdx, 1);
3005
+ return true;
3006
+ }
3007
+
3008
+ return superset.some(function(elem2, matchIdx) {
3009
+ if (!cmp(elem, elem2)) return false;
3010
+
3011
+ // Remove match from superset so not counted twice if duplicate in subset.
3012
+ if (!contains) superset.splice(matchIdx, 1);
3013
+ return true;
3014
+ });
3015
+ });
3016
+ }
3017
+
3018
+ /**
3019
+ * ### .members(set[, msg])
3020
+ *
3021
+ * Asserts that the target array has the same members as the given array
3022
+ * `set`.
3023
+ *
3024
+ * expect([1, 2, 3]).to.have.members([2, 1, 3]);
3025
+ * expect([1, 2, 2]).to.have.members([2, 1, 2]);
3026
+ *
3027
+ * By default, members are compared using strict (`===`) equality. Add `.deep`
3028
+ * earlier in the chain to use deep equality instead. See the `deep-eql`
3029
+ * project page for info on the deep equality algorithm:
3030
+ * https://github.com/chaijs/deep-eql.
3031
+ *
3032
+ * // Target array deeply (but not strictly) has member `{a: 1}`
3033
+ * expect([{a: 1}]).to.have.deep.members([{a: 1}]);
3034
+ * expect([{a: 1}]).to.not.have.members([{a: 1}]);
3035
+ *
3036
+ * By default, order doesn't matter. Add `.ordered` earlier in the chain to
3037
+ * require that members appear in the same order.
3038
+ *
3039
+ * expect([1, 2, 3]).to.have.ordered.members([1, 2, 3]);
3040
+ * expect([1, 2, 3]).to.have.members([2, 1, 3])
3041
+ * .but.not.ordered.members([2, 1, 3]);
3042
+ *
3043
+ * By default, both arrays must be the same size. Add `.include` earlier in
3044
+ * the chain to require that the target's members be a superset of the
3045
+ * expected members. Note that duplicates are ignored in the subset when
3046
+ * `.include` is added.
3047
+ *
3048
+ * // Target array is a superset of [1, 2] but not identical
3049
+ * expect([1, 2, 3]).to.include.members([1, 2]);
3050
+ * expect([1, 2, 3]).to.not.have.members([1, 2]);
3051
+ *
3052
+ * // Duplicates in the subset are ignored
3053
+ * expect([1, 2, 3]).to.include.members([1, 2, 2, 2]);
3054
+ *
3055
+ * `.deep`, `.ordered`, and `.include` can all be combined. However, if
3056
+ * `.include` and `.ordered` are combined, the ordering begins at the start of
3057
+ * both arrays.
3058
+ *
3059
+ * expect([{a: 1}, {b: 2}, {c: 3}])
3060
+ * .to.include.deep.ordered.members([{a: 1}, {b: 2}])
3061
+ * .but.not.include.deep.ordered.members([{b: 2}, {c: 3}]);
3062
+ *
3063
+ * Add `.not` earlier in the chain to negate `.members`. However, it's
3064
+ * dangerous to do so. The problem is that it creates uncertain expectations
3065
+ * by asserting that the target array doesn't have all of the same members as
3066
+ * the given array `set` but may or may not have some of them. It's often best
3067
+ * to identify the exact output that's expected, and then write an assertion
3068
+ * that only accepts that exact output.
3069
+ *
3070
+ * expect([1, 2]).to.not.include(3).and.not.include(4); // Recommended
3071
+ * expect([1, 2]).to.not.have.members([3, 4]); // Not recommended
3072
+ *
3073
+ * `.members` accepts an optional `msg` argument which is a custom error
3074
+ * message to show when the assertion fails. The message can also be given as
3075
+ * the second argument to `expect`.
3076
+ *
3077
+ * expect([1, 2]).to.have.members([1, 2, 3], 'nooo why fail??');
3078
+ * expect([1, 2], 'nooo why fail??').to.have.members([1, 2, 3]);
3079
+ *
3080
+ * @name members
3081
+ * @param {Array} set
3082
+ * @param {String} msg _optional_
3083
+ * @namespace BDD
3084
+ * @api public
3085
+ */
3086
+
3087
+ Assertion.addMethod('members', function (subset, msg) {
3088
+ if (msg) flag(this, 'message', msg);
3089
+ var obj = flag(this, 'object')
3090
+ , flagMsg = flag(this, 'message')
3091
+ , ssfi = flag(this, 'ssfi');
3092
+
3093
+ new Assertion(obj, flagMsg, ssfi, true).to.be.an('array');
3094
+ new Assertion(subset, flagMsg, ssfi, true).to.be.an('array');
3095
+
3096
+ var contains = flag(this, 'contains');
3097
+ var ordered = flag(this, 'ordered');
3098
+
3099
+ var subject, failMsg, failNegateMsg;
3100
+
3101
+ if (contains) {
3102
+ subject = ordered ? 'an ordered superset' : 'a superset';
3103
+ failMsg = 'expected #{this} to be ' + subject + ' of #{exp}';
3104
+ failNegateMsg = 'expected #{this} to not be ' + subject + ' of #{exp}';
3105
+ } else {
3106
+ subject = ordered ? 'ordered members' : 'members';
3107
+ failMsg = 'expected #{this} to have the same ' + subject + ' as #{exp}';
3108
+ failNegateMsg = 'expected #{this} to not have the same ' + subject + ' as #{exp}';
3109
+ }
3110
+
3111
+ var cmp = flag(this, 'deep') ? _.eql : undefined;
3112
+
3113
+ this.assert(
3114
+ isSubsetOf(subset, obj, cmp, contains, ordered)
3115
+ , failMsg
3116
+ , failNegateMsg
3117
+ , subset
3118
+ , obj
3119
+ , true
3120
+ );
3121
+ });
3122
+
3123
+ /**
3124
+ * ### .oneOf(list[, msg])
3125
+ *
3126
+ * Asserts that the target is a member of the given array `list`. However,
3127
+ * it's often best to assert that the target is equal to its expected value.
3128
+ *
3129
+ * expect(1).to.equal(1); // Recommended
3130
+ * expect(1).to.be.oneOf([1, 2, 3]); // Not recommended
3131
+ *
3132
+ * Comparisons are performed using strict (`===`) equality.
3133
+ *
3134
+ * Add `.not` earlier in the chain to negate `.oneOf`.
3135
+ *
3136
+ * expect(1).to.equal(1); // Recommended
3137
+ * expect(1).to.not.be.oneOf([2, 3, 4]); // Not recommended
3138
+ *
3139
+ * It can also be chained with `.contain` or `.include`, which will work with
3140
+ * both arrays and strings:
3141
+ *
3142
+ * expect('Today is sunny').to.contain.oneOf(['sunny', 'cloudy'])
3143
+ * expect('Today is rainy').to.not.contain.oneOf(['sunny', 'cloudy'])
3144
+ * expect([1,2,3]).to.contain.oneOf([3,4,5])
3145
+ * expect([1,2,3]).to.not.contain.oneOf([4,5,6])
3146
+ *
3147
+ * `.oneOf` accepts an optional `msg` argument which is a custom error message
3148
+ * to show when the assertion fails. The message can also be given as the
3149
+ * second argument to `expect`.
3150
+ *
3151
+ * expect(1).to.be.oneOf([2, 3, 4], 'nooo why fail??');
3152
+ * expect(1, 'nooo why fail??').to.be.oneOf([2, 3, 4]);
3153
+ *
3154
+ * @name oneOf
3155
+ * @param {Array<*>} list
3156
+ * @param {String} msg _optional_
3157
+ * @namespace BDD
3158
+ * @api public
3159
+ */
3160
+
3161
+ function oneOf (list, msg) {
3162
+ if (msg) flag(this, 'message', msg);
3163
+ var expected = flag(this, 'object')
3164
+ , flagMsg = flag(this, 'message')
3165
+ , ssfi = flag(this, 'ssfi')
3166
+ , contains = flag(this, 'contains')
3167
+ , isDeep = flag(this, 'deep');
3168
+ new Assertion(list, flagMsg, ssfi, true).to.be.an('array');
3169
+
3170
+ if (contains) {
3171
+ this.assert(
3172
+ list.some(function(possibility) { return expected.indexOf(possibility) > -1 })
3173
+ , 'expected #{this} to contain one of #{exp}'
3174
+ , 'expected #{this} to not contain one of #{exp}'
3175
+ , list
3176
+ , expected
3177
+ );
3178
+ } else {
3179
+ if (isDeep) {
3180
+ this.assert(
3181
+ list.some(function(possibility) { return _.eql(expected, possibility) })
3182
+ , 'expected #{this} to deeply equal one of #{exp}'
3183
+ , 'expected #{this} to deeply equal one of #{exp}'
3184
+ , list
3185
+ , expected
3186
+ );
3187
+ } else {
3188
+ this.assert(
3189
+ list.indexOf(expected) > -1
3190
+ , 'expected #{this} to be one of #{exp}'
3191
+ , 'expected #{this} to not be one of #{exp}'
3192
+ , list
3193
+ , expected
3194
+ );
3195
+ }
3196
+ }
3197
+ }
3198
+
3199
+ Assertion.addMethod('oneOf', oneOf);
3200
+
3201
+ /**
3202
+ * ### .change(subject[, prop[, msg]])
3203
+ *
3204
+ * When one argument is provided, `.change` asserts that the given function
3205
+ * `subject` returns a different value when it's invoked before the target
3206
+ * function compared to when it's invoked afterward. However, it's often best
3207
+ * to assert that `subject` is equal to its expected value.
3208
+ *
3209
+ * var dots = ''
3210
+ * , addDot = function () { dots += '.'; }
3211
+ * , getDots = function () { return dots; };
3212
+ *
3213
+ * // Recommended
3214
+ * expect(getDots()).to.equal('');
3215
+ * addDot();
3216
+ * expect(getDots()).to.equal('.');
3217
+ *
3218
+ * // Not recommended
3219
+ * expect(addDot).to.change(getDots);
3220
+ *
3221
+ * When two arguments are provided, `.change` asserts that the value of the
3222
+ * given object `subject`'s `prop` property is different before invoking the
3223
+ * target function compared to afterward.
3224
+ *
3225
+ * var myObj = {dots: ''}
3226
+ * , addDot = function () { myObj.dots += '.'; };
3227
+ *
3228
+ * // Recommended
3229
+ * expect(myObj).to.have.property('dots', '');
3230
+ * addDot();
3231
+ * expect(myObj).to.have.property('dots', '.');
3232
+ *
3233
+ * // Not recommended
3234
+ * expect(addDot).to.change(myObj, 'dots');
3235
+ *
3236
+ * Strict (`===`) equality is used to compare before and after values.
3237
+ *
3238
+ * Add `.not` earlier in the chain to negate `.change`.
3239
+ *
3240
+ * var dots = ''
3241
+ * , noop = function () {}
3242
+ * , getDots = function () { return dots; };
3243
+ *
3244
+ * expect(noop).to.not.change(getDots);
3245
+ *
3246
+ * var myObj = {dots: ''}
3247
+ * , noop = function () {};
3248
+ *
3249
+ * expect(noop).to.not.change(myObj, 'dots');
3250
+ *
3251
+ * `.change` accepts an optional `msg` argument which is a custom error
3252
+ * message to show when the assertion fails. The message can also be given as
3253
+ * the second argument to `expect`. When not providing two arguments, always
3254
+ * use the second form.
3255
+ *
3256
+ * var myObj = {dots: ''}
3257
+ * , addDot = function () { myObj.dots += '.'; };
3258
+ *
3259
+ * expect(addDot).to.not.change(myObj, 'dots', 'nooo why fail??');
3260
+ *
3261
+ * var dots = ''
3262
+ * , addDot = function () { dots += '.'; }
3263
+ * , getDots = function () { return dots; };
3264
+ *
3265
+ * expect(addDot, 'nooo why fail??').to.not.change(getDots);
3266
+ *
3267
+ * `.change` also causes all `.by` assertions that follow in the chain to
3268
+ * assert how much a numeric subject was increased or decreased by. However,
3269
+ * it's dangerous to use `.change.by`. The problem is that it creates
3270
+ * uncertain expectations by asserting that the subject either increases by
3271
+ * the given delta, or that it decreases by the given delta. It's often best
3272
+ * to identify the exact output that's expected, and then write an assertion
3273
+ * that only accepts that exact output.
3274
+ *
3275
+ * var myObj = {val: 1}
3276
+ * , addTwo = function () { myObj.val += 2; }
3277
+ * , subtractTwo = function () { myObj.val -= 2; };
3278
+ *
3279
+ * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended
3280
+ * expect(addTwo).to.change(myObj, 'val').by(2); // Not recommended
3281
+ *
3282
+ * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended
3283
+ * expect(subtractTwo).to.change(myObj, 'val').by(2); // Not recommended
3284
+ *
3285
+ * The alias `.changes` can be used interchangeably with `.change`.
3286
+ *
3287
+ * @name change
3288
+ * @alias changes
3289
+ * @param {String} subject
3290
+ * @param {String} prop name _optional_
3291
+ * @param {String} msg _optional_
3292
+ * @namespace BDD
3293
+ * @api public
3294
+ */
3295
+
3296
+ function assertChanges (subject, prop, msg) {
3297
+ if (msg) flag(this, 'message', msg);
3298
+ var fn = flag(this, 'object')
3299
+ , flagMsg = flag(this, 'message')
3300
+ , ssfi = flag(this, 'ssfi');
3301
+ new Assertion(fn, flagMsg, ssfi, true).is.a('function');
3302
+
3303
+ var initial;
3304
+ if (!prop) {
3305
+ new Assertion(subject, flagMsg, ssfi, true).is.a('function');
3306
+ initial = subject();
3307
+ } else {
3308
+ new Assertion(subject, flagMsg, ssfi, true).to.have.property(prop);
3309
+ initial = subject[prop];
3310
+ }
3311
+
3312
+ fn();
3313
+
3314
+ var final = prop === undefined || prop === null ? subject() : subject[prop];
3315
+ var msgObj = prop === undefined || prop === null ? initial : '.' + prop;
3316
+
3317
+ // This gets flagged because of the .by(delta) assertion
3318
+ flag(this, 'deltaMsgObj', msgObj);
3319
+ flag(this, 'initialDeltaValue', initial);
3320
+ flag(this, 'finalDeltaValue', final);
3321
+ flag(this, 'deltaBehavior', 'change');
3322
+ flag(this, 'realDelta', final !== initial);
3323
+
3324
+ this.assert(
3325
+ initial !== final
3326
+ , 'expected ' + msgObj + ' to change'
3327
+ , 'expected ' + msgObj + ' to not change'
3328
+ );
3329
+ }
3330
+
3331
+ Assertion.addMethod('change', assertChanges);
3332
+ Assertion.addMethod('changes', assertChanges);
3333
+
3334
+ /**
3335
+ * ### .increase(subject[, prop[, msg]])
3336
+ *
3337
+ * When one argument is provided, `.increase` asserts that the given function
3338
+ * `subject` returns a greater number when it's invoked after invoking the
3339
+ * target function compared to when it's invoked beforehand. `.increase` also
3340
+ * causes all `.by` assertions that follow in the chain to assert how much
3341
+ * greater of a number is returned. It's often best to assert that the return
3342
+ * value increased by the expected amount, rather than asserting it increased
3343
+ * by any amount.
3344
+ *
3345
+ * var val = 1
3346
+ * , addTwo = function () { val += 2; }
3347
+ * , getVal = function () { return val; };
3348
+ *
3349
+ * expect(addTwo).to.increase(getVal).by(2); // Recommended
3350
+ * expect(addTwo).to.increase(getVal); // Not recommended
3351
+ *
3352
+ * When two arguments are provided, `.increase` asserts that the value of the
3353
+ * given object `subject`'s `prop` property is greater after invoking the
3354
+ * target function compared to beforehand.
3355
+ *
3356
+ * var myObj = {val: 1}
3357
+ * , addTwo = function () { myObj.val += 2; };
3358
+ *
3359
+ * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended
3360
+ * expect(addTwo).to.increase(myObj, 'val'); // Not recommended
3361
+ *
3362
+ * Add `.not` earlier in the chain to negate `.increase`. However, it's
3363
+ * dangerous to do so. The problem is that it creates uncertain expectations
3364
+ * by asserting that the subject either decreases, or that it stays the same.
3365
+ * It's often best to identify the exact output that's expected, and then
3366
+ * write an assertion that only accepts that exact output.
3367
+ *
3368
+ * When the subject is expected to decrease, it's often best to assert that it
3369
+ * decreased by the expected amount.
3370
+ *
3371
+ * var myObj = {val: 1}
3372
+ * , subtractTwo = function () { myObj.val -= 2; };
3373
+ *
3374
+ * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended
3375
+ * expect(subtractTwo).to.not.increase(myObj, 'val'); // Not recommended
3376
+ *
3377
+ * When the subject is expected to stay the same, it's often best to assert
3378
+ * exactly that.
3379
+ *
3380
+ * var myObj = {val: 1}
3381
+ * , noop = function () {};
3382
+ *
3383
+ * expect(noop).to.not.change(myObj, 'val'); // Recommended
3384
+ * expect(noop).to.not.increase(myObj, 'val'); // Not recommended
3385
+ *
3386
+ * `.increase` accepts an optional `msg` argument which is a custom error
3387
+ * message to show when the assertion fails. The message can also be given as
3388
+ * the second argument to `expect`. When not providing two arguments, always
3389
+ * use the second form.
3390
+ *
3391
+ * var myObj = {val: 1}
3392
+ * , noop = function () {};
3393
+ *
3394
+ * expect(noop).to.increase(myObj, 'val', 'nooo why fail??');
3395
+ *
3396
+ * var val = 1
3397
+ * , noop = function () {}
3398
+ * , getVal = function () { return val; };
3399
+ *
3400
+ * expect(noop, 'nooo why fail??').to.increase(getVal);
3401
+ *
3402
+ * The alias `.increases` can be used interchangeably with `.increase`.
3403
+ *
3404
+ * @name increase
3405
+ * @alias increases
3406
+ * @param {String|Function} subject
3407
+ * @param {String} prop name _optional_
3408
+ * @param {String} msg _optional_
3409
+ * @namespace BDD
3410
+ * @api public
3411
+ */
3412
+
3413
+ function assertIncreases (subject, prop, msg) {
3414
+ if (msg) flag(this, 'message', msg);
3415
+ var fn = flag(this, 'object')
3416
+ , flagMsg = flag(this, 'message')
3417
+ , ssfi = flag(this, 'ssfi');
3418
+ new Assertion(fn, flagMsg, ssfi, true).is.a('function');
3419
+
3420
+ var initial;
3421
+ if (!prop) {
3422
+ new Assertion(subject, flagMsg, ssfi, true).is.a('function');
3423
+ initial = subject();
3424
+ } else {
3425
+ new Assertion(subject, flagMsg, ssfi, true).to.have.property(prop);
3426
+ initial = subject[prop];
3427
+ }
3428
+
3429
+ // Make sure that the target is a number
3430
+ new Assertion(initial, flagMsg, ssfi, true).is.a('number');
3431
+
3432
+ fn();
3433
+
3434
+ var final = prop === undefined || prop === null ? subject() : subject[prop];
3435
+ var msgObj = prop === undefined || prop === null ? initial : '.' + prop;
3436
+
3437
+ flag(this, 'deltaMsgObj', msgObj);
3438
+ flag(this, 'initialDeltaValue', initial);
3439
+ flag(this, 'finalDeltaValue', final);
3440
+ flag(this, 'deltaBehavior', 'increase');
3441
+ flag(this, 'realDelta', final - initial);
3442
+
3443
+ this.assert(
3444
+ final - initial > 0
3445
+ , 'expected ' + msgObj + ' to increase'
3446
+ , 'expected ' + msgObj + ' to not increase'
3447
+ );
3448
+ }
3449
+
3450
+ Assertion.addMethod('increase', assertIncreases);
3451
+ Assertion.addMethod('increases', assertIncreases);
3452
+
3453
+ /**
3454
+ * ### .decrease(subject[, prop[, msg]])
3455
+ *
3456
+ * When one argument is provided, `.decrease` asserts that the given function
3457
+ * `subject` returns a lesser number when it's invoked after invoking the
3458
+ * target function compared to when it's invoked beforehand. `.decrease` also
3459
+ * causes all `.by` assertions that follow in the chain to assert how much
3460
+ * lesser of a number is returned. It's often best to assert that the return
3461
+ * value decreased by the expected amount, rather than asserting it decreased
3462
+ * by any amount.
3463
+ *
3464
+ * var val = 1
3465
+ * , subtractTwo = function () { val -= 2; }
3466
+ * , getVal = function () { return val; };
3467
+ *
3468
+ * expect(subtractTwo).to.decrease(getVal).by(2); // Recommended
3469
+ * expect(subtractTwo).to.decrease(getVal); // Not recommended
3470
+ *
3471
+ * When two arguments are provided, `.decrease` asserts that the value of the
3472
+ * given object `subject`'s `prop` property is lesser after invoking the
3473
+ * target function compared to beforehand.
3474
+ *
3475
+ * var myObj = {val: 1}
3476
+ * , subtractTwo = function () { myObj.val -= 2; };
3477
+ *
3478
+ * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended
3479
+ * expect(subtractTwo).to.decrease(myObj, 'val'); // Not recommended
3480
+ *
3481
+ * Add `.not` earlier in the chain to negate `.decrease`. However, it's
3482
+ * dangerous to do so. The problem is that it creates uncertain expectations
3483
+ * by asserting that the subject either increases, or that it stays the same.
3484
+ * It's often best to identify the exact output that's expected, and then
3485
+ * write an assertion that only accepts that exact output.
3486
+ *
3487
+ * When the subject is expected to increase, it's often best to assert that it
3488
+ * increased by the expected amount.
3489
+ *
3490
+ * var myObj = {val: 1}
3491
+ * , addTwo = function () { myObj.val += 2; };
3492
+ *
3493
+ * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended
3494
+ * expect(addTwo).to.not.decrease(myObj, 'val'); // Not recommended
3495
+ *
3496
+ * When the subject is expected to stay the same, it's often best to assert
3497
+ * exactly that.
3498
+ *
3499
+ * var myObj = {val: 1}
3500
+ * , noop = function () {};
3501
+ *
3502
+ * expect(noop).to.not.change(myObj, 'val'); // Recommended
3503
+ * expect(noop).to.not.decrease(myObj, 'val'); // Not recommended
3504
+ *
3505
+ * `.decrease` accepts an optional `msg` argument which is a custom error
3506
+ * message to show when the assertion fails. The message can also be given as
3507
+ * the second argument to `expect`. When not providing two arguments, always
3508
+ * use the second form.
3509
+ *
3510
+ * var myObj = {val: 1}
3511
+ * , noop = function () {};
3512
+ *
3513
+ * expect(noop).to.decrease(myObj, 'val', 'nooo why fail??');
3514
+ *
3515
+ * var val = 1
3516
+ * , noop = function () {}
3517
+ * , getVal = function () { return val; };
3518
+ *
3519
+ * expect(noop, 'nooo why fail??').to.decrease(getVal);
3520
+ *
3521
+ * The alias `.decreases` can be used interchangeably with `.decrease`.
3522
+ *
3523
+ * @name decrease
3524
+ * @alias decreases
3525
+ * @param {String|Function} subject
3526
+ * @param {String} prop name _optional_
3527
+ * @param {String} msg _optional_
3528
+ * @namespace BDD
3529
+ * @api public
3530
+ */
3531
+
3532
+ function assertDecreases (subject, prop, msg) {
3533
+ if (msg) flag(this, 'message', msg);
3534
+ var fn = flag(this, 'object')
3535
+ , flagMsg = flag(this, 'message')
3536
+ , ssfi = flag(this, 'ssfi');
3537
+ new Assertion(fn, flagMsg, ssfi, true).is.a('function');
3538
+
3539
+ var initial;
3540
+ if (!prop) {
3541
+ new Assertion(subject, flagMsg, ssfi, true).is.a('function');
3542
+ initial = subject();
3543
+ } else {
3544
+ new Assertion(subject, flagMsg, ssfi, true).to.have.property(prop);
3545
+ initial = subject[prop];
3546
+ }
3547
+
3548
+ // Make sure that the target is a number
3549
+ new Assertion(initial, flagMsg, ssfi, true).is.a('number');
3550
+
3551
+ fn();
3552
+
3553
+ var final = prop === undefined || prop === null ? subject() : subject[prop];
3554
+ var msgObj = prop === undefined || prop === null ? initial : '.' + prop;
3555
+
3556
+ flag(this, 'deltaMsgObj', msgObj);
3557
+ flag(this, 'initialDeltaValue', initial);
3558
+ flag(this, 'finalDeltaValue', final);
3559
+ flag(this, 'deltaBehavior', 'decrease');
3560
+ flag(this, 'realDelta', initial - final);
3561
+
3562
+ this.assert(
3563
+ final - initial < 0
3564
+ , 'expected ' + msgObj + ' to decrease'
3565
+ , 'expected ' + msgObj + ' to not decrease'
3566
+ );
3567
+ }
3568
+
3569
+ Assertion.addMethod('decrease', assertDecreases);
3570
+ Assertion.addMethod('decreases', assertDecreases);
3571
+
3572
+ /**
3573
+ * ### .by(delta[, msg])
3574
+ *
3575
+ * When following an `.increase` assertion in the chain, `.by` asserts that
3576
+ * the subject of the `.increase` assertion increased by the given `delta`.
3577
+ *
3578
+ * var myObj = {val: 1}
3579
+ * , addTwo = function () { myObj.val += 2; };
3580
+ *
3581
+ * expect(addTwo).to.increase(myObj, 'val').by(2);
3582
+ *
3583
+ * When following a `.decrease` assertion in the chain, `.by` asserts that the
3584
+ * subject of the `.decrease` assertion decreased by the given `delta`.
3585
+ *
3586
+ * var myObj = {val: 1}
3587
+ * , subtractTwo = function () { myObj.val -= 2; };
3588
+ *
3589
+ * expect(subtractTwo).to.decrease(myObj, 'val').by(2);
3590
+ *
3591
+ * When following a `.change` assertion in the chain, `.by` asserts that the
3592
+ * subject of the `.change` assertion either increased or decreased by the
3593
+ * given `delta`. However, it's dangerous to use `.change.by`. The problem is
3594
+ * that it creates uncertain expectations. It's often best to identify the
3595
+ * exact output that's expected, and then write an assertion that only accepts
3596
+ * that exact output.
3597
+ *
3598
+ * var myObj = {val: 1}
3599
+ * , addTwo = function () { myObj.val += 2; }
3600
+ * , subtractTwo = function () { myObj.val -= 2; };
3601
+ *
3602
+ * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended
3603
+ * expect(addTwo).to.change(myObj, 'val').by(2); // Not recommended
3604
+ *
3605
+ * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended
3606
+ * expect(subtractTwo).to.change(myObj, 'val').by(2); // Not recommended
3607
+ *
3608
+ * Add `.not` earlier in the chain to negate `.by`. However, it's often best
3609
+ * to assert that the subject changed by its expected delta, rather than
3610
+ * asserting that it didn't change by one of countless unexpected deltas.
3611
+ *
3612
+ * var myObj = {val: 1}
3613
+ * , addTwo = function () { myObj.val += 2; };
3614
+ *
3615
+ * // Recommended
3616
+ * expect(addTwo).to.increase(myObj, 'val').by(2);
3617
+ *
3618
+ * // Not recommended
3619
+ * expect(addTwo).to.increase(myObj, 'val').but.not.by(3);
3620
+ *
3621
+ * `.by` accepts an optional `msg` argument which is a custom error message to
3622
+ * show when the assertion fails. The message can also be given as the second
3623
+ * argument to `expect`.
3624
+ *
3625
+ * var myObj = {val: 1}
3626
+ * , addTwo = function () { myObj.val += 2; };
3627
+ *
3628
+ * expect(addTwo).to.increase(myObj, 'val').by(3, 'nooo why fail??');
3629
+ * expect(addTwo, 'nooo why fail??').to.increase(myObj, 'val').by(3);
3630
+ *
3631
+ * @name by
3632
+ * @param {Number} delta
3633
+ * @param {String} msg _optional_
3634
+ * @namespace BDD
3635
+ * @api public
3636
+ */
3637
+
3638
+ function assertDelta(delta, msg) {
3639
+ if (msg) flag(this, 'message', msg);
3640
+
3641
+ var msgObj = flag(this, 'deltaMsgObj');
3642
+ var initial = flag(this, 'initialDeltaValue');
3643
+ var final = flag(this, 'finalDeltaValue');
3644
+ var behavior = flag(this, 'deltaBehavior');
3645
+ var realDelta = flag(this, 'realDelta');
3646
+
3647
+ var expression;
3648
+ if (behavior === 'change') {
3649
+ expression = Math.abs(final - initial) === Math.abs(delta);
3650
+ } else {
3651
+ expression = realDelta === Math.abs(delta);
3652
+ }
3653
+
3654
+ this.assert(
3655
+ expression
3656
+ , 'expected ' + msgObj + ' to ' + behavior + ' by ' + delta
3657
+ , 'expected ' + msgObj + ' to not ' + behavior + ' by ' + delta
3658
+ );
3659
+ }
3660
+
3661
+ Assertion.addMethod('by', assertDelta);
3662
+
3663
+ /**
3664
+ * ### .extensible
3665
+ *
3666
+ * Asserts that the target is extensible, which means that new properties can
3667
+ * be added to it. Primitives are never extensible.
3668
+ *
3669
+ * expect({a: 1}).to.be.extensible;
3670
+ *
3671
+ * Add `.not` earlier in the chain to negate `.extensible`.
3672
+ *
3673
+ * var nonExtensibleObject = Object.preventExtensions({})
3674
+ * , sealedObject = Object.seal({})
3675
+ * , frozenObject = Object.freeze({});
3676
+ *
3677
+ * expect(nonExtensibleObject).to.not.be.extensible;
3678
+ * expect(sealedObject).to.not.be.extensible;
3679
+ * expect(frozenObject).to.not.be.extensible;
3680
+ * expect(1).to.not.be.extensible;
3681
+ *
3682
+ * A custom error message can be given as the second argument to `expect`.
3683
+ *
3684
+ * expect(1, 'nooo why fail??').to.be.extensible;
3685
+ *
3686
+ * @name extensible
3687
+ * @namespace BDD
3688
+ * @api public
3689
+ */
3690
+
3691
+ Assertion.addProperty('extensible', function() {
3692
+ var obj = flag(this, 'object');
3693
+
3694
+ // In ES5, if the argument to this method is a primitive, then it will cause a TypeError.
3695
+ // In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false.
3696
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible
3697
+ // The following provides ES6 behavior for ES5 environments.
3698
+
3699
+ var isExtensible = obj === Object(obj) && Object.isExtensible(obj);
3700
+
3701
+ this.assert(
3702
+ isExtensible
3703
+ , 'expected #{this} to be extensible'
3704
+ , 'expected #{this} to not be extensible'
3705
+ );
3706
+ });
3707
+
3708
+ /**
3709
+ * ### .sealed
3710
+ *
3711
+ * Asserts that the target is sealed, which means that new properties can't be
3712
+ * added to it, and its existing properties can't be reconfigured or deleted.
3713
+ * However, it's possible that its existing properties can still be reassigned
3714
+ * to different values. Primitives are always sealed.
3715
+ *
3716
+ * var sealedObject = Object.seal({});
3717
+ * var frozenObject = Object.freeze({});
3718
+ *
3719
+ * expect(sealedObject).to.be.sealed;
3720
+ * expect(frozenObject).to.be.sealed;
3721
+ * expect(1).to.be.sealed;
3722
+ *
3723
+ * Add `.not` earlier in the chain to negate `.sealed`.
3724
+ *
3725
+ * expect({a: 1}).to.not.be.sealed;
3726
+ *
3727
+ * A custom error message can be given as the second argument to `expect`.
3728
+ *
3729
+ * expect({a: 1}, 'nooo why fail??').to.be.sealed;
3730
+ *
3731
+ * @name sealed
3732
+ * @namespace BDD
3733
+ * @api public
3734
+ */
3735
+
3736
+ Assertion.addProperty('sealed', function() {
3737
+ var obj = flag(this, 'object');
3738
+
3739
+ // In ES5, if the argument to this method is a primitive, then it will cause a TypeError.
3740
+ // In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true.
3741
+ // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed
3742
+ // The following provides ES6 behavior for ES5 environments.
3743
+
3744
+ var isSealed = obj === Object(obj) ? Object.isSealed(obj) : true;
3745
+
3746
+ this.assert(
3747
+ isSealed
3748
+ , 'expected #{this} to be sealed'
3749
+ , 'expected #{this} to not be sealed'
3750
+ );
3751
+ });
3752
+
3753
+ /**
3754
+ * ### .frozen
3755
+ *
3756
+ * Asserts that the target is frozen, which means that new properties can't be
3757
+ * added to it, and its existing properties can't be reassigned to different
3758
+ * values, reconfigured, or deleted. Primitives are always frozen.
3759
+ *
3760
+ * var frozenObject = Object.freeze({});
3761
+ *
3762
+ * expect(frozenObject).to.be.frozen;
3763
+ * expect(1).to.be.frozen;
3764
+ *
3765
+ * Add `.not` earlier in the chain to negate `.frozen`.
3766
+ *
3767
+ * expect({a: 1}).to.not.be.frozen;
3768
+ *
3769
+ * A custom error message can be given as the second argument to `expect`.
3770
+ *
3771
+ * expect({a: 1}, 'nooo why fail??').to.be.frozen;
3772
+ *
3773
+ * @name frozen
3774
+ * @namespace BDD
3775
+ * @api public
3776
+ */
3777
+
3778
+ Assertion.addProperty('frozen', function() {
3779
+ var obj = flag(this, 'object');
3780
+
3781
+ // In ES5, if the argument to this method is a primitive, then it will cause a TypeError.
3782
+ // In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true.
3783
+ // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen
3784
+ // The following provides ES6 behavior for ES5 environments.
3785
+
3786
+ var isFrozen = obj === Object(obj) ? Object.isFrozen(obj) : true;
3787
+
3788
+ this.assert(
3789
+ isFrozen
3790
+ , 'expected #{this} to be frozen'
3791
+ , 'expected #{this} to not be frozen'
3792
+ );
3793
+ });
3794
+
3795
+ /**
3796
+ * ### .finite
3797
+ *
3798
+ * Asserts that the target is a number, and isn't `NaN` or positive/negative
3799
+ * `Infinity`.
3800
+ *
3801
+ * expect(1).to.be.finite;
3802
+ *
3803
+ * Add `.not` earlier in the chain to negate `.finite`. However, it's
3804
+ * dangerous to do so. The problem is that it creates uncertain expectations
3805
+ * by asserting that the subject either isn't a number, or that it's `NaN`, or
3806
+ * that it's positive `Infinity`, or that it's negative `Infinity`. It's often
3807
+ * best to identify the exact output that's expected, and then write an
3808
+ * assertion that only accepts that exact output.
3809
+ *
3810
+ * When the target isn't expected to be a number, it's often best to assert
3811
+ * that it's the expected type, rather than asserting that it isn't one of
3812
+ * many unexpected types.
3813
+ *
3814
+ * expect('foo').to.be.a('string'); // Recommended
3815
+ * expect('foo').to.not.be.finite; // Not recommended
3816
+ *
3817
+ * When the target is expected to be `NaN`, it's often best to assert exactly
3818
+ * that.
3819
+ *
3820
+ * expect(NaN).to.be.NaN; // Recommended
3821
+ * expect(NaN).to.not.be.finite; // Not recommended
3822
+ *
3823
+ * When the target is expected to be positive infinity, it's often best to
3824
+ * assert exactly that.
3825
+ *
3826
+ * expect(Infinity).to.equal(Infinity); // Recommended
3827
+ * expect(Infinity).to.not.be.finite; // Not recommended
3828
+ *
3829
+ * When the target is expected to be negative infinity, it's often best to
3830
+ * assert exactly that.
3831
+ *
3832
+ * expect(-Infinity).to.equal(-Infinity); // Recommended
3833
+ * expect(-Infinity).to.not.be.finite; // Not recommended
3834
+ *
3835
+ * A custom error message can be given as the second argument to `expect`.
3836
+ *
3837
+ * expect('foo', 'nooo why fail??').to.be.finite;
3838
+ *
3839
+ * @name finite
3840
+ * @namespace BDD
3841
+ * @api public
3842
+ */
3843
+
3844
+ Assertion.addProperty('finite', function(msg) {
3845
+ var obj = flag(this, 'object');
3846
+
3847
+ this.assert(
3848
+ typeof obj === 'number' && isFinite(obj)
3849
+ , 'expected #{this} to be a finite number'
3850
+ , 'expected #{this} to not be a finite number'
3851
+ );
3852
+ });
3853
+ };