chai-3.5.0/000775 000000 000000 00000000000 12652401517 012406 5ustar00rootroot000000 000000 chai-3.5.0/.gitignore000664 000000 000000 00000000246 12652401517 014400 0ustar00rootroot000000 000000 lib-cov *.seed *.log *.csv *.dat *.out *.pid *.gz pids logs results build components node_modules npm-debug.log coverage /chai.js test/auth/* !test/auth/.gitkeep chai-3.5.0/.mailmap000664 000000 000000 00000000057 12652401517 014031 0ustar00rootroot000000 000000 Domenic Denicola chai-3.5.0/.npmignore000664 000000 000000 00000000176 12652401517 014411 0ustar00rootroot000000 000000 .git* docs/ test/ support/ component.json components/ build/ lib-cov/ coverage/ .travis.yml .mailmap Makefile *.swp .DS_Store chai-3.5.0/.travis.yml000664 000000 000000 00000002010 12652401517 014510 0ustar00rootroot000000 000000 sudo: false language: node_js node_js: - 0.1 script: - make test-travisci env: global: - secure: h4eLQ2jkR1p2O5BEyscLtbNT/84LDGFnj977SeKmg3flVTpRR+ZiYb5YvIUIYfnwsw1jlr11xv0cya23nJjJA5DQjrVS1/kg4sWrLD9Gs6TTqpSNSk0HrFpxhrHZ/uSSPfV9fbyxfDLxgq72fc55WCuY5Osy1kXmsPdJX79/cOU= - secure: GXrMWPVtgAG4ICawbVdzh3R+Q+tHwYT1FcgtFbn4w7s6NZUKRdDodBM0yuDZA8pxqhQvSj/HlLjkNQI4G1wPhkHESlMWzrH5737eaJ1PHQvYV/XEnpjawQXYTOg3OYEx07mHGm+mqbAaDDHulgkeI5J4NXFMQO+JG7eYTqpotXE= - SAUCE_CONNECT_READY_FILE=/tmp/sauce-connect-ready - LOGS_DIR=/tmp/chai-build/logs deploy: provider: npm email: secure: "M9J56tqJwOxn6D3PSh8BNGac/8XjTCRGCFexN5QFl7Ha9AKnyQTy1ZAaJonMGoClBhh37Dy/89wVWmqg4NPckrD5Ej7NvwhTjVfEHusllaCROqVu5m7ijS3WKlIxM/xtBzU7SqRY41JxloP+CLKxRiKRWQJDvgwUZW7OHdmAkAY=" api_key: secure: ihzLWemQDFmsF4iQ3sS5/Wt0GQy6v15WgsxYfocpLuYWjxaAWgB4vQ3gUar8UpnE7lEFtNUOTIkPob0MSgNrFjoH2PB1sh5cW/acDE7kF7Z7hVxr8zGWkgiWXeNd08lz1mruizK1L/I0o2k/7o7zEDzShpsYSwgWfekzbJxLtC8= on: tags: true repo: chaijs/chai all_branches: true chai-3.5.0/CODE_OF_CONDUCT.md000664 000000 000000 00000005461 12652401517 015213 0ustar00rootroot000000 000000 # Contributor Code of Conduct > Read in: [Español](http://contributor-covenant.org/version/1/3/0/es/) | [Français](http://contributor-covenant.org/version/1/3/0/fr/) | [Italiano](http://contributor-covenant.org/version/1/3/0/it/) | [Magyar](http://contributor-covenant.org/version/1/3/0/hu/) | [Polskie](http://contributor-covenant.org/version/1/3/0/pl/) | [Português](http://contributor-covenant.org/version/1/3/0/pt/) | [Português do Brasil](http://contributor-covenant.org/version/1/3/0/pt_br/) As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at [INSERT EMAIL ADDRESS]. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.3.0, available at [http://contributor-covenant.org/version/1/3/0/][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/3/0/ chai-3.5.0/CONTRIBUTING.md000664 000000 000000 00000023352 12652401517 014644 0ustar00rootroot000000 000000 # Chai Contribution Guidelines We like to encourage you to contribute to the Chai.js repository. This should be as easy as possible for you but there are a few things to consider when contributing. The following guidelines for contribution should be followed if you want to submit a pull request or open an issue. Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue or assessing patches and features. #### Table of Contents - [TLDR;](#tldr) - [Contributing](#contributing) - [Bug Reports](#bugs) - [Feature Requests](#features) - [Pull Requests](#pull-requests) - [Releasing](#releasing) - [Support](#support) - [Resources](#resources) - [Core Contributors](#contributors) ## TLDR; - Creating an Issue or Pull Request requires a [GitHub](http://github.com) account. - Issue reports should be **clear**, **concise** and **reproducible**. Check to see if your issue has already been resolved in the [master]() branch or already reported in Chai's [GitHub Issue Tracker](https://github.com/chaijs/chai/issues). - Pull Requests must adhere to strict [coding style guidelines](https://github.com/chaijs/chai/wiki/Chai-Coding-Style-Guide). - In general, avoid submitting PRs for new Assertions without asking core contributors first. More than likely it would be better implemented as a plugin. - Additional support is available via the [Google Group](http://groups.google.com/group/chaijs) or on irc.freenode.net#chaijs. - **IMPORTANT**: By submitting a patch, you agree to allow the project owner to license your work under the same license as that used by the project. ## Contributing The issue tracker is the preferred channel for [bug reports](#bugs), [feature requests](#features) and [submitting pull requests](#pull-requests), but please respect the following restrictions: * Please **do not** use the issue tracker for personal support requests (use [Google Group](https://groups.google.com/forum/#!forum/chaijs) or IRC). * Please **do not** derail or troll issues. Keep the discussion on topic and respect the opinions of others ### Bug Reports A bug is a **demonstrable problem** that is caused by the code in the repository. Guidelines for bug reports: 1. **Use the GitHub issue search** — check if the issue has already been reported. 2. **Check if the issue has been fixed** — try to reproduce it using the latest `master` or development branch in the repository. 3. **Isolate the problem** — create a test case to demonstrate your issue. Provide either a repo, gist, or code sample to demonstrate you problem. A good bug report shouldn't leave others needing to chase you up for more information. Please try to be as detailed as possible in your report. What is your environment? What steps will reproduce the issue? What browser(s) and/or Node.js versions experience the problem? What would you expect to be the outcome? All these details will help people to fix any potential bugs. Example: > Short and descriptive example bug report title > > A summary of the issue and the browser/OS environment in which it occurs. If suitable, include the steps required to reproduce the bug. > > 1. This is the first step > 2. This is the second step > 3. Further steps, etc. > > `` - a link to the reduced test case OR > ```js > expect(a).to.equal('a'); > // code sample > ``` > > Any other information you want to share that is relevant to the issue being reported. This might include the lines of code that you have identified as causing the bug, and potential solutions (and your opinions on their merits). ### Feature Requests Feature requests are welcome. But take a moment to find out whether your idea fits with the scope and aims of the project. It's up to *you* to make a strong case to convince the project's developers of the merits of this feature. Please provide as much detail and context as possible. Furthermore, since Chai.js has a [robust plugin API](http://chaijs.com/guide/plugins/), we encourage you to publish **new Assertions** as plugins. If your feature is an enhancement to an **existing Assertion**, please propose your changes as an issue prior to opening a pull request. If the core Chai.js contributors feel your plugin would be better suited as a core assertion, they will invite you to open a PR in [chaijs/chai](https://github.com/chaijs/chai). ### Pull Requests - PRs for new core-assertions are advised against. - PRs for core-assertion bug fixes are always welcome. - PRs for enhancing the interfaces are always welcome. - PRs that increase test coverage are always welcome. - PRs are scrutinized for coding-style. Good pull requests - patches, improvements, new features - are a fantastic help. They should remain focused in scope and avoid containing unrelated commits. **Please ask first** before embarking on any significant pull request (e.g. implementing features, refactoring code), otherwise you risk spending a lot of time working on something that the project's developers might not want to merge into the project. Please adhere to the coding conventions used throughout a project (indentation, accurate comments, etc.) and any other requirements (such as test coverage). Please review the [Chai.js Coding Style Guide](https://github.com/chaijs/chai/wiki/Chai-Coding-Style-Guide). Follow this process if you'd like your work considered for inclusion in the project: 1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork, and configure the remotes: ```bash # Clone your fork of the repo into the current directory git clone https://github.com// # Navigate to the newly cloned directory cd # Assign the original repo to a remote called "upstream" git remote add upstream https://github.com// ``` 2. If you cloned a while ago, get the latest changes from upstream: ```bash git checkout git pull upstream ``` 3. Create a new topic branch (off the main project development branch) to contain your feature, change, or fix: ```bash git checkout -b ``` 4. Commit your changes in logical chunks. Use Git's [interactive rebase](https://help.github.com/articles/interactive-rebase) feature to tidy up your commits before making them public. 5. Run you code to make sure it works. If you're still having problems please try to run `make clean` and then test your code again. ```bash npm test # when finished running tests... git checkout chai.js ``` 6. Locally merge (or rebase) the upstream development branch into your topic branch: ```bash git pull [--rebase] upstream ``` 7. Push your topic branch up to your fork: ```bash git push origin ``` 8. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) with a clear title and description. **IMPORTANT**: By submitting a patch, you agree to allow the project owner to license your work under the same license as that used by the project. ## Releasing Releases can be **prepared** by anyone with access to the code. Simply run `make release-major`, `make release-minor`, or `make-release-patch` and it will automatically do the following: - Build chai.js - Bump the version numbers accross the project - Make a commit within git All you need to do is push the commit up and make a pull request, one of the core contributors will merge it and publish a release. ### Publishing a Release Anyone who is a core contributor (see the [Core Contributors Heading in the Readme](https://github.com/chaijs/chai#core-contributors)) can publish a release: 1. Go to te [Releases page on Github](https://github.com/chaijs/chai/releases) 2. Hit "Draft a new release" (if you can't see this, you're not a core contributor!) 3. Write human-friendly Release Notes based on changelog. - The release title is "x.x.x / YYYY-MM-DD" (where x.x.x is the version number) - If breaking changes, write migration tutorial(s) and reasoning. - Callouts for community contributions (PRs) with links to PR and contributing user. - Callouts for other fixes made by core contributors with links to issue. 4. Hit "Save Draft" and get other core contributors to check your work, or alternatively hit "Publish release" 5. That's it! ## Support ### Resources For most of the documentation you are going to want to visit [ChaiJS.com](http://chaijs.com). - [Getting Started Guide](http://chaijs.com/guide/) - [API Reference](http://chaijs.com/api/) - [Plugins](http://chaijs.com/plugins/) Alternatively, the [wiki](https://github.com/chaijs/chai/wiki) might be what you are looking for. - [Chai Coding Style Guide](https://github.com/chaijs/chai/wiki/Chai-Coding-Style-Guide) - [Third-party Resources](https://github.com/chaijs/chai/wiki/Third-Party-Resources) Or finally, you may find a core-contributor or like-minded developer in any of our support channels. - IRC: irc.freenode.org #chaijs - [Mailing List / Google Group](https://groups.google.com/forum/#!forum/chaijs) ### Core Contributors Feel free to reach out to any of the core-contributors with you questions or concerns. We will do our best to respond in a timely manner. - Jake Luer - GH: [@logicalparadox](https://github.com/logicalparadox) - TW: [@jakeluer](http://twitter.com/jakeluer) - IRC: logicalparadox - Veselin Todorov - GH: [@vesln](https://github.com/vesln/) - TW: [@vesln](http://twitter.com/vesln) - IRC: vesln - Keith Cirkel - GH: [@keithamus](https://github.com/keithamus) - TW: [@keithamus](http://twitter.com/keithamus) - IRC: keithamus chai-3.5.0/History.md000664 000000 000000 00000111353 12652401517 014375 0ustar00rootroot000000 000000 ### Note As of 3.0.0, the History.md file has been deprecated. [Please refer to the full commit logs available on GitHub](https://github.com/chaijs/chai/commits/master). --- 2.3.0 / 2015-04-26 ================== * Merge pull request #423 from ehntoo/patch-1 * Merge pull request #422 from ljharb/fix_descriptor_tests * Fix a small bug in the .null assertion docs * Use a regex to account for property ordering issues across engines. * Add `make test-firefox` * Merge pull request #417 from astorije/astorije/minimalist-typo * Remove trailing whitespaces * Fix super minor typo in an example * Merge pull request #408 from ljharb/enumerableProperty * Add `ownPropertyDescriptor` assertion. 2.2.0 / 2015-03-26 ================== * Merge pull request #405 from chaijs/deep-escape-doc-tweaks * Tweak documentation on `.deep` flag. * Merge pull request #402 from umireon/escaping-dot-should-be-taken * Documentation of escaping in `.deep` flag. * take regular expression apart * Feature: backslash-escaping in `.deep.property` * Escaping dot should be taken in deep property 2.1.2 / 2015-03-15 ================== * Merge pull request #396 from chaijs/add-keith-cirkel-contributing-md * Add Keith Cirkel to CONTRIBUTING.md * Merge pull request #395 from cjqed/386-assert-operator-no-eval * No longer using eval on assert operator #386 * Merge pull request #389 from chaijs/update-git-summary * Update `git summary` in README 2.1.1 / 2015-03-04 ================== * Merge pull request #385 from eldritch-fossicker/master * updates to reflect code style preference from @keithamus * fix indexing into array with deep propery * Merge pull request #382 from astorije/patch-2 * Merge pull request #383 from gurdiga/config-doc-wording-improvement * config.truncateThreshold docs: simpler wording * Add missing docstring for showDiff argument of assert * Merge pull request #381 from astorije/patch-1 * Add a minor precision that empty asserts on strings too. * Merge pull request #379 from dcneiner/should-primitive-fix * Primitives now use valueOf in shouldGetter 2.1.0 / 2015-02-23 ================== * Merge pull request #374 from jmm/v2.0.1 * Increment version to 2.0.1. * Merge pull request #365 from chaijs/fix-travis * Fix travis.yml deploy * Merge pull request #356 from Soviut/master * documented fail methods for expect and should interfaces * fail method added directly to expect 2.0.0 / 2015-02-09 ================== * Merge pull request #361 from gregglind/b265-keys-object * fix #359. Add `.keys(object)` * Merge pull request #359 from gregglind/b359-unexpected-keys-sort * Fix #359 keys() sorts input unexpectedly * contrib: publish release strategy and travis npm creds #337 * Merge pull request #357 from danilovaz/master * Update copyright date * Merge pull request #349 from toastynerd/add-which-chain-method * add the which chain method as per issue #347 * Merge pull request #333 from cmpolis/change-assertions * more `by` cleanup * cleaned out `.by` for #333 * Merge pull request #335 from DingoEatingFuzz/expose-util * Expose chai util through the chai object * cleanup (per notes on pr #333) * updated `change` to work w/ non-number values + tests * Merge pull request #334 from hurrymaplelad/patch-1 * Typo, the flag is called 'contains' with an 's' * updated assertion interface with `change` (#330) * added `change`,`increase`,`decrease` assertions (#330) * assert tests for `change`,`increase`,`decrease` * expect/should tests for `change`,`increase`,`decrease` * Merge pull request #328 from lo1tuma/issue-327 * Add includes and contains alias (fixes #327) * Merge pull request #325 from chasenlehara/overwriteChainableMethodDocs * Fix docs for overwriteChainableMethod parameters * Merge pull request #317 from jasonkarns/patch-2 * Merge pull request #318 from jasonkarns/patch-3 * Merge pull request #316 from jasonkarns/patch-1 * typos in docs * minor docs typo * update docs: getAllFlags -> transferFlags * Merge pull request #313 from cjqed/254-expect-any-all * Added the all and any flags for keys assertion, with all being the default behavior * Merge pull request #312 from cjqed/291-assert-same-deep-members * Changed public comment of sameDeepMemebers to be more clear * Fixes issue #291, adds assert.sameDeepMembers * Merge pull request #311 from cjqed/305-above-below-on-assert * Merge pull request #308 from prodatakey/hasproperty * Issue #305 fixed, added assert.isAbove and assert.isBelow * Fix typo * More unit tests for new utility functions * Refactor common functionality, document, test * Refactor if statement out * Small unit test fix * Handle array indexing terminating paths * Merge pull request #309 from ericdouglas/iterableEqual-couting-once * couting variables just once * Fix properties with `undefined` value pass property assertion * Merge pull request #306 from chaijs/revert-297-noopchainfunc * Revert "Allows writing lint-friendly tests" 1.10.0 / 2014-11-10 ================== * Merge pull request #297 from prodatakey/noopchainfunc * Merge pull request #300 from julienw/299-fix-getMessage-test * Fix #299: the test is defining global variables * Add a couple more unit tests * Add unit tests for chained terminating property asserts * Revise documentation wording * Add docs for function style NOOP asserts * Make the NOOP function a shared constant * Merge pull request #298 from dasilvacontin/negativeZeroLogging * why not more assertions * added test for inspecting `-0` * a more readable/simple condition statement, as pointed out by @keithamus * added check for logging negative zero * Change test to not trigger argument bug * Allows writing lint-friendly tests * readme: update contributors for 1.9.2 1.9.2 / 2014-09-29 ================== * Merge pull request #268 from charlierudolph/cr-lazyMessages * Merge pull request #269 from charlierudolph/cr-codeCleanup * Merge pull request #277 from charlierudolph/fix-doc * Merge pull request #279 from mohayonao/fix-closeTo * Merge pull request #292 from boneskull/mocha * resolves #255: upgrade mocha * Merge pull request #289 from charlierudolph/cr-dryUpCode * Dry up code * Merge pull request #275 from DrRataplan/master * assert: .closeTo() verify value's type before assertion * Rewrite pretty-printing HTML elements to prevent throwing internal errors Fixes errors occuring when using a non-native DOM implementation * Fix assert documentation * Remove unused argument * Allow messages to be functions * Merge pull request #267 from shinnn/master * Use SVG badge * Merge pull request #264 from cjthompson/keys_diff * Show diff for keys assertion 1.9.1 / 2014-03-19 ================== * deps update * util: [getActual] select actual logic now allows undefined for actual. Closes #183 * docs: [config] make public, express param type * Merge pull request #251 from romario333/threshold3 * Fix issue #166 - configurable threshold in objDisplay. * Move configuration options to config.js. * Merge pull request #233 from Empeeric/master * Merge pull request #244 from leider/fix_for_contains * Merge pull request #247 from didoarellano/typo-fixes * Fix typos * Merge pull request #245 from lfac-pt/patch-1 * Update `exports.version` to 1.9.0 * aborting loop on finding * declaring variable only once * additional test finds incomplete implementation * simplified code * fixing #239 (without changing chai.js) * ssfi as it should be * Merge pull request #228 from duncanbeevers/deep_members * Deep equality check for collection membership 1.9.0 / 2014-01-29 ================== * docs: add contributing.md #238 * assert: .throws() returns thrown error. Closes #185 * Merge pull request #232 from laconbass/assert-throws * assert: .fail() parameter mismatch. Closes #206 * Merge branch 'karma-fixes' * Add karma phantomjs launcher * Use latest karma and sauce launcher * Karma tweaks * Merge pull request #230 from jkroso/include * Merge pull request #237 from chaijs/coverage * Add coverage to npmignore * Remove lib-cov from test-travisci dependents * Remove the not longer needed lcov reporter * Test coverage with istanbul * Remove jscoverage * Remove coveralls * Merge pull request #226 from duncanbeevers/add_has * Avoid error instantiation if possible on assert.throws * Merge pull request #231 from duncanbeevers/update_copyright_year * Update Copyright notices to 2014 * handle negation correctly * add failing test case * support `{a:1,b:2}.should.include({a:1})` * Merge pull request #224 from vbardales/master * Add `has` to language chains * Merge pull request #219 from demands/overwrite_chainable * return error on throw method to chain on error properties, possibly different from message * util: store chainable behavior in a __methods object on ctx * util: code style fix * util: add overwriteChainableMethod utility (for #215) * Merge pull request #217 from demands/test_cleanup * test: make it possible to run utilities tests with --watch * makefile: change location of karma-runner bin script * Merge pull request #202 from andreineculau/patch-2 * test: add tests for throwing custom errors * Merge pull request #201 from andreineculau/patch-1 * test: updated for the new assertion errors * core: improve message for assertion errors (throw assertion) 1.8.1 / 2013-10-10 ================== * pkg: update deep-eql version 1.8.0 / 2013-09-18 ================== * test: [sauce] add a few more browsers * Merge branch 'refactor/deep-equal' * util: remove embedded deep equal utility * util: replace embedded deep equal with external module * Merge branch 'feature/karma' * docs: add sauce badge to readme [ci skip] * test: [sauce] use karma@canary to prevent timeouts * travis: only run on node 0.10 * test: [karma] use karma phantomjs runner * Merge pull request #181 from tricknotes/fix-highlight * Fix highlight for example code 1.7.2 / 2013-06-27 ================== * coverage: add coveralls badge * test: [coveralls] add coveralls api integration. testing travis-ci integration * Merge branch 'master' of github.com:chaijs/chai * Merge branch 'feature/bower' * Merge pull request #180 from tricknotes/modify-method-title * Merge pull request #179 from tricknotes/highlight-code-example * Modify method title to include argument name * Fix to highlight code example * bower: granular ignores 1.7.1 / 2013-06-24 ================== * Merge branch 'feature/bower'. #175 * bower: add json file * build: browser 1.7.0 / 2013-06-17 ================== * error: remove internal assertion error constructor * core: [assertion-error] replace internal assertion error with dep * deps: add chaijs/assertion-error@1.0.0 * docs: fix typo in source file. #174 * Merge pull request #174 from piecioshka/master * typo * Merge branch 'master' of github.com:chaijs/chai * pkg: lock mocha/mocha-phantomjs versions (for now) * Merge pull request #173 from chaijs/inspect-fix * Fix `utils.inspect` with custom object-returning inspect()s. * Merge pull request #171 from Bartvds/master * replaced tabs with 2 spaces * added assert.notOk() * Merge pull request #169 from katsgeorgeek/topics/master * Fix comparison objects. 1.6.1 / 2013-06-05 ================== * Merge pull request #168 from katsgeorgeek/topics/master * Add test for different RegExp flags. * Add test for regexp comparison. * Downgrade mocha version for fix running Phantom tests. * Fix comparison equality of two regexps. * Merge pull request #161 from brandonpayton/master * Fix documented name for assert interfaces isDefined method 1.6.0 / 2013-04-29 ================== * build: browser * assert: [(not)include] throw on incompatible haystack. Closes #142 * assert: [notInclude] add assert.notInclude. Closes #158 * browser build * makefile: force browser build on browser-test * makefile: use component for browser build * core: [assertions] remove extraneous comments * Merge branch 'master' of github.com:chaijs/chai * test: [assert] deep equal ordering * Merge pull request #153 from NickHeiner/array-assertions * giving members a no-flag assertion * Code review comments - changing syntax * Code review comments * Adding members and memberEquals assertions for checking for subsets and set equality. Implements chaijs/chai#148. * Merge pull request #140 from RubenVerborgh/function-prototype * Restore the `call` and `apply` methods of Function when adding a chainable method. * readme: 2013 * notes: migration notes for deep equal changes * test: for ever err() there must be a passing version 1.5.0 / 2013-02-03 ================== * docs: add Release Notes for non-gitlog summary of changes. * lib: update copyright to 2013 * Merge branch 'refactor/travis' * makefile: remove test-component for full test run * pkg: script test now runs make test so travis will test browser * browser: build * tests: refactor some tests to support new objDisplay output * test: [bootstrap] normalize boostrap across all test scenarios * assertions: refactor some assertions to use objDisplay instead of inspect * util: [objDisplay] normalize output of functions * makefile: refactor for full build scenarios * component: fix build bug where missing util:type file * assertions: [throw] code cleanup * Merge branch 'refactor/typeDetection' * browser: build * makefile: chai.js is .PHONY so it builds every time * test: [expect] add arguments type detection test * core/assertions: [type] (a/an) refactor to use type detection utility * util: add cross-browser type detection utility * Merge branch 'feature/component' * browser: build * component: add component.json file * makefile: refactor for fine grain control of testing scenarios * test: add mochaPhantomJS support and component test file * deps: add component and mocha-phantomjs for browser testing * ignore: update ignore files for component support * travis: run for all branches * Merge branch 'feature/showDiff' * test: [Assertion] configruable showDiff flag. Closes #132 * lib: [Assertion] add configurable showDiff flag. #132 * Merge branch 'feature/saucelabs' * Merge branch 'master' into feature/saucelabs * browser: build * support: add mocha cloud runner, client, and html test page * test: [saucelabs] add auth placeholder * deps: add mocha-cloud * Merge pull request #136 from whatthejeff/message_fix * Merge pull request #138 from timnew/master * Fix issue #137, test message existence by using message!=null rather than using message * Fixed backwards negation messages. * Merge pull request #133 from RubenVerborgh/throw * Functions throwing strings can reliably be tested. * Merge pull request #131 from RubenVerborgh/proto * Cache whether __proto__ is supported. * Use __proto__ if available. * Determine the property names to exclude beforehand. * Merge pull request #126 from RubenVerborgh/eqls * Add alias eqls for eql. * Use inherited enumerable properties in deep equality comparison. * Show inherited properties when inspecting an object. * Add new getProperties and getEnumerableProperties utils. * showDiff: force true for equal and eql 1.4.2 / 2012-12-21 ================== * browser build: (object diff support when used with mocha) #106 * test: [display] array test for mocha object diff * browser: no longer need different AssertionError constructor 1.4.1 / 2012-12-21 ================== * showDiff: force diff for equal and eql. #106 * test: [expect] type null. #122 * Merge pull request #115 from eshao/fix-assert-Throw * FIX: assert.Throw checks error type/message * TST: assert.Throw should check error type/message 1.4.0 / 2012-11-29 ================== * pre-release browser build * clean up index.js to not check for cov, revert package.json to use index.js * convert tests to use new bootstrap * refactor testing bootstrap * use spaces (not tabs). Clean up #114 * Merge pull request #114 from trantorLiu/master * Add most() (alias: lte) and least() (alias: gte) to the API with new chainers "at" and "of". * Change `main` to ./lib/chai. Fixes #28. * Merge pull request #104 from connec/deep_equals_circular_references_ * Merge pull request #109 from nnarhinen/patch-1 * Check for 'actual' type * Added support for circular references when checking deep (in)equality. 1.3.0 / 2012-10-01 ================== * browser build w/ folio >= 0.3.4. Closes #99 * add back buffer test for deep equal * do not write flags to assertion.prototype * remove buffer test from expect * browser build * improve documentation of custom error messages * Merge branch 'master' of git://github.com/Liffft/chai into Liffft-master * browser build * improved buffer deep equal checking * mocha is npm test command * Cleaning up the js style… * expect tests now include message pass-through * packaging up browser-side changes… * Increasing Throws error message verbosity * Should syntax: piping message through * Make globalShould test work in browser too. * Add a setter for `Object.prototype.should`. Closes #86. 1.2.0 / 2012-08-07 ================== * Merge branch 'feature/errmsg' * browser build * comment updates for utilities * tweak objDislay to only kick in if object inspection is too long * Merge branch 'master' into feature/errmsg * add display sample for error message refactor * first draft of error message refactor. #93 * add `closeTo` assertion to `assert` interface. Closes #89. * update folio build for better require.js handling. Closes #85 * Merge pull request #92 from paulmillr/topics/add-dom-checks * Add check for DOM objects. * browser build * Merge branch 'master' of github.com:chaijs/chai * bug - getActual not defaulting to assertion subject * Merge pull request #88 from pwnall/master * Don't inspect() assertion arguments if the assertion passes. 1.1.1 / 2012-07-09 ================== * improve commonjs support on browser build * Merge pull request #83 from tkazec/equals * Document .equals * Add .equals as an alias of .equal * remove unused browser prefix/suffix * Merge branch 'feature/folio-build' * browser build * using folio to compile * clean up makefile * early folio 0.3.x support 1.1.0 / 2012-06-26 ================== * browser build * Disable "Assertion.includeStack is false" test in IE. * Use `utils.getName` for all function inspections. * Merge pull request #80 from kilianc/closeTo * fixes #79 * browser build * expand docs to indicate change of subject for chaining. Closes #78 * add `that` chain noop * Merge branch 'bug/74' * comments on how to property use `length` as chain. Closes #74 * tests for length as chainable property. #74 * add support for `length` as chainable prop/method. * Merge branch 'bug/77' * tests for getPathValue when working with nested arrays. Closes #77 * add getPathValue support for nested arrays * browser build * fix bug for missing browser utils * compile tool aware of new folder layout * Merge branch 'refactor/1dot1' * move core assertions to own file and refactor all using utils * rearrange folder structure 1.0.4 / 2012-06-03 ================== * Merge pull request #68 from fizker/itself * Added itself chain. * simplify error inspections for cross browser compatibility * fix safari `addChainableMethod` errors. Closes #69 1.0.3 / 2012-05-27 ================== * Point Travis badge to the right place. * Make error message for eql/deep.equal more clear. * Fix .not.deep.equal. * contributors list 1.0.2 / 2012-05-26 ================== * Merge pull request #67 from chaijs/chaining-and-flags * Browser build. * Use `addChainableMethod` to get away from `__proto__` manipulation. * New `addChainableMethod` utility. * Replace `getAllFlags` with `transferFlags` utility. * browser build * test - get all flags * utility - get all flags * Add .mailmap to .npmignore. * Add a .mailmap file to fix my name in shortlogs. 1.0.1 / 2012-05-18 ================== * browser build * Fixing "an" vs. "a" grammar in type assertions. * Uniformize `assert` interface inline docs. * Don't use `instanceof` for `assert.isArray`. * Add `deep` flag for equality and property value. * Merge pull request #64 from chaijs/assertion-docs * Uniformize assertion inline docs. * Add npm-debug.log to .gitignore. * no reserved words as actuals. #62 1.0.0 / 2012-05-15 ================== * readme cleanup * browser build * utility comments * removed docs * update to package.json * docs build * comments / docs updates * plugins app cleanup * Merge pull request #61 from joliss/doc * Fix and improve documentation of assert.equal and friends * browser build * doc checkpoint - texture * Update chai-jquery link * Use defined return value of Assertion extension functions * Update utility docs 1.0.0-rc3 / 2012-05-09 ================== * Merge branch 'feature/rc3' * docs update * browser build * assert test conformity for minor refactor api * assert minor refactor * update util tests for new add/overwrite prop/method format * added chai.Assertion.add/overwrite prop/method for plugin toolbox * add/overwrite prop/method don't make assumptions about context * doc test suite * docs don't need coverage * refactor all simple chains into one forEach loop, for clean documentation * updated npm ignore * remove old docs * docs checkpoint - guide styled * Merge pull request #59 from joliss/doc * Document how to run the test suite * don't need to rebuild docs to view * dep update * docs checkpoint - api section * comment updates for docs * new doc site checkpoint - plugin directory! * Merge pull request #57 from kossnocorp/patch-1 * Fix typo: devDependancies → devDependencies * Using message flag in `getMessage` util instead of old `msg` property. * Adding self to package.json contributors. * `getMessage` shouldn't choke on null/omitted messages. * `return this` not necessary in example. * `return this` not necessary in example. * Sinon–Chai has a dash * updated plugins list for docs 1.0.0-rc2 / 2012-05-06 ================== * Merge branch 'feature/test-cov' * browser build * missing assert tests for ownProperty * appropriate assert equivalent for expect.to.have.property(key, val) * reset AssertionError to include full stack * test for plugin utilities * overwrite Property and Method now ensure chain * version notes in readme 1.0.0-rc1 / 2012-05-04 ================== * browser build (rc1) * assert match/notMatch tests * assert interface - notMatch, ownProperty, notOwnProperty, ownPropertyVal, ownPropertyNotVal * cleaner should interface export. * added chai.Assertion.prototype._obj (getter) for quick access to object flag * moved almostEqual / almostDeepEqual to stats plugin * added mocha.opts * Add test for `utils.addMethod` * Fix a typo * Add test for `utils.overwriteMethod` * Fix a typo * Browser build * Add undefined assertion * Add null assertion * Fix an issue with `mocha --watch` * travis no longer tests on node 0.4.x * removing unnecissary carbon dep * Merge branch 'feature/plugins-app' * docs build * templates for docs express app for plugin directory * express app for plugin and static serving * added web server deps * Merge pull request #54 from josher19/master * Remove old test.assert code * Use util.inspect instead of inspect for deepAlmostEqual and almostEqual * browser build * Added almostEqual and deepAlmostEqual to assert test suite. * bug - context determinants for utils * dec=0 means rounding, so assert.deepAlmostEqual({pi: 3.1416}, {pi: 3}, 0) is true * wrong travis link * readme updates for version information * travis tests 0.5.x branch as well * [bug] util `addProperty` not correctly exporting * read me version notes * browser build 1.0.0alpha1 * not using reserved words in internal assertions. #52 * version tick * clean up redundant tests * Merge branch 'refs/heads/0.6.x' * update version tag in package 1.0.0alpha1 * browser build * added utility tests to browser specs * beginning utility testing * updated utility comments * utility - overwriteMethod * utility - overwriteProperty * utility - addMethod * utility - addProperty * missing ; * contributors list update * Merge branch 'refs/heads/0.6.x-docs' into 0.6.x * Added guide link to docs. WIP * Include/contain are now both properties and methods * Add an alias annotation * Remove usless function wrapper * Fix a typo * A/an are now both properties and methods * [docs] new site homepage layout / color checkpoint * Ignore IE-specific error properties. * Fixing order of error message test. * New cross-browser `getName` util. * Fixing up `AssertionError` inheritance. * backup docs * Add doctypes * [bug] was still using `constructor.name` in `throw` assertion * [bug] flag Object.create(null) instead of new Object * [test] browser build * [refactor] all usage of Assertion.prototype.assert now uses template tags and flags * [refactor] remove Assertion.prototype.inspect for testable object inspection * [refactor] object to test is now stored in flag, with ssfi and custom message * [bug] flag util - don't return on `set` * [docs] comments for getMessage utility * [feature] getMessage * [feature] testing utilities * [refactor] flag doesn't require `call` * Make order of source files well-defined * Added support for throw(errorInstance). * Use a foolproof method of grabbing an error's name. * Removed constructor.name check from throw. * disabled stackTrack configuration tests until api is stable again * first version of line displayed error for node js (unstable) * refactor core Assertion to use flag utility for negation * added flag utility * tests for assert interface negatives. Closed #42 * added assertion negatives that were missing. #42 * Support for expected and actual parameters in assert-style error object * chai as promised - readme * Added assert.fail. Closes #40 * better error message for assert.operator. Closes #39 * [refactor] Assertion#property to use getPathValue property * added getPathValue utility helper * removed todo about browser build * version notes * version bumb 0.6.0 * browser build * [refactor] browser compile function to replace with `require('./error')' with 'require('./browser/error')' * [feature] browser uses different error.js * [refactor] error without chai.fail * Assertion & interfaces use new utils helper export * [refactor] primary export for new plugin util usage * added util index.js helper * added 2012 to copyright headers * Added DeepEqual assertions 0.5.3 / 2012-04-21 ================== * Merge branch 'refs/heads/jgonera-oldbrowsers' * browser build * fixed reserved names for old browsers in interface/assert * fixed reserved names for old browsers in interface/should * fixed: chai.js no longer contains fail() * fixed reserved names for old browsers in Assertion * Merge pull request #49 from joliss/build-order * Make order of source files well-defined * Merge pull request #43 from zzen/patch-1 * Support for expected and actual parameters in assert-style error object * chai as promised - readme 0.5.2 / 2012-03-21 ================== * browser build * Merge branch 'feature/assert-fail' * Added assert.fail. Closes #40 * Merge branch 'bug/operator-msg' * better error message for assert.operator. Closes #39 * version notes 0.5.1 / 2012-03-14 ================== * chai.fail no longer exists * Merge branch 'feature/assertdefined' * Added asset#isDefined. Closes #37. * dev docs update for Assertion#assert 0.5.0 / 2012-03-07 ================== * [bug] on inspect of reg on n 0.4.12 * Merge branch 'bug/33-throws' * Merge pull request #35 from logicalparadox/empty-object * browser build * updated #throw docs * Assertion#throw `should` tests updated * Assertion#throw `expect` tests * Should interface supports multiple throw parameters * Update Assertion#throw to support strings and type checks. * Add more tests for `empty` in `should`. * Add more tests for `empty` in `expect`. * Merge branch 'master' into empty-object * don't switch act/exp * Merge pull request #34 from logicalparadox/assert-operator * Update the compiled verison. * Add `assert.operator`. * Notes on messages. #22 * browser build * have been test * below tests * Merge branch 'feature/actexp' * browser build * remove unnecessary fail export * full support for actual/expected where relevant * Assertion.assert support expected value * clean up error * Update the compiled version. * Add object & sane arguments support to `Assertion#empty`. 0.4.2 / 2012-02-28 ================== * fix for `process` not available in browser when used via browserify. Closes #28 * Merge pull request #31 from joliss/doc * Document that "should" works in browsers other than IE * Merge pull request #30 from logicalparadox/assert-tests * Update the browser version of chai. * Update `assert.doesNotThrow` test in order to check the use case when type is a string. * Add test for `assert.ifError`. * Falsey -> falsy. * Full coverage for `assert.throws` and `assert.doesNotThrow`. * Add test for `assert.doesNotThrow`. * Add test for `assert.throws`. * Add test for `assert.length`. * Add test for `assert.include`. * Add test for `assert.isBoolean`. * Fix the implementation of `assert.isNumber`. * Add test for `assert.isNumber`. * Add test for `assert.isString`. * Add test for `assert.isArray`. * Add test for `assert.isUndefined`. * Add test for `assert.isNotNull`. * Fix `assert.isNotNull` implementation. * Fix `assert.isNull` implementation. * Add test for `assert.isNull`. * Add test for `assert.notDeepEqual`. * Add test for `assert.deepEqual`. * Add test for `assert.notStrictEqual`. * Add test for `assert.strictEqual`. * Add test for `assert.notEqual`. 0.4.1 / 2012-02-26 ================== * Merge pull request #27 from logicalparadox/type-fix * Update the browser version. * Add should tests for type checks. * Add function type check test. * Add more type checks tests. * Add test for `new Number` type check. * Fix type of actual checks. 0.4.0 / 2012-02-25 ================== * docs and readme for upcoming 0.4.0 * docs generated * putting coverage and tests for docs in docs/out/support * make docs * makefile copy necessary resources for tests in docs * rename configuration test * Merge pull request #21 from logicalparadox/close-to * Update the browser version. * Update `closeTo()` docs. * Add `Assertion.closeTo()` method. * Add `.closeTo()` should test. * Add `.closeTo()` expect test. * Merge pull request #20 from logicalparadox/satisfy * Update the browser version. * `..` -> `()` in `.satisfy()` should test. * Update example for `.satisfy()`. * Update the compiled browser version. * Add `Assertion.satisfy()` method. * Add `.satisfy()` should test. * Add `.satisfy()` expect test. * Merge pull request #19 from logicalparadox/respond-to * Update the compiled browser version. * Add `respondTo` Assertion. * Add `respondTo` should test. * Add `respondTo` expect test. * Merge branch 'feature/coverage' * mocha coverage support * doc contributors * README contributors 0.3.4 / 2012-02-23 ================== * inline comment typos for #15 * Merge branch 'refs/heads/jeffbski-configErrorStackCompat' * includeStack documentation for all interfaces * suite name more generic * Update test to be compatible with browsers that do not support err.stack * udpated compiled chai.js and added to browser tests * Allow inclusion of stack trace for Assert error messages to be configurable * docs sharing buttons * sinon-chai link * doc updates * read me updates include plugins 0.3.3 / 2012-02-12 ================== * Merge pull request #14 from jfirebaugh/configurable_properties * Make Assertion.prototype properties configurable 0.3.2 / 2012-02-10 ================== * codex version * docs * docs cleanup 0.3.1 / 2012-02-07 ================== * node 0.4.x compat 0.3.0 / 2012-02-07 ================== * Merge branch 'feature/03x' * browser build * remove html/json/headers testign * regex error.message testing * tests for using plugins * Merge pull request #11 from domenic/master * Make `chai.use` a no-op if the function has already been used. 0.2.4 / 2012-02-02 ================== * added in past tense switch for `been` 0.2.3 / 2012-02-01 ================== * try that again 0.2.2 / 2012-02-01 ================== * added `been` (past of `be`) alias 0.2.1 / 2012-01-29 ================== * added Throw, with a capital T, as an alias to `throw` (#7) 0.2.0 / 2012-01-26 ================== * update gitignore for vim *.swp * Merge branch 'feature/plugins' * browser build * interfaces now work with use * simple .use function. See #9. * readme notice on browser compat 0.1.7 / 2012-01-25 ================== * added assert tests to browser test runner * browser update * `should` interface patch for primitives support in FF * fix isObject() Thanks @milewise * travis only on branch `master` * add instanceof alias `instanceOf`. #6 * some tests for assert module 0.1.6 / 2012-01-02 ================== * commenting for assert interface * updated codex dep 0.1.5 / 2012-01-02 ================== * browser tests pass * type in should.not.equal * test for should (not) exist * added should.exist and should.not.exist * browser uses tdd * convert tests to tdd 0.1.4 / 2011-12-26 ================== * browser lib update for new assert interface compatiblitiy * inspect typos * added strict equal + negatives and ifError * interface assert had doesNotThrow * added should tests to browser * new expect empty tests * should test browser compat * Fix typo for instanceof docs. Closes #3 [ci skip] 0.1.3 / 2011-12-18 ================== * much cleaner reporting string on error. 0.1.2 / 2011-12-18 ================== * [docs] for upcoming 0.1.2 * browser version built with pre/suffix … all tests passing * make / compile now use prefix/suffix correctly * code clean * prefix/suffix to wrap browser output to prevent conflicts with other `require` methods. * Merge branch 'feature/should4xcompatibility' * compile for browser tests.. all pass * added header/status/html/json * throw tests * should.throw & should.not.throw shortcuts * improved `throw` type detection and messaging * contain is now `include` … keys modifier is now `contain` * removed object() test * removed #respondTo * Merge branch 'bug/2' * replaced __defineGetter__ with defineProperty for all uses * [docs] change mp tracking code * docs site updated with assert (TDD) interface * updated doc comments for assert interface 0.1.1 / 2011-12-16 ================== * docs ready for upcoming 0.1.1 * readme image fixed [ci skip] * more readme tweaks [ci skip] * réadmet image fixed [ci skip] * documentation * codex locked in version 0.0.5 * more comments to assertions for docs * assertions fully commented, browser library updated * adding codex as doc dependancy * prepping for docs * assertion component completely commented for documentation * added exist test * var expect outside of browser if check * added keywords to package.json 0.1.0 / 2011-12-15 ================== * failing on purpose successful .. back to normal * testing travis failure * assert#arguments getter * readme typo * updated README * added travis and npmignore * copyright notices … think i got them all * moved expect interface to own file for consistency * assert ui deepEqual * browser tests expect (all working) * browser version built * chai.fail (should ui) * expect tests browser compatible * tests for should and expect (all pass) * moved fail to primary export * should compatibility testing * within, greaterThan, object, keys, * Aliases * Assertion#property now correctly works with negate and undefined values * error message language matches should * Assertion#respondTo * Assertion now uses inspect util * git ignore node modules * should is exported * AssertionError __proto__ from Error.prototype * add should interface for should.js compatibility * moved eql to until folder and added inspect from (joyent/node) * added mocha for testing * browser build for current api * multiple .property assertions * added deep equal from node 0.0.2 / 2011-12-07 ================== * cleaner output on error * improved exists detection * package remnant artifact * empty deep equal * test browser build * assertion cleanup * client compile script * makefile * most of the basic assertions * allow no parameters to assertion error * name change * assertion error instance * main exports: assert() & expect() * initialize chai-3.5.0/Makefile000664 000000 000000 00000003621 12652401517 014050 0ustar00rootroot000000 000000 TESTS = test/*.js REPORTER = dot # # Browser Build # all: chai.js chai.js: node_modules lib/* @printf "==> [Browser :: build]\n" @./node_modules/.bin/browserify \ --bare \ --outfile chai.js \ --standalone chai \ --entry index.js # # Release Task # define release ./node_modules/.bin/bump -y --$(1) package.json lib/chai.js make chai.js git add --force chai.js lib/chai.js package.json bower.json npm ls --depth=-1 --long . --loglevel silent | head -1 | git commit -F- endef release-patch: @$(call release,patch) release-minor: @$(call release,minor) release-major: @$(call release,major) # # Node Module # node_modules: package.json @npm install # # Tests # test: test-node test-phantom test-node: node_modules @printf "==> [Test :: Node.js]\n" @NODE_ENV=test ./node_modules/.bin/mocha \ --require ./test/bootstrap \ --reporter $(REPORTER) \ $(TESTS) test-cov: node_modules @NODE_ENV=test ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- \ --require ./test/bootstrap \ $(TESTS) \ test-phantom: clean-browser chai.js @printf "==> [Test :: Karma (PhantomJS)]\n" @./node_modules/karma/bin/karma start \ --single-run --browsers PhantomJS test-firefox: clean-browser chai.js @printf "==> [Test :: Karma (Firefox)]\n" @./node_modules/karma/bin/karma start \ --browsers Firefox test-sauce: clean-browser chai.js @printf "==> [Test :: Karma (Sauce)]\n" @CHAI_TEST_ENV=sauce ./node_modules/karma/bin/karma start \ --single-run test-travisci: @echo TRAVIS_JOB_ID $(TRAVIS_JOB_ID) @make test-cov @make test-sauce # # Clean up # clean: clean-node clean-browser clean-cov clean-node: @rm -rf node_modules clean-browser: @rm -f chai.js clean-cov: @rm -rf coverage # # Instructions # .PHONY: all .PHONY: test test-all test-node test-phantom test-sauce test-cov .PHONY: clean clean-node clean-browser clean-cov .PHONY: release-patch release-minor release-major chai-3.5.0/README.md000664 000000 000000 00000010737 12652401517 013675 0ustar00rootroot000000 000000 [![Chai Documentation](http://chaijs.com/public/img/chai-logo.png)](http://chaijs.com) [![license:mit](https://img.shields.io/badge/license-mit-green.svg?style=flat-square)](#license)
[![tag:?](https://img.shields.io/github/tag/chaijs/chai.svg?style=flat-square)](https://github.com/chaijs/chai/releases) [![build:?](https://img.shields.io/travis/chaijs/chai/master.svg?style=flat-square)](https://travis-ci.org/chaijs/chai) [![coverage:?](https://img.shields.io/coveralls/chaijs/chai/master.svg?style=flat-square)](https://coveralls.io/r/chaijs/chai)
[![npm:](https://img.shields.io/npm/v/chai.svg?style=flat-square)](https://www.npmjs.com/packages/chai) [![dependencies:?](https://img.shields.io/npm/dm/chai.svg?style=flat-square)](https://www.npmjs.com/packages/chai) [![devDependencies:?](https://img.shields.io/david/chaijs/chai.svg?style=flat-square)](https://david-dm.org/chaijs/chai) [![Selenium Test Status](https://saucelabs.com/browser-matrix/chaijs.svg)](https://saucelabs.com/u/chaijs) [![Slack Status](https://chai-slack.herokuapp.com/badge.svg)]( https://chai-slack.herokuapp.com/) [![Join the chat at https://gitter.im/chaijs/chai](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/chaijs/chai) Chai is a BDD / TDD assertion library for [node](http://nodejs.org) and the browser that can be delightfully paired with any javascript testing framework. For more information or to download plugins, view the [documentation](http://chaijs.com). ### Plugins Chai offers a robust Plugin architecture for extending Chai's assertions and interfaces. - Need a plugin? View the [official plugin list](http://chaijs.com/plugins). - Have a plugin and want it listed? Open a Pull Request at [chaijs/chai-docs:plugin.js](https://github.com/chaijs/chai-docs/blob/master/plugins.js#L1-L12). - Want to build a plugin? Read the [plugin api documentation](http://chaijs.com/guide/plugins/). ### Related Projects - [chaijs / assertion-error](https://github.com/chaijs/assertion-error): Custom `Error` constructor thrown upon an assertion failing. - [chaijs / deep-eql](https://github.com/chaijs/deep-eql): Improved deep equality testing for Node.js and the browser. - [chaijs / type-detect](https://github.com/chaijs/type-detect): Improved typeof detection for node.js and the browser. ### Contributing Thank you very much for considering to contribute! Here are a few issues other contributors frequently ran into when opening pull requests: - Please do not commit changes to the `chai.js` build. We do it once per release. - Before pushing your commits, please make sure you [rebase](https://github.com/chaijs/chai/blob/master/CONTRIBUTING.md#pull-requests) them. We also strongly encourage you to read our detailed [contribution guidelines](https://github.com/chaijs/chai/blob/master/CONTRIBUTING.md). ### Contributors Please see the full [Contributors Graph](https://github.com/chaijs/chai/graphs/contributors) for our list of contributors. ### Core Contributors Feel free to reach out to any of the core contributors with your questions or concerns. We will do our best to respond in a timely manner. [![Jake Luer](https://avatars3.githubusercontent.com/u/58988?v=3&s=50)](https://github.com/logicalparadox) [![Veselin Todorov](https://avatars3.githubusercontent.com/u/330048?v=3&s=50)](https://github.com/vesln) [![Keith Cirkel](https://avatars3.githubusercontent.com/u/118266?v=3&s=50)](https://github.com/keithamus) ## License (The MIT License) Copyright (c) 2011-2015 Jake Luer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. chai-3.5.0/ReleaseNotes.md000664 000000 000000 00000072510 12652401517 015326 0ustar00rootroot000000 000000 # Release Notes ## Note As of 3.0.0, the ReleaseNotes.md file has been deprecated. [Please refer to the release notes available on Github](https://github.com/chaijs/chai/releases). Or [the release notes on the chaijs.com website](https://chaijs.com/releases). --- ## 2.3.0 / 2015-04-26 Added `ownPropertyDescriptor` assertion: ```js expect('test').to.have.ownPropertyDescriptor('length'); expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 }); expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 }); expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false); expect('test').ownPropertyDescriptor('length').to.have.keys('value'); ``` ### Community Contributions #### Code Features & Fixes * [#408](https://github.com/chaijs/chai/pull/408) Add `ownPropertyDescriptor` assertion. By [@ljharb](https://github.com/ljharb) * [#422](https://github.com/chaijs/chai/pull/422) Improve ownPropertyDescriptor tests. By [@ljharb](https://github.com/ljharb) #### Documentation fixes * [#417](https://github.com/chaijs/chai/pull/417) Fix documentation typo By [@astorije](https://github.com/astorije) * [#423](https://github.com/chaijs/chai/pull/423) Fix inconsistency in docs. By [@ehntoo](https://github.com/ehntoo) ## 2.2.0 / 2015-03-26 Deep property strings can now be escaped using `\\` - for example: ```js var deepCss = { '.link': { '[target]': 42 }}; expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42) ``` ### Community Contributions #### Code Features & Fixes * [#402](https://github.com/chaijs/chai/pull/402) Allow escaping of deep property keys. By [@umireon](https://github.com/umireon) #### Documentation fixes * [#405](https://github.com/chaijs/chai/pull/405) Tweak documentation around deep property escaping. By [@keithamus](https://github.com/keithamus) ## 2.1.2 / 2015-03-15 A minor bug fix. No new features. ### Community Contributions #### Code Features & Fixes * [#395](https://github.com/chaijs/chai/pull/395) Fix eval-related bugs with assert.operator ([#386](https://github.com/chaijs/chai/pull/386)). By [@cjqed](https://github.com/cjqed) ## 2.1.1 / 2015-03-04 Two minor bugfixes. No new features. ### Community Contributions #### Code Features & Fixes * [#385](https://github.com/chaijs/chai/pull/385) Fix a bug (also described in [#387](https://github.com/chaijs/chai/pull/385)) where `deep.property` would not work with single key names. By [@eldritch-fossicker](https://github.com/eldritch-fossicker) * [#379](https://github.com/chaijs/chai/pull/379) Fix bug where tools which overwrite primitive prototypes, such as Babel or core-js would fail. By [@dcneiner](https://github.com/dcneiner) #### Documentation fixes * [#382](https://github.com/chaijs/chai/pull/382) Add doc for showDiff argument in assert. By [@astorije](https://github.com/astorije) * [#383](https://github.com/chaijs/chai/pull/383) Improve wording for truncateTreshold docs By [@gurdiga](https://github.com/gurdiga) * [#381](https://github.com/chaijs/chai/pull/381) Improve wording for assert.empty docs By [@astorije](https://github.com/astorije) ## 2.1.0 / 2015-02-23 Small release; fixes an issue where the Chai lib was incorrectly reporting the version number. Adds new `should.fail()` and `expect.fail()` methods, which are convinience methods to throw Assertion Errors. ### Community Contributions #### Code Features & Fixes * [#356](https://github.com/chaijs/chai/pull/356) Add should.fail(), expect.fail(). By [@Soviut](https://github.com/Soviut) * [#374](https://github.com/chaijs/chai/pull/374) Increment version. By [@jmm](https://github.com/jmm) ## 2.0.0 / 2015-02-09 Unfortunately with 1.10.0 - compatibility broke with older versions because of the `addChainableNoop`. This change has been reverted. Any plugins using `addChainableNoop` should cease to do so. Any developers wishing for this behaviour can use [dirty-chai](https://www.npmjs.com/package/dirty-chai) by [@joshperry](https://github.com/joshperry) ### Community Contributions #### Code Features & Fixes * [#361](https://github.com/chaijs/chai/pull/361) `.keys()` now accepts Objects, extracting keys from them. By [@gregglind](https://github.com/gregglind) * [#359](https://github.com/chaijs/chai/pull/359) `.keys()` no longer mutates passed arrays. By [@gregglind](https://github.com/gregglind) * [#349](https://github.com/chaijs/chai/pull/349) Add a new chainable keyword - `.which`. By [@toastynerd](https://github.com/toastynerd) * [#333](https://github.com/chaijs/chai/pull/333) Add `.change`, `.increase` and `.decrease` assertions. By [@cmpolis](https://github.com/cmpolis) * [#335](https://github.com/chaijs/chai/pull/335) `chai.util` is now exposed [@DingoEatingFuzz](https://github.com/DingoEatingFuzz) * [#328](https://github.com/chaijs/chai/pull/328) Add `.includes` and `.contains` aliases (for `.include` and `.contain`). By [@lo1tuma](https://github.com/lo1tuma) * [#313](https://github.com/chaijs/chai/pull/313) Add `.any.keys()` and `.all.keys()` qualifiers. By [@cjqed](https://github.com/cjqed) * [#312](https://github.com/chaijs/chai/pull/312) Add `assert.sameDeepMembers()`. By [@cjqed](https://github.com/cjqed) * [#311](https://github.com/chaijs/chai/pull/311) Add `assert.isAbove()` and `assert.isBelow()`. By [@cjqed](https://github.com/cjqed) * [#308](https://github.com/chaijs/chai/pull/308) `property` and `deep.property` now pass if a value is set to `undefined`. By [@prodatakey](https://github.com/prodatakey) * [#309](https://github.com/chaijs/chai/pull/309) optimize deep equal in Arrays. By [@ericdouglas](https://github.com/ericdouglas) * [#306](https://github.com/chaijs/chai/pull/306) revert #297 - allowing lint-friendly tests. By [@keithamus](https://github.com/keithamus) #### Documentation fixes * [#357](https://github.com/chaijs/chai/pull/357) Copyright year updated in docs. By [@danilovaz](https://github.com/danilovaz) * [#325](https://github.com/chaijs/chai/pull/325) Fix documentation for overwriteChainableMethod. By [@chasenlehara](https://github.com/chasenlehara) * [#334](https://github.com/chaijs/chai/pull/334) Typo fix. By [@hurrymaplelad](https://github.com/hurrymaplelad) * [#317](https://github.com/chaijs/chai/pull/317) Typo fix. By [@jasonkarns](https://github.com/jasonkarns) * [#318](https://github.com/chaijs/chai/pull/318) Typo fix. By [@jasonkarns](https://github.com/jasonkarns) * [#316](https://github.com/chaijs/chai/pull/316) Typo fix. By [@jasonkarns](https://github.com/jasonkarns) ## 1.10.0 / 2014-11-10 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required - **Plugin Developers:** - Review `addChainableNoop` notes below. - **Core Contributors:** - Refresh `node_modules` folder for updated dependencies. ### Noop Function for Terminating Assertion Properties The following assertions can now also be used in the function-call form: * ok * true * false * null * undefined * exist * empty * arguments * Arguments The above list of assertions are property getters that assert immediately on access. Because of that, they were written to be used by terminating the assertion chain with a property access. ```js expect(true).to.be.true; foo.should.be.ok; ``` This syntax is definitely aesthetically pleasing but, if you are linting your test code, your linter will complain with an error something like "Expected an assignment or function call and instead saw an expression." Since the linter doesn't know about the property getter it assumes this line has no side-effects, and throws a warning in case you made a mistake. Squelching these errors is not a good solution as test code is getting to be just as important as, if not more than, production code. Catching syntactical errors in tests using static analysis is a great tool to help make sure that your tests are well-defined and free of typos. A better option was to provide a function-call form for these assertions so that the code's intent is more clear and the linters stop complaining about something looking off. This form is added in addition to the existing property access form and does not impact existing test code. ```js expect(true).to.be.true(); foo.should.be.ok(); ``` These forms can also be mixed in any way, these are all functionally identical: ```js expect(true).to.be.true.and.not.false(); expect(true).to.be.true().and.not.false; expect(true).to.be.true.and.not.false; ``` #### Plugin Authors If you would like to provide this function-call form for your terminating assertion properties, there is a new function to register these types of asserts. Instead of using `addProperty` to register terminating assertions, simply use `addChainableNoop` instead; the arguments to both are identical. The latter will make the assertion available in both the attribute and function-call forms and should have no impact on existing users of your plugin. ### Community Contributions - [#297](https://github.com/chaijs/chai/pull/297) Allow writing lint-friendly tests. [@joshperry](https://github.com/joshperry) - [#298](https://github.com/chaijs/chai/pull/298) Add check for logging `-0`. [@dasilvacontin](https://github.com/dasilvacontin) - [#300](https://github.com/chaijs/chai/pull/300) Fix #299: the test is defining global variables [@julienw](https://github.com/julienw) Thank you to all who took time to contribute! ## 1.9.2 / 2014-09-29 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required - **Plugin Developers:** - No changes required - **Core Contributors:** - Refresh `node_modules` folder for updated dependencies. ### Community Contributions - [#264](https://github.com/chaijs/chai/pull/264) Show diff for keys assertions [@cjthompson](https://github.com/cjthompson) - [#267](https://github.com/chaijs/chai/pull/267) Use SVG badges [@shinnn](https://github.com/shinnn) - [#268](https://github.com/chaijs/chai/pull/268) Allow messages to be functions (sinon-compat) [@charlierudolph](https://github.com/charlierudolph) - [#269](https://github.com/chaijs/chai/pull/269) Remove unused argument for #lengthOf [@charlierudolph](https://github.com/charlierudolph) - [#275](https://github.com/chaijs/chai/pull/275) Rewrite pretty-printing HTML elements to prevent throwing internal errors [@DrRataplan](https://github.com/DrRataplan) - [#277](https://github.com/chaijs/chai/pull/277) Fix assert documentation for #sameMembers [@charlierudolph](https://github.com/charlierudolph) - [#279](https://github.com/chaijs/chai/pull/279) closeTo should check value's type before assertion [@mohayonao](https://github.com/mohayonao) - [#289](https://github.com/chaijs/chai/pull/289) satisfy is called twice [@charlierudolph](https://github.com/charlierudolph) - [#292](https://github.com/chaijs/chai/pull/292) resolve conflicts with node-webkit and global usage [@boneskull](https://github.com/boneskull) Thank you to all who took time to contribute! ## 1.9.1 / 2014-03-19 The following changes are required if you are upgrading from the previous version: - **Users:** - Migrate configuration options to new interface. (see notes) - **Plugin Developers:** - No changes required - **Core Contributors:** - Refresh `node_modules` folder for updated dependencies. ### Configuration There have been requests for changes and additions to the configuration mechanisms and their impact in the Chai architecture. As such, we have decoupled the configuration from the `Assertion` constructor. This not only allows for centralized configuration, but will allow us to shift the responsibility from the `Assertion` constructor to the `assert` interface in future releases. These changes have been implemented in a non-breaking way, but a depretiation warning will be presented to users until they migrate. The old config method will be removed in either `v1.11.0` or `v2.0.0`, whichever comes first. #### Quick Migration ```js // change this: chai.Assertion.includeStack = true; chai.Assertion.showDiff = false; // ... to this: chai.config.includeStack = true; chai.config.showDiff = false; ``` #### All Config Options ##### config.includeStack - **@param** _{Boolean}_ - **@default** `false` User configurable property, influences whether stack trace is included in Assertion error message. Default of `false` suppresses stack trace in the error message. ##### config.showDiff - **@param** _{Boolean}_ - **@default** `true` User configurable property, influences whether or not the `showDiff` flag should be included in the thrown AssertionErrors. `false` will always be `false`; `true` will be true when the assertion has requested a diff be shown. ##### config.truncateThreshold **(NEW)** - **@param** _{Number}_ - **@default** `40` User configurable property, sets length threshold for actual and expected values in assertion errors. If this threshold is exceeded, the value is truncated. Set it to zero if you want to disable truncating altogether. ```js chai.config.truncateThreshold = 0; // disable truncating ``` ### Community Contributions - [#228](https://github.com/chaijs/chai/pull/228) Deep equality check for memebers. [@duncanbeevers](https://github.com/duncanbeevers) - [#247](https://github.com/chaijs/chai/pull/247) Proofreading. [@didorellano](https://github.com/didoarellano) - [#244](https://github.com/chaijs/chai/pull/244) Fix `contain`/`include` 1.9.0 regression. [@leider](https://github.com/leider) - [#233](https://github.com/chaijs/chai/pull/233) Improvements to `ssfi` for `assert` interface. [@refack](https://github.com/refack) - [#251](https://github.com/chaijs/chai/pull/251) New config option: object display threshold. [@romario333](https://github.com/romario333) Thank you to all who took time to contribute! ### Other Bug Fixes - [#183](https://github.com/chaijs/chai/issues/183) Allow `undefined` for actual. (internal api) - Update Karam(+plugins)/Istanbul to most recent versions. ## 1.9.0 / 2014-01-29 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required - **Plugin Developers:** - Review [#219](https://github.com/chaijs/chai/pull/219). - **Core Contributors:** - Refresh `node_modules` folder for updated dependencies. ### Community Contributions - [#202](https://github.com/chaijs/chai/pull/201) Improve error message for .throw(). [@andreineculau](https://github.com/andreineculau) - [#217](https://github.com/chaijs/chai/pull/217) Chai tests can be run with `--watch`. [@demands](https://github.com/demands) - [#219](https://github.com/chaijs/chai/pull/219) Add overwriteChainableMethod utility. [@demands](https://github.com/demands) - [#224](https://github.com/chaijs/chai/pull/224) Return error on throw method to chain on error properties. [@vbardales](https://github.com/vbardales) - [#226](https://github.com/chaijs/chai/pull/226) Add `has` to language chains. [@duncanbeevers](https://github.com/duncanbeevers) - [#230](https://github.com/chaijs/chai/pull/230) Support `{a:1,b:2}.should.include({a:1})` [@jkroso](https://github.com/jkroso) - [#231](https://github.com/chaijs/chai/pull/231) Update Copyright notices to 2014 [@duncanbeevers](https://github.com/duncanbeevers) - [#232](https://github.com/chaijs/chai/pull/232) Avoid error instantiation if possible on assert.throws. [@laconbass](https://github.com/laconbass) Thank you to all who took time to contribute! ### Other Bug Fixes - [#225](https://github.com/chaijs/chai/pull/225) Improved AMD wrapper provided by upstream `component(1)`. - [#185](https://github.com/chaijs/chai/issues/185) `assert.throws()` returns thrown error for further assertions. - [#237](https://github.com/chaijs/chai/pull/237) Remove coveralls/jscoverage, include istanbul coverage report in travis test. - Update Karma and Sauce runner versions for consistent CI results. No more karma@canary. ## 1.8.1 / 2013-10-10 The following changes are required if you are upgrading from the previous version: - **Users:** - Refresh `node_modules` folder for updated dependencies. - **Plugin Developers:** - No changes required - **Core Contributors:** - Refresh `node_modules` folder for updated dependencies. ### Browserify This is a small patch that updates the dependency tree so browserify users can install chai. (Remove conditional requires) ## 1.8.0 / 2013-09-18 The following changes are required if you are upgrading from the previous version: - **Users:** - See `deep.equal` notes. - **Plugin Developers:** - No changes required - **Core Contributors:** - Refresh `node_modules` folder for updated dependencies. ### Deep Equals This version of Chai focused on a overhaul to the deep equal utility. The code for this tool has been removed from the core lib and can now be found at: [chai / deep-eql](https://github.com/chaijs/deep-eql). As stated in previous releases, this is part of a larger initiative to provide transparency, independent testing, and coverage for some of the more complicated internal tools. For the most part `.deep.equal` will behave the same as it has. However, in order to provide a consistent ruleset across all types being tested, the following changes have been made and _might_ require changes to your tests. **1.** Strict equality for non-traversable nodes according to [egal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). _Previously:_ Non-traversable equal via `===`. ```js expect(NaN).to.deep.equal(NaN); expect(-0).to.not.deep.equal(+0); ``` **2.** Arguments are not Arrays (and all types must be equal): _Previously:_ Some crazy nonsense that led to empty arrays deep equaling empty objects deep equaling dates. ```js expect(arguments).to.not.deep.equal([]); expect(Array.prototype.slice.call(arguments)).to.deep.equal([]); ``` - [#156](https://github.com/chaijs/chai/issues/156) Empty object is eql to empty array - [#192](https://github.com/chaijs/chai/issues/192) empty object is eql to a Date object - [#194](https://github.com/chaijs/chai/issues/194) refactor deep-equal utility ### CI and Browser Testing Chai now runs the browser CI suite using [Karma](http://karma-runner.github.io/) directed at [SauceLabs](https://saucelabs.com/). This means we get to know where our browser support stands... and we get a cool badge: [![Selenium Test Status](https://saucelabs.com/browser-matrix/logicalparadox.svg)](https://saucelabs.com/u/logicalparadox) Look for the list of browsers/versions to expand over the coming releases. - [#195](https://github.com/chaijs/chai/issues/195) karma test framework ## 1.7.2 / 2013-06-27 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required. - **Plugin Developers:** - No changes required - **Core Contributors:** - Refresh `node_modules` folder for updated dependencies. ### Coverage Reporting Coverage reporting has always been available for core-developers but the data has never been published for our end users. In our ongoing effort to improve accountability this data will now be published via the [coveralls.io](https://coveralls.io/) service. A badge has been added to the README and the full report can be viewed online at the [chai coveralls project](https://coveralls.io/r/chaijs/chai). Furthermore, PRs will receive automated messages indicating how their PR impacts test coverage. This service is tied to TravisCI. ### Other Fixes - [#175](https://github.com/chaijs/chai/issues/175) Add `bower.json`. (Fix ignore all) ## 1.7.1 / 2013-06-24 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required. - **Plugin Developers:** - No changes required - **Core Contributors:** - Refresh `node_modules` folder for updated dependencies. ### Official Bower Support Support has been added for the Bower Package Manager ([bower.io])(http://bower.io/). Though Chai could be installed via Bower in the past, this update adds official support via the `bower.json` specification file. - [#175](https://github.com/chaijs/chai/issues/175) Add `bower.json`. ## 1.7.0 / 2013-06-17 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required. - **Plugin Developers:** - Review AssertionError update notice. - **Core Contributors:** - Refresh `node_modules` folder for updated dependencies. ### AssertionError Update Notice Chai now uses [chaijs/assertion-error](https://github.com/chaijs/assertion-error) instead an internal constructor. This will allow for further iteration/experimentation of the AssertionError constructor independant of Chai. Future plans include stack parsing for callsite support. This update constructor has a different constructor param signature that conforms more with the standard `Error` object. If your plugin throws and `AssertionError` directly you will need to update your plugin with the new signature. ```js var AssertionError = require('chai').AssertionError; /** * previous * * @param {Object} options */ throw new AssertionError({ message: 'An assertion error occurred' , actual: actual , expect: expect , startStackFunction: arguments.callee , showStack: true }); /** * new * * @param {String} message * @param {Object} options * @param {Function} start stack function */ throw new AssertionError('An assertion error occurred', { actual: actual , expect: expect , showStack: true }, arguments.callee); // other signatures throw new AssertionError('An assertion error occurred'); throw new AssertionError('An assertion error occurred', null, arguments.callee); ``` #### External Dependencies This is the first non-developement dependency for Chai. As Chai continues to evolve we will begin adding more; the next will likely be improved type detection and deep equality. With Chai's userbase continually growing there is an higher need for accountability and documentation. External dependencies will allow us to iterate and test on features independent from our interfaces. Note: The browser packaged version `chai.js` will ALWAYS contain all dependencies needed to run Chai. ### Community Contributions - [#169](https://github.com/chaijs/chai/pull/169) Fix deep equal comparison for Date/Regexp types. [@katsgeorgeek](https://github.com/katsgeorgeek) - [#171](https://github.com/chaijs/chai/pull/171) Add `assert.notOk()`. [@Bartvds](https://github.com/Bartvds) - [#173](https://github.com/chaijs/chai/pull/173) Fix `inspect` utility. [@domenic](https://github.com/domenic) Thank you to all who took the time to contribute! ## 1.6.1 / 2013-06-05 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required. - **Plugin Developers:** - No changes required. - **Core Contributors:** - Refresh `node_modules` folder for updated developement dependencies. ### Deep Equality Regular Expressions are now tested as part of all deep equality assertions. In previous versions they silently passed for all scenarios. Thanks to [@katsgeorgeek](https://github.com/katsgeorgeek) for the contribution. ### Community Contributions - [#161](https://github.com/chaijs/chai/pull/161) Fix documented name for assert interface's isDefined method. [@brandonpayton](https://github.com/brandonpayton) - [#168](https://github.com/chaijs/chai/pull/168) Fix comparison equality of two regexps for when using deep equality. [@katsgeorgeek](https://github.com/katsgeorgeek) Thank you to all who took the time to contribute! ### Additional Notes - Mocha has been locked at version `1.8.x` to ensure `mocha-phantomjs` compatibility. ## 1.6.0 / 2013-04-29 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required. - **Plugin Developers:** - No changes required. - **Core Contributors:** - Refresh `node_modules` folder for updated developement dependencies. ### New Assertions #### Array Members Inclusion Asserts that the target is a superset of `set`, or that the target and `set` have the same members. Order is not taken into account. Thanks to [@NickHeiner](https://github.com/NickHeiner) for the contribution. ```js // (expect/should) full set expect([4, 2]).to.have.members([2, 4]); expect([5, 2]).to.not.have.members([5, 2, 1]); // (expect/should) inclusion expect([1, 2, 3]).to.include.members([3, 2]); expect([1, 2, 3]).to.not.include.members([3, 2, 8]); // (assert) full set assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members'); // (assert) inclusion assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members'); ``` #### Non-inclusion for Assert Interface Most `assert` functions have a negative version, like `instanceOf()` has a corresponding `notInstaceOf()`. However `include()` did not have a corresponding `notInclude()`. This has been added. ```js assert.notInclude([ 1, 2, 3 ], 8); assert.notInclude('foobar', 'baz'); ``` ### Community Contributions - [#140](https://github.com/chaijs/chai/pull/140) Restore `call`/`apply` methods for plugin interface. [@RubenVerborgh](https://github.com/RubenVerborgh) - [#148](https://github.com/chaijs/chai/issues/148)/[#153](https://github.com/chaijs/chai/pull/153) Add `members` and `include.members` assertions. [#NickHeiner](https://github.com/NickHeiner) Thank you to all who took time to contribute! ### Other Bug Fixes - [#142](https://github.com/chaijs/chai/issues/142) `assert#include` will no longer silently pass on wrong-type haystack. - [#158](https://github.com/chaijs/chai/issues/158) `assert#notInclude` has been added. - Travis-CI now tests Node.js `v0.10.x`. Support for `v0.6.x` has been removed. `v0.8.x` is still tested as before. ## 1.5.0 / 2013-02-03 ### Migration Requirements The following changes are required if you are upgrading from the previous version: - **Users:** - _Update [2013-02-04]:_ Some users may notice a small subset of deep equality assertions will no longer pass. This is the result of [#120](https://github.com/chaijs/chai/issues/120), an improvement to our deep equality algorithm. Users will need to revise their assertions to be more granular should this occur. Further information: [#139](https://github.com/chaijs/chai/issues/139). - **Plugin Developers:** - No changes required. - **Core Contributors:** - Refresh `node_modules` folder for updated developement dependencies. ### Community Contributions - [#126](https://github.com/chaijs/chai/pull/126): Add `eqls` alias for `eql`. [@RubenVerborgh](https://github.com/RubenVerborgh) - [#127](https://github.com/chaijs/chai/issues/127): Performance refactor for chainable methods. [@RubenVerborgh](https://github.com/RubenVerborgh) - [#133](https://github.com/chaijs/chai/pull/133): Assertion `.throw` support for primitives. [@RubenVerborgh](https://github.com/RubenVerborgh) - [#137](https://github.com/chaijs/chai/issues/137): Assertion `.throw` support for empty messages. [@timnew](https://github.com/timnew) - [#136](https://github.com/chaijs/chai/pull/136): Fix backward negation messages when using `.above()` and `.below()`. [@whatthejeff](https://github.com/whatthejeff) Thank you to all who took time to contribute! ### Other Bug Fixes - Improve type detection of `.a()`/`.an()` to work in cross-browser scenarios. - [#116](https://github.com/chaijs/chai/issues/116): `.throw()` has cleaner display of errors when WebKit browsers. - [#120](https://github.com/chaijs/chai/issues/120): `.eql()` now works to compare dom nodes in browsers. ### Usage Updates #### For Users **1. Component Support:** Chai now included the proper configuration to be installed as a [component](https://github.com/component/component). Component users are encouraged to consult [chaijs.com](http://chaijs.com) for the latest version number as using the master branch does not gaurantee stability. ```js // relevant component.json devDependencies: { "chaijs/chai": "1.5.0" } ``` Alternatively, bleeding-edge is available: $ component install chaijs/chai **2. Configurable showDiff:** Some test runners (such as [mocha](http://visionmedia.github.com/mocha/)) include support for showing the diff of strings and objects when an equality error occurs. Chai has already included support for this, however some users may not prefer this display behavior. To revert to no diff display, the following configuration is available: ```js chai.Assertion.showDiff = false; // diff output disabled chai.Assertion.showDiff = true; // default, diff output enabled ``` #### For Plugin Developers **1. New Utility - type**: The new utility `.type()` is available as a better implementation of `typeof` that can be used cross-browser. It handles the inconsistencies of Array, `null`, and `undefined` detection. - **@param** _{Mixed}_ object to detect type of - **@return** _{String}_ object type ```js chai.use(function (c, utils) { // some examples utils.type({}); // 'object' utils.type(null); // `null' utils.type(undefined); // `undefined` utils.type([]); // `array` }); ``` #### For Core Contributors **1. Browser Testing**: Browser testing of the `./chai.js` file is now available in the command line via PhantomJS. `make test` and Travis-CI will now also rebuild and test `./chai.js`. Consequently, all pull requests will now be browser tested in this way. _Note: Contributors opening pull requests should still NOT include the browser build._ **2. SauceLabs Testing**: Early SauceLab support has been enabled with the file `./support/mocha-cloud.js`. Those interested in trying it out should create a free [Open Sauce](https://saucelabs.com/signup/plan) account and include their credentials in `./test/auth/sauce.json`. chai-3.5.0/bower.json000664 000000 000000 00000000700 12652401517 014414 0ustar00rootroot000000 000000 { "name": "chai", "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic.", "license": "MIT", "keywords": [ "test", "assertion", "assert", "testing", "chai" ], "main": "chai.js", "ignore": [ "build", "components", "lib", "node_modules", "support", "test", "index.js", "Makefile", ".*" ], "dependencies": {}, "devDependencies": {} } chai-3.5.0/index.js000664 000000 000000 00000000050 12652401517 014046 0ustar00rootroot000000 000000 module.exports = require('./lib/chai'); chai-3.5.0/karma.conf.js000664 000000 000000 00000001152 12652401517 014762 0ustar00rootroot000000 000000 module.exports = function(config) { config.set({ frameworks: [ 'mocha' ] , files: [ 'chai.js' , 'test/bootstrap/karma.js' , 'test/*.js' ] , reporters: [ 'progress' ] , colors: true , logLevel: config.LOG_INFO , autoWatch: false , browsers: [ 'PhantomJS' ] , browserDisconnectTimeout: 10000 , browserDisconnectTolerance: 2 , browserNoActivityTimeout: 20000 , singleRun: true }); switch (process.env.CHAI_TEST_ENV) { case 'sauce': require('./karma.sauce')(config); break; default: // ... break; }; }; chai-3.5.0/karma.sauce.js000664 000000 000000 00000002261 12652401517 015137 0ustar00rootroot000000 000000 var version = require('./package.json').version; var ts = new Date().getTime(); module.exports = function(config) { var auth; try { auth = require('./test/auth/index'); } catch(ex) { auth = {}; auth.SAUCE_USERNAME = process.env.SAUCE_USERNAME || null; auth.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY || null; } if (!auth.SAUCE_USERNAME || !auth.SAUCE_ACCESS_KEY) return; if (process.env.SKIP_SAUCE) return; var branch = process.env.TRAVIS_BRANCH || 'local' var browserConfig = require('./sauce.browsers'); var browsers = Object.keys(browserConfig); var tags = [ 'chaijs_' + version, auth.SAUCE_USERNAME + '@' + branch ]; var tunnel = process.env.TRAVIS_JOB_NUMBER || ts; if (process.env.TRAVIS_JOB_NUMBER) { tags.push('travis@' + process.env.TRAVIS_JOB_NUMBER); } config.browsers = config.browsers.concat(browsers); config.customLaunchers = browserConfig; config.reporters.push('saucelabs'); config.transports = [ 'xhr-polling' ]; config.sauceLabs = { username: auth.SAUCE_USERNAME , accessKey: auth.SAUCE_ACCESS_KEY , startConnect: true , tags: tags , testName: 'ChaiJS' , tunnelIdentifier: tunnel }; }; chai-3.5.0/lib/000775 000000 000000 00000000000 12652401517 013154 5ustar00rootroot000000 000000 chai-3.5.0/lib/chai.js000664 000000 000000 00000002405 12652401517 014417 0ustar00rootroot000000 000000 /*! * chai * Copyright(c) 2011-2014 Jake Luer * MIT Licensed */ var used = [] , exports = module.exports = {}; /*! * Chai version */ exports.version = '3.5.0'; /*! * Assertion Error */ exports.AssertionError = require('assertion-error'); /*! * Utils for plugins (not exported) */ var util = require('./chai/utils'); /** * # .use(function) * * Provides a way to extend the internals of Chai * * @param {Function} * @returns {this} for chaining * @api public */ exports.use = function (fn) { if (!~used.indexOf(fn)) { fn(this, util); used.push(fn); } return this; }; /*! * Utility Functions */ exports.util = util; /*! * Configuration */ var config = require('./chai/config'); exports.config = config; /*! * Primary `Assertion` prototype */ var assertion = require('./chai/assertion'); exports.use(assertion); /*! * Core Assertions */ var core = require('./chai/core/assertions'); exports.use(core); /*! * Expect interface */ var expect = require('./chai/interface/expect'); exports.use(expect); /*! * Should interface */ var should = require('./chai/interface/should'); exports.use(should); /*! * Assert interface */ var assert = require('./chai/interface/assert'); exports.use(assert); chai-3.5.0/lib/chai/000775 000000 000000 00000000000 12652401517 014060 5ustar00rootroot000000 000000 chai-3.5.0/lib/chai/assertion.js000664 000000 000000 00000007322 12652401517 016431 0ustar00rootroot000000 000000 /*! * chai * http://chaijs.com * Copyright(c) 2011-2014 Jake Luer * MIT Licensed */ var config = require('./config'); module.exports = function (_chai, util) { /*! * Module dependencies. */ var AssertionError = _chai.AssertionError , flag = util.flag; /*! * Module export. */ _chai.Assertion = Assertion; /*! * Assertion Constructor * * Creates object for chaining. * * @api private */ function Assertion (obj, msg, stack) { flag(this, 'ssfi', stack || arguments.callee); flag(this, 'object', obj); flag(this, 'message', msg); } Object.defineProperty(Assertion, 'includeStack', { get: function() { console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); return config.includeStack; }, set: function(value) { console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); config.includeStack = value; } }); Object.defineProperty(Assertion, 'showDiff', { get: function() { console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); return config.showDiff; }, set: function(value) { console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); config.showDiff = value; } }); Assertion.addProperty = function (name, fn) { util.addProperty(this.prototype, name, fn); }; Assertion.addMethod = function (name, fn) { util.addMethod(this.prototype, name, fn); }; Assertion.addChainableMethod = function (name, fn, chainingBehavior) { util.addChainableMethod(this.prototype, name, fn, chainingBehavior); }; Assertion.overwriteProperty = function (name, fn) { util.overwriteProperty(this.prototype, name, fn); }; Assertion.overwriteMethod = function (name, fn) { util.overwriteMethod(this.prototype, name, fn); }; Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) { util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior); }; /** * ### .assert(expression, message, negateMessage, expected, actual, showDiff) * * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass. * * @name assert * @param {Philosophical} expression to be tested * @param {String|Function} message or function that returns message to display if expression fails * @param {String|Function} negatedMessage or function that returns negatedMessage to display if negated expression fails * @param {Mixed} expected value (remember to check for negation) * @param {Mixed} actual (optional) will default to `this.obj` * @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails * @api private */ Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) { var ok = util.test(this, arguments); if (true !== showDiff) showDiff = false; if (true !== config.showDiff) showDiff = false; if (!ok) { var msg = util.getMessage(this, arguments) , actual = util.getActual(this, arguments); throw new AssertionError(msg, { actual: actual , expected: expected , showDiff: showDiff }, (config.includeStack) ? this.assert : flag(this, 'ssfi')); } }; /*! * ### ._obj * * Quick reference to stored `actual` value for plugin developers. * * @api private */ Object.defineProperty(Assertion.prototype, '_obj', { get: function () { return flag(this, 'object'); } , set: function (val) { flag(this, 'object', val); } }); }; chai-3.5.0/lib/chai/config.js000664 000000 000000 00000002665 12652401517 015674 0ustar00rootroot000000 000000 module.exports = { /** * ### config.includeStack * * User configurable property, influences whether stack trace * is included in Assertion error message. Default of false * suppresses stack trace in the error message. * * chai.config.includeStack = true; // enable stack on error * * @param {Boolean} * @api public */ includeStack: false, /** * ### config.showDiff * * User configurable property, influences whether or not * the `showDiff` flag should be included in the thrown * AssertionErrors. `false` will always be `false`; `true` * will be true when the assertion has requested a diff * be shown. * * @param {Boolean} * @api public */ showDiff: true, /** * ### config.truncateThreshold * * User configurable property, sets length threshold for actual and * expected values in assertion errors. If this threshold is exceeded, for * example for large data structures, the value is replaced with something * like `[ Array(3) ]` or `{ Object (prop1, prop2) }`. * * Set it to zero if you want to disable truncating altogether. * * This is especially userful when doing assertions on arrays: having this * set to a reasonable large value makes the failure messages readily * inspectable. * * chai.config.truncateThreshold = 0; // disable truncating * * @param {Number} * @api public */ truncateThreshold: 40 }; chai-3.5.0/lib/chai/core/000775 000000 000000 00000000000 12652401517 015010 5ustar00rootroot000000 000000 chai-3.5.0/lib/chai/core/assertions.js000664 000000 000000 00000145110 12652401517 017542 0ustar00rootroot000000 000000 /*! * chai * http://chaijs.com * Copyright(c) 2011-2014 Jake Luer * MIT Licensed */ module.exports = function (chai, _) { var Assertion = chai.Assertion , toString = Object.prototype.toString , flag = _.flag; /** * ### Language Chains * * The following are provided as chainable getters to * improve the readability of your assertions. They * do not provide testing capabilities unless they * have been overwritten by a plugin. * * **Chains** * * - to * - be * - been * - is * - that * - which * - and * - has * - have * - with * - at * - of * - same * * @name language chains * @namespace BDD * @api public */ [ 'to', 'be', 'been' , 'is', 'and', 'has', 'have' , 'with', 'that', 'which', 'at' , 'of', 'same' ].forEach(function (chain) { Assertion.addProperty(chain, function () { return this; }); }); /** * ### .not * * Negates any of assertions following in the chain. * * expect(foo).to.not.equal('bar'); * expect(goodFn).to.not.throw(Error); * expect({ foo: 'baz' }).to.have.property('foo') * .and.not.equal('bar'); * * @name not * @namespace BDD * @api public */ Assertion.addProperty('not', function () { flag(this, 'negate', true); }); /** * ### .deep * * Sets the `deep` flag, later used by the `equal` and * `property` assertions. * * expect(foo).to.deep.equal({ bar: 'baz' }); * expect({ foo: { bar: { baz: 'quux' } } }) * .to.have.deep.property('foo.bar.baz', 'quux'); * * `.deep.property` special characters can be escaped * by adding two slashes before the `.` or `[]`. * * var deepCss = { '.link': { '[target]': 42 }}; * expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42); * * @name deep * @namespace BDD * @api public */ Assertion.addProperty('deep', function () { flag(this, 'deep', true); }); /** * ### .any * * Sets the `any` flag, (opposite of the `all` flag) * later used in the `keys` assertion. * * expect(foo).to.have.any.keys('bar', 'baz'); * * @name any * @namespace BDD * @api public */ Assertion.addProperty('any', function () { flag(this, 'any', true); flag(this, 'all', false) }); /** * ### .all * * Sets the `all` flag (opposite of the `any` flag) * later used by the `keys` assertion. * * expect(foo).to.have.all.keys('bar', 'baz'); * * @name all * @namespace BDD * @api public */ Assertion.addProperty('all', function () { flag(this, 'all', true); flag(this, 'any', false); }); /** * ### .a(type) * * The `a` and `an` assertions are aliases that can be * used either as language chains or to assert a value's * type. * * // typeof * expect('test').to.be.a('string'); * expect({ foo: 'bar' }).to.be.an('object'); * expect(null).to.be.a('null'); * expect(undefined).to.be.an('undefined'); * expect(new Error).to.be.an('error'); * expect(new Promise).to.be.a('promise'); * expect(new Float32Array()).to.be.a('float32array'); * expect(Symbol()).to.be.a('symbol'); * * // es6 overrides * expect({[Symbol.toStringTag]:()=>'foo'}).to.be.a('foo'); * * // language chain * expect(foo).to.be.an.instanceof(Foo); * * @name a * @alias an * @param {String} type * @param {String} message _optional_ * @namespace BDD * @api public */ function an (type, msg) { if (msg) flag(this, 'message', msg); type = type.toLowerCase(); var obj = flag(this, 'object') , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a '; this.assert( type === _.type(obj) , 'expected #{this} to be ' + article + type , 'expected #{this} not to be ' + article + type ); } Assertion.addChainableMethod('an', an); Assertion.addChainableMethod('a', an); /** * ### .include(value) * * The `include` and `contain` assertions can be used as either property * based language chains or as methods to assert the inclusion of an object * in an array or a substring in a string. When used as language chains, * they toggle the `contains` flag for the `keys` assertion. * * expect([1,2,3]).to.include(2); * expect('foobar').to.contain('foo'); * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo'); * * @name include * @alias contain * @alias includes * @alias contains * @param {Object|String|Number} obj * @param {String} message _optional_ * @namespace BDD * @api public */ function includeChainingBehavior () { flag(this, 'contains', true); } function include (val, msg) { _.expectTypes(this, ['array', 'object', 'string']); if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); var expected = false; if (_.type(obj) === 'array' && _.type(val) === 'object') { for (var i in obj) { if (_.eql(obj[i], val)) { expected = true; break; } } } else if (_.type(val) === 'object') { if (!flag(this, 'negate')) { for (var k in val) new Assertion(obj).property(k, val[k]); return; } var subset = {}; for (var k in val) subset[k] = obj[k]; expected = _.eql(subset, val); } else { expected = (obj != undefined) && ~obj.indexOf(val); } this.assert( expected , 'expected #{this} to include ' + _.inspect(val) , 'expected #{this} to not include ' + _.inspect(val)); } Assertion.addChainableMethod('include', include, includeChainingBehavior); Assertion.addChainableMethod('contain', include, includeChainingBehavior); Assertion.addChainableMethod('contains', include, includeChainingBehavior); Assertion.addChainableMethod('includes', include, includeChainingBehavior); /** * ### .ok * * Asserts that the target is truthy. * * expect('everything').to.be.ok; * expect(1).to.be.ok; * expect(false).to.not.be.ok; * expect(undefined).to.not.be.ok; * expect(null).to.not.be.ok; * * @name ok * @namespace BDD * @api public */ Assertion.addProperty('ok', function () { this.assert( flag(this, 'object') , 'expected #{this} to be truthy' , 'expected #{this} to be falsy'); }); /** * ### .true * * Asserts that the target is `true`. * * expect(true).to.be.true; * expect(1).to.not.be.true; * * @name true * @namespace BDD * @api public */ Assertion.addProperty('true', function () { this.assert( true === flag(this, 'object') , 'expected #{this} to be true' , 'expected #{this} to be false' , this.negate ? false : true ); }); /** * ### .false * * Asserts that the target is `false`. * * expect(false).to.be.false; * expect(0).to.not.be.false; * * @name false * @namespace BDD * @api public */ Assertion.addProperty('false', function () { this.assert( false === flag(this, 'object') , 'expected #{this} to be false' , 'expected #{this} to be true' , this.negate ? true : false ); }); /** * ### .null * * Asserts that the target is `null`. * * expect(null).to.be.null; * expect(undefined).to.not.be.null; * * @name null * @namespace BDD * @api public */ Assertion.addProperty('null', function () { this.assert( null === flag(this, 'object') , 'expected #{this} to be null' , 'expected #{this} not to be null' ); }); /** * ### .undefined * * Asserts that the target is `undefined`. * * expect(undefined).to.be.undefined; * expect(null).to.not.be.undefined; * * @name undefined * @namespace BDD * @api public */ Assertion.addProperty('undefined', function () { this.assert( undefined === flag(this, 'object') , 'expected #{this} to be undefined' , 'expected #{this} not to be undefined' ); }); /** * ### .NaN * Asserts that the target is `NaN`. * * expect('foo').to.be.NaN; * expect(4).not.to.be.NaN; * * @name NaN * @namespace BDD * @api public */ Assertion.addProperty('NaN', function () { this.assert( isNaN(flag(this, 'object')) , 'expected #{this} to be NaN' , 'expected #{this} not to be NaN' ); }); /** * ### .exist * * Asserts that the target is neither `null` nor `undefined`. * * var foo = 'hi' * , bar = null * , baz; * * expect(foo).to.exist; * expect(bar).to.not.exist; * expect(baz).to.not.exist; * * @name exist * @namespace BDD * @api public */ Assertion.addProperty('exist', function () { this.assert( null != flag(this, 'object') , 'expected #{this} to exist' , 'expected #{this} to not exist' ); }); /** * ### .empty * * Asserts that the target's length is `0`. For arrays and strings, it checks * the `length` property. For objects, it gets the count of * enumerable keys. * * expect([]).to.be.empty; * expect('').to.be.empty; * expect({}).to.be.empty; * * @name empty * @namespace BDD * @api public */ Assertion.addProperty('empty', function () { var obj = flag(this, 'object') , expected = obj; if (Array.isArray(obj) || 'string' === typeof object) { expected = obj.length; } else if (typeof obj === 'object') { expected = Object.keys(obj).length; } this.assert( !expected , 'expected #{this} to be empty' , 'expected #{this} not to be empty' ); }); /** * ### .arguments * * Asserts that the target is an arguments object. * * function test () { * expect(arguments).to.be.arguments; * } * * @name arguments * @alias Arguments * @namespace BDD * @api public */ function checkArguments () { var obj = flag(this, 'object') , type = Object.prototype.toString.call(obj); this.assert( '[object Arguments]' === type , 'expected #{this} to be arguments but got ' + type , 'expected #{this} to not be arguments' ); } Assertion.addProperty('arguments', checkArguments); Assertion.addProperty('Arguments', checkArguments); /** * ### .equal(value) * * Asserts that the target is strictly equal (`===`) to `value`. * Alternately, if the `deep` flag is set, asserts that * the target is deeply equal to `value`. * * expect('hello').to.equal('hello'); * expect(42).to.equal(42); * expect(1).to.not.equal(true); * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' }); * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' }); * * @name equal * @alias equals * @alias eq * @alias deep.equal * @param {Mixed} value * @param {String} message _optional_ * @namespace BDD * @api public */ function assertEqual (val, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'deep')) { return this.eql(val); } else { this.assert( val === obj , 'expected #{this} to equal #{exp}' , 'expected #{this} to not equal #{exp}' , val , this._obj , true ); } } Assertion.addMethod('equal', assertEqual); Assertion.addMethod('equals', assertEqual); Assertion.addMethod('eq', assertEqual); /** * ### .eql(value) * * Asserts that the target is deeply equal to `value`. * * expect({ foo: 'bar' }).to.eql({ foo: 'bar' }); * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]); * * @name eql * @alias eqls * @param {Mixed} value * @param {String} message _optional_ * @namespace BDD * @api public */ function assertEql(obj, msg) { if (msg) flag(this, 'message', msg); this.assert( _.eql(obj, flag(this, 'object')) , 'expected #{this} to deeply equal #{exp}' , 'expected #{this} to not deeply equal #{exp}' , obj , this._obj , true ); } Assertion.addMethod('eql', assertEql); Assertion.addMethod('eqls', assertEql); /** * ### .above(value) * * Asserts that the target is greater than `value`. * * expect(10).to.be.above(5); * * Can also be used in conjunction with `length` to * assert a minimum length. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.above(2); * expect([ 1, 2, 3 ]).to.have.length.above(2); * * @name above * @alias gt * @alias greaterThan * @param {Number} value * @param {String} message _optional_ * @namespace BDD * @api public */ function assertAbove (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len > n , 'expected #{this} to have a length above #{exp} but got #{act}' , 'expected #{this} to not have a length above #{exp}' , n , len ); } else { this.assert( obj > n , 'expected #{this} to be above ' + n , 'expected #{this} to be at most ' + n ); } } Assertion.addMethod('above', assertAbove); Assertion.addMethod('gt', assertAbove); Assertion.addMethod('greaterThan', assertAbove); /** * ### .least(value) * * Asserts that the target is greater than or equal to `value`. * * expect(10).to.be.at.least(10); * * Can also be used in conjunction with `length` to * assert a minimum length. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.of.at.least(2); * expect([ 1, 2, 3 ]).to.have.length.of.at.least(3); * * @name least * @alias gte * @param {Number} value * @param {String} message _optional_ * @namespace BDD * @api public */ function assertLeast (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len >= n , 'expected #{this} to have a length at least #{exp} but got #{act}' , 'expected #{this} to have a length below #{exp}' , n , len ); } else { this.assert( obj >= n , 'expected #{this} to be at least ' + n , 'expected #{this} to be below ' + n ); } } Assertion.addMethod('least', assertLeast); Assertion.addMethod('gte', assertLeast); /** * ### .below(value) * * Asserts that the target is less than `value`. * * expect(5).to.be.below(10); * * Can also be used in conjunction with `length` to * assert a maximum length. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.below(4); * expect([ 1, 2, 3 ]).to.have.length.below(4); * * @name below * @alias lt * @alias lessThan * @param {Number} value * @param {String} message _optional_ * @namespace BDD * @api public */ function assertBelow (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len < n , 'expected #{this} to have a length below #{exp} but got #{act}' , 'expected #{this} to not have a length below #{exp}' , n , len ); } else { this.assert( obj < n , 'expected #{this} to be below ' + n , 'expected #{this} to be at least ' + n ); } } Assertion.addMethod('below', assertBelow); Assertion.addMethod('lt', assertBelow); Assertion.addMethod('lessThan', assertBelow); /** * ### .most(value) * * Asserts that the target is less than or equal to `value`. * * expect(5).to.be.at.most(5); * * Can also be used in conjunction with `length` to * assert a maximum length. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.of.at.most(4); * expect([ 1, 2, 3 ]).to.have.length.of.at.most(3); * * @name most * @alias lte * @param {Number} value * @param {String} message _optional_ * @namespace BDD * @api public */ function assertMost (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len <= n , 'expected #{this} to have a length at most #{exp} but got #{act}' , 'expected #{this} to have a length above #{exp}' , n , len ); } else { this.assert( obj <= n , 'expected #{this} to be at most ' + n , 'expected #{this} to be above ' + n ); } } Assertion.addMethod('most', assertMost); Assertion.addMethod('lte', assertMost); /** * ### .within(start, finish) * * Asserts that the target is within a range. * * expect(7).to.be.within(5,10); * * Can also be used in conjunction with `length` to * assert a length range. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.within(2,4); * expect([ 1, 2, 3 ]).to.have.length.within(2,4); * * @name within * @param {Number} start lowerbound inclusive * @param {Number} finish upperbound inclusive * @param {String} message _optional_ * @namespace BDD * @api public */ Assertion.addMethod('within', function (start, finish, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') , range = start + '..' + finish; if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len >= start && len <= finish , 'expected #{this} to have a length within ' + range , 'expected #{this} to not have a length within ' + range ); } else { this.assert( obj >= start && obj <= finish , 'expected #{this} to be within ' + range , 'expected #{this} to not be within ' + range ); } }); /** * ### .instanceof(constructor) * * Asserts that the target is an instance of `constructor`. * * var Tea = function (name) { this.name = name; } * , Chai = new Tea('chai'); * * expect(Chai).to.be.an.instanceof(Tea); * expect([ 1, 2, 3 ]).to.be.instanceof(Array); * * @name instanceof * @param {Constructor} constructor * @param {String} message _optional_ * @alias instanceOf * @namespace BDD * @api public */ function assertInstanceOf (constructor, msg) { if (msg) flag(this, 'message', msg); var name = _.getName(constructor); this.assert( flag(this, 'object') instanceof constructor , 'expected #{this} to be an instance of ' + name , 'expected #{this} to not be an instance of ' + name ); }; Assertion.addMethod('instanceof', assertInstanceOf); Assertion.addMethod('instanceOf', assertInstanceOf); /** * ### .property(name, [value]) * * Asserts that the target has a property `name`, optionally asserting that * the value of that property is strictly equal to `value`. * If the `deep` flag is set, you can use dot- and bracket-notation for deep * references into objects and arrays. * * // simple referencing * var obj = { foo: 'bar' }; * expect(obj).to.have.property('foo'); * expect(obj).to.have.property('foo', 'bar'); * * // deep referencing * var deepObj = { * green: { tea: 'matcha' } * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ] * }; * * expect(deepObj).to.have.deep.property('green.tea', 'matcha'); * expect(deepObj).to.have.deep.property('teas[1]', 'matcha'); * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); * * You can also use an array as the starting point of a `deep.property` * assertion, or traverse nested arrays. * * var arr = [ * [ 'chai', 'matcha', 'konacha' ] * , [ { tea: 'chai' } * , { tea: 'matcha' } * , { tea: 'konacha' } ] * ]; * * expect(arr).to.have.deep.property('[0][1]', 'matcha'); * expect(arr).to.have.deep.property('[1][2].tea', 'konacha'); * * Furthermore, `property` changes the subject of the assertion * to be the value of that property from the original object. This * permits for further chainable assertions on that property. * * expect(obj).to.have.property('foo') * .that.is.a('string'); * expect(deepObj).to.have.property('green') * .that.is.an('object') * .that.deep.equals({ tea: 'matcha' }); * expect(deepObj).to.have.property('teas') * .that.is.an('array') * .with.deep.property('[2]') * .that.deep.equals({ tea: 'konacha' }); * * Note that dots and bracket in `name` must be backslash-escaped when * the `deep` flag is set, while they must NOT be escaped when the `deep` * flag is not set. * * // simple referencing * var css = { '.link[target]': 42 }; * expect(css).to.have.property('.link[target]', 42); * * // deep referencing * var deepCss = { '.link': { '[target]': 42 }}; * expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42); * * @name property * @alias deep.property * @param {String} name * @param {Mixed} value (optional) * @param {String} message _optional_ * @returns value of property for chaining * @namespace BDD * @api public */ Assertion.addMethod('property', function (name, val, msg) { if (msg) flag(this, 'message', msg); var isDeep = !!flag(this, 'deep') , descriptor = isDeep ? 'deep property ' : 'property ' , negate = flag(this, 'negate') , obj = flag(this, 'object') , pathInfo = isDeep ? _.getPathInfo(name, obj) : null , hasProperty = isDeep ? pathInfo.exists : _.hasProperty(name, obj) , value = isDeep ? pathInfo.value : obj[name]; if (negate && arguments.length > 1) { if (undefined === value) { msg = (msg != null) ? msg + ': ' : ''; throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name)); } } else { this.assert( hasProperty , 'expected #{this} to have a ' + descriptor + _.inspect(name) , 'expected #{this} to not have ' + descriptor + _.inspect(name)); } if (arguments.length > 1) { this.assert( val === value , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}' , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}' , val , value ); } flag(this, 'object', value); }); /** * ### .ownProperty(name) * * Asserts that the target has an own property `name`. * * expect('test').to.have.ownProperty('length'); * * @name ownProperty * @alias haveOwnProperty * @param {String} name * @param {String} message _optional_ * @namespace BDD * @api public */ function assertOwnProperty (name, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); this.assert( obj.hasOwnProperty(name) , 'expected #{this} to have own property ' + _.inspect(name) , 'expected #{this} to not have own property ' + _.inspect(name) ); } Assertion.addMethod('ownProperty', assertOwnProperty); Assertion.addMethod('haveOwnProperty', assertOwnProperty); /** * ### .ownPropertyDescriptor(name[, descriptor[, message]]) * * Asserts that the target has an own property descriptor `name`, that optionally matches `descriptor`. * * expect('test').to.have.ownPropertyDescriptor('length'); * expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 }); * expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 }); * expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false); * expect('test').ownPropertyDescriptor('length').to.have.keys('value'); * * @name ownPropertyDescriptor * @alias haveOwnPropertyDescriptor * @param {String} name * @param {Object} descriptor _optional_ * @param {String} message _optional_ * @namespace BDD * @api public */ function assertOwnPropertyDescriptor (name, descriptor, msg) { if (typeof descriptor === 'string') { msg = descriptor; descriptor = null; } if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name); if (actualDescriptor && descriptor) { this.assert( _.eql(descriptor, actualDescriptor) , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor) , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor) , descriptor , actualDescriptor , true ); } else { this.assert( actualDescriptor , 'expected #{this} to have an own property descriptor for ' + _.inspect(name) , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name) ); } flag(this, 'object', actualDescriptor); } Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor); Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor); /** * ### .length * * Sets the `doLength` flag later used as a chain precursor to a value * comparison for the `length` property. * * expect('foo').to.have.length.above(2); * expect([ 1, 2, 3 ]).to.have.length.above(2); * expect('foo').to.have.length.below(4); * expect([ 1, 2, 3 ]).to.have.length.below(4); * expect('foo').to.have.length.within(2,4); * expect([ 1, 2, 3 ]).to.have.length.within(2,4); * * *Deprecation notice:* Using `length` as an assertion will be deprecated * in version 2.4.0 and removed in 3.0.0. Code using the old style of * asserting for `length` property value using `length(value)` should be * switched to use `lengthOf(value)` instead. * * @name length * @namespace BDD * @api public */ /** * ### .lengthOf(value[, message]) * * Asserts that the target's `length` property has * the expected value. * * expect([ 1, 2, 3]).to.have.lengthOf(3); * expect('foobar').to.have.lengthOf(6); * * @name lengthOf * @param {Number} length * @param {String} message _optional_ * @namespace BDD * @api public */ function assertLengthChain () { flag(this, 'doLength', true); } function assertLength (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len == n , 'expected #{this} to have a length of #{exp} but got #{act}' , 'expected #{this} to not have a length of #{act}' , n , len ); } Assertion.addChainableMethod('length', assertLength, assertLengthChain); Assertion.addMethod('lengthOf', assertLength); /** * ### .match(regexp) * * Asserts that the target matches a regular expression. * * expect('foobar').to.match(/^foo/); * * @name match * @alias matches * @param {RegExp} RegularExpression * @param {String} message _optional_ * @namespace BDD * @api public */ function assertMatch(re, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); this.assert( re.exec(obj) , 'expected #{this} to match ' + re , 'expected #{this} not to match ' + re ); } Assertion.addMethod('match', assertMatch); Assertion.addMethod('matches', assertMatch); /** * ### .string(string) * * Asserts that the string target contains another string. * * expect('foobar').to.have.string('bar'); * * @name string * @param {String} string * @param {String} message _optional_ * @namespace BDD * @api public */ Assertion.addMethod('string', function (str, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj, msg).is.a('string'); this.assert( ~obj.indexOf(str) , 'expected #{this} to contain ' + _.inspect(str) , 'expected #{this} to not contain ' + _.inspect(str) ); }); /** * ### .keys(key1, [key2], [...]) * * Asserts that the target contains any or all of the passed-in keys. * Use in combination with `any`, `all`, `contains`, or `have` will affect * what will pass. * * When used in conjunction with `any`, at least one key that is passed * in must exist in the target object. This is regardless whether or not * the `have` or `contain` qualifiers are used. Note, either `any` or `all` * should be used in the assertion. If neither are used, the assertion is * defaulted to `all`. * * When both `all` and `contain` are used, the target object must have at * least all of the passed-in keys but may have more keys not listed. * * When both `all` and `have` are used, the target object must both contain * all of the passed-in keys AND the number of keys in the target object must * match the number of keys passed in (in other words, a target object must * have all and only all of the passed-in keys). * * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz'); * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo'); * expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz'); * expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']); * expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6}); * expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']); * expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo': 7}); * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']); * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys({'bar': 6}); * * * @name keys * @alias key * @param {...String|Array|Object} keys * @namespace BDD * @api public */ function assertKeys (keys) { var obj = flag(this, 'object') , str , ok = true , mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments'; switch (_.type(keys)) { case "array": if (arguments.length > 1) throw (new Error(mixedArgsMsg)); break; case "object": if (arguments.length > 1) throw (new Error(mixedArgsMsg)); keys = Object.keys(keys); break; default: keys = Array.prototype.slice.call(arguments); } if (!keys.length) throw new Error('keys required'); var actual = Object.keys(obj) , expected = keys , len = keys.length , any = flag(this, 'any') , all = flag(this, 'all'); if (!any && !all) { all = true; } // Has any if (any) { var intersection = expected.filter(function(key) { return ~actual.indexOf(key); }); ok = intersection.length > 0; } // Has all if (all) { ok = keys.every(function(key){ return ~actual.indexOf(key); }); if (!flag(this, 'negate') && !flag(this, 'contains')) { ok = ok && keys.length == actual.length; } } // Key string if (len > 1) { keys = keys.map(function(key){ return _.inspect(key); }); var last = keys.pop(); if (all) { str = keys.join(', ') + ', and ' + last; } if (any) { str = keys.join(', ') + ', or ' + last; } } else { str = _.inspect(keys[0]); } // Form str = (len > 1 ? 'keys ' : 'key ') + str; // Have / include str = (flag(this, 'contains') ? 'contain ' : 'have ') + str; // Assertion this.assert( ok , 'expected #{this} to ' + str , 'expected #{this} to not ' + str , expected.slice(0).sort() , actual.sort() , true ); } Assertion.addMethod('keys', assertKeys); Assertion.addMethod('key', assertKeys); /** * ### .throw(constructor) * * Asserts that the function target will throw a specific error, or specific type of error * (as determined using `instanceof`), optionally with a RegExp or string inclusion test * for the error's message. * * var err = new ReferenceError('This is a bad function.'); * var fn = function () { throw err; } * expect(fn).to.throw(ReferenceError); * expect(fn).to.throw(Error); * expect(fn).to.throw(/bad function/); * expect(fn).to.not.throw('good function'); * expect(fn).to.throw(ReferenceError, /bad function/); * expect(fn).to.throw(err); * * Please note that when a throw expectation is negated, it will check each * parameter independently, starting with error constructor type. The appropriate way * to check for the existence of a type of error but for a message that does not match * is to use `and`. * * expect(fn).to.throw(ReferenceError) * .and.not.throw(/good function/); * * @name throw * @alias throws * @alias Throw * @param {ErrorConstructor} constructor * @param {String|RegExp} expected error message * @param {String} message _optional_ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types * @returns error for chaining (null if no error) * @namespace BDD * @api public */ function assertThrows (constructor, errMsg, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj, msg).is.a('function'); var thrown = false , desiredError = null , name = null , thrownError = null; if (arguments.length === 0) { errMsg = null; constructor = null; } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) { errMsg = constructor; constructor = null; } else if (constructor && constructor instanceof Error) { desiredError = constructor; constructor = null; errMsg = null; } else if (typeof constructor === 'function') { name = constructor.prototype.name; if (!name || (name === 'Error' && constructor !== Error)) { name = constructor.name || (new constructor()).name; } } else { constructor = null; } try { obj(); } catch (err) { // first, check desired error if (desiredError) { this.assert( err === desiredError , 'expected #{this} to throw #{exp} but #{act} was thrown' , 'expected #{this} to not throw #{exp}' , (desiredError instanceof Error ? desiredError.toString() : desiredError) , (err instanceof Error ? err.toString() : err) ); flag(this, 'object', err); return this; } // next, check constructor if (constructor) { this.assert( err instanceof constructor , 'expected #{this} to throw #{exp} but #{act} was thrown' , 'expected #{this} to not throw #{exp} but #{act} was thrown' , name , (err instanceof Error ? err.toString() : err) ); if (!errMsg) { flag(this, 'object', err); return this; } } // next, check message var message = 'error' === _.type(err) && "message" in err ? err.message : '' + err; if ((message != null) && errMsg && errMsg instanceof RegExp) { this.assert( errMsg.exec(message) , 'expected #{this} to throw error matching #{exp} but got #{act}' , 'expected #{this} to throw error not matching #{exp}' , errMsg , message ); flag(this, 'object', err); return this; } else if ((message != null) && errMsg && 'string' === typeof errMsg) { this.assert( ~message.indexOf(errMsg) , 'expected #{this} to throw error including #{exp} but got #{act}' , 'expected #{this} to throw error not including #{act}' , errMsg , message ); flag(this, 'object', err); return this; } else { thrown = true; thrownError = err; } } var actuallyGot = '' , expectedThrown = name !== null ? name : desiredError ? '#{exp}' //_.inspect(desiredError) : 'an error'; if (thrown) { actuallyGot = ' but #{act} was thrown' } this.assert( thrown === true , 'expected #{this} to throw ' + expectedThrown + actuallyGot , 'expected #{this} to not throw ' + expectedThrown + actuallyGot , (desiredError instanceof Error ? desiredError.toString() : desiredError) , (thrownError instanceof Error ? thrownError.toString() : thrownError) ); flag(this, 'object', thrownError); }; Assertion.addMethod('throw', assertThrows); Assertion.addMethod('throws', assertThrows); Assertion.addMethod('Throw', assertThrows); /** * ### .respondTo(method) * * Asserts that the object or class target will respond to a method. * * Klass.prototype.bar = function(){}; * expect(Klass).to.respondTo('bar'); * expect(obj).to.respondTo('bar'); * * To check if a constructor will respond to a static function, * set the `itself` flag. * * Klass.baz = function(){}; * expect(Klass).itself.to.respondTo('baz'); * * @name respondTo * @alias respondsTo * @param {String} method * @param {String} message _optional_ * @namespace BDD * @api public */ function respondTo (method, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') , itself = flag(this, 'itself') , context = ('function' === _.type(obj) && !itself) ? obj.prototype[method] : obj[method]; this.assert( 'function' === typeof context , 'expected #{this} to respond to ' + _.inspect(method) , 'expected #{this} to not respond to ' + _.inspect(method) ); } Assertion.addMethod('respondTo', respondTo); Assertion.addMethod('respondsTo', respondTo); /** * ### .itself * * Sets the `itself` flag, later used by the `respondTo` assertion. * * function Foo() {} * Foo.bar = function() {} * Foo.prototype.baz = function() {} * * expect(Foo).itself.to.respondTo('bar'); * expect(Foo).itself.not.to.respondTo('baz'); * * @name itself * @namespace BDD * @api public */ Assertion.addProperty('itself', function () { flag(this, 'itself', true); }); /** * ### .satisfy(method) * * Asserts that the target passes a given truth test. * * expect(1).to.satisfy(function(num) { return num > 0; }); * * @name satisfy * @alias satisfies * @param {Function} matcher * @param {String} message _optional_ * @namespace BDD * @api public */ function satisfy (matcher, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); var result = matcher(obj); this.assert( result , 'expected #{this} to satisfy ' + _.objDisplay(matcher) , 'expected #{this} to not satisfy' + _.objDisplay(matcher) , this.negate ? false : true , result ); } Assertion.addMethod('satisfy', satisfy); Assertion.addMethod('satisfies', satisfy); /** * ### .closeTo(expected, delta) * * Asserts that the target is equal `expected`, to within a +/- `delta` range. * * expect(1.5).to.be.closeTo(1, 0.5); * * @name closeTo * @alias approximately * @param {Number} expected * @param {Number} delta * @param {String} message _optional_ * @namespace BDD * @api public */ function closeTo(expected, delta, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj, msg).is.a('number'); if (_.type(expected) !== 'number' || _.type(delta) !== 'number') { throw new Error('the arguments to closeTo or approximately must be numbers'); } this.assert( Math.abs(obj - expected) <= delta , 'expected #{this} to be close to ' + expected + ' +/- ' + delta , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta ); } Assertion.addMethod('closeTo', closeTo); Assertion.addMethod('approximately', closeTo); function isSubsetOf(subset, superset, cmp) { return subset.every(function(elem) { if (!cmp) return superset.indexOf(elem) !== -1; return superset.some(function(elem2) { return cmp(elem, elem2); }); }) } /** * ### .members(set) * * Asserts that the target is a superset of `set`, * or that the target and `set` have the same strictly-equal (===) members. * Alternately, if the `deep` flag is set, set members are compared for deep * equality. * * expect([1, 2, 3]).to.include.members([3, 2]); * expect([1, 2, 3]).to.not.include.members([3, 2, 8]); * * expect([4, 2]).to.have.members([2, 4]); * expect([5, 2]).to.not.have.members([5, 2, 1]); * * expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]); * * @name members * @param {Array} set * @param {String} message _optional_ * @namespace BDD * @api public */ Assertion.addMethod('members', function (subset, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj).to.be.an('array'); new Assertion(subset).to.be.an('array'); var cmp = flag(this, 'deep') ? _.eql : undefined; if (flag(this, 'contains')) { return this.assert( isSubsetOf(subset, obj, cmp) , 'expected #{this} to be a superset of #{act}' , 'expected #{this} to not be a superset of #{act}' , obj , subset ); } this.assert( isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp) , 'expected #{this} to have the same members as #{act}' , 'expected #{this} to not have the same members as #{act}' , obj , subset ); }); /** * ### .oneOf(list) * * Assert that a value appears somewhere in the top level of array `list`. * * expect('a').to.be.oneOf(['a', 'b', 'c']); * expect(9).to.not.be.oneOf(['z']); * expect([3]).to.not.be.oneOf([1, 2, [3]]); * * var three = [3]; * // for object-types, contents are not compared * expect(three).to.not.be.oneOf([1, 2, [3]]); * // comparing references works * expect(three).to.be.oneOf([1, 2, three]); * * @name oneOf * @param {Array<*>} list * @param {String} message _optional_ * @namespace BDD * @api public */ function oneOf (list, msg) { if (msg) flag(this, 'message', msg); var expected = flag(this, 'object'); new Assertion(list).to.be.an('array'); this.assert( list.indexOf(expected) > -1 , 'expected #{this} to be one of #{exp}' , 'expected #{this} to not be one of #{exp}' , list , expected ); } Assertion.addMethod('oneOf', oneOf); /** * ### .change(function) * * Asserts that a function changes an object property * * var obj = { val: 10 }; * var fn = function() { obj.val += 3 }; * var noChangeFn = function() { return 'foo' + 'bar'; } * expect(fn).to.change(obj, 'val'); * expect(noChangeFn).to.not.change(obj, 'val') * * @name change * @alias changes * @alias Change * @param {String} object * @param {String} property name * @param {String} message _optional_ * @namespace BDD * @api public */ function assertChanges (object, prop, msg) { if (msg) flag(this, 'message', msg); var fn = flag(this, 'object'); new Assertion(object, msg).to.have.property(prop); new Assertion(fn).is.a('function'); var initial = object[prop]; fn(); this.assert( initial !== object[prop] , 'expected .' + prop + ' to change' , 'expected .' + prop + ' to not change' ); } Assertion.addChainableMethod('change', assertChanges); Assertion.addChainableMethod('changes', assertChanges); /** * ### .increase(function) * * Asserts that a function increases an object property * * var obj = { val: 10 }; * var fn = function() { obj.val = 15 }; * expect(fn).to.increase(obj, 'val'); * * @name increase * @alias increases * @alias Increase * @param {String} object * @param {String} property name * @param {String} message _optional_ * @namespace BDD * @api public */ function assertIncreases (object, prop, msg) { if (msg) flag(this, 'message', msg); var fn = flag(this, 'object'); new Assertion(object, msg).to.have.property(prop); new Assertion(fn).is.a('function'); var initial = object[prop]; fn(); this.assert( object[prop] - initial > 0 , 'expected .' + prop + ' to increase' , 'expected .' + prop + ' to not increase' ); } Assertion.addChainableMethod('increase', assertIncreases); Assertion.addChainableMethod('increases', assertIncreases); /** * ### .decrease(function) * * Asserts that a function decreases an object property * * var obj = { val: 10 }; * var fn = function() { obj.val = 5 }; * expect(fn).to.decrease(obj, 'val'); * * @name decrease * @alias decreases * @alias Decrease * @param {String} object * @param {String} property name * @param {String} message _optional_ * @namespace BDD * @api public */ function assertDecreases (object, prop, msg) { if (msg) flag(this, 'message', msg); var fn = flag(this, 'object'); new Assertion(object, msg).to.have.property(prop); new Assertion(fn).is.a('function'); var initial = object[prop]; fn(); this.assert( object[prop] - initial < 0 , 'expected .' + prop + ' to decrease' , 'expected .' + prop + ' to not decrease' ); } Assertion.addChainableMethod('decrease', assertDecreases); Assertion.addChainableMethod('decreases', assertDecreases); /** * ### .extensible * * Asserts that the target is extensible (can have new properties added to * it). * * var nonExtensibleObject = Object.preventExtensions({}); * var sealedObject = Object.seal({}); * var frozenObject = Object.freeze({}); * * expect({}).to.be.extensible; * expect(nonExtensibleObject).to.not.be.extensible; * expect(sealedObject).to.not.be.extensible; * expect(frozenObject).to.not.be.extensible; * * @name extensible * @namespace BDD * @api public */ Assertion.addProperty('extensible', function() { var obj = flag(this, 'object'); // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError. // In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible // The following provides ES6 behavior when a TypeError is thrown under ES5. var isExtensible; try { isExtensible = Object.isExtensible(obj); } catch (err) { if (err instanceof TypeError) isExtensible = false; else throw err; } this.assert( isExtensible , 'expected #{this} to be extensible' , 'expected #{this} to not be extensible' ); }); /** * ### .sealed * * Asserts that the target is sealed (cannot have new properties added to it * and its existing properties cannot be removed). * * var sealedObject = Object.seal({}); * var frozenObject = Object.freeze({}); * * expect(sealedObject).to.be.sealed; * expect(frozenObject).to.be.sealed; * expect({}).to.not.be.sealed; * * @name sealed * @namespace BDD * @api public */ Assertion.addProperty('sealed', function() { var obj = flag(this, 'object'); // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError. // In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true. // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed // The following provides ES6 behavior when a TypeError is thrown under ES5. var isSealed; try { isSealed = Object.isSealed(obj); } catch (err) { if (err instanceof TypeError) isSealed = true; else throw err; } this.assert( isSealed , 'expected #{this} to be sealed' , 'expected #{this} to not be sealed' ); }); /** * ### .frozen * * Asserts that the target is frozen (cannot have new properties added to it * and its existing properties cannot be modified). * * var frozenObject = Object.freeze({}); * * expect(frozenObject).to.be.frozen; * expect({}).to.not.be.frozen; * * @name frozen * @namespace BDD * @api public */ Assertion.addProperty('frozen', function() { var obj = flag(this, 'object'); // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError. // In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true. // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen // The following provides ES6 behavior when a TypeError is thrown under ES5. var isFrozen; try { isFrozen = Object.isFrozen(obj); } catch (err) { if (err instanceof TypeError) isFrozen = true; else throw err; } this.assert( isFrozen , 'expected #{this} to be frozen' , 'expected #{this} to not be frozen' ); }); }; chai-3.5.0/lib/chai/interface/000775 000000 000000 00000000000 12652401517 016020 5ustar00rootroot000000 000000 chai-3.5.0/lib/chai/interface/assert.js000664 000000 000000 00000117657 12652401517 017700 0ustar00rootroot000000 000000 /*! * chai * Copyright(c) 2011-2014 Jake Luer * MIT Licensed */ module.exports = function (chai, util) { /*! * Chai dependencies. */ var Assertion = chai.Assertion , flag = util.flag; /*! * Module export. */ /** * ### assert(expression, message) * * Write your own test expressions. * * assert('foo' !== 'bar', 'foo is not bar'); * assert(Array.isArray([]), 'empty arrays are arrays'); * * @param {Mixed} expression to test for truthiness * @param {String} message to display on error * @name assert * @namespace Assert * @api public */ var assert = chai.assert = function (express, errmsg) { var test = new Assertion(null, null, chai.assert); test.assert( express , errmsg , '[ negation message unavailable ]' ); }; /** * ### .fail(actual, expected, [message], [operator]) * * Throw a failure. Node.js `assert` module-compatible. * * @name fail * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @param {String} operator * @namespace Assert * @api public */ assert.fail = function (actual, expected, message, operator) { message = message || 'assert.fail()'; throw new chai.AssertionError(message, { actual: actual , expected: expected , operator: operator }, assert.fail); }; /** * ### .isOk(object, [message]) * * Asserts that `object` is truthy. * * assert.isOk('everything', 'everything is ok'); * assert.isOk(false, 'this will fail'); * * @name isOk * @alias ok * @param {Mixed} object to test * @param {String} message * @namespace Assert * @api public */ assert.isOk = function (val, msg) { new Assertion(val, msg).is.ok; }; /** * ### .isNotOk(object, [message]) * * Asserts that `object` is falsy. * * assert.isNotOk('everything', 'this will fail'); * assert.isNotOk(false, 'this will pass'); * * @name isNotOk * @alias notOk * @param {Mixed} object to test * @param {String} message * @namespace Assert * @api public */ assert.isNotOk = function (val, msg) { new Assertion(val, msg).is.not.ok; }; /** * ### .equal(actual, expected, [message]) * * Asserts non-strict equality (`==`) of `actual` and `expected`. * * assert.equal(3, '3', '== coerces values to strings'); * * @name equal * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @namespace Assert * @api public */ assert.equal = function (act, exp, msg) { var test = new Assertion(act, msg, assert.equal); test.assert( exp == flag(test, 'object') , 'expected #{this} to equal #{exp}' , 'expected #{this} to not equal #{act}' , exp , act ); }; /** * ### .notEqual(actual, expected, [message]) * * Asserts non-strict inequality (`!=`) of `actual` and `expected`. * * assert.notEqual(3, 4, 'these numbers are not equal'); * * @name notEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @namespace Assert * @api public */ assert.notEqual = function (act, exp, msg) { var test = new Assertion(act, msg, assert.notEqual); test.assert( exp != flag(test, 'object') , 'expected #{this} to not equal #{exp}' , 'expected #{this} to equal #{act}' , exp , act ); }; /** * ### .strictEqual(actual, expected, [message]) * * Asserts strict equality (`===`) of `actual` and `expected`. * * assert.strictEqual(true, true, 'these booleans are strictly equal'); * * @name strictEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @namespace Assert * @api public */ assert.strictEqual = function (act, exp, msg) { new Assertion(act, msg).to.equal(exp); }; /** * ### .notStrictEqual(actual, expected, [message]) * * Asserts strict inequality (`!==`) of `actual` and `expected`. * * assert.notStrictEqual(3, '3', 'no coercion for strict equality'); * * @name notStrictEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @namespace Assert * @api public */ assert.notStrictEqual = function (act, exp, msg) { new Assertion(act, msg).to.not.equal(exp); }; /** * ### .deepEqual(actual, expected, [message]) * * Asserts that `actual` is deeply equal to `expected`. * * assert.deepEqual({ tea: 'green' }, { tea: 'green' }); * * @name deepEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @namespace Assert * @api public */ assert.deepEqual = function (act, exp, msg) { new Assertion(act, msg).to.eql(exp); }; /** * ### .notDeepEqual(actual, expected, [message]) * * Assert that `actual` is not deeply equal to `expected`. * * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' }); * * @name notDeepEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @namespace Assert * @api public */ assert.notDeepEqual = function (act, exp, msg) { new Assertion(act, msg).to.not.eql(exp); }; /** * ### .isAbove(valueToCheck, valueToBeAbove, [message]) * * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove` * * assert.isAbove(5, 2, '5 is strictly greater than 2'); * * @name isAbove * @param {Mixed} valueToCheck * @param {Mixed} valueToBeAbove * @param {String} message * @namespace Assert * @api public */ assert.isAbove = function (val, abv, msg) { new Assertion(val, msg).to.be.above(abv); }; /** * ### .isAtLeast(valueToCheck, valueToBeAtLeast, [message]) * * Asserts `valueToCheck` is greater than or equal to (>=) `valueToBeAtLeast` * * assert.isAtLeast(5, 2, '5 is greater or equal to 2'); * assert.isAtLeast(3, 3, '3 is greater or equal to 3'); * * @name isAtLeast * @param {Mixed} valueToCheck * @param {Mixed} valueToBeAtLeast * @param {String} message * @namespace Assert * @api public */ assert.isAtLeast = function (val, atlst, msg) { new Assertion(val, msg).to.be.least(atlst); }; /** * ### .isBelow(valueToCheck, valueToBeBelow, [message]) * * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow` * * assert.isBelow(3, 6, '3 is strictly less than 6'); * * @name isBelow * @param {Mixed} valueToCheck * @param {Mixed} valueToBeBelow * @param {String} message * @namespace Assert * @api public */ assert.isBelow = function (val, blw, msg) { new Assertion(val, msg).to.be.below(blw); }; /** * ### .isAtMost(valueToCheck, valueToBeAtMost, [message]) * * Asserts `valueToCheck` is less than or equal to (<=) `valueToBeAtMost` * * assert.isAtMost(3, 6, '3 is less than or equal to 6'); * assert.isAtMost(4, 4, '4 is less than or equal to 4'); * * @name isAtMost * @param {Mixed} valueToCheck * @param {Mixed} valueToBeAtMost * @param {String} message * @namespace Assert * @api public */ assert.isAtMost = function (val, atmst, msg) { new Assertion(val, msg).to.be.most(atmst); }; /** * ### .isTrue(value, [message]) * * Asserts that `value` is true. * * var teaServed = true; * assert.isTrue(teaServed, 'the tea has been served'); * * @name isTrue * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isTrue = function (val, msg) { new Assertion(val, msg).is['true']; }; /** * ### .isNotTrue(value, [message]) * * Asserts that `value` is not true. * * var tea = 'tasty chai'; * assert.isNotTrue(tea, 'great, time for tea!'); * * @name isNotTrue * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNotTrue = function (val, msg) { new Assertion(val, msg).to.not.equal(true); }; /** * ### .isFalse(value, [message]) * * Asserts that `value` is false. * * var teaServed = false; * assert.isFalse(teaServed, 'no tea yet? hmm...'); * * @name isFalse * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isFalse = function (val, msg) { new Assertion(val, msg).is['false']; }; /** * ### .isNotFalse(value, [message]) * * Asserts that `value` is not false. * * var tea = 'tasty chai'; * assert.isNotFalse(tea, 'great, time for tea!'); * * @name isNotFalse * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNotFalse = function (val, msg) { new Assertion(val, msg).to.not.equal(false); }; /** * ### .isNull(value, [message]) * * Asserts that `value` is null. * * assert.isNull(err, 'there was no error'); * * @name isNull * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNull = function (val, msg) { new Assertion(val, msg).to.equal(null); }; /** * ### .isNotNull(value, [message]) * * Asserts that `value` is not null. * * var tea = 'tasty chai'; * assert.isNotNull(tea, 'great, time for tea!'); * * @name isNotNull * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNotNull = function (val, msg) { new Assertion(val, msg).to.not.equal(null); }; /** * ### .isNaN * Asserts that value is NaN * * assert.isNaN('foo', 'foo is NaN'); * * @name isNaN * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNaN = function (val, msg) { new Assertion(val, msg).to.be.NaN; }; /** * ### .isNotNaN * Asserts that value is not NaN * * assert.isNotNaN(4, '4 is not NaN'); * * @name isNotNaN * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNotNaN = function (val, msg) { new Assertion(val, msg).not.to.be.NaN; }; /** * ### .isUndefined(value, [message]) * * Asserts that `value` is `undefined`. * * var tea; * assert.isUndefined(tea, 'no tea defined'); * * @name isUndefined * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isUndefined = function (val, msg) { new Assertion(val, msg).to.equal(undefined); }; /** * ### .isDefined(value, [message]) * * Asserts that `value` is not `undefined`. * * var tea = 'cup of chai'; * assert.isDefined(tea, 'tea has been defined'); * * @name isDefined * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isDefined = function (val, msg) { new Assertion(val, msg).to.not.equal(undefined); }; /** * ### .isFunction(value, [message]) * * Asserts that `value` is a function. * * function serveTea() { return 'cup of tea'; }; * assert.isFunction(serveTea, 'great, we can have tea now'); * * @name isFunction * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isFunction = function (val, msg) { new Assertion(val, msg).to.be.a('function'); }; /** * ### .isNotFunction(value, [message]) * * Asserts that `value` is _not_ a function. * * var serveTea = [ 'heat', 'pour', 'sip' ]; * assert.isNotFunction(serveTea, 'great, we have listed the steps'); * * @name isNotFunction * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNotFunction = function (val, msg) { new Assertion(val, msg).to.not.be.a('function'); }; /** * ### .isObject(value, [message]) * * Asserts that `value` is an object of type 'Object' (as revealed by `Object.prototype.toString`). * _The assertion does not match subclassed objects._ * * var selection = { name: 'Chai', serve: 'with spices' }; * assert.isObject(selection, 'tea selection is an object'); * * @name isObject * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isObject = function (val, msg) { new Assertion(val, msg).to.be.a('object'); }; /** * ### .isNotObject(value, [message]) * * Asserts that `value` is _not_ an object of type 'Object' (as revealed by `Object.prototype.toString`). * * var selection = 'chai' * assert.isNotObject(selection, 'tea selection is not an object'); * assert.isNotObject(null, 'null is not an object'); * * @name isNotObject * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNotObject = function (val, msg) { new Assertion(val, msg).to.not.be.a('object'); }; /** * ### .isArray(value, [message]) * * Asserts that `value` is an array. * * var menu = [ 'green', 'chai', 'oolong' ]; * assert.isArray(menu, 'what kind of tea do we want?'); * * @name isArray * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isArray = function (val, msg) { new Assertion(val, msg).to.be.an('array'); }; /** * ### .isNotArray(value, [message]) * * Asserts that `value` is _not_ an array. * * var menu = 'green|chai|oolong'; * assert.isNotArray(menu, 'what kind of tea do we want?'); * * @name isNotArray * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNotArray = function (val, msg) { new Assertion(val, msg).to.not.be.an('array'); }; /** * ### .isString(value, [message]) * * Asserts that `value` is a string. * * var teaOrder = 'chai'; * assert.isString(teaOrder, 'order placed'); * * @name isString * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isString = function (val, msg) { new Assertion(val, msg).to.be.a('string'); }; /** * ### .isNotString(value, [message]) * * Asserts that `value` is _not_ a string. * * var teaOrder = 4; * assert.isNotString(teaOrder, 'order placed'); * * @name isNotString * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNotString = function (val, msg) { new Assertion(val, msg).to.not.be.a('string'); }; /** * ### .isNumber(value, [message]) * * Asserts that `value` is a number. * * var cups = 2; * assert.isNumber(cups, 'how many cups'); * * @name isNumber * @param {Number} value * @param {String} message * @namespace Assert * @api public */ assert.isNumber = function (val, msg) { new Assertion(val, msg).to.be.a('number'); }; /** * ### .isNotNumber(value, [message]) * * Asserts that `value` is _not_ a number. * * var cups = '2 cups please'; * assert.isNotNumber(cups, 'how many cups'); * * @name isNotNumber * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNotNumber = function (val, msg) { new Assertion(val, msg).to.not.be.a('number'); }; /** * ### .isBoolean(value, [message]) * * Asserts that `value` is a boolean. * * var teaReady = true * , teaServed = false; * * assert.isBoolean(teaReady, 'is the tea ready'); * assert.isBoolean(teaServed, 'has tea been served'); * * @name isBoolean * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isBoolean = function (val, msg) { new Assertion(val, msg).to.be.a('boolean'); }; /** * ### .isNotBoolean(value, [message]) * * Asserts that `value` is _not_ a boolean. * * var teaReady = 'yep' * , teaServed = 'nope'; * * assert.isNotBoolean(teaReady, 'is the tea ready'); * assert.isNotBoolean(teaServed, 'has tea been served'); * * @name isNotBoolean * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.isNotBoolean = function (val, msg) { new Assertion(val, msg).to.not.be.a('boolean'); }; /** * ### .typeOf(value, name, [message]) * * Asserts that `value`'s type is `name`, as determined by * `Object.prototype.toString`. * * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object'); * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array'); * assert.typeOf('tea', 'string', 'we have a string'); * assert.typeOf(/tea/, 'regexp', 'we have a regular expression'); * assert.typeOf(null, 'null', 'we have a null'); * assert.typeOf(undefined, 'undefined', 'we have an undefined'); * * @name typeOf * @param {Mixed} value * @param {String} name * @param {String} message * @namespace Assert * @api public */ assert.typeOf = function (val, type, msg) { new Assertion(val, msg).to.be.a(type); }; /** * ### .notTypeOf(value, name, [message]) * * Asserts that `value`'s type is _not_ `name`, as determined by * `Object.prototype.toString`. * * assert.notTypeOf('tea', 'number', 'strings are not numbers'); * * @name notTypeOf * @param {Mixed} value * @param {String} typeof name * @param {String} message * @namespace Assert * @api public */ assert.notTypeOf = function (val, type, msg) { new Assertion(val, msg).to.not.be.a(type); }; /** * ### .instanceOf(object, constructor, [message]) * * Asserts that `value` is an instance of `constructor`. * * var Tea = function (name) { this.name = name; } * , chai = new Tea('chai'); * * assert.instanceOf(chai, Tea, 'chai is an instance of tea'); * * @name instanceOf * @param {Object} object * @param {Constructor} constructor * @param {String} message * @namespace Assert * @api public */ assert.instanceOf = function (val, type, msg) { new Assertion(val, msg).to.be.instanceOf(type); }; /** * ### .notInstanceOf(object, constructor, [message]) * * Asserts `value` is not an instance of `constructor`. * * var Tea = function (name) { this.name = name; } * , chai = new String('chai'); * * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea'); * * @name notInstanceOf * @param {Object} object * @param {Constructor} constructor * @param {String} message * @namespace Assert * @api public */ assert.notInstanceOf = function (val, type, msg) { new Assertion(val, msg).to.not.be.instanceOf(type); }; /** * ### .include(haystack, needle, [message]) * * Asserts that `haystack` includes `needle`. Works * for strings and arrays. * * assert.include('foobar', 'bar', 'foobar contains string "bar"'); * assert.include([ 1, 2, 3 ], 3, 'array contains value'); * * @name include * @param {Array|String} haystack * @param {Mixed} needle * @param {String} message * @namespace Assert * @api public */ assert.include = function (exp, inc, msg) { new Assertion(exp, msg, assert.include).include(inc); }; /** * ### .notInclude(haystack, needle, [message]) * * Asserts that `haystack` does not include `needle`. Works * for strings and arrays. * * assert.notInclude('foobar', 'baz', 'string not include substring'); * assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value'); * * @name notInclude * @param {Array|String} haystack * @param {Mixed} needle * @param {String} message * @namespace Assert * @api public */ assert.notInclude = function (exp, inc, msg) { new Assertion(exp, msg, assert.notInclude).not.include(inc); }; /** * ### .match(value, regexp, [message]) * * Asserts that `value` matches the regular expression `regexp`. * * assert.match('foobar', /^foo/, 'regexp matches'); * * @name match * @param {Mixed} value * @param {RegExp} regexp * @param {String} message * @namespace Assert * @api public */ assert.match = function (exp, re, msg) { new Assertion(exp, msg).to.match(re); }; /** * ### .notMatch(value, regexp, [message]) * * Asserts that `value` does not match the regular expression `regexp`. * * assert.notMatch('foobar', /^foo/, 'regexp does not match'); * * @name notMatch * @param {Mixed} value * @param {RegExp} regexp * @param {String} message * @namespace Assert * @api public */ assert.notMatch = function (exp, re, msg) { new Assertion(exp, msg).to.not.match(re); }; /** * ### .property(object, property, [message]) * * Asserts that `object` has a property named by `property`. * * assert.property({ tea: { green: 'matcha' }}, 'tea'); * * @name property * @param {Object} object * @param {String} property * @param {String} message * @namespace Assert * @api public */ assert.property = function (obj, prop, msg) { new Assertion(obj, msg).to.have.property(prop); }; /** * ### .notProperty(object, property, [message]) * * Asserts that `object` does _not_ have a property named by `property`. * * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee'); * * @name notProperty * @param {Object} object * @param {String} property * @param {String} message * @namespace Assert * @api public */ assert.notProperty = function (obj, prop, msg) { new Assertion(obj, msg).to.not.have.property(prop); }; /** * ### .deepProperty(object, property, [message]) * * Asserts that `object` has a property named by `property`, which can be a * string using dot- and bracket-notation for deep reference. * * assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green'); * * @name deepProperty * @param {Object} object * @param {String} property * @param {String} message * @namespace Assert * @api public */ assert.deepProperty = function (obj, prop, msg) { new Assertion(obj, msg).to.have.deep.property(prop); }; /** * ### .notDeepProperty(object, property, [message]) * * Asserts that `object` does _not_ have a property named by `property`, which * can be a string using dot- and bracket-notation for deep reference. * * assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong'); * * @name notDeepProperty * @param {Object} object * @param {String} property * @param {String} message * @namespace Assert * @api public */ assert.notDeepProperty = function (obj, prop, msg) { new Assertion(obj, msg).to.not.have.deep.property(prop); }; /** * ### .propertyVal(object, property, value, [message]) * * Asserts that `object` has a property named by `property` with value given * by `value`. * * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good'); * * @name propertyVal * @param {Object} object * @param {String} property * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.propertyVal = function (obj, prop, val, msg) { new Assertion(obj, msg).to.have.property(prop, val); }; /** * ### .propertyNotVal(object, property, value, [message]) * * Asserts that `object` has a property named by `property`, but with a value * different from that given by `value`. * * assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad'); * * @name propertyNotVal * @param {Object} object * @param {String} property * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.propertyNotVal = function (obj, prop, val, msg) { new Assertion(obj, msg).to.not.have.property(prop, val); }; /** * ### .deepPropertyVal(object, property, value, [message]) * * Asserts that `object` has a property named by `property` with value given * by `value`. `property` can use dot- and bracket-notation for deep * reference. * * assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha'); * * @name deepPropertyVal * @param {Object} object * @param {String} property * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.deepPropertyVal = function (obj, prop, val, msg) { new Assertion(obj, msg).to.have.deep.property(prop, val); }; /** * ### .deepPropertyNotVal(object, property, value, [message]) * * Asserts that `object` has a property named by `property`, but with a value * different from that given by `value`. `property` can use dot- and * bracket-notation for deep reference. * * assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha'); * * @name deepPropertyNotVal * @param {Object} object * @param {String} property * @param {Mixed} value * @param {String} message * @namespace Assert * @api public */ assert.deepPropertyNotVal = function (obj, prop, val, msg) { new Assertion(obj, msg).to.not.have.deep.property(prop, val); }; /** * ### .lengthOf(object, length, [message]) * * Asserts that `object` has a `length` property with the expected value. * * assert.lengthOf([1,2,3], 3, 'array has length of 3'); * assert.lengthOf('foobar', 6, 'string has length of 6'); * * @name lengthOf * @param {Mixed} object * @param {Number} length * @param {String} message * @namespace Assert * @api public */ assert.lengthOf = function (exp, len, msg) { new Assertion(exp, msg).to.have.length(len); }; /** * ### .throws(function, [constructor/string/regexp], [string/regexp], [message]) * * Asserts that `function` will throw an error that is an instance of * `constructor`, or alternately that it will throw an error with message * matching `regexp`. * * assert.throws(fn, 'function throws a reference error'); * assert.throws(fn, /function throws a reference error/); * assert.throws(fn, ReferenceError); * assert.throws(fn, ReferenceError, 'function throws a reference error'); * assert.throws(fn, ReferenceError, /function throws a reference error/); * * @name throws * @alias throw * @alias Throw * @param {Function} function * @param {ErrorConstructor} constructor * @param {RegExp} regexp * @param {String} message * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types * @namespace Assert * @api public */ assert.throws = function (fn, errt, errs, msg) { if ('string' === typeof errt || errt instanceof RegExp) { errs = errt; errt = null; } var assertErr = new Assertion(fn, msg).to.throw(errt, errs); return flag(assertErr, 'object'); }; /** * ### .doesNotThrow(function, [constructor/regexp], [message]) * * Asserts that `function` will _not_ throw an error that is an instance of * `constructor`, or alternately that it will not throw an error with message * matching `regexp`. * * assert.doesNotThrow(fn, Error, 'function does not throw'); * * @name doesNotThrow * @param {Function} function * @param {ErrorConstructor} constructor * @param {RegExp} regexp * @param {String} message * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types * @namespace Assert * @api public */ assert.doesNotThrow = function (fn, type, msg) { if ('string' === typeof type) { msg = type; type = null; } new Assertion(fn, msg).to.not.Throw(type); }; /** * ### .operator(val1, operator, val2, [message]) * * Compares two values using `operator`. * * assert.operator(1, '<', 2, 'everything is ok'); * assert.operator(1, '>', 2, 'this will fail'); * * @name operator * @param {Mixed} val1 * @param {String} operator * @param {Mixed} val2 * @param {String} message * @namespace Assert * @api public */ assert.operator = function (val, operator, val2, msg) { var ok; switch(operator) { case '==': ok = val == val2; break; case '===': ok = val === val2; break; case '>': ok = val > val2; break; case '>=': ok = val >= val2; break; case '<': ok = val < val2; break; case '<=': ok = val <= val2; break; case '!=': ok = val != val2; break; case '!==': ok = val !== val2; break; default: throw new Error('Invalid operator "' + operator + '"'); } var test = new Assertion(ok, msg); test.assert( true === flag(test, 'object') , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2) , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) ); }; /** * ### .closeTo(actual, expected, delta, [message]) * * Asserts that the target is equal `expected`, to within a +/- `delta` range. * * assert.closeTo(1.5, 1, 0.5, 'numbers are close'); * * @name closeTo * @param {Number} actual * @param {Number} expected * @param {Number} delta * @param {String} message * @namespace Assert * @api public */ assert.closeTo = function (act, exp, delta, msg) { new Assertion(act, msg).to.be.closeTo(exp, delta); }; /** * ### .approximately(actual, expected, delta, [message]) * * Asserts that the target is equal `expected`, to within a +/- `delta` range. * * assert.approximately(1.5, 1, 0.5, 'numbers are close'); * * @name approximately * @param {Number} actual * @param {Number} expected * @param {Number} delta * @param {String} message * @namespace Assert * @api public */ assert.approximately = function (act, exp, delta, msg) { new Assertion(act, msg).to.be.approximately(exp, delta); }; /** * ### .sameMembers(set1, set2, [message]) * * Asserts that `set1` and `set2` have the same members. * Order is not taken into account. * * assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members'); * * @name sameMembers * @param {Array} set1 * @param {Array} set2 * @param {String} message * @namespace Assert * @api public */ assert.sameMembers = function (set1, set2, msg) { new Assertion(set1, msg).to.have.same.members(set2); } /** * ### .sameDeepMembers(set1, set2, [message]) * * Asserts that `set1` and `set2` have the same members - using a deep equality checking. * Order is not taken into account. * * assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members'); * * @name sameDeepMembers * @param {Array} set1 * @param {Array} set2 * @param {String} message * @namespace Assert * @api public */ assert.sameDeepMembers = function (set1, set2, msg) { new Assertion(set1, msg).to.have.same.deep.members(set2); } /** * ### .includeMembers(superset, subset, [message]) * * Asserts that `subset` is included in `superset`. * Order is not taken into account. * * assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members'); * * @name includeMembers * @param {Array} superset * @param {Array} subset * @param {String} message * @namespace Assert * @api public */ assert.includeMembers = function (superset, subset, msg) { new Assertion(superset, msg).to.include.members(subset); } /** * ### .includeDeepMembers(superset, subset, [message]) * * Asserts that `subset` is included in `superset` - using deep equality checking. * Order is not taken into account. * Duplicates are ignored. * * assert.includeDeepMembers([ {a: 1}, {b: 2}, {c: 3} ], [ {b: 2}, {a: 1}, {b: 2} ], 'include deep members'); * * @name includeDeepMembers * @param {Array} superset * @param {Array} subset * @param {String} message * @namespace Assert * @api public */ assert.includeDeepMembers = function (superset, subset, msg) { new Assertion(superset, msg).to.include.deep.members(subset); } /** * ### .oneOf(inList, list, [message]) * * Asserts that non-object, non-array value `inList` appears in the flat array `list`. * * assert.oneOf(1, [ 2, 1 ], 'Not found in list'); * * @name oneOf * @param {*} inList * @param {Array<*>} list * @param {String} message * @namespace Assert * @api public */ assert.oneOf = function (inList, list, msg) { new Assertion(inList, msg).to.be.oneOf(list); } /** * ### .changes(function, object, property) * * Asserts that a function changes the value of a property * * var obj = { val: 10 }; * var fn = function() { obj.val = 22 }; * assert.changes(fn, obj, 'val'); * * @name changes * @param {Function} modifier function * @param {Object} object * @param {String} property name * @param {String} message _optional_ * @namespace Assert * @api public */ assert.changes = function (fn, obj, prop) { new Assertion(fn).to.change(obj, prop); } /** * ### .doesNotChange(function, object, property) * * Asserts that a function does not changes the value of a property * * var obj = { val: 10 }; * var fn = function() { console.log('foo'); }; * assert.doesNotChange(fn, obj, 'val'); * * @name doesNotChange * @param {Function} modifier function * @param {Object} object * @param {String} property name * @param {String} message _optional_ * @namespace Assert * @api public */ assert.doesNotChange = function (fn, obj, prop) { new Assertion(fn).to.not.change(obj, prop); } /** * ### .increases(function, object, property) * * Asserts that a function increases an object property * * var obj = { val: 10 }; * var fn = function() { obj.val = 13 }; * assert.increases(fn, obj, 'val'); * * @name increases * @param {Function} modifier function * @param {Object} object * @param {String} property name * @param {String} message _optional_ * @namespace Assert * @api public */ assert.increases = function (fn, obj, prop) { new Assertion(fn).to.increase(obj, prop); } /** * ### .doesNotIncrease(function, object, property) * * Asserts that a function does not increase object property * * var obj = { val: 10 }; * var fn = function() { obj.val = 8 }; * assert.doesNotIncrease(fn, obj, 'val'); * * @name doesNotIncrease * @param {Function} modifier function * @param {Object} object * @param {String} property name * @param {String} message _optional_ * @namespace Assert * @api public */ assert.doesNotIncrease = function (fn, obj, prop) { new Assertion(fn).to.not.increase(obj, prop); } /** * ### .decreases(function, object, property) * * Asserts that a function decreases an object property * * var obj = { val: 10 }; * var fn = function() { obj.val = 5 }; * assert.decreases(fn, obj, 'val'); * * @name decreases * @param {Function} modifier function * @param {Object} object * @param {String} property name * @param {String} message _optional_ * @namespace Assert * @api public */ assert.decreases = function (fn, obj, prop) { new Assertion(fn).to.decrease(obj, prop); } /** * ### .doesNotDecrease(function, object, property) * * Asserts that a function does not decreases an object property * * var obj = { val: 10 }; * var fn = function() { obj.val = 15 }; * assert.doesNotDecrease(fn, obj, 'val'); * * @name doesNotDecrease * @param {Function} modifier function * @param {Object} object * @param {String} property name * @param {String} message _optional_ * @namespace Assert * @api public */ assert.doesNotDecrease = function (fn, obj, prop) { new Assertion(fn).to.not.decrease(obj, prop); } /*! * ### .ifError(object) * * Asserts if value is not a false value, and throws if it is a true value. * This is added to allow for chai to be a drop-in replacement for Node's * assert class. * * var err = new Error('I am a custom error'); * assert.ifError(err); // Rethrows err! * * @name ifError * @param {Object} object * @namespace Assert * @api public */ assert.ifError = function (val) { if (val) { throw(val); } }; /** * ### .isExtensible(object) * * Asserts that `object` is extensible (can have new properties added to it). * * assert.isExtensible({}); * * @name isExtensible * @alias extensible * @param {Object} object * @param {String} message _optional_ * @namespace Assert * @api public */ assert.isExtensible = function (obj, msg) { new Assertion(obj, msg).to.be.extensible; }; /** * ### .isNotExtensible(object) * * Asserts that `object` is _not_ extensible. * * var nonExtensibleObject = Object.preventExtensions({}); * var sealedObject = Object.seal({}); * var frozenObject = Object.freese({}); * * assert.isNotExtensible(nonExtensibleObject); * assert.isNotExtensible(sealedObject); * assert.isNotExtensible(frozenObject); * * @name isNotExtensible * @alias notExtensible * @param {Object} object * @param {String} message _optional_ * @namespace Assert * @api public */ assert.isNotExtensible = function (obj, msg) { new Assertion(obj, msg).to.not.be.extensible; }; /** * ### .isSealed(object) * * Asserts that `object` is sealed (cannot have new properties added to it * and its existing properties cannot be removed). * * var sealedObject = Object.seal({}); * var frozenObject = Object.seal({}); * * assert.isSealed(sealedObject); * assert.isSealed(frozenObject); * * @name isSealed * @alias sealed * @param {Object} object * @param {String} message _optional_ * @namespace Assert * @api public */ assert.isSealed = function (obj, msg) { new Assertion(obj, msg).to.be.sealed; }; /** * ### .isNotSealed(object) * * Asserts that `object` is _not_ sealed. * * assert.isNotSealed({}); * * @name isNotSealed * @alias notSealed * @param {Object} object * @param {String} message _optional_ * @namespace Assert * @api public */ assert.isNotSealed = function (obj, msg) { new Assertion(obj, msg).to.not.be.sealed; }; /** * ### .isFrozen(object) * * Asserts that `object` is frozen (cannot have new properties added to it * and its existing properties cannot be modified). * * var frozenObject = Object.freeze({}); * assert.frozen(frozenObject); * * @name isFrozen * @alias frozen * @param {Object} object * @param {String} message _optional_ * @namespace Assert * @api public */ assert.isFrozen = function (obj, msg) { new Assertion(obj, msg).to.be.frozen; }; /** * ### .isNotFrozen(object) * * Asserts that `object` is _not_ frozen. * * assert.isNotFrozen({}); * * @name isNotFrozen * @alias notFrozen * @param {Object} object * @param {String} message _optional_ * @namespace Assert * @api public */ assert.isNotFrozen = function (obj, msg) { new Assertion(obj, msg).to.not.be.frozen; }; /*! * Aliases. */ (function alias(name, as){ assert[as] = assert[name]; return alias; }) ('isOk', 'ok') ('isNotOk', 'notOk') ('throws', 'throw') ('throws', 'Throw') ('isExtensible', 'extensible') ('isNotExtensible', 'notExtensible') ('isSealed', 'sealed') ('isNotSealed', 'notSealed') ('isFrozen', 'frozen') ('isNotFrozen', 'notFrozen'); }; chai-3.5.0/lib/chai/interface/expect.js000664 000000 000000 00000001402 12652401517 017643 0ustar00rootroot000000 000000 /*! * chai * Copyright(c) 2011-2014 Jake Luer * MIT Licensed */ module.exports = function (chai, util) { chai.expect = function (val, message) { return new chai.Assertion(val, message); }; /** * ### .fail(actual, expected, [message], [operator]) * * Throw a failure. * * @name fail * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @param {String} operator * @namespace Expect * @api public */ chai.expect.fail = function (actual, expected, message, operator) { message = message || 'expect.fail()'; throw new chai.AssertionError(message, { actual: actual , expected: expected , operator: operator }, chai.expect.fail); }; }; chai-3.5.0/lib/chai/interface/should.js000664 000000 000000 00000013043 12652401517 017655 0ustar00rootroot000000 000000 /*! * chai * Copyright(c) 2011-2014 Jake Luer * MIT Licensed */ module.exports = function (chai, util) { var Assertion = chai.Assertion; function loadShould () { // explicitly define this method as function as to have it's name to include as `ssfi` function shouldGetter() { if (this instanceof String || this instanceof Number || this instanceof Boolean ) { return new Assertion(this.valueOf(), null, shouldGetter); } return new Assertion(this, null, shouldGetter); } function shouldSetter(value) { // See https://github.com/chaijs/chai/issues/86: this makes // `whatever.should = someValue` actually set `someValue`, which is // especially useful for `global.should = require('chai').should()`. // // Note that we have to use [[DefineProperty]] instead of [[Put]] // since otherwise we would trigger this very setter! Object.defineProperty(this, 'should', { value: value, enumerable: true, configurable: true, writable: true }); } // modify Object.prototype to have `should` Object.defineProperty(Object.prototype, 'should', { set: shouldSetter , get: shouldGetter , configurable: true }); var should = {}; /** * ### .fail(actual, expected, [message], [operator]) * * Throw a failure. * * @name fail * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @param {String} operator * @namespace Should * @api public */ should.fail = function (actual, expected, message, operator) { message = message || 'should.fail()'; throw new chai.AssertionError(message, { actual: actual , expected: expected , operator: operator }, should.fail); }; /** * ### .equal(actual, expected, [message]) * * Asserts non-strict equality (`==`) of `actual` and `expected`. * * should.equal(3, '3', '== coerces values to strings'); * * @name equal * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @namespace Should * @api public */ should.equal = function (val1, val2, msg) { new Assertion(val1, msg).to.equal(val2); }; /** * ### .throw(function, [constructor/string/regexp], [string/regexp], [message]) * * Asserts that `function` will throw an error that is an instance of * `constructor`, or alternately that it will throw an error with message * matching `regexp`. * * should.throw(fn, 'function throws a reference error'); * should.throw(fn, /function throws a reference error/); * should.throw(fn, ReferenceError); * should.throw(fn, ReferenceError, 'function throws a reference error'); * should.throw(fn, ReferenceError, /function throws a reference error/); * * @name throw * @alias Throw * @param {Function} function * @param {ErrorConstructor} constructor * @param {RegExp} regexp * @param {String} message * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types * @namespace Should * @api public */ should.Throw = function (fn, errt, errs, msg) { new Assertion(fn, msg).to.Throw(errt, errs); }; /** * ### .exist * * Asserts that the target is neither `null` nor `undefined`. * * var foo = 'hi'; * * should.exist(foo, 'foo exists'); * * @name exist * @namespace Should * @api public */ should.exist = function (val, msg) { new Assertion(val, msg).to.exist; } // negation should.not = {} /** * ### .not.equal(actual, expected, [message]) * * Asserts non-strict inequality (`!=`) of `actual` and `expected`. * * should.not.equal(3, 4, 'these numbers are not equal'); * * @name not.equal * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @namespace Should * @api public */ should.not.equal = function (val1, val2, msg) { new Assertion(val1, msg).to.not.equal(val2); }; /** * ### .throw(function, [constructor/regexp], [message]) * * Asserts that `function` will _not_ throw an error that is an instance of * `constructor`, or alternately that it will not throw an error with message * matching `regexp`. * * should.not.throw(fn, Error, 'function does not throw'); * * @name not.throw * @alias not.Throw * @param {Function} function * @param {ErrorConstructor} constructor * @param {RegExp} regexp * @param {String} message * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types * @namespace Should * @api public */ should.not.Throw = function (fn, errt, errs, msg) { new Assertion(fn, msg).to.not.Throw(errt, errs); }; /** * ### .not.exist * * Asserts that the target is neither `null` nor `undefined`. * * var bar = null; * * should.not.exist(bar, 'bar does not exist'); * * @name not.exist * @namespace Should * @api public */ should.not.exist = function (val, msg) { new Assertion(val, msg).to.not.exist; } should['throw'] = should['Throw']; should.not['throw'] = should.not['Throw']; return should; }; chai.should = loadShould; chai.Should = loadShould; }; chai-3.5.0/lib/chai/utils/000775 000000 000000 00000000000 12652401517 015220 5ustar00rootroot000000 000000 chai-3.5.0/lib/chai/utils/addChainableMethod.js000664 000000 000000 00000007051 12652401517 021241 0ustar00rootroot000000 000000 /*! * Chai - addChainingMethod utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /*! * Module dependencies */ var transferFlags = require('./transferFlags'); var flag = require('./flag'); var config = require('../config'); /*! * Module variables */ // Check whether `__proto__` is supported var hasProtoSupport = '__proto__' in Object; // Without `__proto__` support, this module will need to add properties to a function. // However, some Function.prototype methods cannot be overwritten, // and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69). var excludeNames = /^(?:length|name|arguments|caller)$/; // Cache `Function` properties var call = Function.prototype.call, apply = Function.prototype.apply; /** * ### addChainableMethod (ctx, name, method, chainingBehavior) * * Adds a method to an object, such that the method can also be chained. * * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) { * var obj = utils.flag(this, 'object'); * new chai.Assertion(obj).to.be.equal(str); * }); * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior); * * The result can then be used as both a method assertion, executing both `method` and * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`. * * expect(fooStr).to.be.foo('bar'); * expect(fooStr).to.be.foo.equal('foo'); * * @param {Object} ctx object to which the method is added * @param {String} name of method to add * @param {Function} method function to be used for `name`, when called * @param {Function} chainingBehavior function to be called every time the property is accessed * @namespace Utils * @name addChainableMethod * @api public */ module.exports = function (ctx, name, method, chainingBehavior) { if (typeof chainingBehavior !== 'function') { chainingBehavior = function () { }; } var chainableBehavior = { method: method , chainingBehavior: chainingBehavior }; // save the methods so we can overwrite them later, if we need to. if (!ctx.__methods) { ctx.__methods = {}; } ctx.__methods[name] = chainableBehavior; Object.defineProperty(ctx, name, { get: function () { chainableBehavior.chainingBehavior.call(this); var assert = function assert() { var old_ssfi = flag(this, 'ssfi'); if (old_ssfi && config.includeStack === false) flag(this, 'ssfi', assert); var result = chainableBehavior.method.apply(this, arguments); return result === undefined ? this : result; }; // Use `__proto__` if available if (hasProtoSupport) { // Inherit all properties from the object by replacing the `Function` prototype var prototype = assert.__proto__ = Object.create(this); // Restore the `call` and `apply` methods from `Function` prototype.call = call; prototype.apply = apply; } // Otherwise, redefine all properties (slow!) else { var asserterNames = Object.getOwnPropertyNames(ctx); asserterNames.forEach(function (asserterName) { if (!excludeNames.test(asserterName)) { var pd = Object.getOwnPropertyDescriptor(ctx, asserterName); Object.defineProperty(assert, asserterName, pd); } }); } transferFlags(this, assert); return assert; } , configurable: true }); }; chai-3.5.0/lib/chai/utils/addMethod.js000664 000000 000000 00000002237 12652401517 017453 0ustar00rootroot000000 000000 /*! * Chai - addMethod utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ var config = require('../config'); /** * ### .addMethod (ctx, name, method) * * Adds a method to the prototype of an object. * * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) { * var obj = utils.flag(this, 'object'); * new chai.Assertion(obj).to.be.equal(str); * }); * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.addMethod('foo', fn); * * Then can be used as any other assertion. * * expect(fooStr).to.be.foo('bar'); * * @param {Object} ctx object to which the method is added * @param {String} name of method to add * @param {Function} method function to be used for name * @namespace Utils * @name addMethod * @api public */ var flag = require('./flag'); module.exports = function (ctx, name, method) { ctx[name] = function () { var old_ssfi = flag(this, 'ssfi'); if (old_ssfi && config.includeStack === false) flag(this, 'ssfi', ctx[name]); var result = method.apply(this, arguments); return result === undefined ? this : result; }; }; chai-3.5.0/lib/chai/utils/addProperty.js000664 000000 000000 00000002400 12652401517 020047 0ustar00rootroot000000 000000 /*! * Chai - addProperty utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ var config = require('../config'); var flag = require('./flag'); /** * ### addProperty (ctx, name, getter) * * Adds a property to the prototype of an object. * * utils.addProperty(chai.Assertion.prototype, 'foo', function () { * var obj = utils.flag(this, 'object'); * new chai.Assertion(obj).to.be.instanceof(Foo); * }); * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.addProperty('foo', fn); * * Then can be used as any other assertion. * * expect(myFoo).to.be.foo; * * @param {Object} ctx object to which the property is added * @param {String} name of property to add * @param {Function} getter function to be used for name * @namespace Utils * @name addProperty * @api public */ module.exports = function (ctx, name, getter) { Object.defineProperty(ctx, name, { get: function addProperty() { var old_ssfi = flag(this, 'ssfi'); if (old_ssfi && config.includeStack === false) flag(this, 'ssfi', addProperty); var result = getter.call(this); return result === undefined ? this : result; } , configurable: true }); }; chai-3.5.0/lib/chai/utils/expectTypes.js000664 000000 000000 00000002321 12652401517 020071 0ustar00rootroot000000 000000 /*! * Chai - expectTypes utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /** * ### expectTypes(obj, types) * * Ensures that the object being tested against is of a valid type. * * utils.expectTypes(this, ['array', 'object', 'string']); * * @param {Mixed} obj constructed Assertion * @param {Array} type A list of allowed types for this assertion * @namespace Utils * @name expectTypes * @api public */ var AssertionError = require('assertion-error'); var flag = require('./flag'); var type = require('type-detect'); module.exports = function (obj, types) { var obj = flag(obj, 'object'); types = types.map(function (t) { return t.toLowerCase(); }); types.sort(); // Transforms ['lorem', 'ipsum'] into 'a lirum, or an ipsum' var str = types.map(function (t, index) { var art = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(t.charAt(0)) ? 'an' : 'a'; var or = types.length > 1 && index === types.length - 1 ? 'or ' : ''; return or + art + ' ' + t; }).join(', '); if (!types.some(function (expected) { return type(obj) === expected; })) { throw new AssertionError( 'object tested must be ' + str + ', but ' + type(obj) + ' given' ); } }; chai-3.5.0/lib/chai/utils/flag.js000664 000000 000000 00000001447 12652401517 016475 0ustar00rootroot000000 000000 /*! * Chai - flag utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /** * ### flag(object, key, [value]) * * Get or set a flag value on an object. If a * value is provided it will be set, else it will * return the currently set value or `undefined` if * the value is not set. * * utils.flag(this, 'foo', 'bar'); // setter * utils.flag(this, 'foo'); // getter, returns `bar` * * @param {Object} object constructed Assertion * @param {String} key * @param {Mixed} value (optional) * @namespace Utils * @name flag * @api private */ module.exports = function (obj, key, value) { var flags = obj.__flags || (obj.__flags = Object.create(null)); if (arguments.length === 3) { flags[key] = value; } else { return flags[key]; } }; chai-3.5.0/lib/chai/utils/getActual.js000664 000000 000000 00000000706 12652401517 017472 0ustar00rootroot000000 000000 /*! * Chai - getActual utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /** * # getActual(object, [actual]) * * Returns the `actual` value for an Assertion * * @param {Object} object (constructed Assertion) * @param {Arguments} chai.Assertion.prototype.assert arguments * @namespace Utils * @name getActual */ module.exports = function (obj, args) { return args.length > 4 ? args[4] : obj._obj; }; chai-3.5.0/lib/chai/utils/getEnumerableProperties.js000664 000000 000000 00000001043 12652401517 022410 0ustar00rootroot000000 000000 /*! * Chai - getEnumerableProperties utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /** * ### .getEnumerableProperties(object) * * This allows the retrieval of enumerable property names of an object, * inherited or not. * * @param {Object} object * @returns {Array} * @namespace Utils * @name getEnumerableProperties * @api public */ module.exports = function getEnumerableProperties(object) { var result = []; for (var name in object) { result.push(name); } return result; }; chai-3.5.0/lib/chai/utils/getMessage.js000664 000000 000000 00000002563 12652401517 017650 0ustar00rootroot000000 000000 /*! * Chai - message composition utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /*! * Module dependancies */ var flag = require('./flag') , getActual = require('./getActual') , inspect = require('./inspect') , objDisplay = require('./objDisplay'); /** * ### .getMessage(object, message, negateMessage) * * Construct the error message based on flags * and template tags. Template tags will return * a stringified inspection of the object referenced. * * Message template tags: * - `#{this}` current asserted object * - `#{act}` actual value * - `#{exp}` expected value * * @param {Object} object (constructed Assertion) * @param {Arguments} chai.Assertion.prototype.assert arguments * @namespace Utils * @name getMessage * @api public */ module.exports = function (obj, args) { var negate = flag(obj, 'negate') , val = flag(obj, 'object') , expected = args[3] , actual = getActual(obj, args) , msg = negate ? args[2] : args[1] , flagMsg = flag(obj, 'message'); if(typeof msg === "function") msg = msg(); msg = msg || ''; msg = msg .replace(/#\{this\}/g, function () { return objDisplay(val); }) .replace(/#\{act\}/g, function () { return objDisplay(actual); }) .replace(/#\{exp\}/g, function () { return objDisplay(expected); }); return flagMsg ? flagMsg + ': ' + msg : msg; }; chai-3.5.0/lib/chai/utils/getName.js000664 000000 000000 00000000722 12652401517 017137 0ustar00rootroot000000 000000 /*! * Chai - getName utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /** * # getName(func) * * Gets the name of a function, in a cross-browser way. * * @param {Function} a function (usually a constructor) * @namespace Utils * @name getName */ module.exports = function (func) { if (func.name) return func.name; var match = /^\s?function ([^(]*)\(/.exec(func); return match && match[1] ? match[1] : ""; }; chai-3.5.0/lib/chai/utils/getPathInfo.js000664 000000 000000 00000005403 12652401517 017770 0ustar00rootroot000000 000000 /*! * Chai - getPathInfo utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ var hasProperty = require('./hasProperty'); /** * ### .getPathInfo(path, object) * * This allows the retrieval of property info in an * object given a string path. * * The path info consists of an object with the * following properties: * * * parent - The parent object of the property referenced by `path` * * name - The name of the final property, a number if it was an array indexer * * value - The value of the property, if it exists, otherwise `undefined` * * exists - Whether the property exists or not * * @param {String} path * @param {Object} object * @returns {Object} info * @namespace Utils * @name getPathInfo * @api public */ module.exports = function getPathInfo(path, obj) { var parsed = parsePath(path), last = parsed[parsed.length - 1]; var info = { parent: parsed.length > 1 ? _getPathValue(parsed, obj, parsed.length - 1) : obj, name: last.p || last.i, value: _getPathValue(parsed, obj) }; info.exists = hasProperty(info.name, info.parent); return info; }; /*! * ## parsePath(path) * * Helper function used to parse string object * paths. Use in conjunction with `_getPathValue`. * * var parsed = parsePath('myobject.property.subprop'); * * ### Paths: * * * Can be as near infinitely deep and nested * * Arrays are also valid using the formal `myobject.document[3].property`. * * Literal dots and brackets (not delimiter) must be backslash-escaped. * * @param {String} path * @returns {Object} parsed * @api private */ function parsePath (path) { var str = path.replace(/([^\\])\[/g, '$1.[') , parts = str.match(/(\\\.|[^.]+?)+/g); return parts.map(function (value) { var re = /^\[(\d+)\]$/ , mArr = re.exec(value); if (mArr) return { i: parseFloat(mArr[1]) }; else return { p: value.replace(/\\([.\[\]])/g, '$1') }; }); } /*! * ## _getPathValue(parsed, obj) * * Helper companion function for `.parsePath` that returns * the value located at the parsed address. * * var value = getPathValue(parsed, obj); * * @param {Object} parsed definition from `parsePath`. * @param {Object} object to search against * @param {Number} object to search against * @returns {Object|Undefined} value * @api private */ function _getPathValue (parsed, obj, index) { var tmp = obj , res; index = (index === undefined ? parsed.length : index); for (var i = 0, l = index; i < l; i++) { var part = parsed[i]; if (tmp) { if ('undefined' !== typeof part.p) tmp = tmp[part.p]; else if ('undefined' !== typeof part.i) tmp = tmp[part.i]; if (i == (l - 1)) res = tmp; } else { res = undefined; } } return res; } chai-3.5.0/lib/chai/utils/getPathValue.js000664 000000 000000 00000002006 12652401517 020145 0ustar00rootroot000000 000000 /*! * Chai - getPathValue utility * Copyright(c) 2012-2014 Jake Luer * @see https://github.com/logicalparadox/filtr * MIT Licensed */ var getPathInfo = require('./getPathInfo'); /** * ### .getPathValue(path, object) * * This allows the retrieval of values in an * object given a string path. * * var obj = { * prop1: { * arr: ['a', 'b', 'c'] * , str: 'Hello' * } * , prop2: { * arr: [ { nested: 'Universe' } ] * , str: 'Hello again!' * } * } * * The following would be the results. * * getPathValue('prop1.str', obj); // Hello * getPathValue('prop1.att[2]', obj); // b * getPathValue('prop2.arr[0].nested', obj); // Universe * * @param {String} path * @param {Object} object * @returns {Object} value or `undefined` * @namespace Utils * @name getPathValue * @api public */ module.exports = function(path, obj) { var info = getPathInfo(path, obj); return info.value; }; chai-3.5.0/lib/chai/utils/getProperties.js000664 000000 000000 00000001425 12652401517 020414 0ustar00rootroot000000 000000 /*! * Chai - getProperties utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /** * ### .getProperties(object) * * This allows the retrieval of property names of an object, enumerable or not, * inherited or not. * * @param {Object} object * @returns {Array} * @namespace Utils * @name getProperties * @api public */ module.exports = function getProperties(object) { var result = Object.getOwnPropertyNames(object); function addProperty(property) { if (result.indexOf(property) === -1) { result.push(property); } } var proto = Object.getPrototypeOf(object); while (proto !== null) { Object.getOwnPropertyNames(proto).forEach(addProperty); proto = Object.getPrototypeOf(proto); } return result; }; chai-3.5.0/lib/chai/utils/hasProperty.js000664 000000 000000 00000002777 12652401517 020113 0ustar00rootroot000000 000000 /*! * Chai - hasProperty utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ var type = require('type-detect'); /** * ### .hasProperty(object, name) * * This allows checking whether an object has * named property or numeric array index. * * Basically does the same thing as the `in` * operator but works properly with natives * and null/undefined values. * * var obj = { * arr: ['a', 'b', 'c'] * , str: 'Hello' * } * * The following would be the results. * * hasProperty('str', obj); // true * hasProperty('constructor', obj); // true * hasProperty('bar', obj); // false * * hasProperty('length', obj.str); // true * hasProperty(1, obj.str); // true * hasProperty(5, obj.str); // false * * hasProperty('length', obj.arr); // true * hasProperty(2, obj.arr); // true * hasProperty(3, obj.arr); // false * * @param {Objuect} object * @param {String|Number} name * @returns {Boolean} whether it exists * @namespace Utils * @name getPathInfo * @api public */ var literals = { 'number': Number , 'string': String }; module.exports = function hasProperty(name, obj) { var ot = type(obj); // Bad Object, obviously no props at all if(ot === 'null' || ot === 'undefined') return false; // The `in` operator does not work with certain literals // box these before the check if(literals[ot] && typeof obj !== 'object') obj = new literals[ot](obj); return name in obj; }; chai-3.5.0/lib/chai/utils/index.js000664 000000 000000 00000003254 12652401517 016671 0ustar00rootroot000000 000000 /*! * chai * Copyright(c) 2011 Jake Luer * MIT Licensed */ /*! * Main exports */ var exports = module.exports = {}; /*! * test utility */ exports.test = require('./test'); /*! * type utility */ exports.type = require('type-detect'); /*! * expectTypes utility */ exports.expectTypes = require('./expectTypes'); /*! * message utility */ exports.getMessage = require('./getMessage'); /*! * actual utility */ exports.getActual = require('./getActual'); /*! * Inspect util */ exports.inspect = require('./inspect'); /*! * Object Display util */ exports.objDisplay = require('./objDisplay'); /*! * Flag utility */ exports.flag = require('./flag'); /*! * Flag transferring utility */ exports.transferFlags = require('./transferFlags'); /*! * Deep equal utility */ exports.eql = require('deep-eql'); /*! * Deep path value */ exports.getPathValue = require('./getPathValue'); /*! * Deep path info */ exports.getPathInfo = require('./getPathInfo'); /*! * Check if a property exists */ exports.hasProperty = require('./hasProperty'); /*! * Function name */ exports.getName = require('./getName'); /*! * add Property */ exports.addProperty = require('./addProperty'); /*! * add Method */ exports.addMethod = require('./addMethod'); /*! * overwrite Property */ exports.overwriteProperty = require('./overwriteProperty'); /*! * overwrite Method */ exports.overwriteMethod = require('./overwriteMethod'); /*! * Add a chainable method */ exports.addChainableMethod = require('./addChainableMethod'); /*! * Overwrite chainable method */ exports.overwriteChainableMethod = require('./overwriteChainableMethod'); chai-3.5.0/lib/chai/utils/inspect.js000664 000000 000000 00000023202 12652401517 017222 0ustar00rootroot000000 000000 // This is (almost) directly from Node.js utils // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js var getName = require('./getName'); var getProperties = require('./getProperties'); var getEnumerableProperties = require('./getEnumerableProperties'); module.exports = inspect; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Boolean} showHidden Flag that shows hidden (not enumerable) * properties of objects. * @param {Number} depth Depth in which to descend in object. Default is 2. * @param {Boolean} colors Flag to turn on ANSI escape codes to color the * output. Default is false (no coloring). * @namespace Utils * @name inspect */ function inspect(obj, showHidden, depth, colors) { var ctx = { showHidden: showHidden, seen: [], stylize: function (str) { return str; } }; return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth)); } // Returns true if object is a DOM element. var isDOMElement = function (object) { if (typeof HTMLElement === 'object') { return object instanceof HTMLElement; } else { return object && typeof object === 'object' && object.nodeType === 1 && typeof object.nodeName === 'string'; } }; function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (value && typeof value.inspect === 'function' && // Filter out the util module, it's inspect function is special value.inspect !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { var ret = value.inspect(recurseTimes); if (typeof ret !== 'string') { ret = formatValue(ctx, ret, recurseTimes); } return ret; } // Primitive types cannot have properties var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // If this is a DOM element, try to get the outer HTML. if (isDOMElement(value)) { if ('outerHTML' in value) { return value.outerHTML; // This value does not have an outerHTML attribute, // it could still be an XML element } else { // Attempt to serialize it try { if (document.xmlVersion) { var xmlSerializer = new XMLSerializer(); return xmlSerializer.serializeToString(value); } else { // Firefox 11- do not support outerHTML // It does, however, support innerHTML // Use the following to render the element var ns = "http://www.w3.org/1999/xhtml"; var container = document.createElementNS(ns, '_'); container.appendChild(value.cloneNode(false)); html = container.innerHTML .replace('><', '>' + value.innerHTML + '<'); container.innerHTML = ''; return html; } } catch (err) { // This could be a non-native DOM implementation, // continue with the normal flow: // printing the element as if it is an object. } } } // Look up the keys of the object. var visibleKeys = getEnumerableProperties(value); var keys = ctx.showHidden ? getProperties(value) : visibleKeys; // Some type of object without properties can be shortcutted. // In IE, errors have a single `stack` property, or if they are vanilla `Error`, // a `stack` plus `description` property; ignore those for consistency. if (keys.length === 0 || (isError(value) && ( (keys.length === 1 && keys[0] === 'stack') || (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack') ))) { if (typeof value === 'function') { var name = getName(value); var nameSuffix = name ? ': ' + name : ''; return ctx.stylize('[Function' + nameSuffix + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toUTCString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; // Make Array say that they are Array if (isArray(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if (typeof value === 'function') { var name = getName(value); var nameSuffix = name ? ': ' + name : ''; base = ' [Function' + nameSuffix + ']'; } // Make RegExps say that they are RegExps if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } // Make error with message first say the error if (isError(value)) { return formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { switch (typeof value) { case 'undefined': return ctx.stylize('undefined', 'undefined'); case 'string': var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); case 'number': if (value === 0 && (1/value) === -Infinity) { return ctx.stylize('-0', 'number'); } return ctx.stylize('' + value, 'number'); case 'boolean': return ctx.stylize('' + value, 'boolean'); } // For some reason typeof null is "object", so special case here. if (value === null) { return ctx.stylize('null', 'null'); } } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (Object.prototype.hasOwnProperty.call(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str; if (value.__lookupGetter__) { if (value.__lookupGetter__(key)) { if (value.__lookupSetter__(key)) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (value.__lookupSetter__(key)) { str = ctx.stylize('[Setter]', 'special'); } } } if (visibleKeys.indexOf(key) < 0) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(value[key]) < 0) { if (recurseTimes === null) { str = formatValue(ctx, value[key], null); } else { str = formatValue(ctx, value[key], recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (typeof name === 'undefined') { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } function isArray(ar) { return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]'); } function isRegExp(re) { return typeof re === 'object' && objectToString(re) === '[object RegExp]'; } function isDate(d) { return typeof d === 'object' && objectToString(d) === '[object Date]'; } function isError(e) { return typeof e === 'object' && objectToString(e) === '[object Error]'; } function objectToString(o) { return Object.prototype.toString.call(o); } chai-3.5.0/lib/chai/utils/objDisplay.js000664 000000 000000 00000002301 12652401517 017652 0ustar00rootroot000000 000000 /*! * Chai - flag utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /*! * Module dependancies */ var inspect = require('./inspect'); var config = require('../config'); /** * ### .objDisplay (object) * * Determines if an object or an array matches * criteria to be inspected in-line for error * messages or should be truncated. * * @param {Mixed} javascript object to inspect * @name objDisplay * @namespace Utils * @api public */ module.exports = function (obj) { var str = inspect(obj) , type = Object.prototype.toString.call(obj); if (config.truncateThreshold && str.length >= config.truncateThreshold) { if (type === '[object Function]') { return !obj.name || obj.name === '' ? '[Function]' : '[Function: ' + obj.name + ']'; } else if (type === '[object Array]') { return '[ Array(' + obj.length + ') ]'; } else if (type === '[object Object]') { var keys = Object.keys(obj) , kstr = keys.length > 2 ? keys.splice(0, 2).join(', ') + ', ...' : keys.join(', '); return '{ Object (' + kstr + ') }'; } else { return str; } } else { return str; } }; chai-3.5.0/lib/chai/utils/overwriteChainableMethod.js000664 000000 000000 00000003303 12652401517 022533 0ustar00rootroot000000 000000 /*! * Chai - overwriteChainableMethod utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /** * ### overwriteChainableMethod (ctx, name, method, chainingBehavior) * * Overwites an already existing chainable method * and provides access to the previous function or * property. Must return functions to be used for * name. * * utils.overwriteChainableMethod(chai.Assertion.prototype, 'length', * function (_super) { * } * , function (_super) { * } * ); * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.overwriteChainableMethod('foo', fn, fn); * * Then can be used as any other assertion. * * expect(myFoo).to.have.length(3); * expect(myFoo).to.have.length.above(3); * * @param {Object} ctx object whose method / property is to be overwritten * @param {String} name of method / property to overwrite * @param {Function} method function that returns a function to be used for name * @param {Function} chainingBehavior function that returns a function to be used for property * @namespace Utils * @name overwriteChainableMethod * @api public */ module.exports = function (ctx, name, method, chainingBehavior) { var chainableBehavior = ctx.__methods[name]; var _chainingBehavior = chainableBehavior.chainingBehavior; chainableBehavior.chainingBehavior = function () { var result = chainingBehavior(_chainingBehavior).call(this); return result === undefined ? this : result; }; var _method = chainableBehavior.method; chainableBehavior.method = function () { var result = method(_method).apply(this, arguments); return result === undefined ? this : result; }; }; chai-3.5.0/lib/chai/utils/overwriteMethod.js000664 000000 000000 00000002654 12652401517 020754 0ustar00rootroot000000 000000 /*! * Chai - overwriteMethod utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /** * ### overwriteMethod (ctx, name, fn) * * Overwites an already existing method and provides * access to previous function. Must return function * to be used for name. * * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) { * return function (str) { * var obj = utils.flag(this, 'object'); * if (obj instanceof Foo) { * new chai.Assertion(obj.value).to.equal(str); * } else { * _super.apply(this, arguments); * } * } * }); * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.overwriteMethod('foo', fn); * * Then can be used as any other assertion. * * expect(myFoo).to.equal('bar'); * * @param {Object} ctx object whose method is to be overwritten * @param {String} name of method to overwrite * @param {Function} method function that returns a function to be used for name * @namespace Utils * @name overwriteMethod * @api public */ module.exports = function (ctx, name, method) { var _method = ctx[name] , _super = function () { return this; }; if (_method && 'function' === typeof _method) _super = _method; ctx[name] = function () { var result = method(_super).apply(this, arguments); return result === undefined ? this : result; } }; chai-3.5.0/lib/chai/utils/overwriteProperty.js000664 000000 000000 00000002771 12652401517 021360 0ustar00rootroot000000 000000 /*! * Chai - overwriteProperty utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /** * ### overwriteProperty (ctx, name, fn) * * Overwites an already existing property getter and provides * access to previous value. Must return function to use as getter. * * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) { * return function () { * var obj = utils.flag(this, 'object'); * if (obj instanceof Foo) { * new chai.Assertion(obj.name).to.equal('bar'); * } else { * _super.call(this); * } * } * }); * * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.overwriteProperty('foo', fn); * * Then can be used as any other assertion. * * expect(myFoo).to.be.ok; * * @param {Object} ctx object whose property is to be overwritten * @param {String} name of property to overwrite * @param {Function} getter function that returns a getter function to be used for name * @namespace Utils * @name overwriteProperty * @api public */ module.exports = function (ctx, name, getter) { var _get = Object.getOwnPropertyDescriptor(ctx, name) , _super = function () {}; if (_get && 'function' === typeof _get.get) _super = _get.get Object.defineProperty(ctx, name, { get: function () { var result = getter(_super).call(this); return result === undefined ? this : result; } , configurable: true }); }; chai-3.5.0/lib/chai/utils/test.js000664 000000 000000 00000001026 12652401517 016534 0ustar00rootroot000000 000000 /*! * Chai - test utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /*! * Module dependancies */ var flag = require('./flag'); /** * # test(object, expression) * * Test and object for expression. * * @param {Object} object (constructed Assertion) * @param {Arguments} chai.Assertion.prototype.assert arguments * @namespace Utils * @name test */ module.exports = function (obj, args) { var negate = flag(obj, 'negate') , expr = args[0]; return negate ? !expr : expr; }; chai-3.5.0/lib/chai/utils/transferFlags.js000664 000000 000000 00000002440 12652401517 020357 0ustar00rootroot000000 000000 /*! * Chai - transferFlags utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ /** * ### transferFlags(assertion, object, includeAll = true) * * Transfer all the flags for `assertion` to `object`. If * `includeAll` is set to `false`, then the base Chai * assertion flags (namely `object`, `ssfi`, and `message`) * will not be transferred. * * * var newAssertion = new Assertion(); * utils.transferFlags(assertion, newAssertion); * * var anotherAsseriton = new Assertion(myObj); * utils.transferFlags(assertion, anotherAssertion, false); * * @param {Assertion} assertion the assertion to transfer the flags from * @param {Object} object the object to transfer the flags to; usually a new assertion * @param {Boolean} includeAll * @namespace Utils * @name transferFlags * @api private */ module.exports = function (assertion, object, includeAll) { var flags = assertion.__flags || (assertion.__flags = Object.create(null)); if (!object.__flags) { object.__flags = Object.create(null); } includeAll = arguments.length === 3 ? includeAll : true; for (var flag in flags) { if (includeAll || (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) { object.__flags[flag] = flags[flag]; } } }; chai-3.5.0/package.json000664 000000 000000 00000002354 12652401517 014700 0ustar00rootroot000000 000000 { "author": "Jake Luer ", "name": "chai", "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic.", "keywords": [ "test", "assertion", "assert", "testing", "chai" ], "homepage": "http://chaijs.com", "license": "MIT", "contributors": [ "Jake Luer ", "Domenic Denicola (http://domenicdenicola.com)", "Veselin Todorov ", "John Firebaugh " ], "version": "3.5.0", "repository": { "type": "git", "url": "https://github.com/chaijs/chai" }, "bugs": { "url": "https://github.com/chaijs/chai/issues" }, "main": "./index", "scripts": { "test": "make test" }, "engines": { "node": ">= 0.4.0" }, "dependencies": { "assertion-error": "^1.0.1", "deep-eql": "^0.1.3", "type-detect": "^1.0.0" }, "devDependencies": { "browserify": "^10.2.1", "bump-cli": "^1.1.3", "karma": "^0.13.16", "karma-mocha": "^0.1.10", "karma-sauce-launcher": "^0.2.11", "karma-phantomjs-launcher": "^0.2.0", "karma-firefox-launcher": "^0.1.6", "mocha": "^2.2.5", "istanbul": "^0.3.14" } } chai-3.5.0/sauce.browsers.js000664 000000 000000 00000003406 12652401517 015714 0ustar00rootroot000000 000000 /*! * Chrome */ exports['SL_Chrome'] = { base: 'SauceLabs' , browserName: 'chrome' }; /*! * Firefox */ /*! * TODO: Karma doesn't seem to like this, though sauce boots its up * exports['SL_Firefox_23'] = { base: 'SauceLabs' , browserName: 'firefox' , platform: 'Windows XP' , version: '23' }; */ exports['SL_Firefox_22'] = { base: 'SauceLabs' , browserName: 'firefox' , platform: 'Windows 7' , version: '22' }; /*! * Opera */ exports['SL_Opera_12'] = { base: 'SauceLabs' , browserName: 'opera' , platform: 'Windows 7' , version: '12' }; exports['SL_Opera_11'] = { base: 'SauceLabs' , browserName: 'opera' , platform: 'Windows 7' , version: '11' }; /*! * Internet Explorer */ exports['SL_IE_10'] = { base: 'SauceLabs' , browserName: 'internet explorer' , platform: 'Windows 2012' , version: '10' }; /*! * Safari */ exports['SL_Safari_6'] = { base: 'SauceLabs' , browserName: 'safari' , platform: 'Mac 10.8' , version: '6' }; exports['SL_Safari_5'] = { base: 'SauceLabs' , browserName: 'safari' , platform: 'Mac 10.6' , version: '5' }; /*! * iPhone */ /*! * TODO: These take forever to boot or shut down. Causes timeout. * exports['SL_iPhone_6'] = { base: 'SauceLabs' , browserName: 'iphone' , platform: 'Mac 10.8' , version: '6' }; exports['SL_iPhone_5-1'] = { base: 'SauceLabs' , browserName: 'iphone' , platform: 'Mac 10.8' , version: '5.1' }; exports['SL_iPhone_5'] = { base: 'SauceLabs' , browserName: 'iphone' , platform: 'Mac 10.6' , version: '5' }; */ /*! * Android */ /*! * TODO: fails because of error serialization * exports['SL_Android_4'] = { base: 'SauceLabs' , browserName: 'android' , platform: 'Linux' , version: '4' }; */ chai-3.5.0/support/000775 000000 000000 00000000000 12652401517 014122 5ustar00rootroot000000 000000 chai-3.5.0/support/sauce/000775 000000 000000 00000000000 12652401517 015222 5ustar00rootroot000000 000000 chai-3.5.0/support/sauce/sauce_connect_block.sh000775 000000 000000 00000000171 12652401517 021543 0ustar00rootroot000000 000000 #!/bin/bash # Wait for Connect to be ready before exiting while [ ! -f $SAUCE_CONNECT_READY_FILE ]; do sleep .5 done chai-3.5.0/support/sauce/sauce_connect_setup.sh000775 000000 000000 00000003140 12652401517 021610 0ustar00rootroot000000 000000 #!/bin/bash set -e # Setup and start Sauce Connect for your TravisCI build # This script requires your .travis.yml to include the following two private env variables: # SAUCE_USERNAME # SAUCE_ACCESS_KEY # Follow the steps at https://saucelabs.com/opensource/travis to set that up. # # Curl and run this script as part of your .travis.yml before_script section: # before_script: # - curl https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash CONNECT_URL="http://saucelabs.com/downloads/Sauce-Connect-latest.zip" CONNECT_DIR="/tmp/sauce-connect-$RANDOM" CONNECT_DOWNLOAD="Sauce_Connect.zip" mkdir -p $LOGS_DIR CONNECT_LOG="$LOGS_DIR/sauce-connect" CONNECT_STDOUT="$LOGS_DIR/sauce-connect.stdout" CONNECT_STDERR="$LOGS_DIR/sauce-connect.stderr" # Get Connect and start it mkdir -p $CONNECT_DIR cd $CONNECT_DIR curl $CONNECT_URL -o $CONNECT_DOWNLOAD 2> /dev/null 1> /dev/null unzip $CONNECT_DOWNLOAD > /dev/null rm $CONNECT_DOWNLOAD SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev` ARGS="" # Set tunnel-id only on Travis, to make local testing easier. if [ ! -z "$TRAVIS_JOB_NUMBER" ]; then ARGS="$ARGS --tunnel-identifier $TRAVIS_JOB_NUMBER" fi if [ ! -z "$SAUCE_CONNECT_READY_FILE" ]; then ARGS="$ARGS --readyfile $SAUCE_CONNECT_READY_FILE" fi echo "Starting Sauce Connect in the background:" echo " Arg: $ARGS" echo "Logging into:" echo " Log: $CONNECT_LOG" echo " Out: $CONNECT_STDOUT" echo " Err: $CONNECT_STDERR" java -jar Sauce-Connect.jar $ARGS $SAUCE_USERNAME $SAUCE_ACCESS_KEY \ --logfile $CONNECT_LOG 2> $CONNECT_STDERR 1> $CONNECT_STDOUT & CONNECT_PID=$! echo " Pid: $CONNECT_PID" chai-3.5.0/test/000775 000000 000000 00000000000 12652401517 013365 5ustar00rootroot000000 000000 chai-3.5.0/test/assert.js000664 000000 000000 00000071300 12652401517 015225 0ustar00rootroot000000 000000 describe('assert', function () { var assert = chai.assert; it('assert', function () { var foo = 'bar'; assert(foo == 'bar', "expected foo to equal `bar`"); err(function () { assert(foo == 'baz', "expected foo to equal `bar`"); }, "expected foo to equal `bar`"); err(function () { assert(foo == 'baz', function() { return "expected foo to equal `bar`"; }); }, "expected foo to equal `bar`"); }); it('fail', function () { chai.expect(function () { assert.fail(0, 1, 'this has failed'); }).to.throw(chai.AssertionError, /this has failed/); }); it('isTrue', function () { assert.isTrue(true); err(function() { assert.isTrue(false); }, "expected false to be true"); err(function() { assert.isTrue(1); }, "expected 1 to be true"); err(function() { assert.isTrue('test'); }, "expected 'test' to be true"); }); it('isNotTrue', function () { assert.isNotTrue(false); err(function() { assert.isNotTrue(true); }, "expected true to not equal true"); }); it('isOk / ok', function () { ['isOk', 'ok'].forEach(function (isOk) { assert[isOk](true); assert[isOk](1); assert[isOk]('test'); err(function () { assert[isOk](false); }, "expected false to be truthy"); err(function () { assert[isOk](0); }, "expected 0 to be truthy"); err(function () { assert[isOk](''); }, "expected '' to be truthy"); }); }); it('isNotOk, notOk', function () { ['isNotOk', 'notOk'].forEach(function (isNotOk) { assert[isNotOk](false); assert[isNotOk](0); assert[isNotOk](''); err(function () { assert[isNotOk](true); }, "expected true to be falsy"); err(function () { assert[isNotOk](1); }, "expected 1 to be falsy"); err(function () { assert[isNotOk]('test'); }, "expected 'test' to be falsy"); }); }); it('isFalse', function () { assert.isFalse(false); err(function() { assert.isFalse(true); }, "expected true to be false"); err(function() { assert.isFalse(0); }, "expected 0 to be false"); }); it('isNotFalse', function () { assert.isNotFalse(true); err(function() { assert.isNotFalse(false); }, "expected false to not equal false"); }); it('equal', function () { var foo; assert.equal(foo, undefined); }); it('typeof', function () { assert.typeOf('test', 'string'); assert.typeOf(true, 'boolean'); assert.typeOf(5, 'number'); err(function () { assert.typeOf(5, 'string'); }, "expected 5 to be a string"); }); it('notTypeOf', function () { assert.notTypeOf('test', 'number'); err(function () { assert.notTypeOf(5, 'number'); }, "expected 5 not to be a number"); }); it('instanceOf', function() { function Foo(){} assert.instanceOf(new Foo(), Foo); err(function () { assert.instanceOf(5, Foo); }, "expected 5 to be an instance of Foo"); function CrashyObject() {}; CrashyObject.prototype.inspect = function () { throw new Error("Arg's inspect() called even though the test passed"); }; assert.instanceOf(new CrashyObject(), CrashyObject); }); it('notInstanceOf', function () { function Foo(){} assert.notInstanceOf(new Foo(), String); err(function () { assert.notInstanceOf(new Foo(), Foo); }, "expected {} to not be an instance of Foo"); }); it('isObject', function () { function Foo(){} assert.isObject({}); assert.isObject(new Foo()); err(function() { assert.isObject(true); }, "expected true to be an object"); err(function() { assert.isObject(Foo); }, "expected [Function: Foo] to be an object"); err(function() { assert.isObject('foo'); }, "expected 'foo' to be an object"); }); it('isNotObject', function () { function Foo(){} assert.isNotObject(5); err(function() { assert.isNotObject({}); }, "expected {} not to be an object"); }); it('notEqual', function() { assert.notEqual(3, 4); err(function () { assert.notEqual(5, 5); }, "expected 5 to not equal 5"); }); it('strictEqual', function() { assert.strictEqual('foo', 'foo'); err(function () { assert.strictEqual('5', 5); }, "expected \'5\' to equal 5"); }); it('notStrictEqual', function() { assert.notStrictEqual(5, '5'); err(function () { assert.notStrictEqual(5, 5); }, "expected 5 to not equal 5"); }); it('deepEqual', function() { assert.deepEqual({tea: 'chai'}, {tea: 'chai'}); err(function () { assert.deepEqual({tea: 'chai'}, {tea: 'black'}); }, "expected { tea: \'chai\' } to deeply equal { tea: \'black\' }"); var obja = Object.create({ tea: 'chai' }) , objb = Object.create({ tea: 'chai' }); assert.deepEqual(obja, objb); var obj1 = Object.create({tea: 'chai'}) , obj2 = Object.create({tea: 'black'}); err(function () { assert.deepEqual(obj1, obj2); }, "expected { tea: \'chai\' } to deeply equal { tea: \'black\' }"); }); it('deepEqual (ordering)', function() { var a = { a: 'b', c: 'd' } , b = { c: 'd', a: 'b' }; assert.deepEqual(a, b); }); it('deepEqual /regexp/', function() { assert.deepEqual(/a/, /a/); assert.notDeepEqual(/a/, /b/); assert.notDeepEqual(/a/, {}); assert.deepEqual(/a/g, /a/g); assert.notDeepEqual(/a/g, /b/g); assert.deepEqual(/a/i, /a/i); assert.notDeepEqual(/a/i, /b/i); assert.deepEqual(/a/m, /a/m); assert.notDeepEqual(/a/m, /b/m); }); it('deepEqual (Date)', function() { var a = new Date(1, 2, 3) , b = new Date(4, 5, 6); assert.deepEqual(a, a); assert.notDeepEqual(a, b); assert.notDeepEqual(a, {}); }); it('deepEqual (circular)', function() { var circularObject = {} , secondCircularObject = {}; circularObject.field = circularObject; secondCircularObject.field = secondCircularObject; assert.deepEqual(circularObject, secondCircularObject); err(function() { secondCircularObject.field2 = secondCircularObject; assert.deepEqual(circularObject, secondCircularObject); }, "expected { field: [Circular] } to deeply equal { Object (field, field2) }"); }); it('notDeepEqual', function() { assert.notDeepEqual({tea: 'jasmine'}, {tea: 'chai'}); err(function () { assert.notDeepEqual({tea: 'chai'}, {tea: 'chai'}); }, "expected { tea: \'chai\' } to not deeply equal { tea: \'chai\' }"); }); it('notDeepEqual (circular)', function() { var circularObject = {} , secondCircularObject = { tea: 'jasmine' }; circularObject.field = circularObject; secondCircularObject.field = secondCircularObject; assert.notDeepEqual(circularObject, secondCircularObject); err(function() { delete secondCircularObject.tea; assert.notDeepEqual(circularObject, secondCircularObject); }, "expected { field: [Circular] } to not deeply equal { field: [Circular] }"); }); it('isNull', function() { assert.isNull(null); err(function () { assert.isNull(undefined); }, "expected undefined to equal null"); }); it('isNotNull', function() { assert.isNotNull(undefined); err(function () { assert.isNotNull(null); }, "expected null to not equal null"); }); it('isNaN', function() { assert.isNaN('hello'); err(function (){ assert.isNaN(4); }, "expected 4 to be NaN"); }); it('isNotNaN', function() { assert.isNotNaN(4); err(function (){ assert.isNotNaN('hello'); }, "expected 'hello' not to be NaN"); }); it('isUndefined', function() { assert.isUndefined(undefined); err(function () { assert.isUndefined(null); }, "expected null to equal undefined"); }); it('isDefined', function() { assert.isDefined(null); err(function () { assert.isDefined(undefined); }, "expected undefined to not equal undefined"); }); it('isFunction', function() { var func = function() {}; assert.isFunction(func); err(function () { assert.isFunction({}); }, "expected {} to be a function"); }); it('isNotFunction', function () { assert.isNotFunction(5); err(function () { assert.isNotFunction(function () {}); }, "expected [Function] not to be a function"); }); it('isArray', function() { assert.isArray([]); assert.isArray(new Array); err(function () { assert.isArray({}); }, "expected {} to be an array"); }); it('isNotArray', function () { assert.isNotArray(3); err(function () { assert.isNotArray([]); }, "expected [] not to be an array"); err(function () { assert.isNotArray(new Array); }, "expected [] not to be an array"); }); it('isString', function() { assert.isString('Foo'); assert.isString(new String('foo')); err(function () { assert.isString(1); }, "expected 1 to be a string"); }); it('isNotString', function () { assert.isNotString(3); assert.isNotString([ 'hello' ]); err(function () { assert.isNotString('hello'); }, "expected 'hello' not to be a string"); }); it('isNumber', function() { assert.isNumber(1); assert.isNumber(Number('3')); err(function () { assert.isNumber('1'); }, "expected \'1\' to be a number"); }); it('isNotNumber', function () { assert.isNotNumber('hello'); assert.isNotNumber([ 5 ]); err(function () { assert.isNotNumber(4); }, "expected 4 not to be a number"); }); it('isBoolean', function() { assert.isBoolean(true); assert.isBoolean(false); err(function () { assert.isBoolean('1'); }, "expected \'1\' to be a boolean"); }); it('isNotBoolean', function () { assert.isNotBoolean('true'); err(function () { assert.isNotBoolean(true); }, "expected true not to be a boolean"); err(function () { assert.isNotBoolean(false); }, "expected false not to be a boolean"); }); it('include', function() { assert.include('foobar', 'bar'); assert.include('', ''); assert.include([ 1, 2, 3], 3); assert.include({a:1, b:2}, {b:2}); err(function () { assert.include('foobar', 'baz'); }, "expected \'foobar\' to include \'baz\'"); err(function(){ assert.include(true, true); }, "object tested must be an array, an object, or a string, but boolean given"); err(function () { assert.include(42, 'bar'); }, "object tested must be an array, an object, or a string, but number given"); err(function(){ assert.include(null, 42); }, "object tested must be an array, an object, or a string, but null given"); err(function () { assert.include(undefined, 'bar'); }, "object tested must be an array, an object, or a string, but undefined given"); }); it('notInclude', function () { assert.notInclude('foobar', 'baz'); assert.notInclude([ 1, 2, 3 ], 4); err(function(){ assert.notInclude(true, true); }, "object tested must be an array, an object, or a string, but boolean given"); err(function () { assert.notInclude(42, 'bar'); }, "object tested must be an array, an object, or a string, but number given"); err(function(){ assert.notInclude(null, 42); }, "object tested must be an array, an object, or a string, but null given"); err(function () { assert.notInclude(undefined, 'bar'); }, "object tested must be an array, an object, or a string, but undefined given"); err(function () { assert.notInclude('foobar', 'bar'); }, "expected \'foobar\' to not include \'bar\'"); }); it('lengthOf', function() { assert.lengthOf([1,2,3], 3); assert.lengthOf('foobar', 6); err(function () { assert.lengthOf('foobar', 5); }, "expected 'foobar' to have a length of 5 but got 6"); err(function () { assert.lengthOf(1, 5); }, "expected 1 to have a property \'length\'"); }); it('match', function () { assert.match('foobar', /^foo/); assert.notMatch('foobar', /^bar/); err(function () { assert.match('foobar', /^bar/i); }, "expected 'foobar' to match /^bar/i"); err(function () { assert.notMatch('foobar', /^foo/i); }, "expected 'foobar' not to match /^foo/i"); }); it('property', function () { var obj = { foo: { bar: 'baz' } }; var simpleObj = { foo: 'bar' }; var undefinedKeyObj = { foo: undefined }; assert.property(obj, 'foo'); assert.property(undefinedKeyObj, 'foo'); assert.propertyVal(undefinedKeyObj, 'foo', undefined); assert.deepProperty(obj, 'foo.bar'); assert.notProperty(obj, 'baz'); assert.notProperty(obj, 'foo.bar'); assert.notDeepProperty(obj, 'foo.baz'); assert.deepPropertyVal(obj, 'foo.bar', 'baz'); assert.deepPropertyNotVal(obj, 'foo.bar', 'flow'); err(function () { assert.property(obj, 'baz'); }, "expected { foo: { bar: 'baz' } } to have a property 'baz'"); err(function () { assert.deepProperty(obj, 'foo.baz'); }, "expected { foo: { bar: 'baz' } } to have a deep property 'foo.baz'"); err(function () { assert.notProperty(obj, 'foo'); }, "expected { foo: { bar: 'baz' } } to not have property 'foo'"); err(function () { assert.notDeepProperty(obj, 'foo.bar'); }, "expected { foo: { bar: 'baz' } } to not have deep property 'foo.bar'"); err(function () { assert.propertyVal(simpleObj, 'foo', 'ball'); }, "expected { foo: 'bar' } to have a property 'foo' of 'ball', but got 'bar'"); err(function () { assert.propertyVal(simpleObj, 'foo', undefined); }, "expected { foo: 'bar' } to have a property 'foo' of undefined, but got 'bar'"); err(function () { assert.deepPropertyVal(obj, 'foo.bar', 'ball'); }, "expected { foo: { bar: 'baz' } } to have a deep property 'foo.bar' of 'ball', but got 'baz'"); err(function () { assert.propertyNotVal(simpleObj, 'foo', 'bar'); }, "expected { foo: 'bar' } to not have a property 'foo' of 'bar'"); err(function () { assert.deepPropertyNotVal(obj, 'foo.bar', 'baz'); }, "expected { foo: { bar: 'baz' } } to not have a deep property 'foo.bar' of 'baz'"); }); it('throws / throw / Throw', function() { ['throws', 'throw', 'Throw'].forEach(function (throws) { assert[throws](function() { throw new Error('foo'); }); assert[throws](function() { throw new Error('bar'); }, 'bar'); assert[throws](function() { throw new Error('bar'); }, /bar/); assert[throws](function() { throw new Error('bar'); }, Error); assert[throws](function() { throw new Error('bar'); }, Error, 'bar'); var thrownErr = assert[throws](function() { throw new Error('foo'); }); assert(thrownErr instanceof Error, 'assert.' + throws + ' returns error'); assert(thrownErr.message === 'foo', 'assert.' + throws + ' returns error message'); err(function () { assert[throws](function() { throw new Error('foo') }, TypeError); }, "expected [Function] to throw 'TypeError' but 'Error: foo' was thrown") err(function () { assert[throws](function() { throw new Error('foo') }, 'bar'); }, "expected [Function] to throw error including 'bar' but got 'foo'") err(function () { assert[throws](function() { throw new Error('foo') }, Error, 'bar'); }, "expected [Function] to throw error including 'bar' but got 'foo'") err(function () { assert[throws](function() { throw new Error('foo') }, TypeError, 'bar'); }, "expected [Function] to throw 'TypeError' but 'Error: foo' was thrown") err(function () { assert[throws](function() {}); }, "expected [Function] to throw an error"); err(function () { assert[throws](function() { throw new Error('') }, 'bar'); }, "expected [Function] to throw error including 'bar' but got ''"); err(function () { assert[throws](function() { throw new Error('') }, /bar/); }, "expected [Function] to throw error matching /bar/ but got ''"); }); }); it('doesNotThrow', function() { function CustomError(message) { this.name = 'CustomError'; this.message = message; } CustomError.prototype = Error.prototype; assert.doesNotThrow(function() { }); assert.doesNotThrow(function() { }, 'foo'); err(function () { assert.doesNotThrow(function() { throw new Error('foo'); }); }, "expected [Function] to not throw an error but 'Error: foo' was thrown"); err(function () { assert.doesNotThrow(function() { throw new CustomError('foo'); }); }, "expected [Function] to not throw an error but 'CustomError: foo' was thrown"); }); it('ifError', function() { assert.ifError(false); assert.ifError(null); assert.ifError(undefined); err(function () { var err = new Error('This is an error message'); assert.ifError(err); }, 'This is an error message'); }); it('operator', function() { // For testing undefined and null with == and === var w; assert.operator(1, '<', 2); assert.operator(2, '>', 1); assert.operator(1, '==', 1); assert.operator(1, '<=', 1); assert.operator(1, '>=', 1); assert.operator(1, '!=', 2); assert.operator(1, '!==', 2); assert.operator(1, '!==', '1'); assert.operator(w, '==', undefined); assert.operator(w, '===', undefined); assert.operator(w, '==', null); err(function () { assert.operator(1, '=', 2); }, 'Invalid operator "="'); err(function () { assert.operator(2, '<', 1); }, "expected 2 to be < 1"); err(function () { assert.operator(1, '>', 2); }, "expected 1 to be > 2"); err(function () { assert.operator(1, '==', 2); }, "expected 1 to be == 2"); err(function () { assert.operator(1, '===', '1'); }, "expected 1 to be === \'1\'"); err(function () { assert.operator(2, '<=', 1); }, "expected 2 to be <= 1"); err(function () { assert.operator(1, '>=', 2); }, "expected 1 to be >= 2"); err(function () { assert.operator(1, '!=', 1); }, "expected 1 to be != 1"); err(function () { assert.operator(1, '!==', 1); }, "expected 1 to be !== 1"); err(function () { assert.operator(w, '===', null); }, "expected undefined to be === null"); }); it('closeTo', function(){ assert.closeTo(1.5, 1.0, 0.5); assert.closeTo(10, 20, 20); assert.closeTo(-10, 20, 30); err(function(){ assert.closeTo(2, 1.0, 0.5); }, "expected 2 to be close to 1 +/- 0.5"); err(function(){ assert.closeTo(-10, 20, 29); }, "expected -10 to be close to 20 +/- 29"); err(function() { assert.closeTo([1.5], 1.0, 0.5); }, "expected [ 1.5 ] to be a number"); err(function() { assert.closeTo(1.5, "1.0", 0.5); }, "the arguments to closeTo or approximately must be numbers"); err(function() { assert.closeTo(1.5, 1.0, true); }, "the arguments to closeTo or approximately must be numbers"); }); it('approximately', function(){ assert.approximately(1.5, 1.0, 0.5); assert.approximately(10, 20, 20); assert.approximately(-10, 20, 30); err(function(){ assert.approximately(2, 1.0, 0.5); }, "expected 2 to be close to 1 +/- 0.5"); err(function(){ assert.approximately(-10, 20, 29); }, "expected -10 to be close to 20 +/- 29"); err(function() { assert.approximately([1.5], 1.0, 0.5); }, "expected [ 1.5 ] to be a number"); err(function() { assert.approximately(1.5, "1.0", 0.5); }, "the arguments to closeTo or approximately must be numbers"); err(function() { assert.approximately(1.5, 1.0, true); }, "the arguments to closeTo or approximately must be numbers"); }); it('members', function() { assert.includeMembers([1, 2, 3], [2, 3]); assert.includeMembers([1, 2, 3], []); assert.includeMembers([1, 2, 3], [3]); err(function() { assert.includeMembers([5, 6], [7, 8]); }, 'expected [ 5, 6 ] to be a superset of [ 7, 8 ]'); err(function() { assert.includeMembers([5, 6], [5, 6, 0]); }, 'expected [ 5, 6 ] to be a superset of [ 5, 6, 0 ]'); }); it('memberEquals', function() { assert.sameMembers([], []); assert.sameMembers([1, 2, 3], [3, 2, 1]); assert.sameMembers([4, 2], [4, 2]); err(function() { assert.sameMembers([], [1, 2]); }, 'expected [] to have the same members as [ 1, 2 ]'); err(function() { assert.sameMembers([1, 54], [6, 1, 54]); }, 'expected [ 1, 54 ] to have the same members as [ 6, 1, 54 ]'); }); it('oneOf', function() { assert.oneOf(1, [1, 2, 3]); var three = [3]; assert.oneOf(three, [1, 2, three]); var four = { four: 4 }; assert.oneOf(four, [1, 2, four]); err(function() { assert.oneOf(1, 1); }, 'expected 1 to be an array'); err(function() { assert.oneOf(1, { a: 1 }); }, 'expected { a: 1 } to be an array'); err(function() { assert.oneOf(9, [1, 2, 3], 'Message'); }, 'Message: expected 9 to be one of [ 1, 2, 3 ]'); err(function() { assert.oneOf([3], [1, 2, [3]]); }, 'expected [ 3 ] to be one of [ 1, 2, [ 3 ] ]'); err(function() { assert.oneOf({ four: 4 }, [1, 2, { four: 4 }]); }, 'expected { four: 4 } to be one of [ 1, 2, { four: 4 } ]'); }); it('above', function() { assert.isAbove(5, 2, '5 should be above 2'); err(function() { assert.isAbove(1, 3); }, 'expected 1 to be above 3'); err(function() { assert.isAbove(1, 1); }, 'expected 1 to be above 1'); }); it('atLeast', function() { assert.isAtLeast(5, 2, '5 should be above 2'); assert.isAtLeast(1, 1, '1 should be equal to 1'); err(function() { assert.isAtLeast(1, 3); }, 'expected 1 to be at least 3'); }); it('below', function() { assert.isBelow(2, 5, '2 should be below 5'); err(function() { assert.isBelow(3, 1); }, 'expected 3 to be below 1'); err(function() { assert.isBelow(1, 1); }, 'expected 1 to be below 1'); }); it('atMost', function() { assert.isAtMost(2, 5, '2 should be below 5'); assert.isAtMost(1, 1, '1 should be equal to 1'); err(function() { assert.isAtMost(3, 1); }, 'expected 3 to be at most 1'); }); it('memberDeepEquals', function() { assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members'); assert.sameDeepMembers([ {b: 3}, {a: 2}, 5, "hello" ], [ "hello", 5, {b: 3}, {a: 2} ], 'same deep members'); err(function() { assert.sameDeepMembers([ {b: 3} ], [ {c: 3} ]) }, 'expected [ { b: 3 } ] to have the same members as [ { c: 3 } ]'); err(function() { assert.sameDeepMembers([ {b: 3} ], [ {b: 5} ]) }, 'expected [ { b: 3 } ] to have the same members as [ { b: 5 } ]'); }); it('includeDeepMembers', function() { assert.includeDeepMembers([{a:1}, {b:2}, {c:3}], [{c:3}, {b:2}]); assert.includeDeepMembers([{a:1}, {b:2}, {c:3}], []); assert.includeDeepMembers([{a:1}, {b:2}, {c:3}], [{c:3}]); assert.includeDeepMembers([{a:1}, {b:2}, {c:3}, {c:3}], [{c:3}, {c:3}]); assert.includeDeepMembers([{a:1}, {b:2}, {c:3}], [{c:3}, {c:3}]); err(function() { assert.includeDeepMembers([{e:5}, {f:6}], [{g:7}, {h:8}]); }, 'expected [ { e: 5 }, { f: 6 } ] to be a superset of [ { g: 7 }, { h: 8 } ]'); err(function() { assert.includeDeepMembers([{e:5}, {f:6}], [{e:5}, {f:6}, {z:0}]); }, 'expected [ { e: 5 }, { f: 6 } ] to be a superset of [ { e: 5 }, { f: 6 }, { z: 0 } ]'); }); it('change', function() { var obj = { value: 10, str: 'foo' }, fn = function() { obj.value += 5 }, bangFn = function() { obj.str += '!' }, smFn = function() { 'foo' + 'bar' }; assert.changes(fn, obj, 'value'); assert.doesNotChange(smFn, obj, 'value'); assert.changes(bangFn, obj, 'str'); }); it('increase, decrease', function() { var obj = { value: 10 }, incFn = function() { obj.value += 2 }, decFn = function() { obj.value -= 3 }, smFn = function() { obj.value += 0 }; assert.decreases(decFn, obj, 'value'); assert.doesNotDecrease(smFn, obj, 'value'); assert.increases(incFn, obj, 'value'); assert.doesNotIncrease(smFn, obj, 'value'); }); it('isExtensible / extensible', function() { ['isExtensible', 'extensible'].forEach(function (isExtensible) { var nonExtensibleObject = Object.preventExtensions({}); assert[isExtensible]({}); err(function() { assert[isExtensible](nonExtensibleObject); }, 'expected {} to be extensible'); // Making sure ES6-like Object.isExtensible response is respected for all primitive types err(function() { assert[isExtensible](42); }, 'expected 42 to be extensible'); err(function() { assert[isExtensible](null); }, 'expected null to be extensible'); err(function() { assert[isExtensible]('foo'); }, 'expected \'foo\' to be extensible'); err(function() { assert[isExtensible](false); }, 'expected false to be extensible'); err(function() { assert[isExtensible](undefined); }, 'expected undefined to be extensible'); }); }); it('isNotExtensible / notExtensible', function() { ['isNotExtensible', 'notExtensible'].forEach(function (isNotExtensible) { var nonExtensibleObject = Object.preventExtensions({}); assert[isNotExtensible](nonExtensibleObject); err(function() { assert[isNotExtensible]({}); }, 'expected {} to not be extensible'); // Making sure ES6-like Object.isExtensible response is respected for all primitive types assert[isNotExtensible](42); assert[isNotExtensible](null); assert[isNotExtensible]('foo'); assert[isNotExtensible](false); assert[isNotExtensible](undefined); }); }); it('isSealed / sealed', function() { ['isSealed', 'sealed'].forEach(function (isSealed) { var sealedObject = Object.seal({}); assert[isSealed](sealedObject); err(function() { assert[isSealed]({}); }, 'expected {} to be sealed'); // Making sure ES6-like Object.isSealed response is respected for all primitive types assert[isSealed](42); assert[isSealed](null); assert[isSealed]('foo'); assert[isSealed](false); assert[isSealed](undefined); }); }); it('isNotSealed / notSealed', function() { ['isNotSealed', 'notSealed'].forEach(function (isNotSealed) { var sealedObject = Object.seal({}); assert[isNotSealed]({}); err(function() { assert[isNotSealed](sealedObject); }, 'expected {} to not be sealed'); // Making sure ES6-like Object.isSealed response is respected for all primitive types err(function() { assert[isNotSealed](42); }, 'expected 42 to not be sealed'); err(function() { assert[isNotSealed](null); }, 'expected null to not be sealed'); err(function() { assert[isNotSealed]('foo'); }, 'expected \'foo\' to not be sealed'); err(function() { assert[isNotSealed](false); }, 'expected false to not be sealed'); err(function() { assert[isNotSealed](undefined); }, 'expected undefined to not be sealed'); }); }); it('isFrozen / frozen', function() { ['isFrozen', 'frozen'].forEach(function (isFrozen) { var frozenObject = Object.freeze({}); assert[isFrozen](frozenObject); err(function() { assert[isFrozen]({}); }, 'expected {} to be frozen'); // Making sure ES6-like Object.isFrozen response is respected for all primitive types assert[isFrozen](42); assert[isFrozen](null); assert[isFrozen]('foo'); assert[isFrozen](false); assert[isFrozen](undefined); }); }); it('isNotFrozen / notFrozen', function() { ['isNotFrozen', 'notFrozen'].forEach(function (isNotFrozen) { var frozenObject = Object.freeze({}); assert[isNotFrozen]({}); err(function() { assert[isNotFrozen](frozenObject); }, 'expected {} to not be frozen'); // Making sure ES6-like Object.isFrozen response is respected for all primitive types err(function() { assert[isNotFrozen](42); }, 'expected 42 to not be frozen'); err(function() { assert[isNotFrozen](null); }, 'expected null to not be frozen'); err(function() { assert[isNotFrozen]('foo'); }, 'expected \'foo\' to not be frozen'); err(function() { assert[isNotFrozen](false); }, 'expected false to not be frozen'); err(function() { assert[isNotFrozen](undefined); }, 'expected undefined to not be frozen'); }); }); }); chai-3.5.0/test/auth/000775 000000 000000 00000000000 12652401517 014326 5ustar00rootroot000000 000000 chai-3.5.0/test/auth/.gitkeep000664 000000 000000 00000000000 12652401517 015745 0ustar00rootroot000000 000000 chai-3.5.0/test/bootstrap/000775 000000 000000 00000000000 12652401517 015402 5ustar00rootroot000000 000000 chai-3.5.0/test/bootstrap/index.js000664 000000 000000 00000000624 12652401517 017051 0ustar00rootroot000000 000000 /*! * Attach chai to global */ global.chai = require('../..'); /*! * Provide check for fail function. */ global.err = function (fn, msg) { try { fn(); throw new chai.AssertionError({ message: 'Expected an error' }); } catch (err) { if ('string' === typeof msg) { chai.expect(err.message).to.equal(msg); } else { chai.expect(err.message).to.match(msg); } } }; chai-3.5.0/test/bootstrap/karma.js000664 000000 000000 00000000504 12652401517 017032 0ustar00rootroot000000 000000 /*! * Provide check for fail function. */ window.err = function (fn, msg) { try { fn(); throw new chai.AssertionError('Expected an error'); } catch (err) { if ('string' === typeof msg) { chai.expect(err.message).to.equal(msg); } else { chai.expect(err.message).to.match(msg); } } }; chai-3.5.0/test/configuration.js000664 000000 000000 00000013255 12652401517 016600 0ustar00rootroot000000 000000 describe('configuration', function () { var assert = chai.assert; var origConfig; beforeEach(function() { // backup current config function clone(o) { return JSON.parse(JSON.stringify(o)); } origConfig = clone(chai.config); }); afterEach(function() { // restore config Object.keys(origConfig).forEach(function(key) { chai.config[key] = origConfig[key]; }); }); function fooThrows () { chai.expect('foo').to.be.equal('bar'); } function fooPropThrows () { chai.expect('foo').to.not.exist; } it('includeStack is true for method assertions', function () { chai.config.includeStack = true; try { fooThrows(); assert.ok(false, 'should not get here because error thrown'); } catch (err) { // not all browsers support err.stack if ('undefined' !== typeof err.stack) { assert.include(err.stack, 'assertEqual', 'should have internal stack trace in error message'); assert.include(err.stack, 'fooThrows', 'should have user stack trace in error message'); } } }); it('includeStack is false for method assertions', function () { chai.config.includeStack = false; try { fooThrows(); assert.ok(false, 'should not get here because error thrown'); } catch (err) { // IE 10 supports err.stack in Chrome format, but without // `Error.captureStackTrace` support that allows tuning of the error // message. if ('undefined' !== typeof err.stack && 'undefined' !== typeof Error.captureStackTrace) { assert.notInclude(err.stack, 'assertEqual', 'should not have internal stack trace in error message'); assert.include(err.stack, 'fooThrows', 'should have user stack trace in error message'); } } }); it('includeStack is true for property assertions', function () { chai.config.includeStack = true; try { fooPropThrows(); assert.ok(false, 'should not get here because error thrown'); } catch (err) { // not all browsers support err.stack // Phantom does not include function names for getter exec if ('undefined' !== typeof err.stack && 'undefined' !== typeof Error.captureStackTrace) { assert.include(err.stack, 'addProperty', 'should have internal stack trace in error message'); assert.include(err.stack, 'fooPropThrows', 'should have user stack trace in error message'); } } }); it('includeStack is false for property assertions', function () { chai.config.includeStack = false; try { fooPropThrows(); assert.ok(false, 'should not get here because error thrown'); } catch (err) { // IE 10 supports err.stack in Chrome format, but without // `Error.captureStackTrace` support that allows tuning of the error // message. if ('undefined' !== typeof err.stack && 'undefined' !== typeof Error.captureStackTrace) { assert.notInclude(err.stack, 'addProperty', 'should not have internal stack trace in error message'); assert.include(err.stack, 'fooPropThrows', 'should have user stack trace in error message'); } } }); describe('truncateThreshold', function() { it('is 20', function() { chai.config.truncateThreshold = 20; err(function() { assert.deepEqual({v: 'something longer than 20'}, {v: 'x'}); }, "expected { Object (v) } to deeply equal { v: 'x' }"); }); it('is 0', function() { chai.config.truncateThreshold = 0; err(function() { assert.deepEqual({v: 'something longer than 20'}, {v: 'x'}); }, "expected { v: 'something longer than 20' } to deeply equal { v: 'x' }"); }); }); describe('deprecated properties', function() { var origWarnFn; var warnings; beforeEach(function() { origWarnFn = console.warn; warnings = []; console.warn = function(message) { warnings.push(message); }; }); afterEach(function() { console.warn = origWarnFn; }); it('Assertion.includeStack warns that it is deprecated', function() { chai.Assertion.includeStack; assert.equal(warnings.length, 1); assert.equal(warnings[0], 'Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); chai.Assertion.includeStack = true; assert.equal(warnings.length, 2); assert.equal(warnings[1], 'Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); }); it('Assertion.includeStack is kept in sync with config.includeStack', function() { assert.equal(chai.Assertion.includeStack, chai.config.includeStack); chai.Assertion.includeStack = !chai.Assertion.includeStack; assert.equal(chai.Assertion.includeStack, chai.config.includeStack); chai.config.includeStack = !chai.config.includeStack; assert.equal(chai.Assertion.includeStack, chai.config.includeStack); }); it('Assertion.showDiff warns that it is deprecated', function() { chai.Assertion.showDiff; assert.equal(warnings.length, 1); assert.equal(warnings[0], 'Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); chai.Assertion.showDiff = true; assert.equal(warnings.length, 2); assert.equal(warnings[1], 'Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); }); it('Assertion.showDiff is kept in sync with config.showDiff', function() { assert.equal(chai.Assertion.showDiff, chai.config.showDiff); chai.Assertion.showDiff = !chai.Assertion.showDiff; assert.equal(chai.Assertion.showDiff, chai.config.showDiff); chai.config.showDiff = !chai.config.showDiff; assert.equal(chai.Assertion.showDiff, chai.config.showDiff); }); }); }); chai-3.5.0/test/display/000775 000000 000000 00000000000 12652401517 015032 5ustar00rootroot000000 000000 chai-3.5.0/test/display/errors.js000664 000000 000000 00000000334 12652401517 016704 0ustar00rootroot000000 000000 if (!chai) var chai = require('../..'); var expect = chai.expect; chai.config.includeStack = true; suite('error display', function () { test('show error line', function () { expect(4).to.equal(2); }); }); chai-3.5.0/test/display/message.js000664 000000 000000 00000001551 12652401517 017016 0ustar00rootroot000000 000000 var chai = require('../..') , expect = chai.expect , should = chai.should(); var deepObj = { green: { tea: 'matcha' } , teas: [ 'chai' , 'matcha' , { tea: 'konacha' } ] }; var deepObj2 = { green: { tea: 'matcha' } , teas: [ 'chai' , 'oolong' , { tea: 'konacha' } ] }; chai.config.includeStack = true; suite('object display', function () { test('property', function () { deepObj.should.have.property('chai'); }); test('deep equal', function () { deepObj.should.deep.equal(deepObj2); }); test('deep equal no diff', function () { chai.config.showDiff = false; deepObj.should.deep.equal(deepObj2); chai.config.showDiff = true; }); }); suite('undefined/null display', function() { test('undefined for actual', function() { expect(undefined).to.equal(null); }); }); chai-3.5.0/test/expect.js000664 000000 000000 00000120563 12652401517 015222 0ustar00rootroot000000 000000 describe('expect', function () { var expect = chai.expect; it('chai.version', function() { expect(chai).to.have.property('version'); }); it('assertion', function(){ expect('test').to.be.a('string'); expect('foo').to.equal('foo'); }); it('fail', function () { err(function() { expect.fail(0, 1, 'this has failed'); }, /this has failed/); }); it('true', function(){ expect(true).to.be.true; expect(false).to.not.be.true; expect(1).to.not.be.true; err(function(){ expect('test').to.be.true; }, "expected 'test' to be true") }); it('ok', function(){ expect(true).to.be.ok; expect(false).to.not.be.ok; expect(1).to.be.ok; expect(0).to.not.be.ok; err(function(){ expect('').to.be.ok; }, "expected '' to be truthy"); err(function(){ expect('test').to.not.be.ok; }, "expected 'test' to be falsy"); }); it('false', function(){ expect(false).to.be.false; expect(true).to.not.be.false; expect(0).to.not.be.false; err(function(){ expect('').to.be.false; }, "expected '' to be false") }); it('null', function(){ expect(null).to.be.null; expect(false).to.not.be.null; err(function(){ expect('').to.be.null; }, "expected '' to be null") }); it('undefined', function(){ expect(undefined).to.be.undefined; expect(null).to.not.be.undefined; err(function(){ expect('').to.be.undefined; }, "expected '' to be undefined") }); it('exist', function(){ var foo = 'bar' , bar; expect(foo).to.exist; expect(bar).to.not.exist; }); it('arguments', function(){ var args = (function(){ return arguments; })(1,2,3); expect(args).to.be.arguments; expect([]).to.not.be.arguments; expect(args).to.be.an('arguments').and.be.arguments; expect([]).to.be.an('array').and.not.be.Arguments; }); it('.equal()', function(){ var foo; expect(undefined).to.equal(foo); err(function(){ expect(undefined).to.equal(null); }, "expected undefined to equal null") }); it('typeof', function(){ expect('test').to.be.a('string'); err(function(){ expect('test').to.not.be.a('string'); }, "expected 'test' not to be a string"); (function () { expect(arguments).to.be.an('arguments'); })(1, 2); expect(5).to.be.a('number'); expect(new Number(1)).to.be.a('number'); expect(Number(1)).to.be.a('number'); expect(true).to.be.a('boolean'); expect(new Array()).to.be.a('array'); expect(new Object()).to.be.a('object'); expect({}).to.be.a('object'); expect([]).to.be.a('array'); expect(function() {}).to.be.a('function'); expect(null).to.be.a('null'); err(function(){ expect(5).to.not.be.a('number', 'blah'); }, "blah: expected 5 not to be a number"); }); it('instanceof', function(){ function Foo(){} expect(new Foo()).to.be.an.instanceof(Foo); err(function(){ expect(3).to.an.instanceof(Foo, 'blah'); }, "blah: expected 3 to be an instance of Foo"); }); it('within(start, finish)', function(){ expect(5).to.be.within(5, 10); expect(5).to.be.within(3,6); expect(5).to.be.within(3,5); expect(5).to.not.be.within(1,3); expect('foo').to.have.length.within(2,4); expect([ 1, 2, 3 ]).to.have.length.within(2,4); err(function(){ expect(5).to.not.be.within(4,6, 'blah'); }, "blah: expected 5 to not be within 4..6", 'blah'); err(function(){ expect(10).to.be.within(50,100, 'blah'); }, "blah: expected 10 to be within 50..100"); err(function () { expect('foo').to.have.length.within(5,7, 'blah'); }, "blah: expected \'foo\' to have a length within 5..7"); err(function () { expect([ 1, 2, 3 ]).to.have.length.within(5,7, 'blah'); }, "blah: expected [ 1, 2, 3 ] to have a length within 5..7"); }); it('above(n)', function(){ expect(5).to.be.above(2); expect(5).to.be.greaterThan(2); expect(5).to.not.be.above(5); expect(5).to.not.be.above(6); expect('foo').to.have.length.above(2); expect([ 1, 2, 3 ]).to.have.length.above(2); err(function(){ expect(5).to.be.above(6, 'blah'); }, "blah: expected 5 to be above 6", 'blah'); err(function(){ expect(10).to.not.be.above(6, 'blah'); }, "blah: expected 10 to be at most 6"); err(function () { expect('foo').to.have.length.above(4, 'blah'); }, "blah: expected \'foo\' to have a length above 4 but got 3"); err(function () { expect([ 1, 2, 3 ]).to.have.length.above(4, 'blah'); }, "blah: expected [ 1, 2, 3 ] to have a length above 4 but got 3"); }); it('least(n)', function(){ expect(5).to.be.at.least(2); expect(5).to.be.at.least(5); expect(5).to.not.be.at.least(6); expect('foo').to.have.length.of.at.least(2); expect([ 1, 2, 3 ]).to.have.length.of.at.least(2); err(function(){ expect(5).to.be.at.least(6, 'blah'); }, "blah: expected 5 to be at least 6", 'blah'); err(function(){ expect(10).to.not.be.at.least(6, 'blah'); }, "blah: expected 10 to be below 6"); err(function () { expect('foo').to.have.length.of.at.least(4, 'blah'); }, "blah: expected \'foo\' to have a length at least 4 but got 3"); err(function () { expect([ 1, 2, 3 ]).to.have.length.of.at.least(4, 'blah'); }, "blah: expected [ 1, 2, 3 ] to have a length at least 4 but got 3"); err(function () { expect([ 1, 2, 3, 4 ]).to.not.have.length.of.at.least(4, 'blah'); }, "blah: expected [ 1, 2, 3, 4 ] to have a length below 4"); }); it('below(n)', function(){ expect(2).to.be.below(5); expect(2).to.be.lessThan(5); expect(2).to.not.be.below(2); expect(2).to.not.be.below(1); expect('foo').to.have.length.below(4); expect([ 1, 2, 3 ]).to.have.length.below(4); err(function(){ expect(6).to.be.below(5, 'blah'); }, "blah: expected 6 to be below 5"); err(function(){ expect(6).to.not.be.below(10, 'blah'); }, "blah: expected 6 to be at least 10"); err(function () { expect('foo').to.have.length.below(2, 'blah'); }, "blah: expected \'foo\' to have a length below 2 but got 3"); err(function () { expect([ 1, 2, 3 ]).to.have.length.below(2, 'blah'); }, "blah: expected [ 1, 2, 3 ] to have a length below 2 but got 3"); }); it('most(n)', function(){ expect(2).to.be.at.most(5); expect(2).to.be.at.most(2); expect(2).to.not.be.at.most(1); expect(2).to.not.be.at.most(1); expect('foo').to.have.length.of.at.most(4); expect([ 1, 2, 3 ]).to.have.length.of.at.most(4); err(function(){ expect(6).to.be.at.most(5, 'blah'); }, "blah: expected 6 to be at most 5"); err(function(){ expect(6).to.not.be.at.most(10, 'blah'); }, "blah: expected 6 to be above 10"); err(function () { expect('foo').to.have.length.of.at.most(2, 'blah'); }, "blah: expected \'foo\' to have a length at most 2 but got 3"); err(function () { expect([ 1, 2, 3 ]).to.have.length.of.at.most(2, 'blah'); }, "blah: expected [ 1, 2, 3 ] to have a length at most 2 but got 3"); err(function () { expect([ 1, 2 ]).to.not.have.length.of.at.most(2, 'blah'); }, "blah: expected [ 1, 2 ] to have a length above 2"); }); it('match(regexp)', function(){ expect('foobar').to.match(/^foo/) expect('foobar').to.matches(/^foo/) expect('foobar').to.not.match(/^bar/) err(function(){ expect('foobar').to.match(/^bar/i, 'blah') }, "blah: expected 'foobar' to match /^bar/i"); err(function(){ expect('foobar').to.matches(/^bar/i, 'blah') }, "blah: expected 'foobar' to match /^bar/i"); err(function(){ expect('foobar').to.not.match(/^foo/i, 'blah') }, "blah: expected 'foobar' not to match /^foo/i"); }); it('length(n)', function(){ expect('test').to.have.length(4); expect('test').to.not.have.length(3); expect([1,2,3]).to.have.length(3); err(function(){ expect(4).to.have.length(3, 'blah'); }, 'blah: expected 4 to have a property \'length\''); err(function(){ expect('asd').to.not.have.length(3, 'blah'); }, "blah: expected 'asd' to not have a length of 3"); }); it('eql(val)', function(){ expect('test').to.eql('test'); expect({ foo: 'bar' }).to.eql({ foo: 'bar' }); expect(1).to.eql(1); expect('4').to.not.eql(4); err(function(){ expect(4).to.eql(3, 'blah'); }, 'blah: expected 4 to deeply equal 3'); }); if ('undefined' !== typeof Buffer) { it('Buffer eql()', function () { expect(new Buffer([ 1 ])).to.eql(new Buffer([ 1 ])); err(function () { expect(new Buffer([ 0 ])).to.eql(new Buffer([ 1 ])); }, 'expected to deeply equal '); }); } it('equal(val)', function(){ expect('test').to.equal('test'); expect(1).to.equal(1); err(function(){ expect(4).to.equal(3, 'blah'); }, 'blah: expected 4 to equal 3'); err(function(){ expect('4').to.equal(4, 'blah'); }, "blah: expected '4' to equal 4"); }); it('deep.equal(val)', function(){ expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' }); expect({ foo: 'bar' }).not.to.deep.equal({ foo: 'baz' }); }); it('deep.equal(/regexp/)', function(){ expect(/a/).to.deep.equal(/a/); expect(/a/).not.to.deep.equal(/b/); expect(/a/).not.to.deep.equal({}); expect(/a/g).to.deep.equal(/a/g); expect(/a/g).not.to.deep.equal(/b/g); expect(/a/i).to.deep.equal(/a/i); expect(/a/i).not.to.deep.equal(/b/i); expect(/a/m).to.deep.equal(/a/m); expect(/a/m).not.to.deep.equal(/b/m); }); it('deep.equal(Date)', function(){ var a = new Date(1, 2, 3) , b = new Date(4, 5, 6); expect(a).to.deep.equal(a); expect(a).not.to.deep.equal(b); expect(a).not.to.deep.equal({}); }); it('empty', function(){ function FakeArgs() {}; FakeArgs.prototype.length = 0; expect('').to.be.empty; expect('foo').not.to.be.empty; expect([]).to.be.empty; expect(['foo']).not.to.be.empty; expect(new FakeArgs).to.be.empty; expect({arguments: 0}).not.to.be.empty; expect({}).to.be.empty; expect({foo: 'bar'}).not.to.be.empty; err(function(){ expect('').not.to.be.empty; }, "expected \'\' not to be empty"); err(function(){ expect('foo').to.be.empty; }, "expected \'foo\' to be empty"); err(function(){ expect([]).not.to.be.empty; }, "expected [] not to be empty"); err(function(){ expect(['foo']).to.be.empty; }, "expected [ \'foo\' ] to be empty"); err(function(){ expect(new FakeArgs).not.to.be.empty; }, "expected { length: 0 } not to be empty"); err(function(){ expect({arguments: 0}).to.be.empty; }, "expected { arguments: 0 } to be empty"); err(function(){ expect({}).not.to.be.empty; }, "expected {} not to be empty"); err(function(){ expect({foo: 'bar'}).to.be.empty; }, "expected { foo: \'bar\' } to be empty"); }); it('NaN', function() { expect(NaN).to.be.NaN; expect('foo').to.be.NaN; expect({}).to.be.NaN; expect(4).not.to.be.NaN; expect([]).not.to.be.NaN; err(function(){ expect(4).to.be.NaN; }, "expected 4 to be NaN"); err(function(){ expect([]).to.be.NaN; }, "expected [] to be NaN"); err(function(){ expect('foo').not.to.be.NaN; }, "expected 'foo' not to be NaN"); }); it('property(name)', function(){ expect('test').to.have.property('length'); expect(4).to.not.have.property('length'); expect({ 'foo.bar': 'baz' }) .to.have.property('foo.bar'); expect({ foo: { bar: 'baz' } }) .to.not.have.property('foo.bar'); // Properties with the value 'undefined' are still properties var obj = { foo: undefined }; Object.defineProperty(obj, 'bar', { get: function() { } }); expect(obj).to.have.property('foo'); expect(obj).to.have.property('bar'); expect({ 'foo.bar[]': 'baz'}) .to.have.property('foo.bar[]'); err(function(){ expect('asd').to.have.property('foo'); }, "expected 'asd' to have a property 'foo'"); err(function(){ expect({ foo: { bar: 'baz' } }) .to.have.property('foo.bar'); }, "expected { foo: { bar: 'baz' } } to have a property 'foo.bar'"); }); it('deep.property(name)', function(){ expect({ 'foo.bar': 'baz'}) .to.not.have.deep.property('foo.bar'); expect({ foo: { bar: 'baz' } }) .to.have.deep.property('foo.bar'); expect({ 'foo': [1, 2, 3] }) .to.have.deep.property('foo[1]'); expect({ 'foo.bar[]': 'baz'}) .to.have.deep.property('foo\\.bar\\[\\]'); err(function(){ expect({ 'foo.bar': 'baz' }) .to.have.deep.property('foo.bar'); }, "expected { 'foo.bar': 'baz' } to have a deep property 'foo.bar'"); }); it('property(name, val)', function(){ expect('test').to.have.property('length', 4); expect('asd').to.have.property('constructor', String); var deepObj = { green: { tea: 'matcha' } , teas: [ 'chai', 'matcha', { tea: 'konacha' } ] }; expect(deepObj).to.have.deep.property('green.tea', 'matcha'); expect(deepObj).to.have.deep.property('teas[1]', 'matcha'); expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); expect(deepObj).to.have.property('teas') .that.is.an('array') .with.deep.property('[2]') .that.deep.equals({tea: 'konacha'}); err(function(){ expect(deepObj).to.have.deep.property('teas[3]'); }, "expected { Object (green, teas) } to have a deep property 'teas[3]'"); err(function(){ expect(deepObj).to.have.deep.property('teas[3]', 'bar'); }, "expected { Object (green, teas) } to have a deep property 'teas[3]'"); err(function(){ expect(deepObj).to.have.deep.property('teas[3].tea', 'bar'); }, "expected { Object (green, teas) } to have a deep property 'teas[3].tea'"); var arr = [ [ 'chai', 'matcha', 'konacha' ] , [ { tea: 'chai' } , { tea: 'matcha' } , { tea: 'konacha' } ] ]; expect(arr).to.have.deep.property('[0][1]', 'matcha'); expect(arr).to.have.deep.property('[1][2].tea', 'konacha'); err(function(){ expect(arr).to.have.deep.property('[2][1]'); }, "expected [ Array(2) ] to have a deep property '[2][1]'"); err(function(){ expect(arr).to.have.deep.property('[2][1]', 'none'); }, "expected [ Array(2) ] to have a deep property '[2][1]'"); err(function(){ expect(arr).to.have.deep.property('[0][3]', 'none'); }, "expected [ Array(2) ] to have a deep property '[0][3]'"); err(function(){ expect('asd').to.have.property('length', 4, 'blah'); }, "blah: expected 'asd' to have a property 'length' of 4, but got 3"); err(function(){ expect('asd').to.not.have.property('length', 3, 'blah'); }, "blah: expected 'asd' to not have a property 'length' of 3"); err(function(){ expect('asd').to.not.have.property('foo', 3, 'blah'); }, "blah: 'asd' has no property 'foo'"); err(function(){ expect('asd').to.have.property('constructor', Number, 'blah'); }, "blah: expected 'asd' to have a property 'constructor' of [Function: Number], but got [Function: String]"); }); it('deep.property(name, val)', function(){ expect({ foo: { bar: 'baz' } }) .to.have.deep.property('foo.bar', 'baz'); err(function(){ expect({ foo: { bar: 'baz' } }) .to.have.deep.property('foo.bar', 'quux', 'blah'); }, "blah: expected { foo: { bar: 'baz' } } to have a deep property 'foo.bar' of 'quux', but got 'baz'"); err(function(){ expect({ foo: { bar: 'baz' } }) .to.not.have.deep.property('foo.bar', 'baz', 'blah'); }, "blah: expected { foo: { bar: 'baz' } } to not have a deep property 'foo.bar' of 'baz'"); err(function(){ expect({ foo: 5 }) .to.not.have.deep.property('foo.bar', 'baz', 'blah'); }, "blah: { foo: 5 } has no deep property 'foo.bar'"); }); it('ownProperty(name)', function(){ expect('test').to.have.ownProperty('length'); expect('test').to.haveOwnProperty('length'); expect({ length: 12 }).to.have.ownProperty('length'); err(function(){ expect({ length: 12 }).to.not.have.ownProperty('length', 'blah'); }, "blah: expected { length: 12 } to not have own property 'length'"); }); it('ownPropertyDescriptor(name)', function(){ expect('test').to.have.ownPropertyDescriptor('length'); expect('test').to.haveOwnPropertyDescriptor('length'); expect('test').not.to.have.ownPropertyDescriptor('foo'); var obj = {}; var descriptor = { configurable: false, enumerable: true, writable: true, value: NaN }; Object.defineProperty(obj, 'test', descriptor); expect(obj).to.have.ownPropertyDescriptor('test', descriptor); err(function(){ expect(obj).not.to.have.ownPropertyDescriptor('test', descriptor, 'blah'); }, /^blah: expected the own property descriptor for 'test' on \{ test: NaN \} to not match \{ [^\}]+ \}$/); err(function(){ var wrongDescriptor = { configurable: false, enumerable: true, writable: false, value: NaN }; expect(obj).to.have.ownPropertyDescriptor('test', wrongDescriptor, 'blah'); }, /^blah: expected the own property descriptor for 'test' on \{ test: NaN \} to match \{ [^\}]+ \}, got \{ [^\}]+ \}$/); err(function(){ expect(obj).to.have.ownPropertyDescriptor('test2', 'blah'); }, "blah: expected { test: NaN } to have an own property descriptor for 'test2'"); expect(obj).to.have.ownPropertyDescriptor('test').and.have.property('enumerable', true); }); it('string()', function(){ expect('foobar').to.have.string('bar'); expect('foobar').to.have.string('foo'); expect('foobar').to.not.have.string('baz'); err(function(){ expect(3).to.have.string('baz'); }, "expected 3 to be a string"); err(function(){ expect('foobar').to.have.string('baz', 'blah'); }, "blah: expected 'foobar' to contain 'baz'"); err(function(){ expect('foobar').to.not.have.string('bar', 'blah'); }, "blah: expected 'foobar' to not contain 'bar'"); }); it('include()', function(){ expect(['foo', 'bar']).to.include('foo'); expect(['foo', 'bar']).to.include('foo'); expect(['foo', 'bar']).to.include('bar'); expect([1,2]).to.include(1); expect(['foo', 'bar']).to.not.include('baz'); expect(['foo', 'bar']).to.not.include(1); expect({a:1,b:2}).to.include({b:2}); expect({a:1,b:2}).to.not.include({b:3}); expect({a:1,b:2}).to.include({a:1,b:2}); expect({a:1,b:2}).to.not.include({a:1,c:2}); expect([{a:1},{b:2}]).to.include({a:1}); expect([{a:1}]).to.include({a:1}); expect([{a:1}]).to.not.include({b:1}); err(function(){ expect(['foo']).to.include('bar', 'blah'); }, "blah: expected [ 'foo' ] to include 'bar'"); err(function(){ expect(['bar', 'foo']).to.not.include('foo', 'blah'); }, "blah: expected [ 'bar', 'foo' ] to not include 'foo'"); err(function(){ expect({a:1}).to.include({b:2}); }, "expected { a: 1 } to have a property 'b'"); err(function(){ expect({a:1,b:2}).to.not.include({b:2}); }, "expected { a: 1, b: 2 } to not include { b: 2 }"); err(function(){ expect([{a:1},{b:2}]).to.not.include({b:2}); }, "expected [ { a: 1 }, { b: 2 } ] to not include { b: 2 }"); err(function(){ expect(true).to.include(true); }, "object tested must be an array, an object, or a string, but boolean given"); err(function(){ expect(42.0).to.include(42); }, "object tested must be an array, an object, or a string, but number given"); err(function(){ expect(null).to.include(42); }, "object tested must be an array, an object, or a string, but null given"); err(function(){ expect(undefined).to.include(42); }, "object tested must be an array, an object, or a string, but undefined given"); err(function(){ expect(true).to.not.include(true); }, "object tested must be an array, an object, or a string, but boolean given"); err(function(){ expect(42.0).to.not.include(42); }, "object tested must be an array, an object, or a string, but number given"); err(function(){ expect(null).to.not.include(42); }, "object tested must be an array, an object, or a string, but null given"); err(function(){ expect(undefined).to.not.include(42); }, "object tested must be an array, an object, or a string, but undefined given"); }); it('keys(array|Object|arguments)', function(){ expect({ foo: 1 }).to.have.keys(['foo']); expect({ foo: 1 }).have.keys({ 'foo': 6 }); expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']); expect({ foo: 1, bar: 2 }).to.have.keys('foo', 'bar'); expect({ foo: 1, bar: 2 }).have.keys({ 'foo': 6, 'bar': 7 }); expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar'); expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('bar', 'foo'); expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('baz'); expect({ foo: 1, bar: 2 }).contain.keys({ 'foo': 6 }); expect({ foo: 1, bar: 2 }).contain.keys({ 'bar': 7 }); expect({ foo: 1, bar: 2 }).contain.keys({ 'foo': 6 }); expect({ foo: 1, bar: 2 }).to.contain.keys('foo'); expect({ foo: 1, bar: 2 }).to.contain.keys('bar', 'foo'); expect({ foo: 1, bar: 2 }).to.contain.keys(['foo']); expect({ foo: 1, bar: 2 }).to.contain.keys(['bar']); expect({ foo: 1, bar: 2 }).to.contain.keys(['bar', 'foo']); expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']); expect({ foo: 1, bar: 2 }).to.not.have.keys('baz'); expect({ foo: 1, bar: 2 }).to.not.have.keys('foo', 'baz'); expect({ foo: 1, bar: 2 }).to.not.contain.keys('baz'); expect({ foo: 1, bar: 2 }).to.not.contain.keys('foo', 'baz'); expect({ foo: 1, bar: 2 }).to.not.contain.keys('baz', 'foo'); expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz'); expect({ foo: 1, bar: 2 }).to.have.any.keys('foo'); expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz'); expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']); expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']); expect({ foo: 1, bar: 2 }).to.contain.all.keys(['bar', 'foo']); expect({ foo: 1, bar: 2 }).contain.any.keys({ 'foo': 6 }); expect({ foo: 1, bar: 2 }).have.all.keys({ 'foo': 6, 'bar': 7 }); expect({ foo: 1, bar: 2 }).contain.all.keys({ 'bar': 7, 'foo': 6 }); expect({ foo: 1, bar: 2 }).to.not.have.any.keys('baz', 'abc', 'def'); expect({ foo: 1, bar: 2 }).to.not.have.any.keys('baz'); expect({ foo: 1, bar: 2 }).to.not.contain.any.keys('baz'); expect({ foo: 1, bar: 2 }).to.not.have.all.keys(['baz', 'foo']); expect({ foo: 1, bar: 2 }).to.not.contain.all.keys(['baz', 'foo']); expect({ foo: 1, bar: 2 }).not.have.all.keys({ 'baz': 8, 'foo': 7 }); expect({ foo: 1, bar: 2 }).not.contain.all.keys({ 'baz': 8, 'foo': 7 }); err(function(){ expect({ foo: 1 }).to.have.keys(); }, "keys required"); err(function(){ expect({ foo: 1 }).to.have.keys([]); }, "keys required"); err(function(){ expect({ foo: 1 }).to.not.have.keys([]); }, "keys required"); err(function(){ expect({ foo: 1 }).to.contain.keys([]); }, "keys required"); var mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments' err(function(){ expect({}).contain.keys(['a'], "b"); }, mixedArgsMsg); err(function(){ expect({}).contain.keys({ 'a': 1 }, "b"); }, mixedArgsMsg); err(function(){ expect({ foo: 1 }).to.have.keys(['bar']); }, "expected { foo: 1 } to have key 'bar'"); err(function(){ expect({ foo: 1 }).to.have.keys(['bar', 'baz']); }, "expected { foo: 1 } to have keys 'bar', and 'baz'"); err(function(){ expect({ foo: 1 }).to.have.keys(['foo', 'bar', 'baz']); }, "expected { foo: 1 } to have keys 'foo', 'bar', and 'baz'"); err(function(){ expect({ foo: 1 }).to.not.have.keys(['foo']); }, "expected { foo: 1 } to not have key 'foo'"); err(function(){ expect({ foo: 1 }).to.not.have.keys(['foo']); }, "expected { foo: 1 } to not have key 'foo'"); err(function(){ expect({ foo: 1, bar: 2 }).to.not.have.keys(['foo', 'bar']); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', and 'bar'"); err(function(){ expect({ foo: 1, bar: 2 }).to.have.all.keys('foo'); }, "expected { foo: 1, bar: 2 } to have key 'foo'"); err(function(){ expect({ foo: 1 }).to.not.contain.keys(['foo']); }, "expected { foo: 1 } to not contain key 'foo'"); err(function(){ expect({ foo: 1 }).to.contain.keys('foo', 'bar'); }, "expected { foo: 1 } to contain keys 'foo', and 'bar'"); err(function() { expect({ foo: 1 }).to.have.any.keys('baz'); }, "expected { foo: 1 } to have key 'baz'"); err(function(){ expect({ foo: 1, bar: 2 }).to.not.have.all.keys(['foo', 'bar']); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', and 'bar'"); err(function(){ expect({ foo: 1, bar: 2 }).to.not.have.any.keys(['foo', 'baz']); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', or 'baz'"); // repeat previous tests with Object as arg. err(function(){ expect({ foo: 1 }).have.keys({ 'bar': 1 }); }, "expected { foo: 1 } to have key 'bar'"); err(function(){ expect({ foo: 1 }).have.keys({ 'bar': 1, 'baz': 1}); }, "expected { foo: 1 } to have keys 'bar', and 'baz'"); err(function(){ expect({ foo: 1 }).have.keys({ 'foo': 1, 'bar': 1, 'baz': 1}); }, "expected { foo: 1 } to have keys 'foo', 'bar', and 'baz'"); err(function(){ expect({ foo: 1 }).not.have.keys({ 'foo': 1 }); }, "expected { foo: 1 } to not have key 'foo'"); err(function(){ expect({ foo: 1 }).not.have.keys({ 'foo': 1 }); }, "expected { foo: 1 } to not have key 'foo'"); err(function(){ expect({ foo: 1, bar: 2 }).not.have.keys({ 'foo': 1, 'bar': 1}); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', and 'bar'"); err(function(){ expect({ foo: 1 }).not.contain.keys({ 'foo': 1 }); }, "expected { foo: 1 } to not contain key 'foo'"); err(function(){ expect({ foo: 1 }).contain.keys('foo', 'bar'); }, "expected { foo: 1 } to contain keys 'foo', and 'bar'"); err(function() { expect({ foo: 1 }).have.any.keys('baz'); }, "expected { foo: 1 } to have key 'baz'"); err(function(){ expect({ foo: 1, bar: 2 }).not.have.all.keys({ 'foo': 1, 'bar': 1}); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', and 'bar'"); err(function(){ expect({ foo: 1, bar: 2 }).not.have.any.keys({ 'foo': 1, 'baz': 1}); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', or 'baz'"); }); it('keys(array) will not mutate array (#359)', function () { var expected = [ 'b', 'a' ]; var original_order = [ 'b', 'a' ]; var obj = { "b": 1, "a": 1 }; expect(expected).deep.equal(original_order); expect(obj).keys(original_order); expect(expected).deep.equal(original_order); }); it('chaining', function(){ var tea = { name: 'chai', extras: ['milk', 'sugar', 'smile'] }; expect(tea).to.have.property('extras').with.lengthOf(3); expect(tea).to.have.property('extras').which.contains('smile'); err(function(){ expect(tea).to.have.property('extras').with.lengthOf(4); }, "expected [ 'milk', 'sugar', 'smile' ] to have a length of 4 but got 3"); expect(tea).to.be.a('object').and.have.property('name', 'chai'); var badFn = function () { throw new Error('testing'); }; expect(badFn).to.throw(Error).with.property('message', 'testing'); }); it('throw', function () { // See GH-45: some poorly-constructed custom errors don't have useful names // on either their constructor or their constructor prototype, but instead // only set the name inside the constructor itself. var PoorlyConstructedError = function () { this.name = 'PoorlyConstructedError'; }; PoorlyConstructedError.prototype = Object.create(Error.prototype); function CustomError(message) { this.name = 'CustomError'; this.message = message; } CustomError.prototype = Error.prototype; var specificError = new RangeError('boo'); var goodFn = function () { 1==1; } , badFn = function () { throw new Error('testing'); } , refErrFn = function () { throw new ReferenceError('hello'); } , ickyErrFn = function () { throw new PoorlyConstructedError(); } , specificErrFn = function () { throw specificError; } , customErrFn = function() { throw new CustomError('foo'); }; expect(goodFn).to.not.throw(); expect(goodFn).to.not.throw(Error); expect(goodFn).to.not.throw(specificError); expect(badFn).to.throw(); expect(badFn).to.throw(Error); expect(badFn).to.not.throw(ReferenceError); expect(badFn).to.not.throw(specificError); expect(refErrFn).to.throw(); expect(refErrFn).to.throw(ReferenceError); expect(refErrFn).to.throw(Error); expect(refErrFn).to.not.throw(TypeError); expect(refErrFn).to.not.throw(specificError); expect(ickyErrFn).to.throw(); expect(ickyErrFn).to.throw(PoorlyConstructedError); expect(ickyErrFn).to.throw(Error); expect(ickyErrFn).to.not.throw(specificError); expect(specificErrFn).to.throw(specificError); expect(badFn).to.throw(/testing/); expect(badFn).to.not.throw(/hello/); expect(badFn).to.throw('testing'); expect(badFn).to.not.throw('hello'); expect(badFn).to.throw(Error, /testing/); expect(badFn).to.throw(Error, 'testing'); err(function(){ expect(goodFn).to.throw(); }, "expected [Function] to throw an error"); err(function(){ expect(goodFn).to.throw(ReferenceError); }, "expected [Function] to throw ReferenceError"); err(function(){ expect(goodFn).to.throw(specificError); }, "expected [Function] to throw 'RangeError: boo'"); err(function(){ expect(badFn).to.not.throw(); }, "expected [Function] to not throw an error but 'Error: testing' was thrown"); err(function(){ expect(badFn).to.throw(ReferenceError); }, "expected [Function] to throw 'ReferenceError' but 'Error: testing' was thrown"); err(function(){ expect(badFn).to.throw(specificError); }, "expected [Function] to throw 'RangeError: boo' but 'Error: testing' was thrown"); err(function(){ expect(badFn).to.not.throw(Error); }, "expected [Function] to not throw 'Error' but 'Error: testing' was thrown"); err(function(){ expect(refErrFn).to.not.throw(ReferenceError); }, "expected [Function] to not throw 'ReferenceError' but 'ReferenceError: hello' was thrown"); err(function(){ expect(badFn).to.throw(PoorlyConstructedError); }, "expected [Function] to throw 'PoorlyConstructedError' but 'Error: testing' was thrown"); err(function(){ expect(ickyErrFn).to.not.throw(PoorlyConstructedError); }, /^(expected \[Function\] to not throw 'PoorlyConstructedError' but)(.*)(PoorlyConstructedError|\{ Object \()(.*)(was thrown)$/); err(function(){ expect(ickyErrFn).to.throw(ReferenceError); }, /^(expected \[Function\] to throw 'ReferenceError' but)(.*)(PoorlyConstructedError|\{ Object \()(.*)(was thrown)$/); err(function(){ expect(specificErrFn).to.throw(new ReferenceError('eek')); }, "expected [Function] to throw 'ReferenceError: eek' but 'RangeError: boo' was thrown"); err(function(){ expect(specificErrFn).to.not.throw(specificError); }, "expected [Function] to not throw 'RangeError: boo'"); err(function (){ expect(badFn).to.not.throw(/testing/); }, "expected [Function] to throw error not matching /testing/"); err(function () { expect(badFn).to.throw(/hello/); }, "expected [Function] to throw error matching /hello/ but got 'testing'"); err(function () { expect(badFn).to.throw(Error, /hello/, 'blah'); }, "blah: expected [Function] to throw error matching /hello/ but got 'testing'"); err(function () { expect(badFn).to.throw(Error, 'hello', 'blah'); }, "blah: expected [Function] to throw error including 'hello' but got 'testing'"); err(function () { (customErrFn).should.not.throw(); }, "expected [Function] to not throw an error but 'CustomError: foo' was thrown"); }); it('respondTo', function(){ function Foo(){}; Foo.prototype.bar = function(){}; Foo.func = function() {}; var bar = {}; bar.foo = function(){}; expect(Foo).to.respondTo('bar'); expect(Foo).to.not.respondTo('foo'); expect(Foo).itself.to.respondTo('func'); expect(Foo).itself.not.to.respondTo('bar'); expect(bar).to.respondTo('foo'); err(function(){ expect(Foo).to.respondTo('baz', 'constructor'); }, /^(constructor: expected)(.*)(\[Function: Foo\])(.*)(to respond to \'baz\')$/); err(function(){ expect(bar).to.respondTo('baz', 'object'); }, /^(object: expected)(.*)(\{ foo: \[Function\] \}|\{ Object \()(.*)(to respond to \'baz\')$/); }); it('satisfy', function(){ var matcher = function (num) { return num === 1; }; expect(1).to.satisfy(matcher); err(function(){ expect(2).to.satisfy(matcher, 'blah'); }, "blah: expected 2 to satisfy [Function]"); }); it('closeTo', function(){ expect(1.5).to.be.closeTo(1.0, 0.5); expect(10).to.be.closeTo(20, 20); expect(-10).to.be.closeTo(20, 30); err(function(){ expect(2).to.be.closeTo(1.0, 0.5, 'blah'); }, "blah: expected 2 to be close to 1 +/- 0.5"); err(function(){ expect(-10).to.be.closeTo(20, 29, 'blah'); }, "blah: expected -10 to be close to 20 +/- 29"); err(function() { expect([1.5]).to.be.closeTo(1.0, 0.5); }, "expected [ 1.5 ] to be a number"); err(function() { expect(1.5).to.be.closeTo("1.0", 0.5); }, "the arguments to closeTo or approximately must be numbers"); err(function() { expect(1.5).to.be.closeTo(1.0, true); }, "the arguments to closeTo or approximately must be numbers"); }); it('approximately', function(){ expect(1.5).to.be.approximately(1.0, 0.5); expect(10).to.be.approximately(20, 20); expect(-10).to.be.approximately(20, 30); err(function(){ expect(2).to.be.approximately(1.0, 0.5, 'blah'); }, "blah: expected 2 to be close to 1 +/- 0.5"); err(function(){ expect(-10).to.be.approximately(20, 29, 'blah'); }, "blah: expected -10 to be close to 20 +/- 29"); err(function() { expect([1.5]).to.be.approximately(1.0, 0.5); }, "expected [ 1.5 ] to be a number"); err(function() { expect(1.5).to.be.approximately("1.0", 0.5); }, "the arguments to closeTo or approximately must be numbers"); err(function() { expect(1.5).to.be.approximately(1.0, true); }, "the arguments to closeTo or approximately must be numbers"); }); it('oneOf', function() { expect(1).to.be.oneOf([1, 2, 3]); expect('1').to.not.be.oneOf([1, 2, 3]); expect([3, [4]]).to.not.be.oneOf([1, 2, [3, 4]]); var threeFour = [3, [4]]; expect(threeFour).to.be.oneOf([1, 2, threeFour]); }); it('include.members', function() { expect([1, 2, 3]).to.include.members([]); expect([1, 2, 3]).to.include.members([3, 2]); expect([1, 2, 3]).to.not.include.members([8, 4]); expect([1, 2, 3]).to.not.include.members([1, 2, 3, 4]); }); it('same.members', function() { expect([5, 4]).to.have.same.members([4, 5]); expect([5, 4]).to.have.same.members([5, 4]); expect([5, 4]).to.not.have.same.members([]); expect([5, 4]).to.not.have.same.members([6, 3]); expect([5, 4]).to.not.have.same.members([5, 4, 2]); }); it('members', function() { expect([5, 4]).members([4, 5]); expect([5, 4]).members([5, 4]); expect([5, 4]).not.members([]); expect([5, 4]).not.members([6, 3]); expect([5, 4]).not.members([5, 4, 2]); expect([{ id: 1 }]).not.members([{ id: 1 }]); }); it('deep.members', function() { expect([{ id: 1 }]).deep.members([{ id: 1 }]); expect([{ id: 2 }]).not.deep.members([{ id: 1 }]); err(function(){ expect([{ id: 1 }]).deep.members([{ id: 2 }]) }, "expected [ { id: 1 } ] to have the same members as [ { id: 2 } ]"); }); it('change', function() { var obj = { value: 10, str: 'foo' }, fn = function() { obj.value += 5 }, sameFn = function() { 'foo' + 'bar' }, bangFn = function() { obj.str += '!' }; expect(fn).to.change(obj, 'value'); expect(sameFn).to.not.change(obj, 'value'); expect(sameFn).to.not.change(obj, 'str'); expect(bangFn).to.change(obj, 'str'); }); it('increase, decrease', function() { var obj = { value: 10 }, incFn = function() { obj.value += 2 }, decFn = function() { obj.value -= 3 }, smFn = function() { obj.value += 0 }; expect(smFn).to.not.increase(obj, 'value'); expect(decFn).to.not.increase(obj, 'value'); expect(incFn).to.increase(obj, 'value'); expect(smFn).to.not.decrease(obj, 'value'); expect(incFn).to.not.decrease(obj, 'value'); expect(decFn).to.decrease(obj, 'value'); }); it('extensible', function() { var nonExtensibleObject = Object.preventExtensions({}); expect({}).to.be.extensible; expect(nonExtensibleObject).to.not.be.extensible; err(function() { expect(nonExtensibleObject).to.be.extensible; }, 'expected {} to be extensible'); err(function() { expect({}).to.not.be.extensible; }, 'expected {} to not be extensible'); // Making sure ES6-like Object.isExtensible response is respected for all primitive types expect(42).to.not.be.extensible; expect(null).to.not.be.extensible; expect('foo').to.not.be.extensible; expect(false).to.not.be.extensible; expect(undefined).to.not.be.extensible; err(function() { expect(42).to.be.extensible; }, 'expected 42 to be extensible'); err(function() { expect(null).to.be.extensible; }, 'expected null to be extensible'); err(function() { expect('foo').to.be.extensible; }, 'expected \'foo\' to be extensible'); err(function() { expect(false).to.be.extensible; }, 'expected false to be extensible'); err(function() { expect(undefined).to.be.extensible; }, 'expected undefined to be extensible'); }); it('sealed', function() { var sealedObject = Object.seal({}); expect(sealedObject).to.be.sealed; expect({}).to.not.be.sealed; err(function() { expect({}).to.be.sealed; }, 'expected {} to be sealed'); err(function() { expect(sealedObject).to.not.be.sealed; }, 'expected {} to not be sealed'); // Making sure ES6-like Object.isSealed response is respected for all primitive types expect(42).to.be.sealed; expect(null).to.be.sealed; expect('foo').to.be.sealed; expect(false).to.be.sealed; expect(undefined).to.be.sealed; err(function() { expect(42).to.not.be.sealed; }, 'expected 42 to not be sealed'); err(function() { expect(null).to.not.be.sealed; }, 'expected null to not be sealed'); err(function() { expect('foo').to.not.be.sealed; }, 'expected \'foo\' to not be sealed'); err(function() { expect(false).to.not.be.sealed; }, 'expected false to not be sealed'); err(function() { expect(undefined).to.not.be.sealed; }, 'expected undefined to not be sealed'); }); it('frozen', function() { var frozenObject = Object.freeze({}); expect(frozenObject).to.be.frozen; expect({}).to.not.be.frozen; err(function() { expect({}).to.be.frozen; }, 'expected {} to be frozen'); err(function() { expect(frozenObject).to.not.be.frozen; }, 'expected {} to not be frozen'); // Making sure ES6-like Object.isFrozen response is respected for all primitive types expect(42).to.be.frozen; expect(null).to.be.frozen; expect('foo').to.be.frozen; expect(false).to.be.frozen; expect(undefined).to.be.frozen; err(function() { expect(42).to.not.be.frozen; }, 'expected 42 to not be frozen'); err(function() { expect(null).to.not.be.frozen; }, 'expected null to not be frozen'); err(function() { expect('foo').to.not.be.frozen; }, 'expected \'foo\' to not be frozen'); err(function() { expect(false).to.not.be.frozen; }, 'expected false to not be frozen'); err(function() { expect(undefined).to.not.be.frozen; }, 'expected undefined to not be frozen'); }); }); chai-3.5.0/test/globalShould.js000664 000000 000000 00000000477 12652401517 016352 0ustar00rootroot000000 000000 describe('global should', function () { it('works', function () { var theGlobal = typeof window !== 'undefined' ? window : global; theGlobal.globalShould = chai.should(); try { globalShould.not.exist(undefined); } finally { delete theGlobal.globalShould; } }); }); chai-3.5.0/test/plugins.js000664 000000 000000 00000001014 12652401517 015400 0ustar00rootroot000000 000000 describe('plugins', function () { function plugin (chai) { if (chai.Assertion.prototype.testing) return; Object.defineProperty(chai.Assertion.prototype, 'testing', { get: function () { return 'successful'; } }); } it('basic usage', function () { chai.use(plugin); var expect = chai.expect; expect(expect('').testing).to.equal('successful'); }); it('double plugin', function () { chai.expect(function () { chai.use(plugin); }).to.not.throw(); }); }); chai-3.5.0/test/should.js000664 000000 000000 00000100703 12652401517 015222 0ustar00rootroot000000 000000 describe('should', function() { var should = chai.Should(); it('assertion', function(){ 'test'.should.be.a('string'); should.equal('foo', 'foo'); should.not.equal('foo', 'bar'); }); it('fail', function () { err(function() { should.fail(0, 1, 'this has failed'); }, 'this has failed'); }); it('root exist', function () { var foo = 'foo' , bar = undefined; should.exist(foo); should.not.exist(bar); err(function () { should.exist(bar, 'blah'); }, "blah: expected undefined to exist"); err(function () { should.not.exist(foo, 'blah'); }, "blah: expected 'foo' to not exist") }); it('root equal', function () { var value1 = 'value' , value2 = 'value' , foo = 'foo'; should.equal(value1, value2); should.not.equal(value1, foo); err(function () { should.equal(value1, foo, 'blah'); }, "blah: expected 'value' to equal 'foo'"); err(function () { should.not.equal(value1, value2, 'blah'); }, "blah: expected 'value' to not equal 'value'") }); it('root Throw', function () { should.Throw(function() { throw new Error('error!') }, Error, 'error!'); should.not.Throw(function () { }); err(function () { should.Throw(function () { throw new Error('error!') }, Error, 'needed user!', 'blah'); }, "blah: expected [Function] to throw error including 'needed user!' but got 'error!'"); err(function () { should.not.Throw(function () { throw new Error('error!') }, Error, 'error!', 'blah'); }, "blah: expected [Function] to not throw 'Error' but 'Error: error!' was thrown"); }); it('true', function(){ (true).should.be.true; false.should.not.be.true; (1).should.not.be.true;false false.should.have.been.false; err(function(){ 'test'.should.be.true; }, "expected 'test' to be true") }); it('ok', function(){ true.should.be.ok; false.should.not.be.ok; (1).should.be.ok; (0).should.not.be.ok; err(function(){ ''.should.be.ok; }, "expected '' to be truthy"); err(function(){ 'test'.should.not.be.ok; }, "expected 'test' to be falsy"); }); it('false', function(){ false.should.be.false; true.should.not.be.false; (0).should.not.be.false; err(function(){ ''.should.be.false; }, "expected '' to be false") }); it('null', function(){ (0).should.not.be.null; err(function(){ ''.should.be.null; }, "expected '' to be null") }); it('NaN', function(){ 'foo'.should.be.NaN; (4).should.not.be.NaN; err(function(){ (4).should.be.NaN; }, "expected 4 to be NaN") }); it('undefined', function(){ (0).should.not.be.undefined; err(function(){ ''.should.be.undefined; }, "expected '' to be undefined") }); it('arguments', function(){ var args = (function(){ return arguments; })(1,2,3); args.should.be.arguments; [].should.not.be.arguments; }); it('.equal()', function(){ var foo; should.equal(undefined, foo); }); it('typeof', function(){ 'test'.should.be.a('string'); err(function(){ 'test'.should.not.be.a('string'); }, "expected 'test' not to be a string"); (5).should.be.a('number'); (new Number(1)).should.be.a('number'); Number(1).should.be.a('number'); (true).should.be.a('boolean'); (new Array()).should.be.a('array'); (new Object()).should.be.a('object'); ({}).should.be.a('object'); ([]).should.be.a('array'); (function() {}).should.be.a('function'); (5).should.be.a('number'); err(function(){ (5).should.not.be.a('number'); }, "expected 5 not to be a number"); }); it('instanceof', function(){ function Foo(){} new Foo().should.be.an.instanceof(Foo); err(function(){ (3).should.an.instanceof(Foo, 'blah'); }, "blah: expected 3 to be an instance of Foo"); }); it('within(start, finish)', function(){ (5).should.be.within(5, 10); (5).should.be.within(3,6); (5).should.be.within(3,5); (5).should.not.be.within(1,3); err(function(){ (5).should.not.be.within(4,6, 'blah'); }, "blah: expected 5 to not be within 4..6"); err(function(){ (10).should.be.within(50,100, 'blah'); }, "blah: expected 10 to be within 50..100"); err(function(){ ({ foo: 1 }).should.have.length.within(50,100, 'blah'); }, "blah: expected { foo: 1 } to have a property 'length'"); }); it('above(n)', function(){ (5).should.be.above(2); (5).should.be.greaterThan(2); (5).should.not.be.above(5); (5).should.not.be.above(6); err(function(){ (5).should.be.above(6, 'blah'); }, "blah: expected 5 to be above 6"); err(function(){ (10).should.not.be.above(6, 'blah'); }, "blah: expected 10 to be at most 6"); err(function(){ ({foo: 1}).should.have.length.above(3, 'blah'); }, "blah: expected { foo: 1 } to have a property 'length'"); }); it('least(n)', function(){ (5).should.be.at.least(5); (5).should.not.be.at.least(6); err(function(){ (5).should.be.at.least(6, 'blah'); }, "blah: expected 5 to be at least 6"); err(function(){ (10).should.not.be.at.least(6, 'blah'); }, "blah: expected 10 to be below 6"); err(function(){ ({foo: 1}).should.have.length.of.at.least(3, 'blah'); }, "blah: expected { foo: 1 } to have a property 'length'"); }); it('below(n)', function(){ (2).should.be.below(5); (2).should.be.lessThan(5); (2).should.not.be.below(2); (2).should.not.be.below(1); err(function(){ (6).should.be.below(5, 'blah'); }, "blah: expected 6 to be below 5"); err(function(){ (6).should.not.be.below(10, 'blah'); }, "blah: expected 6 to be at least 10"); err(function(){ ({foo: 1}).should.have.length.below(3, 'blah'); }, "blah: expected { foo: 1 } to have a property 'length'"); }); it('most(n)', function(){ (2).should.be.at.most(2); (2).should.not.be.at.most(1); err(function(){ (6).should.be.at.most(5, 'blah'); }, "blah: expected 6 to be at most 5"); err(function(){ (6).should.not.be.at.most(10, 'blah'); }, "blah: expected 6 to be above 10"); err(function(){ ({foo: 1}).should.have.length.of.at.most(3, 'blah'); }, "blah: expected { foo: 1 } to have a property 'length'"); }); it('match(regexp)', function(){ 'foobar'.should.match(/^foo/) 'foobar'.should.not.match(/^bar/) err(function(){ 'foobar'.should.match(/^bar/i, 'blah') }, "blah: expected 'foobar' to match /^bar/i"); err(function(){ 'foobar'.should.not.match(/^foo/i, 'blah') }, "blah: expected 'foobar' not to match /^foo/i"); }); it('length(n)', function(){ 'test'.should.have.length(4); 'test'.should.not.have.length(3); [1,2,3].should.have.length(3); err(function(){ (4).should.have.length(3, 'blah'); }, 'blah: expected 4 to have a property \'length\''); err(function(){ 'asd'.should.not.have.length(3, 'blah'); }, "blah: expected 'asd' to not have a length of 3"); }); it('eql(val)', function(){ var a = new Date(1, 2, 3) , b = new Date(4, 5, 6); a.should.eql(a); a.should.not.eql(b); a.should.not.eql({}); 'test'.should.eql('test'); ({ foo: 'bar' }).should.eql({ foo: 'bar' }); /a/.should.eql(/a/); /a/.should.not.eql(/b/); /a/.should.not.eql({}); /a/g.should.eql(/a/g); /a/g.should.not.eql(/b/g); /a/i.should.eql(/a/i); /a/i.should.not.eql(/b/i); /a/m.should.eql(/a/m); /a/m.should.not.eql(/b/m); (1).should.eql(1); '4'.should.not.eql(4); err(function(){ (4).should.eql(3, 'blah'); }, 'blah: expected 4 to deeply equal 3'); }); it('equal(val)', function(){ 'test'.should.equal('test'); (1).should.equal(1); err(function(){ (4).should.equal(3, 'blah'); }, 'blah: expected 4 to equal 3'); err(function(){ '4'.should.equal(4, 'blah'); }, "blah: expected '4' to equal 4"); }); it('empty', function(){ function FakeArgs() {}; FakeArgs.prototype.length = 0; ''.should.be.empty; 'foo'.should.not.be.empty; ([]).should.be.empty; (['foo']).should.not.be.empty; (new FakeArgs).should.be.empty; ({arguments: 0}).should.not.be.empty; ({}).should.be.empty; ({foo: 'bar'}).should.not.be.empty; err(function(){ ''.should.not.be.empty; }, "expected \'\' not to be empty"); err(function(){ 'foo'.should.be.empty; }, "expected \'foo\' to be empty"); err(function(){ ([]).should.not.be.empty; }, "expected [] not to be empty"); err(function(){ (['foo']).should.be.empty; }, "expected [ \'foo\' ] to be empty"); err(function(){ (new FakeArgs).should.not.be.empty; }, "expected { length: 0 } not to be empty"); err(function(){ ({arguments: 0}).should.be.empty; }, "expected { arguments: 0 } to be empty"); err(function(){ ({}).should.not.be.empty; }, "expected {} not to be empty"); err(function(){ ({foo: 'bar'}).should.be.empty; }, "expected { foo: \'bar\' } to be empty"); }); it('property(name)', function(){ 'test'.should.have.property('length'); (4).should.not.have.property('length'); err(function(){ 'asd'.should.have.property('foo'); }, "expected 'asd' to have a property 'foo'"); }); it('property(name, val)', function(){ 'test'.should.have.property('length', 4); 'asd'.should.have.property('constructor', String); err(function(){ 'asd'.should.have.property('length', 4, 'blah'); }, "blah: expected 'asd' to have a property 'length' of 4, but got 3"); err(function(){ 'asd'.should.not.have.property('length', 3, 'blah'); }, "blah: expected 'asd' to not have a property 'length' of 3"); err(function(){ 'asd'.should.not.have.property('foo', 3, 'blah'); }, "blah: 'asd' has no property 'foo'"); err(function(){ 'asd'.should.have.property('constructor', Number, 'blah'); }, "blah: expected 'asd' to have a property 'constructor' of [Function: Number], but got [Function: String]"); }); it('ownProperty(name)', function(){ 'test'.should.have.ownProperty('length'); 'test'.should.haveOwnProperty('length'); ({ length: 12 }).should.have.ownProperty('length'); err(function(){ ({ length: 12 }).should.not.have.ownProperty('length', 'blah'); }, "blah: expected { length: 12 } to not have own property 'length'"); }); it('ownPropertyDescriptor(name)', function(){ 'test'.should.haveOwnPropertyDescriptor('length'); 'test'.should.have.ownPropertyDescriptor('length'); 'test'.should.not.have.ownPropertyDescriptor('foo'); var obj = { }; var descriptor = { configurable: false, enumerable: true, writable: true, value: NaN }; Object.defineProperty(obj, 'test', descriptor); obj.should.haveOwnPropertyDescriptor('test', descriptor); err(function(){ obj.should.not.haveOwnPropertyDescriptor('test', descriptor, 'blah'); }, /^blah: expected the own property descriptor for 'test' on \{ test: NaN \} to not match \{ [^\}]+ \}$/); err(function(){ var wrongDescriptor = { configurable: false, enumerable: true, writable: false, value: NaN }; obj.should.haveOwnPropertyDescriptor('test', wrongDescriptor, 'blah'); }, /^blah: expected the own property descriptor for 'test' on \{ test: NaN \} to match \{ [^\}]+ \}, got \{ [^\}]+ \}$/); err(function(){ obj.should.haveOwnPropertyDescriptor('test2', 'blah'); }, "blah: expected { test: NaN } to have an own property descriptor for 'test2'"); obj.should.have.ownPropertyDescriptor('test').and.have.property('enumerable', true); }); it('string()', function(){ 'foobar'.should.contain.string('bar'); 'foobar'.should.contain.string('foo'); 'foobar'.should.not.contain.string('baz'); err(function(){ (3).should.contain.string('baz', 'blah'); }, "blah: expected 3 to be a string"); err(function(){ 'foobar'.should.contain.string('baz', 'blah'); }, "blah: expected 'foobar' to contain 'baz'"); err(function(){ 'foobar'.should.not.contain.string('bar', 'blah'); }, "blah: expected 'foobar' to not contain 'bar'"); }); it('oneOf()', function(){ 'foo'.should.be.oneOf(['foo', 'bar']); 'bar'.should.be.oneOf(['foo', 'bar']); 'baz'.should.not.be.oneOf(['foo', 'bar']); 'baz'.should.not.be.oneOf([]); }); it('include()', function(){ ['foo', 'bar'].should.include('foo'); ['foo', 'bar'].should.contain('foo'); ['foo', 'bar'].should.include('bar'); [1,2].should.include(1); ['foo', 'bar'].should.not.include('baz'); ['foo', 'bar'].should.not.include(1); ({a:1,b:2}).should.include({b:2}); ({a:1,b:2}).should.not.include({b:3}); err(function(){ ['foo'].should.include('bar', 'blah'); }, "blah: expected [ 'foo' ] to include 'bar'"); err(function(){ ['bar', 'foo'].should.not.include('foo', 'blah'); }, "blah: expected [ 'bar', 'foo' ] to not include 'foo'"); err(function(){ ({a:1}).should.include({b:2}); }, "expected { a: 1 } to have a property 'b'"); err(function(){ (true).should.include(true); }, "object tested must be an array, an object, or a string, but boolean given"); err(function(){ (42).should.include(4); }, "object tested must be an array, an object, or a string, but number given"); err(function(){ (true).should.not.include(true); }, "object tested must be an array, an object, or a string, but boolean given"); err(function(){ (42).should.not.include(4); }, "object tested must be an array, an object, or a string, but number given"); }); it('keys(array|Object|arguments)', function(){ ({ foo: 1 }).should.have.keys(['foo']); ({ foo: 1 }).should.have.keys({ 'foo': 6 }); ({ foo: 1, bar: 2 }).should.have.keys(['foo', 'bar']); ({ foo: 1, bar: 2 }).should.have.keys('foo', 'bar'); ({ foo: 1, bar: 2 }).should.have.keys({ 'foo': 6, 'bar': 7 }); ({ foo: 1, bar: 2, baz: 3 }).should.include.keys('foo', 'bar'); ({ foo: 1, bar: 2, baz: 3 }).should.contain.keys('bar', 'foo'); ({ foo: 1, bar: 2, baz: 3 }).should.contain.keys('baz'); ({ foo: 1, bar: 2 }).should.contain.keys('foo'); ({ foo: 1, bar: 2 }).should.contain.keys('bar', 'foo'); ({ foo: 1, bar: 2 }).should.contain.keys(['foo']); ({ foo: 1, bar: 2 }).should.contain.keys(['bar']); ({ foo: 1, bar: 2 }).should.contain.keys(['bar', 'foo']); ({ foo: 1, bar: 2 }).should.contain.keys({ 'foo': 6 }); ({ foo: 1, bar: 2 }).should.contain.keys({ 'bar': 7 }); ({ foo: 1, bar: 2 }).should.contain.keys({ 'foo': 6 }); ({ foo: 1, bar: 2 }).should.not.have.keys('baz'); ({ foo: 1, bar: 2 }).should.not.have.keys('foo', 'baz'); ({ foo: 1, bar: 2 }).should.not.contain.keys('baz'); ({ foo: 1, bar: 2 }).should.not.contain.keys('foo', 'baz'); ({ foo: 1, bar: 2 }).should.not.contain.keys('baz', 'foo'); ({ foo: 1, bar: 2 }).should.have.any.keys('foo', 'baz'); ({ foo: 1, bar: 2 }).should.have.any.keys('foo'); ({ foo: 1, bar: 2 }).should.contain.any.keys('bar', 'baz'); ({ foo: 1, bar: 2 }).should.contain.any.keys(['foo']); ({ foo: 1, bar: 2 }).should.have.all.keys(['bar', 'foo']); ({ foo: 1, bar: 2 }).should.contain.all.keys(['bar', 'foo']); ({ foo: 1, bar: 2 }).should.contain.any.keys({ 'foo': 6 }); ({ foo: 1, bar: 2 }).should.have.all.keys({ 'foo': 6, 'bar': 7 }); ({ foo: 1, bar: 2 }).should.contain.all.keys({ 'bar': 7, 'foo': 6 }); ({ foo: 1, bar: 2 }).should.not.have.any.keys('baz', 'abc', 'def'); ({ foo: 1, bar: 2 }).should.not.have.any.keys('baz'); ({ foo: 1, bar: 2 }).should.not.contain.any.keys('baz'); ({ foo: 1, bar: 2 }).should.not.have.all.keys(['baz', 'foo']); ({ foo: 1, bar: 2 }).should.not.contain.all.keys(['baz', 'foo']); ({ foo: 1, bar: 2 }).should.not.have.all.keys({ 'baz': 8, 'foo': 7 }); ({ foo: 1, bar: 2 }).should.not.contain.all.keys({ 'baz': 8, 'foo': 7 }); err(function(){ ({ foo: 1 }).should.have.keys(); }, "keys required"); err(function(){ ({ foo: 1 }).should.have.keys([]); }, "keys required"); err(function(){ ({ foo: 1 }).should.not.have.keys([]); }, "keys required"); err(function(){ ({ foo: 1 }).should.contain.keys([]); }, "keys required"); var mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments' err(function(){ ({}).should.contain.keys(['a'], "b"); }, mixedArgsMsg); err(function(){ ({}).should.contain.keys({ 'a': 1 }, "b"); }, mixedArgsMsg); err(function(){ ({ foo: 1 }).should.have.keys(['bar']); }, "expected { foo: 1 } to have key 'bar'"); err(function(){ ({ foo: 1 }).should.have.keys(['bar', 'baz']); }, "expected { foo: 1 } to have keys 'bar', and 'baz'"); err(function(){ ({ foo: 1 }).should.have.keys(['foo', 'bar', 'baz']); }, "expected { foo: 1 } to have keys 'foo', 'bar', and 'baz'"); err(function(){ ({ foo: 1 }).should.not.have.keys(['foo']); }, "expected { foo: 1 } to not have key 'foo'"); err(function(){ ({ foo: 1 }).should.not.have.keys(['foo']); }, "expected { foo: 1 } to not have key 'foo'"); err(function(){ ({ foo: 1, bar: 2 }).should.not.have.keys(['foo', 'bar']); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', and 'bar'"); err(function(){ ({ foo: 1 }).should.not.contain.keys(['foo']); }, "expected { foo: 1 } to not contain key 'foo'"); err(function(){ ({ foo: 1 }).should.contain.keys('foo', 'bar'); }, "expected { foo: 1 } to contain keys 'foo', and 'bar'"); err(function() { ({ foo: 1 }).should.have.any.keys('baz'); }, "expected { foo: 1 } to have key 'baz'"); err(function(){ ({ foo: 1, bar: 2 }).should.not.have.all.keys(['foo', 'bar']); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', and 'bar'"); err(function(){ ({ foo: 1, bar: 2 }).should.not.have.any.keys(['foo', 'baz']); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', or 'baz'"); // repeat previous tests with Object as arg. err(function(){ ({ foo: 1 }).should.have.keys({ 'bar': 1 }); }, "expected { foo: 1 } to have key 'bar'"); err(function(){ ({ foo: 1 }).should.have.keys({ 'bar': 1, 'baz': 1}); }, "expected { foo: 1 } to have keys 'bar', and 'baz'"); err(function(){ ({ foo: 1 }).should.have.keys({ 'foo': 1, 'bar': 1, 'baz': 1}); }, "expected { foo: 1 } to have keys 'foo', 'bar', and 'baz'"); err(function(){ ({ foo: 1 }).should.not.have.keys({ 'foo': 1 }); }, "expected { foo: 1 } to not have key 'foo'"); err(function(){ ({ foo: 1 }).should.not.have.keys({ 'foo': 1 }); }, "expected { foo: 1 } to not have key 'foo'"); err(function(){ ({ foo: 1, bar: 2 }).should.not.have.keys({ 'foo': 1, 'bar': 1}); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', and 'bar'"); err(function(){ ({ foo: 1 }).should.not.contain.keys({ 'foo': 1 }); }, "expected { foo: 1 } to not contain key 'foo'"); err(function(){ ({ foo: 1 }).should.contain.keys('foo', 'bar'); }, "expected { foo: 1 } to contain keys 'foo', and 'bar'"); err(function() { ({ foo: 1 }).should.have.any.keys('baz'); }, "expected { foo: 1 } to have key 'baz'"); err(function(){ ({ foo: 1, bar: 2 }).should.not.have.all.keys({ 'foo': 1, 'bar': 1}); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', and 'bar'"); err(function(){ ({ foo: 1, bar: 2 }).should.not.have.any.keys({ 'foo': 1, 'baz': 1}); }, "expected { foo: 1, bar: 2 } to not have keys 'foo', or 'baz'"); }); it('keys(array) will not mutate array (#359)', function () { var expected = [ 'b', 'a' ]; var original_order = [ 'b', 'a' ]; var obj = { "b": 1, "a": 1 }; expected.should.deep.equal(original_order); obj.should.keys(original_order); expected.should.deep.equal(original_order); }); it('throw', function () { // See GH-45: some poorly-constructed custom errors don't have useful names // on either their constructor or their constructor prototype, but instead // only set the name inside the constructor itself. var PoorlyConstructedError = function () { this.name = 'PoorlyConstructedError'; }; PoorlyConstructedError.prototype = Object.create(Error.prototype); function CustomError(message) { this.name = 'CustomError'; this.message = message; } CustomError.prototype = Error.prototype; var specificError = new RangeError('boo'); var goodFn = function () { 1==1; } , badFn = function () { throw new Error('testing'); } , stringErrFn = function () { throw 'testing'; } , refErrFn = function () { throw new ReferenceError('hello'); } , ickyErrFn = function () { throw new PoorlyConstructedError(); } , specificErrFn = function () { throw specificError; } , customErrFn = function() { throw new CustomError('foo'); }; (goodFn).should.not.throw(); (goodFn).should.not.throw(Error); (goodFn).should.not.throw(specificError); (badFn).should.throw(); (badFn).should.throw(Error); (badFn).should.not.throw(ReferenceError); (badFn).should.not.throw(specificError); (stringErrFn).should.throw(); (stringErrFn).should.not.throw(ReferenceError); (stringErrFn).should.not.throw(specificError); (refErrFn).should.throw(); (refErrFn).should.throw(ReferenceError); (refErrFn).should.throw(Error); (refErrFn).should.not.throw(TypeError); (refErrFn).should.not.throw(specificError); (ickyErrFn).should.throw(); (ickyErrFn).should.throw(PoorlyConstructedError); (ickyErrFn).should.throw(Error); (ickyErrFn).should.not.throw(specificError); (specificErrFn).should.throw(specificError); (badFn).should.throw(/testing/); (badFn).should.throw('testing'); (badFn).should.not.throw(/hello/); (badFn).should.not.throw('hello'); (badFn).should.throw(Error, /testing/); (badFn).should.throw(Error, 'testing'); (stringErrFn).should.throw(/testing/); (stringErrFn).should.throw('testing'); (stringErrFn).should.not.throw(/hello/); (stringErrFn).should.not.throw('hello'); should.throw(badFn); should.throw(refErrFn, ReferenceError); should.throw(refErrFn, Error); should.throw(ickyErrFn, PoorlyConstructedError); should.throw(specificErrFn, specificError); should.not.throw(goodFn); should.not.throw(badFn, ReferenceError); should.not.throw(badFn, specificError); should.throw(badFn, Error, /testing/); should.throw(badFn, Error, 'testing'); err(function(){ (goodFn).should.throw(); }, "expected [Function] to throw an error"); err(function(){ (goodFn).should.throw(ReferenceError); }, "expected [Function] to throw ReferenceError"); err(function(){ (goodFn).should.throw(specificError); }, "expected [Function] to throw 'RangeError: boo'"); err(function(){ (badFn).should.not.throw(); }, "expected [Function] to not throw an error but 'Error: testing' was thrown"); err(function(){ (badFn).should.throw(ReferenceError); }, "expected [Function] to throw 'ReferenceError' but 'Error: testing' was thrown"); err(function(){ (badFn).should.throw(specificError); }, "expected [Function] to throw 'RangeError: boo' but 'Error: testing' was thrown"); err(function(){ (badFn).should.not.throw(Error); }, "expected [Function] to not throw 'Error' but 'Error: testing' was thrown"); err(function(){ (stringErrFn).should.not.throw(); }, "expected [Function] to not throw an error but 'testing' was thrown"); err(function(){ (stringErrFn).should.throw(ReferenceError); }, "expected [Function] to throw 'ReferenceError' but 'testing' was thrown"); err(function(){ (stringErrFn).should.throw(specificError); }, "expected [Function] to throw 'RangeError: boo' but 'testing' was thrown"); err(function(){ (stringErrFn).should.not.throw('testing'); }, "expected [Function] to throw error not including 'testing'"); err(function(){ (refErrFn).should.not.throw(ReferenceError); }, "expected [Function] to not throw 'ReferenceError' but 'ReferenceError: hello' was thrown"); err(function(){ (badFn).should.throw(PoorlyConstructedError); }, "expected [Function] to throw 'PoorlyConstructedError' but 'Error: testing' was thrown") err(function(){ (ickyErrFn).should.not.throw(PoorlyConstructedError); }, /^(expected \[Function\] to not throw 'PoorlyConstructedError' but)(.*)(PoorlyConstructedError|\{ Object \()(.*)(was thrown)$/); err(function(){ (ickyErrFn).should.throw(ReferenceError); }, /^(expected \[Function\] to throw 'ReferenceError' but)(.*)(PoorlyConstructedError|\{ Object \()(.*)(was thrown)$/); err(function(){ (specificErrFn).should.throw(new ReferenceError('eek')); }, "expected [Function] to throw 'ReferenceError: eek' but 'RangeError: boo' was thrown"); err(function(){ (specificErrFn).should.not.throw(specificError); }, "expected [Function] to not throw 'RangeError: boo'"); err(function (){ (badFn).should.not.throw(/testing/); }, "expected [Function] to throw error not matching /testing/"); err(function () { (badFn).should.throw(/hello/); }, "expected [Function] to throw error matching /hello/ but got \'testing\'"); err(function () { (badFn).should.throw(Error, /hello/, 'blah'); }, "blah: expected [Function] to throw error matching /hello/ but got 'testing'"); err(function () { (badFn).should.throw(Error, 'hello', 'blah'); }, "blah: expected [Function] to throw error including 'hello' but got 'testing'"); err(function () { (customErrFn).should.not.throw(); }, "expected [Function] to not throw an error but 'CustomError: foo' was thrown"); }); it('respondTo', function(){ function Foo(){}; Foo.prototype.bar = function(){}; Foo.func = function(){}; var bar = {}; bar.foo = function(){}; Foo.should.respondTo('bar'); Foo.should.not.respondTo('foo'); Foo.should.itself.respondTo('func'); Foo.should.itself.not.respondTo('bar'); bar.should.respondTo('foo'); err(function(){ Foo.should.respondTo('baz', 'constructor'); }, /^(constructor: expected)(.*)(\[Function: Foo\])(.*)(to respond to \'baz\')$/); err(function(){ bar.should.respondTo('baz', 'object'); }, /^(object: expected)(.*)(\{ foo: \[Function\] \}|\{ Object \()(.*)(to respond to \'baz\')$/); }); it('satisfy', function(){ var matcher = function (num){ return num === 1; }; (1).should.satisfy(matcher); err(function(){ (2).should.satisfy(matcher, 'blah'); }, "blah: expected 2 to satisfy [Function]"); }); it('closeTo', function(){ (1.5).should.be.closeTo(1.0, 0.5); err(function(){ (2).should.be.closeTo(1.0, 0.5, 'blah'); }, "blah: expected 2 to be close to 1 +/- 0.5"); err(function() { [1.5].should.be.closeTo(1.0, 0.5); }, "expected [ 1.5 ] to be a number"); err(function() { (1.5).should.be.closeTo("1.0", 0.5); }, "the arguments to closeTo or approximately must be numbers"); err(function() { (1.5).should.be.closeTo(1.0, true); }, "the arguments to closeTo or approximately must be numbers"); }); it('approximately', function(){ (1.5).should.be.approximately(1.0, 0.5); err(function(){ (2).should.be.approximately(1.0, 0.5, 'blah'); }, "blah: expected 2 to be close to 1 +/- 0.5"); err(function() { [1.5].should.be.approximately(1.0, 0.5); }, "expected [ 1.5 ] to be a number"); err(function() { (1.5).should.be.approximately("1.0", 0.5); }, "the arguments to closeTo or approximately must be numbers"); err(function() { (1.5).should.be.approximately(1.0, true); }, "the arguments to closeTo or approximately must be numbers"); }); it('include.members', function() { [1, 2, 3].should.include.members([3]); [1, 2, 3].should.include.members([]); [1, 2, 3].should.include.members([2, 1]); [1, 2, 3].should.not.include.members([999]); [].should.not.include.members([23]); err(function() { [].should.include.members([43]); }, 'expected [] to be a superset of [ 43 ]'); err(function() { [5, 2, 1].should.not.include.members([2]); }, 'expected [ 5, 2, 1 ] to not be a superset of [ 2 ]'); err(function() { 'foo'.should.include.members([12]); }, "expected 'foo' to be an array"); err(function() { [1, 2, 3].should.include.members('o'); }, "expected 'o' to be an array"); }); it('memberEquals', function() { [1, 2, 3].should.have.same.members([3, 2, 1]); [5, 4].should.have.same.members([5, 4]); [].should.have.same.members([]); err(function() { [1, 2, 3].should.have.same.members([]); }, 'expected [ 1, 2, 3 ] to have the same members as []'); err(function() { [1, 2, 3].should.have.same.members(4); }, 'expected 4 to be an array'); }); it('change', function() { var obj = { value: 10, str: 'foo' }, fn = function() { obj.value += 5 }, sameFn = function() { obj.value += 0 }, decFn = function() { obj.value -= 3 }, bangFn = function() { obj.str += '!' }; fn.should.change(obj, 'value'); sameFn.should.not.change(obj, 'value'); sameFn.should.not.change(obj, 'str'); bangFn.should.change(obj, 'str'); }); it('increase, decrease', function() { var obj = { value: 10 }, incFn = function() { obj.value += 2 }, decFn = function() { obj.value -= 3 }, smFn = function() { obj.value += 0 }; smFn.should.not.increase(obj, 'value'); decFn.should.not.increase(obj, 'value'); incFn.should.increase(obj, 'value'); smFn.should.not.decrease(obj, 'value'); incFn.should.not.decrease(obj, 'value'); decFn.should.decrease(obj, 'value'); }); it('extensible', function() { var nonExtensibleObject = Object.preventExtensions({}); ({}).should.be.extensible; nonExtensibleObject.should.not.be.extensible; err(function() { nonExtensibleObject.should.be.extensible; }, 'expected {} to be extensible'); err(function() { ({}).should.not.be.extensible; }, 'expected {} to not be extensible'); // Making sure ES6-like Object.isExtensible response is respected for all primitive types (42).should.not.be.extensible; 'foo'.should.not.be.extensible; false.should.not.be.extensible; err(function() { (42).should.be.extensible; }, 'expected 42 to be extensible'); err(function() { 'foo'.should.be.extensible; }, 'expected \'foo\' to be extensible'); err(function() { false.should.be.extensible; }, 'expected false to be extensible'); }); it('sealed', function() { var sealedObject = Object.seal({}); sealedObject.should.be.sealed; ({}).should.not.be.sealed; err(function() { ({}).should.be.sealed; }, 'expected {} to be sealed'); err(function() { sealedObject.should.not.be.sealed; }, 'expected {} to not be sealed'); // Making sure ES6-like Object.isSealed response is respected for all primitive types (42).should.be.sealed; 'foo'.should.be.sealed; false.should.be.sealed; err(function() { (42).should.not.be.sealed; }, 'expected 42 to not be sealed'); err(function() { 'foo'.should.not.be.sealed; }, 'expected \'foo\' to not be sealed'); err(function() { false.should.not.be.sealed; }, 'expected false to not be sealed'); }); it('frozen', function() { var frozenObject = Object.freeze({}); frozenObject.should.be.frozen; ({}).should.not.be.frozen; err(function() { ({}).should.be.frozen; }, 'expected {} to be frozen'); err(function() { frozenObject.should.not.be.frozen; }, 'expected {} to not be frozen'); // Making sure ES6-like Object.isFrozen response is respected for all primitive types (42).should.be.frozen; 'foo'.should.be.frozen; false.should.be.frozen; err(function() { (42).should.not.be.frozen; }, 'expected 42 to not be frozen'); err(function() { 'foo'.should.not.be.frozen; }, 'expected \'foo\' to not be frozen'); err(function() { false.should.not.be.frozen; }, 'expected false to not be frozen'); }); }); chai-3.5.0/test/utilities.js000664 000000 000000 00000036070 12652401517 015744 0ustar00rootroot000000 000000 describe('utilities', function () { var expect = chai.expect; after(function() { // Some clean-up so we can run tests in a --watch delete chai.Assertion.prototype.eqqqual; delete chai.Assertion.prototype.result; delete chai.Assertion.prototype.doesnotexist; }); it('_obj', function () { var foo = 'bar' , test = expect(foo); expect(test).to.have.property('_obj', foo); var bar = 'baz'; test._obj = bar; expect(test).to.have.property('_obj', bar); test.equal(bar); }); it('transferFlags', function () { var foo = 'bar' , test = expect(foo).not; chai.use(function (_chai, utils) { var obj = {}; utils.transferFlags(test, obj); expect(utils.flag(obj, 'object')).to.equal(foo); expect(utils.flag(obj, 'negate')).to.equal(true); }); }); it('transferFlags, includeAll = false', function () { var foo = 'bar'; chai.use(function (_chai, utils) { var obj = {}; var test = function() {}; var assertion = new chai.Assertion({}, "message", test); var flag = {}; utils.flag(obj, 'flagMe', flag); utils.flag(obj, 'negate', true); utils.transferFlags(test, obj, false); expect(utils.flag(obj, 'object')).to.equal(undefined); expect(utils.flag(obj, 'message')).to.equal(undefined); expect(utils.flag(obj, 'ssfi')).to.equal(undefined); expect(utils.flag(obj, 'negate')).to.equal(true); expect(utils.flag(obj, 'flagMe')).to.equal(flag); }); }); it('getPathValue', function () { var object = { hello: 'universe' , universe: { hello: 'world' } , world: [ 'hello', 'universe' ] , complex: [ { hello: 'universe' } , { universe: 'world' } , [ { hello: 'world' } ] ] } var arr = [ [ true ] ]; chai.use(function (_chai, utils) { var gpv = utils.getPathValue; expect(gpv('hello', object)).to.equal('universe'); expect(gpv('universe.hello', object)).to.equal('world'); expect(gpv('world[1]', object)).to.equal('universe'); expect(gpv('complex[1].universe', object)).to.equal('world'); expect(gpv('complex[2][0].hello', object)).to.equal('world'); expect(gpv('[0][0]', arr)).to.be.true; }); }); describe('getPathInfo', function() { var gpi, obj = { id: '10702S300W', primes: [2, 3, 5, 7, 11], dimensions: { units: 'mm', lengths: [[1.2, 3.5], [2.2, 1.5], [5, 7]] }, 'dimensions.lengths': { '[2]': [1.2, 3.5] } }; beforeEach(function() { chai.use(function (_chai, utils) { gpi = utils.getPathInfo; }); }); it('should handle simple property', function() { var info = gpi('dimensions.units', obj); info.parent.should.equal(obj.dimensions); info.value.should.equal(obj.dimensions.units); info.name.should.equal('units'); info.exists.should.be.true; }); it('should handle non-existent property', function() { var info = gpi('dimensions.size', obj); info.parent.should.equal(obj.dimensions); expect(info.value).to.be.undefined; info.name.should.equal('size'); info.exists.should.be.false; }); it('should handle array index', function() { var info = gpi('primes[2]', obj); info.parent.should.equal(obj.primes); info.value.should.equal(obj.primes[2]); info.name.should.equal(2); info.exists.should.be.true; }); it('should handle dimensional array', function() { var info = gpi('dimensions.lengths[2][1]', obj); info.parent.should.equal(obj.dimensions.lengths[2]); info.value.should.equal(obj.dimensions.lengths[2][1]); info.name.should.equal(1); info.exists.should.be.true; }); it('should handle out of bounds array index', function() { var info = gpi('dimensions.lengths[3]', obj); info.parent.should.equal(obj.dimensions.lengths); expect(info.value).to.be.undefined; info.name.should.equal(3); info.exists.should.be.false; }); it('should handle out of bounds dimensional array index', function() { var info = gpi('dimensions.lengths[2][5]', obj); info.parent.should.equal(obj.dimensions.lengths[2]); expect(info.value).to.be.undefined; info.name.should.equal(5); info.exists.should.be.false; }); it('should handle backslash-escaping for .[]', function() { var info = gpi('dimensions\\.lengths.\\[2\\][1]', obj); info.parent.should.equal(obj['dimensions.lengths']['[2]']); info.value.should.equal(obj['dimensions.lengths']['[2]'][1]); info.name.should.equal(1); info.exists.should.be.true; }); }); describe('hasProperty', function() { var hp; beforeEach(function() { chai.use(function (_chai, utils) { hp = utils.hasProperty; }); }); it('should handle array index', function() { var arr = [1, 2, 'cheeseburger']; hp(1, arr).should.be.true; hp(3, arr).should.be.false; }); it('should handle literal types', function() { var s = 'string literal'; hp('length', s).should.be.true; hp(3, s).should.be.true; hp(14, s).should.be.false; hp('foo', 1).should.be.false; }); it('should handle undefined', function() { var o = { foo: 'bar' }; hp('foo', o).should.be.true; hp('baz', o).should.be.false; hp(0, o).should.be.false; }); it('should handle undefined', function() { hp('foo', undefined).should.be.false; }); it('should handle null', function() { hp('foo', null).should.be.false; }); }); it('addMethod', function () { chai.use(function(_chai, utils) { expect(_chai.Assertion).to.not.respondTo('eqqqual'); _chai.Assertion.addMethod('eqqqual', function (str) { var object = utils.flag(this, 'object'); new _chai.Assertion(object).to.be.eql(str); }); expect(_chai.Assertion).to.respondTo('eqqqual'); }); expect('spec').to.eqqqual('spec'); }); it('addMethod returning result', function () { chai.use(function(_chai, utils) { _chai.Assertion.addMethod('result', function () { return 'result'; }) }); expect(expect('foo').result()).to.equal('result'); }); it('overwriteMethod', function () { chai.use(function (_chai, _) { expect(_chai.Assertion).to.respondTo('eqqqual'); _chai.Assertion.overwriteMethod('eqqqual', function (_super) { return function (str) { var object = _.flag(this, 'object'); if (object == 'cucumber' && str == 'cuke') { _.flag(this, 'cucumber', true); } else { _super.apply(this, arguments); } }; }); }); var vege = expect('cucumber').to.eqqqual('cucumber'); expect(vege.__flags).to.not.have.property('cucumber'); var cuke = expect('cucumber').to.eqqqual('cuke'); expect(cuke.__flags).to.have.property('cucumber'); chai.use(function (_chai, _) { expect(_chai.Assertion).to.not.respondTo('doesnotexist'); _chai.Assertion.overwriteMethod('doesnotexist', function (_super) { expect(_super).to.be.a('function'); return function () { _.flag(this, 'doesnt', true); _super.apply(this, arguments); } }); }); var dne = expect('something').to.doesnotexist(); expect(dne.__flags).to.have.property('doesnt'); }); it('overwriteMethod returning result', function () { chai.use(function (_chai, _) { _chai.Assertion.overwriteMethod('result', function (_super) { return function () { return 'result'; } }); }); expect(expect('foo').result()).to.equal('result'); }); it('addProperty', function () { chai.use(function (_chai, _) { _chai.Assertion.addProperty('tea', function () { _.flag(this, 'tea', 'chai'); }); }); var assert = expect('chai').to.be.tea; expect(assert.__flags.tea).to.equal('chai'); }); it('addProperty returning result', function () { chai.use(function(_chai, _) { _chai.Assertion.addProperty('result', function () { return 'result'; }) }); expect(expect('foo').result).to.equal('result'); }); it('overwriteProperty', function () { chai.use(function (_chai, _) { expect(new chai.Assertion()).to.have.property('tea'); _chai.Assertion.overwriteProperty('tea', function (_super) { return function () { var act = _.flag(this, 'object'); if (act === 'matcha') { _.flag(this, 'tea', 'matcha'); } else { _super.call(this); } } }); }); var matcha = expect('matcha').to.be.tea; expect(matcha.__flags.tea).to.equal('matcha'); var assert = expect('something').to.be.tea; expect(assert.__flags.tea).to.equal('chai'); }); it('overwriteProperty returning result', function () { chai.use(function(_chai, _) { _chai.Assertion.overwriteProperty('result', function (_super) { return function () { return 'result'; } }); }); expect(expect('foo').result).to.equal('result'); }); it('getMessage', function () { chai.use(function (_chai, _) { expect(_.getMessage({}, [])).to.equal(''); expect(_.getMessage({}, [null, null, null])).to.equal(''); var obj = {}; _.flag(obj, 'message', 'foo'); expect(_.getMessage(obj, [])).to.contain('foo'); }); }); it('getMessage passed message as function', function () { chai.use(function (_chai, _) { var obj = {}; var msg = function() { return "expected a to eql b"; } var negateMsg = function() { return "expected a not to eql b"; } expect(_.getMessage(obj, [null, msg, negateMsg])).to.equal("expected a to eql b"); _.flag(obj, 'negate', true); expect(_.getMessage(obj, [null, msg, negateMsg])).to.equal("expected a not to eql b"); }); }); it('getMessage template tag substitution', function () { chai.use(function (_chai, _) { var objName = 'trojan horse'; var actualValue = 'an actual value'; var expectedValue = 'an expected value'; [ // known template tags { template: 'one #{this} two', expected: 'one \'' + objName + '\' two' }, { template: 'one #{act} two', expected: 'one \'' + actualValue + '\' two' }, { template: 'one #{exp} two', expected: 'one \'' + expectedValue + '\' two' }, // unknown template tag { template: 'one #{unknown} two', expected: 'one #{unknown} two' }, // repeated template tag { template: '#{this}#{this}', expected: '\'' + objName + '\'\'' + objName + '\'' }, // multiple template tags in different order { template: '#{this}#{act}#{exp}#{act}#{this}', expected: '\'' + objName + '\'\'' + actualValue + '\'\'' + expectedValue + '\'\'' + actualValue + '\'\'' + objName + '\'' }, // immune to string.prototype.replace() `$` substitution { objName: '-$$-', template: '#{this}', expected: '\'-$$-\'' }, { actualValue: '-$$-', template: '#{act}', expected: '\'-$$-\'' }, { expectedValue: '-$$-', template: '#{exp}', expected: '\'-$$-\'' } ].forEach(function (config) { config.objName = config.objName || objName; config.actualValue = config.actualValue || actualValue; config.expectedValue = config.expectedValue || expectedValue; var obj = {_obj: config.actualValue}; _.flag(obj, 'object', config.objName); expect(_.getMessage(obj, [null, config.template, null, config.expectedValue])).to.equal(config.expected); }); }); }); it('inspect with custom object-returning inspect()s', function () { chai.use(function (_chai, _) { var obj = { outer: { inspect: function () { return { foo: 'bar' }; } } }; expect(_.inspect(obj)).to.equal('{ outer: { foo: \'bar\' } }'); }); }); it('inspect negative zero', function () { chai.use(function (_chai, _) { expect(_.inspect(-0)).to.equal('-0'); expect(_.inspect([-0])).to.equal('[ -0 ]'); expect(_.inspect({ hp: -0 })).to.equal('{ hp: -0 }'); }); }); it('addChainableMethod', function () { chai.use(function (_chai, _) { _chai.Assertion.addChainableMethod('x', function () { new chai.Assertion(this._obj).to.be.equal('x'); } , function () { this._obj = this._obj || {}; this._obj.__x = 'X!' } ); expect("foo").x.to.equal("foo"); expect("x").x(); expect(function () { expect("foo").x(); }).to.throw(_chai.AssertionError); // Verify whether the original Function properties are present. // see https://github.com/chaijs/chai/commit/514dd6ce4#commitcomment-2593383 var propertyDescriptor = Object.getOwnPropertyDescriptor(chai.Assertion.prototype, "x"); expect(propertyDescriptor.get).to.have.property("call", Function.prototype.call); expect(propertyDescriptor.get).to.have.property("apply", Function.prototype.apply); expect(propertyDescriptor.get()).to.have.property("call", Function.prototype.call); expect(propertyDescriptor.get()).to.have.property("apply", Function.prototype.apply); var obj = {}; expect(obj).x.to.be.ok; expect(obj).to.have.property('__x', 'X!'); }) }); it('overwriteChainableMethod', function () { chai.use(function (_chai, _) { _chai.Assertion.overwriteChainableMethod('x', function(_super) { return function() { if (_.flag(this, 'marked')) { new chai.Assertion(this._obj).to.be.equal('spot'); } else { _super.apply(this, arguments); } }; } , function(_super) { return function() { _.flag(this, 'message', 'x marks the spot'); _super.apply(this, arguments); }; } ); // Make sure the original behavior of 'x' remains the same expect('foo').x.to.equal("foo"); expect("x").x(); expect(function () { expect("foo").x(); }).to.throw(_chai.AssertionError); var obj = {}; expect(obj).x.to.be.ok; expect(obj).to.have.property('__x', 'X!'); // Test the new behavior of 'x' var assertion = expect('foo').x.to.be.ok; expect(_.flag(assertion, 'message')).to.equal('x marks the spot'); expect(function () { var assertion = expect('x'); _.flag(assertion, 'marked', true); assertion.x() }).to.throw(_chai.AssertionError); }); }); });