diff --git a/.gitignore b/.gitignore
index d922a61222..3a84892c54 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,4 @@ mocha.js
*_BASE_*
*_LOCAL_*
*_REMOTE_*
+docs/_site
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000000..743d18eca7
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,3 @@
+source "https://rubygems.org"
+# Added at 2017-12-05 23:01:55 -0800 by boneskull:
+gem "jekyll", "~> 3.6"
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000000..33a59259ef
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,50 @@
+GEM
+ specs:
+ addressable (2.5.2)
+ public_suffix (>= 2.0.2, < 4.0)
+ colorator (1.1.0)
+ ffi (1.9.18)
+ forwardable-extended (2.6.0)
+ jekyll (3.6.2)
+ addressable (~> 2.4)
+ colorator (~> 1.0)
+ jekyll-sass-converter (~> 1.0)
+ jekyll-watch (~> 1.1)
+ kramdown (~> 1.14)
+ liquid (~> 4.0)
+ mercenary (~> 0.3.3)
+ pathutil (~> 0.9)
+ rouge (>= 1.7, < 3)
+ safe_yaml (~> 1.0)
+ jekyll-sass-converter (1.5.0)
+ sass (~> 3.4)
+ jekyll-watch (1.5.1)
+ listen (~> 3.0)
+ kramdown (1.14.0)
+ liquid (4.0.0)
+ listen (3.0.8)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
+ mercenary (0.3.6)
+ pathutil (0.16.0)
+ forwardable-extended (~> 2.6)
+ public_suffix (3.0.0)
+ rb-fsevent (0.10.2)
+ rb-inotify (0.9.10)
+ ffi (>= 0.5.0, < 2)
+ rouge (2.2.1)
+ safe_yaml (1.0.4)
+ sass (3.5.3)
+ sass-listen (~> 4.0.0)
+ sass-listen (4.0.0)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ jekyll (~> 3.6)
+
+BUNDLED WITH
+ 1.16.0
diff --git a/docs/.eslintrc.yaml b/docs/.eslintrc.yaml
new file mode 100644
index 0000000000..6887df39ef
--- /dev/null
+++ b/docs/.eslintrc.yaml
@@ -0,0 +1,3 @@
+env:
+ browser: true
+ node: false
diff --git a/docs/CNAME b/docs/CNAME
new file mode 100644
index 0000000000..f596d46df1
--- /dev/null
+++ b/docs/CNAME
@@ -0,0 +1 @@
+mochajs.org
diff --git a/docs/LICENSE-CC-BY-4.0 b/docs/LICENSE-CC-BY-4.0
new file mode 100644
index 0000000000..2f244ac814
--- /dev/null
+++ b/docs/LICENSE-CC-BY-4.0
@@ -0,0 +1,395 @@
+Attribution 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More_considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution 4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution 4.0 International Public License ("Public License"). To the
+extent this Public License may be interpreted as a contract, You are
+granted the Licensed Rights in consideration of Your acceptance of
+these terms and conditions, and the Licensor grants You such rights in
+consideration of benefits the Licensor receives from making the
+Licensed Material available under these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+
+ c. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+
+ d. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+
+ e. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+
+ f. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+
+ g. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+
+ h. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+
+ i. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+
+ j. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+
+ k. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+ a. License grant.
+
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+
+ a. reproduce and Share the Licensed Material, in whole or
+ in part; and
+
+ b. produce, reproduce, and Share Adapted Material.
+
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+
+ 5. Downstream recipients.
+
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+
+ b. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+ a. Attribution.
+
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of
+ warranties;
+
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+
+ 4. If You Share Adapted Material You produce, the Adapter's
+ License You apply must not prevent recipients of the Adapted
+ Material from complying with this Public License.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database;
+
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material; and
+
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+
+
+=======================================================================
+
+Creative Commons is not a party to its public
+licenses. Notwithstanding, Creative Commons may elect to apply one of
+its public licenses to material it publishes and in those instances
+will be considered the “Licensor.” The text of the Creative Commons
+public licenses is dedicated to the public domain under the CC0 Public
+Domain Dedication. Except for the limited purpose of indicating that
+material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the
+public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000000..44619e7aca
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,33 @@
+# mochajs.org
+
+*So you wanna build the site?*
+
+[mochajs.org](https://mochajs.org) is built using [Jekyll](http://jekyllrb.com), the popular static site generator.
+
+## Prerequisites
+
+- Ruby
+- RubyGems
+- Bundler (`gem install bundler`)
+- Node.js v4.0.0 or greater
+
+## Development
+
+1. Run `npm install` to get Node.js deps.
+2. Run `bundle install` to install Jekyll and its dependencies. This may or may not require elevated privileges, depending on your system.
+3. To serve the site and rebuild as changes are made, execute `npm run serveDocs`.
+4. To rebuild the site *once*, execute `npm start buildDocs`.
+
+### Notes
+
+- The content lives in `docs/index.md`; everything else is markup, scripts, assets, etc.
+- `docs/index.md` may be mutated upon build. If you update the table of contents, **you must commit `index.md`**; GitHub won't do it for you.
+- `docs/_site/` is where the generated static site lives (and is what you see at [mochajs.org](https://mochajs.org)). It is *not* under version control.
+
+## License
+
+:copyright: 2016-2017 [JS Foundation](https://js.foundation) and contributors.
+
+Content licensed [CC-BY-4.0](https://raw.githubusercontent.com/mochajs/mocha/master/docs/LICENSE-CC-BY-4.0).
+
+Code licensed [MIT](https://raw.githubusercontent.com/mochajs/mocha/master/LICENSE-MIT).
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644
index 0000000000..ac625af7d3
--- /dev/null
+++ b/docs/_config.yml
@@ -0,0 +1,8 @@
+url: https://mochajs.org
+exclude:
+ - README.md
+ - .*
+ - LICENSE*
+repository: mochajs/mocha
+source: docs
+
diff --git a/docs/_includes/backers.md b/docs/_includes/backers.md
new file mode 100644
index 0000000000..ccf561abfa
--- /dev/null
+++ b/docs/_includes/backers.md
@@ -0,0 +1,6 @@
+## Backers
+
+Find Mocha helpful? Become a [backer](https://opencollective.com/mochajs#support) and support Mocha with a monthly donation.
+
+{: id="_backers" }
+{% for i in (0..29) %}[![](//opencollective.com/mochajs/backer/{{ i }}/avatar){: onload="window.avatars.backerLoaded()" }](https://opencollective.com/mochajs/backer/{{ i }}/website){: target="_blank"} {% endfor %}
diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html
new file mode 100644
index 0000000000..0a1f43e861
--- /dev/null
+++ b/docs/_includes/footer.html
@@ -0,0 +1,14 @@
+
diff --git a/docs/_includes/head.html b/docs/_includes/head.html
new file mode 100644
index 0000000000..509d0b7ebf
--- /dev/null
+++ b/docs/_includes/head.html
@@ -0,0 +1,14 @@
+
+
diff --git a/docs/_includes/sponsors.md b/docs/_includes/sponsors.md
new file mode 100644
index 0000000000..5fe0c7d9c1
--- /dev/null
+++ b/docs/_includes/sponsors.md
@@ -0,0 +1,6 @@
+## Sponsors
+
+Use Mocha at Work? Ask your manager or marketing team if they'd help [support](https://opencollective.com/mochajs#support) our project. Your company's logo will also be displayed on [npmjs.com](http://npmjs.com/package/mocha) and our [GitHub repository](https://github.com/mochajs/mocha#sponsors).
+
+{: id="_sponsors" }
+{% for i in (0..29) %}[![](//opencollective.com/mochajs/sponsor/{{ i }}/avatar){: onload="window.avatars.sponsorLoaded()" }](https://opencollective.com/mochajs/sponsor/{{ i }}/website){: target="_blank"} {% endfor %}
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html
new file mode 100644
index 0000000000..db3bdf76e4
--- /dev/null
+++ b/docs/_layouts/default.html
@@ -0,0 +1,17 @@
+
+
+
+ {% include head.html %}
+
+
+
+ {% include header.html %}
+
+
+ {{ content }}
+
+
+ {% include footer.html %}
+
+
+
diff --git a/docs/css/pygments.css b/docs/css/pygments.css
new file mode 100644
index 0000000000..851ba3c1ae
--- /dev/null
+++ b/docs/css/pygments.css
@@ -0,0 +1,59 @@
+.highlight .hll { background-color: #ffffcc }
+.highlight .c { color: #999988; font-style: italic } /* Comment */
+.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
+.highlight .k { font-weight: bold } /* Keyword */
+.highlight .o { font-weight: bold } /* Operator */
+.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
+.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
+.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #aa0000 } /* Generic.Error */
+.highlight .gh { color: #999999 } /* Generic.Heading */
+.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
+.highlight .go { color: #888888 } /* Generic.Output */
+.highlight .gp { color: #555555 } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
+.highlight .gt { color: #aa0000 } /* Generic.Traceback */
+.highlight .kc { font-weight: bold } /* Keyword.Constant */
+.highlight .kd { font-weight: bold } /* Keyword.Declaration */
+.highlight .kn { font-weight: bold } /* Keyword.Namespace */
+.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
+.highlight .kr { font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
+.highlight .m { color: #009999 } /* Literal.Number */
+.highlight .s { color: #bb8844 } /* Literal.String */
+.highlight .na { color: #008080 } /* Name.Attribute */
+.highlight .nb { color: #999999 } /* Name.Builtin */
+.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
+.highlight .no { color: #008080 } /* Name.Constant */
+.highlight .ni { color: #800080 } /* Name.Entity */
+.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
+.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
+.highlight .nn { color: #555555 } /* Name.Namespace */
+.highlight .nt { color: #000080 } /* Name.Tag */
+.highlight .nv { color: #008080 } /* Name.Variable */
+.highlight .ow { font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mf { color: #009999 } /* Literal.Number.Float */
+.highlight .mh { color: #009999 } /* Literal.Number.Hex */
+.highlight .mi { color: #009999 } /* Literal.Number.Integer */
+.highlight .mo { color: #009999 } /* Literal.Number.Oct */
+.highlight .sb { color: #bb8844 } /* Literal.String.Backtick */
+.highlight .sc { color: #bb8844 } /* Literal.String.Char */
+.highlight .sd { color: #bb8844 } /* Literal.String.Doc */
+.highlight .s2 { color: #bb8844 } /* Literal.String.Double */
+.highlight .se { color: #bb8844 } /* Literal.String.Escape */
+.highlight .sh { color: #bb8844 } /* Literal.String.Heredoc */
+.highlight .si { color: #bb8844 } /* Literal.String.Interpol */
+.highlight .sx { color: #bb8844 } /* Literal.String.Other */
+.highlight .sr { color: #808000 } /* Literal.String.Regex */
+.highlight .s1 { color: #bb8844 } /* Literal.String.Single */
+.highlight .ss { color: #bb8844 } /* Literal.String.Symbol */
+.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
+.highlight .vc { color: #008080 } /* Name.Variable.Class */
+.highlight .vg { color: #008080 } /* Name.Variable.Global */
+.highlight .vi { color: #008080 } /* Name.Variable.Instance */
+.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
diff --git a/docs/css/style.css b/docs/css/style.css
new file mode 100644
index 0000000000..4df465e56a
--- /dev/null
+++ b/docs/css/style.css
@@ -0,0 +1,208 @@
+html {
+ font: 16px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+body {
+ color: #2c2c2c;
+ border-top: 2px solid #ddd;
+}
+
+#content {
+ padding: 0 110px 60px 110px;
+}
+
+header {
+ padding: 140px 110px 0 110px;
+}
+
+h1 {
+ margin-left: -19px;
+ opacity: 0;
+ -webkit-transition: opacity 1s;
+ -moz-transition: opacity 1s;
+ -o-transition: opacity 1s;
+ transition: opacity 1s;
+}
+
+#_backers a, #_sponsors a {
+ opacity: 0;
+ -webkit-transition: opacity .3s;
+ -moz-transition: opacity .3s;
+ -o-transition: opacity .3s;
+ transition: opacity .3s;
+}
+
+#_backers a img, #_sponsors a img {
+ max-height: 64px;
+}
+
+.onload h1, #_backers.onload a, #_sponsors.onload a {
+ opacity: 1;
+}
+
+h2 {
+ margin-top: 80px;
+ font-weight: 400;
+ letter-spacing: 1px;
+ border-bottom: 1px solid #ddd;
+ text-transform: uppercase;
+}
+
+h3 {
+ font-weight: 200;
+ letter-spacing: 1px;
+ border-bottom: 1px solid #eee;
+ margin-top: 40px;
+ text-transform: uppercase;
+}
+
+h3 > code {
+ text-transform: none;
+ font-size: 14px;
+}
+
+#tag {
+ opacity: 0;
+ color: #c29d7f;
+ font-weight: 100;
+ font-size: 30px;
+ margin-top: -155px;
+ margin-left: 140px;
+ margin-bottom: 125px;
+ letter-spacing: 2px;
+ -webkit-transition: opacity 1s, margin-top 200ms, margin-bottom 200ms, margin-left 1s;
+ -moz-transition: opacity 1s, margin-top 200ms, margin-bottom 200ms, margin-left 1s;
+ -o-transition: opacity 1s, margin-top 200ms, margin-bottom 200ms, margin-left 1s;
+ transition: opacity 1s, margin-top 200ms, margin-bottom 200ms, margin-left 1s;
+}
+
+#tag em {
+ font-style: normal
+}
+
+.onload #tag {
+ opacity: 1;
+ margin-left: 185px;
+}
+
+#content > p:first-child {
+ font-size: 20px;
+ font-weight: 200;
+ letter-spacing: 1px;
+}
+
+a {
+ color: #8D6748;
+}
+
+a:hover {
+ color: #717171;
+}
+
+ul {
+ margin-top: 20px;
+ padding: 0 15px;
+ width: 100%;
+ -webkit-column-count: 2;
+ -moz-column-count: 2;
+ column-count: 2;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+
+ul li {
+ margin-top: 5px;
+ margin-right: 60px;
+ list-style: none;
+ border-bottom: 1px solid #eee;
+ padding: 5px 0;
+ -webkit-column-break-inside: avoid;
+ -moz-column-break-inside: avoid;
+ column-break-inside: avoid;
+}
+
+ul::after {
+ content: '.';
+ height: 0;
+ display: block;
+ visibility: hidden;
+ clear: both;
+}
+
+code {
+ font: 14px monaco, monospace;
+ line-height: 1.8;
+}
+
+pre {
+ margin: 20px;
+ padding: 20px;
+ border: 1px solid #ddd;
+ border-bottom-color: #ccc;
+ background-color: #f3f3f3;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ -o-border-radius: 3px;
+ border-radius: 3px;
+ -webkit-box-shadow: inset 0 0 10px #ddd;
+ -moz-box-shadow: inset 0 0 10px #ddd;
+ box-shadow: inset 0 0 10px #ddd;
+ overflow-x: auto;
+}
+
+img {
+ margin: 30px;
+ padding: 1px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ -o-border-radius: 3px;
+ border-radius: 3px;
+ -webkit-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
+ -moz-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
+ box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
+ max-width: 100%;
+}
+
+img[src*="opencollective.com/mochajs"], img[src*=badges], img[src*=".svg"] {
+ margin: 0;
+ box-shadow: none;
+}
+
+footer {
+ background-color: #eee;
+ width: 100%;
+ padding: 50px 0;
+ text-align: right;
+ border-top: 1px solid #ddd;
+}
+
+footer span {
+ display: block;
+ margin-right: 30px;
+ color: #888;
+ font-size: 0.8em;
+}
+
+@media all and (max-width: 850px) {
+ ul li {
+ width: 100%;
+ }
+}
+
+@media all and (max-width: 600px) {
+ #tag {
+ margin-top: 0;
+ margin-left: 0;
+ margin-bottom: 0;
+ }
+
+ .onload #tag {
+ margin-left: 0;
+ }
+}
+
+blockquote {
+ padding: 10px;
+ border-left: 1px solid #eee;
+}
diff --git a/docs/example/Array.js b/docs/example/Array.js
new file mode 100644
index 0000000000..18105cf75f
--- /dev/null
+++ b/docs/example/Array.js
@@ -0,0 +1,73 @@
+
+describe('Array', function(){
+ describe('.push()', function(){
+ it('should append a value', function(){
+ var arr = [];
+ arr.push('foo');
+ arr.push('bar');
+ expect(arr[0]).to.equal('foo');
+ expect(arr[1]).to.equal('bar');
+ })
+
+ it('should return the length', function(){
+ var arr = [];
+ var n = arr.push('foo');
+ expect(n).to.equal(1);
+ var n = arr.push('bar');
+ expect(n).to.equal(2);
+ })
+
+ describe('with many arguments', function(){
+ it('should add the values', function(){
+ var arr = [];
+ arr.push('foo', 'bar');
+ expect(arr[0]).to.equal('foo');
+ expect(arr[1]).to.equal('bar');
+ })
+ })
+ })
+
+ describe('.unshift()', function(){
+ it('should prepend a value', function(){
+ var arr = [1,2,3];
+ arr.unshift('foo');
+ expect(arr[0]).to.equal('foo');
+ expect(arr[1]).to.equal(1);
+ })
+
+ it('should return the length', function(){
+ var arr = [];
+ var n = arr.unshift('foo');
+ expect(n).to.equal(1);
+ var n = arr.unshift('bar');
+ expect(n).to.equal(2);
+ })
+
+ describe('with many arguments', function(){
+ it('should add the values', function(){
+ var arr = [];
+ arr.unshift('foo', 'bar');
+ expect(arr[0]).to.equal('foo');
+ expect(arr[1]).to.equal('bar');
+ })
+ })
+ })
+
+ describe('.pop()', function(){
+ it('should remove and return the last value', function(){
+ var arr = [1,2,3];
+ expect(arr.pop()).to.equal(3);
+ expect(arr.pop()).to.equal(2);
+ expect(arr).to.have.length(1);
+ })
+ })
+
+ describe('.shift()', function(){
+ it('should remove and return the first value', function(){
+ var arr = [1,2,3];
+ expect(arr.shift()).to.equal(1);
+ expect(arr.shift()).to.equal(2);
+ expect(arr).to.have.length(1);
+ })
+ })
+})
\ No newline at end of file
diff --git a/docs/example/async-dump.js b/docs/example/async-dump.js
new file mode 100644
index 0000000000..c1c15058bc
--- /dev/null
+++ b/docs/example/async-dump.js
@@ -0,0 +1,33 @@
+'use strict';
+
+const {createHook} = require('async_hooks');
+const {stackTraceFilter} = require('mocha/lib/utils');
+const allResources = new Map();
+const resourceActivity = new Set();
+
+const filterStack = stackTraceFilter();
+
+const hook = createHook({
+ init(asyncId, type, triggerAsyncId) {
+ allResources.set(asyncId, {type, triggerAsyncId, stack: (new Error()).stack});
+ },
+ before(asyncId) {
+ resourceActivity.add(asyncId);
+ },
+ after(asyncId) {
+ resourceActivity.delete(asyncId);
+ },
+ destroy(asyncId) {
+ allResources.delete(asyncId);
+ }
+}).enable();
+
+global.asyncDump = module.exports = () => {
+ hook.disable();
+ console.error('STUFF STILL IN THE EVENT LOOP:')
+ allResources.forEach(value=> {
+ console.error(`Type: ${value.type}`);
+ console.error(filterStack(value.stack));
+ console.error('\n');
+ });
+};
diff --git a/docs/example/chai.js b/docs/example/chai.js
new file mode 100644
index 0000000000..43fbf644d3
--- /dev/null
+++ b/docs/example/chai.js
@@ -0,0 +1,3403 @@
+!function (name, definition) {
+ if (typeof define == 'function' && typeof define.amd == 'object') define(definition);
+ else this[name] = definition();
+}('chai', function () {
+
+// CommonJS require()
+
+function require(p){
+ var path = require.resolve(p)
+ , mod = require.modules[path];
+ if (!mod) throw new Error('failed to require "' + p + '"');
+ if (!mod.exports) {
+ mod.exports = {};
+ mod.call(mod.exports, mod, mod.exports, require.relative(path));
+ }
+ return mod.exports;
+ }
+
+require.modules = {};
+
+require.resolve = function (path){
+ var orig = path
+ , reg = path + '.js'
+ , index = path + '/index.js';
+ return require.modules[reg] && reg
+ || require.modules[index] && index
+ || orig;
+ };
+
+require.register = function (path, fn){
+ require.modules[path] = fn;
+ };
+
+require.relative = function (parent) {
+ return function(p){
+ if ('.' != p[0]) return require(p);
+
+ var path = parent.split('/')
+ , segs = p.split('/');
+ path.pop();
+
+ for (var i = 0; i < segs.length; i++) {
+ var seg = segs[i];
+ if ('..' == seg) path.pop();
+ else if ('.' != seg) path.push(seg);
+ }
+
+ return require(path.join('/'));
+ };
+ };
+
+
+require.register("assertion.js", function(module, exports, require){
+/*!
+ * chai
+ * http://chaijs.com
+ * Copyright(c) 2011-2012 Jake Luer
+ * MIT Licensed
+ */
+
+
+/*!
+ * Module dependencies.
+ */
+
+var AssertionError = require('./browser/error')
+ , toString = Object.prototype.toString
+ , util = require('./utils')
+ , flag = util.flag;
+
+/*!
+ * Module export.
+ */
+
+module.exports = 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);
+}
+
+/*!
+ * ### Assertion.includeStack
+ *
+ * User configurable property, influences whether stack trace
+ * is included in Assertion error message. Default of false
+ * suppresses stack trace in the error message
+ *
+ * Assertion.includeStack = true; // enable stack on error
+ *
+ * @api public
+ */
+
+Assertion.includeStack = false;
+
+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);
+};
+
+/*!
+ * ### .assert(expression, message, negateMessage, expected, actual)
+ *
+ * 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} message to display if fails
+ * @param {String} 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`
+ * @api private
+ */
+
+Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual) {
+ var msg = util.getMessage(this, arguments)
+ , actual = util.getActual(this, arguments)
+ , ok = util.test(this, arguments);
+
+ if (!ok) {
+ throw new AssertionError({
+ message: msg
+ , actual: actual
+ , expected: expected
+ , stackStartFunction: (Assertion.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);
+ }
+});
+
+/**
+ * ### Language Chains
+ *
+ * The following are provide as chainable getters to
+ * improve the readability of your assertions. They
+ * do not provide an testing capability unless they
+ * have been overwritten by a plugin.
+ *
+ * **Chains**
+ *
+ * - to
+ * - be
+ * - been
+ * - is
+ * - and
+ * - have
+ * - with
+ *
+ * @name language chains
+ * @api public
+ */
+
+[ 'to', 'be', 'been'
+, 'is', 'and', 'have'
+, 'with' ].forEach(function (chain) {
+ Object.defineProperty(Assertion.prototype, chain,
+ { get: function () {
+ return this;
+ }
+ , configurable: true
+ });
+});
+
+/**
+ * ### .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
+ * @api public
+ */
+
+Object.defineProperty(Assertion.prototype, 'not',
+ { get: function () {
+ flag(this, 'negate', true);
+ return this;
+ }
+ , configurable: 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');
+ *
+ * @name deep
+ * @api public
+ */
+
+Object.defineProperty(Assertion.prototype, 'deep',
+ { get: function () {
+ flag(this, 'deep', true);
+ return this;
+ }
+ , configurable: true
+});
+
+/**
+ * ### .a(type)
+ *
+ * The `a` and `an` assertions are aliases that can be
+ * used either as language chains or to assert a value's
+ * type (as revealed by `Object.prototype.toString`).
+ *
+ * // 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');
+ *
+ * // language chain
+ * expect(foo).to.be.an.instanceof(Foo);
+ *
+ * @name a
+ * @alias an
+ * @param {String} type
+ * @api public
+ */
+
+function an(type) {
+ var obj = flag(this, 'object')
+ , klassStart = type.charAt(0).toUpperCase()
+ , klass = klassStart + type.slice(1)
+ , article = ~[ 'A', 'E', 'I', 'O', 'U' ].indexOf(klassStart) ? 'an ' : 'a ';
+
+ this.assert(
+ '[object ' + klass + ']' === toString.call(obj)
+ , 'expected #{this} to be ' + article + type
+ , 'expected #{this} not to be ' + article + type
+ , '[object ' + klass + ']'
+ , toString.call(obj)
+ );
+}
+
+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 `contain` 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
+ * @param {Object|String|Number} obj
+ * @api public
+ */
+
+function includeChainingBehavior () {
+ flag(this, 'contains', true);
+}
+
+function include (val) {
+ var obj = flag(this, 'object')
+ this.assert(
+ ~obj.indexOf(val)
+ , 'expected #{this} to include ' + util.inspect(val)
+ , 'expected #{this} to not include ' + util.inspect(val));
+}
+
+Assertion.addChainableMethod('include', include, includeChainingBehavior);
+Assertion.addChainableMethod('contain', include, includeChainingBehavior);
+
+/**
+ * ### .ok
+ *
+ * Asserts that the target is truthy.
+ *
+ * expect('everthing').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
+ * @api public
+ */
+
+Object.defineProperty(Assertion.prototype, 'ok',
+ { get: function () {
+ this.assert(
+ flag(this, 'object')
+ , 'expected #{this} to be truthy'
+ , 'expected #{this} to be falsy');
+
+ return this;
+ }
+ , configurable: true
+});
+
+/**
+ * ### .true
+ *
+ * Asserts that the target is `true`.
+ *
+ * expect(true).to.be.true;
+ * expect(1).to.not.be.true;
+ *
+ * @name true
+ * @api public
+ */
+
+Object.defineProperty(Assertion.prototype, 'true',
+ { get: function () {
+ this.assert(
+ true === flag(this, 'object')
+ , 'expected #{this} to be true'
+ , 'expected #{this} to be false'
+ , this.negate ? false : true
+ );
+
+ return this;
+ }
+ , configurable: true
+});
+
+/**
+ * ### .false
+ *
+ * Asserts that the target is `false`.
+ *
+ * expect(false).to.be.false;
+ * expect(0).to.not.be.false;
+ *
+ * @name false
+ * @api public
+ */
+
+Object.defineProperty(Assertion.prototype, 'false',
+ { get: function () {
+ this.assert(
+ false === flag(this, 'object')
+ , 'expected #{this} to be false'
+ , 'expected #{this} to be true'
+ , this.negate ? true : false
+ );
+
+ return this;
+ }
+ , configurable: true
+});
+
+/**
+ * ### .null
+ *
+ * Asserts that the target is `null`.
+ *
+ * expect(null).to.be.null;
+ * expect(undefined).not.to.be.null;
+ *
+ * @name null
+ * @api public
+ */
+
+Object.defineProperty(Assertion.prototype, 'null',
+ { get: function () {
+ this.assert(
+ null === flag(this, 'object')
+ , 'expected #{this} to be null'
+ , 'expected #{this} not to be null'
+ , this.negate ? false : true
+ );
+
+ return this;
+ }
+ , configurable: true
+});
+
+/**
+ * ### .undefined
+ *
+ * Asserts that the target is `undefined`.
+ *
+ * expect(undefined).to.be.undefined;
+ * expect(null).to.not.be.undefined;
+ *
+ * @name undefined
+ * @api public
+ */
+
+Object.defineProperty(Assertion.prototype, 'undefined',
+ { get: function () {
+ this.assert(
+ undefined === flag(this, 'object')
+ , 'expected #{this} to be undefined'
+ , 'expected #{this} not to be undefined'
+ , this.negate ? false : true
+ );
+
+ return this;
+ }
+ , configurable: true
+});
+
+/**
+ * ### .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
+ * @api public
+ */
+
+Object.defineProperty(Assertion.prototype, 'exist',
+ { get: function () {
+ this.assert(
+ null != flag(this, 'object')
+ , 'expected #{this} to exist'
+ , 'expected #{this} to not exist'
+ );
+
+ return this;
+ }
+ , configurable: true
+});
+
+/**
+ * ### .empty
+ *
+ * Asserts that the target's length is `0`. For arrays, 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
+ * @api public
+ */
+
+Object.defineProperty(Assertion.prototype, 'empty',
+ { get: 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');
+
+ return this;
+ }
+ , configurable: true
+});
+
+/**
+ * ### .arguments
+ *
+ * Asserts that the target is an arguments object.
+ *
+ * function test () {
+ * expect(arguments).to.be.arguments;
+ * }
+ *
+ * @name arguments
+ * @alias Arguments
+ * @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
+ * @param {Mixed} value
+ * @api public
+ */
+
+Assertion.prototype.equal = function (val) {
+ 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);
+ }
+
+ return this;
+};
+
+/**
+ * ### .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
+ * @param {Mixed} value
+ * @api public
+ */
+
+Assertion.prototype.eql = function (obj) {
+ this.assert(
+ util.eql(obj, flag(this, 'object'))
+ , 'expected #{this} to deeply equal #{exp}'
+ , 'expected #{this} to not deeply equal #{exp}'
+ , obj );
+
+ return this;
+};
+
+/**
+ * ### .above(value)
+ *
+ * Asserts that the target is greater than `value`.
+ *
+ * expect(10).to.be.above(5);
+ *
+ * @name above
+ * @alias gt
+ * @param {Number} value
+ * @api public
+ */
+
+Assertion.prototype.above = function (val) {
+ this.assert(
+ flag(this, 'object') > val
+ , 'expected #{this} to be above ' + val
+ , 'expected #{this} to be below ' + val);
+
+ return this;
+};
+
+/**
+ * ### .below(value)
+ *
+ * Asserts that the target is less than `value`.
+ *
+ * expect(5).to.be.below(10);
+ *
+ * @name below
+ * @alias lt
+ * @param {Number} value
+ * @api public
+ */
+
+Assertion.prototype.below = function (val) {
+ this.assert(
+ flag(this, 'object') < val
+ , 'expected #{this} to be below ' + val
+ , 'expected #{this} to be above ' + val);
+
+ return this;
+};
+
+/**
+ * ### .within(start, finish)
+ *
+ * Asserts that the target is within a range.
+ *
+ * expect(7).to.be.within(5,10);
+ *
+ * @name within
+ * @param {Number} start lowerbound inclusive
+ * @param {Number} finish upperbound inclusive
+ * @api public
+ */
+
+Assertion.prototype.within = function (start, finish) {
+ var obj = flag(this, 'object')
+ , range = start + '..' + finish;
+
+ this.assert(
+ obj >= start && obj <= finish
+ , 'expected #{this} to be within ' + range
+ , 'expected #{this} to not be within ' + range);
+
+ return this;
+};
+
+/**
+ * ### .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
+ * @alias instanceOf
+ * @api public
+ */
+
+Assertion.prototype.instanceOf = function (constructor) {
+ var name = util.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);
+
+ return this;
+};
+
+/**
+ * ### .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');
+ * expect(obj).to.have.property('foo').to.be.a('string');
+ *
+ * // 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');
+ *
+ * @name property
+ * @param {String} name
+ * @param {Mixed} value (optional)
+ * @returns value of property for chaining
+ * @api public
+ */
+
+Assertion.prototype.property = function (name, val) {
+ var obj = flag(this, 'object')
+ , value = flag(this, 'deep') ? util.getPathValue(name, obj) : obj[name]
+ , descriptor = flag(this, 'deep') ? 'deep property ' : 'property '
+ , negate = flag(this, 'negate');
+
+ if (negate && undefined !== val) {
+ if (undefined === value) {
+ throw new Error(util.inspect(obj) + ' has no ' + descriptor + util.inspect(name));
+ }
+ } else {
+ this.assert(
+ undefined !== value
+ , 'expected #{this} to have a ' + descriptor + util.inspect(name)
+ , 'expected #{this} to not have ' + descriptor + util.inspect(name));
+ }
+
+ if (undefined !== val) {
+ this.assert(
+ val === value
+ , 'expected #{this} to have a ' + descriptor + util.inspect(name) + ' of #{exp}, but got #{act}'
+ , 'expected #{this} to not have a ' + descriptor + util.inspect(name) + ' of #{act}'
+ , val
+ , value
+ );
+ }
+
+ flag(this, 'object', value);
+ return this;
+};
+
+/**
+ * ### .ownProperty(name)
+ *
+ * Asserts that the target has an own property `name`.
+ *
+ * expect('test').to.have.ownProperty('length');
+ *
+ * @name ownProperty
+ * @alias haveOwnProperty
+ * @param {String} name
+ * @api public
+ */
+
+Assertion.prototype.ownProperty = function (name) {
+ var obj = flag(this, 'object');
+ this.assert(
+ obj.hasOwnProperty(name)
+ , 'expected #{this} to have own property ' + util.inspect(name)
+ , 'expected #{this} to not have own property ' + util.inspect(name));
+ return this;
+};
+
+/**
+ * ### .length(value)
+ *
+ * Asserts that the target's `length` property has the expected value.
+ *
+ * expect([1,2,3]).to.have.length(3);
+ * expect('foobar').to.have.length(6);
+ *
+ * @name length
+ * @alias lengthOf
+ * @param {Number} length
+ * @api public
+ */
+
+Assertion.prototype.length = function (n) {
+ var obj = flag(this, 'object');
+ new Assertion(obj).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
+ );
+
+ return this;
+};
+
+/**
+ * ### .match(regexp)
+ *
+ * Asserts that the target matches a regular expression.
+ *
+ * expect('foobar').to.match(/^foo/);
+ *
+ * @name match
+ * @param {RegExp} RegularExpression
+ * @api public
+ */
+
+Assertion.prototype.match = function (re) {
+ var obj = flag(this, 'object');
+ this.assert(
+ re.exec(obj)
+ , 'expected #{this} to match ' + re
+ , 'expected #{this} not to match ' + re);
+
+ return this;
+};
+
+
+/**
+ * ### .string(string)
+ *
+ * Asserts that the string target contains another string.
+ *
+ * expect('foobar').to.have.string('bar');
+ *
+ * @name string
+ * @param {String} string
+ * @api public
+ */
+
+Assertion.prototype.string = function (str) {
+ var obj = flag(this, 'object');
+ new Assertion(obj).is.a('string');
+
+ this.assert(
+ ~obj.indexOf(str)
+ , 'expected #{this} to contain ' + util.inspect(str)
+ , 'expected #{this} to not contain ' + util.inspect(str));
+
+ return this;
+};
+
+/**
+ * ### .keys(key1, [key2], [...])
+ *
+ * Asserts that the target has exactly the given keys, or
+ * asserts the inclusion of some keys when using the
+ * `include` or `contain` modifiers.
+ *
+ * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);
+ * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');
+ *
+ * @name keys
+ * @alias key
+ * @param {String...|Array} keys
+ * @api public
+ */
+
+Assertion.prototype.keys = function(keys) {
+ var obj = flag(this, 'object')
+ , str
+ , ok = true;
+
+ keys = keys instanceof Array
+ ? keys
+ : Array.prototype.slice.call(arguments);
+
+ if (!keys.length) throw new Error('keys required');
+
+ var actual = Object.keys(obj)
+ , len = keys.length;
+
+ // Inclusion
+ ok = keys.every(function(key){
+ return ~actual.indexOf(key);
+ });
+
+ // Strict
+ if (!flag(this, 'negate') && !flag(this, 'contains')) {
+ ok = ok && keys.length == actual.length;
+ }
+
+ // Key string
+ if (len > 1) {
+ keys = keys.map(function(key){
+ return util.inspect(key);
+ });
+ var last = keys.pop();
+ str = keys.join(', ') + ', and ' + last;
+ } else {
+ str = util.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
+ , keys
+ , Object.keys(obj)
+ );
+
+ return this;
+}
+
+/**
+ * ### .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);
+ * expect(fn).to.not.throw(new RangeError('Out of range.'));
+ *
+ * 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
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
+ * @api public
+ */
+
+Assertion.prototype.Throw = function (constructor, msg) {
+ var obj = flag(this, 'object');
+ new Assertion(obj).is.a('function');
+
+ var thrown = false
+ , desiredError = null
+ , name = null;
+
+ if (arguments.length === 0) {
+ msg = null;
+ constructor = null;
+ } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
+ msg = constructor;
+ constructor = null;
+ } else if (constructor && constructor instanceof Error) {
+ desiredError = constructor;
+ constructor = null;
+ msg = null;
+ } else if (typeof constructor === 'function') {
+ 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 ' + util.inspect(desiredError) + ' but ' + util.inspect(err) + ' was thrown'
+ , 'expected #{this} to not throw ' + util.inspect(desiredError)
+ );
+ return this;
+ }
+ // next, check constructor
+ if (constructor) {
+ this.assert(
+ err instanceof constructor
+ , 'expected #{this} to throw ' + name + ' but a ' + err.name + ' was thrown'
+ , 'expected #{this} to not throw ' + name );
+ if (!msg) return this;
+ }
+ // next, check message
+ if (err.message && msg && msg instanceof RegExp) {
+ this.assert(
+ msg.exec(err.message)
+ , 'expected #{this} to throw error matching ' + msg + ' but got ' + util.inspect(err.message)
+ , 'expected #{this} to throw error not matching ' + msg
+ );
+ return this;
+ } else if (err.message && msg && 'string' === typeof msg) {
+ this.assert(
+ ~err.message.indexOf(msg)
+ , 'expected #{this} to throw error including #{exp} but got #{act}'
+ , 'expected #{this} to throw error not including #{act}'
+ , msg
+ , err.message
+ );
+ return this;
+ } else {
+ thrown = true;
+ }
+ }
+
+ var expectedThrown = name ? name : desiredError ? util.inspect(desiredError) : 'an error';
+
+ this.assert(
+ thrown === true
+ , 'expected #{this} to throw ' + expectedThrown
+ , 'expected #{this} to not throw ' + expectedThrown);
+
+ return this;
+};
+
+/**
+ * ### .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
+ * @param {String} method
+ * @api public
+ */
+
+Assertion.prototype.respondTo = function (method) {
+ var obj = flag(this, 'object')
+ , itself = flag(this, 'itself')
+ , context = ('function' === typeof obj && !itself)
+ ? obj.prototype[method]
+ : obj[method];
+
+ this.assert(
+ 'function' === typeof context
+ , 'expected #{this} to respond to ' + util.inspect(method)
+ , 'expected #{this} to not respond to ' + util.inspect(method)
+ , 'function'
+ , typeof context
+ );
+
+ return this;
+};
+
+/**
+ * ### .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
+ * @api public
+ */
+Object.defineProperty(Assertion.prototype, 'itself',
+ { get: function () {
+ flag(this, 'itself', true);
+ return this;
+ }
+ , configurable: true
+});
+
+/**
+ * ### .satisfy(method)
+ *
+ * Asserts that the target passes a given truth test.
+ *
+ * expect(1).to.satisfy(function(num) { return num > 0; });
+ *
+ * @name satisfy
+ * @param {Function} matcher
+ * @api public
+ */
+
+Assertion.prototype.satisfy = function (matcher) {
+ var obj = flag(this, 'object');
+ this.assert(
+ matcher(obj)
+ , 'expected #{this} to satisfy ' + util.inspect(matcher)
+ , 'expected #{this} to not satisfy' + util.inspect(matcher)
+ , this.negate ? false : true
+ , matcher(obj)
+ );
+
+ return this;
+};
+
+/**
+ * ### .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
+ * @param {Number} expected
+ * @param {Number} delta
+ * @api public
+ */
+
+Assertion.prototype.closeTo = function (expected, delta) {
+ var obj = flag(this, 'object');
+ this.assert(
+ (obj - delta === expected) || (obj + delta === expected)
+ , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
+ , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta);
+
+ return this;
+};
+
+/*!
+ * Aliases.
+ */
+
+(function alias(name, as){
+ Assertion.prototype[as] = Assertion.prototype[name];
+ return alias;
+})
+('equal', 'eq')
+('above', 'gt')
+('below', 'lt')
+('length', 'lengthOf')
+('keys', 'key')
+('ownProperty', 'haveOwnProperty')
+('above', 'greaterThan')
+('below', 'lessThan')
+('Throw', 'throws')
+('Throw', 'throw')
+('instanceOf', 'instanceof');
+
+}); // module: assertion.js
+
+require.register("browser/error.js", function(module, exports, require){
+/*!
+ * chai
+ * Copyright(c) 2011-2012 Jake Luer
+ * MIT Licensed
+ */
+
+module.exports = AssertionError;
+
+function AssertionError (options) {
+ options = options || {};
+ this.message = options.message;
+ this.actual = options.actual;
+ this.expected = options.expected;
+ this.operator = options.operator;
+
+ if (options.stackStartFunction && Error.captureStackTrace) {
+ var stackStartFunction = options.stackStartFunction;
+ Error.captureStackTrace(this, stackStartFunction);
+ }
+}
+
+AssertionError.prototype = Object.create(Error.prototype);
+AssertionError.prototype.name = 'AssertionError';
+AssertionError.prototype.constructor = AssertionError;
+
+AssertionError.prototype.toString = function() {
+ return this.message;
+};
+
+}); // module: browser/error.js
+
+require.register("chai.js", function(module, exports, require){
+/*!
+ * chai
+ * Copyright(c) 2011-2012 Jake Luer
+ * MIT Licensed
+ */
+
+var used = []
+ , exports = module.exports = {};
+
+/*!
+ * Chai version
+ */
+
+exports.version = '1.0.4';
+
+/*!
+ * Primary `Assertion` prototype
+ */
+
+exports.Assertion = require('./assertion');
+
+/*!
+ * Assertion Error
+ */
+
+exports.AssertionError = require('./browser/error');
+
+/*!
+ * Utils for plugins (not exported)
+ */
+
+var util = require('./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;
+};
+
+/*!
+ * Expect interface
+ */
+
+var expect = require('./interface/expect');
+exports.use(expect);
+
+/*!
+ * Should interface
+ */
+
+var should = require('./interface/should');
+exports.use(should);
+
+/*!
+ * Assert interface
+ */
+
+var assert = require('./interface/assert');
+exports.use(assert);
+
+}); // module: chai.js
+
+require.register("interface/assert.js", function(module, exports, require){
+/*!
+ * chai
+ * Copyright(c) 2011-2012 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
+ * @api public
+ */
+
+ var assert = chai.assert = function (express, errmsg) {
+ var test = new Assertion(null);
+ 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
+ * @api public
+ */
+
+ assert.fail = function (actual, expected, message, operator) {
+ throw new chai.AssertionError({
+ actual: actual
+ , expected: expected
+ , message: message
+ , operator: operator
+ , stackStartFunction: assert.fail
+ });
+ };
+
+ /**
+ * ### .ok(object, [message])
+ *
+ * Asserts that `object` is truthy.
+ *
+ * assert.ok('everything', 'everything is ok');
+ * assert.ok(false, 'this will fail');
+ *
+ * @name ok
+ * @param {Mixed} object to test
+ * @param {String} message
+ * @api public
+ */
+
+ assert.ok = function (val, msg) {
+ new Assertion(val, msg).is.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
+ * @api public
+ */
+
+ assert.equal = function (act, exp, msg) {
+ var test = new Assertion(act, msg);
+
+ 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
+ * @api public
+ */
+
+ assert.notEqual = function (act, exp, msg) {
+ var test = new Assertion(act, msg);
+
+ 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
+ * @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
+ * @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
+ * @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
+ * @api public
+ */
+
+ assert.notDeepEqual = function (act, exp, msg) {
+ new Assertion(act, msg).to.not.eql(exp);
+ };
+
+ /**
+ * ### .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
+ * @api public
+ */
+
+ assert.isTrue = function (val, msg) {
+ new Assertion(val, msg).is['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
+ * @api public
+ */
+
+ assert.isFalse = function (val, msg) {
+ new Assertion(val, msg).is['false'];
+ };
+
+ /**
+ * ### .isNull(value, [message])
+ *
+ * Asserts that `value` is null.
+ *
+ * assert.isNull(err, 'there was no error');
+ *
+ * @name isNull
+ * @param {Mixed} value
+ * @param {String} message
+ * @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
+ * @api public
+ */
+
+ assert.isNotNull = function (val, msg) {
+ new Assertion(val, msg).to.not.equal(null);
+ };
+
+ /**
+ * ### .isUndefined(value, [message])
+ *
+ * Asserts that `value` is `undefined`.
+ *
+ * var tea;
+ * assert.isUndefined(tea, 'no tea defined');
+ *
+ * @name isUndefined
+ * @param {Mixed} value
+ * @param {String} message
+ * @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 isUndefined
+ * @param {Mixed} value
+ * @param {String} message
+ * @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
+ * @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
+ * @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 (as revealed by
+ * `Object.prototype.toString`).
+ *
+ * var selection = { name: 'Chai', serve: 'with spices' };
+ * assert.isObject(selection, 'tea selection is an object');
+ *
+ * @name isObject
+ * @param {Mixed} value
+ * @param {String} message
+ * @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.
+ *
+ * var selection = 'chai'
+ * assert.isObject(selection, 'tea selection is not an object');
+ * assert.isObject(null, 'null is not an object');
+ *
+ * @name isNotObject
+ * @param {Mixed} value
+ * @param {String} message
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @api public
+ */
+
+ assert.include = function (exp, inc, msg) {
+ var obj = new Assertion(exp, msg);
+
+ if (Array.isArray(exp)) {
+ obj.to.include(inc);
+ } else if ('string' === typeof exp) {
+ obj.to.contain.string(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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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', 5, 'string has length of 6');
+ *
+ * @name lengthOf
+ * @param {Mixed} object
+ * @param {Number} length
+ * @param {String} message
+ * @api public
+ */
+
+ assert.lengthOf = function (exp, len, msg) {
+ new Assertion(exp, msg).to.have.length(len);
+ };
+
+ /**
+ * ### .throws(function, [constructor/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.throw(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
+ * @api public
+ */
+
+ assert.Throw = function (fn, type, msg) {
+ if ('string' === typeof type) {
+ msg = type;
+ type = null;
+ }
+
+ new Assertion(fn, msg).to.Throw(type);
+ };
+
+ /**
+ * ### .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
+ * @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
+ * @api public
+ */
+
+ assert.operator = function (val, operator, val2, msg) {
+ if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) {
+ throw new Error('Invalid operator "' + operator + '"');
+ }
+ var test = new Assertion(eval(val + operator + val2), 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) );
+ };
+
+ /*!
+ * Undocumented / untested
+ */
+
+ assert.ifError = function (val, msg) {
+ new Assertion(val, msg).to.not.be.ok;
+ };
+
+ /*!
+ * Aliases.
+ */
+
+ (function alias(name, as){
+ assert[as] = assert[name];
+ return alias;
+ })
+ ('Throw', 'throw')
+ ('Throw', 'throws');
+};
+
+}); // module: interface/assert.js
+
+require.register("interface/expect.js", function(module, exports, require){
+/*!
+ * chai
+ * Copyright(c) 2011-2012 Jake Luer
+ * MIT Licensed
+ */
+
+module.exports = function (chai, util) {
+ chai.expect = function (val, message) {
+ return new chai.Assertion(val, message);
+ };
+};
+
+
+}); // module: interface/expect.js
+
+require.register("interface/should.js", function(module, exports, require){
+/*!
+ * chai
+ * Copyright(c) 2011-2012 Jake Luer
+ * MIT Licensed
+ */
+
+module.exports = function (chai, util) {
+ var Assertion = chai.Assertion;
+
+ function loadShould () {
+ // modify Object.prototype to have `should`
+ Object.defineProperty(Object.prototype, 'should',
+ { set: function () {}
+ , get: function(){
+ if (this instanceof String || this instanceof Number) {
+ return new Assertion(this.constructor(this));
+ } else if (this instanceof Boolean) {
+ return new Assertion(this == true);
+ }
+ return new Assertion(this);
+ }
+ , configurable: true
+ });
+
+ var should = {};
+
+ should.equal = function (val1, val2) {
+ new Assertion(val1).to.equal(val2);
+ };
+
+ should.Throw = function (fn, errt, errs) {
+ new Assertion(fn).to.Throw(errt, errs);
+ };
+
+ should.exist = function (val) {
+ new Assertion(val).to.exist;
+ }
+
+ // negation
+ should.not = {}
+
+ should.not.equal = function (val1, val2) {
+ new Assertion(val1).to.not.equal(val2);
+ };
+
+ should.not.Throw = function (fn, errt, errs) {
+ new Assertion(fn).to.not.Throw(errt, errs);
+ };
+
+ should.not.exist = function (val) {
+ new Assertion(val).to.not.exist;
+ }
+
+ should['throw'] = should['Throw'];
+ should.not['throw'] = should.not['Throw'];
+
+ return should;
+ };
+
+ chai.should = loadShould;
+ chai.Should = loadShould;
+};
+
+}); // module: interface/should.js
+
+require.register("utils/addChainableMethod.js", function(module, exports, require){
+/*!
+ * Chai - addChainingMethod utility
+ * Copyright(c) 2012 Jake Luer
+ * MIT Licensed
+ */
+
+/*!
+ * Module dependencies
+ */
+
+var transferFlags = require('./transferFlags');
+
+/**
+ * ### 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
+ * @name addChainableMethod
+ * @api public
+ */
+
+module.exports = function (ctx, name, method, chainingBehavior) {
+ if (typeof chainingBehavior !== 'function')
+ chainingBehavior = function () { };
+
+ Object.defineProperty(ctx, name,
+ { get: function () {
+ chainingBehavior.call(this);
+
+ var assert = function () {
+ var result = method.apply(this, arguments);
+ return result === undefined ? this : result;
+ };
+
+ // Re-enumerate every time to better accomodate plugins.
+ var asserterNames = Object.getOwnPropertyNames(ctx);
+ asserterNames.forEach(function (asserterName) {
+ var pd = Object.getOwnPropertyDescriptor(ctx, asserterName)
+ , functionProtoPD = Object.getOwnPropertyDescriptor(Function.prototype, asserterName);
+ // Avoid trying to overwrite things that we can't, like `length` and `arguments`.
+ if (functionProtoPD && !functionProtoPD.configurable) return;
+ if (asserterName === 'arguments') return; // @see chaijs/chai/issues/69
+ Object.defineProperty(assert, asserterName, pd);
+ });
+
+ transferFlags(this, assert);
+ return assert;
+ }
+ , configurable: true
+ });
+};
+
+}); // module: utils/addChainableMethod.js
+
+require.register("utils/addMethod.js", function(module, exports, require){
+/*!
+ * Chai - addMethod utility
+ * Copyright(c) 2012 Jake Luer
+ * MIT Licensed
+ */
+
+/**
+ * ### 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
+ * @name addMethod
+ * @api public
+ */
+
+module.exports = function (ctx, name, method) {
+ ctx[name] = function () {
+ var result = method.apply(this, arguments);
+ return result === undefined ? this : result;
+ };
+};
+
+}); // module: utils/addMethod.js
+
+require.register("utils/addProperty.js", function(module, exports, require){
+/*!
+ * Chai - addProperty utility
+ * Copyright(c) 2012 Jake Luer
+ * MIT Licensed
+ */
+
+/**
+ * ### 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
+ * @name addProperty
+ * @api public
+ */
+
+module.exports = function (ctx, name, getter) {
+ Object.defineProperty(ctx, name,
+ { get: function () {
+ var result = getter.call(this);
+ return result === undefined ? this : result;
+ }
+ , configurable: true
+ });
+};
+
+}); // module: utils/addProperty.js
+
+require.register("utils/eql.js", function(module, exports, require){
+// This is directly from Node.js assert
+// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/assert.js
+
+
+module.exports = _deepEqual;
+
+// For browser implementation
+if (!Buffer) {
+ var Buffer = {
+ isBuffer: function () {
+ return false;
+ }
+ };
+}
+
+function _deepEqual(actual, expected) {
+ // 7.1. All identical values are equivalent, as determined by ===.
+ if (actual === expected) {
+ return true;
+
+ } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
+ if (actual.length != expected.length) return false;
+
+ for (var i = 0; i < actual.length; i++) {
+ if (actual[i] !== expected[i]) return false;
+ }
+
+ return true;
+
+ // 7.2. If the expected value is a Date object, the actual value is
+ // equivalent if it is also a Date object that refers to the same time.
+ } else if (actual instanceof Date && expected instanceof Date) {
+ return actual.getTime() === expected.getTime();
+
+ // 7.3. Other pairs that do not both pass typeof value == 'object',
+ // equivalence is determined by ==.
+ } else if (typeof actual != 'object' && typeof expected != 'object') {
+ return actual === expected;
+
+ // 7.4. For all other Object pairs, including Array objects, equivalence is
+ // determined by having the same number of owned properties (as verified
+ // with Object.prototype.hasOwnProperty.call), the same set of keys
+ // (although not necessarily the same order), equivalent values for every
+ // corresponding key, and an identical 'prototype' property. Note: this
+ // accounts for both named and indexed properties on Arrays.
+ } else {
+ return objEquiv(actual, expected);
+ }
+}
+
+function isUndefinedOrNull(value) {
+ return value === null || value === undefined;
+}
+
+function isArguments(object) {
+ return Object.prototype.toString.call(object) == '[object Arguments]';
+}
+
+function objEquiv(a, b) {
+ if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
+ return false;
+ // an identical 'prototype' property.
+ if (a.prototype !== b.prototype) return false;
+ //~~~I've managed to break Object.keys through screwy arguments passing.
+ // Converting to array solves the problem.
+ if (isArguments(a)) {
+ if (!isArguments(b)) {
+ return false;
+ }
+ a = pSlice.call(a);
+ b = pSlice.call(b);
+ return _deepEqual(a, b);
+ }
+ try {
+ var ka = Object.keys(a),
+ kb = Object.keys(b),
+ key, i;
+ } catch (e) {//happens when one is a string literal and the other isn't
+ return false;
+ }
+ // having the same number of owned properties (keys incorporates
+ // hasOwnProperty)
+ if (ka.length != kb.length)
+ return false;
+ //the same set of keys (although not necessarily the same order),
+ ka.sort();
+ kb.sort();
+ //~~~cheap key test
+ for (i = ka.length - 1; i >= 0; i--) {
+ if (ka[i] != kb[i])
+ return false;
+ }
+ //equivalent values for every corresponding key, and
+ //~~~possibly expensive deep test
+ for (i = ka.length - 1; i >= 0; i--) {
+ key = ka[i];
+ if (!_deepEqual(a[key], b[key])) return false;
+ }
+ return true;
+}
+}); // module: utils/eql.js
+
+require.register("utils/flag.js", function(module, exports, require){
+/*!
+ * Chai - flag utility
+ * Copyright(c) 2012 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)
+ * @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];
+ }
+};
+
+}); // module: utils/flag.js
+
+require.register("utils/getActual.js", function(module, exports, require){
+/*!
+ * Chai - getActual utility
+ * Copyright(c) 2012 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
+ */
+
+module.exports = function (obj, args) {
+ var actual = args[4];
+ return 'undefined' !== actual ? actual : obj.obj;
+};
+
+}); // module: utils/getActual.js
+
+require.register("utils/getMessage.js", function(module, exports, require){
+/*!
+ * Chai - message composition utility
+ * Copyright(c) 2012 Jake Luer
+ * MIT Licensed
+ */
+
+/*!
+ * Module dependancies
+ */
+
+var flag = require('./flag')
+ , getActual = require('./getActual')
+ , inspect = require('./inspect');
+
+/**
+ * # 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.
+ *
+ * Messsage template tags:
+ * - `#{this}` current asserted object
+ * - `#{act}` actual value
+ * - `#{exp}` expected value
+ *
+ * @param {Object} object (constructed Assertion)
+ * @param {Arguments} chai.Assertion.prototype.assert arguments
+ */
+
+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');
+
+ msg = msg || '';
+ msg = msg
+ .replace(/#{this}/g, inspect(val))
+ .replace(/#{act}/g, inspect(actual))
+ .replace(/#{exp}/g, inspect(expected));
+
+ return flagMsg ? flagMsg + ': ' + msg : msg;
+};
+
+}); // module: utils/getMessage.js
+
+require.register("utils/getName.js", function(module, exports, require){
+/*!
+ * Chai - getName utility
+ * Copyright(c) 2012 Jake Luer
+ * MIT Licensed
+ */
+
+/**
+ * # getName(func)
+ *
+ * Gets the name of a function, in a cross-browser way.
+ *
+ * @param {Function} a function (usually a constructor)
+ */
+
+module.exports = function (func) {
+ if (func.name) return func.name;
+
+ var match = /^\s?function ([^(]*)\(/.exec(func);
+ return match && match[1] ? match[1] : "";
+};
+
+}); // module: utils/getName.js
+
+require.register("utils/getPathValue.js", function(module, exports, require){
+/*!
+ * Chai - getPathValue utility
+ * Copyright(c) 2012 Jake Luer
+ * @see https://github.com/logicalparadox/filtr
+ * MIT Licensed
+ */
+
+/**
+ * ### .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`
+ * @name getPathValue
+ * @api public
+ */
+
+var getPathValue = module.exports = function (path, obj) {
+ var parsed = parsePath(path);
+ return _getPathValue(parsed, obj);
+};
+
+/*!
+ * ## 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`.
+ *
+ * @param {String} path
+ * @returns {Object} parsed
+ * @api private
+ */
+
+function parsePath (path) {
+ var parts = path.split('.').filter(Boolean);
+ return parts.map(function (value) {
+ var re = /([A-Za-z0-9]+)\[(\d+)\]$/
+ , mArr = re.exec(value)
+ , val;
+ if (mArr) val = { p: mArr[1], i: parseFloat(mArr[2]) };
+ return val || value;
+ });
+};
+
+/*!
+ * ## _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
+ * @returns {Object|Undefined} value
+ * @api private
+ */
+
+function _getPathValue (parsed, obj) {
+ var tmp = obj
+ , res;
+ for (var i = 0, l = parsed.length; i < l; i++) {
+ var part = parsed[i];
+ if (tmp) {
+ if ('object' === typeof part && tmp[part.p]) {
+ tmp = tmp[part.p][part.i];
+ } else {
+ tmp = tmp[part];
+ }
+ if (i == (l - 1)) res = tmp;
+ } else {
+ res = undefined;
+ }
+ }
+ return res;
+};
+
+}); // module: utils/getPathValue.js
+
+require.register("utils/index.js", function(module, exports, require){
+/*!
+ * chai
+ * Copyright(c) 2011 Jake Luer
+ * MIT Licensed
+ */
+
+/*!
+ * Main exports
+ */
+
+var exports = module.exports = {};
+
+/*!
+ * test utility
+ */
+
+exports.test = require('./test');
+
+/*!
+ * message utility
+ */
+
+exports.getMessage = require('./getMessage');
+
+/*!
+ * actual utility
+ */
+
+exports.getActual = require('./getActual');
+
+/*!
+ * Inspect util
+ */
+
+exports.inspect = require('./inspect');
+
+/*!
+ * Flag utility
+ */
+
+exports.flag = require('./flag');
+
+/*!
+ * Flag transferring utility
+ */
+
+exports.transferFlags = require('./transferFlags');
+
+/*!
+ * Deep equal utility
+ */
+
+exports.eql = require('./eql');
+
+/*!
+ * Deep path value
+ */
+
+exports.getPathValue = require('./getPathValue');
+
+/*!
+ * 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');
+
+
+}); // module: utils/index.js
+
+require.register("utils/inspect.js", function(module, exports, require){
+// This is (almost) directly from Node.js utils
+// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
+
+var getName = require('./getName');
+
+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).
+ */
+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));
+}
+
+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)) {
+ return value.inspect(recurseTimes);
+ }
+
+ // Primitive types cannot have properties
+ var primitive = formatPrimitive(ctx, value);
+ if (primitive) {
+ return primitive;
+ }
+
+ // Look up the keys of the object.
+ var visibleKeys = Object.keys(value);
+ var keys = ctx.showHidden ? Object.getOwnPropertyNames(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 n = value.name ? ': ' + value.name : '';
+ base = ' [Function' + n + ']';
+ }
+
+ // 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':
+ 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);
+}
+
+}); // module: utils/inspect.js
+
+require.register("utils/overwriteMethod.js", function(module, exports, require){
+/*!
+ * Chai - overwriteMethod utility
+ * Copyright(c) 2012 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
+ * @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;
+ }
+};
+
+}); // module: utils/overwriteMethod.js
+
+require.register("utils/overwriteProperty.js", function(module, exports, require){
+/*!
+ * Chai - overwriteProperty utility
+ * Copyright(c) 2012 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
+ * @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
+ });
+};
+
+}); // module: utils/overwriteProperty.js
+
+require.register("utils/test.js", function(module, exports, require){
+/*!
+ * Chai - test utility
+ * Copyright(c) 2012 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
+ */
+
+module.exports = function (obj, args) {
+ var negate = flag(obj, 'negate')
+ , expr = args[0];
+ return negate ? !expr : expr;
+};
+
+}); // module: utils/test.js
+
+require.register("utils/transferFlags.js", function(module, exports, require){
+/*!
+ * Chai - transferFlags utility
+ * Copyright(c) 2012 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 too; usually a new assertion
+ * @param {Boolean} includeAll
+ * @name getAllFlags
+ * @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];
+ }
+ }
+};
+
+}); // module: utils/transferFlags.js
+
+
+ return require('chai');
+});
\ No newline at end of file
diff --git a/docs/example/debug-hanging-mocha.js b/docs/example/debug-hanging-mocha.js
new file mode 100644
index 0000000000..fb36dc83c4
--- /dev/null
+++ b/docs/example/debug-hanging-mocha.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const net = require('net');
+const assert = require('assert');
+
+describe('how to debug Mocha when it hangs', function () {
+ before(function (done) {
+ const server = net.createServer();
+ server.listen(10101, done);
+ });
+
+ after(function () {
+ global.asyncDump();
+ });
+
+ it('should complete, but Mocha should not exit', function(done) {
+ const sock = net.createConnection(10101, () => {
+ assert.deepEqual(sock.address().family, 'IPv4');
+ done();
+ });
+ });
+});
\ No newline at end of file
diff --git a/docs/example/tests.html b/docs/example/tests.html
new file mode 100644
index 0000000000..b4c8a7354e
--- /dev/null
+++ b/docs/example/tests.html
@@ -0,0 +1,20 @@
+
+
+
+
+ Mocha
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/favicon.ico b/docs/favicon.ico
new file mode 100644
index 0000000000..8c773fc0e1
Binary files /dev/null and b/docs/favicon.ico differ
diff --git a/docs/images/emacs.png b/docs/images/emacs.png
new file mode 100644
index 0000000000..ec3be76abe
Binary files /dev/null and b/docs/images/emacs.png differ
diff --git a/docs/images/jetbrains-plugin.png b/docs/images/jetbrains-plugin.png
new file mode 100644
index 0000000000..f3423031ec
Binary files /dev/null and b/docs/images/jetbrains-plugin.png differ
diff --git a/docs/images/reporter-doc.png b/docs/images/reporter-doc.png
new file mode 100644
index 0000000000..c0b227f22b
Binary files /dev/null and b/docs/images/reporter-doc.png differ
diff --git a/docs/images/reporter-dot.png b/docs/images/reporter-dot.png
new file mode 100644
index 0000000000..5477cb63f4
Binary files /dev/null and b/docs/images/reporter-dot.png differ
diff --git a/docs/images/reporter-html.png b/docs/images/reporter-html.png
new file mode 100644
index 0000000000..997d252b6c
Binary files /dev/null and b/docs/images/reporter-html.png differ
diff --git a/docs/images/reporter-json-stream.png b/docs/images/reporter-json-stream.png
new file mode 100644
index 0000000000..19d5724709
Binary files /dev/null and b/docs/images/reporter-json-stream.png differ
diff --git a/docs/images/reporter-json.png b/docs/images/reporter-json.png
new file mode 100644
index 0000000000..249f49a566
Binary files /dev/null and b/docs/images/reporter-json.png differ
diff --git a/docs/images/reporter-landing-fail.png b/docs/images/reporter-landing-fail.png
new file mode 100644
index 0000000000..a90562c25e
Binary files /dev/null and b/docs/images/reporter-landing-fail.png differ
diff --git a/docs/images/reporter-landing.png b/docs/images/reporter-landing.png
new file mode 100644
index 0000000000..fc9d443ad3
Binary files /dev/null and b/docs/images/reporter-landing.png differ
diff --git a/docs/images/reporter-list.png b/docs/images/reporter-list.png
new file mode 100644
index 0000000000..c7a68f1208
Binary files /dev/null and b/docs/images/reporter-list.png differ
diff --git a/docs/images/reporter-min.png b/docs/images/reporter-min.png
new file mode 100644
index 0000000000..55c45d6ffe
Binary files /dev/null and b/docs/images/reporter-min.png differ
diff --git a/docs/images/reporter-nyan.png b/docs/images/reporter-nyan.png
new file mode 100644
index 0000000000..b21e0a4f43
Binary files /dev/null and b/docs/images/reporter-nyan.png differ
diff --git a/docs/images/reporter-progress.png b/docs/images/reporter-progress.png
new file mode 100644
index 0000000000..79237b388c
Binary files /dev/null and b/docs/images/reporter-progress.png differ
diff --git a/docs/images/reporter-spec-duration.png b/docs/images/reporter-spec-duration.png
new file mode 100644
index 0000000000..d48e750e3e
Binary files /dev/null and b/docs/images/reporter-spec-duration.png differ
diff --git a/docs/images/reporter-spec-fail.png b/docs/images/reporter-spec-fail.png
new file mode 100644
index 0000000000..e4910a7029
Binary files /dev/null and b/docs/images/reporter-spec-fail.png differ
diff --git a/docs/images/reporter-spec.png b/docs/images/reporter-spec.png
new file mode 100644
index 0000000000..2fd39d76eb
Binary files /dev/null and b/docs/images/reporter-spec.png differ
diff --git a/docs/images/reporter-string-diffs.png b/docs/images/reporter-string-diffs.png
new file mode 100644
index 0000000000..f761c215b5
Binary files /dev/null and b/docs/images/reporter-string-diffs.png differ
diff --git a/docs/images/reporter-tap.png b/docs/images/reporter-tap.png
new file mode 100644
index 0000000000..054a6ef7cb
Binary files /dev/null and b/docs/images/reporter-tap.png differ
diff --git a/docs/images/wallaby.png b/docs/images/wallaby.png
new file mode 100644
index 0000000000..ac68bac80e
Binary files /dev/null and b/docs/images/wallaby.png differ
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000000..819061b574
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,1299 @@
+---
+layout: default
+title: 'Mocha - the fun, simple, flexible JavaScript test framework'
+---
+Mocha is a feature-rich JavaScript test framework running on [Node.js](http://nodejs.org) and in the browser, making asynchronous testing *simple* and *fun*. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted on [GitHub](https://github.com/mochajs/mocha).
+
+ [![Gitter](//badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mochajs/mocha)
+ [![OpenCollective](//opencollective.com/mochajs/backers/badge.svg)](#backers)
+ [![OpenCollective](//opencollective.com/mochajs/sponsors/badge.svg)](#sponsors)
+
+{% include backers.md %}
+{% include sponsors.md %}
+
+## Features
+
+- browser support
+- simple async support, including promises
+- test coverage reporting
+- string diff support
+- javascript API for running tests
+- proper exit status for CI support etc
+- auto-detects and disables coloring for non-ttys
+- maps uncaught exceptions to the correct test case
+- async test timeout support
+- test retry support
+- test-specific timeouts
+- growl notification support
+- reports test durations
+- highlights slow tests
+- file watcher support
+- global variable leak detection
+- optionally run tests that match a regexp
+- auto-exit to prevent "hanging" with an active loop
+- easily meta-generate suites & test-cases
+- mocha.opts file support
+- clickable suite titles to filter test execution
+- node debugger support
+- detects multiple calls to `done()`
+- use any assertion library you want
+- extensible reporting, bundled with 9+ reporters
+- extensible test DSLs or "interfaces"
+- before, after, before each, after each hooks
+- arbitrary transpiler support (coffee-script etc)
+- TextMate bundle
+- and more!
+
+## Table of Contents
+
+
+
+- [Installation](#installation)
+- [Getting Started](#getting-started)
+- [Assertions](#assertions)
+- [Asynchronous Code](#asynchronous-code)
+- [Synchronous Code](#synchronous-code)
+- [Arrow Functions](#arrow-functions)
+- [Hooks](#hooks)
+- [Pending Tests](#pending-tests)
+- [Exclusive Tests](#exclusive-tests)
+- [Inclusive Tests](#inclusive-tests)
+- [Retry Tests](#retry-tests)
+- [Dynamically Generating Tests](#dynamically-generating-tests)
+- [Timeouts](#timeouts)
+- [Diffs](#diffs)
+- [Usage](#usage)
+- [Interfaces](#interfaces)
+- [Reporters](#reporters)
+- [Running Mocha in the Browser](#running-mocha-in-the-browser)
+- [`mocha.opts`](#mochaopts)
+- [The `test/` Directory](#the-test-directory)
+- [Editor Plugins](#editor-plugins)
+- [Examples](#examples)
+- [Testing Mocha](#testing-mocha)
+- [More Information](#more-information)
+
+
+
+## Installation
+
+Install with [npm](https://npmjs.org) globally:
+
+```sh
+$ npm install --global mocha
+```
+
+or as a development dependency for your project:
+
+```sh
+$ npm install --save-dev mocha
+```
+
+> To install Mocha v3.0.0 or newer with `npm`, you will need `npm` v2.14.2 or newer. Additionally, to run Mocha, you will need Node.js v4 or newer.
+
+Mocha can also be installed via [Bower](http://bower.io) (`bower install mocha`), and is available at [cdnjs](https://cdnjs.com/libraries/mocha).
+
+## Getting Started
+
+```sh
+$ npm install mocha
+$ mkdir test
+$ $EDITOR test/test.js # or open with your favorite editor
+```
+
+In your editor:
+
+```js
+var assert = require('assert');
+describe('Array', function() {
+ describe('#indexOf()', function() {
+ it('should return -1 when the value is not present', function() {
+ assert.equal([1,2,3].indexOf(4), -1);
+ });
+ });
+});
+```
+
+Back in the terminal:
+
+```sh
+$ ./node_modules/mocha/bin/mocha
+
+ Array
+ #indexOf()
+ ✓ should return -1 when the value is not present
+
+
+ 1 passing (9ms)
+```
+
+Set up a test script in package.json:
+
+```json
+"scripts": {
+ "test": "mocha"
+ }
+```
+
+Then run tests with:
+
+```sh
+$ npm test
+```
+
+## Assertions
+
+Mocha allows you to use any assertion library you wish. In the above example, we're using Node.js' built-in [assert](https://nodejs.org/api/assert.html) module--but generally, if it throws an `Error`, it will work! This means you can use libraries such as:
+
+- [should.js](https://github.com/shouldjs/should.js) - BDD style shown throughout these docs
+- [expect.js](https://github.com/LearnBoost/expect.js) - `expect()` style assertions
+- [chai](http://chaijs.com/) - `expect()`, `assert()` and `should`-style assertions
+- [better-assert](https://github.com/visionmedia/better-assert) - C-style self-documenting `assert()`
+- [unexpected](http://unexpected.js.org) - "the extensible BDD assertion toolkit"
+
+## Asynchronous Code
+
+Testing asynchronous code with Mocha could not be simpler! Simply invoke the callback when your test is complete. By adding a callback (usually named `done`) to `it()`, Mocha will know that it should wait for this function to be called to complete the test.
+
+```js
+describe('User', function() {
+ describe('#save()', function() {
+ it('should save without error', function(done) {
+ var user = new User('Luna');
+ user.save(function(err) {
+ if (err) done(err);
+ else done();
+ });
+ });
+ });
+});
+```
+
+To make things even easier, the `done()` callback accepts an error, so we may use this directly:
+
+```js
+describe('User', function() {
+ describe('#save()', function() {
+ it('should save without error', function(done) {
+ var user = new User('Luna');
+ user.save(done);
+ });
+ });
+});
+```
+
+### Working with Promises
+
+Alternately, instead of using the `done()` callback, you may return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). This is useful if the APIs you are testing return promises instead of taking callbacks:
+
+```js
+beforeEach(function() {
+ return db.clear()
+ .then(function() {
+ return db.save([tobi, loki, jane]);
+ });
+});
+
+describe('#find()', function() {
+ it('respond with matching records', function() {
+ return db.find({ type: 'User' }).should.eventually.have.length(3);
+ });
+});
+```
+
+> The latter example uses [Chai as Promised](https://www.npmjs.com/package/chai-as-promised) for fluent promise assertions.
+
+In Mocha v3.0.0 and newer, returning a `Promise` *and* calling `done()` will result in an exception, as this is generally a mistake:
+
+```js
+const assert = require('assert');
+
+it('should complete this test', function (done) {
+ return new Promise(function (resolve) {
+ assert.ok(true);
+ resolve();
+ })
+ .then(done);
+});
+```
+
+The above test will fail with `Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.`. In versions older than v3.0.0, the call to `done()` is effectively ignored.
+
+### Using async / await
+
+If your JS environment supports [async / await](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/async_function) you can also write asynchronous tests like this:
+
+```js
+beforeEach(async function() {
+ await db.clear();
+ await db.save([tobi, loki, jane]);
+});
+
+describe('#find()', function() {
+ it('responds with matching records', async function() {
+ const users = await db.find({ type: 'User' });
+ users.should.have.length(3);
+ });
+});
+```
+
+## Synchronous Code
+
+When testing synchronous code, omit the callback and Mocha will automatically continue on to the next test.
+
+```js
+describe('Array', function() {
+ describe('#indexOf()', function() {
+ it('should return -1 when the value is not present', function() {
+ [1,2,3].indexOf(5).should.equal(-1);
+ [1,2,3].indexOf(0).should.equal(-1);
+ });
+ });
+});
+```
+
+## Arrow Functions
+
+Passing [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) ("lambdas") to Mocha is discouraged. Lambdas lexically bind `this` and cannot access the Mocha context. For example, the following code will fail:
+
+```js
+describe('my suite', () => {
+ it('my test', () => {
+ // should set the timeout of this test to 1000 ms; instead will fail
+ this.timeout(1000);
+ assert.ok(true);
+ });
+});
+```
+
+*If you do not need to use* Mocha's context, lambdas should work. However, the result will be more difficult to refactor if the need eventually arises.
+
+## Hooks
+
+With its default "BDD"-style interface, Mocha provides the hooks `before()`, `after()`, `beforeEach()`, and `afterEach()`. These should be used to set up preconditions and clean up after your tests.
+
+```js
+describe('hooks', function() {
+
+ before(function() {
+ // runs before all tests in this block
+ });
+
+ after(function() {
+ // runs after all tests in this block
+ });
+
+ beforeEach(function() {
+ // runs before each test in this block
+ });
+
+ afterEach(function() {
+ // runs after each test in this block
+ });
+
+ // test cases
+});
+```
+
+> Tests can appear before, after, or interspersed with your hooks. Hooks will run in the order they are defined, as appropriate; all `before()` hooks run (once), then any `beforeEach()` hooks, tests, any `afterEach()` hooks, and finally `after()` hooks (once).
+
+### Describing Hooks
+
+Any hook can be invoked with an optional description, making it easier to pinpoint errors in your tests. If a hook is given a named function, that name will be used if no description is supplied.
+
+```js
+beforeEach(function() {
+ // beforeEach hook
+});
+
+beforeEach(function namedFun() {
+ // beforeEach:namedFun
+});
+
+beforeEach('some description', function() {
+ // beforeEach:some description
+});
+```
+
+### Asynchronous Hooks
+
+All hooks (`before()`, `after()`, `beforeEach()`, `afterEach()`) may be sync or async as well, behaving much like a regular test-case. For example, you may wish to populate database with dummy content before each test:
+
+```js
+describe('Connection', function() {
+ var db = new Connection,
+ tobi = new User('tobi'),
+ loki = new User('loki'),
+ jane = new User('jane');
+
+ beforeEach(function(done) {
+ db.clear(function(err) {
+ if (err) return done(err);
+ db.save([tobi, loki, jane], done);
+ });
+ });
+
+ describe('#find()', function() {
+ it('respond with matching records', function(done) {
+ db.find({type: 'User'}, function(err, res) {
+ if (err) return done(err);
+ res.should.have.length(3);
+ done();
+ });
+ });
+ });
+});
+```
+
+### Root-Level Hooks
+
+You may also pick any file and add "root"-level hooks. For example, add `beforeEach()` outside of all `describe()` blocks. This will cause the callback to `beforeEach()` to run before any test case, regardless of the file it lives in (this is because Mocha has an *implied* `describe()` block, called the "root suite").
+
+```js
+beforeEach(function() {
+ console.log('before every test in every file');
+});
+```
+
+### Delayed Root Suite
+
+If you need to perform asynchronous operations before any of your suites are run, you may delay the root suite. Run `mocha` with the `--delay` flag. This will attach a special callback function, `run()`, to the global context:
+
+```js
+setTimeout(function() {
+ // do some setup
+
+ describe('my suite', function() {
+ // ...
+ });
+
+ run();
+}, 5000);
+```
+
+## Pending Tests
+
+"Pending"--as in "someone should write these test cases eventually"--test-cases are simply those *without* a callback:
+
+```js
+describe('Array', function() {
+ describe('#indexOf()', function() {
+ // pending test below
+ it('should return -1 when the value is not present');
+ });
+});
+```
+
+Pending tests will be reported as such.
+
+## Exclusive Tests
+
+The exclusivity feature allows you to run *only* the specified suite or test-case
+ by appending `.only()` to the function. Here's an example of executing only a particular suite:
+
+```js
+describe('Array', function() {
+ describe.only('#indexOf()', function() {
+ // ...
+ });
+});
+```
+
+*Note*: All nested suites will still be executed.
+
+Here's an example of executing an individual test case:
+
+```js
+describe('Array', function() {
+ describe('#indexOf()', function() {
+ it.only('should return -1 unless present', function() {
+ // ...
+ });
+
+ it('should return the index when present', function() {
+ // ...
+ });
+ });
+});
+```
+
+Previous to v3.0.0, `.only()` used string matching to decide which tests to execute. As of v3.0.0, this is no longer the case. In v3.0.0 or newer, `.only()` can be used multiple times to define a subset of tests to run:
+
+```js
+describe('Array', function() {
+ describe('#indexOf()', function() {
+ it.only('should return -1 unless present', function() {
+ // this test will be run
+ });
+
+ it.only('should return the index when present', function() {
+ // this test will also be run
+ });
+
+ it('should return -1 if called with a non-Array context', function() {
+ // this test will not be run
+ });
+ });
+});
+```
+
+You may also choose multiple suites:
+
+```js
+describe('Array', function() {
+ describe.only('#indexOf()', function() {
+ it('should return -1 unless present', function() {
+ // this test will be run
+ });
+
+ it('should return the index when present', function() {
+ // this test will also be run
+ });
+ });
+
+ describe.only('#concat()', function () {
+ it('should return a new Array', function () {
+ // this test will also be run
+ });
+ });
+
+ describe('#slice()', function () {
+ it('should return a new Array', function () {
+ // this test will not be run
+ });
+ });
+});
+```
+
+But *tests will have precedence*:
+
+```js
+describe('Array', function() {
+ describe.only('#indexOf()', function() {
+ it.only('should return -1 unless present', function() {
+ // this test will be run
+ });
+
+ it('should return the index when present', function() {
+ // this test will not be run
+ });
+ });
+});
+```
+
+*Note*: Hooks, if present, will still be executed.
+
+> Be mindful not to commit usages of `.only()` to version control, unless you really mean it!
+
+## Inclusive Tests
+
+This feature is the inverse of `.only()`. By appending `.skip()`, you may tell Mocha to simply ignore these suite(s) and test case(s). Anything skipped will be marked as [pending](#pending-tests), and reported as such. Here's an example of skipping an entire suite:
+
+```js
+describe('Array', function() {
+ describe.skip('#indexOf()', function() {
+ // ...
+ });
+});
+```
+
+Or a specific test-case:
+
+```js
+describe('Array', function() {
+ describe('#indexOf()', function() {
+ it.skip('should return -1 unless present', function() {
+ // this test will not be run
+ });
+
+ it('should return the index when present', function() {
+ // this test will be run
+ });
+ });
+});
+```
+
+> *Best practice*: Use `.skip()` instead of commenting tests out.
+
+You may also skip *at runtime* using `this.skip()`. If a test needs an environment or configuration which cannot be detected beforehand, a runtime skip is appropriate. For example:
+
+```js
+it('should only test in the correct environment', function() {
+ if (/* check test environment */) {
+ // make assertions
+ } else {
+ this.skip();
+ }
+});
+```
+
+The above test will be reported as [pending](#pending-tests). It's also important to note that calling `this.skip()` will effectively *abort* the test.
+
+> *Best practice*: To avoid confusion, do not execute further instructions in a test or hook after calling `this.skip()`.
+
+Contrast the above test with the following code:
+
+```js
+it('should only test in the correct environment', function() {
+ if (/* check test environment */) {
+ // make assertions
+ } else {
+ // do nothing
+ }
+});
+```
+
+Because this test *does nothing*, it will be reported as *passing*.
+
+> *Best practice*: Don't do nothing! A test should make an assertion or use `this.skip()`.
+
+To skip *multiple* tests in this manner, use `this.skip()` in a "before" hook:
+
+```js
+before(function() {
+ if (/* check test environment */) {
+ // setup code
+ } else {
+ this.skip();
+ }
+});
+```
+
+> Before Mocha v3.0.0, `this.skip()` was not supported in asynchronous tests and hooks.
+
+## Retry Tests
+
+You can choose to retry failed tests up to a certain number of times. This feature is designed to handle end-to-end tests (functional tests/Selenium...) where resources cannot be easily mocked/stubbed. **It's not recommended to use this feature for unit tests**.
+
+This feature does re-run `beforeEach/afterEach` hooks but not `before/after` hooks.
+
+**NOTE**: Example below was written using Selenium webdriver (which [overwrites global Mocha hooks](https://github.com/SeleniumHQ/selenium/blob/c10e8a955883f004452cdde18096d70738397788/javascript/node/selenium-webdriver/testing/index.js) for `Promise` chain).
+
+```js
+describe('retries', function() {
+ // Retry all tests in this suite up to 4 times
+ this.retries(4);
+
+ beforeEach(function () {
+ browser.get('http://www.yahoo.com');
+ });
+
+ it('should succeed on the 3rd try', function () {
+ // Specify this test to only retry up to 2 times
+ this.retries(2);
+ expect($('.foo').isDisplayed()).to.eventually.be.true;
+ });
+});
+
+```
+
+## Dynamically Generating Tests
+
+Given Mocha's use of `Function.prototype.call` and function expressions to define suites and test cases, it's straightforward to generate your tests dynamically. No special syntax is required — plain ol' JavaScript can be used to achieve functionality similar to "parameterized" tests, which you may have seen in other frameworks.
+
+Take the following example:
+
+```js
+var assert = require('chai').assert;
+
+function add() {
+ return Array.prototype.slice.call(arguments).reduce(function(prev, curr) {
+ return prev + curr;
+ }, 0);
+}
+
+describe('add()', function() {
+ var tests = [
+ {args: [1, 2], expected: 3},
+ {args: [1, 2, 3], expected: 6},
+ {args: [1, 2, 3, 4], expected: 10}
+ ];
+
+ tests.forEach(function(test) {
+ it('correctly adds ' + test.args.length + ' args', function() {
+ var res = add.apply(null, test.args);
+ assert.equal(res, test.expected);
+ });
+ });
+});
+```
+
+The above code will produce a suite with three specs:
+
+```sh
+$ mocha
+
+ add()
+ ✓ correctly adds 2 args
+ ✓ correctly adds 3 args
+ ✓ correctly adds 4 args
+```
+
+
Test duration
+
+Many reporters will display test duration, as well as flagging tests that are slow, as shown here with the "spec" reporter:
+
+![test duration](images/reporter-spec-duration.png)
+
+To tweak what's considered "slow", you can use the `slow()` method:
+
+```js
+describe('something slow', function() {
+ this.slow(10000);
+
+ it('should take long enough for me to go make a sandwich', function() {
+ // ...
+ });
+});
+```
+
+
+## Timeouts
+
+### Suite-level
+
+Suite-level timeouts may be applied to entire test "suites", or disabled via `this.timeout(0)`. This will be inherited by all nested suites and test-cases that do not override the value.
+
+```js
+describe('a suite of tests', function() {
+ this.timeout(500);
+
+ it('should take less than 500ms', function(done){
+ setTimeout(done, 300);
+ });
+
+ it('should take less than 500ms as well', function(done){
+ setTimeout(done, 250);
+ });
+})
+```
+
+### Test-level
+
+Test-specific timeouts may also be applied, or the use of `this.timeout(0)` to disable timeouts all together:
+
+```js
+it('should take less than 500ms', function(done){
+ this.timeout(500);
+ setTimeout(done, 300);
+});
+```
+
+### Hook-level
+
+Hook-level timeouts may also be applied:
+
+```js
+describe('a suite of tests', function() {
+ beforeEach(function(done) {
+ this.timeout(3000); // A very long environment setup.
+ setTimeout(done, 2500);
+ });
+});
+```
+
+Again, use `this.timeout(0)` to disable the timeout for a hook.
+
+> In v3.0.0 or newer, a parameter passed to `this.timeout()` greater than the [maximum delay value](https://developer.mozilla.org/docs/Web/API/WindowTimers/setTimeout#Maximum_delay_value) will cause the timeout to be disabled.
+
+## Diffs
+
+Mocha supports the `err.expected` and `err.actual` properties of any thrown `AssertionError`s from an assertion library. Mocha will attempt to display the difference between what was expected, and what the assertion actually saw. Here's an example of a "string" diff:
+
+![string diffs](images/reporter-string-diffs.png)
+
+## Usage
+
+```
+ Usage: mocha [debug] [options] [files]
+
+
+ Options:
+
+ -V, --version output the version number
+ -A, --async-only force all tests to take a callback (async) or return a promise
+ -c, --colors force enabling of colors
+ -C, --no-colors force disabling of colors
+ -G, --growl enable growl notification support
+ -O, --reporter-options reporter-specific options
+ -R, --reporter specify the reporter to use
+ -S, --sort sort test files
+ -b, --bail bail after first test failure
+ -d, --debug enable node's debugger, synonym for node --debug
+ -g, --grep only run tests matching
+ -f, --fgrep only run tests containing
+ -gc, --expose-gc expose gc extension
+ -i, --invert inverts --grep and --fgrep matches
+ -r, --require require the given module
+ -s, --slow "slow" test threshold in milliseconds [75]
+ -t, --timeout set test-case timeout in milliseconds [2000]
+ -u, --ui specify user-interface (bdd|tdd|qunit|exports)
+ -w, --watch watch files for changes
+ --check-leaks check for global variable leaks
+ --full-trace display the full stack trace
+ --compilers :,... use the given module(s) to compile files
+ --debug-brk enable node's debugger breaking on the first line
+ --globals allow the given comma-delimited global [names]
+ --es_staging enable all staged features
+ --harmony<_classes,_generators,...> all node --harmony* flags are available
+ --preserve-symlinks Instructs the module loader to preserve symbolic links when resolving and caching modules
+ --icu-data-dir include ICU data
+ --inline-diffs display actual/expected differences inline within each string
+ --inspect activate devtools in chrome
+ --inspect-brk activate devtools in chrome and break on the first line
+ --interfaces display available interfaces
+ --no-deprecation silence deprecation warnings
+ --exit force shutdown of the event loop after test run: mocha will call process.exit
+ --no-timeouts disables timeouts, given implicitly with --debug
+ --no-warnings silence all node process warnings
+ --opts specify opts path
+ --perf-basic-prof enable perf linux profiler (basic support)
+ --napi-modules enable experimental NAPI modules
+ --prof log statistical profiling information
+ --log-timer-events Time events including external callbacks
+ --recursive include sub directories
+ --reporters display available reporters
+ --retries set numbers of time to retry a failed test case
+ --throw-deprecation throw an exception anytime a deprecated function is used
+ --trace trace function calls
+ --trace-deprecation show stack traces on deprecations
+ --trace-warnings show stack traces on node process warnings
+ --use_strict enforce strict mode
+ --watch-extensions ,... additional extensions to monitor with --watch
+ --delay wait for async suite definition
+ --allow-uncaught enable uncaught errors to propagate
+ --forbid-only causes test marked with only to fail the suite
+ --forbid-pending causes pending tests and test marked with skip to fail the suite
+ -h, --help output usage information
+
+
+ Commands:
+
+ init initialize a client-side mocha setup at
+```
+
+### `-w, --watch`
+
+Executes tests on changes to JavaScript in the CWD, and once initially.
+
+### `--exit` / `--no-exit`
+
+*Updated in Mocha v4.0.0*
+
+*Prior to* version v4.0.0, *by default*, Mocha would force its own process to exit once it was finished executing all tests. This behavior enables a set of potential problems; it's indicative of tests (or fixtures, harnesses, code under test, etc.) which don't clean up after themselves properly. Ultimately, "dirty" tests can (but not always) lead to *false positive* or *false negative* results.
+
+"Hanging" most often manifests itself if a server is still listening on a port, or a socket is still open, etc. It can also be something like a runaway `setInterval()`, or even an errant `Promise` that never fulfilled.
+
+The *default behavior* in v4.0.0 is `--no-exit`, where previously it was `--exit`.
+
+**The easiest way to "fix" the issue is to simply pass `--exit` to the Mocha process.** It *can* be time-consuming to debug--because it's not always obvious where the problem is--but it *is* recommended to do so.
+
+To ensure your tests aren't leaving messes around, here are some ideas to get started:
+
+- See the [Node.js guide to debugging](https://nodejs.org/en/docs/inspector/)
+- Use the new [`async_hooks`](https://github.com/nodejs/node/blob/master/doc/api/async_hooks.md) API ([example](https://git.io/vdlNM))
+- Try something like [why-is-node-running](https://npm.im/why-is-node-running)
+- Use [`.only`](#exclusive-tests) until you find the test that causes Mocha to hang
+
+### `--compilers`
+
+*Updated in Mocha v4.0.0*
+
+**`--compilers` is deprecated as of Mocha v4.0.0. See [further explanation and workarounds](https://github.com/mochajs/mocha/wiki/compilers-deprecation).**
+
+CoffeeScript is no longer supported out of the box. CS and similar transpilers
+may be used by mapping the file extensions (for use with `--watch`) and the module
+name. For example `--compilers coffee:coffee-script` with CoffeeScript 1.6- or
+`--compilers coffee:coffee-script/register` with CoffeeScript 1.7+.
+
+#### About Babel
+
+If your ES6 modules have extension `.js`, you can `npm install --save-dev babel-register` and use `mocha --require babel-register`; `--compilers` is only necessary if you need to specify a file extension.
+
+### `-b, --bail`
+
+Only interested in the first exception? use `--bail`!
+
+### `-d, --debug`
+
+Enables node's debugger support, this executes your script(s) with `node debug ` allowing you to step through code and break with the `debugger` statement. Note the difference between `mocha debug` and `mocha --debug`: `mocha debug` will fire up node's built-in debug client, `mocha --debug` will allow you to use a different interface — such as the Blink Developer Tools.
+
+### `--globals `
+
+Accepts a comma-delimited list of accepted global variable names. For example, suppose your app deliberately exposes a global named `app` and `YUI`, you may want to add `--globals app,YUI`. It also accepts wildcards. You could do `--globals '*bar'` and it would match `foobar`, `barbar`, etc. You can also simply pass in `'*'` to ignore all globals.
+
+By using this option in conjunction with `--check-leaks`, you can specify a whitelist of known global variables that you would expect to leak into global scope.
+
+### `--check-leaks`
+
+Use this option to have Mocha check for global variables that are leaked while running tests. Specify globals that are acceptable via the `--globals` option (for example: `--check-leaks --globals jQuery,MyLib`).
+
+### `-r, --require `
+
+The `--require` option is useful for libraries such as [should.js](https://github.com/shouldjs/should.js), so you may simply `--require should` instead of manually invoking `require('should')` within each test file. Note that this works well for `should` as it augments `Object.prototype`, however if you wish to access a module's exports you will have to require them, for example `var should = require('should')`. Furthermore, it can be used with relative paths, e.g. `--require ./test/helper.js`
+
+### `-u, --ui `
+
+The `--ui` option lets you specify the interface to use, defaulting to "bdd".
+
+### `-R, --reporter `
+
+The `--reporter` option allows you to specify the reporter that will be used, defaulting to "spec". This flag may also be used to utilize third-party reporters. For example if you `npm install mocha-lcov-reporter` you may then do `--reporter mocha-lcov-reporter`.
+
+### `-t, --timeout `
+
+Specifies the test-case timeout, defaulting to 2 seconds. To override you may pass the timeout in milliseconds, or a value with the `s` suffix, ex: `--timeout 2s` or `--timeout 2000` would be equivalent.
+
+### `-s, --slow `
+
+Specify the "slow" test threshold, defaulting to 75ms. Mocha uses this to highlight test-cases that are taking too long.
+
+### `-g, --grep `
+
+The `--grep` option when specified will trigger mocha to only run tests matching the given `pattern` which is internally compiled to a `RegExp`.
+
+Suppose, for example, you have "api" related tests, as well as "app" related tests, as shown in the following snippet; One could use `--grep api` or `--grep app` to run one or the other. The same goes for any other part of a suite or test-case title, `--grep users` would be valid as well, or even `--grep GET`.
+
+```js
+describe('api', function() {
+ describe('GET /api/users', function() {
+ it('respond with an array of users', function() {
+ // ...
+ });
+ });
+});
+
+describe('app', function() {
+ describe('GET /users', function() {
+ it('respond with an array of users', function() {
+ // ...
+ });
+ });
+});
+```
+
+## Interfaces
+
+Mocha's "interface" system allows developers to choose their style of DSL. Mocha has **BDD**, **TDD**, **Exports**, **QUnit** and **Require**-style interfaces.
+
+### BDD
+
+The **BDD** interface provides `describe()`, `context()`, `it()`, `specify()`, `before()`, `after()`, `beforeEach()`, and `afterEach()`.
+
+`context()` is just an alias for `describe()`, and behaves the same way; it just provides a way to keep tests easier to read and organized. Similarly, `specify()` is an alias for `it()`.
+
+> All of the previous examples were written using the **BDD** interface.
+
+```js
+ describe('Array', function() {
+ before(function() {
+ // ...
+ });
+
+ describe('#indexOf()', function() {
+ context('when not present', function() {
+ it('should not throw an error', function() {
+ (function() {
+ [1,2,3].indexOf(4);
+ }).should.not.throw();
+ });
+ it('should return -1', function() {
+ [1,2,3].indexOf(4).should.equal(-1);
+ });
+ });
+ context('when present', function() {
+ it('should return the index where the element first appears in the array', function() {
+ [1,2,3].indexOf(3).should.equal(2);
+ });
+ });
+ });
+ });
+```
+
+### TDD
+
+The **TDD** interface provides `suite()`, `test()`, `suiteSetup()`, `suiteTeardown()`, `setup()`, and `teardown()`:
+
+```js
+suite('Array', function() {
+ setup(function() {
+ // ...
+ });
+
+ suite('#indexOf()', function() {
+ test('should return -1 when not present', function() {
+ assert.equal(-1, [1,2,3].indexOf(4));
+ });
+ });
+});
+```
+
+### Exports
+
+The **Exports** interface is much like Mocha's predecessor [expresso](https://github.com/tj/expresso). The keys `before`, `after`, `beforeEach`, and `afterEach` are special-cased, object values are suites, and function values are test-cases:
+
+```js
+module.exports = {
+ before: function() {
+ // ...
+ },
+
+ 'Array': {
+ '#indexOf()': {
+ 'should return -1 when not present': function() {
+ [1,2,3].indexOf(4).should.equal(-1);
+ }
+ }
+ }
+};
+```
+
+### QUnit
+
+The [QUnit](http://qunitjs.com)-inspired interface matches the "flat" look of QUnit, where the test suite title is simply defined before the test-cases. Like TDD, it uses `suite()` and `test()`, but resembling BDD, it also contains `before()`, `after()`, `beforeEach()`, and `afterEach()`.
+
+```js
+function ok(expr, msg) {
+ if (!expr) throw new Error(msg);
+}
+
+suite('Array');
+
+test('#length', function() {
+ var arr = [1,2,3];
+ ok(arr.length == 3);
+});
+
+test('#indexOf()', function() {
+ var arr = [1,2,3];
+ ok(arr.indexOf(1) == 0);
+ ok(arr.indexOf(2) == 1);
+ ok(arr.indexOf(3) == 2);
+});
+
+suite('String');
+
+test('#length', function() {
+ ok('foo'.length == 3);
+});
+```
+
+### Require
+
+The `require` interface allows you to require the `describe` and friend words directly using `require` and call them whatever you want. This interface is also useful if you want to avoid global variables in your tests.
+
+*Note*: The `require` interface cannot be run via the `node` executable, and must be run via `mocha`.
+
+```js
+var testCase = require('mocha').describe;
+var pre = require('mocha').before;
+var assertions = require('mocha').it;
+var assert = require('chai').assert;
+
+testCase('Array', function() {
+ pre(function() {
+ // ...
+ });
+
+ testCase('#indexOf()', function() {
+ assertions('should return -1 when not present', function() {
+ assert.equal([1,2,3].indexOf(4), -1);
+ });
+ });
+});
+```
+
+## Reporters
+
+Mocha reporters adjust to the terminal window, and always disable ANSI-escape coloring when the stdio streams are not associated with a TTY.
+
+### Spec
+
+This is the default reporter. The "spec" reporter outputs a hierarchical view nested just as the test cases are.
+
+![spec reporter](images/reporter-spec.png)
+![spec reporter with failure](images/reporter-spec-fail.png)
+
+### Dot Matrix
+
+The dot matrix (or "dot") reporter is simply a series of characters which represent test cases. Failures highlight in red exclamation marks (`!`), pending tests with a blue comma (`,`), and slow tests as yellow. Good if you prefer minimal output.
+
+![dot matrix reporter](images/reporter-dot.png)
+
+### Nyan
+
+The "nyan" reporter is exactly what you might expect:
+
+![js nyan cat reporter](images/reporter-nyan.png)
+
+### TAP
+
+The TAP reporter emits lines for a [Test-Anything-Protocol](http://en.wikipedia.org/wiki/Test_Anything_Protocol) consumer.
+
+![test anything protocol](images/reporter-tap.png)
+
+### Landing Strip
+
+The Landing Strip (`landing`) reporter is a gimmicky test reporter simulating a plane landing :) unicode ftw
+
+![landing strip plane reporter](images/reporter-landing.png)
+![landing strip with failure](images/reporter-landing-fail.png)
+
+### List
+
+The "list" reporter outputs a simple specifications list as test cases pass or fail, outputting the failure details at the bottom of the output.
+
+![list reporter](images/reporter-list.png)
+
+### Progress
+
+The "progress" reporter implements a simple progress-bar:
+
+![progress bar](images/reporter-progress.png)
+
+### JSON
+
+The "JSON" reporter outputs a single large JSON object when the tests have completed (failures or not).
+
+![json reporter](images/reporter-json.png)
+
+### JSON Stream
+
+The "JSON stream" reporter outputs newline-delimited JSON "events" as they occur, beginning with a "start" event, followed by test passes or failures, and then the final "end" event.
+
+![json stream reporter](images/reporter-json-stream.png)
+
+### Min
+
+The "min" reporter displays the summary only, while still outputting errors on failure. This reporter works great with `--watch` as it clears the terminal in order to keep your test summary at the top.
+
+![min reporter](images/reporter-min.png)
+
+### Doc
+
+The "doc" reporter outputs a hierarchical HTML body representation of your tests. Wrap it with a header, footer, and some styling, then you have some fantastic documentation!
+
+![doc reporter](images/reporter-doc.png)
+
+For example, suppose you have the following JavaScript:
+
+```js
+describe('Array', function() {
+ describe('#indexOf()', function() {
+ it('should return -1 when the value is not present', function() {
+ [1,2,3].indexOf(5).should.equal(-1);
+ [1,2,3].indexOf(0).should.equal(-1);
+ });
+ });
+});
+```
+
+The command `mocha --reporter doc array` would yield:
+
+```html
+
+
+
+```
+
+The SuperAgent request library [test documentation](http://visionmedia.github.io/superagent/docs/test.html) was generated with Mocha's doc reporter using this simple make target:
+
+```makefile
+test-docs:
+ $(MAKE) test REPORTER=doc \
+ | cat docs/head.html - docs/tail.html \
+ > docs/test.html
+```
+
+View the entire [Makefile](https://github.com/visionmedia/superagent/blob/master/Makefile) for reference.
+
+### Markdown
+
+The "markdown" reporter generates a markdown TOC and body for your test suite. This is great if you want to use the tests as documentation within a Github wiki page, or a markdown file in the repository that Github can render. For example here is the Connect [test output](https://github.com/senchalabs/connect/blob/90a725343c2945aaee637e799b1cd11e065b2bff/tests.md).
+
+### HTML
+
+The "HTML" reporter is currently the only browser reporter supported by Mocha, and it looks like this:
+
+![HTML test reporter](images/reporter-html.png)
+
+### Undocumented Reporters
+
+The "XUnit" reporter is also available. By default, it will output to the console. To write directly to a file, use `--reporter-options output=filename.xml`.
+
+### Third party reporters
+
+Mocha allows you to define custom third-party reporters. For more information see the [wiki](https://github.com/mochajs/mocha/wiki/Third-party-reporters). An example is the [TeamCity reporter](https://github.com/travisjeffery/mocha-teamcity-reporter).
+
+## Running Mocha in the Browser
+
+Mocha runs in the browser. Every release of Mocha will have new builds of `./mocha.js` and `./mocha.css` for use in the browser.
+
+### Browser-specific methods
+
+ The following method(s) *only* function in a browser context:
+
+ `mocha.allowUncaught()` : If called, uncaught errors will not be absorbed by the error handler.
+
+A typical setup might look something like the following, where we call `mocha.setup('bdd')` to use the **BDD** interface before loading the test scripts, running them `onload` with `mocha.run()`.
+
+```html
+
+
+
+ Mocha Tests
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Grep
+
+The browser may use the `--grep` as functionality. Append a query-string to your URL: `?grep=api`.
+
+### Browser Configuration
+
+Mocha options can be set via `mocha.setup()`. Examples:
+
+```js
+// Use "tdd" interface. This is a shortcut to setting the interface;
+// any other options must be passed via an object.
+mocha.setup('tdd');
+
+// This is equivalent to the above.
+mocha.setup({
+ ui: 'tdd'
+});
+
+// Use "tdd" interface, ignore leaks, and force all tests to be asynchronous
+mocha.setup({
+ ui: 'tdd',
+ ignoreLeaks: true,
+ asyncOnly: true
+});
+```
+
+### Browser-specific Option(s)
+
+The following option(s) *only* function in a browser context:
+
+`noHighlighting`: If set to `true`, do not attempt to use syntax highlighting on output test code.
+
+## `mocha.opts`
+
+Back on the server, Mocha will attempt to load `./test/mocha.opts` as a configuration file of sorts. The lines in this file are combined with any command-line arguments. The command-line arguments take precedence. For example, suppose you have the following `mocha.opts` file:
+
+```
+ --require should
+ --reporter dot
+ --ui bdd
+```
+
+This will default the reporter to `dot`, require the `should` library, and use `bdd` as the interface. With this, you may then invoke `mocha` with additional arguments, here enabling [Growl](http://growl.info) support, and changing the reporter to `list`:
+
+```sh
+$ mocha --reporter list --growl
+```
+
+## The `test/` Directory
+
+By default, `mocha` looks for the glob `./test/*.js` and `./test/*.coffee`, so you may want to put your tests in `test/` folder.
+
+## Editor Plugins
+
+The following editor-related packages are available:
+
+### Mocha Sidebar (VS Code)
+
+[Mocha sidebar](https://marketplace.visualstudio.com/items?itemName=maty.vscode-mocha-sidebar) is the most complete mocha extension for vs code.
+
+#### Features
+
+* [x] see all tests in VS Code sidebar menu
+* [x] run & debug tests for each level hierarchy from all tests to a single test (and each describe of course)
+* [x] auto run tests on file save
+* [x] see tests results directly in the code editor
+
+### TextMate
+
+The Mocha TextMate bundle includes snippets to make writing tests quicker and more enjoyable. To install the bundle, clone a copy of the [Mocha repo](https://github.com/mochajs/mocha), and run:
+
+```sh
+$ make tm
+```
+
+### JetBrains
+
+[JetBrains](http://jetbrains.com) provides a [NodeJS plugin](http://www.jetbrains.com/idea/features/nodejs.html) for its suite of IDEs (IntelliJ IDEA, WebStorm, etc.), which contains a Mocha test runner, among other things.
+
+![JetBrains Mocha Runner Plugin in Action](images/jetbrains-plugin.png)
+
+The plugin is titled **NodeJS**, and can be installed via **Preferences** > **Plugins**, assuming your license allows it.
+
+### Wallaby.js
+
+[Wallaby.js](http://wallabyjs.com) is a continuous testing tool that enables real-time code coverage for Mocha with any assertion library in JetBrains IDEs (IntelliJ IDEA, WebStorm, etc.) and Visual Studio for both browser and node.js projects.
+
+![Wallaby.js in Action](images/wallaby.png)
+
+### Emacs
+[Emacs](https://www.gnu.org/software/emacs/) support for running Mocha tests is available via a 3rd party package [mocha.el](https://github.com/scottaj/mocha.el). The package is available on MELPA, and can be installed via `M-x package-install mocha`.
+
+![Emacs Mocha Runner in Action](images/emacs.png)
+
+## Examples
+
+Real live example code:
+
+- [Express](https://github.com/visionmedia/express/tree/master/test)
+- [Connect](https://github.com/senchalabs/connect/tree/master/test)
+- [SuperAgent](https://github.com/visionmedia/superagent/tree/master/test/node)
+- [WebSocket.io](https://github.com/LearnBoost/websocket.io/tree/master/test)
+- [Mocha](https://github.com/mochajs/mocha/tree/master/test)
+
+## Testing Mocha
+
+To run Mocha's tests, you will need GNU Make or compatible; Cygwin should work.
+
+```sh
+$ cd /path/to/mocha
+$ npm install
+$ npm test
+```
+
+To use a different reporter:
+
+```sh
+$ REPORTER=nyan npm test
+```
+
+## More Information
+
+In addition to chatting with us on [Gitter](https://gitter.im/mochajs/mocha), for additional information such as using spies, mocking, and shared behaviours be sure to check out the [Mocha Wiki](https://github.com/mochajs/mocha/wiki) on GitHub. For discussions join the [Google Group](http://groups.google.com/group/mochajs). For a running example of Mocha, view [example/tests.html](example/tests.html). For the JavaScript API, view the [source](https://github.com/mochajs/mocha/blob/master/lib/mocha.js#L51).
diff --git a/docs/js/avatars.js b/docs/js/avatars.js
new file mode 100644
index 0000000000..1bf3e690be
--- /dev/null
+++ b/docs/js/avatars.js
@@ -0,0 +1,15 @@
+(function () {
+ 'use strict';
+ // dumb thing that helps with animation of avatars
+ var avatars = window.avatars = function (type) {
+ return function avatarLoaded () {
+ avatars[type] = typeof avatars[type] === 'number' ? avatars[type] + 1 : 1;
+ if (avatars[type] === 30) {
+ document.getElementById(type).classList.add('onload');
+ }
+ };
+ };
+
+ avatars.backerLoaded = avatars('_backers');
+ avatars.sponsorLoaded = avatars('_sponsors');
+}());
diff --git a/docs/js/ga.js b/docs/js/ga.js
new file mode 100644
index 0000000000..6e3ff1949b
--- /dev/null
+++ b/docs/js/ga.js
@@ -0,0 +1,7 @@
+(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+ga('create', 'UA-65024936-1', 'auto');
+ga('send', 'pageview');
diff --git a/package.json b/package.json
index d7d2055d30..1fcbd718ed 100644
--- a/package.json
+++ b/package.json
@@ -303,7 +303,10 @@
"lint": "eslint . bin/*",
"test": "make clean && make test",
"prepublishOnly": "npm test && make clean && make mocha.js",
- "coveralls": "nyc report --reporter=text-lcov | coveralls"
+ "coveralls": "nyc report --reporter=text-lcov | coveralls",
+ "prebuildDocs": "node scripts/pre-build-docs.js",
+ "buildDocs": "bundle exec jekyll build --source docs --destination docs/_site --layouts docs/_layouts --safe --drafts",
+ "serveDocs": "bundle exec jekyll serve --config docs/_config.yml --safe --drafts --watch"
},
"dependencies": {
"browser-stdout": "1.3.0",
@@ -340,6 +343,7 @@
"karma-mocha-reporter": "^2.2.4",
"karma-phantomjs-launcher": "^1.0.4",
"karma-sauce-launcher": "^1.2.0",
+ "markdown-toc": "^1.2.0",
"nyc": "^11.2.1",
"rimraf": "^2.5.2",
"through2": "^2.0.1",
diff --git a/scripts/.eslintrc.yaml b/scripts/.eslintrc.yaml
new file mode 100644
index 0000000000..1ddd632e1c
--- /dev/null
+++ b/scripts/.eslintrc.yaml
@@ -0,0 +1,2 @@
+parserOptions:
+ ecmaVersion: 2017
diff --git a/scripts/pre-build-docs.js b/scripts/pre-build-docs.js
new file mode 100755
index 0000000000..e4e661602e
--- /dev/null
+++ b/scripts/pre-build-docs.js
@@ -0,0 +1,31 @@
+#!/usr/bin/env node
+
+/**
+ * The CLI included with markdown-toc doesn't support `bullets`
+ * and `maxdepth` options, so that's why this exists.
+ */
+
+'use strict';
+
+const toc = require('markdown-toc');
+const utils = require('markdown-toc/lib/utils');
+const fs = require('fs');
+const path = require('path');
+
+const docsFilepath = path.join(__dirname, '..', 'docs', 'index.md');
+
+console.log('Updating TOC...');
+
+fs.createReadStream(docsFilepath)
+ .on('error', err => {
+ console.log(err);
+ process.exit(1);
+ })
+ .on('close', () => {
+ console.log('Done.');
+ })
+ .pipe(utils.concat(
+ input => fs.writeFileSync(docsFilepath, toc.insert(String(input), {
+ bullets: '-',
+ maxdepth: 2
+ }))));