CVE-2020-28271: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution') (CWE-1321)
value: Prototype pollution vulnerability in 'deephas' versions 1.0.0 through 1.0.5 allows attacker to cause a denial of service and may lead to remote code execution.
CWE description: The product receives input from an upstream component that specifies attributes that are to be initialized or updated in an object, but it does not properly control modifications of attributes of the object prototype.
CVSS v3 base score: 9.8
Published: 2020-11-12T18:15Z
Repository: https://github.com/sharpred/deepHas
Language: JavaScript
Files changed: .jshintignore, .jshintrc, .project, .settings/com.eclipsesource.jshint.ui.prefs, .settings/org.eclipse.core.resources.prefs, .travis.yml, README.md, deepHas.js, node_modules/should/.eslintrc, node_modules/should/.npmignore, node_modules/should/.travis.yml, node_modules/should/.zuul.yml, node_modules/should/CONTRIBUTING.md, node_modules/should/History.md, node_modules/should/LICENSE, node_modules/should/Readme.md, node_modules/should/as-function.js, node_modules/should/bower.json, node_modules/should/browser-entry.js, node_modules/should/gulpfile.js, node_modules/should/index.js, node_modules/should/lib/assertion-error.js, node_modules/should/lib/assertion.js, node_modules/should/lib/config.js, node_modules/should/lib/ext/_assert.js, node_modules/should/lib/ext/assert.js, node_modules/should/lib/ext/bool.js, node_modules/should/lib/ext/chain.js, node_modules/should/lib/ext/contain.js, node_modules/should/lib/ext/eql.js, node_modules/should/lib/ext/error.js, node_modules/should/lib/ext/match.js, node_modules/should/lib/ext/number.js, node_modules/should/lib/ext/promise.js, node_modules/should/lib/ext/property.js, node_modules/should/lib/ext/string.js, node_modules/should/lib/ext/type.js, node_modules/should/lib/should.js, node_modules/should/lib/util.js, node_modules/should/node_modules/should-equal/.eslintrc, node_modules/should/node_modules/should-equal/.npmignore, node_modules/should/node_modules/should-equal/.travis.yml, node_modules/should/node_modules/should-equal/LICENSE, node_modules/should/node_modules/should-equal/README.md, node_modules/should/node_modules/should-equal/format.js, node_modules/should/node_modules/should-equal/index.js, node_modules/should/node_modules/should-equal/package.json, node_modules/should/node_modules/should-equal/test.js, node_modules/should/node_modules/should-format/.eslintrc, node_modules/should/node_modules/should-format/.npmignore, node_modules/should/node_modules/should-format/.travis.yml, node_modules/should/node_modules/should-format/LICENSE, node_modules/should/node_modules/should-format/README.md, node_modules/should/node_modules/should-format/index.js, node_modules/should/node_modules/should-format/package.json, node_modules/should/node_modules/should-format/tests/browser/index.html, node_modules/should/node_modules/should-format/tests/browser/mocha.css, node_modules/should/node_modules/should-format/tests/browser/mocha.js, node_modules/should/node_modules/should-format/tests/browser/tests.js, node_modules/should/node_modules/should-format/tests/test.js, node_modules/should/node_modules/should-format/util.js, node_modules/should/node_modules/should-type/.npmignore, node_modules/should/node_modules/should-type/LICENSE, node_modules/should/node_modules/should-type/README.md, node_modules/should/node_modules/should-type/index.js, node_modules/should/node_modules/should-type/package.json, node_modules/should/node_modules/should-type/types.js, node_modules/should/package.json, node_modules/should/should.js, node_modules/should/should.min.js, package-lock.json, package.json, poc.js, runTests.sh, tests/testExports.js, tests/testGet.js, tests/testHas.js, tests/testSet.js, tests/testVulnerability.js
Commit date: 2020-10-27 09:44:05 +0000
Commit message: fix vulnerability reported by whitesource software

Diff: diff --git a/.jshintignore b/.jshintignore
new file mode 100644
index 0000000..d3745c1
--- /dev/null
+++ b/.jshintignore
@@ -0,0 +1 @@
+tests/**
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..86a9aa7
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,63 @@
+{
+    "bitwise": true,
+    "globals": {
+        "Alloy": false,
+        "_": false,
+        "L": false,
+        "Ti": false,
+        "Titanium": false,
+        "require": false,
+        "module": false,
+        "$": false,
+        "Backbone": false,
+        "exports": false,
+        "L": false,
+        "WPATH": false,
+        "OS_ANDROID": false,
+        "OS_IOS": false,
+        "ENV_DEV": false,
+        "ENV_TEST": false,
+        "clearInterval": false,
+        "setInterval": false,
+        "clearTimeout": false,
+        "setTimeout": false,
+        "console": false,
+        "process": false
+    },
+    "camelcase": false,
+    "eqeqeq": true,
+    "indent": 4,
+    "unused": true,
+    "undef" : true,
+    "curly" : true,
+    "immed" : true,
+    "undef": true,
+    "latedef": true,
+    "trailing": true,
+    "newcap": false,
+    "sub": true,
+    "shadow": false,
+    "laxcomma": false,
+    "maxcomplexity": 10,
+    "predef": [
+        "require",
+        "module",
+        "$",
+        "Ti",
+        "_",
+        "Backbone",
+        "Titanium",
+        "Alloy",
+        "exports",
+        "L",
+        "WPATH",
+        "OS_ANDROID",
+        "OS_IOS",
+        "ENV_DEV",
+        "ENV_TEST",
+        "setTimeout",
+        "console",
+        "process",
+        "alert"
+    ]
+}
\ No newline at end of file
diff --git a/.project b/.project
new file mode 100644
index 0000000..4af23de
--- /dev/null
+++ b/.project
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>deepHas</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+	</buildSpec>
+	<natures>
+		<nature>com.aptana.projects.webnature</nature>
+	</natures>
+</projectDescription>
diff --git a/.settings/com.eclipsesource.jshint.ui.prefs b/.settings/com.eclipsesource.jshint.ui.prefs
new file mode 100644
index 0000000..752b66f
--- /dev/null
+++ b/.settings/com.eclipsesource.jshint.ui.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+included=//deepHas.js
+projectSpecificOptions=true
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..879c68e
--- /dev/null
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/.jshintrc=UTF-8
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b84f1aa
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,13 @@
+language: node_js
+node_js:
+- node
+install: npm install
+deploy:
+  provider: npm
+  email: paul.ryan@stepupsoftware.co.uk
+  api_key:
+    secure: Um2/kvcWM2cEVPwq2kGCACk2VMoPZJb3W0KNBzFwPTDxUs4D96erb0mh/1dv7Jpz8qQpw2Ldrk873N96mEC2HRA8z13EuslpMm7XXPHCzLY2Sx5XFgYrDoec9Wn2A3wVuDLsRd79m/E+MZyBu5+qbfk8JqSs2x43IqFU/eBKgeZn8mnI1hoHFBfPeJ70hzscoYj87PbrHc0YyVfQpXZCB3vKkYXmeBGcQIkloQhSr7z2TzH+IlXWDgDBxeASb6k+aTKypaRC/sglmFme0O7oWAmkC0MIoXkO1rm9+MnAc9kYDe2pUBjgFuQRGDQD51jLobanqrsgosbtHeNB25ALJTrFR1O6GWR1Pmw1gdJvAfMGx2i4ofpsX8pSV2ocJwxLx6Q8d7f9wTRp4E0oFNdG8YGbY9fRV7d4Bk4brWi/Yq3XAjDqWCc/JGoNI20nJe2TScSdh33qHvyMGSioTMDbFVmeFNA4SADVgPxg59pFs6f+BKoJ5pwOSNP612GsW2yMuGvNY4AzZoARqFsKzPgtE2MZDC9/OVPFXnKFsS1oNF10EfsDd1EYZlrS63jsnpeYFzsU3g+zO/CWCiUNJBA1/BqpN8GzHfSBXdgZP1qpx5zMZfaP699B/Vf0vJS3wRN9pwfz4lvXU6MYwJ7WZgAvYwPLWYLfRJc+dmC3HP1MWPE=
+  on:
+    tags: true
+    repo: sharpred/deepHas
+    branch: master
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..26165e6
--- /dev/null
+++ b/README.md
@@ -0,0 +1,26 @@
+![Build Status](https://travis-ci.org/sharpred/deepHas.svg?branch=master)
+# deepHas
+
+test for existence of nested object key and optionally return that key
+
+##Installation
+npm install deephas
+
+or just drop deepHas.js into your project.
+
+##Usage
+
+`dh = require("deepHas");\n`
+`var obj = {"some": {"nested": {"property":""your value here"}}};`
+
+### dh.has(obj, 'some.nested.property')
+
+Returns true or false if 'some.nested.property' exists or not.
+
+### dh.get(obj, 'some.nested.property')
+
+Returns the value or undefined if it does not exist.
+
+### dh.set(obj, 'some.nested.newproperty', "your value here")
+
+Adds a new property or object.
diff --git a/deepHas.js b/deepHas.js
new file mode 100644
index 0000000..369546b
--- /dev/null
+++ b/deepHas.js
@@ -0,0 +1,113 @@
+var indexFalse,
+    indexTrue,
+    indexer,
+    reduce,
+    add,
+    has,
+    get,
+    set;
+
+function indexer(set) {
+    return function (obj, i) {
+        "use strict";
+        try {
+            if (obj && i && obj.hasOwnProperty(i)) {
+                return obj[i];
+            } else if (obj && i && set) {
+                obj[i] = {};
+                return obj[i];
+            }
+            return;
+        } catch (ex) {
+            console.error(ex);
+            return;
+        }
+    };
+}
+
+indexTrue = indexer(true);
+indexFalse = indexer(false);
+
+function reduce(obj, str) {
+    "use strict";
+    try {
+        if (typeof str !== "string") {
+            return;
+        }
+        if (typeof obj !== "object") {
+            return;
+        }
+        return str.split('.').reduce(indexFalse, obj);
+
+    } catch (ex) {
+        console.error(ex);
+        return;
+    }
+
+}
+
+function add(obj, str, val) {
+    "use strict";
+    try {
+        if (typeof str !== "string") {
+            return;
+        }
+        if (str.indexOf('__proto__') != -1) {
+            throw "cannot modify prototype property";
+        }
+        if (typeof obj !== "object") {
+            return;
+        }
+        if (!val) {
+            return;
+        }
+        var items = str.split('.');
+        console.log(str);
+        var initial = items.slice(0, items.length - 1);
+        var last = items.slice(items.length - 1);
+        var test = initial.reduce(indexTrue, obj);
+        test[last] = val;
+
+    } catch (ex) {
+        console.error(ex);
+        return;
+    }
+}
+
+function has(target, path) {
+    "use strict";
+    try {
+        var test = reduce(target, path);
+        if (typeof test !== "undefined") {
+            return true;
+        }
+        return false;
+    } catch (ex) {
+        console.error(ex);
+        return;
+    }
+}
+
+function get(target, path) {
+    "use strict";
+    try {
+        return reduce(target, path);
+    } catch (ex) {
+        console.error(ex);
+        return;
+    }
+}
+
+function set(target, path, val) {
+    "use strict";
+    try {
+        return add(target, path, val);
+    } catch (ex) {
+        console.error(ex);
+        return;
+    }
+}
+
+exports.has = has;
+exports.get = get;
+exports.set = set;
diff --git a/node_modules/should/.eslintrc b/node_modules/should/.eslintrc
new file mode 100644
index 0000000..142881f
--- /dev/null
+++ b/node_modules/should/.eslintrc
@@ -0,0 +1,18 @@
+{
+  "extends": "eslint",
+  "env": {
+    "node": true,
+    "browser": true,
+    "mocha": true,
+    "es6": true
+  },
+  "rules": {
+    "valid-jsdoc": 0,
+    "strict": 0,
+    "quotes": 0,
+    "indent": 0,
+    "yoda": 0,
+    "new-cap": 0,
+    "space-after-keywords": 0
+  }
+}
diff --git a/node_modules/should/.npmignore b/node_modules/should/.npmignore
new file mode 100644
index 0000000..6e10b86
--- /dev/null
+++ b/node_modules/should/.npmignore
@@ -0,0 +1,3 @@
+examples
+test
+.idea
\ No newline at end of file
diff --git a/node_modules/should/.travis.yml b/node_modules/should/.travis.yml
new file mode 100644
index 0000000..90e1ef6
--- /dev/null
+++ b/node_modules/should/.travis.yml
@@ -0,0 +1,10 @@
+language: node_js
+node_js:
+- '0.12'
+script:
+- test $SAUCE_USERNAME && npm run zuul || echo 'not running on saucelabs'
+- npm test
+env:
+  global:
+  - secure: aB4+vAj+mJHqQfnq9x10eZ5//erfxecs3l9u/oSJX1Ok+WLrpUW0x3qpaC1bEEPq4bkAuIifxohnPv0XTE3m8GyTfRHzqmeNnNQNsnex3IzunbU4aG7QyS3jFa6gjT5OrgPA+eHobNXBvwASZczighlWtoYKD5RW7Uak4E8EpPs=
+  - secure: kJaOWFzFnSGEZ4keShHST18OC6z+rmvnnht0SwqmhPlBX4nBQ2bdBR09n0O/GVQ0uAzohn1oObouQH0yuXpbgmk4whMVZgt8RPztusLskt88fE9EOPFNA+YOWNpmcelDiXsMXv7vN2bBlZJSrILUgUppuHIqsdqTGWut08l3Zhg=
diff --git a/node_modules/should/.zuul.yml b/node_modules/should/.zuul.yml
new file mode 100644
index 0000000..6895ed6
--- /dev/null
+++ b/node_modules/should/.zuul.yml
@@ -0,0 +1,10 @@
+ui: mocha-bdd
+browsers:
+  - name: chrome
+    version: 38..latest
+  - name: ie
+    version: 9..latest
+  - name: firefox
+    version: 33..latest
+  - name: safari
+    version: 6..latest
\ No newline at end of file
diff --git a/node_modules/should/CONTRIBUTING.md b/node_modules/should/CONTRIBUTING.md
new file mode 100644
index 0000000..6659c55
--- /dev/null
+++ b/node_modules/should/CONTRIBUTING.md
@@ -0,0 +1,14 @@
+Before contribute something:
+
+Follow simple rules:
+
+- Not violate [DRY](http://programmer.97things.oreilly.com/wiki/index.php/Don%27t_Repeat_Yourself).
+- [Boy Scout Rule](http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule) needs to have been applied.
+
+1. Your code should look like all the other code - this project should look like it was written by one man, always.
+2. If you want to propose something - just create an issue and describe your question with as much description as you can.
+3. Please never send issues or pull requests about code style, jshint violations etc - I do not accept it (and you will spend your time for free).
+4. If you think you have some general improvement, consider creating a pull request with it.
+5. If you are not sure whether your improvement is general enough, just create your own plugin for should.js. (see should.use and Assertion.add usage).
+6. If you add new code, it should be covered by tests. No tests - no code.
+7. If you find a bug (or at least you think it is a bug), create an issue with the library version and test case that I can run and see what are you talking about, or at least full steps by which I can reproduce it.
diff --git a/node_modules/should/History.md b/node_modules/should/History.md
new file mode 100644
index 0000000..74e1a8d
--- /dev/null
+++ b/node_modules/should/History.md
@@ -0,0 +1,493 @@
+8.0.1 / 2015-12-11
+==================
+
+  * Fix throwing TypeError in .match
+
+8.0.0 / 2015-12-08
+==================
+
+  * Move should-promised to main repo
+  * Expose window.should as should function and not a getter
+
+7.1.1 / 2015-10-20
+==================
+
+  * Update format package to fix node 0.12 Symbol formatting
+
+7.1.0 / 2015-08-28
+==================
+
+  * Added .aboveOrEqual and .belowOrEqual for numbers (<= and >=)
+  * Added .oneOf and .equalOneOf to check equality of one of values
+  * Added 'browser' field to package.json
+
+7.0.4 / 2015-08-14
+==================
+
+  * Missing doc for .deepEqual
+  * Fix .match and dependent assertions to check property in object-object matching
+
+7.0.3 / 2015-08-09
+==================
+
+  * Add alias .deepEqual for .eql
+
+7.0.2 / 2015-07-09
+==================
+
+  * Bug in browser script and build
+
+7.0.1 / 2015-06-18
+==================
+
+  * Fixes in should-type for dom nodes, host object and promises
+
+7.0.0 / 2015-06-18
+==================
+
+  * Added support to `.eql` es6 set, map and symbol (`should-type`, `should-format`, `should-equal`)
+  * **Breaking Change** More accurate work with types (dom nodes, typed-arrays).
+  * **Breaking Change** Change result of should-type to be more accurate and consistent.
+  * Fixed should-equal options checks
+  * Fixed should-format typed arrays (more then 8 bits)
+  * Added aliases: .matchEach => .matchSome, .matchAny => .matchEvery (to be similar to array methods). See #65.
+  * **Breaking Change (possibly)** .matchEach and .matchAny now uses internally .match. See #65.
+  * **Breaking Change** No more getter assertions. No all assertions are functions.
+  * **Breaking Change** No more proxy returning, to check property names.
+  * **Breaking Change** `should-format` now looks more like chrome developer tools inpections.
+
+6.0.3 / 2015-05-18
+==================
+
+  * Replace rest of usage after 6.0.2
+
+6.0.2 / 2015-05-18
+==================
+
+  * Replace in all internal assertions `should` usage to non getter form
+
+6.0.1 / 2015-04-15
+==================
+
+  * Remove dummy debug messages
+
+6.0.0 / 2015-04-15
+==================
+
+  * From .containDeep* removed .indexOf checks for strings, now it is just equality checks (see #55)
+  * Fix for .not.throws for generators
+
+5.2.0 / 2015-03-12
+==================
+
+ * Added `.matchAny`, like `.matchEach` but with `some` semantics
+
+5.1.0 / 2015-03-05
+==================
+
+ * Initial support of es6 generators, iterables, iterators and symbols
+ * .throwError now support generator functions
+ * Fix bug in .propertyByPath
+
+5.0.1 / 2015-02-21
+==================
+
+ * Export utils via should.util
+
+5.0.0 / 2015-02-10
+==================
+
+ * Remove old .eql implementation
+ * Refactor nested errors
+ * Added separate reporting message for false negative results like 10.should.not.equal(10)
+ * Make error.message lazy fix old perfomance bottlenecks for constructing messages for big objects
+ * Added .propertyWithDescriptor
+
+4.6.5 / 2015-02-05
+==================
+
+ * Fix perfomance degradation on large objects
+
+4.6.4 / 2015-02-05
+==================
+
+ * Fix end cases for .containDeep and .containDeepOrdered
+
+4.6.3 / 2015-02-01
+==================
+
+ * Added small check for .noConflict
+ * Fix end cases for .containDeep and .containDeepOrdered
+
+4.6.2 / 2015-01-28
+==================
+
+ * Make assertion properties configurable
+
+4.6.1 / 2015-01-18
+==================
+
+ * Bump deps
+ * Set showDiff only if the same types
+
+4.6.0 / 2015-01-13
+==================
+
+ * Wrap everywhere returned assertion with Proxy if available.
+
+4.5.2 / 2015-01-13
+==================
+
+ * Fixed null properties in .containDeep and .containDeepOrdered
+
+4.5.1 / 2015-01-13
+==================
+
+ * Fixed leaked \_eql
+
+4.5.0 / 2015-01-11
+==================
+
+ * Added config flag .useOldDeepEqual to use old .eql implementation
+
+4.4.4 / 2015-01-08
+==================
+
+ * Added .enumerables
+
+4.4.3 / 2015-01-08
+==================
+
+ * Bump dependencies to get more accurate format of promise
+ * Added a lot of jsdocs
+
+4.4.2 / 2014-12-27
+==================
+
+ * Remove breaking change with should-equal that check also object prototypes. Instead document how get both behaviours in .eql docs.
+
+4.4.1 / 2014-12-13
+==================
+
+ * bump deps
+
+4.4.0 / 2014-12-12
+==================
+
+ * assert methods reimplemented via assertion, deepEqual done via should-equal. To avoid possible confusion between should.deepEqual and a.should.eql(b)
+ * Possible fix for error tests
+
+4.3.1 / 2014-12-08
+==================
+
+ * `.throw()` check if given object is a function
+
+4.3.0 / 2014-11-10
+==================
+
+ * Remove node's version of .eql
+ * Added reason why .eql failed
+
+4.2.1 / 2014-11-07
+==================
+
+ * Move inspection from .formattedObj to be in .getMessage - to make inspection as late as possible.
+
+4.2.0 / 2014-11-06
+==================
+
+ * Remove node util.inspect and use instead own inspection module with type detection and browser types compatibility
+
+4.1.0 / 2014-10-19
+==================
+
+ * As inspect function was moved to repo, refine how it show Dates (added millis via custom format)
+ * Added warnings for potential shoot in the leg: eql non strict and should unwrapping primitive wrappers
+ * Added possibility to disable any warnings via environment variable SHOULDJS_WARN and should.warn = false
+ * Added new deep equality check function
+ * Nested assertions can contribute to parent assertions own messages
+
+4.0.4 / 2014-06-09
+==================
+
+ * Make all assertions enumerable in Assertion.prototype
+
+4.0.3 / 2014-06-09
+==================
+
+ * Fix wrong/strange behaviour of .containDeep with equal keys. Now it check to contain element once.
+ * Added util.formatProp to format properties more accurate
+
+4.0.1 / 2014-06-04
+==================
+
+ * Missing name in browser script
+
+4.0.0 / 2014-05-29
+==================
+
+ * Breaking change: Move non core assertions out
+ * Added casting in properties assertions to String for all property names
+ * Added .propertyByPath assertion
+ * Breaking change: Remove deprecated .includeEql and .include
+ * Breaking change: .containDeep now do not check order for 2 arrays case
+ * Added .containDeepOrdered for old .containDeep
+ * Added support of array-like objects
+ * Added to .throw matching by error properties with .match
+
+3.3.2 / 2014-05-23
+==================
+
+ * Fix for should.format
+
+3.3.1 / 2014-04-16
+==================
+
+ * Added aliases for es reserved words
+ * Fix bug with ownProperty alias
+ * Fix bug with not function alias
+
+3.3.0 / 2014-04-07
+==================
+
+ * Added .enumerable(name, val)
+
+3.2.0 / 2014-03-29
+==================
+
+ * Added first version of .any modifier that affect assertions with multiple parameters
+ * .header now have more nice message
+ * assertion can now override how to show object
+
+3.1.4 / 2014-03-18
+==================
+
+ * .Error now do not throw assertion error for custom errors.
+
+3.1.3 / 2014-02-25
+==================
+
+ * Fix TypeError in .containEql
+
+3.1.2 / 2014-01-28
+==================
+
+ * Fix for adding .inspect for JQuery object only in case when it is exist
+
+3.1.1 / 2014-01-28
+==================
+
+ * Fix for HTMLElement in DOM less environments
+
+3.1.0 / 2014-01-23
+==================
+
+ * Added jquery based browser extension
+
+3.0.1 / 2014-01-17
+==================
+
+ * Fix: .lengthOf()
+
+3.0.0 / 2014-01-17
+==================
+
+ * Split everything to smaller files
+ * Added huge extension to .match and .matchEach. Thanks @alsotang for initial code and idea.
+ * Added .containDeep and .containEql
+ * Separate build for browser and node.js
+ * Basic plugin system
+ * Breaking change: .Object now do not fail on arrays
+ * Breaking change: Additional messages now replaces generated and do not added
+ * Breaking change: .keys now check as is - no keys in args means no keys in object
+ * Deprecated: assert extension
+ * Deprecated: .include and .includeEql
+ * Now all assertions define only positive cases, should.js take care about negations and chains
+
+2.1.1 / 2013-12-05
+==================
+
+ * Move date formatting out of should.inspect
+
+2.1.0 / 2013-11-11
+==================
+
+ * Override .inspect for Date's to convert them to ISOString
+
+2.0.2 / 2013-10-21
+==================
+
+ * Add '#of' as getter for chaining.
+ * Exclude browser script for .npmignore.
+
+2.0.1 / 2013-10-10
+==================
+
+ * Fix wrong path in .npmignore.
+
+2.0.0 / 2013-10-10
+==================
+
+ * breaking change: #a now getter like #an. Was replaced with #type(str)
+ * breaking change: #empty does not check length for objects. Now it check if object do not have own properties.
+ * #properties check if object have some properties
+ * util.inspect now exposed as should.inspect
+ * assertions for NaN, Infinity, Array, Object, String, Boolean, Number, Error, Function
+ * #equal got alias #exactly
+
+1.3.0 / 2013-09-13
+==================
+
+ * fix doc for .keys. Closes #108.
+ * add #endWith()
+ * add .startWith (#119)
+
+1.2.2 / 2013-02-19
+==================
+
+  * fix should.be.instanceOf() failure on Date
+
+1.2.1 / 2012-11-02
+==================
+
+  * add .showDiff
+  * Make instanceOf and throwError be aliased like others [alFReD-NSH]
+  * Fix should[.not].exist not having stack trace #84 [alFReD-NSH]
+
+1.2.0 / 2012-09-21
+==================
+
+  * Added #approximately(value, delta, description) for doing assertions on results of operations with numbers. [titarenko]
+
+1.1.1 / 2012-09-19
+==================
+
+  * add .type for eql()s assert
+
+1.1.0 / 2012-07-30
+==================
+
+  * add enclosing of failure message functions. Closes #81
+  * add mocha .actual / .expected string support for all assertion values
+
+0.7.0 / 2012-07-17
+==================
+
+  * add `.throw(Constructor)` support [snakamura]
+
+0.6.3 / 2012-04-26
+==================
+
+  * Added object inclusion support back
+
+0.6.2 / 2012-04-26
+==================
+
+  * Added homepage to package.json
+  * Fixed .equal() with dates. Closes #63
+
+0.6.1 / 2012-04-10
+==================
+
+  * package: add "repository" section [TooTallNate]
+  * use valueOf() to get the reference the object [TooTallNate]
+
+0.6.0 / 2012-03-01
+==================
+
+  * Added `err.actual` and `err.expected` for .{eql,equal}()
+  * Added 'return this;' to 'get json' and 'get html' in order to provide chaining for should.be.json and should.be.html
+
+0.5.1 / 2012-01-13
+==================
+
+  * Added better `.json`
+  * Added better `.html`
+
+0.5.0 / 2012-01-12
+==================
+
+  * Added string matching to `.throw()` [serby]
+  * Added regexp matching to `.throw()` [serby]
+  * Added `.includeEql()` [RubenVerborgh]
+  * Added `.should.be.html`
+  * Added `.should.be.json`
+  * Added optional description args to most matchers [Mike Swift]
+
+0.4.2 / 2011-12-17
+==================
+
+  * Fixed .header() for realzzz
+
+0.4.1 / 2011-12-16
+==================
+
+  * Fixed: chain .header() to retain negation
+
+0.4.0 / 2011-12-16
+==================
+
+  * Added `.should.throw()`
+  * Added `.include()` support for strings
+  * Added `.include()` support for arrays
+  * Removed `keys()` `.include` modifier support
+  * Removed `.object()`
+  * Removed `.string()`
+  * Removed `.contain()`
+  * Removed `.respondTo()` rubyism
+  * expresso -> mocha
+
+0.3.2 / 2011-10-24
+==================
+
+  * Fixed tests for 0.5.x
+  * Fixed sys warning
+
+0.3.1 / 2011-08-22
+==================
+
+  * configurable
+
+0.3.0 / 2011-08-20
+==================
+
+  * Added assertion for inclusion of an object: `foo.should.include.object({ foo: 'bar' })`
+
+0.2.1 / 2011-05-13
+==================
+
+  * Fixed .status(code). Closes #18
+
+0.2.0 / 2011-04-17
+==================
+
+  * Added `res.should.have.status(code)` method
+  * Added `res.should.have.header(field, val)` method
+
+0.1.0 / 2011-04-06
+==================
+
+  * Added `should.exist(obj)` [aseemk]
+  * Added `should.not.exist(obj)` [aseemk]
+
+0.0.4 / 2010-11-24
+==================
+
+  * Added `.ok` to assert truthfulness
+  * Added `.arguments`
+  * Fixed double required bug. [thanks dominictarr]
+
+0.0.3 / 2010-11-19
+==================
+
+  * Added `true` / `false` assertions
+
+0.0.2 / 2010-11-19
+==================
+
+  * Added chaining support
+
+0.0.1 / 2010-11-19
+==================
+
+  * Initial release
diff --git a/node_modules/should/LICENSE b/node_modules/should/LICENSE
new file mode 100644
index 0000000..e3fcf59
--- /dev/null
+++ b/node_modules/should/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010-2014 TJ Holowaychuk <tj@vision-media.ca>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/node_modules/should/Readme.md b/node_modules/should/Readme.md
new file mode 100644
index 0000000..c5254b1
--- /dev/null
+++ b/node_modules/should/Readme.md
@@ -0,0 +1,206 @@
+# should.js
+
+[![Join the chat at https://gitter.im/shouldjs/should.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/shouldjs/should.js)
+
+[![Build Status](https://travis-ci.org/shouldjs/should.js.svg?branch=master)](https://travis-ci.org/shouldjs/should.js)
+
+[![Selenium Test Status](https://saucelabs.com/browser-matrix/shouldjs.svg)](https://saucelabs.com/u/shouldjs)
+
+_should_ is an expressive, readable, framework-agnostic assertion library. The main goals of this library are __to be expressive__ and __to be helpful__. It keeps your test code clean, and your error messages helpful.
+
+By default (when you `require('should')`) _should_ extends the `Object.prototype` with a single non-enumerable getter that allows you to express how that object should behave. It also returns itself when required with `require`.
+
+It is also possible to use should.js without getter (it will not even try to extend Object.prototype), just `require('should/as-function')`. Or if you already use version that auto add getter, you can call `.noConflict` function.
+
+**Results of `(something).should` getter and `should(something)` in most situations are the same**
+
+### Upgrading instructions
+
+Please check [wiki page](https://github.com/shouldjs/should.js/wiki/Breaking-changes) for upgrading instructions.
+
+### FAQ
+
+You can take look in [FAQ](https://github.com/shouldjs/should.js/wiki/FAQ).
+
+## Example
+```javascript
+var should = require('should');
+
+var user = {
+    name: 'tj'
+  , pets: ['tobi', 'loki', 'jane', 'bandit']
+};
+
+user.should.have.property('name', 'tj');
+user.should.have.property('pets').with.lengthOf(4);
+
+// If the object was created with Object.create(null)
+// then it doesn't inherit `Object.prototype`, so it will not have `.should` getter
+// so you can do:
+should(user).have.property('name', 'tj');
+
+// also you can test in that way for null's
+should(null).not.be.ok();
+
+someAsyncTask(foo, function(err, result){
+  should.not.exist(err);
+  should.exist(result);
+  result.bar.should.equal(foo);
+});
+```
+## To begin
+
+ 1. Install it:
+
+    ```bash
+    $ npm install should --save-dev
+    ```
+
+ 2. Require it and use:
+
+    ```js
+    var should = require('should');
+
+    (5).should.be.exactly(5).and.be.a.Number();
+    ```
+
+    ```js
+    var should = require('should/as-function');
+
+    should(10).be.exactly(5).and.be.a.Number();
+    ```
+
+## In browser
+
+Well, even when browsers by complains of authors has 100% es5 support, it does not mean it has no bugs. Please see [wiki](https://github.com/shouldjs/should.js/wiki/Known-Bugs) for known bugs.
+
+If you want to use _should_ in browser, use the `should.js` file in the root of this repository, or build it yourself. To build a fresh version:
+
+```bash
+$ npm install
+$ gulp script
+```
+
+The script is exported to `window.should`:
+
+```js
+should(10).be.exactly(10)
+```
+
+You can easy install it with npm or bower:
+
+```sh
+npm install should -D
+# or
+bower install shouldjs/should.js
+```
+
+## API docs
+
+Actual api docs generated by jsdoc comments and available at [http://shouldjs.github.io](http://shouldjs.github.io).
+
+## Usage examples
+
+Please look on usage in [examples](https://github.com/shouldjs/examples)
+
+## .not
+
+`.not` negates the current assertion.
+
+## .any
+
+`.any` allow for assertions with multiple parameters to assert any of the parameters (but not all). This is similar to the native JavaScript [array.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
+
+# Assertions
+## chaining assertions
+
+Every assertion will return a `should.js`-wrapped Object, so assertions can be chained.
+To help chained assertions read more clearly, you can use the following helpers anywhere in your chain: `.an`, `.of`, `.a`, `.and`, `.be`, `.have`, `.with`, `.is`, `.which`. Use them for better readability; they do nothing at all.
+For example:
+```js
+user.should.be.an.instanceOf(Object).and.have.property('name', 'tj');
+user.pets.should.be.instanceof(Array).and.have.lengthOf(4);
+```
+Almost all assertions return the same object - so you can easy chain them. But some (eg: `.length` and `.property`) move the assertion object to a property value, so be careful.
+
+## Adding own assertions
+
+Adding own assertion is pretty easy. You need to call `should.Assertion.add` function. It accept 2 arguments:
+
+1. name of assertion method (string)
+2. assertion function (function)
+
+What assertion function should do. It should check only positive case. `should` will handle `.not` itself.
+`this` in assertion function will be instance of `should.Assertion` and you **must** define in any way this.params object
+ in your assertion function call before assertion check happen.
+
+`params` object can contain several fields:
+
+- `operator` - it is string which describe your assertion
+- `actual` it is actual value, you can assume it is your own this.obj if you need to define you own
+- `expected` it is any value that expected to be matched this.obj
+
+You can assume its usage in generating AssertionError message like: expected `obj`? || this.obj not? `operator` `expected`?
+
+In `should` sources appeared 2 kinds of usage of this method.
+
+First not preferred and used **only** for shortcuts to other assertions, e.g how `.should.be.true()` defined:
+
+```javascript
+Assertion.add('true', function() {
+    this.is.exactly(true);
+});
+```
+There you can see that assertion function do not define own `this.params` and instead call within the same assertion `.exactly`
+that will fill `this.params`. **You should use this way very carefully, but you can use it**.
+
+Second way preferred and i assume you will use it instead of first.
+
+```javascript
+Assertion.add('true', function() {
+    this.params = { operator: 'to be true', expected: true };
+
+    should(this.obj).be.exactly(true);
+});
+```
+in this case this.params defined and then used new assertion context (because called `.should`). Internally this way does not
+ create any edge cases as first.
+
+```javascript
+Assertion.add('asset', function() {
+    this.params = { operator: 'to be asset' };
+
+    this.obj.should.have.property('id').which.is.a.Number();
+    this.obj.should.have.property('path');
+})
+
+//then
+> ({ id: '10' }).should.be.an.asset();
+AssertionError: expected { id: '10' } to be asset
+    expected '10' to be a number
+
+> ({ id: 10 }).should.be.an.asset();
+AssertionError: expected { id: 10 } to be asset
+    expected { id: 10 } to have property path
+```
+
+
+## Contributions
+
+[Actual list of contributors](https://github.com/visionmedia/should.js/graphs/contributors) if you want to show it your friends.
+
+To run the tests for _should_ simply run:
+
+    $ npm test
+
+See also [CONTRIBUTING](./CONTRIBUTING.md).
+
+## OMG IT EXTENDS OBJECT???!?!@
+
+Yes, yes it does, with a single getter _should_, and no it won't break your code, because it does this **properly** with a non-enumerable property.
+
+Also it is possible use it without extension.
+
+## License
+
+MIT &copy; 2010-2014 TJ Holowaychuk
diff --git a/node_modules/should/as-function.js b/node_modules/should/as-function.js
new file mode 100644
index 0000000..c3f0d0a
--- /dev/null
+++ b/node_modules/should/as-function.js
@@ -0,0 +1 @@
+module.exports = require('./lib/should');
diff --git a/node_modules/should/bower.json b/node_modules/should/bower.json
new file mode 100644
index 0000000..1fb8787
--- /dev/null
+++ b/node_modules/should/bower.json
@@ -0,0 +1,28 @@
+{
+  "name": "should",
+  "main": "should.js",
+  "homepage": "https://github.com/shouldjs/should.js",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/shouldjs/should.js.git"
+  },
+  "authors": [
+    "TJ Holowaychuk <tj@vision-media.ca> and contributors"
+  ],
+  "description": "test framework agnostic BDD-style assertions",
+  "keywords": [
+    "test",
+    "bdd",
+    "assert",
+    "should"
+  ],
+  "license": "MIT",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "test",
+    "*.md",
+    "LICENSE",
+    "package.json"
+  ]
+}
diff --git a/node_modules/should/browser-entry.js b/node_modules/should/browser-entry.js
new file mode 100644
index 0000000..f7863fa
--- /dev/null
+++ b/node_modules/should/browser-entry.js
@@ -0,0 +1,7 @@
+window.Should = require('./index');
+
+Object.defineProperty(window, 'should', {
+  enumerable: false,
+  configurable: true,
+  value: window.Should
+});
diff --git a/node_modules/should/gulpfile.js b/node_modules/should/gulpfile.js
new file mode 100644
index 0000000..9d41c3e
--- /dev/null
+++ b/node_modules/should/gulpfile.js
@@ -0,0 +1,43 @@
+var gulp = require('gulp');
+
+var header = require('gulp-header');
+var uglify = require('gulp-uglify');
+var rename = require('gulp-rename');
+
+var source = require('vinyl-source-stream');
+var buffer = require('vinyl-buffer');
+
+var browserify = require('browserify');
+
+var pkg = require('./package.json');
+
+var banner = [
+  '/*!',
+  ' * <%= pkg.name %> - <%= pkg.description %>',
+  ' * @version v<%= pkg.version %>',
+  ' * @author <%= pkg.author %>',
+  ' * @link <%= pkg.homepage %>',
+  ' * @license <%= pkg.license %>',
+  ' */',
+  ''].join('\n');
+
+gulp.task('script', function() {
+  var bundleStream = browserify({
+    entries: './browser-entry',
+    builtins: null,
+    insertGlobals: false,
+    detectGlobals: false,
+    standalone: 'Should',
+    fullPaths: false
+  })
+    .bundle();
+
+  return bundleStream
+    .pipe(source('should.js'))
+    .pipe(buffer())
+    .pipe(header(banner, {pkg: pkg}))
+    .pipe(gulp.dest('./'))
+    .pipe(uglify({ preserveComments: 'some' }))
+    .pipe(rename('should.min.js'))
+    .pipe(gulp.dest('./'));
+});
diff --git a/node_modules/should/index.js b/node_modules/should/index.js
new file mode 100644
index 0000000..9aa4ffc
--- /dev/null
+++ b/node_modules/should/index.js
@@ -0,0 +1,14 @@
+var should = require('./lib/should');
+
+var defaultProto = Object.prototype;
+var defaultProperty = 'should';
+
+//Expose api via `Object#should`.
+try {
+  var prevShould = should.extend(defaultProperty, defaultProto);
+  should._prevShould = prevShould;
+} catch(e) {
+  //ignore errors
+}
+
+module.exports = should;
diff --git a/node_modules/should/lib/assertion-error.js b/node_modules/should/lib/assertion-error.js
new file mode 100644
index 0000000..b7408de
--- /dev/null
+++ b/node_modules/should/lib/assertion-error.js
@@ -0,0 +1,92 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('./util');
+
+/**
+ * should AssertionError
+ * @param {Object} options
+ * @constructor
+ * @memberOf should
+ * @static
+ */
+var AssertionError = function AssertionError(options) {
+  util.merge(this, options);
+
+  if(!options.message) {
+    Object.defineProperty(this, 'message', {
+        get: function() {
+          if(!this._message) {
+            this._message = this.generateMessage();
+            this.generatedMessage = true;
+          }
+          return this._message;
+        },
+        configurable: true,
+        enumerable: false
+      }
+    );
+  }
+
+  if(Error.captureStackTrace) {
+    Error.captureStackTrace(this, this.stackStartFunction);
+  } else {
+    // non v8 browsers so we can have a stacktrace
+    var err = new Error();
+    if(err.stack) {
+      var out = err.stack;
+
+      if(this.stackStartFunction) {
+        // try to strip useless frames
+        var fn_name = util.functionName(this.stackStartFunction);
+        var idx = out.indexOf('\n' + fn_name);
+        if(idx >= 0) {
+          // once we have located the function frame
+          // we need to strip out everything before it (and its line)
+          var next_line = out.indexOf('\n', idx + 1);
+          out = out.substring(next_line + 1);
+        }
+      }
+
+      this.stack = out;
+    }
+  }
+};
+
+
+var indent = '    ';
+function prependIndent(line) {
+  return indent + line;
+}
+
+function indentLines(text) {
+  return text.split('\n').map(prependIndent).join('\n');
+}
+
+
+// assert.AssertionError instanceof Error
+AssertionError.prototype = Object.create(Error.prototype, {
+  name: {
+    value: 'AssertionError'
+  },
+
+  generateMessage: {
+    value: function() {
+      if(!this.operator && this.previous) {
+        return this.previous.message;
+      }
+      var actual = util.format(this.actual);
+      var expected = 'expected' in this ? ' ' + util.format(this.expected) : '';
+      var details = 'details' in this && this.details ? ' (' + this.details + ')' : '';
+
+      var previous = this.previous ? '\n' + indentLines(this.previous.message) : '';
+
+      return 'expected ' + actual + (this.negate ? ' not ' : ' ') + this.operator + expected + details + previous;
+    }
+  }
+});
+
+module.exports = AssertionError;
diff --git a/node_modules/should/lib/assertion.js b/node_modules/should/lib/assertion.js
new file mode 100644
index 0000000..007a940
--- /dev/null
+++ b/node_modules/should/lib/assertion.js
@@ -0,0 +1,277 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var AssertionError = require('./assertion-error');
+
+/**
+ * should Assertion
+ * @param {*} obj Given object for assertion
+ * @constructor
+ * @memberOf should
+ * @static
+ */
+function Assertion(obj) {
+  this.obj = obj;
+
+  this.anyOne = false;
+  this.negate = false;
+
+  this.params = {actual: obj};
+}
+
+Assertion.prototype = {
+  constructor: Assertion,
+
+  /**
+   * Base method for assertions.
+   *
+   * Before calling this method need to fill Assertion#params object. This method usually called from other assertion methods.
+   * `Assertion#params` can contain such properties:
+   * * `operator` - required string containing description of this assertion
+   * * `obj` - optional replacement for this.obj, it usefull if you prepare more clear object then given
+   * * `message` - if this property filled with string any others will be ignored and this one used as assertion message
+   * * `expected` - any object used when you need to assert relation between given object and expected. Like given == expected (== is a relation)
+   * * `details` - additional string with details to generated message
+   *
+   * @memberOf Assertion
+   * @category assertion
+   * @param {*} expr Any expression that will be used as a condition for asserting.
+   * @example
+   *
+   * var a = new should.Assertion(42);
+   *
+   * a.params = {
+   *  operator: 'to be magic number',
+   * }
+   *
+   * a.assert(false);
+   * //throws AssertionError: expected 42 to be magic number
+   */
+  assert: function(expr) {
+    if(expr) {
+      return this;
+    }
+
+    var params = this.params;
+
+    if('obj' in params && !('actual' in params)) {
+      params.actual = params.obj;
+    } else if(!('obj' in params) && !('actual' in params)) {
+      params.actual = this.obj;
+    }
+
+    params.stackStartFunction = params.stackStartFunction || this.assert;
+    params.negate = this.negate;
+
+    params.assertion = this;
+
+    throw new AssertionError(params);
+  },
+
+  /**
+   * Shortcut for `Assertion#assert(false)`.
+   *
+   * @memberOf Assertion
+   * @category assertion
+   * @example
+   *
+   * var a = new should.Assertion(42);
+   *
+   * a.params = {
+   *  operator: 'to be magic number',
+   * }
+   *
+   * a.fail();
+   * //throws AssertionError: expected 42 to be magic number
+   */
+  fail: function() {
+    return this.assert(false);
+  }
+};
+
+
+
+/**
+ * Assertion used to delegate calls of Assertion methods inside of Promise.
+ * It has almost all methods of Assertion.prototype
+ *
+ * @param {Promise} obj
+ */
+function PromisedAssertion(/* obj */) {
+  Assertion.apply(this, arguments);
+}
+
+/**
+ * Make PromisedAssertion to look like promise. Delegate resolve and reject to given promise.
+ * 
+ * @private
+ * @returns {Promise}
+ */
+PromisedAssertion.prototype.then = function(resolve, reject) {
+  return this.obj.then(resolve, reject);
+};
+
+/**
+ * Way to extend Assertion function. It uses some logic
+ * to define only positive assertions and itself rule with negative assertion.
+ *
+ * All actions happen in subcontext and this method take care about negation.
+ * Potentially we can add some more modifiers that does not depends from state of assertion.
+ *
+ * @memberOf Assertion
+ * @static
+ * @param {String} name Name of assertion. It will be used for defining method or getter on Assertion.prototype
+ * @param {Function} func Function that will be called on executing assertion
+ * @example
+ *
+ * Assertion.add('asset', function() {
+ *      this.params = { operator: 'to be asset' }
+ *
+ *      this.obj.should.have.property('id').which.is.a.Number()
+ *      this.obj.should.have.property('path')
+ * })
+ */
+Assertion.add = function(name, func) {
+  Object.defineProperty(Assertion.prototype, name, {
+    enumerable: true,
+    configurable: true,
+    value: function() {
+      var context = new Assertion(this.obj, this, name);
+      context.anyOne = this.anyOne;
+
+      try {
+        func.apply(context, arguments);
+      } catch (e) {
+        // check for fail
+        if (e instanceof AssertionError) {
+          // negative fail
+          if (this.negate) {
+            this.obj = context.obj;
+            this.negate = false;
+            return this;
+          }
+
+          if (context !== e.assertion) {
+            context.params.previous = e;
+          }
+
+          // positive fail
+          context.negate = false;
+          context.fail();
+        }
+        // throw if it is another exception
+        throw e;
+      }
+
+      // negative pass
+      if (this.negate) {
+        context.negate = true; // because .fail will set negate
+        context.params.details = 'false negative fail';
+        context.fail();
+      }
+
+      // positive pass
+      if (!this.params.operator) {
+        this.params = context.params; // shortcut
+      }
+      this.obj = context.obj;
+      this.negate = false;
+      return this;
+    }
+  });
+
+  Object.defineProperty(PromisedAssertion.prototype, name, {
+    enumerable: true,
+    configurable: true,
+    value: function() {
+      var args = arguments;
+      this.obj = this.obj.then(function(a) {
+        return a[name].apply(a, args);
+      });
+
+      return this;
+    }
+  });
+};
+
+/**
+ * Add chaining getter to Assertion like .a, .which etc
+ * 
+ * @memberOf Assertion
+ * @static
+ * @param  {string} name   name of getter
+ * @param  {function} [onCall] optional function to call
+ */
+Assertion.addChain = function(name, onCall) {
+  onCall = onCall || function() {};
+  Object.defineProperty(Assertion.prototype, name, {
+    get: function() {
+      onCall.call(this);
+      return this;
+    },
+    enumerable: true
+  });
+
+  Object.defineProperty(PromisedAssertion.prototype, name, {
+    enumerable: true,
+    configurable: true,
+    get: function() {
+      this.obj = this.obj.then(function(a) {
+        return a[name];
+      });
+
+      return this;
+    }
+  });
+};
+
+/**
+ * Create alias for some `Assertion` property
+ *
+ * @memberOf Assertion
+ * @static
+ * @param {String} from Name of to map
+ * @param {String} to Name of alias
+ * @example
+ *
+ * Assertion.alias('true', 'True')
+ */
+Assertion.alias = function(from, to) {
+  var desc = Object.getOwnPropertyDescriptor(Assertion.prototype, from);
+  if (!desc) throw new Error('Alias ' + from + ' -> ' + to + ' could not be created as ' + from + ' not defined');
+  Object.defineProperty(Assertion.prototype, to, desc);
+
+  var desc2 = Object.getOwnPropertyDescriptor(PromisedAssertion.prototype, from);
+  if (desc2) {
+    Object.defineProperty(PromisedAssertion.prototype, to, desc2);
+  }
+};
+/**
+ * Negation modifier. Current assertion chain become negated. Each call invert negation on current assertion.
+ *
+ * @name not
+ * @property
+ * @memberOf Assertion
+ * @category assertion
+ */
+Assertion.addChain('not', function() {
+  this.negate = !this.negate;
+});
+
+/**
+ * Any modifier - it affect on execution of sequenced assertion to do not `check all`, but `check any of`.
+ *
+ * @name any
+ * @property
+ * @memberOf Assertion
+ * @category assertion
+ */
+Assertion.addChain('any', function() {
+  this.anyOne = true;
+});
+
+module.exports = Assertion;
+module.exports.PromisedAssertion = PromisedAssertion;
diff --git a/node_modules/should/lib/config.js b/node_modules/should/lib/config.js
new file mode 100644
index 0000000..a7c2bb5
--- /dev/null
+++ b/node_modules/should/lib/config.js
@@ -0,0 +1,17 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var Formatter = require('should-format').Formatter;
+
+var config = {
+  checkProtoEql: false,
+
+  getFormatter: function(opts) {
+    return new Formatter(opts || config);
+  }
+};
+
+module.exports = config;
diff --git a/node_modules/should/lib/ext/_assert.js b/node_modules/should/lib/ext/_assert.js
new file mode 100644
index 0000000..05e4aee
--- /dev/null
+++ b/node_modules/should/lib/ext/_assert.js
@@ -0,0 +1,279 @@
+// implement assert interface using already written peaces of should.js
+
+// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
+//
+// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
+//
+// Originally from narwhal.js (http://narwhaljs.org)
+// Copyright (c) 2009 Thomas Robinson <280north.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the 'Software'), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// when used in node, this will actually load the util module we depend on
+// versus loading the builtin util module as happens otherwise
+// this is a bug in node module loading as far as I am concerned
+var Assertion = require('./../assertion');
+
+var _deepEqual = require('should-equal');
+
+var pSlice = Array.prototype.slice;
+
+// 1. The assert module provides functions that throw
+// AssertionError's when particular conditions are not met. The
+// assert module must conform to the following interface.
+
+var assert = module.exports = ok;
+
+// 3. All of the following functions must throw an AssertionError
+// when a corresponding condition is not met, with a message that
+// may be undefined if not provided.  All assertion methods provide
+// both the actual and expected values to the assertion error for
+// display purposes.
+/**
+ * Node.js standard [`assert.fail`](http://nodejs.org/api/assert.html#assert_assert_fail_actual_expected_message_operator).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual Actual object
+ * @param {*} expected Expected object
+ * @param {string} message Message for assertion
+ * @param {string} operator Operator text
+ */
+function fail(actual, expected, message, operator, stackStartFunction) {
+  var a = new Assertion(actual);
+  a.params = {
+    operator: operator,
+    expected: expected,
+    message: message,
+    stackStartFunction: stackStartFunction || fail
+  };
+
+  a.fail();
+}
+
+// EXTENSION! allows for well behaved errors defined elsewhere.
+assert.fail = fail;
+
+// 4. Pure assertion tests whether a value is truthy, as determined
+// by !!guard.
+// assert.ok(guard, message_opt);
+// This statement is equivalent to assert.equal(true, !!guard,
+// message_opt);. To test strictly for the value true, use
+// assert.strictEqual(true, guard, message_opt);.
+/**
+ * Node.js standard [`assert.ok`](http://nodejs.org/api/assert.html#assert_assert_value_message_assert_ok_value_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} value
+ * @param {string} [message]
+ */
+function ok(value, message) {
+  if(!value) fail(value, true, message, '==', assert.ok);
+}
+assert.ok = ok;
+
+// 5. The equality assertion tests shallow, coercive equality with
+// ==.
+// assert.equal(actual, expected, message_opt);
+
+/**
+ * Node.js standard [`assert.equal`](http://nodejs.org/api/assert.html#assert_assert_equal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.equal = function equal(actual, expected, message) {
+  if(actual != expected) fail(actual, expected, message, '==', assert.equal);
+};
+
+// 6. The non-equality assertion tests for whether two objects are not equal
+// with != assert.notEqual(actual, expected, message_opt);
+/**
+ * Node.js standard [`assert.notEqual`](http://nodejs.org/api/assert.html#assert_assert_notequal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.notEqual = function notEqual(actual, expected, message) {
+  if(actual == expected) {
+    fail(actual, expected, message, '!=', assert.notEqual);
+  }
+};
+
+// 7. The equivalence assertion tests a deep equality relation.
+// assert.deepEqual(actual, expected, message_opt);
+/**
+ * Node.js standard [`assert.deepEqual`](http://nodejs.org/api/assert.html#assert_assert_deepequal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.deepEqual = function deepEqual(actual, expected, message) {
+  if(!_deepEqual(actual, expected).result) {
+    fail(actual, expected, message, 'deepEqual', assert.deepEqual);
+  }
+};
+
+
+// 8. The non-equivalence assertion tests for any deep inequality.
+// assert.notDeepEqual(actual, expected, message_opt);
+/**
+ * Node.js standard [`assert.notDeepEqual`](http://nodejs.org/api/assert.html#assert_assert_notdeepequal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
+  if(_deepEqual(actual, expected).result) {
+    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
+  }
+};
+
+// 9. The strict equality assertion tests strict equality, as determined by ===.
+// assert.strictEqual(actual, expected, message_opt);
+/**
+ * Node.js standard [`assert.strictEqual`](http://nodejs.org/api/assert.html#assert_assert_strictequal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.strictEqual = function strictEqual(actual, expected, message) {
+  if(actual !== expected) {
+    fail(actual, expected, message, '===', assert.strictEqual);
+  }
+};
+
+// 10. The strict non-equality assertion tests for strict inequality, as
+// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);
+/**
+ * Node.js standard [`assert.notStrictEqual`](http://nodejs.org/api/assert.html#assert_assert_notstrictequal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
+  if(actual === expected) {
+    fail(actual, expected, message, '!==', assert.notStrictEqual);
+  }
+};
+
+function expectedException(actual, expected) {
+  if(!actual || !expected) {
+    return false;
+  }
+
+  if(Object.prototype.toString.call(expected) == '[object RegExp]') {
+    return expected.test(actual);
+  } else if(actual instanceof expected) {
+    return true;
+  } else if(expected.call({}, actual) === true) {
+    return true;
+  }
+
+  return false;
+}
+
+function _throws(shouldThrow, block, expected, message) {
+  var actual;
+
+  if(typeof expected == 'string') {
+    message = expected;
+    expected = null;
+  }
+
+  try {
+    block();
+  } catch(e) {
+    actual = e;
+  }
+
+  message = (expected && expected.name ? ' (' + expected.name + ')' : '.') +
+  (message ? ' ' + message : '.');
+
+  if(shouldThrow && !actual) {
+    fail(actual, expected, 'Missing expected exception' + message);
+  }
+
+  if(!shouldThrow && expectedException(actual, expected)) {
+    fail(actual, expected, 'Got unwanted exception' + message);
+  }
+
+  if((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) {
+    throw actual;
+  }
+}
+
+// 11. Expected to throw an error:
+// assert.throws(block, Error_opt, message_opt);
+/**
+ * Node.js standard [`assert.throws`](http://nodejs.org/api/assert.html#assert_assert_throws_block_error_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {Function} block
+ * @param {Function} [error]
+ * @param {String} [message]
+ */
+assert.throws = function(block, /*optional*/error, /*optional*/message) {
+  _throws.apply(this, [true].concat(pSlice.call(arguments)));
+};
+
+// EXTENSION! This is annoying to write outside this module.
+/**
+ * Node.js standard [`assert.doesNotThrow`](http://nodejs.org/api/assert.html#assert_assert_doesnotthrow_block_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {Function} block
+ * @param {String} [message]
+ */
+assert.doesNotThrow = function(block, /*optional*/message) {
+  _throws.apply(this, [false].concat(pSlice.call(arguments)));
+};
+
+/**
+ * Node.js standard [`assert.ifError`](http://nodejs.org/api/assert.html#assert_assert_iferror_value).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {Error} err
+ */
+assert.ifError = function(err) {
+  if(err) {
+    throw err;
+  }
+};
diff --git a/node_modules/should/lib/ext/assert.js b/node_modules/should/lib/ext/assert.js
new file mode 100644
index 0000000..45ec195
--- /dev/null
+++ b/node_modules/should/lib/ext/assert.js
@@ -0,0 +1,70 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util')
+  , assert = require('./_assert')
+  , AssertionError = require('../assertion-error');
+
+module.exports = function(should) {
+  var i = should.format;
+
+  /*
+   * Expose assert to should
+   *
+   * This allows you to do things like below
+   * without require()ing the assert module.
+   *
+   *    should.equal(foo.bar, undefined);
+   *
+   */
+  util.merge(should, assert);
+
+  /**
+   * Assert _obj_ exists, with optional message.
+   *
+   * @static
+   * @memberOf should
+   * @category assertion assert
+   * @alias should.exists
+   * @param {*} obj
+   * @param {String} [msg]
+   * @example
+   *
+   * should.exist(1);
+   * should.exist(new Date());
+   */
+  should.exist = should.exists = function(obj, msg) {
+    if(null == obj) {
+      throw new AssertionError({
+        message: msg || ('expected ' + i(obj) + ' to exist'), stackStartFunction: should.exist
+      });
+    }
+  };
+
+  should.not = {};
+  /**
+   * Asserts _obj_ does not exist, with optional message.
+   *
+   * @name not.exist
+   * @static
+   * @memberOf should
+   * @category assertion assert
+   * @alias should.not.exists
+   * @param {*} obj
+   * @param {String} [msg]
+   * @example
+   *
+   * should.not.exist(null);
+   * should.not.exist(void 0);
+   */
+  should.not.exist = should.not.exists = function(obj, msg) {
+    if(null != obj) {
+      throw new AssertionError({
+        message: msg || ('expected ' + i(obj) + ' to not exist'), stackStartFunction: should.not.exist
+      });
+    }
+  };
+};
\ No newline at end of file
diff --git a/node_modules/should/lib/ext/bool.js b/node_modules/should/lib/ext/bool.js
new file mode 100644
index 0000000..0976078
--- /dev/null
+++ b/node_modules/should/lib/ext/bool.js
@@ -0,0 +1,67 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+module.exports = function(should, Assertion) {
+  /**
+   * Assert given object is exactly `true`.
+   *
+   * @name true
+   * @memberOf Assertion
+   * @category assertion bool
+   * @alias Assertion#True
+   * @example
+   *
+   * (true).should.be.true();
+   * false.should.not.be.true();
+   *
+   * ({ a: 10}).should.not.be.true();
+   */
+  Assertion.add('true', function() {
+    this.is.exactly(true);
+  });
+
+  Assertion.alias('true', 'True');
+
+  /**
+   * Assert given object is exactly `false`.
+   *
+   * @name false
+   * @memberOf Assertion
+   * @category assertion bool
+   * @alias Assertion#False
+   * @example
+   *
+   * (true).should.not.be.false();
+   * false.should.be.false();
+   */
+  Assertion.add('false', function() {
+    this.is.exactly(false);
+  });
+
+  Assertion.alias('false', 'False');
+
+  /**
+   * Assert given object is thuthy according javascript type conversions.
+   *
+   * @name ok
+   * @memberOf Assertion
+   * @category assertion bool
+   * @example
+   *
+   * (true).should.be.ok();
+   * ''.should.not.be.ok();
+   * should(null).not.be.ok();
+   * should(void 0).not.be.ok();
+   *
+   * (10).should.be.ok();
+   * (0).should.not.be.ok();
+   */
+  Assertion.add('ok', function() {
+    this.params = { operator: 'to be truthy' };
+
+    this.assert(this.obj);
+  });
+};
diff --git a/node_modules/should/lib/ext/chain.js b/node_modules/should/lib/ext/chain.js
new file mode 100644
index 0000000..95c28f4
--- /dev/null
+++ b/node_modules/should/lib/ext/chain.js
@@ -0,0 +1,30 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+module.exports = function(should, Assertion) {
+  /**
+   * Simple chaining. It actually do nothing.
+   *
+   * @memberOf Assertion
+   * @name be
+   * @property {should.Assertion} be
+   * @alias Assertion#an
+   * @alias Assertion#of
+   * @alias Assertion#a
+   * @alias Assertion#and
+   * @alias Assertion#have
+   * @alias Assertion#has
+   * @alias Assertion#with
+   * @alias Assertion#is
+   * @alias Assertion#which
+   * @alias Assertion#the
+   * @alias Assertion#it
+   * @category assertion chaining
+   */
+  ['an', 'of', 'a', 'and', 'be', 'has', 'have', 'with', 'is', 'which', 'the', 'it'].forEach(function(name) {
+    Assertion.addChain(name);
+  });
+};
diff --git a/node_modules/should/lib/ext/contain.js b/node_modules/should/lib/ext/contain.js
new file mode 100644
index 0000000..d5ecc72
--- /dev/null
+++ b/node_modules/should/lib/ext/contain.js
@@ -0,0 +1,158 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util');
+var eql = require('should-equal');
+
+module.exports = function(should, Assertion) {
+  var i = should.format;
+
+  /**
+   * Assert that given object contain something that equal to `other`. It uses `should-equal` for equality checks.
+   * If given object is array it search that one of elements was equal to `other`.
+   * If given object is string it checks if `other` is a substring - expected that `other` is a string.
+   * If given object is Object it checks that `other` is a subobject - expected that `other` is a object.
+   *
+   * @name containEql
+   * @memberOf Assertion
+   * @category assertion contain
+   * @param {*} other Nested object
+   * @example
+   *
+   * [1, 2, 3].should.containEql(1);
+   * [{ a: 1 }, 'a', 10].should.containEql({ a: 1 });
+   *
+   * 'abc'.should.containEql('b');
+   * 'ab1c'.should.containEql(1);
+   *
+   * ({ a: 10, c: { d: 10 }}).should.containEql({ a: 10 });
+   * ({ a: 10, c: { d: 10 }}).should.containEql({ c: { d: 10 }});
+   * ({ a: 10, c: { d: 10 }}).should.containEql({ b: 10 });
+   * // throws AssertionError: expected { a: 10, c: { d: 10 } } to contain { b: 10 }
+   * //            expected { a: 10, c: { d: 10 } } to have property b
+   */
+  Assertion.add('containEql', function(other) {
+    this.params = {operator: 'to contain ' + i(other)};
+
+    this.is.not.null().and.not.undefined();
+
+    var obj = this.obj;
+
+    if(typeof obj == 'string') {
+      this.assert(obj.indexOf(String(other)) >= 0);
+    } else if(util.isIndexable(obj)) {
+      this.assert(util.some(obj, function(v) {
+        return eql(v, other).result;
+      }));
+    } else {
+      this.have.properties(other);
+    }
+  });
+
+  /**
+   * Assert that given object is contain equally structured object on the same depth level.
+   * If given object is an array and `other` is an array it checks that the eql elements is going in the same sequence in given array (recursive)
+   * If given object is an object it checks that the same keys contain deep equal values (recursive)
+   * On other cases it try to check with `.eql`
+   *
+   * @name containDeepOrdered
+   * @memberOf Assertion
+   * @category assertion contain
+   * @param {*} other Nested object
+   * @example
+   *
+   * [ 1, 2, 3].should.containDeepOrdered([1, 2]);
+   * [ 1, 2, [ 1, 2, 3 ]].should.containDeepOrdered([ 1, [ 2, 3 ]]);
+   *
+   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({a: 10});
+   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {c: 10}});
+   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {d: [1, 3]}});
+   */
+  Assertion.add('containDeepOrdered', function(other) {
+    this.params = {operator: 'to contain ' + i(other)};
+
+    var obj = this.obj;
+    if(typeof obj == 'string') {// expect other to be string
+      this.is.equal(String(other));
+    } else if(util.isIndexable(obj) && util.isIndexable(other)) {
+      for(var objIdx = 0, otherIdx = 0, objLength = util.length(obj), otherLength = util.length(other); objIdx < objLength && otherIdx < otherLength; objIdx++) {
+        try {
+          should(obj[objIdx]).containDeepOrdered(other[otherIdx]);
+          otherIdx++;
+        } catch(e) {
+          if(e instanceof should.AssertionError) {
+            continue;
+          }
+          throw e;
+        }
+      }
+
+      this.assert(otherIdx === otherLength);
+    } else if(obj != null && other != null && typeof obj == 'object' && typeof other == 'object') {// object contains object case
+      util.forEach(other, function(value, key) {
+        should(obj[key]).containDeepOrdered(value);
+      });
+
+      // if both objects is empty means we finish traversing - and we need to compare for hidden values
+      if(util.isEmptyObject(other)) {
+        this.eql(other);
+      }
+    } else {
+      this.eql(other);
+    }
+  });
+
+  /**
+   * The same like `Assertion#containDeepOrdered` but all checks on arrays without order.
+   *
+   * @name containDeep
+   * @memberOf Assertion
+   * @category assertion contain
+   * @param {*} other Nested object
+   * @example
+   *
+   * [ 1, 2, 3].should.containDeep([2, 1]);
+   * [ 1, 2, [ 1, 2, 3 ]].should.containDeep([ 1, [ 3, 1 ]]);
+   */
+  Assertion.add('containDeep', function(other) {
+    this.params = {operator: 'to contain ' + i(other)};
+
+    var obj = this.obj;
+    if(typeof obj == 'string') {// expect other to be string
+      this.is.equal(String(other));
+    } else if(util.isIndexable(obj) && util.isIndexable(other)) {
+      var usedKeys = {};
+      util.forEach(other, function(otherItem) {
+        this.assert(util.some(obj, function(item, index) {
+          if(index in usedKeys) return false;
+
+          try {
+            should(item).containDeep(otherItem);
+            usedKeys[index] = true;
+            return true;
+          } catch(e) {
+            if(e instanceof should.AssertionError) {
+              return false;
+            }
+            throw e;
+          }
+        }));
+      }, this);
+    } else if(obj != null && other != null && typeof obj == 'object' && typeof other == 'object') {// object contains object case
+      util.forEach(other, function(value, key) {
+        should(obj[key]).containDeep(value);
+      });
+
+      // if both objects is empty means we finish traversing - and we need to compare for hidden values
+      if(util.isEmptyObject(other)) {
+        this.eql(other);
+      }
+    } else {
+      this.eql(other);
+    }
+  });
+
+};
diff --git a/node_modules/should/lib/ext/eql.js b/node_modules/should/lib/ext/eql.js
new file mode 100644
index 0000000..0ebf1be
--- /dev/null
+++ b/node_modules/should/lib/ext/eql.js
@@ -0,0 +1,136 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var eql = require('should-equal');
+var type = require('should-type');
+var util = require('../util');
+
+function formatEqlResult(r, a, b) {
+  return ((r.path.length > 0 ? 'at ' + r.path.map(util.formatProp).join(' -> ') : '') +
+  (r.a === a ? '' : ', A has ' + util.format(r.a)) +
+  (r.b === b ? '' : ' and B has ' + util.format(r.b)) +
+  (r.showReason ? ' because ' + r.reason : '')).trim();
+}
+
+module.exports = function(should, Assertion) {
+
+  /**
+   * Deep object equality comparison. For full spec see [`should-equal tests`](https://github.com/shouldjs/equal/blob/master/test.js).
+   *
+   * @name eql
+   * @memberOf Assertion
+   * @category assertion equality
+   * @alias Assertion#deepEqual
+   * @param {*} val Expected value
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (10).should.be.eql(10);
+   * ('10').should.not.be.eql(10);
+   * (-0).should.not.be.eql(+0);
+   *
+   * NaN.should.be.eql(NaN);
+   *
+   * ({ a: 10}).should.be.eql({ a: 10 });
+   * [ 'a' ].should.not.be.eql({ '0': 'a' });
+   */
+  Assertion.add('eql', function(val, description) {
+    this.params = {operator: 'to equal', expected: val, message: description};
+
+    var result = eql(this.obj, val, should.config);
+    this.params.details = result.result ? '' : formatEqlResult(result, this.obj, val);
+
+    this.params.showDiff = eql(type(this.obj), type(val)).result;
+
+    this.assert(result.result);
+  });
+
+  /**
+   * Exact comparison using ===.
+   *
+   * @name equal
+   * @memberOf Assertion
+   * @category assertion equality
+   * @alias Assertion#exactly
+   * @param {*} val Expected value
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * 10.should.be.equal(10);
+   * 'a'.should.be.exactly('a');
+   *
+   * should(null).be.exactly(null);
+   */
+  Assertion.add('equal', function(val, description) {
+    this.params = {operator: 'to be', expected: val, message: description};
+
+    this.params.showDiff = eql(type(this.obj), type(val)).result;
+
+    this.assert(val === this.obj);
+  });
+
+  Assertion.alias('equal', 'exactly');
+  Assertion.alias('eql', 'deepEqual');
+
+  function addOneOf(name, message, method) {
+    Assertion.add(name, function(vals) {
+      if(arguments.length !== 1) {
+        vals = Array.prototype.slice.call(arguments);
+      } else {
+        should(vals).be.Array();
+      }
+
+      this.params = {operator: message, expected: vals};
+
+      var obj = this.obj;
+      var found = false;
+
+      util.forEach(vals, function(val) {
+        try {
+          should(val)[method](obj);
+          found = true;
+          return false;
+        } catch(e) {
+          if(e instanceof should.AssertionError) {
+            return;//do nothing
+          }
+          throw e;
+        }
+      });
+
+      this.assert(found);
+    });
+  }
+
+  /**
+   * Exact comparison using === to be one of supplied objects.
+   *
+   * @name equalOneOf
+   * @memberOf Assertion
+   * @category assertion equality
+   * @param {Array|*} vals Expected values
+   * @example
+   *
+   * 'ab'.should.be.equalOneOf('a', 10, 'ab');
+   * 'ab'.should.be.equalOneOf(['a', 10, 'ab']);
+   */
+  addOneOf('equalOneOf', 'to be equals one of', 'equal');
+
+  /**
+   * Exact comparison using .eql to be one of supplied objects.
+   *
+   * @name oneOf
+   * @memberOf Assertion
+   * @category assertion equality
+   * @param {Array|*} vals Expected values
+   * @example
+   *
+   * ({a: 10}).should.be.oneOf('a', 10, 'ab', {a: 10});
+   * ({a: 10}).should.be.oneOf(['a', 10, 'ab', {a: 10}]);
+   */
+  addOneOf('oneOf', 'to be one of', 'eql');
+
+};
diff --git a/node_modules/should/lib/ext/error.js b/node_modules/should/lib/ext/error.js
new file mode 100644
index 0000000..6a769b1
--- /dev/null
+++ b/node_modules/should/lib/ext/error.js
@@ -0,0 +1,109 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+var util = require('../util');
+
+module.exports = function(should, Assertion) {
+  var i = should.format;
+
+  /**
+   * Assert given function throws error with such message.
+   *
+   * @name throw
+   * @memberOf Assertion
+   * @category assertion errors
+   * @alias Assertion#throwError
+   * @param {string|RegExp|Function|Object|GeneratorFunction|GeneratorObject} [message] Message to match or properties
+   * @param {Object} [properties] Optional properties that will be matched to thrown error
+   * @example
+   *
+   * (function(){ throw new Error('fail') }).should.throw();
+   * (function(){ throw new Error('fail') }).should.throw('fail');
+   * (function(){ throw new Error('fail') }).should.throw(/fail/);
+   *
+   * (function(){ throw new Error('fail') }).should.throw(Error);
+   * var error = new Error();
+   * error.a = 10;
+   * (function(){ throw error; }).should.throw(Error, { a: 10 });
+   * (function(){ throw error; }).should.throw({ a: 10 });
+   * (function*() {
+   *   yield throwError();
+   * }).should.throw();
+   */
+  Assertion.add('throw', function(message, properties) {
+    var fn = this.obj
+      , err = {}
+      , errorInfo = ''
+      , thrown = false;
+
+    if(util.isGeneratorFunction(fn)) {
+      return should(fn()).throw(message, properties);
+    } else if(util.isGeneratorObject(fn)) {
+      return should(fn.next.bind(fn)).throw(message, properties);
+    }
+
+    this.is.a.Function();
+
+    var errorMatched = true;
+
+    try {
+      fn();
+    } catch(e) {
+      thrown = true;
+      err = e;
+    }
+
+    if(thrown) {
+      if(message) {
+        if('string' == typeof message) {
+          errorMatched = message == err.message;
+        } else if(message instanceof RegExp) {
+          errorMatched = message.test(err.message);
+        } else if('function' == typeof message) {
+          errorMatched = err instanceof message;
+        } else if(null != message) {
+          try {
+            should(err).match(message);
+          } catch(e) {
+            if(e instanceof should.AssertionError) {
+              errorInfo = ": " + e.message;
+              errorMatched = false;
+            } else {
+              throw e;
+            }
+          }
+        }
+
+        if(!errorMatched) {
+          if('string' == typeof message || message instanceof RegExp) {
+            errorInfo = " with a message matching " + i(message) + ", but got '" + err.message + "'";
+          } else if('function' == typeof message) {
+            errorInfo = " of type " + util.functionName(message) + ", but got " + util.functionName(err.constructor);
+          }
+        } else if('function' == typeof message && properties) {
+          try {
+            should(err).match(properties);
+          } catch(e) {
+            if(e instanceof should.AssertionError) {
+              errorInfo = ": " + e.message;
+              errorMatched = false;
+            } else {
+              throw e;
+            }
+          }
+        }
+      } else {
+        errorInfo = " (got " + i(err) + ")";
+      }
+    }
+
+    this.params = { operator: 'to throw exception' + errorInfo };
+
+    this.assert(thrown);
+    this.assert(errorMatched);
+  });
+
+  Assertion.alias('throw', 'throwError');
+};
diff --git a/node_modules/should/lib/ext/match.js b/node_modules/should/lib/ext/match.js
new file mode 100644
index 0000000..4396172
--- /dev/null
+++ b/node_modules/should/lib/ext/match.js
@@ -0,0 +1,208 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util');
+var eql = require('should-equal');
+
+module.exports = function(should, Assertion) {
+  var i = should.format;
+
+  /**
+   * Asserts if given object match `other` object, using some assumptions:
+   * First object matched if they are equal,
+   * If `other` is a regexp and given object is a string check on matching with regexp
+   * If `other` is a regexp and given object is an array check if all elements matched regexp
+   * If `other` is a regexp and given object is an object check values on matching regexp
+   * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
+   * If `other` is an object check if the same keys matched with above rules
+   * All other cases failed.
+   *
+   * Usually it is right idea to add pre type assertions, like `.String()` or `.Object()` to be sure assertions will do what you are expecting.
+   * Object iteration happen by keys (properties with enumerable: true), thus some objects can cause small pain. Typical example is js
+   * Error - it by default has 2 properties `name` and `message`, but they both non-enumerable. In this case make sure you specify checking props (see examples).
+   *
+   * @name match
+   * @memberOf Assertion
+   * @category assertion matching
+   * @param {*} other Object to match
+   * @param {string} [description] Optional message
+   * @example
+   * 'foobar'.should.match(/^foo/);
+   * 'foobar'.should.not.match(/^bar/);
+   *
+   * ({ a: 'foo', c: 'barfoo' }).should.match(/foo$/);
+   *
+   * ['a', 'b', 'c'].should.match(/[a-z]/);
+   *
+   * (5).should.not.match(function(n) {
+   *   return n < 0;
+   * });
+   * (5).should.not.match(function(it) {
+   *    it.should.be.an.Array();
+   * });
+   * ({ a: 10, b: 'abc', c: { d: 10 }, d: 0 }).should
+   * .match({ a: 10, b: /c$/, c: function(it) {
+   *    return it.should.have.property('d', 10);
+   * }});
+   *
+   * [10, 'abc', { d: 10 }, 0].should
+   * .match({ '0': 10, '1': /c$/, '2': function(it) {
+   *    return it.should.have.property('d', 10);
+   * }});
+   *
+   * var myString = 'abc';
+   *
+   * myString.should.be.a.String().and.match(/abc/);
+   *
+   * myString = {};
+   *
+   * myString.should.match(/abc/); //yes this will pass
+   * //better to do
+   * myString.should.be.an.Object().and.not.empty().and.match(/abc/);//fixed
+   *
+   * (new Error('boom')).should.match(/abc/);//passed because no keys
+   * (new Error('boom')).should.not.match({ message: /abc/ });//check specified property
+   */
+  Assertion.add('match', function(other, description) {
+    this.params = {operator: 'to match ' + i(other), message: description};
+
+    if(!eql(this.obj, other).result) {
+      if(other instanceof RegExp) { // something - regex
+
+        if(typeof this.obj == 'string') {
+
+          this.assert(other.exec(this.obj));
+        } else if(util.isIndexable(this.obj)) {
+          util.forEach(this.obj, function(item) {
+            this.assert(other.exec(item));// should we try to convert to String and exec?
+          }, this);
+        } else if(null != this.obj && typeof this.obj == 'object') {
+
+          var notMatchedProps = [], matchedProps = [];
+          util.forEach(this.obj, function(value, name) {
+            if(other.exec(value)) matchedProps.push(util.formatProp(name));
+            else notMatchedProps.push(util.formatProp(name) + ' (' + i(value) + ')');
+          }, this);
+
+          if(notMatchedProps.length)
+            this.params.operator += '\n    not matched properties: ' + notMatchedProps.join(', ');
+          if(matchedProps.length)
+            this.params.operator += '\n    matched properties: ' + matchedProps.join(', ');
+
+          this.assert(notMatchedProps.length === 0);
+        } // should we try to convert to String and exec?
+      } else if(typeof other == 'function') {
+        var res;
+
+        res = other(this.obj);
+
+        //if(res instanceof Assertion) {
+        //  this.params.operator += '\n    ' + res.getMessage();
+        //}
+
+        //if we throw exception ok - it is used .should inside
+        if(typeof res == 'boolean') {
+          this.assert(res); // if it is just boolean function assert on it
+        }
+      } else if(other != null && this.obj != null && typeof other == 'object') { // try to match properties (for Object and Array)
+        notMatchedProps = [];
+        matchedProps = [];
+
+        util.forEach(other, function(value, key) {
+          try {
+            should(this.obj).have.property(key).which.match(value);
+            matchedProps.push(util.formatProp(key));
+          } catch(e) {
+            if(e instanceof should.AssertionError) {
+              notMatchedProps.push(util.formatProp(key) + ' (' + i(this.obj[key]) + ')');
+            } else {
+              throw e;
+            }
+          }
+        }, this);
+
+        if(notMatchedProps.length)
+          this.params.operator += '\n    not matched properties: ' + notMatchedProps.join(', ');
+        if(matchedProps.length)
+          this.params.operator += '\n    matched properties: ' + matchedProps.join(', ');
+
+        this.assert(notMatchedProps.length === 0);
+      } else {
+        this.assert(false);
+      }
+    }
+  });
+
+  /**
+   * Asserts if given object values or array elements all match `other` object, using some assumptions:
+   * First object matched if they are equal,
+   * If `other` is a regexp - matching with regexp
+   * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
+   * All other cases check if this `other` equal to each element
+   *
+   * @name matchEach
+   * @memberOf Assertion
+   * @category assertion matching
+   * @alias Assertion#matchSome
+   * @param {*} other Object to match
+   * @param {string} [description] Optional message
+   * @example
+   * [ 'a', 'b', 'c'].should.matchEach(/\w+/);
+   * [ 'a', 'a', 'a'].should.matchEach('a');
+   *
+   * [ 'a', 'a', 'a'].should.matchEach(function(value) { value.should.be.eql('a') });
+   *
+   * { a: 'a', b: 'a', c: 'a' }.should.matchEach(function(value) { value.should.be.eql('a') });
+   */
+  Assertion.add('matchEach', function(other, description) {
+    this.params = {operator: 'to match each ' + i(other), message: description};
+
+    util.forEach(this.obj, function(value) {
+      should(value).match(other);
+    }, this);
+  });
+
+  /**
+  * Asserts if any of given object values or array elements match `other` object, using some assumptions:
+  * First object matched if they are equal,
+  * If `other` is a regexp - matching with regexp
+  * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
+  * All other cases check if this `other` equal to each element
+  *
+  * @name matchAny
+  * @memberOf Assertion
+  * @category assertion matching
+  * @param {*} other Object to match
+  * @alias Assertion#matchEvery
+  * @param {string} [description] Optional message
+  * @example
+  * [ 'a', 'b', 'c'].should.matchAny(/\w+/);
+  * [ 'a', 'b', 'c'].should.matchAny('a');
+  *
+  * [ 'a', 'b', 'c'].should.matchAny(function(value) { value.should.be.eql('a') });
+  *
+  * { a: 'a', b: 'b', c: 'c' }.should.matchAny(function(value) { value.should.be.eql('a') });
+  */
+  Assertion.add('matchAny', function(other, description) {
+    this.params = {operator: 'to match any ' + i(other), message: description};
+
+    this.assert(util.some(this.obj, function(value) {
+      try {
+        should(value).match(other);
+        return true;
+      } catch(e) {
+        if(e instanceof should.AssertionError) {
+          // Caught an AssertionError, return false to the iterator
+          return false;
+        }
+        throw e;
+      }
+    }));
+  });
+
+  Assertion.alias('matchAny', 'matchSome');
+  Assertion.alias('matchEach', 'matchEvery');
+};
diff --git a/node_modules/should/lib/ext/number.js b/node_modules/should/lib/ext/number.js
new file mode 100644
index 0000000..160fa0f
--- /dev/null
+++ b/node_modules/should/lib/ext/number.js
@@ -0,0 +1,166 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+module.exports = function(should, Assertion) {
+
+  /**
+   * Assert given object is NaN
+   * @name NaN
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @example
+   *
+   * (10).should.not.be.NaN();
+   * NaN.should.be.NaN();
+   */
+  Assertion.add('NaN', function() {
+    this.params = { operator: 'to be NaN' };
+
+    this.assert(this.obj !== this.obj);
+  });
+
+  /**
+   * Assert given object is not finite (positive or negative)
+   *
+   * @name Infinity
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @example
+   *
+   * (10).should.not.be.Infinity();
+   * NaN.should.not.be.Infinity();
+   */
+  Assertion.add('Infinity', function() {
+    this.params = { operator: 'to be Infinity' };
+
+    this.is.a.Number()
+      .and.not.a.NaN()
+      .and.assert(!isFinite(this.obj));
+  });
+
+  /**
+   * Assert given number between `start` and `finish` or equal one of them.
+   *
+   * @name within
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} start Start number
+   * @param {number} finish Finish number
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (10).should.be.within(0, 20);
+   */
+  Assertion.add('within', function(start, finish, description) {
+    this.params = { operator: 'to be within ' + start + '..' + finish, message: description };
+
+    this.assert(this.obj >= start && this.obj <= finish);
+  });
+
+  /**
+   * Assert given number near some other `value` within `delta`
+   *
+   * @name approximately
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} value Center number
+   * @param {number} delta Radius
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (9.99).should.be.approximately(10, 0.1);
+   */
+  Assertion.add('approximately', function(value, delta, description) {
+    this.params = { operator: 'to be approximately ' + value + ' ±' + delta, message: description };
+
+    this.assert(Math.abs(this.obj - value) <= delta);
+  });
+
+  /**
+   * Assert given number above `n`.
+   *
+   * @name above
+   * @alias Assertion#greaterThan
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} n Margin number
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (10).should.be.above(0);
+   */
+  Assertion.add('above', function(n, description) {
+    this.params = { operator: 'to be above ' + n, message: description };
+
+    this.assert(this.obj > n);
+  });
+
+  /**
+   * Assert given number below `n`.
+   *
+   * @name below
+   * @alias Assertion#lessThan
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} n Margin number
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (0).should.be.below(10);
+   */
+  Assertion.add('below', function(n, description) {
+    this.params = { operator: 'to be below ' + n, message: description };
+
+    this.assert(this.obj < n);
+  });
+
+  Assertion.alias('above', 'greaterThan');
+  Assertion.alias('below', 'lessThan');
+
+  /**
+   * Assert given number above `n`.
+   *
+   * @name aboveOrEqual
+   * @alias Assertion#greaterThanOrEqual
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} n Margin number
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (10).should.be.aboveOrEqual(0);
+   * (10).should.be.aboveOrEqual(10);
+   */
+  Assertion.add('aboveOrEqual', function(n, description) {
+    this.params = { operator: 'to be above or equal' + n, message: description };
+
+    this.assert(this.obj >= n);
+  });
+
+  /**
+   * Assert given number below `n`.
+   *
+   * @name belowOrEqual
+   * @alias Assertion#lessThanOrEqual
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} n Margin number
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (0).should.be.belowOrEqual(10);
+   * (0).should.be.belowOrEqual(0);
+   */
+  Assertion.add('belowOrEqual', function(n, description) {
+    this.params = { operator: 'to be below or equal' + n, message: description };
+
+    this.assert(this.obj <= n);
+  });
+
+  Assertion.alias('aboveOrEqual', 'greaterThanOrEqual');
+  Assertion.alias('belowOrEqual', 'lessThanOrEqual');
+
+};
diff --git a/node_modules/should/lib/ext/promise.js b/node_modules/should/lib/ext/promise.js
new file mode 100644
index 0000000..f8dce05
--- /dev/null
+++ b/node_modules/should/lib/ext/promise.js
@@ -0,0 +1,236 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util');
+var PromisedAssertion = require('../assertion').PromisedAssertion;
+var Assertion = require('../assertion');
+
+module.exports = function(should) {
+  /**
+   * Assert given object is a Promise
+   *
+   * @name Promise
+   * @memberOf Assertion
+   * @category assertion promises
+   * @example
+   *
+   * promise.should.be.Promise()
+   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.a.Promise()
+   * (10).should.not.be.a.Promise()
+   */
+  Assertion.add('Promise', function() {
+    this.params = {operator: 'to be promise'};
+
+    var obj = this.obj;
+
+    should(obj).have.property('then')
+      .which.is.a.Function();
+  });
+
+  /**
+   * Assert given promise will be fulfilled
+   *
+   * @name fulfilled
+   * @memberOf Assertion
+   * @returns {Promise}
+   * @category assertion promises
+   * @example
+   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.fulfilled()
+   */
+  Assertion.prototype.fulfilled = function Assertion$fulfilled() {
+    this.params = {operator: 'to be fulfilled'};
+
+    should(this.obj).be.a.Promise();
+
+    var that = this;
+    return this.obj.then(function next$onResolve(value) {
+      if (that.negate) {
+        that.fail();
+      }
+      return value;
+    }, function next$onReject(err) {
+      if (!that.negate) {
+        that.fail();
+      }
+      return err;
+    });
+  };
+
+  /**
+   * Assert given promise will be rejected
+   *
+   * @name rejected
+   * @memberOf Assertion
+   * @category assertion promises
+   * @returns {Promise}
+   * @example
+   * (new Promise(function(resolve, reject) { resolve(10); })).should.not.be.rejected()
+   */
+  Assertion.prototype.rejected = function() {
+    this.params = {operator: 'to be rejected'};
+
+    should(this.obj).be.a.Promise();
+
+    var that = this;
+    return this.obj.then(function(value) {
+      if (!that.negate) {
+        that.fail();
+      }
+      return value;
+    }, function next$onError(err) {
+      if (that.negate) {
+        that.fail();
+      }
+      return err;
+    });
+  };
+
+  /**
+   * Assert given promise will be fulfilled with some expected value.
+   *
+   * @name fulfilledWith
+   * @memberOf Assertion
+   * @category assertion promises
+   * @returns {Promise}
+   * @example
+   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.fulfilledWith(10)
+   */
+  Assertion.prototype.fulfilledWith = function(expectedValue) {
+    this.params = {operator: 'to be fulfilled'};
+
+    should(this.obj).be.a.Promise();
+
+    var that = this;
+    return this.obj.then(function(value) {
+      if (that.negate) {
+        that.fail();
+      }
+      should(value).eql(expectedValue);
+      return value;
+    }, function next$onError(err) {
+      if (!that.negate) {
+        that.fail();
+      }
+      return err;
+    });
+  };
+
+  /**
+   * Assert given promise will be rejected with some sort of error. Arguments is the same for Assertion#throw
+   *
+   * @name rejectedWith
+   * @memberOf Assertion
+   * @category assertion promises
+   * @returns {Promise}
+   * @example
+   *
+   * function failedPromise() {
+  *   return new Promise(function(resolve, reject) {
+  *     reject(new Error('boom'))
+  *   })
+  * }
+   * failedPromise().should.be.rejectedWith(Error)
+   * failedPromise().should.be.rejectedWith('boom')
+   * failedPromise().should.be.rejectedWith(/boom/)
+   * failedPromise().should.be.rejectedWith(Error, { message: 'boom' })
+   * failedPromise().should.be.rejectedWith({ message: 'boom' })
+   */
+  Assertion.prototype.rejectedWith = function(message, properties) {
+    this.params = {operator: 'to be rejected'};
+
+    should(this.obj).be.a.Promise();
+
+    var that = this;
+    return this.obj.then(function(value) {
+      if (!that.negate) {
+        that.fail();
+      }
+      return value;
+    }, function next$onError(err) {
+      if (that.negate) {
+        that.fail();
+      }
+
+      var errorMatched = true;
+      var errorInfo = '';
+
+      if ('string' === typeof message) {
+        errorMatched = message === err.message;
+      } else if (message instanceof RegExp) {
+        errorMatched = message.test(err.message);
+      } else if ('function' === typeof message) {
+        errorMatched = err instanceof message;
+      } else if (message !== null && typeof message === 'object') {
+        try {
+          should(err).match(message);
+        } catch (e) {
+          if (e instanceof should.AssertionError) {
+            errorInfo = ': ' + e.message;
+            errorMatched = false;
+          } else {
+            throw e;
+          }
+        }
+      }
+
+      if (!errorMatched) {
+        if ( typeof message === 'string' || message instanceof RegExp) {
+          errorInfo = ' with a message matching ' + should.format(message) + ", but got '" + err.message + "'";
+        } else if ('function' === typeof message) {
+          errorInfo = ' of type ' + util.functionName(message) + ', but got ' + util.functionName(err.constructor);
+        }
+      } else if ('function' === typeof message && properties) {
+        try {
+          should(err).match(properties);
+        } catch (e) {
+          if (e instanceof should.AssertionError) {
+            errorInfo = ': ' + e.message;
+            errorMatched = false;
+          } else {
+            throw e;
+          }
+        }
+      }
+
+      that.params.operator += errorInfo;
+
+      that.assert(errorMatched);
+
+      return err;
+    });
+  };
+
+  /**
+   * Assert given object is promise and wrap it in PromisedAssertion, which has all properties of Assertion. That means you can chain as with usual Assertion.
+   *
+   * @name finally
+   * @memberOf Assertion
+   * @alias Assertion#eventually
+   * @category assertion promises
+   * @returns {PromisedAssertion} Like Assertion, but .then this.obj in Assertion
+   * @example
+   *
+   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.eventually.equal(10)
+   */
+  Object.defineProperty(Assertion.prototype, 'finally', {
+    get: function() {
+      should(this.obj).be.a.Promise();
+
+      var that = this;
+
+      return new PromisedAssertion(this.obj.then(function(obj) {
+        var a = should(obj);
+
+        a.negate = that.negate;
+        a.anyOne = that.anyOne;
+
+        return a;
+      }));
+    }
+  });
+
+  Assertion.alias('finally', 'eventually');
+};
diff --git a/node_modules/should/lib/ext/property.js b/node_modules/should/lib/ext/property.js
new file mode 100644
index 0000000..ac35491
--- /dev/null
+++ b/node_modules/should/lib/ext/property.js
@@ -0,0 +1,370 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util');
+var eql = require('should-equal');
+
+var aSlice = Array.prototype.slice;
+
+module.exports = function(should, Assertion) {
+  var i = should.format;
+  /**
+   * Asserts given object has some descriptor. **On success it change given object to be value of property**.
+   *
+   * @name propertyWithDescriptor
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {string} name Name of property
+   * @param {Object} desc Descriptor like used in Object.defineProperty (not required to add all properties)
+   * @example
+   *
+   * ({ a: 10 }).should.have.propertyWithDescriptor('a', { enumerable: true });
+   */
+  Assertion.add('propertyWithDescriptor', function(name, desc) {
+    this.params = {actual: this.obj, operator: 'to have own property with descriptor ' + i(desc)};
+    var obj = this.obj;
+    this.have.ownProperty(name);
+    should(Object.getOwnPropertyDescriptor(Object(obj), name)).have.properties(desc);
+  });
+
+  function processPropsArgs() {
+    var args = {};
+    if(arguments.length > 1) {
+      args.names = aSlice.call(arguments);
+    } else {
+      var arg = arguments[0];
+      if(typeof arg === 'string') {
+        args.names = [arg];
+      } else if(util.isIndexable(arg)) {
+        args.names = arg;
+      } else {
+        args.names = Object.keys(arg);
+        args.values = arg;
+      }
+    }
+    return args;
+  }
+
+
+  /**
+   * Asserts given object has enumerable property with optionally value. **On success it change given object to be value of property**.
+   *
+   * @name enumerable
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {string} name Name of property
+   * @param {*} [val] Optional property value to check
+   * @example
+   *
+   * ({ a: 10 }).should.have.enumerable('a');
+   */
+  Assertion.add('enumerable', function(name, val) {
+    name = util.convertPropertyName(name);
+
+    this.params = {
+      operator: "to have enumerable property " + util.formatProp(name) + (arguments.length > 1 ? " equal to " + i(val): "")
+    };
+
+    var desc = { enumerable: true };
+    if(arguments.length > 1) desc.value = val;
+    this.have.propertyWithDescriptor(name, desc);
+  });
+
+  /**
+   * Asserts given object has enumerable properties
+   *
+   * @name enumerables
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {Array|...string|Object} names Names of property
+   * @example
+   *
+   * ({ a: 10, b: 10 }).should.have.enumerables('a');
+   */
+  Assertion.add('enumerables', function(names) {
+    var args = processPropsArgs.apply(null, arguments);
+
+    this.params = {
+      operator: "to have enumerables " + args.names.map(util.formatProp)
+    };
+
+    var obj = this.obj;
+    args.names.forEach(function(name) {
+      should(obj).have.enumerable(name);
+    });
+  });
+
+  /**
+   * Asserts given object has property with optionally value. **On success it change given object to be value of property**.
+   *
+   * @name property
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {string} name Name of property
+   * @param {*} [val] Optional property value to check
+   * @example
+   *
+   * ({ a: 10 }).should.have.property('a');
+   */
+  Assertion.add('property', function(name, val) {
+    name = util.convertPropertyName(name);
+    if(arguments.length > 1) {
+      var p = {};
+      p[name] = val;
+      this.have.properties(p);
+    } else {
+      this.have.properties(name);
+    }
+    this.obj = this.obj[name];
+  });
+
+  /**
+   * Asserts given object has properties. On this method affect .any modifier, which allow to check not all properties.
+   *
+   * @name properties
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {Array|...string|Object} names Names of property
+   * @example
+   *
+   * ({ a: 10 }).should.have.properties('a');
+   * ({ a: 10, b: 20 }).should.have.properties([ 'a' ]);
+   * ({ a: 10, b: 20 }).should.have.properties({ b: 20 });
+   */
+  Assertion.add('properties', function(names) {
+    var values = {};
+    if(arguments.length > 1) {
+      names = aSlice.call(arguments);
+    } else if(!Array.isArray(names)) {
+      if(typeof names == 'string' || typeof names == 'symbol') {
+        names = [names];
+      } else {
+        values = names;
+        names = Object.keys(names);
+      }
+    }
+
+    var obj = Object(this.obj), missingProperties = [];
+
+    //just enumerate properties and check if they all present
+    names.forEach(function(name) {
+      if(!(name in obj)) missingProperties.push(util.formatProp(name));
+    });
+
+    var props = missingProperties;
+    if(props.length === 0) {
+      props = names.map(util.formatProp);
+    } else if(this.anyOne) {
+      props = names.filter(function(name) {
+        return missingProperties.indexOf(util.formatProp(name)) < 0;
+      }).map(util.formatProp);
+    }
+
+    var operator = (props.length === 1 ?
+        'to have property ' : 'to have ' + (this.anyOne ? 'any of ' : '') + 'properties ') + props.join(', ');
+
+    this.params = {obj: this.obj, operator: operator};
+
+    //check that all properties presented
+    //or if we request one of them that at least one them presented
+    this.assert(missingProperties.length === 0 || (this.anyOne && missingProperties.length != names.length));
+
+    // check if values in object matched expected
+    var valueCheckNames = Object.keys(values);
+    if(valueCheckNames.length) {
+      var wrongValues = [];
+      props = [];
+
+      // now check values, as there we have all properties
+      valueCheckNames.forEach(function(name) {
+        var value = values[name];
+        if(!eql(obj[name], value).result) {
+          wrongValues.push(util.formatProp(name) + ' of ' + i(value) + ' (got ' + i(obj[name]) + ')');
+        } else {
+          props.push(util.formatProp(name) + ' of ' + i(value));
+        }
+      });
+
+      if((wrongValues.length !== 0 && !this.anyOne) || (this.anyOne && props.length === 0)) {
+        props = wrongValues;
+      }
+
+      operator = (props.length === 1 ?
+        'to have property ' : 'to have ' + (this.anyOne ? 'any of ' : '') + 'properties ') + props.join(', ');
+
+      this.params = {obj: this.obj, operator: operator};
+
+      //if there is no not matched values
+      //or there is at least one matched
+      this.assert(wrongValues.length === 0 || (this.anyOne && wrongValues.length != valueCheckNames.length));
+    }
+  });
+
+  /**
+   * Asserts given object has property `length` with given value `n`
+   *
+   * @name length
+   * @alias Assertion#lengthOf
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {number} n Expected length
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * [1, 2].should.have.length(2);
+   */
+  Assertion.add('length', function(n, description) {
+    this.have.property('length', n, description);
+  });
+
+  Assertion.alias('length', 'lengthOf');
+
+  var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+  /**
+   * Asserts given object has own property. **On success it change given object to be value of property**.
+   *
+   * @name ownProperty
+   * @alias Assertion#hasOwnProperty
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {string} name Name of property
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * ({ a: 10 }).should.have.ownProperty('a');
+   */
+  Assertion.add('ownProperty', function(name, description) {
+    name = util.convertPropertyName(name);
+    this.params = {
+      actual: this.obj,
+      operator: 'to have own property ' + util.formatProp(name),
+      message: description
+    };
+
+    this.assert(hasOwnProperty.call(this.obj, name));
+
+    this.obj = this.obj[name];
+  });
+
+  Assertion.alias('ownProperty', 'hasOwnProperty');
+
+  /**
+   * Asserts given object is empty. For strings, arrays and arguments it checks .length property, for objects it checks keys.
+   *
+   * @name empty
+   * @memberOf Assertion
+   * @category assertion property
+   * @example
+   *
+   * ''.should.be.empty();
+   * [].should.be.empty();
+   * ({}).should.be.empty();
+   */
+  Assertion.add('empty', function() {
+    this.params = {operator: 'to be empty'};
+
+    if(util.length(this.obj) !== void 0) {
+      should(this.obj).have.property('length', 0);
+    } else {
+      var obj = Object(this.obj); // wrap to reference for booleans and numbers
+      for(var prop in obj) {
+        should(this.obj).not.have.ownProperty(prop);
+      }
+    }
+  }, true);
+
+  /**
+   * Asserts given object has exact keys. Compared to `properties`, `keys` does not accept Object as a argument.
+   *
+   * @name keys
+   * @alias Assertion#key
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {Array|...string} [keys] Keys to check
+   * @example
+   *
+   * ({ a: 10 }).should.have.keys('a');
+   * ({ a: 10, b: 20 }).should.have.keys('a', 'b');
+   * ({ a: 10, b: 20 }).should.have.keys([ 'a', 'b' ]);
+   * ({}).should.have.keys();
+   */
+  Assertion.add('keys', function(keys) {
+    if(arguments.length > 1) keys = aSlice.call(arguments);
+    else if(arguments.length === 1 && typeof keys === 'string') keys = [keys];
+    else if(arguments.length === 0) keys = [];
+
+    keys = keys.map(String);
+
+    var obj = Object(this.obj);
+
+    // first check if some keys are missing
+    var missingKeys = [];
+    keys.forEach(function(key) {
+      if(!hasOwnProperty.call(this.obj, key))
+        missingKeys.push(util.formatProp(key));
+    }, this);
+
+    // second check for extra keys
+    var extraKeys = [];
+    Object.keys(obj).forEach(function(key) {
+      if(keys.indexOf(key) < 0) {
+        extraKeys.push(util.formatProp(key));
+      }
+    });
+
+    var verb = keys.length === 0 ? 'to be empty' :
+    'to have ' + (keys.length === 1 ? 'key ' : 'keys ');
+
+    this.params = {operator: verb + keys.map(util.formatProp).join(', ')};
+
+    if(missingKeys.length > 0)
+      this.params.operator += '\n\tmissing keys: ' + missingKeys.join(', ');
+
+    if(extraKeys.length > 0)
+      this.params.operator += '\n\textra keys: ' + extraKeys.join(', ');
+
+    this.assert(missingKeys.length === 0 && extraKeys.length === 0);
+  });
+
+  Assertion.alias("keys", "key");
+
+  /**
+   * Asserts given object has nested property in depth by path. **On success it change given object to be value of final property**.
+   *
+   * @name propertyByPath
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {Array|...string} properties Properties path to search
+   * @example
+   *
+   * ({ a: {b: 10}}).should.have.propertyByPath('a', 'b').eql(10);
+   */
+  Assertion.add('propertyByPath', function(properties) {
+    if(arguments.length > 1) properties = aSlice.call(arguments);
+    else if(arguments.length === 1 && typeof properties == 'string') properties = [properties];
+    else if(arguments.length === 0) properties = [];
+
+    var allProps = properties.map(util.formatProp);
+
+    properties = properties.map(String);
+
+    var obj = should(Object(this.obj));
+
+    var foundProperties = [];
+
+    var currentProperty;
+    while(currentProperty = properties.shift()) {
+      this.params = {operator: 'to have property by path ' + allProps.join(', ') + ' - failed on ' + util.formatProp(currentProperty)};
+      obj = obj.have.property(currentProperty);
+      foundProperties.push(currentProperty);
+    }
+
+    this.params = {obj: this.obj, operator: 'to have property by path ' + allProps.join(', ')};
+
+    this.obj = obj.obj;
+  });
+};
diff --git a/node_modules/should/lib/ext/string.js b/node_modules/should/lib/ext/string.js
new file mode 100644
index 0000000..cd3c5da
--- /dev/null
+++ b/node_modules/should/lib/ext/string.js
@@ -0,0 +1,41 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+module.exports = function(should, Assertion) {
+  /**
+   * Assert given string starts with prefix
+   * @name startWith
+   * @memberOf Assertion
+   * @category assertion strings
+   * @param {string} str Prefix
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * 'abc'.should.startWith('a');
+   */
+  Assertion.add('startWith', function(str, description) {
+    this.params = { operator: 'to start with ' + should.format(str), message: description };
+
+    this.assert(0 === this.obj.indexOf(str));
+  });
+
+  /**
+   * Assert given string starts with prefix
+   * @name endWith
+   * @memberOf Assertion
+   * @category assertion strings
+   * @param {string} str Prefix
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * 'abca'.should.endWith('a');
+   */
+  Assertion.add('endWith', function(str, description) {
+    this.params = { operator: 'to end with ' + should.format(str), message: description };
+
+    this.assert(this.obj.indexOf(str, this.obj.length - str.length) >= 0);
+  });
+};
diff --git a/node_modules/should/lib/ext/type.js b/node_modules/should/lib/ext/type.js
new file mode 100644
index 0000000..ec85f3b
--- /dev/null
+++ b/node_modules/should/lib/ext/type.js
@@ -0,0 +1,224 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util');
+
+module.exports = function(should, Assertion) {
+  /**
+   * Assert given object is number
+   * @name Number
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Number', function() {
+    this.params = {operator: 'to be a number'};
+
+    this.have.type('number');
+  });
+
+  /**
+   * Assert given object is arguments
+   * @name arguments
+   * @alias Assertion#Arguments
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('arguments', function() {
+    this.params = {operator: 'to be arguments'};
+
+    this.have.class('Arguments');
+  });
+
+  Assertion.alias('arguments', 'Arguments');
+
+  /**
+   * Assert given object has some type using `typeof`
+   * @name type
+   * @memberOf Assertion
+   * @param {string} type Type name
+   * @param {string} [description] Optional message
+   * @category assertion types
+   */
+  Assertion.add('type', function(type, description) {
+    this.params = {operator: 'to have type ' + type, message: description};
+
+    should(typeof this.obj).be.exactly(type);
+  });
+
+  /**
+   * Assert given object is instance of `constructor`
+   * @name instanceof
+   * @alias Assertion#instanceOf
+   * @memberOf Assertion
+   * @param {Function} constructor Constructor function
+   * @param {string} [description] Optional message
+   * @category assertion types
+   */
+  Assertion.add('instanceof', function(constructor, description) {
+    this.params = {operator: 'to be an instance of ' + util.functionName(constructor), message: description};
+
+    this.assert(Object(this.obj) instanceof constructor);
+  });
+
+  Assertion.alias('instanceof', 'instanceOf');
+
+  /**
+   * Assert given object is function
+   * @name Function
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Function', function() {
+    this.params = {operator: 'to be a function'};
+
+    this.have.type('function');
+  });
+
+  /**
+   * Assert given object is object
+   * @name Object
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Object', function() {
+    this.params = {operator: 'to be an object'};
+
+    this.is.not.null().and.have.type('object');
+  });
+
+  /**
+   * Assert given object is string
+   * @name String
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('String', function() {
+    this.params = {operator: 'to be a string'};
+
+    this.have.type('string');
+  });
+
+  /**
+   * Assert given object is array
+   * @name Array
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Array', function() {
+    this.params = {operator: 'to be an array'};
+
+    this.have.class('Array');
+  });
+
+  /**
+   * Assert given object is boolean
+   * @name Boolean
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Boolean', function() {
+    this.params = {operator: 'to be a boolean'};
+
+    this.have.type('boolean');
+  });
+
+  /**
+   * Assert given object is error
+   * @name Error
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Error', function() {
+    this.params = {operator: 'to be an error'};
+
+    this.have.instanceOf(Error);
+  });
+
+  /**
+   * Assert given object is null
+   * @name null
+   * @alias Assertion#Null
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('null', function() {
+    this.params = {operator: 'to be null'};
+
+    this.assert(this.obj === null);
+  });
+
+  Assertion.alias('null', 'Null');
+
+  /**
+   * Assert given object has some internal [[Class]], via Object.prototype.toString call
+   * @name class
+   * @alias Assertion#Class
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('class', function(cls) {
+    this.params = {operator: 'to have [[Class]] ' + cls};
+
+    this.assert(Object.prototype.toString.call(this.obj) === '[object ' + cls + ']');
+  });
+
+  Assertion.alias('class', 'Class');
+
+  /**
+   * Assert given object is undefined
+   * @name undefined
+   * @alias Assertion#Undefined
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('undefined', function() {
+    this.params = {operator: 'to be undefined'};
+
+    this.assert(this.obj === void 0);
+  });
+
+  Assertion.alias('undefined', 'Undefined');
+
+  /**
+   * Assert given object supports es6 iterable protocol (just check
+   * that object has property Symbol.iterator, which is a function)
+   * @name iterable
+   * @memberOf Assertion
+   * @category assertion es6
+   */
+  Assertion.add('iterable', function() {
+    this.params = {operator: 'to be iterable'};
+
+    should(this.obj).have.property(Symbol.iterator).which.is.a.Function();
+  });
+
+  /**
+   * Assert given object supports es6 iterator protocol (just check
+   * that object has property next, which is a function)
+   * @name iterator
+   * @memberOf Assertion
+   * @category assertion es6
+   */
+  Assertion.add('iterator', function() {
+    this.params = {operator: 'to be iterator'};
+
+    should(this.obj).have.property('next').which.is.a.Function();
+  });
+
+  /**
+   * Assert given object is a generator object
+   * @name generator
+   * @memberOf Assertion
+   * @category assertion es6
+   */
+  Assertion.add('generator', function() {
+    this.params = {operator: 'to be generator'};
+
+    should(this.obj).be.iterable
+      .and.iterator
+      .and.it.is.equal(this.obj[Symbol.iterator]());
+  });
+};
diff --git a/node_modules/should/lib/should.js b/node_modules/should/lib/should.js
new file mode 100644
index 0000000..8f653b4
--- /dev/null
+++ b/node_modules/should/lib/should.js
@@ -0,0 +1,159 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+
+var util = require('./util');
+
+/**
+ * Our function should
+ *
+ * @param {*} obj Object to assert
+ * @returns {should.Assertion} Returns new Assertion for beginning assertion chain
+ * @example
+ *
+ * var should = require('should');
+ * should('abc').be.a.String();
+ */
+function should(obj) {
+  return (new should.Assertion(obj));
+}
+
+should.AssertionError = require('./assertion-error');
+should.Assertion = require('./assertion');
+
+should.format = util.format;
+should.type = require('should-type');
+should.util = util;
+
+/**
+ * Object with configuration.
+ * It contains such properties:
+ * * `checkProtoEql` boolean - Affect if `.eql` will check objects prototypes
+ * Also it can contain options for should-format.
+ *
+ * @type {Object}
+ * @memberOf should
+ * @static
+ * @example
+ *
+ * var a = { a: 10 }, b = Object.create(null);
+ * b.a = 10;
+ *
+ * a.should.be.eql(b);
+ * //not throws
+ *
+ * should.config.checkProtoEql = true;
+ * a.should.be.eql(b);
+ * //throws AssertionError: expected { a: 10 } to equal { a: 10 } (because A and B have different prototypes)
+ */
+should.config = require('./config');
+
+// Expose should to external world.
+exports = module.exports = should;
+
+/**
+ * Allow to extend given prototype with should property using given name. This getter will **unwrap** all standard wrappers like `Number`, `Boolean`, `String`.
+ * Using `should(obj)` is the equivalent of using `obj.should` with known issues (like nulls and method calls etc).
+ *
+ * @param {string} [propertyName] Name of property to add. Default is `'should'`.
+ * @param {Object} [proto] Prototype to extend with. Default is `Object.prototype`.
+ * @memberOf should
+ * @returns {{ name: string, descriptor: Object, proto: Object }} Descriptor enough to return all back
+ * @static
+ * @example
+ *
+ * var prev = should.extend('must', Object.prototype);
+ *
+ * 'abc'.must.startWith('a');
+ *
+ * var should = should.noConflict(prev);
+ * should.not.exist(Object.prototype.must);
+ */
+should.extend = function(propertyName, proto) {
+  propertyName = propertyName || 'should';
+  proto = proto || Object.prototype;
+
+  var prevDescriptor = Object.getOwnPropertyDescriptor(proto, propertyName);
+
+  Object.defineProperty(proto, propertyName, {
+    set: function() {
+    },
+    get: function() {
+      return should(util.isWrapperType(this) ? this.valueOf() : this);
+    },
+    configurable: true
+  });
+
+  return { name: propertyName, descriptor: prevDescriptor, proto: proto };
+};
+
+/**
+ * Delete previous extension. If `desc` missing it will remove default extension.
+ *
+ * @param {{ name: string, descriptor: Object, proto: Object }} [desc] Returned from `should.extend` object
+ * @memberOf should
+ * @returns {Function} Returns should function
+ * @static
+ * @example
+ *
+ * var should = require('should').noConflict();
+ *
+ * should(Object.prototype).not.have.property('should');
+ *
+ * var prev = should.extend('must', Object.prototype);
+ * 'abc'.must.startWith('a');
+ * should.noConflict(prev);
+ *
+ * should(Object.prototype).not.have.property('must');
+ */
+should.noConflict = function(desc) {
+  desc = desc || should._prevShould;
+
+  if(desc) {
+    delete desc.proto[desc.name];
+
+    if(desc.descriptor) {
+      Object.defineProperty(desc.proto, desc.name, desc.descriptor);
+    }
+  }
+  return should;
+};
+
+/**
+ * Simple utility function for a bit more easier should assertion extension
+ * @param {Function} f So called plugin function. It should accept 2 arguments: `should` function and `Assertion` constructor
+ * @memberOf should
+ * @returns {Function} Returns `should` function
+ * @static
+ * @example
+ *
+ * should.use(function(should, Assertion) {
+ *   Assertion.add('asset', function() {
+ *      this.params = { operator: 'to be asset' };
+ *
+ *      this.obj.should.have.property('id').which.is.a.Number();
+ *      this.obj.should.have.property('path');
+ *  })
+ * })
+ */
+should.use = function(f) {
+  f(should, should.Assertion);
+  return this;
+};
+
+should
+  .use(require('./ext/assert'))
+  .use(require('./ext/chain'))
+  .use(require('./ext/bool'))
+  .use(require('./ext/number'))
+  .use(require('./ext/eql'))
+  .use(require('./ext/type'))
+  .use(require('./ext/string'))
+  .use(require('./ext/property'))
+  .use(require('./ext/error'))
+  .use(require('./ext/match'))
+  .use(require('./ext/contain'))
+  .use(require('./ext/promise'));
diff --git a/node_modules/should/lib/util.js b/node_modules/should/lib/util.js
new file mode 100644
index 0000000..decb5cd
--- /dev/null
+++ b/node_modules/should/lib/util.js
@@ -0,0 +1,135 @@
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var type = require('should-type');
+var config = require('./config');
+
+/**
+ * Check if given obj just a primitive type wrapper
+ * @param {Object} obj
+ * @returns {boolean}
+ * @private
+ */
+exports.isWrapperType = function(obj) {
+  return obj instanceof Number || obj instanceof String || obj instanceof Boolean;
+};
+
+exports.merge = function(a, b) {
+  if(a && b) {
+    for(var key in b) {
+      a[key] = b[key];
+    }
+  }
+  return a;
+};
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+exports.forEach = function forEach(obj, f, context) {
+  if(exports.isGeneratorFunction(obj)) {
+    return forEach(obj(), f, context);
+  } else if (exports.isGeneratorObject(obj)) {
+    var value = obj.next();
+    while(!value.done) {
+      if(f.call(context, value.value, 'value', obj) === false)
+        return;
+      value = obj.next();
+    }
+  } else {
+    for(var prop in obj) {
+      if(hasOwnProperty.call(obj, prop)) {
+        if(f.call(context, obj[prop], prop, obj) === false)
+          return;
+      }
+    }
+  }
+};
+
+exports.some = function(obj, f, context) {
+  var res = false;
+  exports.forEach(obj, function(value, key) {
+    if(f.call(context, value, key, obj)) {
+      res = true;
+      return false;
+    }
+  }, context);
+  return res;
+};
+
+exports.isEmptyObject = function(obj) {
+  for(var prop in obj) {
+    if(hasOwnProperty.call(obj, prop)) {
+      return false;
+    }
+  }
+  return true;
+};
+
+exports.isIndexable = function(obj) {
+  var t = type(obj);
+  return (t.type === type.OBJECT && t.cls === type.ARRAY) ||
+   (t.type === type.OBJECT && t.cls === type.BUFFER) ||
+   (t.type === type.OBJECT && t.cls === type.ARGUMENTS) ||
+   (t.type === type.OBJECT && t.cls === type.ARRAY_BUFFER) ||
+   (t.type === type.OBJECT && t.cls === type.TYPED_ARRAY) ||
+   (t.type === type.OBJECT && t.cls === type.DATA_VIEW) ||
+   (t.type === type.OBJECT && t.cls === type.STRING) ||
+   (t.type === type.STRING);
+};
+
+exports.length = function(obj) {
+  var t = type(obj);
+  switch(t.type) {
+    case type.STRING:
+      return obj.length;
+    case type.OBJECT:
+      switch(t.cls) {
+        case type.ARRAY_BUFFER:
+        case type.TYPED_ARRAY:
+        case type.DATA_VIEW:
+          return obj.byteLength;
+
+        case type.ARRAY:
+        case type.BUFFER:
+        case type.ARGUMENTS:
+        case type.FUNCTION:
+          return obj.length;
+      }
+  }
+};
+
+exports.convertPropertyName = function(name) {
+  if(typeof name == 'symbol') {
+    return name;
+  } else {
+    return String(name);
+  }
+};
+
+exports.isGeneratorObject = function(obj) {
+  if(!obj) return false;
+
+  return typeof obj.next == 'function' &&
+          typeof obj[Symbol.iterator] == 'function' &&
+          obj[Symbol.iterator]() === obj;
+};
+
+//TODO find better way
+exports.isGeneratorFunction = function(f) {
+  if(typeof f != 'function') return false;
+
+  return /^function\s*\*\s*/.test(f.toString());
+};
+
+exports.format = function(value, opts) {
+  return config.getFormatter(opts).format(value);
+};
+
+exports.functionName = require('should-format').Formatter.functionName;
+
+exports.formatProp = function(value) {
+  return config.getFormatter().formatPropertyName(String(value));
+};
diff --git a/node_modules/should/node_modules/should-equal/.eslintrc b/node_modules/should/node_modules/should-equal/.eslintrc
new file mode 100644
index 0000000..c491a6e
--- /dev/null
+++ b/node_modules/should/node_modules/should-equal/.eslintrc
@@ -0,0 +1,12 @@
+{
+  "env": {
+    "node": true,
+    "browser": true
+  },
+  "rules": {
+    "quotes": false,
+    "strict": false,
+    "curly": false,
+    "eqeqeq": false
+  }
+}
diff --git a/node_modules/should/node_modules/should-equal/.npmignore b/node_modules/should/node_modules/should-equal/.npmignore
new file mode 100644
index 0000000..485dee6
--- /dev/null
+++ b/node_modules/should/node_modules/should-equal/.npmignore
@@ -0,0 +1 @@
+.idea
diff --git a/node_modules/should/node_modules/should-equal/.travis.yml b/node_modules/should/node_modules/should-equal/.travis.yml
new file mode 100644
index 0000000..a355161
--- /dev/null
+++ b/node_modules/should/node_modules/should-equal/.travis.yml
@@ -0,0 +1,6 @@
+language: node_js
+node_js:
+- '0.10'
+- '0.11'
+script:
+- npm test
\ No newline at end of file
diff --git a/node_modules/should/node_modules/should-equal/LICENSE b/node_modules/should/node_modules/should-equal/LICENSE
new file mode 100644
index 0000000..326fe25
--- /dev/null
+++ b/node_modules/should/node_modules/should-equal/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/should/node_modules/should-equal/README.md b/node_modules/should/node_modules/should-equal/README.md
new file mode 100644
index 0000000..60389bf
--- /dev/null
+++ b/node_modules/should/node_modules/should-equal/README.md
@@ -0,0 +1,20 @@
+equal
+=====
+
+[![Build Status](https://travis-ci.org/shouldjs/equal.svg?branch=master)](https://travis-ci.org/shouldjs/equal)
+
+Deep equality comparison implementation for should.js
+
+Function return an object that have result of comparison and description of fail:
+
+```js
+> var a = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10},
+... b = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:7,i:9,j:10};
+undefined
+> eql(a, b);
+{ result: false,
+  path: [ 'h' ],
+  reason: 'A and B are not equal',
+  a: 8,
+  b: 7 }
+```
diff --git a/node_modules/should/node_modules/should-equal/format.js b/node_modules/should/node_modules/should-equal/format.js
new file mode 100644
index 0000000..94dbfc1
--- /dev/null
+++ b/node_modules/should/node_modules/should-equal/format.js
@@ -0,0 +1,7 @@
+module.exports = function format(msg) {
+  var args = arguments;
+  for(var i = 1, l = args.length; i < l; i++) {
+    msg = msg.replace(/%s/, args[i]);
+  }
+  return msg;
+}
diff --git a/node_modules/should/node_modules/should-equal/index.js b/node_modules/should/node_modules/should-equal/index.js
new file mode 100644
index 0000000..5a0c6b9
--- /dev/null
+++ b/node_modules/should/node_modules/should-equal/index.js
@@ -0,0 +1,340 @@
+var getType = require('should-type');
+var format = require('./format');
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function makeResult(r, path, reason, a, b) {
+  var o = {result: r};
+  if(!r) {
+    o.path = path;
+    o.reason = reason;
+    o.a = a;
+    o.b = b;
+  }
+  return o;
+}
+
+var EQUALS = makeResult(true);
+
+function typeToString(t) {
+  return t.type + (t.cls ? '(' + t.cls + (t.sub ? ' ' + t.sub : '') + ')' : '');
+}
+
+
+
+var REASON = {
+  PLUS_0_AND_MINUS_0: '+0 is not equal to -0',
+  DIFFERENT_TYPES: 'A has type %s and B has type %s',
+  NAN_NUMBER: 'NaN is not equal to any number',
+  EQUALITY: 'A is not equal to B',
+  EQUALITY_PROTOTYPE: 'A and B have different prototypes',
+  WRAPPED_VALUE: 'A wrapped value is not equal to B wrapped value',
+  FUNCTION_SOURCES: 'function A is not equal to B by source code value (via .toString call)',
+  MISSING_KEY: '%s has no key %s',
+  CIRCULAR_VALUES: 'A has circular reference that was visited not in the same time as B',
+  SET_MAP_MISSING_KEY: 'Set/Map missing key',
+  MAP_VALUE_EQUALITY: 'Values of the same key in A and B is not equal'
+};
+
+function eqInternal(a, b, opts, stackA, stackB, path) {
+  var r = EQUALS;
+
+  function result(comparison, reason) {
+    return makeResult(comparison, path, reason, a, b);
+  }
+
+  function checkPropertyEquality(property) {
+    return eqInternal(a[property], b[property], opts, stackA, stackB, path.concat([property]));
+  }
+
+
+  // equal a and b exit early
+  if(a === b) {
+    // check for +0 !== -0;
+    return result(a !== 0 || (1 / a == 1 / b), REASON.PLUS_0_AND_MINUS_0);
+  }
+
+  var l, p;
+
+  var typeA = getType(a),
+    typeB = getType(b);
+
+  // if objects has different types they are not equals
+  var typeDifferents = typeA.type !== typeB.type || typeA.cls !== typeB.cls;
+
+  if(typeDifferents || ((opts.checkSubType && typeA.sub !== typeB.sub) || !opts.checkSubType)) {
+    return result(false, format(REASON.DIFFERENT_TYPES, typeToString(typeA), typeToString(typeB)));
+  }
+
+  //early checks for types
+  switch(typeA.type) {
+    case 'number':
+      // NaN !== NaN
+      return (a !== a) ? result(b !== b, REASON.NAN_NUMBER)
+        // but treat `+0` vs. `-0` as not equal
+        : (a === 0 ? result(1 / a === 1 / b, REASON.PLUS_0_AND_MINUS_0) : result(a === b, REASON.EQUALITY));
+
+    case 'boolean':
+    case 'string':
+      return result(a === b, REASON.EQUALITY);
+
+    case 'function':
+      var fA = a.toString(), fB = b.toString();
+      r = eqInternal(fA, fB, opts, stackA, stackB, path);
+      if(!r.result) {
+        r.reason = REASON.FUNCTION_SOURCES;
+        return r;
+      }
+
+      break;//check user properties
+
+    case 'object':
+      // additional checks for object instances
+      switch(typeA.cls) {
+        // check regexp flags
+        // TODO add es6 flags
+        case 'regexp':
+          p = ['source', 'global', 'multiline', 'lastIndex', 'ignoreCase'];
+          while(p.length) {
+            r = checkPropertyEquality(p.shift());
+            if(!r.result) return r;
+          }
+          break;//check user properties
+
+        //check by timestamp only
+        case 'date':
+          if(+a !== +b) {
+            return result(false, REASON.EQUALITY);
+          }
+          break;//check user properties
+
+        //primitive type wrappers
+        case 'number':
+        case 'boolean':
+        case 'string':
+          r = eqInternal(a.valueOf(), b.valueOf(), opts, stackA, stackB, path);
+          if(!r.result) {
+            r.reason = REASON.WRAPPED_VALUE;
+            return r;
+          }
+          break;//check user properties
+
+        //node buffer
+        case 'buffer':
+          //if length different it is obviously different
+          r = checkPropertyEquality('length');
+          if(!r.result) return r;
+
+          l = a.length;
+          while(l--) {
+            r = checkPropertyEquality(l);
+            if(!r.result) return r;
+          }
+
+          //we do not check for user properties because
+          //node Buffer have some strange hidden properties
+          return EQUALS;
+
+        case 'error':
+          //check defined properties
+          p = ['name', 'message'];
+          while(p.length) {
+            r = checkPropertyEquality(p.shift());
+            if(!r.result) return r;
+          }
+
+          break;//check user properties
+
+        case 'array':
+        case 'arguments':
+        case 'typed-array':
+          r = checkPropertyEquality('length');
+          if(!r.result) return r;
+
+          break;//check user properties
+
+        case 'array-buffer':
+          r = checkPropertyEquality('byteLength');
+          if(!r.result) return r;
+
+          break;//check user properties
+
+        case 'map':
+        case 'set':
+          r = checkPropertyEquality('size');
+          if(!r.result) return r;
+
+          stackA.push(a);
+          stackB.push(b);
+
+          var itA = a.entries();
+          var nextA = itA.next();
+
+          while(!nextA.done) {
+            var key = nextA.value[0];
+            //first check for primitive key if we can do light check
+            //using .has and .get
+            if(getType(key).type != 'object') {
+              if(b.has(key)) {
+                if(typeA.cls == 'map') {
+                  //for map we also check its value to be equal
+                  var value = b.get(key);
+                  r = eqInternal(nextA.value[1], value, opts, stackA, stackB, path);
+                  if(!r.result) {
+                    r.a = nextA.value;
+                    r.b = value;
+                    r.reason = REASON.MAP_VALUE_EQUALITY;
+
+                    break;
+                  }
+                }
+
+              } else {
+                r = result(false, REASON.SET_MAP_MISSING_KEY);
+                r.a = key;
+                r.b = key;
+
+                break;
+              }
+            } else {
+              //heavy check
+              //we search by iterator for key equality using equal
+              var itB = b.entries();
+              var nextB = itB.next();
+
+              while(!nextB.done) {
+                //first check for keys
+                r = eqInternal(nextA.value[0], nextB.value[0], opts, stackA, stackB, path);
+
+                if(!r.result) {
+                  r.reason = REASON.SET_MAP_MISSING_KEY;
+                  r.a = key;
+                  r.b = key;
+                } else {
+                  if(typeA.cls == 'map') {
+                    r = eqInternal(nextA.value[1], nextB.value[1], opts, stackA, stackB, path);
+
+                    if(!r.result) {
+                      r.a = nextA.value;
+                      r.b = nextB.value;
+                      r.reason = REASON.MAP_VALUE_EQUALITY;
+                    }
+                  }
+
+                  break;
+                }
+
+                nextB = itB.next();
+              }
+            }
+
+            if(!r.result) {
+              break;
+            }
+
+            nextA = itA.next();
+          }
+
+          stackA.pop();
+          stackB.pop();
+
+          if(!r.result) {
+            r.reason = REASON.SET_MAP_MISSING_ENTRY;
+            return r;
+          }
+
+          break; //check user properties
+      }
+  }
+
+  // compare deep objects and arrays
+  // stacks contain references only
+  //
+
+  l = stackA.length;
+  while(l--) {
+    if(stackA[l] == a) {
+      return result(stackB[l] == b, REASON.CIRCULAR_VALUES);
+    }
+  }
+
+  // add `a` and `b` to the stack of traversed objects
+  stackA.push(a);
+  stackB.push(b);
+
+  var key;
+
+  for(key in b) {
+    if(hasOwnProperty.call(b, key)) {
+      r = result(hasOwnProperty.call(a, key), format(REASON.MISSING_KEY, 'A', key));
+      if(!r.result) {
+        break;
+      }
+
+      if(r.result) {
+        r = checkPropertyEquality(key);
+        if(!r.result) {
+          break;
+        }
+      }
+    }
+  }
+
+  if(r.result) {
+    // ensure both objects have the same number of properties
+    for(key in a) {
+      if(hasOwnProperty.call(a, key)) {
+        r = result(hasOwnProperty.call(b, key), format(REASON.MISSING_KEY, 'B', key));
+        if(!r.result) {
+          return r;
+        }
+      }
+    }
+  }
+
+  stackA.pop();
+  stackB.pop();
+
+  if(!r.result) return r;
+
+  var prototypesEquals = false, canComparePrototypes = false;
+
+  if(opts.checkProtoEql) {
+    if(Object.getPrototypeOf) {//TODO should i check prototypes for === or use eq?
+      prototypesEquals = Object.getPrototypeOf(a) === Object.getPrototypeOf(b);
+      canComparePrototypes = true;
+    } else if(a.__proto__ && b.__proto__) {
+      prototypesEquals = a.__proto__ === b.__proto__;
+      canComparePrototypes = true;
+    }
+
+    if(canComparePrototypes && !prototypesEquals) {
+      r = result(prototypesEquals, REASON.EQUALITY_PROTOTYPE);
+      r.showReason = true;
+      if(!r.result) {
+        return r;
+      }
+    }
+  }
+
+  return EQUALS;
+}
+
+var defaultOptions = {
+  checkProtoEql: true,
+  checkSubType: true
+};
+
+function eq(a, b, opts) {
+  opts = opts || {};
+  if(typeof opts.checkProtoEql !== 'boolean')
+    opts.checkProtoEql = defaultOptions.checkProtoEql;
+  if(typeof opts.checkSubType !== 'boolean')
+    opts.checkSubType = defaultOptions.checkSubType;
+
+  var r = eqInternal(a, b, opts, [], [], []);
+  return r;
+}
+
+module.exports = eq;
+
+eq.r = REASON;
diff --git a/node_modules/should/node_modules/should-equal/package.json b/node_modules/should/node_modules/should-equal/package.json
new file mode 100644
index 0000000..45012ea
--- /dev/null
+++ b/node_modules/should/node_modules/should-equal/package.json
@@ -0,0 +1,57 @@
+{
+  "name": "should-equal",
+  "version": "0.5.0",
+  "description": "Deep comparison of 2 instances for should.js",
+  "main": "index.js",
+  "scripts": {
+    "test": "mocha --ui bdd -R mocha-better-spec-reporter test.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/shouldjs/equal.git"
+  },
+  "keywords": [
+    "should.js",
+    "deep",
+    "equal"
+  ],
+  "author": {
+    "name": "Denis Bardadym",
+    "email": "bardadymchik@gmail.com"
+  },
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/shouldjs/equal/issues"
+  },
+  "homepage": "https://github.com/shouldjs/equal",
+  "devDependencies": {
+    "mocha": "latest",
+    "mocha-better-spec-reporter": "latest"
+  },
+  "dependencies": {
+    "should-type": "0.2.0"
+  },
+  "gitHead": "d0b73b18fd4a799765de477165caf60fee1f9397",
+  "_id": "should-equal@0.5.0",
+  "_shasum": "c797f135f3067feb69ebecdb306b1c3fe21b3e6f",
+  "_from": "should-equal@0.5.0",
+  "_npmVersion": "2.11.1",
+  "_nodeVersion": "2.3.0",
+  "_npmUser": {
+    "name": "btd",
+    "email": "bardadymchik@gmail.com"
+  },
+  "maintainers": [
+    {
+      "name": "btd",
+      "email": "bardadymchik@gmail.com"
+    }
+  ],
+  "dist": {
+    "shasum": "c797f135f3067feb69ebecdb306b1c3fe21b3e6f",
+    "tarball": "http://registry.npmjs.org/should-equal/-/should-equal-0.5.0.tgz"
+  },
+  "directories": {},
+  "_resolved": "https://registry.npmjs.org/should-equal/-/should-equal-0.5.0.tgz",
+  "readme": "ERROR: No README data found!"
+}
diff --git a/node_modules/should/node_modules/should-equal/test.js b/node_modules/should/node_modules/should-equal/test.js
new file mode 100644
index 0000000..352424e
--- /dev/null
+++ b/node_modules/should/node_modules/should-equal/test.js
@@ -0,0 +1,420 @@
+var assert = require('assert');
+var equal = require('./index');
+
+function eq(a, b) {
+  var r = equal(a, b);
+  var msg = !r.result && (r.reason + ' at ' + r.path + ' ' + r.a + ' =/= ' + r.b);
+  if(!r.result) {
+    assert.equal(a, b, msg);
+  }
+
+}
+
+function ne(a, b) {
+  var r = equal(a, b);
+  assert.ok(!r.result);
+}
+
+/* 1. simple tests */
+
+/* 1.1. positive */
+it("NaN eqs NaN", function() {
+  return eq(NaN, NaN);
+});
+it("finite integer n eqs n", function() {
+  return eq(1234, 1234);
+});
+it("empty list eqs empty list", function() {
+  return eq([], []);
+});
+it("empty obj eqs empty obj", function() {
+  return eq({}, {});
+});
+it("number eqs number of same value", function() {
+  return eq(123.45678, 123.45678);
+});
+it("regex lit's w same pattern, flags are eq", function() {
+  return eq(/^abc[a-zA-Z]/, /^abc[a-zA-Z]/);
+});
+it("pods w same properties are eq", function() {
+  return eq({
+    a: 'b',
+    c: 'd'
+  }, {
+    a: 'b',
+    c: 'd'
+  });
+});
+it("pods that only differ wrt prop ord are eq", function() {
+  return eq({
+    a: 'b',
+    c: 'd'
+  }, {
+    c: 'd',
+    a: 'b'
+  });
+});
+
+/* 1.2. negative */
+it("obj doesn't eq list", function() {
+  return ne({}, []);
+});
+it("obj in a list doesn't eq list in list", function() {
+  return ne([{}], [[]]);
+});
+it("integer n doesn't eq rpr n", function() {
+  return ne(1234, '1234');
+});
+it("integer n doesn't eq n + 1", function() {
+  return ne(1234, 1235);
+});
+it("empty list doesn't eq false", function() {
+  return ne([], false);
+});
+it("list w an integer doesn't eq one w rpr n", function() {
+  return ne([3], ['3']);
+});
+it("regex lit's w diff. patterns, same flags aren't eq", function() {
+  return ne(/^abc[a-zA-Z]/, /^abc[a-zA-Z]x/);
+});
+it("regex lit's w same patterns, diff. flags aren't eq", function() {
+  return ne(/^abc[a-zA-Z]/, /^abc[a-zA-Z]/i);
+});
+it("+0 should ne -0", function() {
+  return ne(+0, -0);
+});
+it("number obj not eqs primitive number of same value", function() {
+  return ne(5, new Number(5));
+});
+it("string obj not eqs primitive string of same value", function() {
+  return ne('helo', new String('helo'));
+});
+it("(1) bool obj not eqs primitive bool of same value", function() {
+  return ne(false, new Boolean(false));
+});
+it("(2) bool obj not eqs primitive bool of same value", function() {
+  return ne(true, new Boolean(true));
+});
+it("number obj eqs the same valued number object", function() {
+  return eq(new Number(5), new Number(5));
+});
+
+/* 2. complex tests */
+it("obj w undef member not eqs other obj w/out same member", function() {
+  var d, e;
+  d = {
+    x: void 0
+  };
+  e = {};
+  return ne(d, e);
+});
+it("fn1: functions w same source are eq", function() {
+  var d, e;
+  d = function( a, b, c ){ return a * b * c; };
+  e = function( a, b, c ){ return a * b * c; };
+  return eq(d, e);
+});
+it("fn2: functions w diff source aren't eq", function() {
+  var d, e;
+  d = function( a, b, c ){ return a * b * c; };
+  e = function( a, b, c ){ return a  *  b  *  c; };
+  return ne(d, e);
+});
+it("fn3: equal functions w equal props are eq", function() {
+  var d, e;
+  d = function() {
+    return null;
+  };
+  d.foo = {
+    some: 'meaningless',
+    properties: 'here'
+  };
+  e = function() {
+    return null;
+  };
+  e.foo = {
+    some: 'meaningless',
+    properties: 'here'
+  };
+  return eq(d, e);
+});
+it("fn4: equal functions w unequal props aren't eq", function() {
+  var d, e;
+  d = function() {
+    return null;
+  };
+  d.foo = {
+    some: 'meaningless',
+    properties: 'here'
+  };
+  e = function() {
+    return null;
+  };
+  e.foo = {
+    some: 'meaningless',
+    properties: 'here!!!'
+  };
+  return ne(d, e);
+});
+it("list w named member eqs other list w same member", function() {
+  var d, e;
+  d = ['foo', null, 3];
+  d['extra'] = 42;
+  e = ['foo', null, 3];
+  e['extra'] = 42;
+  return eq(d, e);
+});
+it("list w named member doesn't eq list w same member, other value", function() {
+  var d, e;
+  d = ['foo', null, 3];
+  d['extra'] = 42;
+  e = ['foo', null, 3];
+  e['extra'] = 108;
+  return ne(d, e);
+});
+it("date eqs other date pointing to same time", function() {
+  var d, e;
+  d = new Date("1995-12-17T03:24:00");
+  e = new Date("1995-12-17T03:24:00");
+  return eq(d, e);
+});
+it("date does not eq other date pointing to other time", function() {
+  var d, e;
+  d = new Date("1995-12-17T03:24:00");
+  e = new Date("1995-12-17T03:24:01");
+  return ne(d, e);
+});
+it("str obj w props eq same str, same props", function() {
+  var d, e;
+  d = new String("helo test");
+  d['abc'] = 42;
+  e = new String("helo test");
+  e['abc'] = 42;
+  return eq(d, e);
+});
+it("str obj w props not eq same str, other props", function() {
+  var d, e;
+  d = new String("helo test");
+  d['abc'] = 42;
+  e = new String("helo test");
+  e['def'] = 42;
+  return ne(d, e);
+});
+it("str obj w props eq same str, same props (circ)", function() {
+  var c, d, e;
+  c = ['a list'];
+  c.push(c);
+  d = new String("helo test");
+  d['abc'] = c;
+  e = new String("helo test");
+  e['abc'] = c;
+  return eq(d, e);
+});
+it("str obj w props not eq same str, other props (circ)", function() {
+  var c, d, e;
+  c = ['a list'];
+  c.push(c);
+  d = new String("helo test");
+  d['abc'] = c;
+  e = new String("helo test");
+  e['def'] = c;
+  return ne(d, e);
+});
+/*it("(1) circ arrays w similar layout, same values aren't eq"] = function() {
+  var d, e;
+  d = [1, 2, 3];
+  d.push(d);
+  e = [1, 2, 3];
+  e.push(d);
+  return ne(d, e);
+};*/
+it("(2) circ arrays w same layout, same values are eq", function() {
+  var d, e;
+  d = [1, 2, 3];
+  d.push(d);
+  e = [1, 2, 3];
+  e.push(e);
+  return eq(d, e);
+});
+it("(fkling1) arrays w eq subarrays are eq", function() {
+  var a, b, bar, foo;
+  a = [1, 2, 3];
+  b = [1, 2, 3];
+  foo = [a, a];
+  bar = [b, b];
+  return eq(foo, bar);
+});
+/*it("(fkling2) arrays w eq subarrays but diff distribution aren't eq"] = function() {
+  var a, b, bar, foo;
+  a = [1, 2, 3];
+  b = [1, 2, 3];
+  foo = [a, a];
+  bar = [a, b];
+  return ne(foo, bar);
+};*/
+
+/* joshwilsdon's test (https://github.com/joyent/node/issues/7161) */
+it("joshwilsdon", function() {
+  var count, d1, d2, errors, idx1, idx2, v1, v2, _i, _j, _len, _ref;
+  d1 = [
+    NaN, void 0, null, true, false, Infinity, 0, 1, "a", "b", {
+      a: 1
+    }, {
+      a: "a"
+    }, [
+      {
+        a: 1
+      }
+    ], [
+      {
+        a: true
+      }
+    ], {
+      a: 1,
+      b: 2
+    }, [1, 2], [1, 2, 3], {
+      a: "1"
+    }, {
+      a: "1",
+      b: "2"
+    }
+  ];
+  d2 = [
+    NaN, void 0, null, true, false, Infinity, 0, 1, "a", "b", {
+      a: 1
+    }, {
+      a: "a"
+    }, [
+      {
+        a: 1
+      }
+    ], [
+      {
+        a: true
+      }
+    ], {
+      a: 1,
+      b: 2
+    }, [1, 2], [1, 2, 3], {
+      a: "1"
+    }, {
+      a: "1",
+      b: "2"
+    }
+  ];
+  errors = [];
+  count = 0;
+  for (idx1 = _i = 0, _len = d1.length; _i < _len; idx1 = ++_i) {
+    v1 = d1[idx1];
+    for (idx2 = _j = idx1, _ref = d2.length; idx1 <= _ref ? _j < _ref : _j > _ref; idx2 = idx1 <= _ref ? ++_j : --_j) {
+      count += 1;
+      v2 = d2[idx2];
+      if (idx1 === idx2) {
+        if (!eq(v1, v2)) {
+          //errors.push("eq " + (rpr(v1)) + ", " + (rpr(v2)));
+        }
+      } else {
+        if (!ne(v1, v2)) {
+          //errors.push("ne " + (rpr(v1)) + ", " + (rpr(v2)));
+        }
+      }
+    }
+  }
+  return [count, errors];
+});
+it('node buffer', function() {
+  eq(new Buffer('abc'), new Buffer('abc'));
+  ne(new Buffer('abc'), new Buffer('abc1'));
+  ne(new Buffer('abd'), new Buffer('abc'));
+});
+it('RegExp with props', function() {
+  var re1 = /a/;
+  re1.lastIndex = 3;
+  ne(re1, /a/);
+});
+it('Date with props', function() {
+  var now = Date.now();
+
+  var d1 = new Date(now);
+  var d2 = new Date(now);
+
+  d1.a = 10;
+
+  ne(d1, d2);
+});
+it('Check object prototypes', function() {
+  var nbRoot = {
+    toString: function() { return this.first + ' ' + this.last; }
+  };
+
+  function nameBuilder(first, last) {
+    this.first = first;
+    this.last = last;
+    return this;
+  }
+  nameBuilder.prototype = nbRoot;
+
+  function nameBuilder2(first, last) {
+    this.first = first;
+    this.last = last;
+    return this;
+  }
+  nameBuilder2.prototype = nbRoot;
+
+  var nb1 = new nameBuilder('Ryan', 'Dahl');
+  var nb2 = new nameBuilder2('Ryan', 'Dahl');
+
+  eq(nb1, nb2);
+
+  nameBuilder2.prototype = Object;
+  nb2 = new nameBuilder2('Ryan', 'Dahl');
+
+  ne(nb1, nb2);
+});
+
+it('typed arrays and array buffer', function() {
+  if(typeof Uint8Array !== 'undefined') {
+    var arr1 = new Uint8Array([21, 31]);
+    var arr2 = new Uint8Array([21, 31]);
+
+    eq(arr1, arr2);
+
+    eq(arr1.buffer, arr2.buffer);
+  }
+});
+
+it('es6 sets', function() {
+  if(typeof Set !== 'undefined') {
+    var s1 = new Set([1, 2, 3]);
+    var s2 = new Set([1, 2, 3]);
+    var s3 = new Set(['a', 'b', 'c']);
+    var s4 = new Set([]);
+
+    var s5 = new Set([{ a: 1}, { a: 1}, { a: 1}]);
+    var s6 = new Set([{ a: 1}, { a: 1}, { a: 1}]);
+
+    eq(s1, s2);
+    ne(s1, s3);
+    ne(s1, s4);
+    ne(s1, s5);
+    eq(s5, s6);
+  }
+});
+
+it('es6 maps', function() {
+  if(typeof Map !== 'undefined') {
+    var m1 = new Map([[1, 1], [2, 2], [3, 3]]);
+    var m2 = new Map([[1, 1], [2, 2], [3, 3]]);
+
+    var m3 = new Map([[1, 2], [2, 3], [3, 4]]);
+    var m4 = new Map([[{ a: 10}, 2], [{ a: 11}, 2], [{ a: 12}, 2]]);
+    var m5 = new Map([[{ a: 11}, 2], [{ a: 12}, 2], [{ a: 13}, 2]]);
+    var m6 = new Map([[{ a: 11}, 2], [{ a: 12}, 2], [{ a: 13}, 2]]);
+
+    eq(m1, m1);
+    eq(m1, m2);
+    ne(m3, m2);
+    ne(m4, m5);
+    eq(m5, m6);
+  }
+});
diff --git a/node_modules/should/node_modules/should-format/.eslintrc b/node_modules/should/node_modules/should-format/.eslintrc
new file mode 100644
index 0000000..e761eb3
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/.eslintrc
@@ -0,0 +1,8 @@
+{
+  "env": {
+    "browser": true,
+    "node": true
+  },
+
+  "extends": "eslint:recommended"
+}
diff --git a/node_modules/should/node_modules/should-format/.npmignore b/node_modules/should/node_modules/should-format/.npmignore
new file mode 100644
index 0000000..723ef36
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/.npmignore
@@ -0,0 +1 @@
+.idea
\ No newline at end of file
diff --git a/node_modules/should/node_modules/should-format/.travis.yml b/node_modules/should/node_modules/should-format/.travis.yml
new file mode 100644
index 0000000..b6e0e8f
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/.travis.yml
@@ -0,0 +1,8 @@
+language: node_js
+node_js:
+- '0.12'
+- '4.0'
+- '4.1'
+- '4.2'
+script:
+- npm test
diff --git a/node_modules/should/node_modules/should-format/LICENSE b/node_modules/should/node_modules/should-format/LICENSE
new file mode 100644
index 0000000..d7e0e57
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/node_modules/should/node_modules/should-format/README.md b/node_modules/should/node_modules/should-format/README.md
new file mode 100644
index 0000000..48b6ae7
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/README.md
@@ -0,0 +1,6 @@
+format
+======
+
+[![Build Status](https://travis-ci.org/shouldjs/format.svg?branch=master)](https://travis-ci.org/shouldjs/format)
+
+Module for text inspections for instances
diff --git a/node_modules/should/node_modules/should-format/index.js b/node_modules/should/node_modules/should-format/index.js
new file mode 100644
index 0000000..f19b9a7
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/index.js
@@ -0,0 +1,456 @@
+var getType = require('should-type');
+var util = require('./util');
+
+function genKeysFunc(f) {
+  return function(value) {
+    var k = f(value);
+    k.sort();
+    return k;
+  };
+}
+
+
+function Formatter(opts) {
+  opts = opts || {};
+
+  this.seen = [];
+  this.keys = genKeysFunc(opts.keys === false ? Object.getOwnPropertyNames : Object.keys);
+
+  this.maxLineLength = typeof opts.maxLineLength === 'number' ? opts.maxLineLength : 60;
+  this.propSep = opts.propSep || ',';
+
+  this.isUTCdate = !!opts.isUTCdate;
+}
+
+Formatter.prototype = {
+  constructor: Formatter,
+
+  format: function(value) {
+    var t = getType(value);
+    var name1 = t.type, name2 = t.type;
+    if(t.cls) {
+      name1 += '_' + t.cls;
+      name2 += '_' + t.cls;
+    }
+    if(t.sub) {
+      name2 += '_' + t.sub;
+    }
+    var f = this['_format_' + name2] || this['_format_' + name1] || this['_format_' + t.type] || this.defaultFormat;
+    return f.call(this, value).trim();
+  },
+
+  _formatObject: function(value, opts) {
+    opts = opts || {};
+    var mainKeys = opts.keys || this.keys(value);
+
+    var len = 0;
+
+    var formatPropertyValue = opts.formatPropertyValue || this.formatPropertyValue;
+    var formatPropertyName = opts.formatPropertyName || this.formatPropertyName;
+    var keyValueSep = opts.keyValueSep || ': ';
+    var keyFilter = opts.keyFilter || function() { return true; };
+
+    this.seen.push(value);
+    var keys = [];
+
+    mainKeys.forEach(function(key) {
+      if(!keyFilter(key)) return;
+
+      var fName = formatPropertyName.call(this, key);
+
+      var f = (fName ? fName + keyValueSep : '') + formatPropertyValue.call(this, value, key);
+      len += f.length;
+      keys.push(f);
+    }, this);
+    this.seen.pop();
+
+    (opts.additionalProperties || []).forEach(function(keyValue) {
+      var f = keyValue[0] + keyValueSep + this.format(keyValue[1]);
+      len += f.length;
+      keys.push(f);
+    }, this);
+
+    var prefix = opts.prefix || Formatter.constructorName(value) || '';
+    if(prefix.length > 0) prefix += ' ';
+
+    var lbracket, rbracket;
+    if(Array.isArray(opts.brackets)) {
+      lbracket = opts.brackets && opts.brackets[0];
+      rbracket = opts.brackets && opts.brackets[1];
+    } else {
+      lbracket = '{';
+      rbracket = '}';
+    }
+
+    var rootValue = opts.value || '';
+
+    if(keys.length === 0)
+      return rootValue || (prefix + lbracket + rbracket);
+
+    if(len <= this.maxLineLength) {
+      return prefix + lbracket + ' ' + (rootValue ? rootValue + ' ' : '') + keys.join(this.propSep + ' ') + ' ' + rbracket;
+    } else {
+      return prefix + lbracket + '\n' + (rootValue ? '  ' + rootValue + '\n' : '') + keys.map(util.addSpaces).join(this.propSep + '\n') + '\n' + rbracket;
+    }
+  },
+
+  formatObject: function(value, prefix, props) {
+    props = props || this.keys(value);
+
+    var len = 0;
+
+    this.seen.push(value);
+    props = props.map(function(prop) {
+      var f = this.formatProperty(value, prop);
+      len += f.length;
+      return f;
+    }, this);
+    this.seen.pop();
+
+    if(props.length === 0) return '{}';
+
+    if(len <= this.maxLineLength) {
+      return '{ ' + (prefix ? prefix + ' ' : '') + props.join(this.propSep + ' ') + ' }';
+    } else {
+      return '{' + '\n' + (prefix ? '  ' + prefix + '\n' : '') + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
+    }
+  },
+
+  formatPropertyName: function(name) {
+    return name.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/) ? name : this.format(name);
+  },
+
+  formatProperty: function(value, prop) {
+    var desc = Formatter.getPropertyDescriptor(value, prop);
+
+    var propName = this.formatPropertyName(prop);
+
+    var propValue = desc.get && desc.set ?
+      '[Getter/Setter]' : desc.get ?
+      '[Getter]' : desc.set ?
+      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
+      '[Circular]' :
+      this.format(desc.value);
+
+    return propName + ': ' + propValue;
+  },
+
+  formatPropertyValue: function(value, prop) {
+    var desc = Formatter.getPropertyDescriptor(value, prop);
+
+    var propValue = desc.get && desc.set ?
+      '[Getter/Setter]' : desc.get ?
+      '[Getter]' : desc.set ?
+      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
+      '[Circular]' :
+      this.format(desc.value);
+
+    return propValue;
+  }
+};
+
+Formatter.add = function add(type, cls, sub, f) {
+  var args = Array.prototype.slice.call(arguments);
+  f = args.pop();
+  Formatter.prototype['_format_' + args.join('_')] = f;
+};
+
+Formatter.formatObjectWithPrefix = function formatObjectWithPrefix(f) {
+  return function(value) {
+    var prefix = f.call(this, value);
+    var props = this.keys(value);
+    if(props.length == 0) return prefix;
+    else return this.formatObject(value, prefix, props);
+  };
+};
+
+var functionNameRE = /^\s*function\s*(\S*)\s*\(/;
+
+Formatter.functionName = function functionName(f) {
+  if(f.name) {
+    return f.name;
+  }
+  var name = f.toString().match(functionNameRE)[1];
+  return name;
+};
+
+Formatter.constructorName = function(obj) {
+  while (obj) {
+    var descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor');
+    if (descriptor !== undefined &&
+        typeof descriptor.value === 'function') {
+
+        var name = Formatter.functionName(descriptor.value);
+        if(name !== '') {
+          return name;
+        }
+    }
+
+    obj = Object.getPrototypeOf(obj);
+  }
+};
+
+Formatter.getPropertyDescriptor = function(obj, value) {
+  var desc;
+  try {
+    desc = Object.getOwnPropertyDescriptor(obj, value) || {value: obj[value]};
+  } catch(e) {
+    desc = {value: e};
+  }
+  return desc;
+};
+
+Formatter.generateFunctionForIndexedArray = function generateFunctionForIndexedArray(lengthProp, name, padding) {
+  return function(value) {
+    var max = this.byteArrayMaxLength || 50;
+    var length = value[lengthProp];
+    var formattedValues = [];
+    var len = 0;
+    for(var i = 0; i < max && i < length; i++) {
+      var b = value[i] || 0;
+      var v = util.pad0(b.toString(16), padding);
+      len += v.length;
+      formattedValues.push(v);
+    }
+    var prefix = value.constructor.name || name || '';
+    if(prefix) prefix += ' ';
+
+    if(formattedValues.length === 0)
+      return prefix + '[]';
+
+    if(len <= this.maxLineLength) {
+      return prefix + '[ ' + formattedValues.join(this.propSep + ' ') + ' ' + ']';
+    } else {
+      return prefix + '[\n' + formattedValues.map(util.addSpaces).join(this.propSep + '\n') + '\n' + ']';
+    }
+  };
+};
+
+Formatter.add('undefined', function() { return 'undefined' });
+Formatter.add('null', function() { return 'null' });
+Formatter.add('boolean', function(value) { return value ? 'true': 'false' });
+Formatter.add('symbol', function(value) { return value.toString() });
+
+['number', 'boolean'].forEach(function(name) {
+  Formatter.add('object', name, function(value) {
+    return this._formatObject(value, {
+      additionalProperties: [['[[PrimitiveValue]]', value.valueOf()]]
+    });
+  });
+});
+
+Formatter.add('object', 'string', function(value) {
+  var realValue = value.valueOf();
+
+  return this._formatObject(value, {
+    keyFilter: function(key) {
+      //skip useless indexed properties
+      return !(key.match(/\d+/) && parseInt(key, 10) < realValue.length);
+    },
+    additionalProperties: [['[[PrimitiveValue]]', realValue]]
+  });
+});
+
+Formatter.add('object', 'regexp', function(value) {
+  return this._formatObject(value, {
+    value: String(value)
+  });
+});
+
+Formatter.add('number', function(value) {
+  if(value === 0 && 1 / value < 0) return '-0';
+  return String(value);
+});
+
+Formatter.add('string', function(value) {
+  return '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+      .replace(/'/g, "\\'")
+      .replace(/\\"/g, '"') + '\'';
+});
+
+Formatter.add('object', function(value) {
+  return this._formatObject(value);
+});
+
+Formatter.add('object', 'arguments', function(value) {
+  return this._formatObject(value, {
+    prefix: 'Arguments',
+    formatPropertyName: function(key) {
+      if(!key.match(/\d+/)) {
+        return this.formatPropertyName(key);
+      }
+    },
+    brackets: ['[', ']']
+  });
+});
+
+Formatter.add('object', 'array', function(value) {
+  return this._formatObject(value, {
+    formatPropertyName: function(key) {
+      if(!key.match(/\d+/)) {
+        return this.formatPropertyName(key);
+      }
+    },
+    brackets: ['[', ']']
+  });
+});
+
+
+function formatDate(value, isUTC) {
+  var prefix = isUTC ? 'UTC' : '';
+
+  var date = value['get' + prefix + 'FullYear']() +
+    '-' +
+    util.pad0(value['get' + prefix + 'Month']() + 1, 2) +
+    '-' +
+    util.pad0(value['get' + prefix + 'Date'](), 2);
+
+  var time = util.pad0(value['get' + prefix + 'Hours'](), 2) +
+    ':' +
+    util.pad0(value['get' + prefix + 'Minutes'](), 2) +
+    ':' +
+    util.pad0(value['get' + prefix + 'Seconds'](), 2) +
+    '.' +
+    util.pad0(value['get' + prefix + 'Milliseconds'](), 3);
+
+  var to = value.getTimezoneOffset();
+  var absTo = Math.abs(to);
+  var hours = Math.floor(absTo / 60);
+  var minutes = absTo - hours * 60;
+  var tzFormat = (to < 0 ? '+' : '-') + util.pad0(hours, 2) + util.pad0(minutes, 2);
+
+  return date + ' ' + time + (isUTC ? '' : ' ' + tzFormat);
+}
+
+Formatter.add('object', 'date', function(value) {
+  return this._formatObject(value, { value: formatDate(value, this.isUTCdate) });
+});
+
+Formatter.add('function', function(value) {
+  return this._formatObject(value, {
+    additionalProperties: [['name', Formatter.functionName(value)]]
+  });
+});
+
+Formatter.add('object', 'error', function(value) {
+  return this._formatObject(value, {
+    prefix: value.name,
+    additionalProperties: [['message', value.message]]
+  });
+});
+
+Formatter.add('object', 'buffer', Formatter.generateFunctionForIndexedArray('length', 'Buffer', 2));
+
+Formatter.add('object', 'array-buffer', Formatter.generateFunctionForIndexedArray('byteLength', 'ArrayBuffer', 2));
+
+Formatter.add('object', 'typed-array', 'int8', Formatter.generateFunctionForIndexedArray('length', 'Int8Array', 2));
+Formatter.add('object', 'typed-array', 'uint8', Formatter.generateFunctionForIndexedArray('length', 'Uint8Array', 2));
+Formatter.add('object', 'typed-array', 'uint8clamped', Formatter.generateFunctionForIndexedArray('length', 'Uint8ClampedArray', 2));
+
+Formatter.add('object', 'typed-array', 'int16', Formatter.generateFunctionForIndexedArray('length', 'Int16Array', 4));
+Formatter.add('object', 'typed-array', 'uint16', Formatter.generateFunctionForIndexedArray('length', 'Uint16Array', 4));
+
+Formatter.add('object', 'typed-array', 'int32', Formatter.generateFunctionForIndexedArray('length', 'Int32Array', 8));
+Formatter.add('object', 'typed-array', 'uint32', Formatter.generateFunctionForIndexedArray('length', 'Uint32Array', 8));
+
+//TODO add float32 and float64
+
+Formatter.add('object', 'promise', function() {
+  return '[Promise]';//TODO it could be nice to inspect its state and value
+});
+
+Formatter.add('object', 'xhr', function() {
+  return '[XMLHttpRequest]';//TODO it could be nice to inspect its state
+});
+
+Formatter.add('object', 'html-element', function(value) {
+  return value.outerHTML;
+});
+
+Formatter.add('object', 'html-element', '#text', function(value) {
+  return value.nodeValue;
+});
+
+Formatter.add('object', 'html-element', '#document', function(value) {
+  return value.documentElement.outerHTML;
+});
+
+Formatter.add('object', 'host', function() {
+  return '[Host]';
+});
+
+Formatter.add('object', 'set', function(value) {
+  var iter = value.values();
+  var len = 0;
+
+  this.seen.push(value);
+
+  var props = [];
+
+  var next = iter.next();
+  while(!next.done) {
+    var val = next.value;
+    var f = this.format(val);
+    len += f.length;
+    props.push(f);
+
+    next = iter.next();
+  }
+
+  this.seen.pop();
+
+  if(props.length === 0) return 'Set {}';
+
+  if(len <= this.maxLineLength) {
+    return 'Set { ' + props.join(this.propSep + ' ') + ' }';
+  } else {
+    return 'Set {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
+  }
+});
+
+Formatter.add('object', 'map', function(value) {
+  var iter = value.entries();
+  var len = 0;
+
+  this.seen.push(value);
+
+  var props = [];
+
+  var next = iter.next();
+  while(!next.done) {
+    var val = next.value;
+    var fK = this.format(val[0]);
+    var fV = this.format(val[1]);
+
+    var f;
+    if((fK.length + fV.length + 4) <= this.maxLineLength) {
+      f = fK + ' => ' + fV;
+    } else {
+      f = fK + ' =>\n' + fV;
+    }
+
+    len += fK.length + fV.length + 4;
+    props.push(f);
+
+    next = iter.next();
+  }
+
+  this.seen.pop();
+
+  if(props.length === 0) return 'Map {}';
+
+  if(len <= this.maxLineLength) {
+    return 'Map { ' + props.join(this.propSep + ' ') + ' }';
+  } else {
+    return 'Map {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
+  }
+});
+
+Formatter.prototype.defaultFormat = Formatter.prototype._format_object;
+
+function defaultFormat(value, opts) {
+  return new Formatter(opts).format(value);
+}
+
+defaultFormat.Formatter = Formatter;
+module.exports = defaultFormat;
diff --git a/node_modules/should/node_modules/should-format/package.json b/node_modules/should/node_modules/should-format/package.json
new file mode 100644
index 0000000..d6272be
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/package.json
@@ -0,0 +1,58 @@
+{
+  "name": "should-format",
+  "version": "0.3.1",
+  "description": "Formatting of objects for should.js",
+  "main": "index.js",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/shouldjs/format.git"
+  },
+  "scripts": {
+    "test": "mocha -R mocha-better-spec-reporter tests/test.js",
+    "browserify": "rm tests/browser/tests.js && browserify tests/test.js >> tests/browser/tests.js"
+  },
+  "keywords": [
+    "should",
+    "format"
+  ],
+  "author": {
+    "name": "Denis Bardadym",
+    "email": "bardadymchik@gmail.com"
+  },
+  "license": "MIT",
+  "devDependencies": {
+    "browserify": "latest",
+    "mocha": "latest",
+    "mocha-better-spec-reporter": "latest"
+  },
+  "dependencies": {
+    "should-type": "0.2.0"
+  },
+  "gitHead": "b0320d30cc16c860b4dc973675ea1f339cef9dce",
+  "bugs": {
+    "url": "https://github.com/shouldjs/format/issues"
+  },
+  "homepage": "https://github.com/shouldjs/format#readme",
+  "_id": "should-format@0.3.1",
+  "_shasum": "2cbb782461670ace4292b2b1ec468db8cf99e330",
+  "_from": "should-format@0.3.1",
+  "_npmVersion": "2.14.7",
+  "_nodeVersion": "4.2.0",
+  "_npmUser": {
+    "name": "btd",
+    "email": "bardadymchik@gmail.com"
+  },
+  "dist": {
+    "shasum": "2cbb782461670ace4292b2b1ec468db8cf99e330",
+    "tarball": "http://registry.npmjs.org/should-format/-/should-format-0.3.1.tgz"
+  },
+  "maintainers": [
+    {
+      "name": "btd",
+      "email": "bardadymchik@gmail.com"
+    }
+  ],
+  "directories": {},
+  "_resolved": "https://registry.npmjs.org/should-format/-/should-format-0.3.1.tgz",
+  "readme": "ERROR: No README data found!"
+}
diff --git a/node_modules/should/node_modules/should-format/tests/browser/index.html b/node_modules/should/node_modules/should-format/tests/browser/index.html
new file mode 100644
index 0000000..0590d4a
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/tests/browser/index.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Mocha</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="stylesheet" href="mocha.css" />
+  </head>
+  <body>
+    <div id="mocha"></div>
+    <script src="mocha.js"></script>
+    <script>mocha.setup('bdd')</script>
+    <script src="tests.js"></script>
+    <script>
+      mocha.run();
+    </script>
+  </body>
+</html>
diff --git a/node_modules/should/node_modules/should-format/tests/browser/mocha.css b/node_modules/should/node_modules/should-format/tests/browser/mocha.css
new file mode 100644
index 0000000..42b9798
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/tests/browser/mocha.css
@@ -0,0 +1,270 @@
+@charset "utf-8";
+
+body {
+  margin:0;
+}
+
+#mocha {
+  font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
+  margin: 60px 50px;
+}
+
+#mocha ul,
+#mocha li {
+  margin: 0;
+  padding: 0;
+}
+
+#mocha ul {
+  list-style: none;
+}
+
+#mocha h1,
+#mocha h2 {
+  margin: 0;
+}
+
+#mocha h1 {
+  margin-top: 15px;
+  font-size: 1em;
+  font-weight: 200;
+}
+
+#mocha h1 a {
+  text-decoration: none;
+  color: inherit;
+}
+
+#mocha h1 a:hover {
+  text-decoration: underline;
+}
+
+#mocha .suite .suite h1 {
+  margin-top: 0;
+  font-size: .8em;
+}
+
+#mocha .hidden {
+  display: none;
+}
+
+#mocha h2 {
+  font-size: 12px;
+  font-weight: normal;
+  cursor: pointer;
+}
+
+#mocha .suite {
+  margin-left: 15px;
+}
+
+#mocha .test {
+  margin-left: 15px;
+  overflow: hidden;
+}
+
+#mocha .test.pending:hover h2::after {
+  content: '(pending)';
+  font-family: arial, sans-serif;
+}
+
+#mocha .test.pass.medium .duration {
+  background: #c09853;
+}
+
+#mocha .test.pass.slow .duration {
+  background: #b94a48;
+}
+
+#mocha .test.pass::before {
+  content: '✓';
+  font-size: 12px;
+  display: block;
+  float: left;
+  margin-right: 5px;
+  color: #00d6b2;
+}
+
+#mocha .test.pass .duration {
+  font-size: 9px;
+  margin-left: 5px;
+  padding: 2px 5px;
+  color: #fff;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+  -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+  box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  -ms-border-radius: 5px;
+  -o-border-radius: 5px;
+  border-radius: 5px;
+}
+
+#mocha .test.pass.fast .duration {
+  display: none;
+}
+
+#mocha .test.pending {
+  color: #0b97c4;
+}
+
+#mocha .test.pending::before {
+  content: '◦';
+  color: #0b97c4;
+}
+
+#mocha .test.fail {
+  color: #c00;
+}
+
+#mocha .test.fail pre {
+  color: black;
+}
+
+#mocha .test.fail::before {
+  content: '✖';
+  font-size: 12px;
+  display: block;
+  float: left;
+  margin-right: 5px;
+  color: #c00;
+}
+
+#mocha .test pre.error {
+  color: #c00;
+  max-height: 300px;
+  overflow: auto;
+}
+
+/**
+ * (1): approximate for browsers not supporting calc
+ * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
+ *      ^^ seriously
+ */
+#mocha .test pre {
+  display: block;
+  float: left;
+  clear: left;
+  font: 12px/1.5 monaco, monospace;
+  margin: 5px;
+  padding: 15px;
+  border: 1px solid #eee;
+  max-width: 85%; /*(1)*/
+  max-width: calc(100% - 42px); /*(2)*/
+  word-wrap: break-word;
+  border-bottom-color: #ddd;
+  -webkit-border-radius: 3px;
+  -webkit-box-shadow: 0 1px 3px #eee;
+  -moz-border-radius: 3px;
+  -moz-box-shadow: 0 1px 3px #eee;
+  border-radius: 3px;
+}
+
+#mocha .test h2 {
+  position: relative;
+}
+
+#mocha .test a.replay {
+  position: absolute;
+  top: 3px;
+  right: 0;
+  text-decoration: none;
+  vertical-align: middle;
+  display: block;
+  width: 15px;
+  height: 15px;
+  line-height: 15px;
+  text-align: center;
+  background: #eee;
+  font-size: 15px;
+  -moz-border-radius: 15px;
+  border-radius: 15px;
+  -webkit-transition: opacity 200ms;
+  -moz-transition: opacity 200ms;
+  transition: opacity 200ms;
+  opacity: 0.3;
+  color: #888;
+}
+
+#mocha .test:hover a.replay {
+  opacity: 1;
+}
+
+#mocha-report.pass .test.fail {
+  display: none;
+}
+
+#mocha-report.fail .test.pass {
+  display: none;
+}
+
+#mocha-report.pending .test.pass,
+#mocha-report.pending .test.fail {
+  display: none;
+}
+#mocha-report.pending .test.pass.pending {
+  display: block;
+}
+
+#mocha-error {
+  color: #c00;
+  font-size: 1.5em;
+  font-weight: 100;
+  letter-spacing: 1px;
+}
+
+#mocha-stats {
+  position: fixed;
+  top: 15px;
+  right: 10px;
+  font-size: 12px;
+  margin: 0;
+  color: #888;
+  z-index: 1;
+}
+
+#mocha-stats .progress {
+  float: right;
+  padding-top: 0;
+}
+
+#mocha-stats em {
+  color: black;
+}
+
+#mocha-stats a {
+  text-decoration: none;
+  color: inherit;
+}
+
+#mocha-stats a:hover {
+  border-bottom: 1px solid #eee;
+}
+
+#mocha-stats li {
+  display: inline-block;
+  margin: 0 5px;
+  list-style: none;
+  padding-top: 11px;
+}
+
+#mocha-stats canvas {
+  width: 40px;
+  height: 40px;
+}
+
+#mocha code .comment { color: #ddd; }
+#mocha code .init { color: #2f6fad; }
+#mocha code .string { color: #5890ad; }
+#mocha code .keyword { color: #8a6343; }
+#mocha code .number { color: #2f6fad; }
+
+@media screen and (max-device-width: 480px) {
+  #mocha {
+    margin: 60px 0px;
+  }
+
+  #mocha #stats {
+    position: absolute;
+  }
+}
diff --git a/node_modules/should/node_modules/should-format/tests/browser/mocha.js b/node_modules/should/node_modules/should-format/tests/browser/mocha.js
new file mode 100644
index 0000000..564a4f3
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/tests/browser/mocha.js
@@ -0,0 +1,6069 @@
+;(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.charAt(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("browser/debug.js", function(module, exports, require){
+module.exports = function(type){
+  return function(){
+  }
+};
+
+}); // module: browser/debug.js
+
+require.register("browser/diff.js", function(module, exports, require){
+/* See LICENSE file for terms of use */
+
+/*
+ * Text diff implementation.
+ *
+ * This library supports the following APIS:
+ * JsDiff.diffChars: Character by character diff
+ * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
+ * JsDiff.diffLines: Line based diff
+ *
+ * JsDiff.diffCss: Diff targeted at CSS content
+ *
+ * These methods are based on the implementation proposed in
+ * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
+ * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
+ */
+var JsDiff = (function() {
+  /*jshint maxparams: 5*/
+  function clonePath(path) {
+    return { newPos: path.newPos, components: path.components.slice(0) };
+  }
+  function removeEmpty(array) {
+    var ret = [];
+    for (var i = 0; i < array.length; i++) {
+      if (array[i]) {
+        ret.push(array[i]);
+      }
+    }
+    return ret;
+  }
+  function escapeHTML(s) {
+    var n = s;
+    n = n.replace(/&/g, '&amp;');
+    n = n.replace(/</g, '&lt;');
+    n = n.replace(/>/g, '&gt;');
+    n = n.replace(/"/g, '&quot;');
+
+    return n;
+  }
+
+  var Diff = function(ignoreWhitespace) {
+    this.ignoreWhitespace = ignoreWhitespace;
+  };
+  Diff.prototype = {
+      diff: function(oldString, newString) {
+        // Handle the identity case (this is due to unrolling editLength == 0
+        if (newString === oldString) {
+          return [{ value: newString }];
+        }
+        if (!newString) {
+          return [{ value: oldString, removed: true }];
+        }
+        if (!oldString) {
+          return [{ value: newString, added: true }];
+        }
+
+        newString = this.tokenize(newString);
+        oldString = this.tokenize(oldString);
+
+        var newLen = newString.length, oldLen = oldString.length;
+        var maxEditLength = newLen + oldLen;
+        var bestPath = [{ newPos: -1, components: [] }];
+
+        // Seed editLength = 0
+        var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
+        if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) {
+          return bestPath[0].components;
+        }
+
+        for (var editLength = 1; editLength <= maxEditLength; editLength++) {
+          for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) {
+            var basePath;
+            var addPath = bestPath[diagonalPath-1],
+                removePath = bestPath[diagonalPath+1];
+            oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
+            if (addPath) {
+              // No one else is going to attempt to use this value, clear it
+              bestPath[diagonalPath-1] = undefined;
+            }
+
+            var canAdd = addPath && addPath.newPos+1 < newLen;
+            var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
+            if (!canAdd && !canRemove) {
+              bestPath[diagonalPath] = undefined;
+              continue;
+            }
+
+            // Select the diagonal that we want to branch from. We select the prior
+            // path whose position in the new string is the farthest from the origin
+            // and does not pass the bounds of the diff graph
+            if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
+              basePath = clonePath(removePath);
+              this.pushComponent(basePath.components, oldString[oldPos], undefined, true);
+            } else {
+              basePath = clonePath(addPath);
+              basePath.newPos++;
+              this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);
+            }
+
+            var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);
+
+            if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) {
+              return basePath.components;
+            } else {
+              bestPath[diagonalPath] = basePath;
+            }
+          }
+        }
+      },
+
+      pushComponent: function(components, value, added, removed) {
+        var last = components[components.length-1];
+        if (last && last.added === added && last.removed === removed) {
+          // We need to clone here as the component clone operation is just
+          // as shallow array clone
+          components[components.length-1] =
+            {value: this.join(last.value, value), added: added, removed: removed };
+        } else {
+          components.push({value: value, added: added, removed: removed });
+        }
+      },
+      extractCommon: function(basePath, newString, oldString, diagonalPath) {
+        var newLen = newString.length,
+            oldLen = oldString.length,
+            newPos = basePath.newPos,
+            oldPos = newPos - diagonalPath;
+        while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {
+          newPos++;
+          oldPos++;
+
+          this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
+        }
+        basePath.newPos = newPos;
+        return oldPos;
+      },
+
+      equals: function(left, right) {
+        var reWhitespace = /\S/;
+        if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
+          return true;
+        } else {
+          return left === right;
+        }
+      },
+      join: function(left, right) {
+        return left + right;
+      },
+      tokenize: function(value) {
+        return value;
+      }
+  };
+
+  var CharDiff = new Diff();
+
+  var WordDiff = new Diff(true);
+  var WordWithSpaceDiff = new Diff();
+  WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) {
+    return removeEmpty(value.split(/(\s+|\b)/));
+  };
+
+  var CssDiff = new Diff(true);
+  CssDiff.tokenize = function(value) {
+    return removeEmpty(value.split(/([{}:;,]|\s+)/));
+  };
+
+  var LineDiff = new Diff();
+  LineDiff.tokenize = function(value) {
+    return value.split(/^/m);
+  };
+
+  return {
+    Diff: Diff,
+
+    diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
+    diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },
+    diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); },
+    diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },
+
+    diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },
+
+    createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
+      var ret = [];
+
+      ret.push('Index: ' + fileName);
+      ret.push('===================================================================');
+      ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
+      ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));
+
+      var diff = LineDiff.diff(oldStr, newStr);
+      if (!diff[diff.length-1].value) {
+        diff.pop();   // Remove trailing newline add
+      }
+      diff.push({value: '', lines: []});   // Append an empty value to make cleanup easier
+
+      function contextLines(lines) {
+        return lines.map(function(entry) { return ' ' + entry; });
+      }
+      function eofNL(curRange, i, current) {
+        var last = diff[diff.length-2],
+            isLast = i === diff.length-2,
+            isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);
+
+        // Figure out if this is the last line for the given file and missing NL
+        if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
+          curRange.push('\\ No newline at end of file');
+        }
+      }
+
+      var oldRangeStart = 0, newRangeStart = 0, curRange = [],
+          oldLine = 1, newLine = 1;
+      for (var i = 0; i < diff.length; i++) {
+        var current = diff[i],
+            lines = current.lines || current.value.replace(/\n$/, '').split('\n');
+        current.lines = lines;
+
+        if (current.added || current.removed) {
+          if (!oldRangeStart) {
+            var prev = diff[i-1];
+            oldRangeStart = oldLine;
+            newRangeStart = newLine;
+
+            if (prev) {
+              curRange = contextLines(prev.lines.slice(-4));
+              oldRangeStart -= curRange.length;
+              newRangeStart -= curRange.length;
+            }
+          }
+          curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; }));
+          eofNL(curRange, i, current);
+
+          if (current.added) {
+            newLine += lines.length;
+          } else {
+            oldLine += lines.length;
+          }
+        } else {
+          if (oldRangeStart) {
+            // Close out any changes that have been output (or join overlapping)
+            if (lines.length <= 8 && i < diff.length-2) {
+              // Overlapping
+              curRange.push.apply(curRange, contextLines(lines));
+            } else {
+              // end the range and output
+              var contextSize = Math.min(lines.length, 4);
+              ret.push(
+                  '@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)
+                  + ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)
+                  + ' @@');
+              ret.push.apply(ret, curRange);
+              ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
+              if (lines.length <= 4) {
+                eofNL(ret, i, current);
+              }
+
+              oldRangeStart = 0;  newRangeStart = 0; curRange = [];
+            }
+          }
+          oldLine += lines.length;
+          newLine += lines.length;
+        }
+      }
+
+      return ret.join('\n') + '\n';
+    },
+
+    applyPatch: function(oldStr, uniDiff) {
+      var diffstr = uniDiff.split('\n');
+      var diff = [];
+      var remEOFNL = false,
+          addEOFNL = false;
+
+      for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) {
+        if(diffstr[i][0] === '@') {
+          var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
+          diff.unshift({
+            start:meh[3],
+            oldlength:meh[2],
+            oldlines:[],
+            newlength:meh[4],
+            newlines:[]
+          });
+        } else if(diffstr[i][0] === '+') {
+          diff[0].newlines.push(diffstr[i].substr(1));
+        } else if(diffstr[i][0] === '-') {
+          diff[0].oldlines.push(diffstr[i].substr(1));
+        } else if(diffstr[i][0] === ' ') {
+          diff[0].newlines.push(diffstr[i].substr(1));
+          diff[0].oldlines.push(diffstr[i].substr(1));
+        } else if(diffstr[i][0] === '\\') {
+          if (diffstr[i-1][0] === '+') {
+            remEOFNL = true;
+          } else if(diffstr[i-1][0] === '-') {
+            addEOFNL = true;
+          }
+        }
+      }
+
+      var str = oldStr.split('\n');
+      for (var i = diff.length - 1; i >= 0; i--) {
+        var d = diff[i];
+        for (var j = 0; j < d.oldlength; j++) {
+          if(str[d.start-1+j] !== d.oldlines[j]) {
+            return false;
+          }
+        }
+        Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
+      }
+
+      if (remEOFNL) {
+        while (!str[str.length-1]) {
+          str.pop();
+        }
+      } else if (addEOFNL) {
+        str.push('');
+      }
+      return str.join('\n');
+    },
+
+    convertChangesToXML: function(changes){
+      var ret = [];
+      for ( var i = 0; i < changes.length; i++) {
+        var change = changes[i];
+        if (change.added) {
+          ret.push('<ins>');
+        } else if (change.removed) {
+          ret.push('<del>');
+        }
+
+        ret.push(escapeHTML(change.value));
+
+        if (change.added) {
+          ret.push('</ins>');
+        } else if (change.removed) {
+          ret.push('</del>');
+        }
+      }
+      return ret.join('');
+    },
+
+    // See: http://code.google.com/p/google-diff-match-patch/wiki/API
+    convertChangesToDMP: function(changes){
+      var ret = [], change;
+      for ( var i = 0; i < changes.length; i++) {
+        change = changes[i];
+        ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);
+      }
+      return ret;
+    }
+  };
+})();
+
+if (typeof module !== 'undefined') {
+    module.exports = JsDiff;
+}
+
+}); // module: browser/diff.js
+
+require.register("browser/escape-string-regexp.js", function(module, exports, require){
+'use strict';
+
+var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
+
+module.exports = function (str) {
+  if (typeof str !== 'string') {
+    throw new TypeError('Expected a string');
+  }
+
+  return str.replace(matchOperatorsRe,  '\\$&');
+};
+
+}); // module: browser/escape-string-regexp.js
+
+require.register("browser/events.js", function(module, exports, require){
+/**
+ * Module exports.
+ */
+
+exports.EventEmitter = EventEmitter;
+
+/**
+ * Check if `obj` is an array.
+ */
+
+function isArray(obj) {
+  return '[object Array]' == {}.toString.call(obj);
+}
+
+/**
+ * Event emitter constructor.
+ *
+ * @api public
+ */
+
+function EventEmitter(){};
+
+/**
+ * Adds a listener.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.on = function (name, fn) {
+  if (!this.$events) {
+    this.$events = {};
+  }
+
+  if (!this.$events[name]) {
+    this.$events[name] = fn;
+  } else if (isArray(this.$events[name])) {
+    this.$events[name].push(fn);
+  } else {
+    this.$events[name] = [this.$events[name], fn];
+  }
+
+  return this;
+};
+
+EventEmitter.prototype.addListener = EventEmitter.prototype.on;
+
+/**
+ * Adds a volatile listener.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.once = function (name, fn) {
+  var self = this;
+
+  function on () {
+    self.removeListener(name, on);
+    fn.apply(this, arguments);
+  };
+
+  on.listener = fn;
+  this.on(name, on);
+
+  return this;
+};
+
+/**
+ * Removes a listener.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.removeListener = function (name, fn) {
+  if (this.$events && this.$events[name]) {
+    var list = this.$events[name];
+
+    if (isArray(list)) {
+      var pos = -1;
+
+      for (var i = 0, l = list.length; i < l; i++) {
+        if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
+          pos = i;
+          break;
+        }
+      }
+
+      if (pos < 0) {
+        return this;
+      }
+
+      list.splice(pos, 1);
+
+      if (!list.length) {
+        delete this.$events[name];
+      }
+    } else if (list === fn || (list.listener && list.listener === fn)) {
+      delete this.$events[name];
+    }
+  }
+
+  return this;
+};
+
+/**
+ * Removes all listeners for an event.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.removeAllListeners = function (name) {
+  if (name === undefined) {
+    this.$events = {};
+    return this;
+  }
+
+  if (this.$events && this.$events[name]) {
+    this.$events[name] = null;
+  }
+
+  return this;
+};
+
+/**
+ * Gets all listeners for a certain event.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.listeners = function (name) {
+  if (!this.$events) {
+    this.$events = {};
+  }
+
+  if (!this.$events[name]) {
+    this.$events[name] = [];
+  }
+
+  if (!isArray(this.$events[name])) {
+    this.$events[name] = [this.$events[name]];
+  }
+
+  return this.$events[name];
+};
+
+/**
+ * Emits an event.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.emit = function (name) {
+  if (!this.$events) {
+    return false;
+  }
+
+  var handler = this.$events[name];
+
+  if (!handler) {
+    return false;
+  }
+
+  var args = [].slice.call(arguments, 1);
+
+  if ('function' == typeof handler) {
+    handler.apply(this, args);
+  } else if (isArray(handler)) {
+    var listeners = handler.slice();
+
+    for (var i = 0, l = listeners.length; i < l; i++) {
+      listeners[i].apply(this, args);
+    }
+  } else {
+    return false;
+  }
+
+  return true;
+};
+
+}); // module: browser/events.js
+
+require.register("browser/fs.js", function(module, exports, require){
+
+}); // module: browser/fs.js
+
+require.register("browser/glob.js", function(module, exports, require){
+
+}); // module: browser/glob.js
+
+require.register("browser/path.js", function(module, exports, require){
+
+}); // module: browser/path.js
+
+require.register("browser/progress.js", function(module, exports, require){
+/**
+ * Expose `Progress`.
+ */
+
+module.exports = Progress;
+
+/**
+ * Initialize a new `Progress` indicator.
+ */
+
+function Progress() {
+  this.percent = 0;
+  this.size(0);
+  this.fontSize(11);
+  this.font('helvetica, arial, sans-serif');
+}
+
+/**
+ * Set progress size to `n`.
+ *
+ * @param {Number} n
+ * @return {Progress} for chaining
+ * @api public
+ */
+
+Progress.prototype.size = function(n){
+  this._size = n;
+  return this;
+};
+
+/**
+ * Set text to `str`.
+ *
+ * @param {String} str
+ * @return {Progress} for chaining
+ * @api public
+ */
+
+Progress.prototype.text = function(str){
+  this._text = str;
+  return this;
+};
+
+/**
+ * Set font size to `n`.
+ *
+ * @param {Number} n
+ * @return {Progress} for chaining
+ * @api public
+ */
+
+Progress.prototype.fontSize = function(n){
+  this._fontSize = n;
+  return this;
+};
+
+/**
+ * Set font `family`.
+ *
+ * @param {String} family
+ * @return {Progress} for chaining
+ */
+
+Progress.prototype.font = function(family){
+  this._font = family;
+  return this;
+};
+
+/**
+ * Update percentage to `n`.
+ *
+ * @param {Number} n
+ * @return {Progress} for chaining
+ */
+
+Progress.prototype.update = function(n){
+  this.percent = n;
+  return this;
+};
+
+/**
+ * Draw on `ctx`.
+ *
+ * @param {CanvasRenderingContext2d} ctx
+ * @return {Progress} for chaining
+ */
+
+Progress.prototype.draw = function(ctx){
+  try {
+    var percent = Math.min(this.percent, 100)
+      , size = this._size
+      , half = size / 2
+      , x = half
+      , y = half
+      , rad = half - 1
+      , fontSize = this._fontSize;
+
+    ctx.font = fontSize + 'px ' + this._font;
+
+    var angle = Math.PI * 2 * (percent / 100);
+    ctx.clearRect(0, 0, size, size);
+
+    // outer circle
+    ctx.strokeStyle = '#9f9f9f';
+    ctx.beginPath();
+    ctx.arc(x, y, rad, 0, angle, false);
+    ctx.stroke();
+
+    // inner circle
+    ctx.strokeStyle = '#eee';
+    ctx.beginPath();
+    ctx.arc(x, y, rad - 1, 0, angle, true);
+    ctx.stroke();
+
+    // text
+    var text = this._text || (percent | 0) + '%'
+      , w = ctx.measureText(text).width;
+
+    ctx.fillText(
+        text
+      , x - w / 2 + 1
+      , y + fontSize / 2 - 1);
+  } catch (ex) {} //don't fail if we can't render progress
+  return this;
+};
+
+}); // module: browser/progress.js
+
+require.register("browser/tty.js", function(module, exports, require){
+exports.isatty = function(){
+  return true;
+};
+
+exports.getWindowSize = function(){
+  if ('innerHeight' in global) {
+    return [global.innerHeight, global.innerWidth];
+  } else {
+    // In a Web Worker, the DOM Window is not available.
+    return [640, 480];
+  }
+};
+
+}); // module: browser/tty.js
+
+require.register("context.js", function(module, exports, require){
+/**
+ * Expose `Context`.
+ */
+
+module.exports = Context;
+
+/**
+ * Initialize a new `Context`.
+ *
+ * @api private
+ */
+
+function Context(){}
+
+/**
+ * Set or get the context `Runnable` to `runnable`.
+ *
+ * @param {Runnable} runnable
+ * @return {Context}
+ * @api private
+ */
+
+Context.prototype.runnable = function(runnable){
+  if (0 == arguments.length) return this._runnable;
+  this.test = this._runnable = runnable;
+  return this;
+};
+
+/**
+ * Set test timeout `ms`.
+ *
+ * @param {Number} ms
+ * @return {Context} self
+ * @api private
+ */
+
+Context.prototype.timeout = function(ms){
+  if (arguments.length === 0) return this.runnable().timeout();
+  this.runnable().timeout(ms);
+  return this;
+};
+
+/**
+ * Set test timeout `enabled`.
+ *
+ * @param {Boolean} enabled
+ * @return {Context} self
+ * @api private
+ */
+
+Context.prototype.enableTimeouts = function (enabled) {
+  this.runnable().enableTimeouts(enabled);
+  return this;
+};
+
+
+/**
+ * Set test slowness threshold `ms`.
+ *
+ * @param {Number} ms
+ * @return {Context} self
+ * @api private
+ */
+
+Context.prototype.slow = function(ms){
+  this.runnable().slow(ms);
+  return this;
+};
+
+/**
+ * Inspect the context void of `._runnable`.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Context.prototype.inspect = function(){
+  return JSON.stringify(this, function(key, val){
+    if ('_runnable' == key) return;
+    if ('test' == key) return;
+    return val;
+  }, 2);
+};
+
+}); // module: context.js
+
+require.register("hook.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Runnable = require('./runnable');
+
+/**
+ * Expose `Hook`.
+ */
+
+module.exports = Hook;
+
+/**
+ * Initialize a new `Hook` with the given `title` and callback `fn`.
+ *
+ * @param {String} title
+ * @param {Function} fn
+ * @api private
+ */
+
+function Hook(title, fn) {
+  Runnable.call(this, title, fn);
+  this.type = 'hook';
+}
+
+/**
+ * Inherit from `Runnable.prototype`.
+ */
+
+function F(){};
+F.prototype = Runnable.prototype;
+Hook.prototype = new F;
+Hook.prototype.constructor = Hook;
+
+
+/**
+ * Get or set the test `err`.
+ *
+ * @param {Error} err
+ * @return {Error}
+ * @api public
+ */
+
+Hook.prototype.error = function(err){
+  if (0 == arguments.length) {
+    var err = this._error;
+    this._error = null;
+    return err;
+  }
+
+  this._error = err;
+};
+
+}); // module: hook.js
+
+require.register("interfaces/bdd.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+  , Test = require('../test')
+  , utils = require('../utils')
+  , escapeRe = require('browser/escape-string-regexp');
+
+/**
+ * BDD-style interface:
+ *
+ *      describe('Array', function(){
+ *        describe('#indexOf()', function(){
+ *          it('should return -1 when not present', function(){
+ *
+ *          });
+ *
+ *          it('should return the index when present', function(){
+ *
+ *          });
+ *        });
+ *      });
+ *
+ */
+
+module.exports = function(suite){
+  var suites = [suite];
+
+  suite.on('pre-require', function(context, file, mocha){
+
+    /**
+     * Execute before running tests.
+     */
+
+    context.before = function(name, fn){
+      suites[0].beforeAll(name, fn);
+    };
+
+    /**
+     * Execute after running tests.
+     */
+
+    context.after = function(name, fn){
+      suites[0].afterAll(name, fn);
+    };
+
+    /**
+     * Execute before each test case.
+     */
+
+    context.beforeEach = function(name, fn){
+      suites[0].beforeEach(name, fn);
+    };
+
+    /**
+     * Execute after each test case.
+     */
+
+    context.afterEach = function(name, fn){
+      suites[0].afterEach(name, fn);
+    };
+
+    /**
+     * Describe a "suite" with the given `title`
+     * and callback `fn` containing nested suites
+     * and/or tests.
+     */
+
+    context.describe = context.context = function(title, fn){
+      var suite = Suite.create(suites[0], title);
+      suite.file = file;
+      suites.unshift(suite);
+      fn.call(suite);
+      suites.shift();
+      return suite;
+    };
+
+    /**
+     * Pending describe.
+     */
+
+    context.xdescribe =
+    context.xcontext =
+    context.describe.skip = function(title, fn){
+      var suite = Suite.create(suites[0], title);
+      suite.pending = true;
+      suites.unshift(suite);
+      fn.call(suite);
+      suites.shift();
+    };
+
+    /**
+     * Exclusive suite.
+     */
+
+    context.describe.only = function(title, fn){
+      var suite = context.describe(title, fn);
+      mocha.grep(suite.fullTitle());
+      return suite;
+    };
+
+    /**
+     * Describe a specification or test-case
+     * with the given `title` and callback `fn`
+     * acting as a thunk.
+     */
+
+    context.it = context.specify = function(title, fn){
+      var suite = suites[0];
+      if (suite.pending) fn = null;
+      var test = new Test(title, fn);
+      test.file = file;
+      suite.addTest(test);
+      return test;
+    };
+
+    /**
+     * Exclusive test-case.
+     */
+
+    context.it.only = function(title, fn){
+      var test = context.it(title, fn);
+      var reString = '^' + escapeRe(test.fullTitle()) + '$';
+      mocha.grep(new RegExp(reString));
+      return test;
+    };
+
+    /**
+     * Pending test case.
+     */
+
+    context.xit =
+    context.xspecify =
+    context.it.skip = function(title){
+      context.it(title);
+    };
+  });
+};
+
+}); // module: interfaces/bdd.js
+
+require.register("interfaces/exports.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+  , Test = require('../test');
+
+/**
+ * TDD-style interface:
+ *
+ *     exports.Array = {
+ *       '#indexOf()': {
+ *         'should return -1 when the value is not present': function(){
+ *
+ *         },
+ *
+ *         'should return the correct index when the value is present': function(){
+ *
+ *         }
+ *       }
+ *     };
+ *
+ */
+
+module.exports = function(suite){
+  var suites = [suite];
+
+  suite.on('require', visit);
+
+  function visit(obj, file) {
+    var suite;
+    for (var key in obj) {
+      if ('function' == typeof obj[key]) {
+        var fn = obj[key];
+        switch (key) {
+          case 'before':
+            suites[0].beforeAll(fn);
+            break;
+          case 'after':
+            suites[0].afterAll(fn);
+            break;
+          case 'beforeEach':
+            suites[0].beforeEach(fn);
+            break;
+          case 'afterEach':
+            suites[0].afterEach(fn);
+            break;
+          default:
+            var test = new Test(key, fn);
+            test.file = file;
+            suites[0].addTest(test);
+        }
+      } else {
+        suite = Suite.create(suites[0], key);
+        suites.unshift(suite);
+        visit(obj[key]);
+        suites.shift();
+      }
+    }
+  }
+};
+
+}); // module: interfaces/exports.js
+
+require.register("interfaces/index.js", function(module, exports, require){
+exports.bdd = require('./bdd');
+exports.tdd = require('./tdd');
+exports.qunit = require('./qunit');
+exports.exports = require('./exports');
+
+}); // module: interfaces/index.js
+
+require.register("interfaces/qunit.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+  , Test = require('../test')
+  , escapeRe = require('browser/escape-string-regexp')
+  , utils = require('../utils');
+
+/**
+ * QUnit-style interface:
+ *
+ *     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);
+ *     });
+ *
+ */
+
+module.exports = function(suite){
+  var suites = [suite];
+
+  suite.on('pre-require', function(context, file, mocha){
+
+    /**
+     * Execute before running tests.
+     */
+
+    context.before = function(name, fn){
+      suites[0].beforeAll(name, fn);
+    };
+
+    /**
+     * Execute after running tests.
+     */
+
+    context.after = function(name, fn){
+      suites[0].afterAll(name, fn);
+    };
+
+    /**
+     * Execute before each test case.
+     */
+
+    context.beforeEach = function(name, fn){
+      suites[0].beforeEach(name, fn);
+    };
+
+    /**
+     * Execute after each test case.
+     */
+
+    context.afterEach = function(name, fn){
+      suites[0].afterEach(name, fn);
+    };
+
+    /**
+     * Describe a "suite" with the given `title`.
+     */
+
+    context.suite = function(title){
+      if (suites.length > 1) suites.shift();
+      var suite = Suite.create(suites[0], title);
+      suite.file = file;
+      suites.unshift(suite);
+      return suite;
+    };
+
+    /**
+     * Exclusive test-case.
+     */
+
+    context.suite.only = function(title, fn){
+      var suite = context.suite(title, fn);
+      mocha.grep(suite.fullTitle());
+    };
+
+    /**
+     * Describe a specification or test-case
+     * with the given `title` and callback `fn`
+     * acting as a thunk.
+     */
+
+    context.test = function(title, fn){
+      var test = new Test(title, fn);
+      test.file = file;
+      suites[0].addTest(test);
+      return test;
+    };
+
+    /**
+     * Exclusive test-case.
+     */
+
+    context.test.only = function(title, fn){
+      var test = context.test(title, fn);
+      var reString = '^' + escapeRe(test.fullTitle()) + '$';
+      mocha.grep(new RegExp(reString));
+    };
+
+    /**
+     * Pending test case.
+     */
+
+    context.test.skip = function(title){
+      context.test(title);
+    };
+  });
+};
+
+}); // module: interfaces/qunit.js
+
+require.register("interfaces/tdd.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+  , Test = require('../test')
+  , escapeRe = require('browser/escape-string-regexp')
+  , utils = require('../utils');
+
+/**
+ * TDD-style interface:
+ *
+ *      suite('Array', function(){
+ *        suite('#indexOf()', function(){
+ *          suiteSetup(function(){
+ *
+ *          });
+ *
+ *          test('should return -1 when not present', function(){
+ *
+ *          });
+ *
+ *          test('should return the index when present', function(){
+ *
+ *          });
+ *
+ *          suiteTeardown(function(){
+ *
+ *          });
+ *        });
+ *      });
+ *
+ */
+
+module.exports = function(suite){
+  var suites = [suite];
+
+  suite.on('pre-require', function(context, file, mocha){
+
+    /**
+     * Execute before each test case.
+     */
+
+    context.setup = function(name, fn){
+      suites[0].beforeEach(name, fn);
+    };
+
+    /**
+     * Execute after each test case.
+     */
+
+    context.teardown = function(name, fn){
+      suites[0].afterEach(name, fn);
+    };
+
+    /**
+     * Execute before the suite.
+     */
+
+    context.suiteSetup = function(name, fn){
+      suites[0].beforeAll(name, fn);
+    };
+
+    /**
+     * Execute after the suite.
+     */
+
+    context.suiteTeardown = function(name, fn){
+      suites[0].afterAll(name, fn);
+    };
+
+    /**
+     * Describe a "suite" with the given `title`
+     * and callback `fn` containing nested suites
+     * and/or tests.
+     */
+
+    context.suite = function(title, fn){
+      var suite = Suite.create(suites[0], title);
+      suite.file = file;
+      suites.unshift(suite);
+      fn.call(suite);
+      suites.shift();
+      return suite;
+    };
+
+    /**
+     * Pending suite.
+     */
+    context.suite.skip = function(title, fn) {
+      var suite = Suite.create(suites[0], title);
+      suite.pending = true;
+      suites.unshift(suite);
+      fn.call(suite);
+      suites.shift();
+    };
+
+    /**
+     * Exclusive test-case.
+     */
+
+    context.suite.only = function(title, fn){
+      var suite = context.suite(title, fn);
+      mocha.grep(suite.fullTitle());
+    };
+
+    /**
+     * Describe a specification or test-case
+     * with the given `title` and callback `fn`
+     * acting as a thunk.
+     */
+
+    context.test = function(title, fn){
+      var suite = suites[0];
+      if (suite.pending) fn = null;
+      var test = new Test(title, fn);
+      test.file = file;
+      suite.addTest(test);
+      return test;
+    };
+
+    /**
+     * Exclusive test-case.
+     */
+
+    context.test.only = function(title, fn){
+      var test = context.test(title, fn);
+      var reString = '^' + escapeRe(test.fullTitle()) + '$';
+      mocha.grep(new RegExp(reString));
+    };
+
+    /**
+     * Pending test case.
+     */
+
+    context.test.skip = function(title){
+      context.test(title);
+    };
+  });
+};
+
+}); // module: interfaces/tdd.js
+
+require.register("mocha.js", function(module, exports, require){
+/*!
+ * mocha
+ * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var path = require('browser/path')
+  , escapeRe = require('browser/escape-string-regexp')
+  , utils = require('./utils');
+
+/**
+ * Expose `Mocha`.
+ */
+
+exports = module.exports = Mocha;
+
+/**
+ * To require local UIs and reporters when running in node.
+ */
+
+if (typeof process !== 'undefined' && typeof process.cwd === 'function') {
+  var join = path.join
+    , cwd = process.cwd();
+  module.paths.push(cwd, join(cwd, 'node_modules'));
+}
+
+/**
+ * Expose internals.
+ */
+
+exports.utils = utils;
+exports.interfaces = require('./interfaces');
+exports.reporters = require('./reporters');
+exports.Runnable = require('./runnable');
+exports.Context = require('./context');
+exports.Runner = require('./runner');
+exports.Suite = require('./suite');
+exports.Hook = require('./hook');
+exports.Test = require('./test');
+
+/**
+ * Return image `name` path.
+ *
+ * @param {String} name
+ * @return {String}
+ * @api private
+ */
+
+function image(name) {
+  return __dirname + '/../images/' + name + '.png';
+}
+
+/**
+ * Setup mocha with `options`.
+ *
+ * Options:
+ *
+ *   - `ui` name "bdd", "tdd", "exports" etc
+ *   - `reporter` reporter instance, defaults to `mocha.reporters.spec`
+ *   - `globals` array of accepted globals
+ *   - `timeout` timeout in milliseconds
+ *   - `bail` bail on the first test failure
+ *   - `slow` milliseconds to wait before considering a test slow
+ *   - `ignoreLeaks` ignore global leaks
+ *   - `grep` string or regexp to filter tests with
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+function Mocha(options) {
+  options = options || {};
+  this.files = [];
+  this.options = options;
+  this.grep(options.grep);
+  this.suite = new exports.Suite('', new exports.Context);
+  this.ui(options.ui);
+  this.bail(options.bail);
+  this.reporter(options.reporter);
+  if (null != options.timeout) this.timeout(options.timeout);
+  this.useColors(options.useColors)
+  if (options.enableTimeouts !== null) this.enableTimeouts(options.enableTimeouts);
+  if (options.slow) this.slow(options.slow);
+
+  this.suite.on('pre-require', function (context) {
+    exports.afterEach = context.afterEach || context.teardown;
+    exports.after = context.after || context.suiteTeardown;
+    exports.beforeEach = context.beforeEach || context.setup;
+    exports.before = context.before || context.suiteSetup;
+    exports.describe = context.describe || context.suite;
+    exports.it = context.it || context.test;
+    exports.setup = context.setup || context.beforeEach;
+    exports.suiteSetup = context.suiteSetup || context.before;
+    exports.suiteTeardown = context.suiteTeardown || context.after;
+    exports.suite = context.suite || context.describe;
+    exports.teardown = context.teardown || context.afterEach;
+    exports.test = context.test || context.it;
+  });
+}
+
+/**
+ * Enable or disable bailing on the first failure.
+ *
+ * @param {Boolean} [bail]
+ * @api public
+ */
+
+Mocha.prototype.bail = function(bail){
+  if (0 == arguments.length) bail = true;
+  this.suite.bail(bail);
+  return this;
+};
+
+/**
+ * Add test `file`.
+ *
+ * @param {String} file
+ * @api public
+ */
+
+Mocha.prototype.addFile = function(file){
+  this.files.push(file);
+  return this;
+};
+
+/**
+ * Set reporter to `reporter`, defaults to "spec".
+ *
+ * @param {String|Function} reporter name or constructor
+ * @api public
+ */
+
+Mocha.prototype.reporter = function(reporter){
+  if ('function' == typeof reporter) {
+    this._reporter = reporter;
+  } else {
+    reporter = reporter || 'spec';
+    var _reporter;
+    try { _reporter = require('./reporters/' + reporter); } catch (err) {};
+    if (!_reporter) try { _reporter = require(reporter); } catch (err) {};
+    if (!_reporter && reporter === 'teamcity')
+      console.warn('The Teamcity reporter was moved to a package named ' +
+        'mocha-teamcity-reporter ' +
+        '(https://npmjs.org/package/mocha-teamcity-reporter).');
+    if (!_reporter) throw new Error('invalid reporter "' + reporter + '"');
+    this._reporter = _reporter;
+  }
+  return this;
+};
+
+/**
+ * Set test UI `name`, defaults to "bdd".
+ *
+ * @param {String} bdd
+ * @api public
+ */
+
+Mocha.prototype.ui = function(name){
+  name = name || 'bdd';
+  this._ui = exports.interfaces[name];
+  if (!this._ui) try { this._ui = require(name); } catch (err) {};
+  if (!this._ui) throw new Error('invalid interface "' + name + '"');
+  this._ui = this._ui(this.suite);
+  return this;
+};
+
+/**
+ * Load registered files.
+ *
+ * @api private
+ */
+
+Mocha.prototype.loadFiles = function(fn){
+  var self = this;
+  var suite = this.suite;
+  var pending = this.files.length;
+  this.files.forEach(function(file){
+    file = path.resolve(file);
+    suite.emit('pre-require', global, file, self);
+    suite.emit('require', require(file), file, self);
+    suite.emit('post-require', global, file, self);
+    --pending || (fn && fn());
+  });
+};
+
+/**
+ * Enable growl support.
+ *
+ * @api private
+ */
+
+Mocha.prototype._growl = function(runner, reporter) {
+  var notify = require('growl');
+
+  runner.on('end', function(){
+    var stats = reporter.stats;
+    if (stats.failures) {
+      var msg = stats.failures + ' of ' + runner.total + ' tests failed';
+      notify(msg, { name: 'mocha', title: 'Failed', image: image('error') });
+    } else {
+      notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
+          name: 'mocha'
+        , title: 'Passed'
+        , image: image('ok')
+      });
+    }
+  });
+};
+
+/**
+ * Add regexp to grep, if `re` is a string it is escaped.
+ *
+ * @param {RegExp|String} re
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.grep = function(re){
+  this.options.grep = 'string' == typeof re
+    ? new RegExp(escapeRe(re))
+    : re;
+  return this;
+};
+
+/**
+ * Invert `.grep()` matches.
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.invert = function(){
+  this.options.invert = true;
+  return this;
+};
+
+/**
+ * Ignore global leaks.
+ *
+ * @param {Boolean} ignore
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.ignoreLeaks = function(ignore){
+  this.options.ignoreLeaks = !!ignore;
+  return this;
+};
+
+/**
+ * Enable global leak checking.
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.checkLeaks = function(){
+  this.options.ignoreLeaks = false;
+  return this;
+};
+
+/**
+ * Enable growl support.
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.growl = function(){
+  this.options.growl = true;
+  return this;
+};
+
+/**
+ * Ignore `globals` array or string.
+ *
+ * @param {Array|String} globals
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.globals = function(globals){
+  this.options.globals = (this.options.globals || []).concat(globals);
+  return this;
+};
+
+/**
+ * Emit color output.
+ *
+ * @param {Boolean} colors
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.useColors = function(colors){
+  this.options.useColors = arguments.length && colors != undefined
+    ? colors
+    : true;
+  return this;
+};
+
+/**
+ * Use inline diffs rather than +/-.
+ *
+ * @param {Boolean} inlineDiffs
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.useInlineDiffs = function(inlineDiffs) {
+  this.options.useInlineDiffs = arguments.length && inlineDiffs != undefined
+  ? inlineDiffs
+  : false;
+  return this;
+};
+
+/**
+ * Set the timeout in milliseconds.
+ *
+ * @param {Number} timeout
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.timeout = function(timeout){
+  this.suite.timeout(timeout);
+  return this;
+};
+
+/**
+ * Set slowness threshold in milliseconds.
+ *
+ * @param {Number} slow
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.slow = function(slow){
+  this.suite.slow(slow);
+  return this;
+};
+
+/**
+ * Enable timeouts.
+ *
+ * @param {Boolean} enabled
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.enableTimeouts = function(enabled) {
+  this.suite.enableTimeouts(arguments.length && enabled !== undefined
+    ? enabled
+    : true);
+  return this
+};
+
+/**
+ * Makes all tests async (accepting a callback)
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.asyncOnly = function(){
+  this.options.asyncOnly = true;
+  return this;
+};
+
+/**
+ * Disable syntax highlighting (in browser).
+ * @returns {Mocha}
+ * @api public
+ */
+Mocha.prototype.noHighlighting = function() {
+  this.options.noHighlighting = true;
+  return this;
+};
+
+/**
+ * Run tests and invoke `fn()` when complete.
+ *
+ * @param {Function} fn
+ * @return {Runner}
+ * @api public
+ */
+
+Mocha.prototype.run = function(fn){
+  if (this.files.length) this.loadFiles();
+  var suite = this.suite;
+  var options = this.options;
+  options.files = this.files;
+  var runner = new exports.Runner(suite);
+  var reporter = new this._reporter(runner, options);
+  runner.ignoreLeaks = false !== options.ignoreLeaks;
+  runner.asyncOnly = options.asyncOnly;
+  if (options.grep) runner.grep(options.grep, options.invert);
+  if (options.globals) runner.globals(options.globals);
+  if (options.growl) this._growl(runner, reporter);
+  exports.reporters.Base.useColors = options.useColors;
+  exports.reporters.Base.inlineDiffs = options.useInlineDiffs;
+  return runner.run(fn);
+};
+
+}); // module: mocha.js
+
+require.register("ms.js", function(module, exports, require){
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ *  - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} options
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options){
+  options = options || {};
+  if ('string' == typeof val) return parse(val);
+  return options['long'] ? longFormat(val) : shortFormat(val);
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+  var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
+  if (!match) return;
+  var n = parseFloat(match[1]);
+  var type = (match[2] || 'ms').toLowerCase();
+  switch (type) {
+    case 'years':
+    case 'year':
+    case 'y':
+      return n * y;
+    case 'days':
+    case 'day':
+    case 'd':
+      return n * d;
+    case 'hours':
+    case 'hour':
+    case 'h':
+      return n * h;
+    case 'minutes':
+    case 'minute':
+    case 'm':
+      return n * m;
+    case 'seconds':
+    case 'second':
+    case 's':
+      return n * s;
+    case 'ms':
+      return n;
+  }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function shortFormat(ms) {
+  if (ms >= d) return Math.round(ms / d) + 'd';
+  if (ms >= h) return Math.round(ms / h) + 'h';
+  if (ms >= m) return Math.round(ms / m) + 'm';
+  if (ms >= s) return Math.round(ms / s) + 's';
+  return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function longFormat(ms) {
+  return plural(ms, d, 'day')
+    || plural(ms, h, 'hour')
+    || plural(ms, m, 'minute')
+    || plural(ms, s, 'second')
+    || ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+  if (ms < n) return;
+  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
+  return Math.ceil(ms / n) + ' ' + name + 's';
+}
+
+}); // module: ms.js
+
+require.register("reporters/base.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var tty = require('browser/tty')
+  , diff = require('browser/diff')
+  , ms = require('../ms')
+  , utils = require('../utils');
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+  , setTimeout = global.setTimeout
+  , setInterval = global.setInterval
+  , clearTimeout = global.clearTimeout
+  , clearInterval = global.clearInterval;
+
+/**
+ * Check if both stdio streams are associated with a tty.
+ */
+
+var isatty = tty.isatty(1) && tty.isatty(2);
+
+/**
+ * Expose `Base`.
+ */
+
+exports = module.exports = Base;
+
+/**
+ * Enable coloring by default.
+ */
+
+exports.useColors = isatty || (process.env.MOCHA_COLORS !== undefined);
+
+/**
+ * Inline diffs instead of +/-
+ */
+
+exports.inlineDiffs = false;
+
+/**
+ * Default color map.
+ */
+
+exports.colors = {
+    'pass': 90
+  , 'fail': 31
+  , 'bright pass': 92
+  , 'bright fail': 91
+  , 'bright yellow': 93
+  , 'pending': 36
+  , 'suite': 0
+  , 'error title': 0
+  , 'error message': 31
+  , 'error stack': 90
+  , 'checkmark': 32
+  , 'fast': 90
+  , 'medium': 33
+  , 'slow': 31
+  , 'green': 32
+  , 'light': 90
+  , 'diff gutter': 90
+  , 'diff added': 42
+  , 'diff removed': 41
+};
+
+/**
+ * Default symbol map.
+ */
+
+exports.symbols = {
+  ok: '✓',
+  err: '✖',
+  dot: '․'
+};
+
+// With node.js on Windows: use symbols available in terminal default fonts
+if ('win32' == process.platform) {
+  exports.symbols.ok = '\u221A';
+  exports.symbols.err = '\u00D7';
+  exports.symbols.dot = '.';
+}
+
+/**
+ * Color `str` with the given `type`,
+ * allowing colors to be disabled,
+ * as well as user-defined color
+ * schemes.
+ *
+ * @param {String} type
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+var color = exports.color = function(type, str) {
+  if (!exports.useColors) return str;
+  return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
+};
+
+/**
+ * Expose term window size, with some
+ * defaults for when stderr is not a tty.
+ */
+
+exports.window = {
+  width: isatty
+    ? process.stdout.getWindowSize
+      ? process.stdout.getWindowSize(1)[0]
+      : tty.getWindowSize()[1]
+    : 75
+};
+
+/**
+ * Expose some basic cursor interactions
+ * that are common among reporters.
+ */
+
+exports.cursor = {
+  hide: function(){
+    isatty && process.stdout.write('\u001b[?25l');
+  },
+
+  show: function(){
+    isatty && process.stdout.write('\u001b[?25h');
+  },
+
+  deleteLine: function(){
+    isatty && process.stdout.write('\u001b[2K');
+  },
+
+  beginningOfLine: function(){
+    isatty && process.stdout.write('\u001b[0G');
+  },
+
+  CR: function(){
+    if (isatty) {
+      exports.cursor.deleteLine();
+      exports.cursor.beginningOfLine();
+    } else {
+      process.stdout.write('\r');
+    }
+  }
+};
+
+/**
+ * Outut the given `failures` as a list.
+ *
+ * @param {Array} failures
+ * @api public
+ */
+
+exports.list = function(failures){
+  console.error();
+  failures.forEach(function(test, i){
+    // format
+    var fmt = color('error title', '  %s) %s:\n')
+      + color('error message', '     %s')
+      + color('error stack', '\n%s\n');
+
+    // msg
+    var err = test.err
+      , message = err.message || ''
+      , stack = err.stack || message
+      , index = stack.indexOf(message) + message.length
+      , msg = stack.slice(0, index)
+      , actual = err.actual
+      , expected = err.expected
+      , escape = true;
+
+    // uncaught
+    if (err.uncaught) {
+      msg = 'Uncaught ' + msg;
+    }
+
+    // explicitly show diff
+    if (err.showDiff && sameType(actual, expected)) {
+      escape = false;
+      err.actual = actual = utils.stringify(actual);
+      err.expected = expected = utils.stringify(expected);
+    }
+
+    // actual / expected diff
+    if (err.showDiff && 'string' == typeof actual && 'string' == typeof expected) {
+      fmt = color('error title', '  %s) %s:\n%s') + color('error stack', '\n%s\n');
+      var match = message.match(/^([^:]+): expected/);
+      msg = '\n      ' + color('error message', match ? match[1] : msg);
+
+      if (exports.inlineDiffs) {
+        msg += inlineDiff(err, escape);
+      } else {
+        msg += unifiedDiff(err, escape);
+      }
+    }
+
+    // indent stack trace without msg
+    stack = stack.slice(index ? index + 1 : index)
+      .replace(/^/gm, '  ');
+
+    console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
+  });
+};
+
+/**
+ * Initialize a new `Base` reporter.
+ *
+ * All other reporters generally
+ * inherit from this reporter, providing
+ * stats such as test duration, number
+ * of tests passed / failed etc.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Base(runner) {
+  var self = this
+    , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }
+    , failures = this.failures = [];
+
+  if (!runner) return;
+  this.runner = runner;
+
+  runner.stats = stats;
+
+  runner.on('start', function(){
+    stats.start = new Date;
+  });
+
+  runner.on('suite', function(suite){
+    stats.suites = stats.suites || 0;
+    suite.root || stats.suites++;
+  });
+
+  runner.on('test end', function(test){
+    stats.tests = stats.tests || 0;
+    stats.tests++;
+  });
+
+  runner.on('pass', function(test){
+    stats.passes = stats.passes || 0;
+
+    var medium = test.slow() / 2;
+    test.speed = test.duration > test.slow()
+      ? 'slow'
+      : test.duration > medium
+        ? 'medium'
+        : 'fast';
+
+    stats.passes++;
+  });
+
+  runner.on('fail', function(test, err){
+    stats.failures = stats.failures || 0;
+    stats.failures++;
+    test.err = err;
+    failures.push(test);
+  });
+
+  runner.on('end', function(){
+    stats.end = new Date;
+    stats.duration = new Date - stats.start;
+  });
+
+  runner.on('pending', function(){
+    stats.pending++;
+  });
+}
+
+/**
+ * Output common epilogue used by many of
+ * the bundled reporters.
+ *
+ * @api public
+ */
+
+Base.prototype.epilogue = function(){
+  var stats = this.stats;
+  var tests;
+  var fmt;
+
+  console.log();
+
+  // passes
+  fmt = color('bright pass', ' ')
+    + color('green', ' %d passing')
+    + color('light', ' (%s)');
+
+  console.log(fmt,
+    stats.passes || 0,
+    ms(stats.duration));
+
+  // pending
+  if (stats.pending) {
+    fmt = color('pending', ' ')
+      + color('pending', ' %d pending');
+
+    console.log(fmt, stats.pending);
+  }
+
+  // failures
+  if (stats.failures) {
+    fmt = color('fail', '  %d failing');
+
+    console.error(fmt,
+      stats.failures);
+
+    Base.list(this.failures);
+    console.error();
+  }
+
+  console.log();
+};
+
+/**
+ * Pad the given `str` to `len`.
+ *
+ * @param {String} str
+ * @param {String} len
+ * @return {String}
+ * @api private
+ */
+
+function pad(str, len) {
+  str = String(str);
+  return Array(len - str.length + 1).join(' ') + str;
+}
+
+
+/**
+ * Returns an inline diff between 2 strings with coloured ANSI output
+ *
+ * @param {Error} Error with actual/expected
+ * @return {String} Diff
+ * @api private
+ */
+
+function inlineDiff(err, escape) {
+  var msg = errorDiff(err, 'WordsWithSpace', escape);
+
+  // linenos
+  var lines = msg.split('\n');
+  if (lines.length > 4) {
+    var width = String(lines.length).length;
+    msg = lines.map(function(str, i){
+      return pad(++i, width) + ' |' + ' ' + str;
+    }).join('\n');
+  }
+
+  // legend
+  msg = '\n'
+    + color('diff removed', 'actual')
+    + ' '
+    + color('diff added', 'expected')
+    + '\n\n'
+    + msg
+    + '\n';
+
+  // indent
+  msg = msg.replace(/^/gm, '      ');
+  return msg;
+}
+
+/**
+ * Returns a unified diff between 2 strings
+ *
+ * @param {Error} Error with actual/expected
+ * @return {String} Diff
+ * @api private
+ */
+
+function unifiedDiff(err, escape) {
+  var indent = '      ';
+  function cleanUp(line) {
+    if (escape) {
+      line = escapeInvisibles(line);
+    }
+    if (line[0] === '+') return indent + colorLines('diff added', line);
+    if (line[0] === '-') return indent + colorLines('diff removed', line);
+    if (line.match(/\@\@/)) return null;
+    if (line.match(/\\ No newline/)) return null;
+    else return indent + line;
+  }
+  function notBlank(line) {
+    return line != null;
+  }
+  msg = diff.createPatch('string', err.actual, err.expected);
+  var lines = msg.split('\n').splice(4);
+  return '\n      '
+         + colorLines('diff added',   '+ expected') + ' '
+         + colorLines('diff removed', '- actual')
+         + '\n\n'
+         + lines.map(cleanUp).filter(notBlank).join('\n');
+}
+
+/**
+ * Return a character diff for `err`.
+ *
+ * @param {Error} err
+ * @return {String}
+ * @api private
+ */
+
+function errorDiff(err, type, escape) {
+  var actual   = escape ? escapeInvisibles(err.actual)   : err.actual;
+  var expected = escape ? escapeInvisibles(err.expected) : err.expected;
+  return diff['diff' + type](actual, expected).map(function(str){
+    if (str.added) return colorLines('diff added', str.value);
+    if (str.removed) return colorLines('diff removed', str.value);
+    return str.value;
+  }).join('');
+}
+
+/**
+ * Returns a string with all invisible characters in plain text
+ *
+ * @param {String} line
+ * @return {String}
+ * @api private
+ */
+function escapeInvisibles(line) {
+    return line.replace(/\t/g, '<tab>')
+               .replace(/\r/g, '<CR>')
+               .replace(/\n/g, '<LF>\n');
+}
+
+/**
+ * Color lines for `str`, using the color `name`.
+ *
+ * @param {String} name
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+function colorLines(name, str) {
+  return str.split('\n').map(function(str){
+    return color(name, str);
+  }).join('\n');
+}
+
+/**
+ * Check that a / b have the same type.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @return {Boolean}
+ * @api private
+ */
+
+function sameType(a, b) {
+  a = Object.prototype.toString.call(a);
+  b = Object.prototype.toString.call(b);
+  return a == b;
+}
+
+}); // module: reporters/base.js
+
+require.register("reporters/doc.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , utils = require('../utils');
+
+/**
+ * Expose `Doc`.
+ */
+
+exports = module.exports = Doc;
+
+/**
+ * Initialize a new `Doc` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Doc(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , total = runner.total
+    , indents = 2;
+
+  function indent() {
+    return Array(indents).join('  ');
+  }
+
+  runner.on('suite', function(suite){
+    if (suite.root) return;
+    ++indents;
+    console.log('%s<section class="suite">', indent());
+    ++indents;
+    console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title));
+    console.log('%s<dl>', indent());
+  });
+
+  runner.on('suite end', function(suite){
+    if (suite.root) return;
+    console.log('%s</dl>', indent());
+    --indents;
+    console.log('%s</section>', indent());
+    --indents;
+  });
+
+  runner.on('pass', function(test){
+    console.log('%s  <dt>%s</dt>', indent(), utils.escape(test.title));
+    var code = utils.escape(utils.clean(test.fn.toString()));
+    console.log('%s  <dd><pre><code>%s</code></pre></dd>', indent(), code);
+  });
+
+  runner.on('fail', function(test, err){
+    console.log('%s  <dt class="error">%s</dt>', indent(), utils.escape(test.title));
+    var code = utils.escape(utils.clean(test.fn.toString()));
+    console.log('%s  <dd class="error"><pre><code>%s</code></pre></dd>', indent(), code);
+    console.log('%s  <dd class="error">%s</dd>', indent(), utils.escape(err));
+  });
+}
+
+}); // module: reporters/doc.js
+
+require.register("reporters/dot.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , color = Base.color;
+
+/**
+ * Expose `Dot`.
+ */
+
+exports = module.exports = Dot;
+
+/**
+ * Initialize a new `Dot` matrix test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Dot(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , width = Base.window.width * .75 | 0
+    , n = -1;
+
+  runner.on('start', function(){
+    process.stdout.write('\n  ');
+  });
+
+  runner.on('pending', function(test){
+    if (++n % width == 0) process.stdout.write('\n  ');
+    process.stdout.write(color('pending', Base.symbols.dot));
+  });
+
+  runner.on('pass', function(test){
+    if (++n % width == 0) process.stdout.write('\n  ');
+    if ('slow' == test.speed) {
+      process.stdout.write(color('bright yellow', Base.symbols.dot));
+    } else {
+      process.stdout.write(color(test.speed, Base.symbols.dot));
+    }
+  });
+
+  runner.on('fail', function(test, err){
+    if (++n % width == 0) process.stdout.write('\n  ');
+    process.stdout.write(color('fail', Base.symbols.dot));
+  });
+
+  runner.on('end', function(){
+    console.log();
+    self.epilogue();
+  });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+Dot.prototype = new F;
+Dot.prototype.constructor = Dot;
+
+
+}); // module: reporters/dot.js
+
+require.register("reporters/html-cov.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var JSONCov = require('./json-cov')
+  , fs = require('browser/fs');
+
+/**
+ * Expose `HTMLCov`.
+ */
+
+exports = module.exports = HTMLCov;
+
+/**
+ * Initialize a new `JsCoverage` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function HTMLCov(runner) {
+  var jade = require('jade')
+    , file = __dirname + '/templates/coverage.jade'
+    , str = fs.readFileSync(file, 'utf8')
+    , fn = jade.compile(str, { filename: file })
+    , self = this;
+
+  JSONCov.call(this, runner, false);
+
+  runner.on('end', function(){
+    process.stdout.write(fn({
+        cov: self.cov
+      , coverageClass: coverageClass
+    }));
+  });
+}
+
+/**
+ * Return coverage class for `n`.
+ *
+ * @return {String}
+ * @api private
+ */
+
+function coverageClass(n) {
+  if (n >= 75) return 'high';
+  if (n >= 50) return 'medium';
+  if (n >= 25) return 'low';
+  return 'terrible';
+}
+
+}); // module: reporters/html-cov.js
+
+require.register("reporters/html.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , utils = require('../utils')
+  , Progress = require('../browser/progress')
+  , escape = utils.escape;
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+  , setTimeout = global.setTimeout
+  , setInterval = global.setInterval
+  , clearTimeout = global.clearTimeout
+  , clearInterval = global.clearInterval;
+
+/**
+ * Expose `HTML`.
+ */
+
+exports = module.exports = HTML;
+
+/**
+ * Stats template.
+ */
+
+var statsTemplate = '<ul id="mocha-stats">'
+  + '<li class="progress"><canvas width="40" height="40"></canvas></li>'
+  + '<li class="passes"><a href="#">passes:</a> <em>0</em></li>'
+  + '<li class="failures"><a href="#">failures:</a> <em>0</em></li>'
+  + '<li class="duration">duration: <em>0</em>s</li>'
+  + '</ul>';
+
+/**
+ * Initialize a new `HTML` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function HTML(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , total = runner.total
+    , stat = fragment(statsTemplate)
+    , items = stat.getElementsByTagName('li')
+    , passes = items[1].getElementsByTagName('em')[0]
+    , passesLink = items[1].getElementsByTagName('a')[0]
+    , failures = items[2].getElementsByTagName('em')[0]
+    , failuresLink = items[2].getElementsByTagName('a')[0]
+    , duration = items[3].getElementsByTagName('em')[0]
+    , canvas = stat.getElementsByTagName('canvas')[0]
+    , report = fragment('<ul id="mocha-report"></ul>')
+    , stack = [report]
+    , progress
+    , ctx
+    , root = document.getElementById('mocha');
+
+  if (canvas.getContext) {
+    var ratio = window.devicePixelRatio || 1;
+    canvas.style.width = canvas.width;
+    canvas.style.height = canvas.height;
+    canvas.width *= ratio;
+    canvas.height *= ratio;
+    ctx = canvas.getContext('2d');
+    ctx.scale(ratio, ratio);
+    progress = new Progress;
+  }
+
+  if (!root) return error('#mocha div missing, add it to your document');
+
+  // pass toggle
+  on(passesLink, 'click', function(){
+    unhide();
+    var name = /pass/.test(report.className) ? '' : ' pass';
+    report.className = report.className.replace(/fail|pass/g, '') + name;
+    if (report.className.trim()) hideSuitesWithout('test pass');
+  });
+
+  // failure toggle
+  on(failuresLink, 'click', function(){
+    unhide();
+    var name = /fail/.test(report.className) ? '' : ' fail';
+    report.className = report.className.replace(/fail|pass/g, '') + name;
+    if (report.className.trim()) hideSuitesWithout('test fail');
+  });
+
+  root.appendChild(stat);
+  root.appendChild(report);
+
+  if (progress) progress.size(40);
+
+  runner.on('suite', function(suite){
+    if (suite.root) return;
+
+    // suite
+    var url = self.suiteURL(suite);
+    var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, escape(suite.title));
+
+    // container
+    stack[0].appendChild(el);
+    stack.unshift(document.createElement('ul'));
+    el.appendChild(stack[0]);
+  });
+
+  runner.on('suite end', function(suite){
+    if (suite.root) return;
+    stack.shift();
+  });
+
+  runner.on('fail', function(test, err){
+    if ('hook' == test.type) runner.emit('test end', test);
+  });
+
+  runner.on('test end', function(test){
+    // TODO: add to stats
+    var percent = stats.tests / this.total * 100 | 0;
+    if (progress) progress.update(percent).draw(ctx);
+
+    // update stats
+    var ms = new Date - stats.start;
+    text(passes, stats.passes);
+    text(failures, stats.failures);
+    text(duration, (ms / 1000).toFixed(2));
+
+    // test
+    if ('passed' == test.state) {
+      var url = self.testURL(test);
+      var el = fragment('<li class="test pass %e"><h2>%e<span class="duration">%ems</span> <a href="%s" class="replay">‣</a></h2></li>', test.speed, test.title, test.duration, url);
+    } else if (test.pending) {
+      var el = fragment('<li class="test pass pending"><h2>%e</h2></li>', test.title);
+    } else {
+      var el = fragment('<li class="test fail"><h2>%e <a href="?grep=%e" class="replay">‣</a></h2></li>', test.title, encodeURIComponent(test.fullTitle()));
+      var str = test.err.stack || test.err.toString();
+
+      // FF / Opera do not add the message
+      if (!~str.indexOf(test.err.message)) {
+        str = test.err.message + '\n' + str;
+      }
+
+      // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
+      // check for the result of the stringifying.
+      if ('[object Error]' == str) str = test.err.message;
+
+      // Safari doesn't give you a stack. Let's at least provide a source line.
+      if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
+        str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
+      }
+
+      el.appendChild(fragment('<pre class="error">%e</pre>', str));
+    }
+
+    // toggle code
+    // TODO: defer
+    if (!test.pending) {
+      var h2 = el.getElementsByTagName('h2')[0];
+
+      on(h2, 'click', function(){
+        pre.style.display = 'none' == pre.style.display
+          ? 'block'
+          : 'none';
+      });
+
+      var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString()));
+      el.appendChild(pre);
+      pre.style.display = 'none';
+    }
+
+    // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.
+    if (stack[0]) stack[0].appendChild(el);
+  });
+}
+
+/**
+ * Makes a URL, preserving querystring ("search") parameters.
+ * @param {string} s
+ * @returns {string} your new URL
+ */
+var makeUrl = function makeUrl(s) {
+  var search = window.location.search;
+  return (search ? search + '&' : '?' ) + 'grep=' + encodeURIComponent(s);
+};
+
+/**
+ * Provide suite URL
+ *
+ * @param {Object} [suite]
+ */
+HTML.prototype.suiteURL = function(suite){
+  return makeUrl(suite.fullTitle());
+};
+
+/**
+ * Provide test URL
+ *
+ * @param {Object} [test]
+ */
+
+HTML.prototype.testURL = function(test){
+  return makeUrl(test.fullTitle());
+};
+
+/**
+ * Display error `msg`.
+ */
+
+function error(msg) {
+  document.body.appendChild(fragment('<div id="mocha-error">%s</div>', msg));
+}
+
+/**
+ * Return a DOM fragment from `html`.
+ */
+
+function fragment(html) {
+  var args = arguments
+    , div = document.createElement('div')
+    , i = 1;
+
+  div.innerHTML = html.replace(/%([se])/g, function(_, type){
+    switch (type) {
+      case 's': return String(args[i++]);
+      case 'e': return escape(args[i++]);
+    }
+  });
+
+  return div.firstChild;
+}
+
+/**
+ * Check for suites that do not have elements
+ * with `classname`, and hide them.
+ */
+
+function hideSuitesWithout(classname) {
+  var suites = document.getElementsByClassName('suite');
+  for (var i = 0; i < suites.length; i++) {
+    var els = suites[i].getElementsByClassName(classname);
+    if (0 == els.length) suites[i].className += ' hidden';
+  }
+}
+
+/**
+ * Unhide .hidden suites.
+ */
+
+function unhide() {
+  var els = document.getElementsByClassName('suite hidden');
+  for (var i = 0; i < els.length; ++i) {
+    els[i].className = els[i].className.replace('suite hidden', 'suite');
+  }
+}
+
+/**
+ * Set `el` text to `str`.
+ */
+
+function text(el, str) {
+  if (el.textContent) {
+    el.textContent = str;
+  } else {
+    el.innerText = str;
+  }
+}
+
+/**
+ * Listen on `event` with callback `fn`.
+ */
+
+function on(el, event, fn) {
+  if (el.addEventListener) {
+    el.addEventListener(event, fn, false);
+  } else {
+    el.attachEvent('on' + event, fn);
+  }
+}
+
+}); // module: reporters/html.js
+
+require.register("reporters/index.js", function(module, exports, require){
+exports.Base = require('./base');
+exports.Dot = require('./dot');
+exports.Doc = require('./doc');
+exports.TAP = require('./tap');
+exports.JSON = require('./json');
+exports.HTML = require('./html');
+exports.List = require('./list');
+exports.Min = require('./min');
+exports.Spec = require('./spec');
+exports.Nyan = require('./nyan');
+exports.XUnit = require('./xunit');
+exports.Markdown = require('./markdown');
+exports.Progress = require('./progress');
+exports.Landing = require('./landing');
+exports.JSONCov = require('./json-cov');
+exports.HTMLCov = require('./html-cov');
+exports.JSONStream = require('./json-stream');
+
+}); // module: reporters/index.js
+
+require.register("reporters/json-cov.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `JSONCov`.
+ */
+
+exports = module.exports = JSONCov;
+
+/**
+ * Initialize a new `JsCoverage` reporter.
+ *
+ * @param {Runner} runner
+ * @param {Boolean} output
+ * @api public
+ */
+
+function JSONCov(runner, output) {
+  var self = this
+    , output = 1 == arguments.length ? true : output;
+
+  Base.call(this, runner);
+
+  var tests = []
+    , failures = []
+    , passes = [];
+
+  runner.on('test end', function(test){
+    tests.push(test);
+  });
+
+  runner.on('pass', function(test){
+    passes.push(test);
+  });
+
+  runner.on('fail', function(test){
+    failures.push(test);
+  });
+
+  runner.on('end', function(){
+    var cov = global._$jscoverage || {};
+    var result = self.cov = map(cov);
+    result.stats = self.stats;
+    result.tests = tests.map(clean);
+    result.failures = failures.map(clean);
+    result.passes = passes.map(clean);
+    if (!output) return;
+    process.stdout.write(JSON.stringify(result, null, 2 ));
+  });
+}
+
+/**
+ * Map jscoverage data to a JSON structure
+ * suitable for reporting.
+ *
+ * @param {Object} cov
+ * @return {Object}
+ * @api private
+ */
+
+function map(cov) {
+  var ret = {
+      instrumentation: 'node-jscoverage'
+    , sloc: 0
+    , hits: 0
+    , misses: 0
+    , coverage: 0
+    , files: []
+  };
+
+  for (var filename in cov) {
+    var data = coverage(filename, cov[filename]);
+    ret.files.push(data);
+    ret.hits += data.hits;
+    ret.misses += data.misses;
+    ret.sloc += data.sloc;
+  }
+
+  ret.files.sort(function(a, b) {
+    return a.filename.localeCompare(b.filename);
+  });
+
+  if (ret.sloc > 0) {
+    ret.coverage = (ret.hits / ret.sloc) * 100;
+  }
+
+  return ret;
+}
+
+/**
+ * Map jscoverage data for a single source file
+ * to a JSON structure suitable for reporting.
+ *
+ * @param {String} filename name of the source file
+ * @param {Object} data jscoverage coverage data
+ * @return {Object}
+ * @api private
+ */
+
+function coverage(filename, data) {
+  var ret = {
+    filename: filename,
+    coverage: 0,
+    hits: 0,
+    misses: 0,
+    sloc: 0,
+    source: {}
+  };
+
+  data.source.forEach(function(line, num){
+    num++;
+
+    if (data[num] === 0) {
+      ret.misses++;
+      ret.sloc++;
+    } else if (data[num] !== undefined) {
+      ret.hits++;
+      ret.sloc++;
+    }
+
+    ret.source[num] = {
+        source: line
+      , coverage: data[num] === undefined
+        ? ''
+        : data[num]
+    };
+  });
+
+  ret.coverage = ret.hits / ret.sloc * 100;
+
+  return ret;
+}
+
+/**
+ * Return a plain-object representation of `test`
+ * free of cyclic properties etc.
+ *
+ * @param {Object} test
+ * @return {Object}
+ * @api private
+ */
+
+function clean(test) {
+  return {
+      title: test.title
+    , fullTitle: test.fullTitle()
+    , duration: test.duration
+  }
+}
+
+}); // module: reporters/json-cov.js
+
+require.register("reporters/json-stream.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , color = Base.color;
+
+/**
+ * Expose `List`.
+ */
+
+exports = module.exports = List;
+
+/**
+ * Initialize a new `List` test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function List(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , total = runner.total;
+
+  runner.on('start', function(){
+    console.log(JSON.stringify(['start', { total: total }]));
+  });
+
+  runner.on('pass', function(test){
+    console.log(JSON.stringify(['pass', clean(test)]));
+  });
+
+  runner.on('fail', function(test, err){
+    test = clean(test);
+    test.err = err.message;
+    console.log(JSON.stringify(['fail', test]));
+  });
+
+  runner.on('end', function(){
+    process.stdout.write(JSON.stringify(['end', self.stats]));
+  });
+}
+
+/**
+ * Return a plain-object representation of `test`
+ * free of cyclic properties etc.
+ *
+ * @param {Object} test
+ * @return {Object}
+ * @api private
+ */
+
+function clean(test) {
+  return {
+      title: test.title
+    , fullTitle: test.fullTitle()
+    , duration: test.duration
+  }
+}
+
+}); // module: reporters/json-stream.js
+
+require.register("reporters/json.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `JSON`.
+ */
+
+exports = module.exports = JSONReporter;
+
+/**
+ * Initialize a new `JSON` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function JSONReporter(runner) {
+  var self = this;
+  Base.call(this, runner);
+
+  var tests = []
+    , pending = []
+    , failures = []
+    , passes = [];
+
+  runner.on('test end', function(test){
+    tests.push(test);
+  });
+
+  runner.on('pass', function(test){
+    passes.push(test);
+  });
+
+  runner.on('fail', function(test){
+    failures.push(test);
+  });
+
+  runner.on('pending', function(test){
+    pending.push(test);
+  });
+
+  runner.on('end', function(){
+    var obj = {
+      stats: self.stats,
+      tests: tests.map(clean),
+      pending: pending.map(clean),
+      failures: failures.map(clean),
+      passes: passes.map(clean)
+    };
+
+    runner.testResults = obj;
+
+    process.stdout.write(JSON.stringify(obj, null, 2));
+  });
+}
+
+/**
+ * Return a plain-object representation of `test`
+ * free of cyclic properties etc.
+ *
+ * @param {Object} test
+ * @return {Object}
+ * @api private
+ */
+
+function clean(test) {
+  return {
+    title: test.title,
+    fullTitle: test.fullTitle(),
+    duration: test.duration,
+    err: errorJSON(test.err || {})
+  }
+}
+
+/**
+ * Transform `error` into a JSON object.
+ * @param {Error} err
+ * @return {Object}
+ */
+
+function errorJSON(err) {
+  var res = {};
+  Object.getOwnPropertyNames(err).forEach(function(key) {
+    res[key] = err[key];
+  }, err);
+  return res;
+}
+
+}); // module: reporters/json.js
+
+require.register("reporters/landing.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `Landing`.
+ */
+
+exports = module.exports = Landing;
+
+/**
+ * Airplane color.
+ */
+
+Base.colors.plane = 0;
+
+/**
+ * Airplane crash color.
+ */
+
+Base.colors['plane crash'] = 31;
+
+/**
+ * Runway color.
+ */
+
+Base.colors.runway = 90;
+
+/**
+ * Initialize a new `Landing` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Landing(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , width = Base.window.width * .75 | 0
+    , total = runner.total
+    , stream = process.stdout
+    , plane = color('plane', '✈')
+    , crashed = -1
+    , n = 0;
+
+  function runway() {
+    var buf = Array(width).join('-');
+    return '  ' + color('runway', buf);
+  }
+
+  runner.on('start', function(){
+    stream.write('\n\n\n  ');
+    cursor.hide();
+  });
+
+  runner.on('test end', function(test){
+    // check if the plane crashed
+    var col = -1 == crashed
+      ? width * ++n / total | 0
+      : crashed;
+
+    // show the crash
+    if ('failed' == test.state) {
+      plane = color('plane crash', '✈');
+      crashed = col;
+    }
+
+    // render landing strip
+    stream.write('\u001b['+(width+1)+'D\u001b[2A');
+    stream.write(runway());
+    stream.write('\n  ');
+    stream.write(color('runway', Array(col).join('⋅')));
+    stream.write(plane)
+    stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
+    stream.write(runway());
+    stream.write('\u001b[0m');
+  });
+
+  runner.on('end', function(){
+    cursor.show();
+    console.log();
+    self.epilogue();
+  });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+Landing.prototype = new F;
+Landing.prototype.constructor = Landing;
+
+
+}); // module: reporters/landing.js
+
+require.register("reporters/list.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `List`.
+ */
+
+exports = module.exports = List;
+
+/**
+ * Initialize a new `List` test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function List(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , n = 0;
+
+  runner.on('start', function(){
+    console.log();
+  });
+
+  runner.on('test', function(test){
+    process.stdout.write(color('pass', '    ' + test.fullTitle() + ': '));
+  });
+
+  runner.on('pending', function(test){
+    var fmt = color('checkmark', '  -')
+      + color('pending', ' %s');
+    console.log(fmt, test.fullTitle());
+  });
+
+  runner.on('pass', function(test){
+    var fmt = color('checkmark', '  '+Base.symbols.dot)
+      + color('pass', ' %s: ')
+      + color(test.speed, '%dms');
+    cursor.CR();
+    console.log(fmt, test.fullTitle(), test.duration);
+  });
+
+  runner.on('fail', function(test, err){
+    cursor.CR();
+    console.log(color('fail', '  %d) %s'), ++n, test.fullTitle());
+  });
+
+  runner.on('end', self.epilogue.bind(self));
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+List.prototype = new F;
+List.prototype.constructor = List;
+
+
+}); // module: reporters/list.js
+
+require.register("reporters/markdown.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , utils = require('../utils');
+
+/**
+ * Expose `Markdown`.
+ */
+
+exports = module.exports = Markdown;
+
+/**
+ * Initialize a new `Markdown` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Markdown(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , level = 0
+    , buf = '';
+
+  function title(str) {
+    return Array(level).join('#') + ' ' + str;
+  }
+
+  function indent() {
+    return Array(level).join('  ');
+  }
+
+  function mapTOC(suite, obj) {
+    var ret = obj;
+    obj = obj[suite.title] = obj[suite.title] || { suite: suite };
+    suite.suites.forEach(function(suite){
+      mapTOC(suite, obj);
+    });
+    return ret;
+  }
+
+  function stringifyTOC(obj, level) {
+    ++level;
+    var buf = '';
+    var link;
+    for (var key in obj) {
+      if ('suite' == key) continue;
+      if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
+      if (key) buf += Array(level).join('  ') + link;
+      buf += stringifyTOC(obj[key], level);
+    }
+    --level;
+    return buf;
+  }
+
+  function generateTOC(suite) {
+    var obj = mapTOC(suite, {});
+    return stringifyTOC(obj, 0);
+  }
+
+  generateTOC(runner.suite);
+
+  runner.on('suite', function(suite){
+    ++level;
+    var slug = utils.slug(suite.fullTitle());
+    buf += '<a name="' + slug + '"></a>' + '\n';
+    buf += title(suite.title) + '\n';
+  });
+
+  runner.on('suite end', function(suite){
+    --level;
+  });
+
+  runner.on('pass', function(test){
+    var code = utils.clean(test.fn.toString());
+    buf += test.title + '.\n';
+    buf += '\n```js\n';
+    buf += code + '\n';
+    buf += '```\n\n';
+  });
+
+  runner.on('end', function(){
+    process.stdout.write('# TOC\n');
+    process.stdout.write(generateTOC(runner.suite));
+    process.stdout.write(buf);
+  });
+}
+
+}); // module: reporters/markdown.js
+
+require.register("reporters/min.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `Min`.
+ */
+
+exports = module.exports = Min;
+
+/**
+ * Initialize a new `Min` minimal test reporter (best used with --watch).
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Min(runner) {
+  Base.call(this, runner);
+
+  runner.on('start', function(){
+    // clear screen
+    process.stdout.write('\u001b[2J');
+    // set cursor position
+    process.stdout.write('\u001b[1;3H');
+  });
+
+  runner.on('end', this.epilogue.bind(this));
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+Min.prototype = new F;
+Min.prototype.constructor = Min;
+
+
+}); // module: reporters/min.js
+
+require.register("reporters/nyan.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , color = Base.color;
+
+/**
+ * Expose `Dot`.
+ */
+
+exports = module.exports = NyanCat;
+
+/**
+ * Initialize a new `Dot` matrix test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function NyanCat(runner) {
+  Base.call(this, runner);
+  var self = this
+    , stats = this.stats
+    , width = Base.window.width * .75 | 0
+    , rainbowColors = this.rainbowColors = self.generateColors()
+    , colorIndex = this.colorIndex = 0
+    , numerOfLines = this.numberOfLines = 4
+    , trajectories = this.trajectories = [[], [], [], []]
+    , nyanCatWidth = this.nyanCatWidth = 11
+    , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth)
+    , scoreboardWidth = this.scoreboardWidth = 5
+    , tick = this.tick = 0
+    , n = 0;
+
+  runner.on('start', function(){
+    Base.cursor.hide();
+    self.draw();
+  });
+
+  runner.on('pending', function(test){
+    self.draw();
+  });
+
+  runner.on('pass', function(test){
+    self.draw();
+  });
+
+  runner.on('fail', function(test, err){
+    self.draw();
+  });
+
+  runner.on('end', function(){
+    Base.cursor.show();
+    for (var i = 0; i < self.numberOfLines; i++) write('\n');
+    self.epilogue();
+  });
+}
+
+/**
+ * Draw the nyan cat
+ *
+ * @api private
+ */
+
+NyanCat.prototype.draw = function(){
+  this.appendRainbow();
+  this.drawScoreboard();
+  this.drawRainbow();
+  this.drawNyanCat();
+  this.tick = !this.tick;
+};
+
+/**
+ * Draw the "scoreboard" showing the number
+ * of passes, failures and pending tests.
+ *
+ * @api private
+ */
+
+NyanCat.prototype.drawScoreboard = function(){
+  var stats = this.stats;
+  var colors = Base.colors;
+
+  function draw(color, n) {
+    write(' ');
+    write('\u001b[' + color + 'm' + n + '\u001b[0m');
+    write('\n');
+  }
+
+  draw(colors.green, stats.passes);
+  draw(colors.fail, stats.failures);
+  draw(colors.pending, stats.pending);
+  write('\n');
+
+  this.cursorUp(this.numberOfLines);
+};
+
+/**
+ * Append the rainbow.
+ *
+ * @api private
+ */
+
+NyanCat.prototype.appendRainbow = function(){
+  var segment = this.tick ? '_' : '-';
+  var rainbowified = this.rainbowify(segment);
+
+  for (var index = 0; index < this.numberOfLines; index++) {
+    var trajectory = this.trajectories[index];
+    if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift();
+    trajectory.push(rainbowified);
+  }
+};
+
+/**
+ * Draw the rainbow.
+ *
+ * @api private
+ */
+
+NyanCat.prototype.drawRainbow = function(){
+  var self = this;
+
+  this.trajectories.forEach(function(line, index) {
+    write('\u001b[' + self.scoreboardWidth + 'C');
+    write(line.join(''));
+    write('\n');
+  });
+
+  this.cursorUp(this.numberOfLines);
+};
+
+/**
+ * Draw the nyan cat
+ *
+ * @api private
+ */
+
+NyanCat.prototype.drawNyanCat = function() {
+  var self = this;
+  var startWidth = this.scoreboardWidth + this.trajectories[0].length;
+  var color = '\u001b[' + startWidth + 'C';
+  var padding = '';
+
+  write(color);
+  write('_,------,');
+  write('\n');
+
+  write(color);
+  padding = self.tick ? '  ' : '   ';
+  write('_|' + padding + '/\\_/\\ ');
+  write('\n');
+
+  write(color);
+  padding = self.tick ? '_' : '__';
+  var tail = self.tick ? '~' : '^';
+  var face;
+  write(tail + '|' + padding + this.face() + ' ');
+  write('\n');
+
+  write(color);
+  padding = self.tick ? ' ' : '  ';
+  write(padding + '""  "" ');
+  write('\n');
+
+  this.cursorUp(this.numberOfLines);
+};
+
+/**
+ * Draw nyan cat face.
+ *
+ * @return {String}
+ * @api private
+ */
+
+NyanCat.prototype.face = function() {
+  var stats = this.stats;
+  if (stats.failures) {
+    return '( x .x)';
+  } else if (stats.pending) {
+    return '( o .o)';
+  } else if(stats.passes) {
+    return '( ^ .^)';
+  } else {
+    return '( - .-)';
+  }
+};
+
+/**
+ * Move cursor up `n`.
+ *
+ * @param {Number} n
+ * @api private
+ */
+
+NyanCat.prototype.cursorUp = function(n) {
+  write('\u001b[' + n + 'A');
+};
+
+/**
+ * Move cursor down `n`.
+ *
+ * @param {Number} n
+ * @api private
+ */
+
+NyanCat.prototype.cursorDown = function(n) {
+  write('\u001b[' + n + 'B');
+};
+
+/**
+ * Generate rainbow colors.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+NyanCat.prototype.generateColors = function(){
+  var colors = [];
+
+  for (var i = 0; i < (6 * 7); i++) {
+    var pi3 = Math.floor(Math.PI / 3);
+    var n = (i * (1.0 / 6));
+    var r = Math.floor(3 * Math.sin(n) + 3);
+    var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);
+    var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);
+    colors.push(36 * r + 6 * g + b + 16);
+  }
+
+  return colors;
+};
+
+/**
+ * Apply rainbow to the given `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+NyanCat.prototype.rainbowify = function(str){
+  var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];
+  this.colorIndex += 1;
+  return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m';
+};
+
+/**
+ * Stdout helper.
+ */
+
+function write(string) {
+  process.stdout.write(string);
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+NyanCat.prototype = new F;
+NyanCat.prototype.constructor = NyanCat;
+
+
+}); // module: reporters/nyan.js
+
+require.register("reporters/progress.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `Progress`.
+ */
+
+exports = module.exports = Progress;
+
+/**
+ * General progress bar color.
+ */
+
+Base.colors.progress = 90;
+
+/**
+ * Initialize a new `Progress` bar test reporter.
+ *
+ * @param {Runner} runner
+ * @param {Object} options
+ * @api public
+ */
+
+function Progress(runner, options) {
+  Base.call(this, runner);
+
+  var self = this
+    , options = options || {}
+    , stats = this.stats
+    , width = Base.window.width * .50 | 0
+    , total = runner.total
+    , complete = 0
+    , max = Math.max
+    , lastN = -1;
+
+  // default chars
+  options.open = options.open || '[';
+  options.complete = options.complete || '▬';
+  options.incomplete = options.incomplete || Base.symbols.dot;
+  options.close = options.close || ']';
+  options.verbose = false;
+
+  // tests started
+  runner.on('start', function(){
+    console.log();
+    cursor.hide();
+  });
+
+  // tests complete
+  runner.on('test end', function(){
+    complete++;
+    var incomplete = total - complete
+      , percent = complete / total
+      , n = width * percent | 0
+      , i = width - n;
+
+    if (lastN === n && !options.verbose) {
+      // Don't re-render the line if it hasn't changed
+      return;
+    }
+    lastN = n;
+
+    cursor.CR();
+    process.stdout.write('\u001b[J');
+    process.stdout.write(color('progress', '  ' + options.open));
+    process.stdout.write(Array(n).join(options.complete));
+    process.stdout.write(Array(i).join(options.incomplete));
+    process.stdout.write(color('progress', options.close));
+    if (options.verbose) {
+      process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
+    }
+  });
+
+  // tests are complete, output some stats
+  // and the failures if any
+  runner.on('end', function(){
+    cursor.show();
+    console.log();
+    self.epilogue();
+  });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+Progress.prototype = new F;
+Progress.prototype.constructor = Progress;
+
+
+}); // module: reporters/progress.js
+
+require.register("reporters/spec.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `Spec`.
+ */
+
+exports = module.exports = Spec;
+
+/**
+ * Initialize a new `Spec` test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Spec(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , indents = 0
+    , n = 0;
+
+  function indent() {
+    return Array(indents).join('  ')
+  }
+
+  runner.on('start', function(){
+    console.log();
+  });
+
+  runner.on('suite', function(suite){
+    ++indents;
+    console.log(color('suite', '%s%s'), indent(), suite.title);
+  });
+
+  runner.on('suite end', function(suite){
+    --indents;
+    if (1 == indents) console.log();
+  });
+
+  runner.on('pending', function(test){
+    var fmt = indent() + color('pending', '  - %s');
+    console.log(fmt, test.title);
+  });
+
+  runner.on('pass', function(test){
+    if ('fast' == test.speed) {
+      var fmt = indent()
+        + color('checkmark', '  ' + Base.symbols.ok)
+        + color('pass', ' %s ');
+      cursor.CR();
+      console.log(fmt, test.title);
+    } else {
+      var fmt = indent()
+        + color('checkmark', '  ' + Base.symbols.ok)
+        + color('pass', ' %s ')
+        + color(test.speed, '(%dms)');
+      cursor.CR();
+      console.log(fmt, test.title, test.duration);
+    }
+  });
+
+  runner.on('fail', function(test, err){
+    cursor.CR();
+    console.log(indent() + color('fail', '  %d) %s'), ++n, test.title);
+  });
+
+  runner.on('end', self.epilogue.bind(self));
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+Spec.prototype = new F;
+Spec.prototype.constructor = Spec;
+
+
+}); // module: reporters/spec.js
+
+require.register("reporters/tap.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `TAP`.
+ */
+
+exports = module.exports = TAP;
+
+/**
+ * Initialize a new `TAP` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function TAP(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , n = 1
+    , passes = 0
+    , failures = 0;
+
+  runner.on('start', function(){
+    var total = runner.grepTotal(runner.suite);
+    console.log('%d..%d', 1, total);
+  });
+
+  runner.on('test end', function(){
+    ++n;
+  });
+
+  runner.on('pending', function(test){
+    console.log('ok %d %s # SKIP -', n, title(test));
+  });
+
+  runner.on('pass', function(test){
+    passes++;
+    console.log('ok %d %s', n, title(test));
+  });
+
+  runner.on('fail', function(test, err){
+    failures++;
+    console.log('not ok %d %s', n, title(test));
+    if (err.stack) console.log(err.stack.replace(/^/gm, '  '));
+  });
+
+  runner.on('end', function(){
+    console.log('# tests ' + (passes + failures));
+    console.log('# pass ' + passes);
+    console.log('# fail ' + failures);
+  });
+}
+
+/**
+ * Return a TAP-safe title of `test`
+ *
+ * @param {Object} test
+ * @return {String}
+ * @api private
+ */
+
+function title(test) {
+  return test.fullTitle().replace(/#/g, '');
+}
+
+}); // module: reporters/tap.js
+
+require.register("reporters/xunit.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , utils = require('../utils')
+  , escape = utils.escape;
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+  , setTimeout = global.setTimeout
+  , setInterval = global.setInterval
+  , clearTimeout = global.clearTimeout
+  , clearInterval = global.clearInterval;
+
+/**
+ * Expose `XUnit`.
+ */
+
+exports = module.exports = XUnit;
+
+/**
+ * Initialize a new `XUnit` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function XUnit(runner) {
+  Base.call(this, runner);
+  var stats = this.stats
+    , tests = []
+    , self = this;
+
+  runner.on('pending', function(test){
+    tests.push(test);
+  });
+
+  runner.on('pass', function(test){
+    tests.push(test);
+  });
+
+  runner.on('fail', function(test){
+    tests.push(test);
+  });
+
+  runner.on('end', function(){
+    console.log(tag('testsuite', {
+        name: 'Mocha Tests'
+      , tests: stats.tests
+      , failures: stats.failures
+      , errors: stats.failures
+      , skipped: stats.tests - stats.failures - stats.passes
+      , timestamp: (new Date).toUTCString()
+      , time: (stats.duration / 1000) || 0
+    }, false));
+
+    tests.forEach(test);
+    console.log('</testsuite>');
+  });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+XUnit.prototype = new F;
+XUnit.prototype.constructor = XUnit;
+
+
+/**
+ * Output tag for the given `test.`
+ */
+
+function test(test) {
+  var attrs = {
+      classname: test.parent.fullTitle()
+    , name: test.title
+    , time: (test.duration / 1000) || 0
+  };
+
+  if ('failed' == test.state) {
+    var err = test.err;
+    console.log(tag('testcase', attrs, false, tag('failure', {}, false, cdata(escape(err.message) + "\n" + err.stack))));
+  } else if (test.pending) {
+    console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
+  } else {
+    console.log(tag('testcase', attrs, true) );
+  }
+}
+
+/**
+ * HTML tag helper.
+ */
+
+function tag(name, attrs, close, content) {
+  var end = close ? '/>' : '>'
+    , pairs = []
+    , tag;
+
+  for (var key in attrs) {
+    pairs.push(key + '="' + escape(attrs[key]) + '"');
+  }
+
+  tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
+  if (content) tag += content + '</' + name + end;
+  return tag;
+}
+
+/**
+ * Return cdata escaped CDATA `str`.
+ */
+
+function cdata(str) {
+  return '<![CDATA[' + escape(str) + ']]>';
+}
+
+}); // module: reporters/xunit.js
+
+require.register("runnable.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('browser/events').EventEmitter
+  , debug = require('browser/debug')('mocha:runnable')
+  , milliseconds = require('./ms');
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+  , setTimeout = global.setTimeout
+  , setInterval = global.setInterval
+  , clearTimeout = global.clearTimeout
+  , clearInterval = global.clearInterval;
+
+/**
+ * Object#toString().
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Expose `Runnable`.
+ */
+
+module.exports = Runnable;
+
+/**
+ * Initialize a new `Runnable` with the given `title` and callback `fn`.
+ *
+ * @param {String} title
+ * @param {Function} fn
+ * @api private
+ */
+
+function Runnable(title, fn) {
+  this.title = title;
+  this.fn = fn;
+  this.async = fn && fn.length;
+  this.sync = ! this.async;
+  this._timeout = 2000;
+  this._slow = 75;
+  this._enableTimeouts = true;
+  this.timedOut = false;
+  this._trace = new Error('done() called multiple times')
+}
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+function F(){};
+F.prototype = EventEmitter.prototype;
+Runnable.prototype = new F;
+Runnable.prototype.constructor = Runnable;
+
+
+/**
+ * Set & get timeout `ms`.
+ *
+ * @param {Number|String} ms
+ * @return {Runnable|Number} ms or self
+ * @api private
+ */
+
+Runnable.prototype.timeout = function(ms){
+  if (0 == arguments.length) return this._timeout;
+  if (ms === 0) this._enableTimeouts = false;
+  if ('string' == typeof ms) ms = milliseconds(ms);
+  debug('timeout %d', ms);
+  this._timeout = ms;
+  if (this.timer) this.resetTimeout();
+  return this;
+};
+
+/**
+ * Set & get slow `ms`.
+ *
+ * @param {Number|String} ms
+ * @return {Runnable|Number} ms or self
+ * @api private
+ */
+
+Runnable.prototype.slow = function(ms){
+  if (0 === arguments.length) return this._slow;
+  if ('string' == typeof ms) ms = milliseconds(ms);
+  debug('timeout %d', ms);
+  this._slow = ms;
+  return this;
+};
+
+/**
+ * Set and & get timeout `enabled`.
+ *
+ * @param {Boolean} enabled
+ * @return {Runnable|Boolean} enabled or self
+ * @api private
+ */
+
+Runnable.prototype.enableTimeouts = function(enabled){
+  if (arguments.length === 0) return this._enableTimeouts;
+  debug('enableTimeouts %s', enabled);
+  this._enableTimeouts = enabled;
+  return this;
+};
+
+/**
+ * Return the full title generated by recursively
+ * concatenating the parent's full title.
+ *
+ * @return {String}
+ * @api public
+ */
+
+Runnable.prototype.fullTitle = function(){
+  return this.parent.fullTitle() + ' ' + this.title;
+};
+
+/**
+ * Clear the timeout.
+ *
+ * @api private
+ */
+
+Runnable.prototype.clearTimeout = function(){
+  clearTimeout(this.timer);
+};
+
+/**
+ * Inspect the runnable void of private properties.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Runnable.prototype.inspect = function(){
+  return JSON.stringify(this, function(key, val){
+    if ('_' == key[0]) return;
+    if ('parent' == key) return '#<Suite>';
+    if ('ctx' == key) return '#<Context>';
+    return val;
+  }, 2);
+};
+
+/**
+ * Reset the timeout.
+ *
+ * @api private
+ */
+
+Runnable.prototype.resetTimeout = function(){
+  var self = this;
+  var ms = this.timeout() || 1e9;
+
+  if (!this._enableTimeouts) return;
+  this.clearTimeout();
+  this.timer = setTimeout(function(){
+    if (!self._enableTimeouts) return;
+    self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
+    self.timedOut = true;
+  }, ms);
+};
+
+/**
+ * Whitelist these globals for this test run
+ *
+ * @api private
+ */
+Runnable.prototype.globals = function(arr){
+  var self = this;
+  this._allowedGlobals = arr;
+};
+
+/**
+ * Run the test and invoke `fn(err)`.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+
+Runnable.prototype.run = function(fn){
+  var self = this
+    , start = new Date
+    , ctx = this.ctx
+    , finished
+    , emitted;
+
+  // Some times the ctx exists but it is not runnable
+  if (ctx && ctx.runnable) ctx.runnable(this);
+
+  // called multiple times
+  function multiple(err) {
+    if (emitted) return;
+    emitted = true;
+    self.emit('error', err || new Error('done() called multiple times; stacktrace may be inaccurate'));
+  }
+
+  // finished
+  function done(err) {
+    var ms = self.timeout();
+    if (self.timedOut) return;
+    if (finished) return multiple(err || self._trace);
+    self.clearTimeout();
+    self.duration = new Date - start;
+    finished = true;
+    if (!err && self.duration > ms && self._enableTimeouts) err = new Error('timeout of ' + ms + 'ms exceeded');
+    fn(err);
+  }
+
+  // for .resetTimeout()
+  this.callback = done;
+
+  // explicit async with `done` argument
+  if (this.async) {
+    this.resetTimeout();
+
+    try {
+      this.fn.call(ctx, function(err){
+        if (err instanceof Error || toString.call(err) === "[object Error]") return done(err);
+        if (null != err) {
+          if (Object.prototype.toString.call(err) === '[object Object]') {
+            return done(new Error('done() invoked with non-Error: ' + JSON.stringify(err)));
+          } else {
+            return done(new Error('done() invoked with non-Error: ' + err));
+          }
+        }
+        done();
+      });
+    } catch (err) {
+      done(err);
+    }
+    return;
+  }
+
+  if (this.asyncOnly) {
+    return done(new Error('--async-only option in use without declaring `done()`'));
+  }
+
+  // sync or promise-returning
+  try {
+    if (this.pending) {
+      done();
+    } else {
+      callFn(this.fn);
+    }
+  } catch (err) {
+    done(err);
+  }
+
+  function callFn(fn) {
+    var result = fn.call(ctx);
+    if (result && typeof result.then === 'function') {
+      self.resetTimeout();
+      result
+        .then(function() {
+          done()
+        },
+        function(reason) {
+          done(reason || new Error('Promise rejected with no or falsy reason'))
+        });
+    } else {
+      done();
+    }
+  }
+};
+
+}); // module: runnable.js
+
+require.register("runner.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('browser/events').EventEmitter
+  , debug = require('browser/debug')('mocha:runner')
+  , Test = require('./test')
+  , utils = require('./utils')
+  , filter = utils.filter
+  , keys = utils.keys;
+
+/**
+ * Non-enumerable globals.
+ */
+
+var globals = [
+  'setTimeout',
+  'clearTimeout',
+  'setInterval',
+  'clearInterval',
+  'XMLHttpRequest',
+  'Date'
+];
+
+/**
+ * Expose `Runner`.
+ */
+
+module.exports = Runner;
+
+/**
+ * Initialize a `Runner` for the given `suite`.
+ *
+ * Events:
+ *
+ *   - `start`  execution started
+ *   - `end`  execution complete
+ *   - `suite`  (suite) test suite execution started
+ *   - `suite end`  (suite) all tests (and sub-suites) have finished
+ *   - `test`  (test) test execution started
+ *   - `test end`  (test) test completed
+ *   - `hook`  (hook) hook execution started
+ *   - `hook end`  (hook) hook complete
+ *   - `pass`  (test) test passed
+ *   - `fail`  (test, err) test failed
+ *   - `pending`  (test) test pending
+ *
+ * @api public
+ */
+
+function Runner(suite) {
+  var self = this;
+  this._globals = [];
+  this._abort = false;
+  this.suite = suite;
+  this.total = suite.total();
+  this.failures = 0;
+  this.on('test end', function(test){ self.checkGlobals(test); });
+  this.on('hook end', function(hook){ self.checkGlobals(hook); });
+  this.grep(/.*/);
+  this.globals(this.globalProps().concat(extraGlobals()));
+}
+
+/**
+ * Wrapper for setImmediate, process.nextTick, or browser polyfill.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.immediately = global.setImmediate || process.nextTick;
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+function F(){};
+F.prototype = EventEmitter.prototype;
+Runner.prototype = new F;
+Runner.prototype.constructor = Runner;
+
+
+/**
+ * Run tests with full titles matching `re`. Updates runner.total
+ * with number of tests matched.
+ *
+ * @param {RegExp} re
+ * @param {Boolean} invert
+ * @return {Runner} for chaining
+ * @api public
+ */
+
+Runner.prototype.grep = function(re, invert){
+  debug('grep %s', re);
+  this._grep = re;
+  this._invert = invert;
+  this.total = this.grepTotal(this.suite);
+  return this;
+};
+
+/**
+ * Returns the number of tests matching the grep search for the
+ * given suite.
+ *
+ * @param {Suite} suite
+ * @return {Number}
+ * @api public
+ */
+
+Runner.prototype.grepTotal = function(suite) {
+  var self = this;
+  var total = 0;
+
+  suite.eachTest(function(test){
+    var match = self._grep.test(test.fullTitle());
+    if (self._invert) match = !match;
+    if (match) total++;
+  });
+
+  return total;
+};
+
+/**
+ * Return a list of global properties.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+Runner.prototype.globalProps = function() {
+  var props = utils.keys(global);
+
+  // non-enumerables
+  for (var i = 0; i < globals.length; ++i) {
+    if (~utils.indexOf(props, globals[i])) continue;
+    props.push(globals[i]);
+  }
+
+  return props;
+};
+
+/**
+ * Allow the given `arr` of globals.
+ *
+ * @param {Array} arr
+ * @return {Runner} for chaining
+ * @api public
+ */
+
+Runner.prototype.globals = function(arr){
+  if (0 == arguments.length) return this._globals;
+  debug('globals %j', arr);
+  this._globals = this._globals.concat(arr);
+  return this;
+};
+
+/**
+ * Check for global variable leaks.
+ *
+ * @api private
+ */
+
+Runner.prototype.checkGlobals = function(test){
+  if (this.ignoreLeaks) return;
+  var ok = this._globals;
+
+  var globals = this.globalProps();
+  var leaks;
+
+  if (test) {
+    ok = ok.concat(test._allowedGlobals || []);
+  }
+
+  if(this.prevGlobalsLength == globals.length) return;
+  this.prevGlobalsLength = globals.length;
+
+  leaks = filterLeaks(ok, globals);
+  this._globals = this._globals.concat(leaks);
+
+  if (leaks.length > 1) {
+    this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
+  } else if (leaks.length) {
+    this.fail(test, new Error('global leak detected: ' + leaks[0]));
+  }
+};
+
+/**
+ * Fail the given `test`.
+ *
+ * @param {Test} test
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.fail = function(test, err){
+  ++this.failures;
+  test.state = 'failed';
+
+  if ('string' == typeof err) {
+    err = new Error('the string "' + err + '" was thrown, throw an Error :)');
+  }
+
+  this.emit('fail', test, err);
+};
+
+/**
+ * Fail the given `hook` with `err`.
+ *
+ * Hook failures work in the following pattern:
+ * - If bail, then exit
+ * - Failed `before` hook skips all tests in a suite and subsuites,
+ *   but jumps to corresponding `after` hook
+ * - Failed `before each` hook skips remaining tests in a
+ *   suite and jumps to corresponding `after each` hook,
+ *   which is run only once
+ * - Failed `after` hook does not alter
+ *   execution order
+ * - Failed `after each` hook skips remaining tests in a
+ *   suite and subsuites, but executes other `after each`
+ *   hooks
+ *
+ * @param {Hook} hook
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.failHook = function(hook, err){
+  this.fail(hook, err);
+  if (this.suite.bail()) {
+    this.emit('end');
+  }
+};
+
+/**
+ * Run hook `name` callbacks and then invoke `fn()`.
+ *
+ * @param {String} name
+ * @param {Function} function
+ * @api private
+ */
+
+Runner.prototype.hook = function(name, fn){
+  var suite = this.suite
+    , hooks = suite['_' + name]
+    , self = this
+    , timer;
+
+  function next(i) {
+    var hook = hooks[i];
+    if (!hook) return fn();
+    if (self.failures && suite.bail()) return fn();
+    self.currentRunnable = hook;
+
+    hook.ctx.currentTest = self.test;
+
+    self.emit('hook', hook);
+
+    hook.on('error', function(err){
+      self.failHook(hook, err);
+    });
+
+    hook.run(function(err){
+      hook.removeAllListeners('error');
+      var testError = hook.error();
+      if (testError) self.fail(self.test, testError);
+      if (err) {
+        self.failHook(hook, err);
+
+        // stop executing hooks, notify callee of hook err
+        return fn(err);
+      }
+      self.emit('hook end', hook);
+      delete hook.ctx.currentTest;
+      next(++i);
+    });
+  }
+
+  Runner.immediately(function(){
+    next(0);
+  });
+};
+
+/**
+ * Run hook `name` for the given array of `suites`
+ * in order, and callback `fn(err, errSuite)`.
+ *
+ * @param {String} name
+ * @param {Array} suites
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.hooks = function(name, suites, fn){
+  var self = this
+    , orig = this.suite;
+
+  function next(suite) {
+    self.suite = suite;
+
+    if (!suite) {
+      self.suite = orig;
+      return fn();
+    }
+
+    self.hook(name, function(err){
+      if (err) {
+        var errSuite = self.suite;
+        self.suite = orig;
+        return fn(err, errSuite);
+      }
+
+      next(suites.pop());
+    });
+  }
+
+  next(suites.pop());
+};
+
+/**
+ * Run hooks from the top level down.
+ *
+ * @param {String} name
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.hookUp = function(name, fn){
+  var suites = [this.suite].concat(this.parents()).reverse();
+  this.hooks(name, suites, fn);
+};
+
+/**
+ * Run hooks from the bottom up.
+ *
+ * @param {String} name
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.hookDown = function(name, fn){
+  var suites = [this.suite].concat(this.parents());
+  this.hooks(name, suites, fn);
+};
+
+/**
+ * Return an array of parent Suites from
+ * closest to furthest.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+Runner.prototype.parents = function(){
+  var suite = this.suite
+    , suites = [];
+  while (suite = suite.parent) suites.push(suite);
+  return suites;
+};
+
+/**
+ * Run the current test and callback `fn(err)`.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.runTest = function(fn){
+  var test = this.test
+    , self = this;
+
+  if (this.asyncOnly) test.asyncOnly = true;
+
+  try {
+    test.on('error', function(err){
+      self.fail(test, err);
+    });
+    test.run(fn);
+  } catch (err) {
+    fn(err);
+  }
+};
+
+/**
+ * Run tests in the given `suite` and invoke
+ * the callback `fn()` when complete.
+ *
+ * @param {Suite} suite
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.runTests = function(suite, fn){
+  var self = this
+    , tests = suite.tests.slice()
+    , test;
+
+
+  function hookErr(err, errSuite, after) {
+    // before/after Each hook for errSuite failed:
+    var orig = self.suite;
+
+    // for failed 'after each' hook start from errSuite parent,
+    // otherwise start from errSuite itself
+    self.suite = after ? errSuite.parent : errSuite;
+
+    if (self.suite) {
+      // call hookUp afterEach
+      self.hookUp('afterEach', function(err2, errSuite2) {
+        self.suite = orig;
+        // some hooks may fail even now
+        if (err2) return hookErr(err2, errSuite2, true);
+        // report error suite
+        fn(errSuite);
+      });
+    } else {
+      // there is no need calling other 'after each' hooks
+      self.suite = orig;
+      fn(errSuite);
+    }
+  }
+
+  function next(err, errSuite) {
+    // if we bail after first err
+    if (self.failures && suite._bail) return fn();
+
+    if (self._abort) return fn();
+
+    if (err) return hookErr(err, errSuite, true);
+
+    // next test
+    test = tests.shift();
+
+    // all done
+    if (!test) return fn();
+
+    // grep
+    var match = self._grep.test(test.fullTitle());
+    if (self._invert) match = !match;
+    if (!match) return next();
+
+    // pending
+    if (test.pending) {
+      self.emit('pending', test);
+      self.emit('test end', test);
+      return next();
+    }
+
+    // execute test and hook(s)
+    self.emit('test', self.test = test);
+    self.hookDown('beforeEach', function(err, errSuite){
+
+      if (err) return hookErr(err, errSuite, false);
+
+      self.currentRunnable = self.test;
+      self.runTest(function(err){
+        test = self.test;
+
+        if (err) {
+          self.fail(test, err);
+          self.emit('test end', test);
+          return self.hookUp('afterEach', next);
+        }
+
+        test.state = 'passed';
+        self.emit('pass', test);
+        self.emit('test end', test);
+        self.hookUp('afterEach', next);
+      });
+    });
+  }
+
+  this.next = next;
+  next();
+};
+
+/**
+ * Run the given `suite` and invoke the
+ * callback `fn()` when complete.
+ *
+ * @param {Suite} suite
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.runSuite = function(suite, fn){
+  var total = this.grepTotal(suite)
+    , self = this
+    , i = 0;
+
+  debug('run suite %s', suite.fullTitle());
+
+  if (!total) return fn();
+
+  this.emit('suite', this.suite = suite);
+
+  function next(errSuite) {
+    if (errSuite) {
+      // current suite failed on a hook from errSuite
+      if (errSuite == suite) {
+        // if errSuite is current suite
+        // continue to the next sibling suite
+        return done();
+      } else {
+        // errSuite is among the parents of current suite
+        // stop execution of errSuite and all sub-suites
+        return done(errSuite);
+      }
+    }
+
+    if (self._abort) return done();
+
+    var curr = suite.suites[i++];
+    if (!curr) return done();
+    self.runSuite(curr, next);
+  }
+
+  function done(errSuite) {
+    self.suite = suite;
+    self.hook('afterAll', function(){
+      self.emit('suite end', suite);
+      fn(errSuite);
+    });
+  }
+
+  this.hook('beforeAll', function(err){
+    if (err) return done();
+    self.runTests(suite, next);
+  });
+};
+
+/**
+ * Handle uncaught exceptions.
+ *
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.uncaught = function(err){
+  if (err) {
+    debug('uncaught exception %s', err !== function () {
+      return this;
+    }.call(err) ? err : ( err.message || err ));
+  } else {
+    debug('uncaught undefined exception');
+    err = new Error('Caught undefined error, did you throw without specifying what?');
+  }
+  err.uncaught = true;
+
+  var runnable = this.currentRunnable;
+  if (!runnable) return;
+
+  var wasAlreadyDone = runnable.state;
+  this.fail(runnable, err);
+
+  runnable.clearTimeout();
+
+  if (wasAlreadyDone) return;
+
+  // recover from test
+  if ('test' == runnable.type) {
+    this.emit('test end', runnable);
+    this.hookUp('afterEach', this.next);
+    return;
+  }
+
+  // bail on hooks
+  this.emit('end');
+};
+
+/**
+ * Run the root suite and invoke `fn(failures)`
+ * on completion.
+ *
+ * @param {Function} fn
+ * @return {Runner} for chaining
+ * @api public
+ */
+
+Runner.prototype.run = function(fn){
+  var self = this
+    , fn = fn || function(){};
+
+  function uncaught(err){
+    self.uncaught(err);
+  }
+
+  debug('start');
+
+  // callback
+  this.on('end', function(){
+    debug('end');
+    process.removeListener('uncaughtException', uncaught);
+    fn(self.failures);
+  });
+
+  // run suites
+  this.emit('start');
+  this.runSuite(this.suite, function(){
+    debug('finished running');
+    self.emit('end');
+  });
+
+  // uncaught exception
+  process.on('uncaughtException', uncaught);
+
+  return this;
+};
+
+/**
+ * Cleanly abort execution
+ *
+ * @return {Runner} for chaining
+ * @api public
+ */
+Runner.prototype.abort = function(){
+  debug('aborting');
+  this._abort = true;
+};
+
+/**
+ * Filter leaks with the given globals flagged as `ok`.
+ *
+ * @param {Array} ok
+ * @param {Array} globals
+ * @return {Array}
+ * @api private
+ */
+
+function filterLeaks(ok, globals) {
+  return filter(globals, function(key){
+    // Firefox and Chrome exposes iframes as index inside the window object
+    if (/^d+/.test(key)) return false;
+
+    // in firefox
+    // if runner runs in an iframe, this iframe's window.getInterface method not init at first
+    // it is assigned in some seconds
+    if (global.navigator && /^getInterface/.test(key)) return false;
+
+    // an iframe could be approached by window[iframeIndex]
+    // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak
+    if (global.navigator && /^\d+/.test(key)) return false;
+
+    // Opera and IE expose global variables for HTML element IDs (issue #243)
+    if (/^mocha-/.test(key)) return false;
+
+    var matched = filter(ok, function(ok){
+      if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);
+      return key == ok;
+    });
+    return matched.length == 0 && (!global.navigator || 'onerror' !== key);
+  });
+}
+
+/**
+ * Array of globals dependent on the environment.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+ function extraGlobals() {
+  if (typeof(process) === 'object' &&
+      typeof(process.version) === 'string') {
+
+    var nodeVersion = process.version.split('.').reduce(function(a, v) {
+      return a << 8 | v;
+    });
+
+    // 'errno' was renamed to process._errno in v0.9.11.
+
+    if (nodeVersion < 0x00090B) {
+      return ['errno'];
+    }
+  }
+
+  return [];
+ }
+
+}); // module: runner.js
+
+require.register("suite.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('browser/events').EventEmitter
+  , debug = require('browser/debug')('mocha:suite')
+  , milliseconds = require('./ms')
+  , utils = require('./utils')
+  , Hook = require('./hook');
+
+/**
+ * Expose `Suite`.
+ */
+
+exports = module.exports = Suite;
+
+/**
+ * Create a new `Suite` with the given `title`
+ * and parent `Suite`. When a suite with the
+ * same title is already present, that suite
+ * is returned to provide nicer reporter
+ * and more flexible meta-testing.
+ *
+ * @param {Suite} parent
+ * @param {String} title
+ * @return {Suite}
+ * @api public
+ */
+
+exports.create = function(parent, title){
+  var suite = new Suite(title, parent.ctx);
+  suite.parent = parent;
+  if (parent.pending) suite.pending = true;
+  title = suite.fullTitle();
+  parent.addSuite(suite);
+  return suite;
+};
+
+/**
+ * Initialize a new `Suite` with the given
+ * `title` and `ctx`.
+ *
+ * @param {String} title
+ * @param {Context} ctx
+ * @api private
+ */
+
+function Suite(title, parentContext) {
+  this.title = title;
+  var context = function() {};
+  context.prototype = parentContext;
+  this.ctx = new context();
+  this.suites = [];
+  this.tests = [];
+  this.pending = false;
+  this._beforeEach = [];
+  this._beforeAll = [];
+  this._afterEach = [];
+  this._afterAll = [];
+  this.root = !title;
+  this._timeout = 2000;
+  this._enableTimeouts = true;
+  this._slow = 75;
+  this._bail = false;
+}
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+function F(){};
+F.prototype = EventEmitter.prototype;
+Suite.prototype = new F;
+Suite.prototype.constructor = Suite;
+
+
+/**
+ * Return a clone of this `Suite`.
+ *
+ * @return {Suite}
+ * @api private
+ */
+
+Suite.prototype.clone = function(){
+  var suite = new Suite(this.title);
+  debug('clone');
+  suite.ctx = this.ctx;
+  suite.timeout(this.timeout());
+  suite.enableTimeouts(this.enableTimeouts());
+  suite.slow(this.slow());
+  suite.bail(this.bail());
+  return suite;
+};
+
+/**
+ * Set timeout `ms` or short-hand such as "2s".
+ *
+ * @param {Number|String} ms
+ * @return {Suite|Number} for chaining
+ * @api private
+ */
+
+Suite.prototype.timeout = function(ms){
+  if (0 == arguments.length) return this._timeout;
+  if (ms === 0) this._enableTimeouts = false;
+  if ('string' == typeof ms) ms = milliseconds(ms);
+  debug('timeout %d', ms);
+  this._timeout = parseInt(ms, 10);
+  return this;
+};
+
+/**
+  * Set timeout `enabled`.
+  *
+  * @param {Boolean} enabled
+  * @return {Suite|Boolean} self or enabled
+  * @api private
+  */
+
+Suite.prototype.enableTimeouts = function(enabled){
+  if (arguments.length === 0) return this._enableTimeouts;
+  debug('enableTimeouts %s', enabled);
+  this._enableTimeouts = enabled;
+  return this;
+};
+
+/**
+ * Set slow `ms` or short-hand such as "2s".
+ *
+ * @param {Number|String} ms
+ * @return {Suite|Number} for chaining
+ * @api private
+ */
+
+Suite.prototype.slow = function(ms){
+  if (0 === arguments.length) return this._slow;
+  if ('string' == typeof ms) ms = milliseconds(ms);
+  debug('slow %d', ms);
+  this._slow = ms;
+  return this;
+};
+
+/**
+ * Sets whether to bail after first error.
+ *
+ * @parma {Boolean} bail
+ * @return {Suite|Number} for chaining
+ * @api private
+ */
+
+Suite.prototype.bail = function(bail){
+  if (0 == arguments.length) return this._bail;
+  debug('bail %s', bail);
+  this._bail = bail;
+  return this;
+};
+
+/**
+ * Run `fn(test[, done])` before running tests.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.beforeAll = function(title, fn){
+  if (this.pending) return this;
+  if ('function' === typeof title) {
+    fn = title;
+    title = fn.name;
+  }
+  title = '"before all" hook' + (title ? ': ' + title : '');
+
+  var hook = new Hook(title, fn);
+  hook.parent = this;
+  hook.timeout(this.timeout());
+  hook.enableTimeouts(this.enableTimeouts());
+  hook.slow(this.slow());
+  hook.ctx = this.ctx;
+  this._beforeAll.push(hook);
+  this.emit('beforeAll', hook);
+  return this;
+};
+
+/**
+ * Run `fn(test[, done])` after running tests.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.afterAll = function(title, fn){
+  if (this.pending) return this;
+  if ('function' === typeof title) {
+    fn = title;
+    title = fn.name;
+  }
+  title = '"after all" hook' + (title ? ': ' + title : '');
+
+  var hook = new Hook(title, fn);
+  hook.parent = this;
+  hook.timeout(this.timeout());
+  hook.enableTimeouts(this.enableTimeouts());
+  hook.slow(this.slow());
+  hook.ctx = this.ctx;
+  this._afterAll.push(hook);
+  this.emit('afterAll', hook);
+  return this;
+};
+
+/**
+ * Run `fn(test[, done])` before each test case.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.beforeEach = function(title, fn){
+  if (this.pending) return this;
+  if ('function' === typeof title) {
+    fn = title;
+    title = fn.name;
+  }
+  title = '"before each" hook' + (title ? ': ' + title : '');
+
+  var hook = new Hook(title, fn);
+  hook.parent = this;
+  hook.timeout(this.timeout());
+  hook.enableTimeouts(this.enableTimeouts());
+  hook.slow(this.slow());
+  hook.ctx = this.ctx;
+  this._beforeEach.push(hook);
+  this.emit('beforeEach', hook);
+  return this;
+};
+
+/**
+ * Run `fn(test[, done])` after each test case.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.afterEach = function(title, fn){
+  if (this.pending) return this;
+  if ('function' === typeof title) {
+    fn = title;
+    title = fn.name;
+  }
+  title = '"after each" hook' + (title ? ': ' + title : '');
+
+  var hook = new Hook(title, fn);
+  hook.parent = this;
+  hook.timeout(this.timeout());
+  hook.enableTimeouts(this.enableTimeouts());
+  hook.slow(this.slow());
+  hook.ctx = this.ctx;
+  this._afterEach.push(hook);
+  this.emit('afterEach', hook);
+  return this;
+};
+
+/**
+ * Add a test `suite`.
+ *
+ * @param {Suite} suite
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.addSuite = function(suite){
+  suite.parent = this;
+  suite.timeout(this.timeout());
+  suite.enableTimeouts(this.enableTimeouts());
+  suite.slow(this.slow());
+  suite.bail(this.bail());
+  this.suites.push(suite);
+  this.emit('suite', suite);
+  return this;
+};
+
+/**
+ * Add a `test` to this suite.
+ *
+ * @param {Test} test
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.addTest = function(test){
+  test.parent = this;
+  test.timeout(this.timeout());
+  test.enableTimeouts(this.enableTimeouts());
+  test.slow(this.slow());
+  test.ctx = this.ctx;
+  this.tests.push(test);
+  this.emit('test', test);
+  return this;
+};
+
+/**
+ * Return the full title generated by recursively
+ * concatenating the parent's full title.
+ *
+ * @return {String}
+ * @api public
+ */
+
+Suite.prototype.fullTitle = function(){
+  if (this.parent) {
+    var full = this.parent.fullTitle();
+    if (full) return full + ' ' + this.title;
+  }
+  return this.title;
+};
+
+/**
+ * Return the total number of tests.
+ *
+ * @return {Number}
+ * @api public
+ */
+
+Suite.prototype.total = function(){
+  return utils.reduce(this.suites, function(sum, suite){
+    return sum + suite.total();
+  }, 0) + this.tests.length;
+};
+
+/**
+ * Iterates through each suite recursively to find
+ * all tests. Applies a function in the format
+ * `fn(test)`.
+ *
+ * @param {Function} fn
+ * @return {Suite}
+ * @api private
+ */
+
+Suite.prototype.eachTest = function(fn){
+  utils.forEach(this.tests, fn);
+  utils.forEach(this.suites, function(suite){
+    suite.eachTest(fn);
+  });
+  return this;
+};
+
+}); // module: suite.js
+
+require.register("test.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Runnable = require('./runnable');
+
+/**
+ * Expose `Test`.
+ */
+
+module.exports = Test;
+
+/**
+ * Initialize a new `Test` with the given `title` and callback `fn`.
+ *
+ * @param {String} title
+ * @param {Function} fn
+ * @api private
+ */
+
+function Test(title, fn) {
+  Runnable.call(this, title, fn);
+  this.pending = !fn;
+  this.type = 'test';
+}
+
+/**
+ * Inherit from `Runnable.prototype`.
+ */
+
+function F(){};
+F.prototype = Runnable.prototype;
+Test.prototype = new F;
+Test.prototype.constructor = Test;
+
+
+}); // module: test.js
+
+require.register("utils.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var fs = require('browser/fs')
+  , path = require('browser/path')
+  , basename = path.basename
+  , exists = fs.existsSync || path.existsSync
+  , glob = require('browser/glob')
+  , join = path.join
+  , debug = require('browser/debug')('mocha:watch');
+
+/**
+ * Ignored directories.
+ */
+
+var ignore = ['node_modules', '.git'];
+
+/**
+ * Escape special characters in the given string of html.
+ *
+ * @param  {String} html
+ * @return {String}
+ * @api private
+ */
+
+exports.escape = function(html){
+  return String(html)
+    .replace(/&/g, '&amp;')
+    .replace(/"/g, '&quot;')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;');
+};
+
+/**
+ * Array#forEach (<=IE8)
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ * @param {Object} scope
+ * @api private
+ */
+
+exports.forEach = function(arr, fn, scope){
+  for (var i = 0, l = arr.length; i < l; i++)
+    fn.call(scope, arr[i], i);
+};
+
+/**
+ * Array#map (<=IE8)
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ * @param {Object} scope
+ * @api private
+ */
+
+exports.map = function(arr, fn, scope){
+  var result = [];
+  for (var i = 0, l = arr.length; i < l; i++)
+    result.push(fn.call(scope, arr[i], i));
+  return result;
+};
+
+/**
+ * Array#indexOf (<=IE8)
+ *
+ * @parma {Array} arr
+ * @param {Object} obj to find index of
+ * @param {Number} start
+ * @api private
+ */
+
+exports.indexOf = function(arr, obj, start){
+  for (var i = start || 0, l = arr.length; i < l; i++) {
+    if (arr[i] === obj)
+      return i;
+  }
+  return -1;
+};
+
+/**
+ * Array#reduce (<=IE8)
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ * @param {Object} initial value
+ * @api private
+ */
+
+exports.reduce = function(arr, fn, val){
+  var rval = val;
+
+  for (var i = 0, l = arr.length; i < l; i++) {
+    rval = fn(rval, arr[i], i, arr);
+  }
+
+  return rval;
+};
+
+/**
+ * Array#filter (<=IE8)
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ * @api private
+ */
+
+exports.filter = function(arr, fn){
+  var ret = [];
+
+  for (var i = 0, l = arr.length; i < l; i++) {
+    var val = arr[i];
+    if (fn(val, i, arr)) ret.push(val);
+  }
+
+  return ret;
+};
+
+/**
+ * Object.keys (<=IE8)
+ *
+ * @param {Object} obj
+ * @return {Array} keys
+ * @api private
+ */
+
+exports.keys = Object.keys || function(obj) {
+  var keys = []
+    , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
+
+  for (var key in obj) {
+    if (has.call(obj, key)) {
+      keys.push(key);
+    }
+  }
+
+  return keys;
+};
+
+/**
+ * Watch the given `files` for changes
+ * and invoke `fn(file)` on modification.
+ *
+ * @param {Array} files
+ * @param {Function} fn
+ * @api private
+ */
+
+exports.watch = function(files, fn){
+  var options = { interval: 100 };
+  files.forEach(function(file){
+    debug('file %s', file);
+    fs.watchFile(file, options, function(curr, prev){
+      if (prev.mtime < curr.mtime) fn(file);
+    });
+  });
+};
+
+/**
+ * Ignored files.
+ */
+
+function ignored(path){
+  return !~ignore.indexOf(path);
+}
+
+/**
+ * Lookup files in the given `dir`.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+exports.files = function(dir, ext, ret){
+  ret = ret || [];
+  ext = ext || ['js'];
+
+  var re = new RegExp('\\.(' + ext.join('|') + ')$');
+
+  fs.readdirSync(dir)
+  .filter(ignored)
+  .forEach(function(path){
+    path = join(dir, path);
+    if (fs.statSync(path).isDirectory()) {
+      exports.files(path, ext, ret);
+    } else if (path.match(re)) {
+      ret.push(path);
+    }
+  });
+
+  return ret;
+};
+
+/**
+ * Compute a slug from the given `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+exports.slug = function(str){
+  return str
+    .toLowerCase()
+    .replace(/ +/g, '-')
+    .replace(/[^-\w]/g, '');
+};
+
+/**
+ * Strip the function definition from `str`,
+ * and re-indent for pre whitespace.
+ */
+
+exports.clean = function(str) {
+  str = str
+    .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '')
+    .replace(/^function *\(.*\) *{|\(.*\) *=> *{?/, '')
+    .replace(/\s+\}$/, '');
+
+  var spaces = str.match(/^\n?( *)/)[1].length
+    , tabs = str.match(/^\n?(\t*)/)[1].length
+    , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm');
+
+  str = str.replace(re, '');
+
+  return exports.trim(str);
+};
+
+/**
+ * Trim the given `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+exports.trim = function(str){
+  return str.replace(/^\s+|\s+$/g, '');
+};
+
+/**
+ * Parse the given `qs`.
+ *
+ * @param {String} qs
+ * @return {Object}
+ * @api private
+ */
+
+exports.parseQuery = function(qs){
+  return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){
+    var i = pair.indexOf('=')
+      , key = pair.slice(0, i)
+      , val = pair.slice(++i);
+
+    obj[key] = decodeURIComponent(val);
+    return obj;
+  }, {});
+};
+
+/**
+ * Highlight the given string of `js`.
+ *
+ * @param {String} js
+ * @return {String}
+ * @api private
+ */
+
+function highlight(js) {
+  return js
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;')
+    .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
+    .replace(/('.*?')/gm, '<span class="string">$1</span>')
+    .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
+    .replace(/(\d+)/gm, '<span class="number">$1</span>')
+    .replace(/\bnew[ \t]+(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
+    .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
+}
+
+/**
+ * Highlight the contents of tag `name`.
+ *
+ * @param {String} name
+ * @api private
+ */
+
+exports.highlightTags = function(name) {
+  var code = document.getElementById('mocha').getElementsByTagName(name);
+  for (var i = 0, len = code.length; i < len; ++i) {
+    code[i].innerHTML = highlight(code[i].innerHTML);
+  }
+};
+
+
+/**
+ * Stringify `obj`.
+ *
+ * @param {Object} obj
+ * @return {String}
+ * @api private
+ */
+
+exports.stringify = function(obj) {
+  if (obj instanceof RegExp) return obj.toString();
+  return JSON.stringify(exports.canonicalize(obj), null, 2).replace(/,(\n|$)/g, '$1');
+};
+
+/**
+ * Return a new object that has the keys in sorted order.
+ * @param {Object} obj
+ * @param {Array} [stack]
+ * @return {Object}
+ * @api private
+ */
+
+exports.canonicalize = function(obj, stack) {
+  stack = stack || [];
+
+  if (exports.indexOf(stack, obj) !== -1) return '[Circular]';
+
+  var canonicalizedObj;
+
+  if ({}.toString.call(obj) === '[object Array]') {
+    stack.push(obj);
+    canonicalizedObj = exports.map(obj, function (item) {
+      return exports.canonicalize(item, stack);
+    });
+    stack.pop();
+  } else if (typeof obj === 'object' && obj !== null) {
+    stack.push(obj);
+    canonicalizedObj = {};
+    exports.forEach(exports.keys(obj).sort(), function (key) {
+      canonicalizedObj[key] = exports.canonicalize(obj[key], stack);
+    });
+    stack.pop();
+  } else {
+    canonicalizedObj = obj;
+  }
+
+  return canonicalizedObj;
+ };
+
+/**
+ * Lookup file names at the given `path`.
+ */
+exports.lookupFiles = function lookupFiles(path, extensions, recursive) {
+  var files = [];
+  var re = new RegExp('\\.(' + extensions.join('|') + ')$');
+
+  if (!exists(path)) {
+    if (exists(path + '.js')) {
+      path += '.js';
+    } else {
+      files = glob.sync(path);
+      if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'");
+      return files;
+    }
+  }
+
+  try {
+    var stat = fs.statSync(path);
+    if (stat.isFile()) return path;
+  }
+  catch (ignored) {
+    return;
+  }
+
+  fs.readdirSync(path).forEach(function(file){
+    file = join(path, file);
+    try {
+      var stat = fs.statSync(file);
+      if (stat.isDirectory()) {
+        if (recursive) {
+          files = files.concat(lookupFiles(file, extensions, recursive));
+        }
+        return;
+      }
+    }
+    catch (ignored) {
+      return;
+    }
+    if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') return;
+    files.push(file);
+  });
+
+  return files;
+};
+
+}); // module: utils.js
+// The global object is "self" in Web Workers.
+var global = (function() { return this; })();
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date;
+var setTimeout = global.setTimeout;
+var setInterval = global.setInterval;
+var clearTimeout = global.clearTimeout;
+var clearInterval = global.clearInterval;
+
+/**
+ * Node shims.
+ *
+ * These are meant only to allow
+ * mocha.js to run untouched, not
+ * to allow running node code in
+ * the browser.
+ */
+
+var process = {};
+process.exit = function(status){};
+process.stdout = {};
+
+var uncaughtExceptionHandlers = [];
+
+var originalOnerrorHandler = global.onerror;
+
+/**
+ * Remove uncaughtException listener.
+ * Revert to original onerror handler if previously defined.
+ */
+
+process.removeListener = function(e, fn){
+  if ('uncaughtException' == e) {
+    if (originalOnerrorHandler) {
+      global.onerror = originalOnerrorHandler;
+    } else {
+      global.onerror = function() {};
+    }
+    var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn);
+    if (i != -1) { uncaughtExceptionHandlers.splice(i, 1); }
+  }
+};
+
+/**
+ * Implements uncaughtException listener.
+ */
+
+process.on = function(e, fn){
+  if ('uncaughtException' == e) {
+    global.onerror = function(err, url, line){
+      fn(new Error(err + ' (' + url + ':' + line + ')'));
+      return true;
+    };
+    uncaughtExceptionHandlers.push(fn);
+  }
+};
+
+/**
+ * Expose mocha.
+ */
+
+var Mocha = global.Mocha = require('mocha'),
+    mocha = global.mocha = new Mocha({ reporter: 'html' });
+
+// The BDD UI is registered by default, but no UI will be functional in the
+// browser without an explicit call to the overridden `mocha.ui` (see below).
+// Ensure that this default UI does not expose its methods to the global scope.
+mocha.suite.removeAllListeners('pre-require');
+
+var immediateQueue = []
+  , immediateTimeout;
+
+function timeslice() {
+  var immediateStart = new Date().getTime();
+  while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) {
+    immediateQueue.shift()();
+  }
+  if (immediateQueue.length) {
+    immediateTimeout = setTimeout(timeslice, 0);
+  } else {
+    immediateTimeout = null;
+  }
+}
+
+/**
+ * High-performance override of Runner.immediately.
+ */
+
+Mocha.Runner.immediately = function(callback) {
+  immediateQueue.push(callback);
+  if (!immediateTimeout) {
+    immediateTimeout = setTimeout(timeslice, 0);
+  }
+};
+
+/**
+ * Function to allow assertion libraries to throw errors directly into mocha.
+ * This is useful when running tests in a browser because window.onerror will
+ * only receive the 'message' attribute of the Error.
+ */
+mocha.throwError = function(err) {
+  Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) {
+    fn(err);
+  });
+  throw err;
+};
+
+/**
+ * Override ui to ensure that the ui functions are initialized.
+ * Normally this would happen in Mocha.prototype.loadFiles.
+ */
+
+mocha.ui = function(ui){
+  Mocha.prototype.ui.call(this, ui);
+  this.suite.emit('pre-require', global, null, this);
+  return this;
+};
+
+/**
+ * Setup mocha with the given setting options.
+ */
+
+mocha.setup = function(opts){
+  if ('string' == typeof opts) opts = { ui: opts };
+  for (var opt in opts) this[opt](opts[opt]);
+  return this;
+};
+
+/**
+ * Run mocha, returning the Runner.
+ */
+
+mocha.run = function(fn){
+  var options = mocha.options;
+  mocha.globals('location');
+
+  var query = Mocha.utils.parseQuery(global.location.search || '');
+  if (query.grep) mocha.grep(query.grep);
+  if (query.invert) mocha.invert();
+
+  return Mocha.prototype.run.call(mocha, function(err){
+    // The DOM Document is not available in Web Workers.
+    var document = global.document;
+    if (document && document.getElementById('mocha') && options.noHighlighting !== true) {
+      Mocha.utils.highlightTags('code');
+    }
+    if (fn) fn(err);
+  });
+};
+
+/**
+ * Expose the process shim.
+ */
+
+Mocha.process = process;
+})();
diff --git a/node_modules/should/node_modules/should-format/tests/browser/tests.js b/node_modules/should/node_modules/should-format/tests/browser/tests.js
new file mode 100644
index 0000000..e2f0751
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/tests/browser/tests.js
@@ -0,0 +1,3771 @@
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+var getType = require('should-type');
+var util = require('./util');
+
+function genKeysFunc(f) {
+  return function(value) {
+    var k = f(value);
+    k.sort();
+    return k;
+  };
+}
+
+
+function Formatter(opts) {
+  opts = opts || {};
+
+  this.seen = [];
+  this.keys = genKeysFunc(opts.keys === false ? Object.getOwnPropertyNames : Object.keys);
+
+  this.maxLineLength = typeof opts.maxLineLength === 'number' ? opts.maxLineLength : 60;
+  this.propSep = opts.propSep || ',';
+
+  this.isUTCdate = !!opts.isUTCdate;
+}
+
+Formatter.prototype = {
+  constructor: Formatter,
+
+  format: function(value) {
+    var t = getType(value);
+    var name1 = t.type, name2 = t.type;
+    if(t.cls) {
+      name1 += '_' + t.cls;
+      name2 += '_' + t.cls;
+    }
+    if(t.sub) {
+      name2 += '_' + t.sub;
+    }
+    var f = this['_format_' + name2] || this['_format_' + name1] || this['_format_' + t.type] || this.defaultFormat;
+    return f.call(this, value).trim();
+  },
+
+  _formatObject: function(value, opts) {
+    opts = opts || {};
+    var mainKeys = opts.keys || this.keys(value);
+
+    var len = 0;
+
+    var formatPropertyValue = opts.formatPropertyValue || this.formatPropertyValue;
+    var formatPropertyName = opts.formatPropertyName || this.formatPropertyName;
+    var keyValueSep = opts.keyValueSep || ': ';
+    var keyFilter = opts.keyFilter || function() { return true; };
+
+    this.seen.push(value);
+    var keys = [];
+
+    mainKeys.forEach(function(key) {
+      if(!keyFilter(key)) return;
+
+      var fName = formatPropertyName.call(this, key);
+
+      var f = (fName ? fName + keyValueSep : '') + formatPropertyValue.call(this, value, key);
+      len += f.length;
+      keys.push(f);
+    }, this);
+    this.seen.pop();
+
+    (opts.additionalProperties || []).forEach(function(keyValue) {
+      var f = keyValue[0] + keyValueSep + this.format(keyValue[1]);
+      len += f.length;
+      keys.push(f);
+    }, this);
+
+    var prefix = opts.prefix || Formatter.constructorName(value) || '';
+    if(prefix.length > 0) prefix += ' ';
+
+    var lbracket, rbracket;
+    if(Array.isArray(opts.brackets)) {
+      lbracket = opts.brackets && opts.brackets[0];
+      rbracket = opts.brackets && opts.brackets[1];
+    } else {
+      lbracket = '{';
+      rbracket = '}';
+    }
+
+    var rootValue = opts.value || '';
+
+    if(keys.length === 0)
+      return rootValue || (prefix + lbracket + rbracket);
+
+    if(len <= this.maxLineLength) {
+      return prefix + lbracket + ' ' + (rootValue ? rootValue + ' ' : '') + keys.join(this.propSep + ' ') + ' ' + rbracket;
+    } else {
+      return prefix + lbracket + '\n' + (rootValue ? '  ' + rootValue + '\n' : '') + keys.map(util.addSpaces).join(this.propSep + '\n') + '\n' + rbracket;
+    }
+  },
+
+  formatObject: function(value, prefix, props) {
+    props = props || this.keys(value);
+
+    var len = 0;
+
+    this.seen.push(value);
+    props = props.map(function(prop) {
+      var f = this.formatProperty(value, prop);
+      len += f.length;
+      return f;
+    }, this);
+    this.seen.pop();
+
+    if(props.length === 0) return '{}';
+
+    if(len <= this.maxLineLength) {
+      return '{ ' + (prefix ? prefix + ' ' : '') + props.join(this.propSep + ' ') + ' }';
+    } else {
+      return '{' + '\n' + (prefix ? '  ' + prefix + '\n' : '') + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
+    }
+  },
+
+  formatPropertyName: function(name) {
+    return name.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/) ? name : this.format(name);
+  },
+
+  formatProperty: function(value, prop) {
+    var desc = Formatter.getPropertyDescriptor(value, prop);
+
+    var propName = this.formatPropertyName(prop);
+
+    var propValue = desc.get && desc.set ?
+      '[Getter/Setter]' : desc.get ?
+      '[Getter]' : desc.set ?
+      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
+      '[Circular]' :
+      this.format(desc.value);
+
+    return propName + ': ' + propValue;
+  },
+
+  formatPropertyValue: function(value, prop) {
+    var desc = Formatter.getPropertyDescriptor(value, prop);
+
+    var propValue = desc.get && desc.set ?
+      '[Getter/Setter]' : desc.get ?
+      '[Getter]' : desc.set ?
+      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
+      '[Circular]' :
+      this.format(desc.value);
+
+    return propValue;
+  }
+};
+
+Formatter.add = function add(type, cls, sub, f) {
+  var args = Array.prototype.slice.call(arguments);
+  f = args.pop();
+  Formatter.prototype['_format_' + args.join('_')] = f;
+};
+
+Formatter.formatObjectWithPrefix = function formatObjectWithPrefix(f) {
+  return function(value) {
+    var prefix = f.call(this, value);
+    var props = this.keys(value);
+    if(props.length == 0) return prefix;
+    else return this.formatObject(value, prefix, props);
+  };
+};
+
+var functionNameRE = /^\s*function\s*(\S*)\s*\(/;
+
+Formatter.functionName = function functionName(f) {
+  if(f.name) {
+    return f.name;
+  }
+  var name = f.toString().match(functionNameRE)[1];
+  return name;
+};
+
+Formatter.constructorName = function(obj) {
+  while (obj) {
+    var descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor');
+    if (descriptor !== undefined &&
+        typeof descriptor.value === 'function') {
+
+        var name = Formatter.functionName(descriptor.value);
+        if(name !== '') {
+          return name;
+        }
+    }
+
+    obj = Object.getPrototypeOf(obj);
+  }
+};
+
+Formatter.getPropertyDescriptor = function(obj, value) {
+  var desc;
+  try {
+    desc = Object.getOwnPropertyDescriptor(obj, value) || {value: obj[value]};
+  } catch(e) {
+    desc = {value: e};
+  }
+  return desc;
+};
+
+Formatter.generateFunctionForIndexedArray = function generateFunctionForIndexedArray(lengthProp, name, padding) {
+  return function(value) {
+    var max = this.byteArrayMaxLength || 50;
+    var length = value[lengthProp];
+    var formattedValues = [];
+    var len = 0;
+    for(var i = 0; i < max && i < length; i++) {
+      var b = value[i] || 0;
+      var v = util.pad0(b.toString(16), padding);
+      len += v.length;
+      formattedValues.push(v);
+    }
+    var prefix = value.constructor.name || name || '';
+    if(prefix) prefix += ' ';
+
+    if(formattedValues.length === 0)
+      return prefix + '[]';
+
+    if(len <= this.maxLineLength) {
+      return prefix + '[ ' + formattedValues.join(this.propSep + ' ') + ' ' + ']';
+    } else {
+      return prefix + '[\n' + formattedValues.map(util.addSpaces).join(this.propSep + '\n') + '\n' + ']';
+    }
+  };
+};
+
+Formatter.add('undefined', function() { return 'undefined' });
+Formatter.add('null', function() { return 'null' });
+Formatter.add('boolean', function(value) { return value ? 'true': 'false' });
+Formatter.add('symbol', function(value) { return value.toString() });
+
+['number', 'boolean'].forEach(function(name) {
+  Formatter.add('object', name, function(value) {
+    return this._formatObject(value, {
+      additionalProperties: [['[[PrimitiveValue]]', value.valueOf()]]
+    });
+  });
+});
+
+Formatter.add('object', 'string', function(value) {
+  var realValue = value.valueOf();
+
+  return this._formatObject(value, {
+    keyFilter: function(key) {
+      //skip useless indexed properties
+      return !(key.match(/\d+/) && parseInt(key, 10) < realValue.length);
+    },
+    additionalProperties: [['[[PrimitiveValue]]', realValue]]
+  });
+});
+
+Formatter.add('object', 'regexp', function(value) {
+  return this._formatObject(value, {
+    value: String(value)
+  });
+});
+
+Formatter.add('number', function(value) {
+  if(value === 0 && 1 / value < 0) return '-0';
+  return String(value);
+});
+
+Formatter.add('string', function(value) {
+  return '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+      .replace(/'/g, "\\'")
+      .replace(/\\"/g, '"') + '\'';
+});
+
+Formatter.add('object', function(value) {
+  return this._formatObject(value);
+});
+
+Formatter.add('object', 'arguments', function(value) {
+  return this._formatObject(value, {
+    prefix: 'Arguments',
+    formatPropertyName: function(key) {
+      if(!key.match(/\d+/)) {
+        return this.formatPropertyName(key);
+      }
+    },
+    brackets: ['[', ']']
+  });
+});
+
+Formatter.add('object', 'array', function(value) {
+  return this._formatObject(value, {
+    formatPropertyName: function(key) {
+      if(!key.match(/\d+/)) {
+        return this.formatPropertyName(key);
+      }
+    },
+    brackets: ['[', ']']
+  });
+});
+
+
+function formatDate(value, isUTC) {
+  var prefix = isUTC ? 'UTC' : '';
+
+  var date = value['get' + prefix + 'FullYear']() +
+    '-' +
+    util.pad0(value['get' + prefix + 'Month']() + 1, 2) +
+    '-' +
+    util.pad0(value['get' + prefix + 'Date'](), 2);
+
+  var time = util.pad0(value['get' + prefix + 'Hours'](), 2) +
+    ':' +
+    util.pad0(value['get' + prefix + 'Minutes'](), 2) +
+    ':' +
+    util.pad0(value['get' + prefix + 'Seconds'](), 2) +
+    '.' +
+    util.pad0(value['get' + prefix + 'Milliseconds'](), 3);
+
+  var to = value.getTimezoneOffset();
+  var absTo = Math.abs(to);
+  var hours = Math.floor(absTo / 60);
+  var minutes = absTo - hours * 60;
+  var tzFormat = (to < 0 ? '+' : '-') + util.pad0(hours, 2) + util.pad0(minutes, 2);
+
+  return date + ' ' + time + (isUTC ? '' : ' ' + tzFormat);
+}
+
+Formatter.add('object', 'date', function(value) {
+  return this._formatObject(value, { value: formatDate(value, this.isUTCdate) });
+});
+
+Formatter.add('function', function(value) {
+  return this._formatObject(value, {
+    additionalProperties: [['name', Formatter.functionName(value)]]
+  });
+});
+
+Formatter.add('object', 'error', function(value) {
+  return this._formatObject(value, {
+    prefix: value.name,
+    additionalProperties: [['message', value.message]]
+  });
+});
+
+Formatter.add('object', 'buffer', Formatter.generateFunctionForIndexedArray('length', 'Buffer', 2));
+
+Formatter.add('object', 'array-buffer', Formatter.generateFunctionForIndexedArray('byteLength', 'ArrayBuffer', 2));
+
+Formatter.add('object', 'typed-array', 'int8', Formatter.generateFunctionForIndexedArray('length', 'Int8Array', 2));
+Formatter.add('object', 'typed-array', 'uint8', Formatter.generateFunctionForIndexedArray('length', 'Uint8Array', 2));
+Formatter.add('object', 'typed-array', 'uint8clamped', Formatter.generateFunctionForIndexedArray('length', 'Uint8ClampedArray', 2));
+
+Formatter.add('object', 'typed-array', 'int16', Formatter.generateFunctionForIndexedArray('length', 'Int16Array', 4));
+Formatter.add('object', 'typed-array', 'uint16', Formatter.generateFunctionForIndexedArray('length', 'Uint16Array', 4));
+
+Formatter.add('object', 'typed-array', 'int32', Formatter.generateFunctionForIndexedArray('length', 'Int32Array', 8));
+Formatter.add('object', 'typed-array', 'uint32', Formatter.generateFunctionForIndexedArray('length', 'Uint32Array', 8));
+
+//TODO add float32 and float64
+
+Formatter.add('object', 'promise', function() {
+  return '[Promise]';//TODO it could be nice to inspect its state and value
+});
+
+Formatter.add('object', 'xhr', function() {
+  return '[XMLHttpRequest]';//TODO it could be nice to inspect its state
+});
+
+Formatter.add('object', 'html-element', function(value) {
+  return value.outerHTML;
+});
+
+Formatter.add('object', 'html-element', '#text', function(value) {
+  return value.nodeValue;
+});
+
+Formatter.add('object', 'html-element', '#document', function(value) {
+  return value.documentElement.outerHTML;
+});
+
+Formatter.add('object', 'host', function() {
+  return '[Host]';
+});
+
+Formatter.add('object', 'set', function(value) {
+  var iter = value.values();
+  var len = 0;
+
+  this.seen.push(value);
+
+  var props = [];
+
+  var next = iter.next();
+  while(!next.done) {
+    var val = next.value;
+    var f = this.format(val);
+    len += f.length;
+    props.push(f);
+
+    next = iter.next();
+  }
+
+  this.seen.pop();
+
+  if(props.length === 0) return 'Set {}';
+
+  if(len <= this.maxLineLength) {
+    return 'Set { ' + props.join(this.propSep + ' ') + ' }';
+  } else {
+    return 'Set {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
+  }
+});
+
+Formatter.add('object', 'map', function(value) {
+  var iter = value.entries();
+  var len = 0;
+
+  this.seen.push(value);
+
+  var props = [];
+
+  var next = iter.next();
+  while(!next.done) {
+    var val = next.value;
+    var fK = this.format(val[0]);
+    var fV = this.format(val[1]);
+
+    var f;
+    if((fK.length + fV.length + 4) <= this.maxLineLength) {
+      f = fK + ' => ' + fV;
+    } else {
+      f = fK + ' =>\n' + fV;
+    }
+
+    len += fK.length + fV.length + 4;
+    props.push(f);
+
+    next = iter.next();
+  }
+
+  this.seen.pop();
+
+  if(props.length === 0) return 'Map {}';
+
+  if(len <= this.maxLineLength) {
+    return 'Map { ' + props.join(this.propSep + ' ') + ' }';
+  } else {
+    return 'Map {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
+  }
+});
+
+Formatter.prototype.defaultFormat = Formatter.prototype._format_object;
+
+function defaultFormat(value, opts) {
+  return new Formatter(opts).format(value);
+}
+
+defaultFormat.Formatter = Formatter;
+module.exports = defaultFormat;
+
+},{"./util":14,"should-type":11}],2:[function(require,module,exports){
+// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
+//
+// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
+//
+// Originally from narwhal.js (http://narwhaljs.org)
+// Copyright (c) 2009 Thomas Robinson <280north.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the 'Software'), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// when used in node, this will actually load the util module we depend on
+// versus loading the builtin util module as happens otherwise
+// this is a bug in node module loading as far as I am concerned
+var util = require('util/');
+
+var pSlice = Array.prototype.slice;
+var hasOwn = Object.prototype.hasOwnProperty;
+
+// 1. The assert module provides functions that throw
+// AssertionError's when particular conditions are not met. The
+// assert module must conform to the following interface.
+
+var assert = module.exports = ok;
+
+// 2. The AssertionError is defined in assert.
+// new assert.AssertionError({ message: message,
+//                             actual: actual,
+//                             expected: expected })
+
+assert.AssertionError = function AssertionError(options) {
+  this.name = 'AssertionError';
+  this.actual = options.actual;
+  this.expected = options.expected;
+  this.operator = options.operator;
+  if (options.message) {
+    this.message = options.message;
+    this.generatedMessage = false;
+  } else {
+    this.message = getMessage(this);
+    this.generatedMessage = true;
+  }
+  var stackStartFunction = options.stackStartFunction || fail;
+
+  if (Error.captureStackTrace) {
+    Error.captureStackTrace(this, stackStartFunction);
+  }
+  else {
+    // non v8 browsers so we can have a stacktrace
+    var err = new Error();
+    if (err.stack) {
+      var out = err.stack;
+
+      // try to strip useless frames
+      var fn_name = stackStartFunction.name;
+      var idx = out.indexOf('\n' + fn_name);
+      if (idx >= 0) {
+        // once we have located the function frame
+        // we need to strip out everything before it (and its line)
+        var next_line = out.indexOf('\n', idx + 1);
+        out = out.substring(next_line + 1);
+      }
+
+      this.stack = out;
+    }
+  }
+};
+
+// assert.AssertionError instanceof Error
+util.inherits(assert.AssertionError, Error);
+
+function replacer(key, value) {
+  if (util.isUndefined(value)) {
+    return '' + value;
+  }
+  if (util.isNumber(value) && !isFinite(value)) {
+    return value.toString();
+  }
+  if (util.isFunction(value) || util.isRegExp(value)) {
+    return value.toString();
+  }
+  return value;
+}
+
+function truncate(s, n) {
+  if (util.isString(s)) {
+    return s.length < n ? s : s.slice(0, n);
+  } else {
+    return s;
+  }
+}
+
+function getMessage(self) {
+  return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
+         self.operator + ' ' +
+         truncate(JSON.stringify(self.expected, replacer), 128);
+}
+
+// At present only the three keys mentioned above are used and
+// understood by the spec. Implementations or sub modules can pass
+// other keys to the AssertionError's constructor - they will be
+// ignored.
+
+// 3. All of the following functions must throw an AssertionError
+// when a corresponding condition is not met, with a message that
+// may be undefined if not provided.  All assertion methods provide
+// both the actual and expected values to the assertion error for
+// display purposes.
+
+function fail(actual, expected, message, operator, stackStartFunction) {
+  throw new assert.AssertionError({
+    message: message,
+    actual: actual,
+    expected: expected,
+    operator: operator,
+    stackStartFunction: stackStartFunction
+  });
+}
+
+// EXTENSION! allows for well behaved errors defined elsewhere.
+assert.fail = fail;
+
+// 4. Pure assertion tests whether a value is truthy, as determined
+// by !!guard.
+// assert.ok(guard, message_opt);
+// This statement is equivalent to assert.equal(true, !!guard,
+// message_opt);. To test strictly for the value true, use
+// assert.strictEqual(true, guard, message_opt);.
+
+function ok(value, message) {
+  if (!value) fail(value, true, message, '==', assert.ok);
+}
+assert.ok = ok;
+
+// 5. The equality assertion tests shallow, coercive equality with
+// ==.
+// assert.equal(actual, expected, message_opt);
+
+assert.equal = function equal(actual, expected, message) {
+  if (actual != expected) fail(actual, expected, message, '==', assert.equal);
+};
+
+// 6. The non-equality assertion tests for whether two objects are not equal
+// with != assert.notEqual(actual, expected, message_opt);
+
+assert.notEqual = function notEqual(actual, expected, message) {
+  if (actual == expected) {
+    fail(actual, expected, message, '!=', assert.notEqual);
+  }
+};
+
+// 7. The equivalence assertion tests a deep equality relation.
+// assert.deepEqual(actual, expected, message_opt);
+
+assert.deepEqual = function deepEqual(actual, expected, message) {
+  if (!_deepEqual(actual, expected)) {
+    fail(actual, expected, message, 'deepEqual', assert.deepEqual);
+  }
+};
+
+function _deepEqual(actual, expected) {
+  // 7.1. All identical values are equivalent, as determined by ===.
+  if (actual === expected) {
+    return true;
+
+  } else if (util.isBuffer(actual) && util.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 (util.isDate(actual) && util.isDate(expected)) {
+    return actual.getTime() === expected.getTime();
+
+  // 7.3 If the expected value is a RegExp object, the actual value is
+  // equivalent if it is also a RegExp object with the same source and
+  // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
+  } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
+    return actual.source === expected.source &&
+           actual.global === expected.global &&
+           actual.multiline === expected.multiline &&
+           actual.lastIndex === expected.lastIndex &&
+           actual.ignoreCase === expected.ignoreCase;
+
+  // 7.4. Other pairs that do not both pass typeof value == 'object',
+  // equivalence is determined by ==.
+  } else if (!util.isObject(actual) && !util.isObject(expected)) {
+    return actual == expected;
+
+  // 7.5 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 isArguments(object) {
+  return Object.prototype.toString.call(object) == '[object Arguments]';
+}
+
+function objEquiv(a, b) {
+  if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
+    return false;
+  // an identical 'prototype' property.
+  if (a.prototype !== b.prototype) return false;
+  // if one is a primitive, the other must be same
+  if (util.isPrimitive(a) || util.isPrimitive(b)) {
+    return a === b;
+  }
+  var aIsArgs = isArguments(a),
+      bIsArgs = isArguments(b);
+  if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
+    return false;
+  if (aIsArgs) {
+    a = pSlice.call(a);
+    b = pSlice.call(b);
+    return _deepEqual(a, b);
+  }
+  var ka = objectKeys(a),
+      kb = objectKeys(b),
+      key, i;
+  // 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;
+}
+
+// 8. The non-equivalence assertion tests for any deep inequality.
+// assert.notDeepEqual(actual, expected, message_opt);
+
+assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
+  if (_deepEqual(actual, expected)) {
+    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
+  }
+};
+
+// 9. The strict equality assertion tests strict equality, as determined by ===.
+// assert.strictEqual(actual, expected, message_opt);
+
+assert.strictEqual = function strictEqual(actual, expected, message) {
+  if (actual !== expected) {
+    fail(actual, expected, message, '===', assert.strictEqual);
+  }
+};
+
+// 10. The strict non-equality assertion tests for strict inequality, as
+// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);
+
+assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
+  if (actual === expected) {
+    fail(actual, expected, message, '!==', assert.notStrictEqual);
+  }
+};
+
+function expectedException(actual, expected) {
+  if (!actual || !expected) {
+    return false;
+  }
+
+  if (Object.prototype.toString.call(expected) == '[object RegExp]') {
+    return expected.test(actual);
+  } else if (actual instanceof expected) {
+    return true;
+  } else if (expected.call({}, actual) === true) {
+    return true;
+  }
+
+  return false;
+}
+
+function _throws(shouldThrow, block, expected, message) {
+  var actual;
+
+  if (util.isString(expected)) {
+    message = expected;
+    expected = null;
+  }
+
+  try {
+    block();
+  } catch (e) {
+    actual = e;
+  }
+
+  message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
+            (message ? ' ' + message : '.');
+
+  if (shouldThrow && !actual) {
+    fail(actual, expected, 'Missing expected exception' + message);
+  }
+
+  if (!shouldThrow && expectedException(actual, expected)) {
+    fail(actual, expected, 'Got unwanted exception' + message);
+  }
+
+  if ((shouldThrow && actual && expected &&
+      !expectedException(actual, expected)) || (!shouldThrow && actual)) {
+    throw actual;
+  }
+}
+
+// 11. Expected to throw an error:
+// assert.throws(block, Error_opt, message_opt);
+
+assert.throws = function(block, /*optional*/error, /*optional*/message) {
+  _throws.apply(this, [true].concat(pSlice.call(arguments)));
+};
+
+// EXTENSION! This is annoying to write outside this module.
+assert.doesNotThrow = function(block, /*optional*/message) {
+  _throws.apply(this, [false].concat(pSlice.call(arguments)));
+};
+
+assert.ifError = function(err) { if (err) {throw err;}};
+
+var objectKeys = Object.keys || function (obj) {
+  var keys = [];
+  for (var key in obj) {
+    if (hasOwn.call(obj, key)) keys.push(key);
+  }
+  return keys;
+};
+
+},{"util/":10}],3:[function(require,module,exports){
+(function (global){
+/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
+ * @license  MIT
+ */
+/* eslint-disable no-proto */
+
+var base64 = require('base64-js')
+var ieee754 = require('ieee754')
+var isArray = require('is-array')
+
+exports.Buffer = Buffer
+exports.SlowBuffer = SlowBuffer
+exports.INSPECT_MAX_BYTES = 50
+Buffer.poolSize = 8192 // not used by this implementation
+
+var rootParent = {}
+
+/**
+ * If `Buffer.TYPED_ARRAY_SUPPORT`:
+ *   === true    Use Uint8Array implementation (fastest)
+ *   === false   Use Object implementation (most compatible, even IE6)
+ *
+ * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
+ * Opera 11.6+, iOS 4.2+.
+ *
+ * Due to various browser bugs, sometimes the Object implementation will be used even
+ * when the browser supports typed arrays.
+ *
+ * Note:
+ *
+ *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
+ *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
+ *
+ *   - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
+ *     on objects.
+ *
+ *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
+ *
+ *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
+ *     incorrect length in some situations.
+
+ * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
+ * get the Object implementation, which is slower but behaves correctly.
+ */
+Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
+  ? global.TYPED_ARRAY_SUPPORT
+  : typedArraySupport()
+
+function typedArraySupport () {
+  function Bar () {}
+  try {
+    var arr = new Uint8Array(1)
+    arr.foo = function () { return 42 }
+    arr.constructor = Bar
+    return arr.foo() === 42 && // typed array instances can be augmented
+        arr.constructor === Bar && // constructor can be set
+        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
+        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
+  } catch (e) {
+    return false
+  }
+}
+
+function kMaxLength () {
+  return Buffer.TYPED_ARRAY_SUPPORT
+    ? 0x7fffffff
+    : 0x3fffffff
+}
+
+/**
+ * Class: Buffer
+ * =============
+ *
+ * The Buffer constructor returns instances of `Uint8Array` that are augmented
+ * with function properties for all the node `Buffer` API functions. We use
+ * `Uint8Array` so that square bracket notation works as expected -- it returns
+ * a single octet.
+ *
+ * By augmenting the instances, we can avoid modifying the `Uint8Array`
+ * prototype.
+ */
+function Buffer (arg) {
+  if (!(this instanceof Buffer)) {
+    // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
+    if (arguments.length > 1) return new Buffer(arg, arguments[1])
+    return new Buffer(arg)
+  }
+
+  this.length = 0
+  this.parent = undefined
+
+  // Common case.
+  if (typeof arg === 'number') {
+    return fromNumber(this, arg)
+  }
+
+  // Slightly less common case.
+  if (typeof arg === 'string') {
+    return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
+  }
+
+  // Unusual.
+  return fromObject(this, arg)
+}
+
+function fromNumber (that, length) {
+  that = allocate(that, length < 0 ? 0 : checked(length) | 0)
+  if (!Buffer.TYPED_ARRAY_SUPPORT) {
+    for (var i = 0; i < length; i++) {
+      that[i] = 0
+    }
+  }
+  return that
+}
+
+function fromString (that, string, encoding) {
+  if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
+
+  // Assumption: byteLength() return value is always < kMaxLength.
+  var length = byteLength(string, encoding) | 0
+  that = allocate(that, length)
+
+  that.write(string, encoding)
+  return that
+}
+
+function fromObject (that, object) {
+  if (Buffer.isBuffer(object)) return fromBuffer(that, object)
+
+  if (isArray(object)) return fromArray(that, object)
+
+  if (object == null) {
+    throw new TypeError('must start with number, buffer, array or string')
+  }
+
+  if (typeof ArrayBuffer !== 'undefined') {
+    if (object.buffer instanceof ArrayBuffer) {
+      return fromTypedArray(that, object)
+    }
+    if (object instanceof ArrayBuffer) {
+      return fromArrayBuffer(that, object)
+    }
+  }
+
+  if (object.length) return fromArrayLike(that, object)
+
+  return fromJsonObject(that, object)
+}
+
+function fromBuffer (that, buffer) {
+  var length = checked(buffer.length) | 0
+  that = allocate(that, length)
+  buffer.copy(that, 0, 0, length)
+  return that
+}
+
+function fromArray (that, array) {
+  var length = checked(array.length) | 0
+  that = allocate(that, length)
+  for (var i = 0; i < length; i += 1) {
+    that[i] = array[i] & 255
+  }
+  return that
+}
+
+// Duplicate of fromArray() to keep fromArray() monomorphic.
+function fromTypedArray (that, array) {
+  var length = checked(array.length) | 0
+  that = allocate(that, length)
+  // Truncating the elements is probably not what people expect from typed
+  // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
+  // of the old Buffer constructor.
+  for (var i = 0; i < length; i += 1) {
+    that[i] = array[i] & 255
+  }
+  return that
+}
+
+function fromArrayBuffer (that, array) {
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    // Return an augmented `Uint8Array` instance, for best performance
+    array.byteLength
+    that = Buffer._augment(new Uint8Array(array))
+  } else {
+    // Fallback: Return an object instance of the Buffer class
+    that = fromTypedArray(that, new Uint8Array(array))
+  }
+  return that
+}
+
+function fromArrayLike (that, array) {
+  var length = checked(array.length) | 0
+  that = allocate(that, length)
+  for (var i = 0; i < length; i += 1) {
+    that[i] = array[i] & 255
+  }
+  return that
+}
+
+// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
+// Returns a zero-length buffer for inputs that don't conform to the spec.
+function fromJsonObject (that, object) {
+  var array
+  var length = 0
+
+  if (object.type === 'Buffer' && isArray(object.data)) {
+    array = object.data
+    length = checked(array.length) | 0
+  }
+  that = allocate(that, length)
+
+  for (var i = 0; i < length; i += 1) {
+    that[i] = array[i] & 255
+  }
+  return that
+}
+
+if (Buffer.TYPED_ARRAY_SUPPORT) {
+  Buffer.prototype.__proto__ = Uint8Array.prototype
+  Buffer.__proto__ = Uint8Array
+}
+
+function allocate (that, length) {
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    // Return an augmented `Uint8Array` instance, for best performance
+    that = Buffer._augment(new Uint8Array(length))
+    that.__proto__ = Buffer.prototype
+  } else {
+    // Fallback: Return an object instance of the Buffer class
+    that.length = length
+    that._isBuffer = true
+  }
+
+  var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
+  if (fromPool) that.parent = rootParent
+
+  return that
+}
+
+function checked (length) {
+  // Note: cannot use `length < kMaxLength` here because that fails when
+  // length is NaN (which is otherwise coerced to zero.)
+  if (length >= kMaxLength()) {
+    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
+                         'size: 0x' + kMaxLength().toString(16) + ' bytes')
+  }
+  return length | 0
+}
+
+function SlowBuffer (subject, encoding) {
+  if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
+
+  var buf = new Buffer(subject, encoding)
+  delete buf.parent
+  return buf
+}
+
+Buffer.isBuffer = function isBuffer (b) {
+  return !!(b != null && b._isBuffer)
+}
+
+Buffer.compare = function compare (a, b) {
+  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
+    throw new TypeError('Arguments must be Buffers')
+  }
+
+  if (a === b) return 0
+
+  var x = a.length
+  var y = b.length
+
+  var i = 0
+  var len = Math.min(x, y)
+  while (i < len) {
+    if (a[i] !== b[i]) break
+
+    ++i
+  }
+
+  if (i !== len) {
+    x = a[i]
+    y = b[i]
+  }
+
+  if (x < y) return -1
+  if (y < x) return 1
+  return 0
+}
+
+Buffer.isEncoding = function isEncoding (encoding) {
+  switch (String(encoding).toLowerCase()) {
+    case 'hex':
+    case 'utf8':
+    case 'utf-8':
+    case 'ascii':
+    case 'binary':
+    case 'base64':
+    case 'raw':
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+      return true
+    default:
+      return false
+  }
+}
+
+Buffer.concat = function concat (list, length) {
+  if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
+
+  if (list.length === 0) {
+    return new Buffer(0)
+  }
+
+  var i
+  if (length === undefined) {
+    length = 0
+    for (i = 0; i < list.length; i++) {
+      length += list[i].length
+    }
+  }
+
+  var buf = new Buffer(length)
+  var pos = 0
+  for (i = 0; i < list.length; i++) {
+    var item = list[i]
+    item.copy(buf, pos)
+    pos += item.length
+  }
+  return buf
+}
+
+function byteLength (string, encoding) {
+  if (typeof string !== 'string') string = '' + string
+
+  var len = string.length
+  if (len === 0) return 0
+
+  // Use a for loop to avoid recursion
+  var loweredCase = false
+  for (;;) {
+    switch (encoding) {
+      case 'ascii':
+      case 'binary':
+      // Deprecated
+      case 'raw':
+      case 'raws':
+        return len
+      case 'utf8':
+      case 'utf-8':
+        return utf8ToBytes(string).length
+      case 'ucs2':
+      case 'ucs-2':
+      case 'utf16le':
+      case 'utf-16le':
+        return len * 2
+      case 'hex':
+        return len >>> 1
+      case 'base64':
+        return base64ToBytes(string).length
+      default:
+        if (loweredCase) return utf8ToBytes(string).length // assume utf8
+        encoding = ('' + encoding).toLowerCase()
+        loweredCase = true
+    }
+  }
+}
+Buffer.byteLength = byteLength
+
+// pre-set for values that may exist in the future
+Buffer.prototype.length = undefined
+Buffer.prototype.parent = undefined
+
+function slowToString (encoding, start, end) {
+  var loweredCase = false
+
+  start = start | 0
+  end = end === undefined || end === Infinity ? this.length : end | 0
+
+  if (!encoding) encoding = 'utf8'
+  if (start < 0) start = 0
+  if (end > this.length) end = this.length
+  if (end <= start) return ''
+
+  while (true) {
+    switch (encoding) {
+      case 'hex':
+        return hexSlice(this, start, end)
+
+      case 'utf8':
+      case 'utf-8':
+        return utf8Slice(this, start, end)
+
+      case 'ascii':
+        return asciiSlice(this, start, end)
+
+      case 'binary':
+        return binarySlice(this, start, end)
+
+      case 'base64':
+        return base64Slice(this, start, end)
+
+      case 'ucs2':
+      case 'ucs-2':
+      case 'utf16le':
+      case 'utf-16le':
+        return utf16leSlice(this, start, end)
+
+      default:
+        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+        encoding = (encoding + '').toLowerCase()
+        loweredCase = true
+    }
+  }
+}
+
+Buffer.prototype.toString = function toString () {
+  var length = this.length | 0
+  if (length === 0) return ''
+  if (arguments.length === 0) return utf8Slice(this, 0, length)
+  return slowToString.apply(this, arguments)
+}
+
+Buffer.prototype.equals = function equals (b) {
+  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
+  if (this === b) return true
+  return Buffer.compare(this, b) === 0
+}
+
+Buffer.prototype.inspect = function inspect () {
+  var str = ''
+  var max = exports.INSPECT_MAX_BYTES
+  if (this.length > 0) {
+    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
+    if (this.length > max) str += ' ... '
+  }
+  return '<Buffer ' + str + '>'
+}
+
+Buffer.prototype.compare = function compare (b) {
+  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
+  if (this === b) return 0
+  return Buffer.compare(this, b)
+}
+
+Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
+  if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
+  else if (byteOffset < -0x80000000) byteOffset = -0x80000000
+  byteOffset >>= 0
+
+  if (this.length === 0) return -1
+  if (byteOffset >= this.length) return -1
+
+  // Negative offsets start from the end of the buffer
+  if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
+
+  if (typeof val === 'string') {
+    if (val.length === 0) return -1 // special case: looking for empty string always fails
+    return String.prototype.indexOf.call(this, val, byteOffset)
+  }
+  if (Buffer.isBuffer(val)) {
+    return arrayIndexOf(this, val, byteOffset)
+  }
+  if (typeof val === 'number') {
+    if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
+      return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
+    }
+    return arrayIndexOf(this, [ val ], byteOffset)
+  }
+
+  function arrayIndexOf (arr, val, byteOffset) {
+    var foundIndex = -1
+    for (var i = 0; byteOffset + i < arr.length; i++) {
+      if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
+        if (foundIndex === -1) foundIndex = i
+        if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
+      } else {
+        foundIndex = -1
+      }
+    }
+    return -1
+  }
+
+  throw new TypeError('val must be string, number or Buffer')
+}
+
+// `get` is deprecated
+Buffer.prototype.get = function get (offset) {
+  console.log('.get() is deprecated. Access using array indexes instead.')
+  return this.readUInt8(offset)
+}
+
+// `set` is deprecated
+Buffer.prototype.set = function set (v, offset) {
+  console.log('.set() is deprecated. Access using array indexes instead.')
+  return this.writeUInt8(v, offset)
+}
+
+function hexWrite (buf, string, offset, length) {
+  offset = Number(offset) || 0
+  var remaining = buf.length - offset
+  if (!length) {
+    length = remaining
+  } else {
+    length = Number(length)
+    if (length > remaining) {
+      length = remaining
+    }
+  }
+
+  // must be an even number of digits
+  var strLen = string.length
+  if (strLen % 2 !== 0) throw new Error('Invalid hex string')
+
+  if (length > strLen / 2) {
+    length = strLen / 2
+  }
+  for (var i = 0; i < length; i++) {
+    var parsed = parseInt(string.substr(i * 2, 2), 16)
+    if (isNaN(parsed)) throw new Error('Invalid hex string')
+    buf[offset + i] = parsed
+  }
+  return i
+}
+
+function utf8Write (buf, string, offset, length) {
+  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
+}
+
+function asciiWrite (buf, string, offset, length) {
+  return blitBuffer(asciiToBytes(string), buf, offset, length)
+}
+
+function binaryWrite (buf, string, offset, length) {
+  return asciiWrite(buf, string, offset, length)
+}
+
+function base64Write (buf, string, offset, length) {
+  return blitBuffer(base64ToBytes(string), buf, offset, length)
+}
+
+function ucs2Write (buf, string, offset, length) {
+  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
+}
+
+Buffer.prototype.write = function write (string, offset, length, encoding) {
+  // Buffer#write(string)
+  if (offset === undefined) {
+    encoding = 'utf8'
+    length = this.length
+    offset = 0
+  // Buffer#write(string, encoding)
+  } else if (length === undefined && typeof offset === 'string') {
+    encoding = offset
+    length = this.length
+    offset = 0
+  // Buffer#write(string, offset[, length][, encoding])
+  } else if (isFinite(offset)) {
+    offset = offset | 0
+    if (isFinite(length)) {
+      length = length | 0
+      if (encoding === undefined) encoding = 'utf8'
+    } else {
+      encoding = length
+      length = undefined
+    }
+  // legacy write(string, encoding, offset, length) - remove in v0.13
+  } else {
+    var swap = encoding
+    encoding = offset
+    offset = length | 0
+    length = swap
+  }
+
+  var remaining = this.length - offset
+  if (length === undefined || length > remaining) length = remaining
+
+  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
+    throw new RangeError('attempt to write outside buffer bounds')
+  }
+
+  if (!encoding) encoding = 'utf8'
+
+  var loweredCase = false
+  for (;;) {
+    switch (encoding) {
+      case 'hex':
+        return hexWrite(this, string, offset, length)
+
+      case 'utf8':
+      case 'utf-8':
+        return utf8Write(this, string, offset, length)
+
+      case 'ascii':
+        return asciiWrite(this, string, offset, length)
+
+      case 'binary':
+        return binaryWrite(this, string, offset, length)
+
+      case 'base64':
+        // Warning: maxLength not taken into account in base64Write
+        return base64Write(this, string, offset, length)
+
+      case 'ucs2':
+      case 'ucs-2':
+      case 'utf16le':
+      case 'utf-16le':
+        return ucs2Write(this, string, offset, length)
+
+      default:
+        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+        encoding = ('' + encoding).toLowerCase()
+        loweredCase = true
+    }
+  }
+}
+
+Buffer.prototype.toJSON = function toJSON () {
+  return {
+    type: 'Buffer',
+    data: Array.prototype.slice.call(this._arr || this, 0)
+  }
+}
+
+function base64Slice (buf, start, end) {
+  if (start === 0 && end === buf.length) {
+    return base64.fromByteArray(buf)
+  } else {
+    return base64.fromByteArray(buf.slice(start, end))
+  }
+}
+
+function utf8Slice (buf, start, end) {
+  end = Math.min(buf.length, end)
+  var res = []
+
+  var i = start
+  while (i < end) {
+    var firstByte = buf[i]
+    var codePoint = null
+    var bytesPerSequence = (firstByte > 0xEF) ? 4
+      : (firstByte > 0xDF) ? 3
+      : (firstByte > 0xBF) ? 2
+      : 1
+
+    if (i + bytesPerSequence <= end) {
+      var secondByte, thirdByte, fourthByte, tempCodePoint
+
+      switch (bytesPerSequence) {
+        case 1:
+          if (firstByte < 0x80) {
+            codePoint = firstByte
+          }
+          break
+        case 2:
+          secondByte = buf[i + 1]
+          if ((secondByte & 0xC0) === 0x80) {
+            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
+            if (tempCodePoint > 0x7F) {
+              codePoint = tempCodePoint
+            }
+          }
+          break
+        case 3:
+          secondByte = buf[i + 1]
+          thirdByte = buf[i + 2]
+          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
+            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
+            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
+              codePoint = tempCodePoint
+            }
+          }
+          break
+        case 4:
+          secondByte = buf[i + 1]
+          thirdByte = buf[i + 2]
+          fourthByte = buf[i + 3]
+          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
+            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
+            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
+              codePoint = tempCodePoint
+            }
+          }
+      }
+    }
+
+    if (codePoint === null) {
+      // we did not generate a valid codePoint so insert a
+      // replacement char (U+FFFD) and advance only 1 byte
+      codePoint = 0xFFFD
+      bytesPerSequence = 1
+    } else if (codePoint > 0xFFFF) {
+      // encode to utf16 (surrogate pair dance)
+      codePoint -= 0x10000
+      res.push(codePoint >>> 10 & 0x3FF | 0xD800)
+      codePoint = 0xDC00 | codePoint & 0x3FF
+    }
+
+    res.push(codePoint)
+    i += bytesPerSequence
+  }
+
+  return decodeCodePointsArray(res)
+}
+
+// Based on http://stackoverflow.com/a/22747272/680742, the browser with
+// the lowest limit is Chrome, with 0x10000 args.
+// We go 1 magnitude less, for safety
+var MAX_ARGUMENTS_LENGTH = 0x1000
+
+function decodeCodePointsArray (codePoints) {
+  var len = codePoints.length
+  if (len <= MAX_ARGUMENTS_LENGTH) {
+    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
+  }
+
+  // Decode in chunks to avoid "call stack size exceeded".
+  var res = ''
+  var i = 0
+  while (i < len) {
+    res += String.fromCharCode.apply(
+      String,
+      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
+    )
+  }
+  return res
+}
+
+function asciiSlice (buf, start, end) {
+  var ret = ''
+  end = Math.min(buf.length, end)
+
+  for (var i = start; i < end; i++) {
+    ret += String.fromCharCode(buf[i] & 0x7F)
+  }
+  return ret
+}
+
+function binarySlice (buf, start, end) {
+  var ret = ''
+  end = Math.min(buf.length, end)
+
+  for (var i = start; i < end; i++) {
+    ret += String.fromCharCode(buf[i])
+  }
+  return ret
+}
+
+function hexSlice (buf, start, end) {
+  var len = buf.length
+
+  if (!start || start < 0) start = 0
+  if (!end || end < 0 || end > len) end = len
+
+  var out = ''
+  for (var i = start; i < end; i++) {
+    out += toHex(buf[i])
+  }
+  return out
+}
+
+function utf16leSlice (buf, start, end) {
+  var bytes = buf.slice(start, end)
+  var res = ''
+  for (var i = 0; i < bytes.length; i += 2) {
+    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
+  }
+  return res
+}
+
+Buffer.prototype.slice = function slice (start, end) {
+  var len = this.length
+  start = ~~start
+  end = end === undefined ? len : ~~end
+
+  if (start < 0) {
+    start += len
+    if (start < 0) start = 0
+  } else if (start > len) {
+    start = len
+  }
+
+  if (end < 0) {
+    end += len
+    if (end < 0) end = 0
+  } else if (end > len) {
+    end = len
+  }
+
+  if (end < start) end = start
+
+  var newBuf
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    newBuf = Buffer._augment(this.subarray(start, end))
+  } else {
+    var sliceLen = end - start
+    newBuf = new Buffer(sliceLen, undefined)
+    for (var i = 0; i < sliceLen; i++) {
+      newBuf[i] = this[i + start]
+    }
+  }
+
+  if (newBuf.length) newBuf.parent = this.parent || this
+
+  return newBuf
+}
+
+/*
+ * Need to make sure that buffer isn't trying to write out of bounds.
+ */
+function checkOffset (offset, ext, length) {
+  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
+  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
+}
+
+Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+  var val = this[offset]
+  var mul = 1
+  var i = 0
+  while (++i < byteLength && (mul *= 0x100)) {
+    val += this[offset + i] * mul
+  }
+
+  return val
+}
+
+Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) {
+    checkOffset(offset, byteLength, this.length)
+  }
+
+  var val = this[offset + --byteLength]
+  var mul = 1
+  while (byteLength > 0 && (mul *= 0x100)) {
+    val += this[offset + --byteLength] * mul
+  }
+
+  return val
+}
+
+Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 1, this.length)
+  return this[offset]
+}
+
+Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 2, this.length)
+  return this[offset] | (this[offset + 1] << 8)
+}
+
+Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 2, this.length)
+  return (this[offset] << 8) | this[offset + 1]
+}
+
+Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+
+  return ((this[offset]) |
+      (this[offset + 1] << 8) |
+      (this[offset + 2] << 16)) +
+      (this[offset + 3] * 0x1000000)
+}
+
+Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+
+  return (this[offset] * 0x1000000) +
+    ((this[offset + 1] << 16) |
+    (this[offset + 2] << 8) |
+    this[offset + 3])
+}
+
+Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+  var val = this[offset]
+  var mul = 1
+  var i = 0
+  while (++i < byteLength && (mul *= 0x100)) {
+    val += this[offset + i] * mul
+  }
+  mul *= 0x80
+
+  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+  return val
+}
+
+Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+  var i = byteLength
+  var mul = 1
+  var val = this[offset + --i]
+  while (i > 0 && (mul *= 0x100)) {
+    val += this[offset + --i] * mul
+  }
+  mul *= 0x80
+
+  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+  return val
+}
+
+Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 1, this.length)
+  if (!(this[offset] & 0x80)) return (this[offset])
+  return ((0xff - this[offset] + 1) * -1)
+}
+
+Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 2, this.length)
+  var val = this[offset] | (this[offset + 1] << 8)
+  return (val & 0x8000) ? val | 0xFFFF0000 : val
+}
+
+Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 2, this.length)
+  var val = this[offset + 1] | (this[offset] << 8)
+  return (val & 0x8000) ? val | 0xFFFF0000 : val
+}
+
+Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+
+  return (this[offset]) |
+    (this[offset + 1] << 8) |
+    (this[offset + 2] << 16) |
+    (this[offset + 3] << 24)
+}
+
+Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+
+  return (this[offset] << 24) |
+    (this[offset + 1] << 16) |
+    (this[offset + 2] << 8) |
+    (this[offset + 3])
+}
+
+Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+  return ieee754.read(this, offset, true, 23, 4)
+}
+
+Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+  return ieee754.read(this, offset, false, 23, 4)
+}
+
+Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 8, this.length)
+  return ieee754.read(this, offset, true, 52, 8)
+}
+
+Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 8, this.length)
+  return ieee754.read(this, offset, false, 52, 8)
+}
+
+function checkInt (buf, value, offset, ext, max, min) {
+  if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
+  if (value > max || value < min) throw new RangeError('value is out of bounds')
+  if (offset + ext > buf.length) throw new RangeError('index out of range')
+}
+
+Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
+  value = +value
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
+
+  var mul = 1
+  var i = 0
+  this[offset] = value & 0xFF
+  while (++i < byteLength && (mul *= 0x100)) {
+    this[offset + i] = (value / mul) & 0xFF
+  }
+
+  return offset + byteLength
+}
+
+Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
+  value = +value
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
+
+  var i = byteLength - 1
+  var mul = 1
+  this[offset + i] = value & 0xFF
+  while (--i >= 0 && (mul *= 0x100)) {
+    this[offset + i] = (value / mul) & 0xFF
+  }
+
+  return offset + byteLength
+}
+
+Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
+  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
+  this[offset] = (value & 0xff)
+  return offset + 1
+}
+
+function objectWriteUInt16 (buf, value, offset, littleEndian) {
+  if (value < 0) value = 0xffff + value + 1
+  for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
+    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
+      (littleEndian ? i : 1 - i) * 8
+  }
+}
+
+Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value & 0xff)
+    this[offset + 1] = (value >>> 8)
+  } else {
+    objectWriteUInt16(this, value, offset, true)
+  }
+  return offset + 2
+}
+
+Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value >>> 8)
+    this[offset + 1] = (value & 0xff)
+  } else {
+    objectWriteUInt16(this, value, offset, false)
+  }
+  return offset + 2
+}
+
+function objectWriteUInt32 (buf, value, offset, littleEndian) {
+  if (value < 0) value = 0xffffffff + value + 1
+  for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
+    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
+  }
+}
+
+Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset + 3] = (value >>> 24)
+    this[offset + 2] = (value >>> 16)
+    this[offset + 1] = (value >>> 8)
+    this[offset] = (value & 0xff)
+  } else {
+    objectWriteUInt32(this, value, offset, true)
+  }
+  return offset + 4
+}
+
+Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value >>> 24)
+    this[offset + 1] = (value >>> 16)
+    this[offset + 2] = (value >>> 8)
+    this[offset + 3] = (value & 0xff)
+  } else {
+    objectWriteUInt32(this, value, offset, false)
+  }
+  return offset + 4
+}
+
+Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) {
+    var limit = Math.pow(2, 8 * byteLength - 1)
+
+    checkInt(this, value, offset, byteLength, limit - 1, -limit)
+  }
+
+  var i = 0
+  var mul = 1
+  var sub = value < 0 ? 1 : 0
+  this[offset] = value & 0xFF
+  while (++i < byteLength && (mul *= 0x100)) {
+    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+  }
+
+  return offset + byteLength
+}
+
+Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) {
+    var limit = Math.pow(2, 8 * byteLength - 1)
+
+    checkInt(this, value, offset, byteLength, limit - 1, -limit)
+  }
+
+  var i = byteLength - 1
+  var mul = 1
+  var sub = value < 0 ? 1 : 0
+  this[offset + i] = value & 0xFF
+  while (--i >= 0 && (mul *= 0x100)) {
+    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+  }
+
+  return offset + byteLength
+}
+
+Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
+  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
+  if (value < 0) value = 0xff + value + 1
+  this[offset] = (value & 0xff)
+  return offset + 1
+}
+
+Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value & 0xff)
+    this[offset + 1] = (value >>> 8)
+  } else {
+    objectWriteUInt16(this, value, offset, true)
+  }
+  return offset + 2
+}
+
+Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value >>> 8)
+    this[offset + 1] = (value & 0xff)
+  } else {
+    objectWriteUInt16(this, value, offset, false)
+  }
+  return offset + 2
+}
+
+Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value & 0xff)
+    this[offset + 1] = (value >>> 8)
+    this[offset + 2] = (value >>> 16)
+    this[offset + 3] = (value >>> 24)
+  } else {
+    objectWriteUInt32(this, value, offset, true)
+  }
+  return offset + 4
+}
+
+Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+  if (value < 0) value = 0xffffffff + value + 1
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value >>> 24)
+    this[offset + 1] = (value >>> 16)
+    this[offset + 2] = (value >>> 8)
+    this[offset + 3] = (value & 0xff)
+  } else {
+    objectWriteUInt32(this, value, offset, false)
+  }
+  return offset + 4
+}
+
+function checkIEEE754 (buf, value, offset, ext, max, min) {
+  if (value > max || value < min) throw new RangeError('value is out of bounds')
+  if (offset + ext > buf.length) throw new RangeError('index out of range')
+  if (offset < 0) throw new RangeError('index out of range')
+}
+
+function writeFloat (buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
+  }
+  ieee754.write(buf, value, offset, littleEndian, 23, 4)
+  return offset + 4
+}
+
+Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
+  return writeFloat(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
+  return writeFloat(this, value, offset, false, noAssert)
+}
+
+function writeDouble (buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
+  }
+  ieee754.write(buf, value, offset, littleEndian, 52, 8)
+  return offset + 8
+}
+
+Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
+  return writeDouble(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
+  return writeDouble(this, value, offset, false, noAssert)
+}
+
+// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
+Buffer.prototype.copy = function copy (target, targetStart, start, end) {
+  if (!start) start = 0
+  if (!end && end !== 0) end = this.length
+  if (targetStart >= target.length) targetStart = target.length
+  if (!targetStart) targetStart = 0
+  if (end > 0 && end < start) end = start
+
+  // Copy 0 bytes; we're done
+  if (end === start) return 0
+  if (target.length === 0 || this.length === 0) return 0
+
+  // Fatal error conditions
+  if (targetStart < 0) {
+    throw new RangeError('targetStart out of bounds')
+  }
+  if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
+  if (end < 0) throw new RangeError('sourceEnd out of bounds')
+
+  // Are we oob?
+  if (end > this.length) end = this.length
+  if (target.length - targetStart < end - start) {
+    end = target.length - targetStart + start
+  }
+
+  var len = end - start
+  var i
+
+  if (this === target && start < targetStart && targetStart < end) {
+    // descending copy from end
+    for (i = len - 1; i >= 0; i--) {
+      target[i + targetStart] = this[i + start]
+    }
+  } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
+    // ascending copy from start
+    for (i = 0; i < len; i++) {
+      target[i + targetStart] = this[i + start]
+    }
+  } else {
+    target._set(this.subarray(start, start + len), targetStart)
+  }
+
+  return len
+}
+
+// fill(value, start=0, end=buffer.length)
+Buffer.prototype.fill = function fill (value, start, end) {
+  if (!value) value = 0
+  if (!start) start = 0
+  if (!end) end = this.length
+
+  if (end < start) throw new RangeError('end < start')
+
+  // Fill 0 bytes; we're done
+  if (end === start) return
+  if (this.length === 0) return
+
+  if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
+  if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
+
+  var i
+  if (typeof value === 'number') {
+    for (i = start; i < end; i++) {
+      this[i] = value
+    }
+  } else {
+    var bytes = utf8ToBytes(value.toString())
+    var len = bytes.length
+    for (i = start; i < end; i++) {
+      this[i] = bytes[i % len]
+    }
+  }
+
+  return this
+}
+
+/**
+ * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
+ * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
+ */
+Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
+  if (typeof Uint8Array !== 'undefined') {
+    if (Buffer.TYPED_ARRAY_SUPPORT) {
+      return (new Buffer(this)).buffer
+    } else {
+      var buf = new Uint8Array(this.length)
+      for (var i = 0, len = buf.length; i < len; i += 1) {
+        buf[i] = this[i]
+      }
+      return buf.buffer
+    }
+  } else {
+    throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
+  }
+}
+
+// HELPER FUNCTIONS
+// ================
+
+var BP = Buffer.prototype
+
+/**
+ * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
+ */
+Buffer._augment = function _augment (arr) {
+  arr.constructor = Buffer
+  arr._isBuffer = true
+
+  // save reference to original Uint8Array set method before overwriting
+  arr._set = arr.set
+
+  // deprecated
+  arr.get = BP.get
+  arr.set = BP.set
+
+  arr.write = BP.write
+  arr.toString = BP.toString
+  arr.toLocaleString = BP.toString
+  arr.toJSON = BP.toJSON
+  arr.equals = BP.equals
+  arr.compare = BP.compare
+  arr.indexOf = BP.indexOf
+  arr.copy = BP.copy
+  arr.slice = BP.slice
+  arr.readUIntLE = BP.readUIntLE
+  arr.readUIntBE = BP.readUIntBE
+  arr.readUInt8 = BP.readUInt8
+  arr.readUInt16LE = BP.readUInt16LE
+  arr.readUInt16BE = BP.readUInt16BE
+  arr.readUInt32LE = BP.readUInt32LE
+  arr.readUInt32BE = BP.readUInt32BE
+  arr.readIntLE = BP.readIntLE
+  arr.readIntBE = BP.readIntBE
+  arr.readInt8 = BP.readInt8
+  arr.readInt16LE = BP.readInt16LE
+  arr.readInt16BE = BP.readInt16BE
+  arr.readInt32LE = BP.readInt32LE
+  arr.readInt32BE = BP.readInt32BE
+  arr.readFloatLE = BP.readFloatLE
+  arr.readFloatBE = BP.readFloatBE
+  arr.readDoubleLE = BP.readDoubleLE
+  arr.readDoubleBE = BP.readDoubleBE
+  arr.writeUInt8 = BP.writeUInt8
+  arr.writeUIntLE = BP.writeUIntLE
+  arr.writeUIntBE = BP.writeUIntBE
+  arr.writeUInt16LE = BP.writeUInt16LE
+  arr.writeUInt16BE = BP.writeUInt16BE
+  arr.writeUInt32LE = BP.writeUInt32LE
+  arr.writeUInt32BE = BP.writeUInt32BE
+  arr.writeIntLE = BP.writeIntLE
+  arr.writeIntBE = BP.writeIntBE
+  arr.writeInt8 = BP.writeInt8
+  arr.writeInt16LE = BP.writeInt16LE
+  arr.writeInt16BE = BP.writeInt16BE
+  arr.writeInt32LE = BP.writeInt32LE
+  arr.writeInt32BE = BP.writeInt32BE
+  arr.writeFloatLE = BP.writeFloatLE
+  arr.writeFloatBE = BP.writeFloatBE
+  arr.writeDoubleLE = BP.writeDoubleLE
+  arr.writeDoubleBE = BP.writeDoubleBE
+  arr.fill = BP.fill
+  arr.inspect = BP.inspect
+  arr.toArrayBuffer = BP.toArrayBuffer
+
+  return arr
+}
+
+var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
+
+function base64clean (str) {
+  // Node strips out invalid characters like \n and \t from the string, base64-js does not
+  str = stringtrim(str).replace(INVALID_BASE64_RE, '')
+  // Node converts strings with length < 2 to ''
+  if (str.length < 2) return ''
+  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
+  while (str.length % 4 !== 0) {
+    str = str + '='
+  }
+  return str
+}
+
+function stringtrim (str) {
+  if (str.trim) return str.trim()
+  return str.replace(/^\s+|\s+$/g, '')
+}
+
+function toHex (n) {
+  if (n < 16) return '0' + n.toString(16)
+  return n.toString(16)
+}
+
+function utf8ToBytes (string, units) {
+  units = units || Infinity
+  var codePoint
+  var length = string.length
+  var leadSurrogate = null
+  var bytes = []
+
+  for (var i = 0; i < length; i++) {
+    codePoint = string.charCodeAt(i)
+
+    // is surrogate component
+    if (codePoint > 0xD7FF && codePoint < 0xE000) {
+      // last char was a lead
+      if (!leadSurrogate) {
+        // no lead yet
+        if (codePoint > 0xDBFF) {
+          // unexpected trail
+          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+          continue
+        } else if (i + 1 === length) {
+          // unpaired lead
+          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+          continue
+        }
+
+        // valid lead
+        leadSurrogate = codePoint
+
+        continue
+      }
+
+      // 2 leads in a row
+      if (codePoint < 0xDC00) {
+        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+        leadSurrogate = codePoint
+        continue
+      }
+
+      // valid surrogate pair
+      codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
+    } else if (leadSurrogate) {
+      // valid bmp char, but last char was a lead
+      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+    }
+
+    leadSurrogate = null
+
+    // encode utf8
+    if (codePoint < 0x80) {
+      if ((units -= 1) < 0) break
+      bytes.push(codePoint)
+    } else if (codePoint < 0x800) {
+      if ((units -= 2) < 0) break
+      bytes.push(
+        codePoint >> 0x6 | 0xC0,
+        codePoint & 0x3F | 0x80
+      )
+    } else if (codePoint < 0x10000) {
+      if ((units -= 3) < 0) break
+      bytes.push(
+        codePoint >> 0xC | 0xE0,
+        codePoint >> 0x6 & 0x3F | 0x80,
+        codePoint & 0x3F | 0x80
+      )
+    } else if (codePoint < 0x110000) {
+      if ((units -= 4) < 0) break
+      bytes.push(
+        codePoint >> 0x12 | 0xF0,
+        codePoint >> 0xC & 0x3F | 0x80,
+        codePoint >> 0x6 & 0x3F | 0x80,
+        codePoint & 0x3F | 0x80
+      )
+    } else {
+      throw new Error('Invalid code point')
+    }
+  }
+
+  return bytes
+}
+
+function asciiToBytes (str) {
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    // Node's code seems to be doing this and not & 0x7F..
+    byteArray.push(str.charCodeAt(i) & 0xFF)
+  }
+  return byteArray
+}
+
+function utf16leToBytes (str, units) {
+  var c, hi, lo
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    if ((units -= 2) < 0) break
+
+    c = str.charCodeAt(i)
+    hi = c >> 8
+    lo = c % 256
+    byteArray.push(lo)
+    byteArray.push(hi)
+  }
+
+  return byteArray
+}
+
+function base64ToBytes (str) {
+  return base64.toByteArray(base64clean(str))
+}
+
+function blitBuffer (src, dst, offset, length) {
+  for (var i = 0; i < length; i++) {
+    if ((i + offset >= dst.length) || (i >= src.length)) break
+    dst[i + offset] = src[i]
+  }
+  return i
+}
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"base64-js":4,"ieee754":5,"is-array":6}],4:[function(require,module,exports){
+var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+
+;(function (exports) {
+	'use strict';
+
+  var Arr = (typeof Uint8Array !== 'undefined')
+    ? Uint8Array
+    : Array
+
+	var PLUS   = '+'.charCodeAt(0)
+	var SLASH  = '/'.charCodeAt(0)
+	var NUMBER = '0'.charCodeAt(0)
+	var LOWER  = 'a'.charCodeAt(0)
+	var UPPER  = 'A'.charCodeAt(0)
+	var PLUS_URL_SAFE = '-'.charCodeAt(0)
+	var SLASH_URL_SAFE = '_'.charCodeAt(0)
+
+	function decode (elt) {
+		var code = elt.charCodeAt(0)
+		if (code === PLUS ||
+		    code === PLUS_URL_SAFE)
+			return 62 // '+'
+		if (code === SLASH ||
+		    code === SLASH_URL_SAFE)
+			return 63 // '/'
+		if (code < NUMBER)
+			return -1 //no match
+		if (code < NUMBER + 10)
+			return code - NUMBER + 26 + 26
+		if (code < UPPER + 26)
+			return code - UPPER
+		if (code < LOWER + 26)
+			return code - LOWER + 26
+	}
+
+	function b64ToByteArray (b64) {
+		var i, j, l, tmp, placeHolders, arr
+
+		if (b64.length % 4 > 0) {
+			throw new Error('Invalid string. Length must be a multiple of 4')
+		}
+
+		// the number of equal signs (place holders)
+		// if there are two placeholders, than the two characters before it
+		// represent one byte
+		// if there is only one, then the three characters before it represent 2 bytes
+		// this is just a cheap hack to not do indexOf twice
+		var len = b64.length
+		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
+
+		// base64 is 4/3 + up to two characters of the original data
+		arr = new Arr(b64.length * 3 / 4 - placeHolders)
+
+		// if there are placeholders, only get up to the last complete 4 chars
+		l = placeHolders > 0 ? b64.length - 4 : b64.length
+
+		var L = 0
+
+		function push (v) {
+			arr[L++] = v
+		}
+
+		for (i = 0, j = 0; i < l; i += 4, j += 3) {
+			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
+			push((tmp & 0xFF0000) >> 16)
+			push((tmp & 0xFF00) >> 8)
+			push(tmp & 0xFF)
+		}
+
+		if (placeHolders === 2) {
+			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
+			push(tmp & 0xFF)
+		} else if (placeHolders === 1) {
+			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
+			push((tmp >> 8) & 0xFF)
+			push(tmp & 0xFF)
+		}
+
+		return arr
+	}
+
+	function uint8ToBase64 (uint8) {
+		var i,
+			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
+			output = "",
+			temp, length
+
+		function encode (num) {
+			return lookup.charAt(num)
+		}
+
+		function tripletToBase64 (num) {
+			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
+		}
+
+		// go through the array every three bytes, we'll deal with trailing stuff later
+		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
+			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
+			output += tripletToBase64(temp)
+		}
+
+		// pad the end with zeros, but make sure to not forget the extra bytes
+		switch (extraBytes) {
+			case 1:
+				temp = uint8[uint8.length - 1]
+				output += encode(temp >> 2)
+				output += encode((temp << 4) & 0x3F)
+				output += '=='
+				break
+			case 2:
+				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
+				output += encode(temp >> 10)
+				output += encode((temp >> 4) & 0x3F)
+				output += encode((temp << 2) & 0x3F)
+				output += '='
+				break
+		}
+
+		return output
+	}
+
+	exports.toByteArray = b64ToByteArray
+	exports.fromByteArray = uint8ToBase64
+}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
+
+},{}],5:[function(require,module,exports){
+exports.read = function (buffer, offset, isLE, mLen, nBytes) {
+  var e, m
+  var eLen = nBytes * 8 - mLen - 1
+  var eMax = (1 << eLen) - 1
+  var eBias = eMax >> 1
+  var nBits = -7
+  var i = isLE ? (nBytes - 1) : 0
+  var d = isLE ? -1 : 1
+  var s = buffer[offset + i]
+
+  i += d
+
+  e = s & ((1 << (-nBits)) - 1)
+  s >>= (-nBits)
+  nBits += eLen
+  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
+
+  m = e & ((1 << (-nBits)) - 1)
+  e >>= (-nBits)
+  nBits += mLen
+  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
+
+  if (e === 0) {
+    e = 1 - eBias
+  } else if (e === eMax) {
+    return m ? NaN : ((s ? -1 : 1) * Infinity)
+  } else {
+    m = m + Math.pow(2, mLen)
+    e = e - eBias
+  }
+  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
+}
+
+exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
+  var e, m, c
+  var eLen = nBytes * 8 - mLen - 1
+  var eMax = (1 << eLen) - 1
+  var eBias = eMax >> 1
+  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
+  var i = isLE ? 0 : (nBytes - 1)
+  var d = isLE ? 1 : -1
+  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
+
+  value = Math.abs(value)
+
+  if (isNaN(value) || value === Infinity) {
+    m = isNaN(value) ? 1 : 0
+    e = eMax
+  } else {
+    e = Math.floor(Math.log(value) / Math.LN2)
+    if (value * (c = Math.pow(2, -e)) < 1) {
+      e--
+      c *= 2
+    }
+    if (e + eBias >= 1) {
+      value += rt / c
+    } else {
+      value += rt * Math.pow(2, 1 - eBias)
+    }
+    if (value * c >= 2) {
+      e++
+      c /= 2
+    }
+
+    if (e + eBias >= eMax) {
+      m = 0
+      e = eMax
+    } else if (e + eBias >= 1) {
+      m = (value * c - 1) * Math.pow(2, mLen)
+      e = e + eBias
+    } else {
+      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
+      e = 0
+    }
+  }
+
+  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
+
+  e = (e << mLen) | m
+  eLen += mLen
+  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
+
+  buffer[offset + i - d] |= s * 128
+}
+
+},{}],6:[function(require,module,exports){
+
+/**
+ * isArray
+ */
+
+var isArray = Array.isArray;
+
+/**
+ * toString
+ */
+
+var str = Object.prototype.toString;
+
+/**
+ * Whether or not the given `val`
+ * is an array.
+ *
+ * example:
+ *
+ *        isArray([]);
+ *        // > true
+ *        isArray(arguments);
+ *        // > false
+ *        isArray('');
+ *        // > false
+ *
+ * @param {mixed} val
+ * @return {bool}
+ */
+
+module.exports = isArray || function (val) {
+  return !! val && '[object Array]' == str.call(val);
+};
+
+},{}],7:[function(require,module,exports){
+if (typeof Object.create === 'function') {
+  // implementation from standard node.js 'util' module
+  module.exports = function inherits(ctor, superCtor) {
+    ctor.super_ = superCtor
+    ctor.prototype = Object.create(superCtor.prototype, {
+      constructor: {
+        value: ctor,
+        enumerable: false,
+        writable: true,
+        configurable: true
+      }
+    });
+  };
+} else {
+  // old school shim for old browsers
+  module.exports = function inherits(ctor, superCtor) {
+    ctor.super_ = superCtor
+    var TempCtor = function () {}
+    TempCtor.prototype = superCtor.prototype
+    ctor.prototype = new TempCtor()
+    ctor.prototype.constructor = ctor
+  }
+}
+
+},{}],8:[function(require,module,exports){
+// shim for using process in browser
+
+var process = module.exports = {};
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+    draining = false;
+    if (currentQueue.length) {
+        queue = currentQueue.concat(queue);
+    } else {
+        queueIndex = -1;
+    }
+    if (queue.length) {
+        drainQueue();
+    }
+}
+
+function drainQueue() {
+    if (draining) {
+        return;
+    }
+    var timeout = setTimeout(cleanUpNextTick);
+    draining = true;
+
+    var len = queue.length;
+    while(len) {
+        currentQueue = queue;
+        queue = [];
+        while (++queueIndex < len) {
+            if (currentQueue) {
+                currentQueue[queueIndex].run();
+            }
+        }
+        queueIndex = -1;
+        len = queue.length;
+    }
+    currentQueue = null;
+    draining = false;
+    clearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+    var args = new Array(arguments.length - 1);
+    if (arguments.length > 1) {
+        for (var i = 1; i < arguments.length; i++) {
+            args[i - 1] = arguments[i];
+        }
+    }
+    queue.push(new Item(fun, args));
+    if (queue.length === 1 && !draining) {
+        setTimeout(drainQueue, 0);
+    }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+    this.fun = fun;
+    this.array = array;
+}
+Item.prototype.run = function () {
+    this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+
+process.binding = function (name) {
+    throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+    throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],9:[function(require,module,exports){
+module.exports = function isBuffer(arg) {
+  return arg && typeof arg === 'object'
+    && typeof arg.copy === 'function'
+    && typeof arg.fill === 'function'
+    && typeof arg.readUInt8 === 'function';
+}
+},{}],10:[function(require,module,exports){
+(function (process,global){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var formatRegExp = /%[sdj%]/g;
+exports.format = function(f) {
+  if (!isString(f)) {
+    var objects = [];
+    for (var i = 0; i < arguments.length; i++) {
+      objects.push(inspect(arguments[i]));
+    }
+    return objects.join(' ');
+  }
+
+  var i = 1;
+  var args = arguments;
+  var len = args.length;
+  var str = String(f).replace(formatRegExp, function(x) {
+    if (x === '%%') return '%';
+    if (i >= len) return x;
+    switch (x) {
+      case '%s': return String(args[i++]);
+      case '%d': return Number(args[i++]);
+      case '%j':
+        try {
+          return JSON.stringify(args[i++]);
+        } catch (_) {
+          return '[Circular]';
+        }
+      default:
+        return x;
+    }
+  });
+  for (var x = args[i]; i < len; x = args[++i]) {
+    if (isNull(x) || !isObject(x)) {
+      str += ' ' + x;
+    } else {
+      str += ' ' + inspect(x);
+    }
+  }
+  return str;
+};
+
+
+// Mark that a method should not be used.
+// Returns a modified function which warns once by default.
+// If --no-deprecation is set, then it is a no-op.
+exports.deprecate = function(fn, msg) {
+  // Allow for deprecating things in the process of starting up.
+  if (isUndefined(global.process)) {
+    return function() {
+      return exports.deprecate(fn, msg).apply(this, arguments);
+    };
+  }
+
+  if (process.noDeprecation === true) {
+    return fn;
+  }
+
+  var warned = false;
+  function deprecated() {
+    if (!warned) {
+      if (process.throwDeprecation) {
+        throw new Error(msg);
+      } else if (process.traceDeprecation) {
+        console.trace(msg);
+      } else {
+        console.error(msg);
+      }
+      warned = true;
+    }
+    return fn.apply(this, arguments);
+  }
+
+  return deprecated;
+};
+
+
+var debugs = {};
+var debugEnviron;
+exports.debuglog = function(set) {
+  if (isUndefined(debugEnviron))
+    debugEnviron = process.env.NODE_DEBUG || '';
+  set = set.toUpperCase();
+  if (!debugs[set]) {
+    if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
+      var pid = process.pid;
+      debugs[set] = function() {
+        var msg = exports.format.apply(exports, arguments);
+        console.error('%s %d: %s', set, pid, msg);
+      };
+    } else {
+      debugs[set] = function() {};
+    }
+  }
+  return debugs[set];
+};
+
+
+/**
+ * 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 {Object} opts Optional options object that alters the output.
+ */
+/* legacy: obj, showHidden, depth, colors*/
+function inspect(obj, opts) {
+  // default options
+  var ctx = {
+    seen: [],
+    stylize: stylizeNoColor
+  };
+  // legacy...
+  if (arguments.length >= 3) ctx.depth = arguments[2];
+  if (arguments.length >= 4) ctx.colors = arguments[3];
+  if (isBoolean(opts)) {
+    // legacy...
+    ctx.showHidden = opts;
+  } else if (opts) {
+    // got an "options" object
+    exports._extend(ctx, opts);
+  }
+  // set default options
+  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
+  if (isUndefined(ctx.depth)) ctx.depth = 2;
+  if (isUndefined(ctx.colors)) ctx.colors = false;
+  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
+  if (ctx.colors) ctx.stylize = stylizeWithColor;
+  return formatValue(ctx, obj, ctx.depth);
+}
+exports.inspect = inspect;
+
+
+// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
+inspect.colors = {
+  'bold' : [1, 22],
+  'italic' : [3, 23],
+  'underline' : [4, 24],
+  'inverse' : [7, 27],
+  'white' : [37, 39],
+  'grey' : [90, 39],
+  'black' : [30, 39],
+  'blue' : [34, 39],
+  'cyan' : [36, 39],
+  'green' : [32, 39],
+  'magenta' : [35, 39],
+  'red' : [31, 39],
+  'yellow' : [33, 39]
+};
+
+// Don't use 'blue' not visible on cmd.exe
+inspect.styles = {
+  'special': 'cyan',
+  'number': 'yellow',
+  'boolean': 'yellow',
+  'undefined': 'grey',
+  'null': 'bold',
+  'string': 'green',
+  'date': 'magenta',
+  // "name": intentionally not styling
+  'regexp': 'red'
+};
+
+
+function stylizeWithColor(str, styleType) {
+  var style = inspect.styles[styleType];
+
+  if (style) {
+    return '\u001b[' + inspect.colors[style][0] + 'm' + str +
+           '\u001b[' + inspect.colors[style][1] + 'm';
+  } else {
+    return str;
+  }
+}
+
+
+function stylizeNoColor(str, styleType) {
+  return str;
+}
+
+
+function arrayToHash(array) {
+  var hash = {};
+
+  array.forEach(function(val, idx) {
+    hash[val] = true;
+  });
+
+  return hash;
+}
+
+
+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 (ctx.customInspect &&
+      value &&
+      isFunction(value.inspect) &&
+      // Filter out the util module, it's inspect function is special
+      value.inspect !== exports.inspect &&
+      // Also filter out any prototype objects using the circular check.
+      !(value.constructor && value.constructor.prototype === value)) {
+    var ret = value.inspect(recurseTimes, ctx);
+    if (!isString(ret)) {
+      ret = formatValue(ctx, ret, recurseTimes);
+    }
+    return ret;
+  }
+
+  // Primitive types cannot have properties
+  var primitive = formatPrimitive(ctx, value);
+  if (primitive) {
+    return primitive;
+  }
+
+  // Look up the keys of the object.
+  var keys = Object.keys(value);
+  var visibleKeys = arrayToHash(keys);
+
+  if (ctx.showHidden) {
+    keys = Object.getOwnPropertyNames(value);
+  }
+
+  // IE doesn't make error fields non-enumerable
+  // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
+  if (isError(value)
+      && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
+    return formatError(value);
+  }
+
+  // Some type of object without properties can be shortcutted.
+  if (keys.length === 0) {
+    if (isFunction(value)) {
+      var name = value.name ? ': ' + value.name : '';
+      return ctx.stylize('[Function' + name + ']', 'special');
+    }
+    if (isRegExp(value)) {
+      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+    }
+    if (isDate(value)) {
+      return ctx.stylize(Date.prototype.toString.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 (isFunction(value)) {
+    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)) {
+    base = ' ' + 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) {
+  if (isUndefined(value))
+    return ctx.stylize('undefined', 'undefined');
+  if (isString(value)) {
+    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+                                             .replace(/'/g, "\\'")
+                                             .replace(/\\"/g, '"') + '\'';
+    return ctx.stylize(simple, 'string');
+  }
+  if (isNumber(value))
+    return ctx.stylize('' + value, 'number');
+  if (isBoolean(value))
+    return ctx.stylize('' + value, 'boolean');
+  // For some reason typeof null is "object", so special case here.
+  if (isNull(value))
+    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 (hasOwnProperty(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, desc;
+  desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
+  if (desc.get) {
+    if (desc.set) {
+      str = ctx.stylize('[Getter/Setter]', 'special');
+    } else {
+      str = ctx.stylize('[Getter]', 'special');
+    }
+  } else {
+    if (desc.set) {
+      str = ctx.stylize('[Setter]', 'special');
+    }
+  }
+  if (!hasOwnProperty(visibleKeys, key)) {
+    name = '[' + key + ']';
+  }
+  if (!str) {
+    if (ctx.seen.indexOf(desc.value) < 0) {
+      if (isNull(recurseTimes)) {
+        str = formatValue(ctx, desc.value, null);
+      } else {
+        str = formatValue(ctx, desc.value, 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 (isUndefined(name)) {
+    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.replace(/\u001b\[\d\d?m/g, '').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];
+}
+
+
+// NOTE: These type checking functions intentionally don't use `instanceof`
+// because it is fragile and can be easily faked with `Object.create()`.
+function isArray(ar) {
+  return Array.isArray(ar);
+}
+exports.isArray = isArray;
+
+function isBoolean(arg) {
+  return typeof arg === 'boolean';
+}
+exports.isBoolean = isBoolean;
+
+function isNull(arg) {
+  return arg === null;
+}
+exports.isNull = isNull;
+
+function isNullOrUndefined(arg) {
+  return arg == null;
+}
+exports.isNullOrUndefined = isNullOrUndefined;
+
+function isNumber(arg) {
+  return typeof arg === 'number';
+}
+exports.isNumber = isNumber;
+
+function isString(arg) {
+  return typeof arg === 'string';
+}
+exports.isString = isString;
+
+function isSymbol(arg) {
+  return typeof arg === 'symbol';
+}
+exports.isSymbol = isSymbol;
+
+function isUndefined(arg) {
+  return arg === void 0;
+}
+exports.isUndefined = isUndefined;
+
+function isRegExp(re) {
+  return isObject(re) && objectToString(re) === '[object RegExp]';
+}
+exports.isRegExp = isRegExp;
+
+function isObject(arg) {
+  return typeof arg === 'object' && arg !== null;
+}
+exports.isObject = isObject;
+
+function isDate(d) {
+  return isObject(d) && objectToString(d) === '[object Date]';
+}
+exports.isDate = isDate;
+
+function isError(e) {
+  return isObject(e) &&
+      (objectToString(e) === '[object Error]' || e instanceof Error);
+}
+exports.isError = isError;
+
+function isFunction(arg) {
+  return typeof arg === 'function';
+}
+exports.isFunction = isFunction;
+
+function isPrimitive(arg) {
+  return arg === null ||
+         typeof arg === 'boolean' ||
+         typeof arg === 'number' ||
+         typeof arg === 'string' ||
+         typeof arg === 'symbol' ||  // ES6 symbol
+         typeof arg === 'undefined';
+}
+exports.isPrimitive = isPrimitive;
+
+exports.isBuffer = require('./support/isBuffer');
+
+function objectToString(o) {
+  return Object.prototype.toString.call(o);
+}
+
+
+function pad(n) {
+  return n < 10 ? '0' + n.toString(10) : n.toString(10);
+}
+
+
+var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
+              'Oct', 'Nov', 'Dec'];
+
+// 26 Feb 16:19:34
+function timestamp() {
+  var d = new Date();
+  var time = [pad(d.getHours()),
+              pad(d.getMinutes()),
+              pad(d.getSeconds())].join(':');
+  return [d.getDate(), months[d.getMonth()], time].join(' ');
+}
+
+
+// log is just a thin wrapper to console.log that prepends a timestamp
+exports.log = function() {
+  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
+};
+
+
+/**
+ * Inherit the prototype methods from one constructor into another.
+ *
+ * The Function.prototype.inherits from lang.js rewritten as a standalone
+ * function (not on Function.prototype). NOTE: If this file is to be loaded
+ * during bootstrapping this function needs to be rewritten using some native
+ * functions as prototype setup using normal JavaScript does not work as
+ * expected during bootstrapping (see mirror.js in r114903).
+ *
+ * @param {function} ctor Constructor function which needs to inherit the
+ *     prototype.
+ * @param {function} superCtor Constructor function to inherit prototype from.
+ */
+exports.inherits = require('inherits');
+
+exports._extend = function(origin, add) {
+  // Don't do anything if add isn't an object
+  if (!add || !isObject(add)) return origin;
+
+  var keys = Object.keys(add);
+  var i = keys.length;
+  while (i--) {
+    origin[keys[i]] = add[keys[i]];
+  }
+  return origin;
+};
+
+function hasOwnProperty(obj, prop) {
+  return Object.prototype.hasOwnProperty.call(obj, prop);
+}
+
+}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"./support/isBuffer":9,"_process":8,"inherits":7}],11:[function(require,module,exports){
+(function (Buffer){
+var toString = Object.prototype.toString;
+
+var types = require('./types');
+
+/**
+ * Simple data function to store type information
+ * @param {string} type Usually what is returned from typeof
+ * @param {string} cls  Sanitized @Class via Object.prototype.toString
+ * @param {string} sub  If type and cls the same, and need to specify somehow
+ * @private
+ * @example
+ *
+ * //for null
+ * new Type('null');
+ *
+ * //for Date
+ * new Type('object', 'date');
+ *
+ * //for Uint8Array
+ *
+ * new Type('object', 'typed-array', 'uint8');
+ */
+function Type(type, cls, sub) {
+  this.type = type;
+  this.cls = cls;
+  this.sub = sub;
+}
+
+/**
+ * Function to store type checks
+ * @private
+ */
+function TypeChecker() {
+  this.checks = [];
+}
+
+TypeChecker.prototype = {
+  add: function(func) {
+    this.checks.push(func);
+    return this;
+  },
+
+  addTypeOf: function(type, res) {
+    return this.add(function(obj, tpeOf) {
+      if(tpeOf === type) {
+        return new Type(res);
+      }
+    });
+  },
+
+  addClass: function(cls, res, sub) {
+    return this.add(function(obj, tpeOf, objCls) {
+      if(objCls === cls) {
+        return new Type(types.OBJECT, res, sub);
+      }
+    });
+  },
+
+  getType: function(obj) {
+    var typeOf = typeof obj;
+    var cls = toString.call(obj);
+
+    for(var i = 0, l = this.checks.length; i < l; i++) {
+      var res = this.checks[i].call(this, obj, typeOf, cls);
+      if(typeof res !== 'undefined') return res;
+    }
+
+  }
+};
+
+var main = new TypeChecker();
+
+//TODO add iterators
+
+main
+  .addTypeOf(types.NUMBER, types.NUMBER)
+  .addTypeOf(types.UNDEFINED, types.UNDEFINED)
+  .addTypeOf(types.STRING, types.STRING)
+  .addTypeOf(types.BOOLEAN, types.BOOLEAN)
+  .addTypeOf(types.FUNCTION, types.FUNCTION)
+  .addTypeOf(types.SYMBOL, types.SYMBOL)
+  .add(function(obj, tpeOf) {
+    if(obj === null) return new Type(types.NULL);
+  })
+  .addClass('[object String]', types.STRING)
+  .addClass('[object Boolean]', types.BOOLEAN)
+  .addClass('[object Number]', types.NUMBER)
+  .addClass('[object Array]', types.ARRAY)
+  .addClass('[object RegExp]', types.REGEXP)
+  .addClass('[object Error]', types.ERROR)
+  .addClass('[object Date]', types.DATE)
+  .addClass('[object Arguments]', types.ARGUMENTS)
+  .addClass('[object Math]')
+  .addClass('[object JSON]')
+  .addClass('[object ArrayBuffer]', types.ARRAY_BUFFER)
+  .addClass('[object Int8Array]', types.TYPED_ARRAY, 'int8')
+  .addClass('[object Uint8Array]', types.TYPED_ARRAY, 'uint8')
+  .addClass('[object Uint8ClampedArray]', types.TYPED_ARRAY, 'uint8clamped')
+  .addClass('[object Int16Array]', types.TYPED_ARRAY, 'int16')
+  .addClass('[object Uint16Array]', types.TYPED_ARRAY, 'uint16')
+  .addClass('[object Int32Array]', types.TYPED_ARRAY, 'int32')
+  .addClass('[object Uint32Array]', types.TYPED_ARRAY, 'uint32')
+  .addClass('[object Float32Array]', types.TYPED_ARRAY, 'float32')
+  .addClass('[object Float64Array]', types.TYPED_ARRAY, 'float64')
+  .addClass('[object DataView]', types.DATA_VIEW)
+  .addClass('[object Map]', types.MAP)
+  .addClass('[object WeakMap]', types.WEAK_MAP)
+  .addClass('[object Set]', types.SET)
+  .addClass('[object WeakSet]', types.WEAK_SET)
+  .addClass('[object Promise]', types.PROMISE)
+  .addClass('[object Blob]', types.BLOB)
+  .addClass('[object File]', types.FILE)
+  .addClass('[object FileList]', types.FILE_LIST)
+  .addClass('[object XMLHttpRequest]', types.XHR)
+  .add(function(obj) {
+    if((typeof Promise === types.FUNCTION && obj instanceof Promise) ||
+        (typeof obj.then === types.FUNCTION)) {
+          return new Type(types.OBJECT, types.PROMISE);
+        }
+  })
+  .add(function(obj) {
+    if(typeof Buffer !== 'undefined' && obj instanceof Buffer) {
+      return new Type(types.OBJECT, types.BUFFER);
+    }
+  })
+  .add(function(obj) {
+    if(typeof Node !== 'undefined' && obj instanceof Node) {
+      return new Type(types.OBJECT, types.HTML_ELEMENT, obj.nodeName);
+    }
+  })
+  .add(function(obj) {
+    // probably at the begginging should be enough these checks
+    if(obj.Boolean === Boolean && obj.Number === Number && obj.String === String && obj.Date === Date) {
+      return new Type(types.OBJECT, types.HOST);
+    }
+  })
+  .add(function() {
+    return new Type(types.OBJECT);
+  });
+
+/**
+ * Get type information of anything
+ *
+ * @param  {any} obj Anything that could require type information
+ * @return {Type}    type info
+ */
+function getGlobalType(obj) {
+  return main.getType(obj);
+}
+
+getGlobalType.checker = main;
+getGlobalType.TypeChecker = TypeChecker;
+getGlobalType.Type = Type;
+
+Object.keys(types).forEach(function(typeName) {
+  getGlobalType[typeName] = types[typeName];
+});
+
+module.exports = getGlobalType;
+
+}).call(this,require("buffer").Buffer)
+},{"./types":12,"buffer":3}],12:[function(require,module,exports){
+var types = {
+  NUMBER: 'number',
+  UNDEFINED: 'undefined',
+  STRING: 'string',
+  BOOLEAN: 'boolean',
+  OBJECT: 'object',
+  FUNCTION: 'function',
+  NULL: 'null',
+  ARRAY: 'array',
+  REGEXP: 'regexp',
+  DATE: 'date',
+  ERROR: 'error',
+  ARGUMENTS: 'arguments',
+  SYMBOL: 'symbol',
+  ARRAY_BUFFER: 'array-buffer',
+  TYPED_ARRAY: 'typed-array',
+  DATA_VIEW: 'data-view',
+  MAP: 'map',
+  SET: 'set',
+  WEAK_SET: 'weak-set',
+  WEAK_MAP: 'weak-map',
+  PROMISE: 'promise',
+
+// node buffer
+  BUFFER: 'buffer',
+
+// dom html element
+  HTML_ELEMENT: 'html-element',
+  HTML_ELEMENT_TEXT: 'html-element-text',
+  DOCUMENT: 'document',
+  WINDOW: 'window',
+  FILE: 'file',
+  FILE_LIST: 'file-list',
+  BLOB: 'blob',
+
+  HOST: 'host',
+
+  XHR: 'xhr'
+};
+
+module.exports = types;
+
+},{}],13:[function(require,module,exports){
+(function (Buffer){
+/*eslint-env mocha*/
+
+var assert = require('assert');
+
+var format = require('../');
+
+it('should format numbers', function() {
+  assert.equal(format(10), '10');
+  assert.equal(format(0.1e-5), '0.000001');
+  assert.equal(format(-0), '-0');
+  assert.equal(format(Infinity), 'Infinity');
+  assert.equal(format(-Infinity), '-Infinity');
+  assert.equal(format(NaN), 'NaN');
+});
+
+it('should format undefined', function() {
+  assert.equal(format(undefined), 'undefined');
+  assert.equal(format(void 0), 'undefined');
+});
+
+it('should format null', function() {
+  assert.equal(format(null), 'null');
+});
+
+it('should format string', function() {
+  assert.equal(format('abc'), "'abc'");
+  assert.equal(format('abc" \' '), "'abc\" \\' '");
+});
+
+it('should format boolean', function() {
+  assert.equal(format(true), 'true');
+  assert.equal(format(false), 'false');
+});
+
+it('should format Symbols', function() {
+  if(typeof Symbol != 'undefined' && Symbol.for) {
+    assert.equal(format(Symbol.for('react.element')), 'Symbol(react.element)')
+  }
+})
+
+it('should format primitive wrappers', function() {
+  assert.equal(format(new Number(10)), 'Number { [[PrimitiveValue]]: 10 }');
+  assert.equal(format(new Boolean(true)), 'Boolean { [[PrimitiveValue]]: true }');
+  assert.equal(format(new String('abc')), 'String { [[PrimitiveValue]]: \'abc\' }');
+});
+
+it('should format primitive wrappers with keys', function() {
+  var b = new Boolean(true);
+  b.abc = 10;
+  assert.equal(format(b), 'Boolean { abc: 10, [[PrimitiveValue]]: true }');
+
+  var s = new String('abc');
+  s.abc = 10;
+  assert.equal(format(s), 'String { abc: 10, [[PrimitiveValue]]: \'abc\' }');
+});
+
+it('should format regex', function() {
+  assert.equal(format(/abc/gi), '/abc/gi');
+  assert.equal(format(new RegExp('abc', 'gi')), '/abc/gi');
+});
+
+it('should format regex with keys', function() {
+  var r = /abc/gi;
+  r.abc = 10;
+  assert.equal(format(r), 'RegExp { /abc/gi abc: 10 }');
+});
+
+function fff() {
+}
+
+it('should format function', function() {
+  var f = function() {
+  };
+  assert.equal(format(f), 'Function { name: \'\' }');
+
+  assert.equal(format(fff), 'Function { name: \'fff\' }');
+});
+
+var getter = Object.create(null, {
+  a: {
+    get: function() {
+      return 'aaa';
+    }
+  }
+});
+var setter = Object.create(null, {
+  b: {
+    set: function() {
+    }
+  }
+});
+var getterAndSetter = Object.create(null, {
+  c: {
+    get: function() {
+      return 'ccc';
+    },
+    set: function() {
+    }
+  }
+});
+
+it('should format object', function() {
+  assert.equal(format({a: 10, b: '10', '123': 'asd'}), "Object { '123': 'asd', a: 10, b: '10' }");
+
+  assert.equal(format(getter, {keys: false}), '{ a: [Getter] }');
+  assert.equal(format(setter, {keys: false}), '{ b: [Setter] }');
+  assert.equal(format(getterAndSetter, {keys: false}), '{ c: [Getter/Setter] }');
+
+  var obj = {a: 10};
+  obj.b = obj;
+  assert.equal(format(obj), 'Object { a: 10, b: [Circular] }');
+
+  var w = {
+    '\\': 1,
+    '\\\\': 2,
+    '\\\\\\': 3,
+    '\\\\\\\\': 4
+  };
+
+  var y = ['a', 'b', 'c'];
+  y['\\\\\\'] = 'd';
+
+  assert.ok(format(w),
+    'Object { \'\\\': 1, \'\\\\\': 2, \'\\\\\\\': 3, \'\\\\\\\\\': 4 }');
+  assert.ok(format(y), '[ \'a\', \'b\', \'c\', \'\\\\\\\': \'d\' ]');
+});
+
+it('should format arguments', function() {
+  var f = function() {
+    return arguments;
+  };
+  assert.equal(format(f(1, 2, 3)), 'Arguments [ 1, 2, 3 ]');
+});
+
+it('should format arrays', function() {
+  assert.equal(format([1, 2, 'abc']), 'Array [ 1, 2, \'abc\' ]');
+});
+
+it('should format node buffer', function() {
+  if(typeof Buffer !== 'undefined') {
+    var b = new Buffer('abc');
+    assert.equal(format(b), 'Buffer [ 61, 62, 63 ]');
+  }
+});
+
+it('should format typed arrays', function() {
+  if(typeof ArrayBuffer != 'undefined') {
+    var buffer = new ArrayBuffer(8);
+    for(var i = 0; i < buffer.byteLength; i++) buffer[i] = 0x00;
+    buffer[1] = 0x20;
+    buffer[2] = 0x2;
+    assert.equal(format(buffer), 'ArrayBuffer [ 00, 20, 02, 00, 00, 00, 00, 00 ]');
+
+    var int8 = new Int8Array(3);
+    int8[0] = 0x20;
+    int8[1] = 0x2;
+    assert.equal(format(int8), 'Int8Array [ 20, 02, 00 ]');
+
+    var int16 = new Int16Array(3);
+    int16[0] = 0x201;
+    int16[1] = 0x2;
+    assert.equal(format(int16), 'Int16Array [ 0201, 0002, 0000 ]');
+
+    //var dataView = new DataView(buffer);
+    //assert.equal(format(dataView), '[DataView: 00 20 02 00 00 00 00 00]');
+  }
+});
+
+it('should format html elements', function() {
+  if(typeof window != 'undefined' && typeof document != 'undefined') {
+    var btn = document.createElement("BUTTON");
+    var t = document.createTextNode("CLICK ME");
+    btn.appendChild(t);
+
+    assert.equal(format(btn), '<button>CLICK ME</button>');
+
+    assert.equal(format(t), 'CLICK ME');
+  }
+});
+
+it('should correctly indent', function() {
+  assert.equal(format({ a: { b: 'abc' }, d: 'abc'}, { maxLineLength: 0 }), 'Object {\n  a: Object {\n    b: \'abc\'\n  },\n  d: \'abc\'\n}');
+});
+
+it('should format set', function() {
+  if(typeof Set !== 'undefined') {
+    assert.equal(format(new Set([1, 2, { a: 10}, 'abc'])),
+      'Set { 1, 2, Object { a: 10 }, \'abc\' }');
+    assert.equal(format(new Set([1, 2, { a: 10}, 'abc']), { maxLineLength: 0 }),
+      'Set {\n  1,\n  2,\n  Object {\n    a: 10\n  },\n  \'abc\'\n}');
+  }
+});
+
+it('should format map', function() {
+  if(typeof Map !== 'undefined') {
+    assert.equal(format(new Map([[1, 2], [2, 'abc'], [{ a: 10}, new Set()], ['abc', null]])),
+      'Map { 1 => 2, 2 => \'abc\', Object { a: 10 } => Set {}, \'abc\' => null }');
+    assert.equal(format(new Map([[1, 2], [2, 'abc'], [{ a: 10}, new Set()], ['abc', null]]), { maxLineLength: 10 }),
+      'Map {\n  1 => 2,\n  2 => \'abc\',\n  Object { a: 10 } =>\n  Set {},\n  \'abc\' =>\n  null\n}');
+  }
+});
+
+}).call(this,require("buffer").Buffer)
+},{"../":1,"assert":2,"buffer":3}],14:[function(require,module,exports){
+function addSpaces(v) {
+  return v.split('\n').map(function(vv) { return '  ' + vv; }).join('\n');
+}
+
+function pad(str, value, filler) {
+  str = String(str)
+  var isRight = false;
+
+  if(value < 0) {
+    isRight = true;
+    value = -value;
+  }
+
+  if(str.length < value) {
+    var padding = new Array(value - str.length + 1).join(filler);
+    return isRight ? str + padding : padding + str;
+  } else{
+    return str;
+  }
+}
+
+module.exports = {
+  addSpaces: addSpaces,
+  pad: pad,
+  pad0: function(str, value) {
+    return pad(str, value, '0');
+  }
+};
+
+},{}]},{},[13]);
diff --git a/node_modules/should/node_modules/should-format/tests/test.js b/node_modules/should/node_modules/should-format/tests/test.js
new file mode 100644
index 0000000..78e8c33
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/tests/test.js
@@ -0,0 +1,201 @@
+/*eslint-env mocha*/
+
+var assert = require('assert');
+
+var format = require('../');
+
+it('should format numbers', function() {
+  assert.equal(format(10), '10');
+  assert.equal(format(0.1e-5), '0.000001');
+  assert.equal(format(-0), '-0');
+  assert.equal(format(Infinity), 'Infinity');
+  assert.equal(format(-Infinity), '-Infinity');
+  assert.equal(format(NaN), 'NaN');
+});
+
+it('should format undefined', function() {
+  assert.equal(format(undefined), 'undefined');
+  assert.equal(format(void 0), 'undefined');
+});
+
+it('should format null', function() {
+  assert.equal(format(null), 'null');
+});
+
+it('should format string', function() {
+  assert.equal(format('abc'), "'abc'");
+  assert.equal(format('abc" \' '), "'abc\" \\' '");
+});
+
+it('should format boolean', function() {
+  assert.equal(format(true), 'true');
+  assert.equal(format(false), 'false');
+});
+
+it('should format Symbols', function() {
+  if(typeof Symbol != 'undefined' && Symbol.for) {
+    assert.equal(format(Symbol.for('react.element')), 'Symbol(react.element)')
+  }
+})
+
+it('should format primitive wrappers', function() {
+  assert.equal(format(new Number(10)), 'Number { [[PrimitiveValue]]: 10 }');
+  assert.equal(format(new Boolean(true)), 'Boolean { [[PrimitiveValue]]: true }');
+  assert.equal(format(new String('abc')), 'String { [[PrimitiveValue]]: \'abc\' }');
+});
+
+it('should format primitive wrappers with keys', function() {
+  var b = new Boolean(true);
+  b.abc = 10;
+  assert.equal(format(b), 'Boolean { abc: 10, [[PrimitiveValue]]: true }');
+
+  var s = new String('abc');
+  s.abc = 10;
+  assert.equal(format(s), 'String { abc: 10, [[PrimitiveValue]]: \'abc\' }');
+});
+
+it('should format regex', function() {
+  assert.equal(format(/abc/gi), '/abc/gi');
+  assert.equal(format(new RegExp('abc', 'gi')), '/abc/gi');
+});
+
+it('should format regex with keys', function() {
+  var r = /abc/gi;
+  r.abc = 10;
+  assert.equal(format(r), 'RegExp { /abc/gi abc: 10 }');
+});
+
+function fff() {
+}
+
+it('should format function', function() {
+  var f = function() {
+  };
+  assert.equal(format(f), 'Function { name: \'\' }');
+
+  assert.equal(format(fff), 'Function { name: \'fff\' }');
+});
+
+var getter = Object.create(null, {
+  a: {
+    get: function() {
+      return 'aaa';
+    }
+  }
+});
+var setter = Object.create(null, {
+  b: {
+    set: function() {
+    }
+  }
+});
+var getterAndSetter = Object.create(null, {
+  c: {
+    get: function() {
+      return 'ccc';
+    },
+    set: function() {
+    }
+  }
+});
+
+it('should format object', function() {
+  assert.equal(format({a: 10, b: '10', '123': 'asd'}), "Object { '123': 'asd', a: 10, b: '10' }");
+
+  assert.equal(format(getter, {keys: false}), '{ a: [Getter] }');
+  assert.equal(format(setter, {keys: false}), '{ b: [Setter] }');
+  assert.equal(format(getterAndSetter, {keys: false}), '{ c: [Getter/Setter] }');
+
+  var obj = {a: 10};
+  obj.b = obj;
+  assert.equal(format(obj), 'Object { a: 10, b: [Circular] }');
+
+  var w = {
+    '\\': 1,
+    '\\\\': 2,
+    '\\\\\\': 3,
+    '\\\\\\\\': 4
+  };
+
+  var y = ['a', 'b', 'c'];
+  y['\\\\\\'] = 'd';
+
+  assert.ok(format(w),
+    'Object { \'\\\': 1, \'\\\\\': 2, \'\\\\\\\': 3, \'\\\\\\\\\': 4 }');
+  assert.ok(format(y), '[ \'a\', \'b\', \'c\', \'\\\\\\\': \'d\' ]');
+});
+
+it('should format arguments', function() {
+  var f = function() {
+    return arguments;
+  };
+  assert.equal(format(f(1, 2, 3)), 'Arguments [ 1, 2, 3 ]');
+});
+
+it('should format arrays', function() {
+  assert.equal(format([1, 2, 'abc']), 'Array [ 1, 2, \'abc\' ]');
+});
+
+it('should format node buffer', function() {
+  if(typeof Buffer !== 'undefined') {
+    var b = new Buffer('abc');
+    assert.equal(format(b), 'Buffer [ 61, 62, 63 ]');
+  }
+});
+
+it('should format typed arrays', function() {
+  if(typeof ArrayBuffer != 'undefined') {
+    var buffer = new ArrayBuffer(8);
+    for(var i = 0; i < buffer.byteLength; i++) buffer[i] = 0x00;
+    buffer[1] = 0x20;
+    buffer[2] = 0x2;
+    assert.equal(format(buffer), 'ArrayBuffer [ 00, 20, 02, 00, 00, 00, 00, 00 ]');
+
+    var int8 = new Int8Array(3);
+    int8[0] = 0x20;
+    int8[1] = 0x2;
+    assert.equal(format(int8), 'Int8Array [ 20, 02, 00 ]');
+
+    var int16 = new Int16Array(3);
+    int16[0] = 0x201;
+    int16[1] = 0x2;
+    assert.equal(format(int16), 'Int16Array [ 0201, 0002, 0000 ]');
+
+    //var dataView = new DataView(buffer);
+    //assert.equal(format(dataView), '[DataView: 00 20 02 00 00 00 00 00]');
+  }
+});
+
+it('should format html elements', function() {
+  if(typeof window != 'undefined' && typeof document != 'undefined') {
+    var btn = document.createElement("BUTTON");
+    var t = document.createTextNode("CLICK ME");
+    btn.appendChild(t);
+
+    assert.equal(format(btn), '<button>CLICK ME</button>');
+
+    assert.equal(format(t), 'CLICK ME');
+  }
+});
+
+it('should correctly indent', function() {
+  assert.equal(format({ a: { b: 'abc' }, d: 'abc'}, { maxLineLength: 0 }), 'Object {\n  a: Object {\n    b: \'abc\'\n  },\n  d: \'abc\'\n}');
+});
+
+it('should format set', function() {
+  if(typeof Set !== 'undefined') {
+    assert.equal(format(new Set([1, 2, { a: 10}, 'abc'])),
+      'Set { 1, 2, Object { a: 10 }, \'abc\' }');
+    assert.equal(format(new Set([1, 2, { a: 10}, 'abc']), { maxLineLength: 0 }),
+      'Set {\n  1,\n  2,\n  Object {\n    a: 10\n  },\n  \'abc\'\n}');
+  }
+});
+
+it('should format map', function() {
+  if(typeof Map !== 'undefined') {
+    assert.equal(format(new Map([[1, 2], [2, 'abc'], [{ a: 10}, new Set()], ['abc', null]])),
+      'Map { 1 => 2, 2 => \'abc\', Object { a: 10 } => Set {}, \'abc\' => null }');
+    assert.equal(format(new Map([[1, 2], [2, 'abc'], [{ a: 10}, new Set()], ['abc', null]]), { maxLineLength: 10 }),
+      'Map {\n  1 => 2,\n  2 => \'abc\',\n  Object { a: 10 } =>\n  Set {},\n  \'abc\' =>\n  null\n}');
+  }
+});
diff --git a/node_modules/should/node_modules/should-format/util.js b/node_modules/should/node_modules/should-format/util.js
new file mode 100644
index 0000000..f72518f
--- /dev/null
+++ b/node_modules/should/node_modules/should-format/util.js
@@ -0,0 +1,28 @@
+function addSpaces(v) {
+  return v.split('\n').map(function(vv) { return '  ' + vv; }).join('\n');
+}
+
+function pad(str, value, filler) {
+  str = String(str)
+  var isRight = false;
+
+  if(value < 0) {
+    isRight = true;
+    value = -value;
+  }
+
+  if(str.length < value) {
+    var padding = new Array(value - str.length + 1).join(filler);
+    return isRight ? str + padding : padding + str;
+  } else{
+    return str;
+  }
+}
+
+module.exports = {
+  addSpaces: addSpaces,
+  pad: pad,
+  pad0: function(str, value) {
+    return pad(str, value, '0');
+  }
+};
diff --git a/node_modules/should/node_modules/should-type/.npmignore b/node_modules/should/node_modules/should-type/.npmignore
new file mode 100644
index 0000000..5d46e4e
--- /dev/null
+++ b/node_modules/should/node_modules/should-type/.npmignore
@@ -0,0 +1,30 @@
+# Logs
+logs
+*.log
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+# Commenting this out is preferred by some people, see
+# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
+node_modules
+
+# Users Environment Variables
+.lock-wscript
+
+.idea
\ No newline at end of file
diff --git a/node_modules/should/node_modules/should-type/LICENSE b/node_modules/should/node_modules/should-type/LICENSE
new file mode 100644
index 0000000..d7e0e57
--- /dev/null
+++ b/node_modules/should/node_modules/should-type/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/node_modules/should/node_modules/should-type/README.md b/node_modules/should/node_modules/should-type/README.md
new file mode 100644
index 0000000..28b38d7
--- /dev/null
+++ b/node_modules/should/node_modules/should-type/README.md
@@ -0,0 +1,4 @@
+type
+====
+
+Simple module to resolve types
diff --git a/node_modules/should/node_modules/should-type/index.js b/node_modules/should/node_modules/should-type/index.js
new file mode 100644
index 0000000..3d950da
--- /dev/null
+++ b/node_modules/should/node_modules/should-type/index.js
@@ -0,0 +1,159 @@
+var toString = Object.prototype.toString;
+
+var types = require('./types');
+
+/**
+ * Simple data function to store type information
+ * @param {string} type Usually what is returned from typeof
+ * @param {string} cls  Sanitized @Class via Object.prototype.toString
+ * @param {string} sub  If type and cls the same, and need to specify somehow
+ * @private
+ * @example
+ *
+ * //for null
+ * new Type('null');
+ *
+ * //for Date
+ * new Type('object', 'date');
+ *
+ * //for Uint8Array
+ *
+ * new Type('object', 'typed-array', 'uint8');
+ */
+function Type(type, cls, sub) {
+  this.type = type;
+  this.cls = cls;
+  this.sub = sub;
+}
+
+/**
+ * Function to store type checks
+ * @private
+ */
+function TypeChecker() {
+  this.checks = [];
+}
+
+TypeChecker.prototype = {
+  add: function(func) {
+    this.checks.push(func);
+    return this;
+  },
+
+  addTypeOf: function(type, res) {
+    return this.add(function(obj, tpeOf) {
+      if(tpeOf === type) {
+        return new Type(res);
+      }
+    });
+  },
+
+  addClass: function(cls, res, sub) {
+    return this.add(function(obj, tpeOf, objCls) {
+      if(objCls === cls) {
+        return new Type(types.OBJECT, res, sub);
+      }
+    });
+  },
+
+  getType: function(obj) {
+    var typeOf = typeof obj;
+    var cls = toString.call(obj);
+
+    for(var i = 0, l = this.checks.length; i < l; i++) {
+      var res = this.checks[i].call(this, obj, typeOf, cls);
+      if(typeof res !== 'undefined') return res;
+    }
+
+  }
+};
+
+var main = new TypeChecker();
+
+//TODO add iterators
+
+main
+  .addTypeOf(types.NUMBER, types.NUMBER)
+  .addTypeOf(types.UNDEFINED, types.UNDEFINED)
+  .addTypeOf(types.STRING, types.STRING)
+  .addTypeOf(types.BOOLEAN, types.BOOLEAN)
+  .addTypeOf(types.FUNCTION, types.FUNCTION)
+  .addTypeOf(types.SYMBOL, types.SYMBOL)
+  .add(function(obj, tpeOf) {
+    if(obj === null) return new Type(types.NULL);
+  })
+  .addClass('[object String]', types.STRING)
+  .addClass('[object Boolean]', types.BOOLEAN)
+  .addClass('[object Number]', types.NUMBER)
+  .addClass('[object Array]', types.ARRAY)
+  .addClass('[object RegExp]', types.REGEXP)
+  .addClass('[object Error]', types.ERROR)
+  .addClass('[object Date]', types.DATE)
+  .addClass('[object Arguments]', types.ARGUMENTS)
+  .addClass('[object Math]')
+  .addClass('[object JSON]')
+  .addClass('[object ArrayBuffer]', types.ARRAY_BUFFER)
+  .addClass('[object Int8Array]', types.TYPED_ARRAY, 'int8')
+  .addClass('[object Uint8Array]', types.TYPED_ARRAY, 'uint8')
+  .addClass('[object Uint8ClampedArray]', types.TYPED_ARRAY, 'uint8clamped')
+  .addClass('[object Int16Array]', types.TYPED_ARRAY, 'int16')
+  .addClass('[object Uint16Array]', types.TYPED_ARRAY, 'uint16')
+  .addClass('[object Int32Array]', types.TYPED_ARRAY, 'int32')
+  .addClass('[object Uint32Array]', types.TYPED_ARRAY, 'uint32')
+  .addClass('[object Float32Array]', types.TYPED_ARRAY, 'float32')
+  .addClass('[object Float64Array]', types.TYPED_ARRAY, 'float64')
+  .addClass('[object DataView]', types.DATA_VIEW)
+  .addClass('[object Map]', types.MAP)
+  .addClass('[object WeakMap]', types.WEAK_MAP)
+  .addClass('[object Set]', types.SET)
+  .addClass('[object WeakSet]', types.WEAK_SET)
+  .addClass('[object Promise]', types.PROMISE)
+  .addClass('[object Blob]', types.BLOB)
+  .addClass('[object File]', types.FILE)
+  .addClass('[object FileList]', types.FILE_LIST)
+  .addClass('[object XMLHttpRequest]', types.XHR)
+  .add(function(obj) {
+    if((typeof Promise === types.FUNCTION && obj instanceof Promise) ||
+        (typeof obj.then === types.FUNCTION)) {
+          return new Type(types.OBJECT, types.PROMISE);
+        }
+  })
+  .add(function(obj) {
+    if(typeof Buffer !== 'undefined' && obj instanceof Buffer) {
+      return new Type(types.OBJECT, types.BUFFER);
+    }
+  })
+  .add(function(obj) {
+    if(typeof Node !== 'undefined' && obj instanceof Node) {
+      return new Type(types.OBJECT, types.HTML_ELEMENT, obj.nodeName);
+    }
+  })
+  .add(function(obj) {
+    // probably at the begginging should be enough these checks
+    if(obj.Boolean === Boolean && obj.Number === Number && obj.String === String && obj.Date === Date) {
+      return new Type(types.OBJECT, types.HOST);
+    }
+  })
+  .add(function() {
+    return new Type(types.OBJECT);
+  });
+
+/**
+ * Get type information of anything
+ *
+ * @param  {any} obj Anything that could require type information
+ * @return {Type}    type info
+ */
+function getGlobalType(obj) {
+  return main.getType(obj);
+}
+
+getGlobalType.checker = main;
+getGlobalType.TypeChecker = TypeChecker;
+getGlobalType.Type = Type;
+
+Object.keys(types).forEach(function(typeName) {
+  getGlobalType[typeName] = types[typeName];
+});
+
+module.exports = getGlobalType;
diff --git a/node_modules/should/node_modules/should-type/package.json b/node_modules/should/node_modules/should-type/package.json
new file mode 100644
index 0000000..3a01769
--- /dev/null
+++ b/node_modules/should/node_modules/should-type/package.json
@@ -0,0 +1,47 @@
+{
+  "name": "should-type",
+  "version": "0.2.0",
+  "description": "Simple module to get instance type. Like a bit more advanced version of typeof",
+  "main": "index.js",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/shouldjs/type.git"
+  },
+  "keywords": [
+    "should",
+    "type"
+  ],
+  "author": {
+    "name": "Denis Bardadym",
+    "email": "bardadymchik@gmail.com"
+  },
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/shouldjs/type/issues"
+  },
+  "homepage": "https://github.com/shouldjs/type",
+  "gitHead": "3ae89bfac659a5c5afbb176622f9773bcabd0a66",
+  "_id": "should-type@0.2.0",
+  "scripts": {},
+  "_shasum": "6707ef95529d989dcc098fe0753ab1f9136bb7f6",
+  "_from": "should-type@0.2.0",
+  "_npmVersion": "2.11.1",
+  "_nodeVersion": "2.3.0",
+  "_npmUser": {
+    "name": "btd",
+    "email": "bardadymchik@gmail.com"
+  },
+  "maintainers": [
+    {
+      "name": "btd",
+      "email": "bardadymchik@gmail.com"
+    }
+  ],
+  "dist": {
+    "shasum": "6707ef95529d989dcc098fe0753ab1f9136bb7f6",
+    "tarball": "http://registry.npmjs.org/should-type/-/should-type-0.2.0.tgz"
+  },
+  "directories": {},
+  "_resolved": "https://registry.npmjs.org/should-type/-/should-type-0.2.0.tgz",
+  "readme": "ERROR: No README data found!"
+}
diff --git a/node_modules/should/node_modules/should-type/types.js b/node_modules/should/node_modules/should-type/types.js
new file mode 100644
index 0000000..18b8c12
--- /dev/null
+++ b/node_modules/should/node_modules/should-type/types.js
@@ -0,0 +1,41 @@
+var types = {
+  NUMBER: 'number',
+  UNDEFINED: 'undefined',
+  STRING: 'string',
+  BOOLEAN: 'boolean',
+  OBJECT: 'object',
+  FUNCTION: 'function',
+  NULL: 'null',
+  ARRAY: 'array',
+  REGEXP: 'regexp',
+  DATE: 'date',
+  ERROR: 'error',
+  ARGUMENTS: 'arguments',
+  SYMBOL: 'symbol',
+  ARRAY_BUFFER: 'array-buffer',
+  TYPED_ARRAY: 'typed-array',
+  DATA_VIEW: 'data-view',
+  MAP: 'map',
+  SET: 'set',
+  WEAK_SET: 'weak-set',
+  WEAK_MAP: 'weak-map',
+  PROMISE: 'promise',
+
+// node buffer
+  BUFFER: 'buffer',
+
+// dom html element
+  HTML_ELEMENT: 'html-element',
+  HTML_ELEMENT_TEXT: 'html-element-text',
+  DOCUMENT: 'document',
+  WINDOW: 'window',
+  FILE: 'file',
+  FILE_LIST: 'file-list',
+  BLOB: 'blob',
+
+  HOST: 'host',
+
+  XHR: 'xhr'
+};
+
+module.exports = types;
diff --git a/node_modules/should/package.json b/node_modules/should/package.json
new file mode 100644
index 0000000..9536b1d
--- /dev/null
+++ b/node_modules/should/package.json
@@ -0,0 +1,84 @@
+{
+  "name": "should",
+  "description": "test framework agnostic BDD-style assertions",
+  "version": "8.0.1",
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/shouldjs/should.js.git"
+  },
+  "homepage": "https://github.com/shouldjs/should.js",
+  "scripts": {
+    "test": "mocha -R mocha-better-spec-reporter --check-leaks ./test/*.test.js ./test/**/*.test.js",
+    "zuul": "zuul -- ./test/**/*.test.js ./test/*.test.js",
+    "browser": "gulp script"
+  },
+  "devDependencies": {
+    "bluebird": "^3.0.6",
+    "browserify": "latest",
+    "eslint": "^1.10.3",
+    "eslint-config-eslint": "^1.0.1",
+    "gulp": "^3.8.10",
+    "gulp-header": "^1.2.2",
+    "gulp-rename": "^1.2.0",
+    "gulp-uglify": "^1.0.1",
+    "mocha": "latest",
+    "mocha-better-spec-reporter": "latest",
+    "vinyl-buffer": "^1.0.0",
+    "vinyl-source-stream": "^1.1.0",
+    "zuul": "latest"
+  },
+  "keywords": [
+    "test",
+    "bdd",
+    "assert",
+    "should"
+  ],
+  "main": "./index.js",
+  "license": "MIT",
+  "dependencies": {
+    "should-equal": "0.5.0",
+    "should-format": "0.3.1",
+    "should-type": "0.2.0"
+  },
+  "gitHead": "49c4b55121a37500b2ec1755d10dff3f22b01380",
+  "bugs": {
+    "url": "https://github.com/shouldjs/should.js/issues"
+  },
+  "_id": "should@8.0.1",
+  "_shasum": "3a3a7117d45f29a367bc129c878a303ec1ef640a",
+  "_from": "should@8.0.1",
+  "_npmVersion": "3.3.12",
+  "_nodeVersion": "5.2.0",
+  "_npmUser": {
+    "name": "btd",
+    "email": "bardadymchik@gmail.com"
+  },
+  "dist": {
+    "shasum": "3a3a7117d45f29a367bc129c878a303ec1ef640a",
+    "tarball": "http://registry.npmjs.org/should/-/should-8.0.1.tgz"
+  },
+  "maintainers": [
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    },
+    {
+      "name": "gjohnson",
+      "email": "gjj391@gmail.com"
+    },
+    {
+      "name": "travisjeffery",
+      "email": "tj@travisjeffery.com"
+    },
+    {
+      "name": "btd",
+      "email": "bardadymchik@gmail.com"
+    }
+  ],
+  "directories": {},
+  "_resolved": "https://registry.npmjs.org/should/-/should-8.0.1.tgz"
+}
diff --git a/node_modules/should/should.js b/node_modules/should/should.js
new file mode 100644
index 0000000..024f606
--- /dev/null
+++ b/node_modules/should/should.js
@@ -0,0 +1,3886 @@
+/*!
+ * should - test framework agnostic BDD-style assertions
+ * @version v8.0.1
+ * @author TJ Holowaychuk <tj@vision-media.ca> and contributors
+ * @link https://github.com/shouldjs/should.js
+ * @license MIT
+ */
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Should = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+window.Should = require('./index');
+
+Object.defineProperty(window, 'should', {
+  enumerable: false,
+  configurable: true,
+  value: window.Should
+});
+
+},{"./index":2}],2:[function(require,module,exports){
+var should = require('./lib/should');
+
+var defaultProto = Object.prototype;
+var defaultProperty = 'should';
+
+//Expose api via `Object#should`.
+try {
+  var prevShould = should.extend(defaultProperty, defaultProto);
+  should._prevShould = prevShould;
+} catch(e) {
+  //ignore errors
+}
+
+module.exports = should;
+
+},{"./lib/should":19}],3:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('./util');
+
+/**
+ * should AssertionError
+ * @param {Object} options
+ * @constructor
+ * @memberOf should
+ * @static
+ */
+var AssertionError = function AssertionError(options) {
+  util.merge(this, options);
+
+  if(!options.message) {
+    Object.defineProperty(this, 'message', {
+        get: function() {
+          if(!this._message) {
+            this._message = this.generateMessage();
+            this.generatedMessage = true;
+          }
+          return this._message;
+        },
+        configurable: true,
+        enumerable: false
+      }
+    );
+  }
+
+  if(Error.captureStackTrace) {
+    Error.captureStackTrace(this, this.stackStartFunction);
+  } else {
+    // non v8 browsers so we can have a stacktrace
+    var err = new Error();
+    if(err.stack) {
+      var out = err.stack;
+
+      if(this.stackStartFunction) {
+        // try to strip useless frames
+        var fn_name = util.functionName(this.stackStartFunction);
+        var idx = out.indexOf('\n' + fn_name);
+        if(idx >= 0) {
+          // once we have located the function frame
+          // we need to strip out everything before it (and its line)
+          var next_line = out.indexOf('\n', idx + 1);
+          out = out.substring(next_line + 1);
+        }
+      }
+
+      this.stack = out;
+    }
+  }
+};
+
+
+var indent = '    ';
+function prependIndent(line) {
+  return indent + line;
+}
+
+function indentLines(text) {
+  return text.split('\n').map(prependIndent).join('\n');
+}
+
+
+// assert.AssertionError instanceof Error
+AssertionError.prototype = Object.create(Error.prototype, {
+  name: {
+    value: 'AssertionError'
+  },
+
+  generateMessage: {
+    value: function() {
+      if(!this.operator && this.previous) {
+        return this.previous.message;
+      }
+      var actual = util.format(this.actual);
+      var expected = 'expected' in this ? ' ' + util.format(this.expected) : '';
+      var details = 'details' in this && this.details ? ' (' + this.details + ')' : '';
+
+      var previous = this.previous ? '\n' + indentLines(this.previous.message) : '';
+
+      return 'expected ' + actual + (this.negate ? ' not ' : ' ') + this.operator + expected + details + previous;
+    }
+  }
+});
+
+module.exports = AssertionError;
+
+},{"./util":20}],4:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var AssertionError = require('./assertion-error');
+
+/**
+ * should Assertion
+ * @param {*} obj Given object for assertion
+ * @constructor
+ * @memberOf should
+ * @static
+ */
+function Assertion(obj) {
+  this.obj = obj;
+
+  this.anyOne = false;
+  this.negate = false;
+
+  this.params = {actual: obj};
+}
+
+Assertion.prototype = {
+  constructor: Assertion,
+
+  /**
+   * Base method for assertions.
+   *
+   * Before calling this method need to fill Assertion#params object. This method usually called from other assertion methods.
+   * `Assertion#params` can contain such properties:
+   * * `operator` - required string containing description of this assertion
+   * * `obj` - optional replacement for this.obj, it usefull if you prepare more clear object then given
+   * * `message` - if this property filled with string any others will be ignored and this one used as assertion message
+   * * `expected` - any object used when you need to assert relation between given object and expected. Like given == expected (== is a relation)
+   * * `details` - additional string with details to generated message
+   *
+   * @memberOf Assertion
+   * @category assertion
+   * @param {*} expr Any expression that will be used as a condition for asserting.
+   * @example
+   *
+   * var a = new should.Assertion(42);
+   *
+   * a.params = {
+   *  operator: 'to be magic number',
+   * }
+   *
+   * a.assert(false);
+   * //throws AssertionError: expected 42 to be magic number
+   */
+  assert: function(expr) {
+    if(expr) {
+      return this;
+    }
+
+    var params = this.params;
+
+    if('obj' in params && !('actual' in params)) {
+      params.actual = params.obj;
+    } else if(!('obj' in params) && !('actual' in params)) {
+      params.actual = this.obj;
+    }
+
+    params.stackStartFunction = params.stackStartFunction || this.assert;
+    params.negate = this.negate;
+
+    params.assertion = this;
+
+    throw new AssertionError(params);
+  },
+
+  /**
+   * Shortcut for `Assertion#assert(false)`.
+   *
+   * @memberOf Assertion
+   * @category assertion
+   * @example
+   *
+   * var a = new should.Assertion(42);
+   *
+   * a.params = {
+   *  operator: 'to be magic number',
+   * }
+   *
+   * a.fail();
+   * //throws AssertionError: expected 42 to be magic number
+   */
+  fail: function() {
+    return this.assert(false);
+  }
+};
+
+
+
+/**
+ * Assertion used to delegate calls of Assertion methods inside of Promise.
+ * It has almost all methods of Assertion.prototype
+ *
+ * @param {Promise} obj
+ */
+function PromisedAssertion(/* obj */) {
+  Assertion.apply(this, arguments);
+}
+
+/**
+ * Make PromisedAssertion to look like promise. Delegate resolve and reject to given promise.
+ * 
+ * @private
+ * @returns {Promise}
+ */
+PromisedAssertion.prototype.then = function(resolve, reject) {
+  return this.obj.then(resolve, reject);
+};
+
+/**
+ * Way to extend Assertion function. It uses some logic
+ * to define only positive assertions and itself rule with negative assertion.
+ *
+ * All actions happen in subcontext and this method take care about negation.
+ * Potentially we can add some more modifiers that does not depends from state of assertion.
+ *
+ * @memberOf Assertion
+ * @static
+ * @param {String} name Name of assertion. It will be used for defining method or getter on Assertion.prototype
+ * @param {Function} func Function that will be called on executing assertion
+ * @example
+ *
+ * Assertion.add('asset', function() {
+ *      this.params = { operator: 'to be asset' }
+ *
+ *      this.obj.should.have.property('id').which.is.a.Number()
+ *      this.obj.should.have.property('path')
+ * })
+ */
+Assertion.add = function(name, func) {
+  Object.defineProperty(Assertion.prototype, name, {
+    enumerable: true,
+    configurable: true,
+    value: function() {
+      var context = new Assertion(this.obj, this, name);
+      context.anyOne = this.anyOne;
+
+      try {
+        func.apply(context, arguments);
+      } catch (e) {
+        // check for fail
+        if (e instanceof AssertionError) {
+          // negative fail
+          if (this.negate) {
+            this.obj = context.obj;
+            this.negate = false;
+            return this;
+          }
+
+          if (context !== e.assertion) {
+            context.params.previous = e;
+          }
+
+          // positive fail
+          context.negate = false;
+          context.fail();
+        }
+        // throw if it is another exception
+        throw e;
+      }
+
+      // negative pass
+      if (this.negate) {
+        context.negate = true; // because .fail will set negate
+        context.params.details = 'false negative fail';
+        context.fail();
+      }
+
+      // positive pass
+      if (!this.params.operator) {
+        this.params = context.params; // shortcut
+      }
+      this.obj = context.obj;
+      this.negate = false;
+      return this;
+    }
+  });
+
+  Object.defineProperty(PromisedAssertion.prototype, name, {
+    enumerable: true,
+    configurable: true,
+    value: function() {
+      var args = arguments;
+      this.obj = this.obj.then(function(a) {
+        return a[name].apply(a, args);
+      });
+
+      return this;
+    }
+  });
+};
+
+/**
+ * Add chaining getter to Assertion like .a, .which etc
+ * 
+ * @memberOf Assertion
+ * @static
+ * @param  {string} name   name of getter
+ * @param  {function} [onCall] optional function to call
+ */
+Assertion.addChain = function(name, onCall) {
+  onCall = onCall || function() {};
+  Object.defineProperty(Assertion.prototype, name, {
+    get: function() {
+      onCall.call(this);
+      return this;
+    },
+    enumerable: true
+  });
+
+  Object.defineProperty(PromisedAssertion.prototype, name, {
+    enumerable: true,
+    configurable: true,
+    get: function() {
+      this.obj = this.obj.then(function(a) {
+        return a[name];
+      });
+
+      return this;
+    }
+  });
+};
+
+/**
+ * Create alias for some `Assertion` property
+ *
+ * @memberOf Assertion
+ * @static
+ * @param {String} from Name of to map
+ * @param {String} to Name of alias
+ * @example
+ *
+ * Assertion.alias('true', 'True')
+ */
+Assertion.alias = function(from, to) {
+  var desc = Object.getOwnPropertyDescriptor(Assertion.prototype, from);
+  if (!desc) throw new Error('Alias ' + from + ' -> ' + to + ' could not be created as ' + from + ' not defined');
+  Object.defineProperty(Assertion.prototype, to, desc);
+
+  var desc2 = Object.getOwnPropertyDescriptor(PromisedAssertion.prototype, from);
+  if (desc2) {
+    Object.defineProperty(PromisedAssertion.prototype, to, desc2);
+  }
+};
+/**
+ * Negation modifier. Current assertion chain become negated. Each call invert negation on current assertion.
+ *
+ * @name not
+ * @property
+ * @memberOf Assertion
+ * @category assertion
+ */
+Assertion.addChain('not', function() {
+  this.negate = !this.negate;
+});
+
+/**
+ * Any modifier - it affect on execution of sequenced assertion to do not `check all`, but `check any of`.
+ *
+ * @name any
+ * @property
+ * @memberOf Assertion
+ * @category assertion
+ */
+Assertion.addChain('any', function() {
+  this.anyOne = true;
+});
+
+module.exports = Assertion;
+module.exports.PromisedAssertion = PromisedAssertion;
+
+},{"./assertion-error":3}],5:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var Formatter = require('should-format').Formatter;
+
+var config = {
+  checkProtoEql: false,
+
+  getFormatter: function(opts) {
+    return new Formatter(opts || config);
+  }
+};
+
+module.exports = config;
+
+},{"should-format":23}],6:[function(require,module,exports){
+// implement assert interface using already written peaces of should.js
+
+// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
+//
+// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
+//
+// Originally from narwhal.js (http://narwhaljs.org)
+// Copyright (c) 2009 Thomas Robinson <280north.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the 'Software'), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// when used in node, this will actually load the util module we depend on
+// versus loading the builtin util module as happens otherwise
+// this is a bug in node module loading as far as I am concerned
+var Assertion = require('./../assertion');
+
+var _deepEqual = require('should-equal');
+
+var pSlice = Array.prototype.slice;
+
+// 1. The assert module provides functions that throw
+// AssertionError's when particular conditions are not met. The
+// assert module must conform to the following interface.
+
+var assert = module.exports = ok;
+
+// 3. All of the following functions must throw an AssertionError
+// when a corresponding condition is not met, with a message that
+// may be undefined if not provided.  All assertion methods provide
+// both the actual and expected values to the assertion error for
+// display purposes.
+/**
+ * Node.js standard [`assert.fail`](http://nodejs.org/api/assert.html#assert_assert_fail_actual_expected_message_operator).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual Actual object
+ * @param {*} expected Expected object
+ * @param {string} message Message for assertion
+ * @param {string} operator Operator text
+ */
+function fail(actual, expected, message, operator, stackStartFunction) {
+  var a = new Assertion(actual);
+  a.params = {
+    operator: operator,
+    expected: expected,
+    message: message,
+    stackStartFunction: stackStartFunction || fail
+  };
+
+  a.fail();
+}
+
+// EXTENSION! allows for well behaved errors defined elsewhere.
+assert.fail = fail;
+
+// 4. Pure assertion tests whether a value is truthy, as determined
+// by !!guard.
+// assert.ok(guard, message_opt);
+// This statement is equivalent to assert.equal(true, !!guard,
+// message_opt);. To test strictly for the value true, use
+// assert.strictEqual(true, guard, message_opt);.
+/**
+ * Node.js standard [`assert.ok`](http://nodejs.org/api/assert.html#assert_assert_value_message_assert_ok_value_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} value
+ * @param {string} [message]
+ */
+function ok(value, message) {
+  if(!value) fail(value, true, message, '==', assert.ok);
+}
+assert.ok = ok;
+
+// 5. The equality assertion tests shallow, coercive equality with
+// ==.
+// assert.equal(actual, expected, message_opt);
+
+/**
+ * Node.js standard [`assert.equal`](http://nodejs.org/api/assert.html#assert_assert_equal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.equal = function equal(actual, expected, message) {
+  if(actual != expected) fail(actual, expected, message, '==', assert.equal);
+};
+
+// 6. The non-equality assertion tests for whether two objects are not equal
+// with != assert.notEqual(actual, expected, message_opt);
+/**
+ * Node.js standard [`assert.notEqual`](http://nodejs.org/api/assert.html#assert_assert_notequal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.notEqual = function notEqual(actual, expected, message) {
+  if(actual == expected) {
+    fail(actual, expected, message, '!=', assert.notEqual);
+  }
+};
+
+// 7. The equivalence assertion tests a deep equality relation.
+// assert.deepEqual(actual, expected, message_opt);
+/**
+ * Node.js standard [`assert.deepEqual`](http://nodejs.org/api/assert.html#assert_assert_deepequal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.deepEqual = function deepEqual(actual, expected, message) {
+  if(!_deepEqual(actual, expected).result) {
+    fail(actual, expected, message, 'deepEqual', assert.deepEqual);
+  }
+};
+
+
+// 8. The non-equivalence assertion tests for any deep inequality.
+// assert.notDeepEqual(actual, expected, message_opt);
+/**
+ * Node.js standard [`assert.notDeepEqual`](http://nodejs.org/api/assert.html#assert_assert_notdeepequal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
+  if(_deepEqual(actual, expected).result) {
+    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
+  }
+};
+
+// 9. The strict equality assertion tests strict equality, as determined by ===.
+// assert.strictEqual(actual, expected, message_opt);
+/**
+ * Node.js standard [`assert.strictEqual`](http://nodejs.org/api/assert.html#assert_assert_strictequal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.strictEqual = function strictEqual(actual, expected, message) {
+  if(actual !== expected) {
+    fail(actual, expected, message, '===', assert.strictEqual);
+  }
+};
+
+// 10. The strict non-equality assertion tests for strict inequality, as
+// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);
+/**
+ * Node.js standard [`assert.notStrictEqual`](http://nodejs.org/api/assert.html#assert_assert_notstrictequal_actual_expected_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {*} actual
+ * @param {*} expected
+ * @param {string} [message]
+ */
+assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
+  if(actual === expected) {
+    fail(actual, expected, message, '!==', assert.notStrictEqual);
+  }
+};
+
+function expectedException(actual, expected) {
+  if(!actual || !expected) {
+    return false;
+  }
+
+  if(Object.prototype.toString.call(expected) == '[object RegExp]') {
+    return expected.test(actual);
+  } else if(actual instanceof expected) {
+    return true;
+  } else if(expected.call({}, actual) === true) {
+    return true;
+  }
+
+  return false;
+}
+
+function _throws(shouldThrow, block, expected, message) {
+  var actual;
+
+  if(typeof expected == 'string') {
+    message = expected;
+    expected = null;
+  }
+
+  try {
+    block();
+  } catch(e) {
+    actual = e;
+  }
+
+  message = (expected && expected.name ? ' (' + expected.name + ')' : '.') +
+  (message ? ' ' + message : '.');
+
+  if(shouldThrow && !actual) {
+    fail(actual, expected, 'Missing expected exception' + message);
+  }
+
+  if(!shouldThrow && expectedException(actual, expected)) {
+    fail(actual, expected, 'Got unwanted exception' + message);
+  }
+
+  if((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) {
+    throw actual;
+  }
+}
+
+// 11. Expected to throw an error:
+// assert.throws(block, Error_opt, message_opt);
+/**
+ * Node.js standard [`assert.throws`](http://nodejs.org/api/assert.html#assert_assert_throws_block_error_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {Function} block
+ * @param {Function} [error]
+ * @param {String} [message]
+ */
+assert.throws = function(block, /*optional*/error, /*optional*/message) {
+  _throws.apply(this, [true].concat(pSlice.call(arguments)));
+};
+
+// EXTENSION! This is annoying to write outside this module.
+/**
+ * Node.js standard [`assert.doesNotThrow`](http://nodejs.org/api/assert.html#assert_assert_doesnotthrow_block_message).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {Function} block
+ * @param {String} [message]
+ */
+assert.doesNotThrow = function(block, /*optional*/message) {
+  _throws.apply(this, [false].concat(pSlice.call(arguments)));
+};
+
+/**
+ * Node.js standard [`assert.ifError`](http://nodejs.org/api/assert.html#assert_assert_iferror_value).
+ * @static
+ * @memberOf should
+ * @category assertion assert
+ * @param {Error} err
+ */
+assert.ifError = function(err) {
+  if(err) {
+    throw err;
+  }
+};
+
+},{"./../assertion":4,"should-equal":22}],7:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util')
+  , assert = require('./_assert')
+  , AssertionError = require('../assertion-error');
+
+module.exports = function(should) {
+  var i = should.format;
+
+  /*
+   * Expose assert to should
+   *
+   * This allows you to do things like below
+   * without require()ing the assert module.
+   *
+   *    should.equal(foo.bar, undefined);
+   *
+   */
+  util.merge(should, assert);
+
+  /**
+   * Assert _obj_ exists, with optional message.
+   *
+   * @static
+   * @memberOf should
+   * @category assertion assert
+   * @alias should.exists
+   * @param {*} obj
+   * @param {String} [msg]
+   * @example
+   *
+   * should.exist(1);
+   * should.exist(new Date());
+   */
+  should.exist = should.exists = function(obj, msg) {
+    if(null == obj) {
+      throw new AssertionError({
+        message: msg || ('expected ' + i(obj) + ' to exist'), stackStartFunction: should.exist
+      });
+    }
+  };
+
+  should.not = {};
+  /**
+   * Asserts _obj_ does not exist, with optional message.
+   *
+   * @name not.exist
+   * @static
+   * @memberOf should
+   * @category assertion assert
+   * @alias should.not.exists
+   * @param {*} obj
+   * @param {String} [msg]
+   * @example
+   *
+   * should.not.exist(null);
+   * should.not.exist(void 0);
+   */
+  should.not.exist = should.not.exists = function(obj, msg) {
+    if(null != obj) {
+      throw new AssertionError({
+        message: msg || ('expected ' + i(obj) + ' to not exist'), stackStartFunction: should.not.exist
+      });
+    }
+  };
+};
+},{"../assertion-error":3,"../util":20,"./_assert":6}],8:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+module.exports = function(should, Assertion) {
+  /**
+   * Assert given object is exactly `true`.
+   *
+   * @name true
+   * @memberOf Assertion
+   * @category assertion bool
+   * @alias Assertion#True
+   * @example
+   *
+   * (true).should.be.true();
+   * false.should.not.be.true();
+   *
+   * ({ a: 10}).should.not.be.true();
+   */
+  Assertion.add('true', function() {
+    this.is.exactly(true);
+  });
+
+  Assertion.alias('true', 'True');
+
+  /**
+   * Assert given object is exactly `false`.
+   *
+   * @name false
+   * @memberOf Assertion
+   * @category assertion bool
+   * @alias Assertion#False
+   * @example
+   *
+   * (true).should.not.be.false();
+   * false.should.be.false();
+   */
+  Assertion.add('false', function() {
+    this.is.exactly(false);
+  });
+
+  Assertion.alias('false', 'False');
+
+  /**
+   * Assert given object is thuthy according javascript type conversions.
+   *
+   * @name ok
+   * @memberOf Assertion
+   * @category assertion bool
+   * @example
+   *
+   * (true).should.be.ok();
+   * ''.should.not.be.ok();
+   * should(null).not.be.ok();
+   * should(void 0).not.be.ok();
+   *
+   * (10).should.be.ok();
+   * (0).should.not.be.ok();
+   */
+  Assertion.add('ok', function() {
+    this.params = { operator: 'to be truthy' };
+
+    this.assert(this.obj);
+  });
+};
+
+},{}],9:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+module.exports = function(should, Assertion) {
+  /**
+   * Simple chaining. It actually do nothing.
+   *
+   * @memberOf Assertion
+   * @name be
+   * @property {should.Assertion} be
+   * @alias Assertion#an
+   * @alias Assertion#of
+   * @alias Assertion#a
+   * @alias Assertion#and
+   * @alias Assertion#have
+   * @alias Assertion#has
+   * @alias Assertion#with
+   * @alias Assertion#is
+   * @alias Assertion#which
+   * @alias Assertion#the
+   * @alias Assertion#it
+   * @category assertion chaining
+   */
+  ['an', 'of', 'a', 'and', 'be', 'has', 'have', 'with', 'is', 'which', 'the', 'it'].forEach(function(name) {
+    Assertion.addChain(name);
+  });
+};
+
+},{}],10:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util');
+var eql = require('should-equal');
+
+module.exports = function(should, Assertion) {
+  var i = should.format;
+
+  /**
+   * Assert that given object contain something that equal to `other`. It uses `should-equal` for equality checks.
+   * If given object is array it search that one of elements was equal to `other`.
+   * If given object is string it checks if `other` is a substring - expected that `other` is a string.
+   * If given object is Object it checks that `other` is a subobject - expected that `other` is a object.
+   *
+   * @name containEql
+   * @memberOf Assertion
+   * @category assertion contain
+   * @param {*} other Nested object
+   * @example
+   *
+   * [1, 2, 3].should.containEql(1);
+   * [{ a: 1 }, 'a', 10].should.containEql({ a: 1 });
+   *
+   * 'abc'.should.containEql('b');
+   * 'ab1c'.should.containEql(1);
+   *
+   * ({ a: 10, c: { d: 10 }}).should.containEql({ a: 10 });
+   * ({ a: 10, c: { d: 10 }}).should.containEql({ c: { d: 10 }});
+   * ({ a: 10, c: { d: 10 }}).should.containEql({ b: 10 });
+   * // throws AssertionError: expected { a: 10, c: { d: 10 } } to contain { b: 10 }
+   * //            expected { a: 10, c: { d: 10 } } to have property b
+   */
+  Assertion.add('containEql', function(other) {
+    this.params = {operator: 'to contain ' + i(other)};
+
+    this.is.not.null().and.not.undefined();
+
+    var obj = this.obj;
+
+    if(typeof obj == 'string') {
+      this.assert(obj.indexOf(String(other)) >= 0);
+    } else if(util.isIndexable(obj)) {
+      this.assert(util.some(obj, function(v) {
+        return eql(v, other).result;
+      }));
+    } else {
+      this.have.properties(other);
+    }
+  });
+
+  /**
+   * Assert that given object is contain equally structured object on the same depth level.
+   * If given object is an array and `other` is an array it checks that the eql elements is going in the same sequence in given array (recursive)
+   * If given object is an object it checks that the same keys contain deep equal values (recursive)
+   * On other cases it try to check with `.eql`
+   *
+   * @name containDeepOrdered
+   * @memberOf Assertion
+   * @category assertion contain
+   * @param {*} other Nested object
+   * @example
+   *
+   * [ 1, 2, 3].should.containDeepOrdered([1, 2]);
+   * [ 1, 2, [ 1, 2, 3 ]].should.containDeepOrdered([ 1, [ 2, 3 ]]);
+   *
+   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({a: 10});
+   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {c: 10}});
+   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {d: [1, 3]}});
+   */
+  Assertion.add('containDeepOrdered', function(other) {
+    this.params = {operator: 'to contain ' + i(other)};
+
+    var obj = this.obj;
+    if(typeof obj == 'string') {// expect other to be string
+      this.is.equal(String(other));
+    } else if(util.isIndexable(obj) && util.isIndexable(other)) {
+      for(var objIdx = 0, otherIdx = 0, objLength = util.length(obj), otherLength = util.length(other); objIdx < objLength && otherIdx < otherLength; objIdx++) {
+        try {
+          should(obj[objIdx]).containDeepOrdered(other[otherIdx]);
+          otherIdx++;
+        } catch(e) {
+          if(e instanceof should.AssertionError) {
+            continue;
+          }
+          throw e;
+        }
+      }
+
+      this.assert(otherIdx === otherLength);
+    } else if(obj != null && other != null && typeof obj == 'object' && typeof other == 'object') {// object contains object case
+      util.forEach(other, function(value, key) {
+        should(obj[key]).containDeepOrdered(value);
+      });
+
+      // if both objects is empty means we finish traversing - and we need to compare for hidden values
+      if(util.isEmptyObject(other)) {
+        this.eql(other);
+      }
+    } else {
+      this.eql(other);
+    }
+  });
+
+  /**
+   * The same like `Assertion#containDeepOrdered` but all checks on arrays without order.
+   *
+   * @name containDeep
+   * @memberOf Assertion
+   * @category assertion contain
+   * @param {*} other Nested object
+   * @example
+   *
+   * [ 1, 2, 3].should.containDeep([2, 1]);
+   * [ 1, 2, [ 1, 2, 3 ]].should.containDeep([ 1, [ 3, 1 ]]);
+   */
+  Assertion.add('containDeep', function(other) {
+    this.params = {operator: 'to contain ' + i(other)};
+
+    var obj = this.obj;
+    if(typeof obj == 'string') {// expect other to be string
+      this.is.equal(String(other));
+    } else if(util.isIndexable(obj) && util.isIndexable(other)) {
+      var usedKeys = {};
+      util.forEach(other, function(otherItem) {
+        this.assert(util.some(obj, function(item, index) {
+          if(index in usedKeys) return false;
+
+          try {
+            should(item).containDeep(otherItem);
+            usedKeys[index] = true;
+            return true;
+          } catch(e) {
+            if(e instanceof should.AssertionError) {
+              return false;
+            }
+            throw e;
+          }
+        }));
+      }, this);
+    } else if(obj != null && other != null && typeof obj == 'object' && typeof other == 'object') {// object contains object case
+      util.forEach(other, function(value, key) {
+        should(obj[key]).containDeep(value);
+      });
+
+      // if both objects is empty means we finish traversing - and we need to compare for hidden values
+      if(util.isEmptyObject(other)) {
+        this.eql(other);
+      }
+    } else {
+      this.eql(other);
+    }
+  });
+
+};
+
+},{"../util":20,"should-equal":22}],11:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var eql = require('should-equal');
+var type = require('should-type');
+var util = require('../util');
+
+function formatEqlResult(r, a, b) {
+  return ((r.path.length > 0 ? 'at ' + r.path.map(util.formatProp).join(' -> ') : '') +
+  (r.a === a ? '' : ', A has ' + util.format(r.a)) +
+  (r.b === b ? '' : ' and B has ' + util.format(r.b)) +
+  (r.showReason ? ' because ' + r.reason : '')).trim();
+}
+
+module.exports = function(should, Assertion) {
+
+  /**
+   * Deep object equality comparison. For full spec see [`should-equal tests`](https://github.com/shouldjs/equal/blob/master/test.js).
+   *
+   * @name eql
+   * @memberOf Assertion
+   * @category assertion equality
+   * @alias Assertion#deepEqual
+   * @param {*} val Expected value
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (10).should.be.eql(10);
+   * ('10').should.not.be.eql(10);
+   * (-0).should.not.be.eql(+0);
+   *
+   * NaN.should.be.eql(NaN);
+   *
+   * ({ a: 10}).should.be.eql({ a: 10 });
+   * [ 'a' ].should.not.be.eql({ '0': 'a' });
+   */
+  Assertion.add('eql', function(val, description) {
+    this.params = {operator: 'to equal', expected: val, message: description};
+
+    var result = eql(this.obj, val, should.config);
+    this.params.details = result.result ? '' : formatEqlResult(result, this.obj, val);
+
+    this.params.showDiff = eql(type(this.obj), type(val)).result;
+
+    this.assert(result.result);
+  });
+
+  /**
+   * Exact comparison using ===.
+   *
+   * @name equal
+   * @memberOf Assertion
+   * @category assertion equality
+   * @alias Assertion#exactly
+   * @param {*} val Expected value
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * 10.should.be.equal(10);
+   * 'a'.should.be.exactly('a');
+   *
+   * should(null).be.exactly(null);
+   */
+  Assertion.add('equal', function(val, description) {
+    this.params = {operator: 'to be', expected: val, message: description};
+
+    this.params.showDiff = eql(type(this.obj), type(val)).result;
+
+    this.assert(val === this.obj);
+  });
+
+  Assertion.alias('equal', 'exactly');
+  Assertion.alias('eql', 'deepEqual');
+
+  function addOneOf(name, message, method) {
+    Assertion.add(name, function(vals) {
+      if(arguments.length !== 1) {
+        vals = Array.prototype.slice.call(arguments);
+      } else {
+        should(vals).be.Array();
+      }
+
+      this.params = {operator: message, expected: vals};
+
+      var obj = this.obj;
+      var found = false;
+
+      util.forEach(vals, function(val) {
+        try {
+          should(val)[method](obj);
+          found = true;
+          return false;
+        } catch(e) {
+          if(e instanceof should.AssertionError) {
+            return;//do nothing
+          }
+          throw e;
+        }
+      });
+
+      this.assert(found);
+    });
+  }
+
+  /**
+   * Exact comparison using === to be one of supplied objects.
+   *
+   * @name equalOneOf
+   * @memberOf Assertion
+   * @category assertion equality
+   * @param {Array|*} vals Expected values
+   * @example
+   *
+   * 'ab'.should.be.equalOneOf('a', 10, 'ab');
+   * 'ab'.should.be.equalOneOf(['a', 10, 'ab']);
+   */
+  addOneOf('equalOneOf', 'to be equals one of', 'equal');
+
+  /**
+   * Exact comparison using .eql to be one of supplied objects.
+   *
+   * @name oneOf
+   * @memberOf Assertion
+   * @category assertion equality
+   * @param {Array|*} vals Expected values
+   * @example
+   *
+   * ({a: 10}).should.be.oneOf('a', 10, 'ab', {a: 10});
+   * ({a: 10}).should.be.oneOf(['a', 10, 'ab', {a: 10}]);
+   */
+  addOneOf('oneOf', 'to be one of', 'eql');
+
+};
+
+},{"../util":20,"should-equal":22,"should-type":25}],12:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+var util = require('../util');
+
+module.exports = function(should, Assertion) {
+  var i = should.format;
+
+  /**
+   * Assert given function throws error with such message.
+   *
+   * @name throw
+   * @memberOf Assertion
+   * @category assertion errors
+   * @alias Assertion#throwError
+   * @param {string|RegExp|Function|Object|GeneratorFunction|GeneratorObject} [message] Message to match or properties
+   * @param {Object} [properties] Optional properties that will be matched to thrown error
+   * @example
+   *
+   * (function(){ throw new Error('fail') }).should.throw();
+   * (function(){ throw new Error('fail') }).should.throw('fail');
+   * (function(){ throw new Error('fail') }).should.throw(/fail/);
+   *
+   * (function(){ throw new Error('fail') }).should.throw(Error);
+   * var error = new Error();
+   * error.a = 10;
+   * (function(){ throw error; }).should.throw(Error, { a: 10 });
+   * (function(){ throw error; }).should.throw({ a: 10 });
+   * (function*() {
+   *   yield throwError();
+   * }).should.throw();
+   */
+  Assertion.add('throw', function(message, properties) {
+    var fn = this.obj
+      , err = {}
+      , errorInfo = ''
+      , thrown = false;
+
+    if(util.isGeneratorFunction(fn)) {
+      return should(fn()).throw(message, properties);
+    } else if(util.isGeneratorObject(fn)) {
+      return should(fn.next.bind(fn)).throw(message, properties);
+    }
+
+    this.is.a.Function();
+
+    var errorMatched = true;
+
+    try {
+      fn();
+    } catch(e) {
+      thrown = true;
+      err = e;
+    }
+
+    if(thrown) {
+      if(message) {
+        if('string' == typeof message) {
+          errorMatched = message == err.message;
+        } else if(message instanceof RegExp) {
+          errorMatched = message.test(err.message);
+        } else if('function' == typeof message) {
+          errorMatched = err instanceof message;
+        } else if(null != message) {
+          try {
+            should(err).match(message);
+          } catch(e) {
+            if(e instanceof should.AssertionError) {
+              errorInfo = ": " + e.message;
+              errorMatched = false;
+            } else {
+              throw e;
+            }
+          }
+        }
+
+        if(!errorMatched) {
+          if('string' == typeof message || message instanceof RegExp) {
+            errorInfo = " with a message matching " + i(message) + ", but got '" + err.message + "'";
+          } else if('function' == typeof message) {
+            errorInfo = " of type " + util.functionName(message) + ", but got " + util.functionName(err.constructor);
+          }
+        } else if('function' == typeof message && properties) {
+          try {
+            should(err).match(properties);
+          } catch(e) {
+            if(e instanceof should.AssertionError) {
+              errorInfo = ": " + e.message;
+              errorMatched = false;
+            } else {
+              throw e;
+            }
+          }
+        }
+      } else {
+        errorInfo = " (got " + i(err) + ")";
+      }
+    }
+
+    this.params = { operator: 'to throw exception' + errorInfo };
+
+    this.assert(thrown);
+    this.assert(errorMatched);
+  });
+
+  Assertion.alias('throw', 'throwError');
+};
+
+},{"../util":20}],13:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util');
+var eql = require('should-equal');
+
+module.exports = function(should, Assertion) {
+  var i = should.format;
+
+  /**
+   * Asserts if given object match `other` object, using some assumptions:
+   * First object matched if they are equal,
+   * If `other` is a regexp and given object is a string check on matching with regexp
+   * If `other` is a regexp and given object is an array check if all elements matched regexp
+   * If `other` is a regexp and given object is an object check values on matching regexp
+   * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
+   * If `other` is an object check if the same keys matched with above rules
+   * All other cases failed.
+   *
+   * Usually it is right idea to add pre type assertions, like `.String()` or `.Object()` to be sure assertions will do what you are expecting.
+   * Object iteration happen by keys (properties with enumerable: true), thus some objects can cause small pain. Typical example is js
+   * Error - it by default has 2 properties `name` and `message`, but they both non-enumerable. In this case make sure you specify checking props (see examples).
+   *
+   * @name match
+   * @memberOf Assertion
+   * @category assertion matching
+   * @param {*} other Object to match
+   * @param {string} [description] Optional message
+   * @example
+   * 'foobar'.should.match(/^foo/);
+   * 'foobar'.should.not.match(/^bar/);
+   *
+   * ({ a: 'foo', c: 'barfoo' }).should.match(/foo$/);
+   *
+   * ['a', 'b', 'c'].should.match(/[a-z]/);
+   *
+   * (5).should.not.match(function(n) {
+   *   return n < 0;
+   * });
+   * (5).should.not.match(function(it) {
+   *    it.should.be.an.Array();
+   * });
+   * ({ a: 10, b: 'abc', c: { d: 10 }, d: 0 }).should
+   * .match({ a: 10, b: /c$/, c: function(it) {
+   *    return it.should.have.property('d', 10);
+   * }});
+   *
+   * [10, 'abc', { d: 10 }, 0].should
+   * .match({ '0': 10, '1': /c$/, '2': function(it) {
+   *    return it.should.have.property('d', 10);
+   * }});
+   *
+   * var myString = 'abc';
+   *
+   * myString.should.be.a.String().and.match(/abc/);
+   *
+   * myString = {};
+   *
+   * myString.should.match(/abc/); //yes this will pass
+   * //better to do
+   * myString.should.be.an.Object().and.not.empty().and.match(/abc/);//fixed
+   *
+   * (new Error('boom')).should.match(/abc/);//passed because no keys
+   * (new Error('boom')).should.not.match({ message: /abc/ });//check specified property
+   */
+  Assertion.add('match', function(other, description) {
+    this.params = {operator: 'to match ' + i(other), message: description};
+
+    if(!eql(this.obj, other).result) {
+      if(other instanceof RegExp) { // something - regex
+
+        if(typeof this.obj == 'string') {
+
+          this.assert(other.exec(this.obj));
+        } else if(util.isIndexable(this.obj)) {
+          util.forEach(this.obj, function(item) {
+            this.assert(other.exec(item));// should we try to convert to String and exec?
+          }, this);
+        } else if(null != this.obj && typeof this.obj == 'object') {
+
+          var notMatchedProps = [], matchedProps = [];
+          util.forEach(this.obj, function(value, name) {
+            if(other.exec(value)) matchedProps.push(util.formatProp(name));
+            else notMatchedProps.push(util.formatProp(name) + ' (' + i(value) + ')');
+          }, this);
+
+          if(notMatchedProps.length)
+            this.params.operator += '\n    not matched properties: ' + notMatchedProps.join(', ');
+          if(matchedProps.length)
+            this.params.operator += '\n    matched properties: ' + matchedProps.join(', ');
+
+          this.assert(notMatchedProps.length === 0);
+        } // should we try to convert to String and exec?
+      } else if(typeof other == 'function') {
+        var res;
+
+        res = other(this.obj);
+
+        //if(res instanceof Assertion) {
+        //  this.params.operator += '\n    ' + res.getMessage();
+        //}
+
+        //if we throw exception ok - it is used .should inside
+        if(typeof res == 'boolean') {
+          this.assert(res); // if it is just boolean function assert on it
+        }
+      } else if(other != null && this.obj != null && typeof other == 'object') { // try to match properties (for Object and Array)
+        notMatchedProps = [];
+        matchedProps = [];
+
+        util.forEach(other, function(value, key) {
+          try {
+            should(this.obj).have.property(key).which.match(value);
+            matchedProps.push(util.formatProp(key));
+          } catch(e) {
+            if(e instanceof should.AssertionError) {
+              notMatchedProps.push(util.formatProp(key) + ' (' + i(this.obj[key]) + ')');
+            } else {
+              throw e;
+            }
+          }
+        }, this);
+
+        if(notMatchedProps.length)
+          this.params.operator += '\n    not matched properties: ' + notMatchedProps.join(', ');
+        if(matchedProps.length)
+          this.params.operator += '\n    matched properties: ' + matchedProps.join(', ');
+
+        this.assert(notMatchedProps.length === 0);
+      } else {
+        this.assert(false);
+      }
+    }
+  });
+
+  /**
+   * Asserts if given object values or array elements all match `other` object, using some assumptions:
+   * First object matched if they are equal,
+   * If `other` is a regexp - matching with regexp
+   * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
+   * All other cases check if this `other` equal to each element
+   *
+   * @name matchEach
+   * @memberOf Assertion
+   * @category assertion matching
+   * @alias Assertion#matchSome
+   * @param {*} other Object to match
+   * @param {string} [description] Optional message
+   * @example
+   * [ 'a', 'b', 'c'].should.matchEach(/\w+/);
+   * [ 'a', 'a', 'a'].should.matchEach('a');
+   *
+   * [ 'a', 'a', 'a'].should.matchEach(function(value) { value.should.be.eql('a') });
+   *
+   * { a: 'a', b: 'a', c: 'a' }.should.matchEach(function(value) { value.should.be.eql('a') });
+   */
+  Assertion.add('matchEach', function(other, description) {
+    this.params = {operator: 'to match each ' + i(other), message: description};
+
+    util.forEach(this.obj, function(value) {
+      should(value).match(other);
+    }, this);
+  });
+
+  /**
+  * Asserts if any of given object values or array elements match `other` object, using some assumptions:
+  * First object matched if they are equal,
+  * If `other` is a regexp - matching with regexp
+  * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
+  * All other cases check if this `other` equal to each element
+  *
+  * @name matchAny
+  * @memberOf Assertion
+  * @category assertion matching
+  * @param {*} other Object to match
+  * @alias Assertion#matchEvery
+  * @param {string} [description] Optional message
+  * @example
+  * [ 'a', 'b', 'c'].should.matchAny(/\w+/);
+  * [ 'a', 'b', 'c'].should.matchAny('a');
+  *
+  * [ 'a', 'b', 'c'].should.matchAny(function(value) { value.should.be.eql('a') });
+  *
+  * { a: 'a', b: 'b', c: 'c' }.should.matchAny(function(value) { value.should.be.eql('a') });
+  */
+  Assertion.add('matchAny', function(other, description) {
+    this.params = {operator: 'to match any ' + i(other), message: description};
+
+    this.assert(util.some(this.obj, function(value) {
+      try {
+        should(value).match(other);
+        return true;
+      } catch(e) {
+        if(e instanceof should.AssertionError) {
+          // Caught an AssertionError, return false to the iterator
+          return false;
+        }
+        throw e;
+      }
+    }));
+  });
+
+  Assertion.alias('matchAny', 'matchSome');
+  Assertion.alias('matchEach', 'matchEvery');
+};
+
+},{"../util":20,"should-equal":22}],14:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+module.exports = function(should, Assertion) {
+
+  /**
+   * Assert given object is NaN
+   * @name NaN
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @example
+   *
+   * (10).should.not.be.NaN();
+   * NaN.should.be.NaN();
+   */
+  Assertion.add('NaN', function() {
+    this.params = { operator: 'to be NaN' };
+
+    this.assert(this.obj !== this.obj);
+  });
+
+  /**
+   * Assert given object is not finite (positive or negative)
+   *
+   * @name Infinity
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @example
+   *
+   * (10).should.not.be.Infinity();
+   * NaN.should.not.be.Infinity();
+   */
+  Assertion.add('Infinity', function() {
+    this.params = { operator: 'to be Infinity' };
+
+    this.is.a.Number()
+      .and.not.a.NaN()
+      .and.assert(!isFinite(this.obj));
+  });
+
+  /**
+   * Assert given number between `start` and `finish` or equal one of them.
+   *
+   * @name within
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} start Start number
+   * @param {number} finish Finish number
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (10).should.be.within(0, 20);
+   */
+  Assertion.add('within', function(start, finish, description) {
+    this.params = { operator: 'to be within ' + start + '..' + finish, message: description };
+
+    this.assert(this.obj >= start && this.obj <= finish);
+  });
+
+  /**
+   * Assert given number near some other `value` within `delta`
+   *
+   * @name approximately
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} value Center number
+   * @param {number} delta Radius
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (9.99).should.be.approximately(10, 0.1);
+   */
+  Assertion.add('approximately', function(value, delta, description) {
+    this.params = { operator: 'to be approximately ' + value + ' ±' + delta, message: description };
+
+    this.assert(Math.abs(this.obj - value) <= delta);
+  });
+
+  /**
+   * Assert given number above `n`.
+   *
+   * @name above
+   * @alias Assertion#greaterThan
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} n Margin number
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (10).should.be.above(0);
+   */
+  Assertion.add('above', function(n, description) {
+    this.params = { operator: 'to be above ' + n, message: description };
+
+    this.assert(this.obj > n);
+  });
+
+  /**
+   * Assert given number below `n`.
+   *
+   * @name below
+   * @alias Assertion#lessThan
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} n Margin number
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (0).should.be.below(10);
+   */
+  Assertion.add('below', function(n, description) {
+    this.params = { operator: 'to be below ' + n, message: description };
+
+    this.assert(this.obj < n);
+  });
+
+  Assertion.alias('above', 'greaterThan');
+  Assertion.alias('below', 'lessThan');
+
+  /**
+   * Assert given number above `n`.
+   *
+   * @name aboveOrEqual
+   * @alias Assertion#greaterThanOrEqual
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} n Margin number
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (10).should.be.aboveOrEqual(0);
+   * (10).should.be.aboveOrEqual(10);
+   */
+  Assertion.add('aboveOrEqual', function(n, description) {
+    this.params = { operator: 'to be above or equal' + n, message: description };
+
+    this.assert(this.obj >= n);
+  });
+
+  /**
+   * Assert given number below `n`.
+   *
+   * @name belowOrEqual
+   * @alias Assertion#lessThanOrEqual
+   * @memberOf Assertion
+   * @category assertion numbers
+   * @param {number} n Margin number
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * (0).should.be.belowOrEqual(10);
+   * (0).should.be.belowOrEqual(0);
+   */
+  Assertion.add('belowOrEqual', function(n, description) {
+    this.params = { operator: 'to be below or equal' + n, message: description };
+
+    this.assert(this.obj <= n);
+  });
+
+  Assertion.alias('aboveOrEqual', 'greaterThanOrEqual');
+  Assertion.alias('belowOrEqual', 'lessThanOrEqual');
+
+};
+
+},{}],15:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util');
+var PromisedAssertion = require('../assertion').PromisedAssertion;
+var Assertion = require('../assertion');
+
+module.exports = function(should) {
+  /**
+   * Assert given object is a Promise
+   *
+   * @name Promise
+   * @memberOf Assertion
+   * @category assertion promises
+   * @example
+   *
+   * promise.should.be.Promise()
+   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.a.Promise()
+   * (10).should.not.be.a.Promise()
+   */
+  Assertion.add('Promise', function() {
+    this.params = {operator: 'to be promise'};
+
+    var obj = this.obj;
+
+    should(obj).have.property('then')
+      .which.is.a.Function();
+  });
+
+  /**
+   * Assert given promise will be fulfilled
+   *
+   * @name fulfilled
+   * @memberOf Assertion
+   * @returns {Promise}
+   * @category assertion promises
+   * @example
+   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.fulfilled()
+   */
+  Assertion.prototype.fulfilled = function Assertion$fulfilled() {
+    this.params = {operator: 'to be fulfilled'};
+
+    should(this.obj).be.a.Promise();
+
+    var that = this;
+    return this.obj.then(function next$onResolve(value) {
+      if (that.negate) {
+        that.fail();
+      }
+      return value;
+    }, function next$onReject(err) {
+      if (!that.negate) {
+        that.fail();
+      }
+      return err;
+    });
+  };
+
+  /**
+   * Assert given promise will be rejected
+   *
+   * @name rejected
+   * @memberOf Assertion
+   * @category assertion promises
+   * @returns {Promise}
+   * @example
+   * (new Promise(function(resolve, reject) { resolve(10); })).should.not.be.rejected()
+   */
+  Assertion.prototype.rejected = function() {
+    this.params = {operator: 'to be rejected'};
+
+    should(this.obj).be.a.Promise();
+
+    var that = this;
+    return this.obj.then(function(value) {
+      if (!that.negate) {
+        that.fail();
+      }
+      return value;
+    }, function next$onError(err) {
+      if (that.negate) {
+        that.fail();
+      }
+      return err;
+    });
+  };
+
+  /**
+   * Assert given promise will be fulfilled with some expected value.
+   *
+   * @name fulfilledWith
+   * @memberOf Assertion
+   * @category assertion promises
+   * @returns {Promise}
+   * @example
+   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.fulfilledWith(10)
+   */
+  Assertion.prototype.fulfilledWith = function(expectedValue) {
+    this.params = {operator: 'to be fulfilled'};
+
+    should(this.obj).be.a.Promise();
+
+    var that = this;
+    return this.obj.then(function(value) {
+      if (that.negate) {
+        that.fail();
+      }
+      should(value).eql(expectedValue);
+      return value;
+    }, function next$onError(err) {
+      if (!that.negate) {
+        that.fail();
+      }
+      return err;
+    });
+  };
+
+  /**
+   * Assert given promise will be rejected with some sort of error. Arguments is the same for Assertion#throw
+   *
+   * @name rejectedWith
+   * @memberOf Assertion
+   * @category assertion promises
+   * @returns {Promise}
+   * @example
+   *
+   * function failedPromise() {
+  *   return new Promise(function(resolve, reject) {
+  *     reject(new Error('boom'))
+  *   })
+  * }
+   * failedPromise().should.be.rejectedWith(Error)
+   * failedPromise().should.be.rejectedWith('boom')
+   * failedPromise().should.be.rejectedWith(/boom/)
+   * failedPromise().should.be.rejectedWith(Error, { message: 'boom' })
+   * failedPromise().should.be.rejectedWith({ message: 'boom' })
+   */
+  Assertion.prototype.rejectedWith = function(message, properties) {
+    this.params = {operator: 'to be rejected'};
+
+    should(this.obj).be.a.Promise();
+
+    var that = this;
+    return this.obj.then(function(value) {
+      if (!that.negate) {
+        that.fail();
+      }
+      return value;
+    }, function next$onError(err) {
+      if (that.negate) {
+        that.fail();
+      }
+
+      var errorMatched = true;
+      var errorInfo = '';
+
+      if ('string' === typeof message) {
+        errorMatched = message === err.message;
+      } else if (message instanceof RegExp) {
+        errorMatched = message.test(err.message);
+      } else if ('function' === typeof message) {
+        errorMatched = err instanceof message;
+      } else if (message !== null && typeof message === 'object') {
+        try {
+          should(err).match(message);
+        } catch (e) {
+          if (e instanceof should.AssertionError) {
+            errorInfo = ': ' + e.message;
+            errorMatched = false;
+          } else {
+            throw e;
+          }
+        }
+      }
+
+      if (!errorMatched) {
+        if ( typeof message === 'string' || message instanceof RegExp) {
+          errorInfo = ' with a message matching ' + should.format(message) + ", but got '" + err.message + "'";
+        } else if ('function' === typeof message) {
+          errorInfo = ' of type ' + util.functionName(message) + ', but got ' + util.functionName(err.constructor);
+        }
+      } else if ('function' === typeof message && properties) {
+        try {
+          should(err).match(properties);
+        } catch (e) {
+          if (e instanceof should.AssertionError) {
+            errorInfo = ': ' + e.message;
+            errorMatched = false;
+          } else {
+            throw e;
+          }
+        }
+      }
+
+      that.params.operator += errorInfo;
+
+      that.assert(errorMatched);
+
+      return err;
+    });
+  };
+
+  /**
+   * Assert given object is promise and wrap it in PromisedAssertion, which has all properties of Assertion. That means you can chain as with usual Assertion.
+   *
+   * @name finally
+   * @memberOf Assertion
+   * @alias Assertion#eventually
+   * @category assertion promises
+   * @returns {PromisedAssertion} Like Assertion, but .then this.obj in Assertion
+   * @example
+   *
+   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.eventually.equal(10)
+   */
+  Object.defineProperty(Assertion.prototype, 'finally', {
+    get: function() {
+      should(this.obj).be.a.Promise();
+
+      var that = this;
+
+      return new PromisedAssertion(this.obj.then(function(obj) {
+        var a = should(obj);
+
+        a.negate = that.negate;
+        a.anyOne = that.anyOne;
+
+        return a;
+      }));
+    }
+  });
+
+  Assertion.alias('finally', 'eventually');
+};
+
+},{"../assertion":4,"../util":20}],16:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util');
+var eql = require('should-equal');
+
+var aSlice = Array.prototype.slice;
+
+module.exports = function(should, Assertion) {
+  var i = should.format;
+  /**
+   * Asserts given object has some descriptor. **On success it change given object to be value of property**.
+   *
+   * @name propertyWithDescriptor
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {string} name Name of property
+   * @param {Object} desc Descriptor like used in Object.defineProperty (not required to add all properties)
+   * @example
+   *
+   * ({ a: 10 }).should.have.propertyWithDescriptor('a', { enumerable: true });
+   */
+  Assertion.add('propertyWithDescriptor', function(name, desc) {
+    this.params = {actual: this.obj, operator: 'to have own property with descriptor ' + i(desc)};
+    var obj = this.obj;
+    this.have.ownProperty(name);
+    should(Object.getOwnPropertyDescriptor(Object(obj), name)).have.properties(desc);
+  });
+
+  function processPropsArgs() {
+    var args = {};
+    if(arguments.length > 1) {
+      args.names = aSlice.call(arguments);
+    } else {
+      var arg = arguments[0];
+      if(typeof arg === 'string') {
+        args.names = [arg];
+      } else if(util.isIndexable(arg)) {
+        args.names = arg;
+      } else {
+        args.names = Object.keys(arg);
+        args.values = arg;
+      }
+    }
+    return args;
+  }
+
+
+  /**
+   * Asserts given object has enumerable property with optionally value. **On success it change given object to be value of property**.
+   *
+   * @name enumerable
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {string} name Name of property
+   * @param {*} [val] Optional property value to check
+   * @example
+   *
+   * ({ a: 10 }).should.have.enumerable('a');
+   */
+  Assertion.add('enumerable', function(name, val) {
+    name = util.convertPropertyName(name);
+
+    this.params = {
+      operator: "to have enumerable property " + util.formatProp(name) + (arguments.length > 1 ? " equal to " + i(val): "")
+    };
+
+    var desc = { enumerable: true };
+    if(arguments.length > 1) desc.value = val;
+    this.have.propertyWithDescriptor(name, desc);
+  });
+
+  /**
+   * Asserts given object has enumerable properties
+   *
+   * @name enumerables
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {Array|...string|Object} names Names of property
+   * @example
+   *
+   * ({ a: 10, b: 10 }).should.have.enumerables('a');
+   */
+  Assertion.add('enumerables', function(names) {
+    var args = processPropsArgs.apply(null, arguments);
+
+    this.params = {
+      operator: "to have enumerables " + args.names.map(util.formatProp)
+    };
+
+    var obj = this.obj;
+    args.names.forEach(function(name) {
+      should(obj).have.enumerable(name);
+    });
+  });
+
+  /**
+   * Asserts given object has property with optionally value. **On success it change given object to be value of property**.
+   *
+   * @name property
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {string} name Name of property
+   * @param {*} [val] Optional property value to check
+   * @example
+   *
+   * ({ a: 10 }).should.have.property('a');
+   */
+  Assertion.add('property', function(name, val) {
+    name = util.convertPropertyName(name);
+    if(arguments.length > 1) {
+      var p = {};
+      p[name] = val;
+      this.have.properties(p);
+    } else {
+      this.have.properties(name);
+    }
+    this.obj = this.obj[name];
+  });
+
+  /**
+   * Asserts given object has properties. On this method affect .any modifier, which allow to check not all properties.
+   *
+   * @name properties
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {Array|...string|Object} names Names of property
+   * @example
+   *
+   * ({ a: 10 }).should.have.properties('a');
+   * ({ a: 10, b: 20 }).should.have.properties([ 'a' ]);
+   * ({ a: 10, b: 20 }).should.have.properties({ b: 20 });
+   */
+  Assertion.add('properties', function(names) {
+    var values = {};
+    if(arguments.length > 1) {
+      names = aSlice.call(arguments);
+    } else if(!Array.isArray(names)) {
+      if(typeof names == 'string' || typeof names == 'symbol') {
+        names = [names];
+      } else {
+        values = names;
+        names = Object.keys(names);
+      }
+    }
+
+    var obj = Object(this.obj), missingProperties = [];
+
+    //just enumerate properties and check if they all present
+    names.forEach(function(name) {
+      if(!(name in obj)) missingProperties.push(util.formatProp(name));
+    });
+
+    var props = missingProperties;
+    if(props.length === 0) {
+      props = names.map(util.formatProp);
+    } else if(this.anyOne) {
+      props = names.filter(function(name) {
+        return missingProperties.indexOf(util.formatProp(name)) < 0;
+      }).map(util.formatProp);
+    }
+
+    var operator = (props.length === 1 ?
+        'to have property ' : 'to have ' + (this.anyOne ? 'any of ' : '') + 'properties ') + props.join(', ');
+
+    this.params = {obj: this.obj, operator: operator};
+
+    //check that all properties presented
+    //or if we request one of them that at least one them presented
+    this.assert(missingProperties.length === 0 || (this.anyOne && missingProperties.length != names.length));
+
+    // check if values in object matched expected
+    var valueCheckNames = Object.keys(values);
+    if(valueCheckNames.length) {
+      var wrongValues = [];
+      props = [];
+
+      // now check values, as there we have all properties
+      valueCheckNames.forEach(function(name) {
+        var value = values[name];
+        if(!eql(obj[name], value).result) {
+          wrongValues.push(util.formatProp(name) + ' of ' + i(value) + ' (got ' + i(obj[name]) + ')');
+        } else {
+          props.push(util.formatProp(name) + ' of ' + i(value));
+        }
+      });
+
+      if((wrongValues.length !== 0 && !this.anyOne) || (this.anyOne && props.length === 0)) {
+        props = wrongValues;
+      }
+
+      operator = (props.length === 1 ?
+        'to have property ' : 'to have ' + (this.anyOne ? 'any of ' : '') + 'properties ') + props.join(', ');
+
+      this.params = {obj: this.obj, operator: operator};
+
+      //if there is no not matched values
+      //or there is at least one matched
+      this.assert(wrongValues.length === 0 || (this.anyOne && wrongValues.length != valueCheckNames.length));
+    }
+  });
+
+  /**
+   * Asserts given object has property `length` with given value `n`
+   *
+   * @name length
+   * @alias Assertion#lengthOf
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {number} n Expected length
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * [1, 2].should.have.length(2);
+   */
+  Assertion.add('length', function(n, description) {
+    this.have.property('length', n, description);
+  });
+
+  Assertion.alias('length', 'lengthOf');
+
+  var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+  /**
+   * Asserts given object has own property. **On success it change given object to be value of property**.
+   *
+   * @name ownProperty
+   * @alias Assertion#hasOwnProperty
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {string} name Name of property
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * ({ a: 10 }).should.have.ownProperty('a');
+   */
+  Assertion.add('ownProperty', function(name, description) {
+    name = util.convertPropertyName(name);
+    this.params = {
+      actual: this.obj,
+      operator: 'to have own property ' + util.formatProp(name),
+      message: description
+    };
+
+    this.assert(hasOwnProperty.call(this.obj, name));
+
+    this.obj = this.obj[name];
+  });
+
+  Assertion.alias('ownProperty', 'hasOwnProperty');
+
+  /**
+   * Asserts given object is empty. For strings, arrays and arguments it checks .length property, for objects it checks keys.
+   *
+   * @name empty
+   * @memberOf Assertion
+   * @category assertion property
+   * @example
+   *
+   * ''.should.be.empty();
+   * [].should.be.empty();
+   * ({}).should.be.empty();
+   */
+  Assertion.add('empty', function() {
+    this.params = {operator: 'to be empty'};
+
+    if(util.length(this.obj) !== void 0) {
+      should(this.obj).have.property('length', 0);
+    } else {
+      var obj = Object(this.obj); // wrap to reference for booleans and numbers
+      for(var prop in obj) {
+        should(this.obj).not.have.ownProperty(prop);
+      }
+    }
+  }, true);
+
+  /**
+   * Asserts given object has exact keys. Compared to `properties`, `keys` does not accept Object as a argument.
+   *
+   * @name keys
+   * @alias Assertion#key
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {Array|...string} [keys] Keys to check
+   * @example
+   *
+   * ({ a: 10 }).should.have.keys('a');
+   * ({ a: 10, b: 20 }).should.have.keys('a', 'b');
+   * ({ a: 10, b: 20 }).should.have.keys([ 'a', 'b' ]);
+   * ({}).should.have.keys();
+   */
+  Assertion.add('keys', function(keys) {
+    if(arguments.length > 1) keys = aSlice.call(arguments);
+    else if(arguments.length === 1 && typeof keys === 'string') keys = [keys];
+    else if(arguments.length === 0) keys = [];
+
+    keys = keys.map(String);
+
+    var obj = Object(this.obj);
+
+    // first check if some keys are missing
+    var missingKeys = [];
+    keys.forEach(function(key) {
+      if(!hasOwnProperty.call(this.obj, key))
+        missingKeys.push(util.formatProp(key));
+    }, this);
+
+    // second check for extra keys
+    var extraKeys = [];
+    Object.keys(obj).forEach(function(key) {
+      if(keys.indexOf(key) < 0) {
+        extraKeys.push(util.formatProp(key));
+      }
+    });
+
+    var verb = keys.length === 0 ? 'to be empty' :
+    'to have ' + (keys.length === 1 ? 'key ' : 'keys ');
+
+    this.params = {operator: verb + keys.map(util.formatProp).join(', ')};
+
+    if(missingKeys.length > 0)
+      this.params.operator += '\n\tmissing keys: ' + missingKeys.join(', ');
+
+    if(extraKeys.length > 0)
+      this.params.operator += '\n\textra keys: ' + extraKeys.join(', ');
+
+    this.assert(missingKeys.length === 0 && extraKeys.length === 0);
+  });
+
+  Assertion.alias("keys", "key");
+
+  /**
+   * Asserts given object has nested property in depth by path. **On success it change given object to be value of final property**.
+   *
+   * @name propertyByPath
+   * @memberOf Assertion
+   * @category assertion property
+   * @param {Array|...string} properties Properties path to search
+   * @example
+   *
+   * ({ a: {b: 10}}).should.have.propertyByPath('a', 'b').eql(10);
+   */
+  Assertion.add('propertyByPath', function(properties) {
+    if(arguments.length > 1) properties = aSlice.call(arguments);
+    else if(arguments.length === 1 && typeof properties == 'string') properties = [properties];
+    else if(arguments.length === 0) properties = [];
+
+    var allProps = properties.map(util.formatProp);
+
+    properties = properties.map(String);
+
+    var obj = should(Object(this.obj));
+
+    var foundProperties = [];
+
+    var currentProperty;
+    while(currentProperty = properties.shift()) {
+      this.params = {operator: 'to have property by path ' + allProps.join(', ') + ' - failed on ' + util.formatProp(currentProperty)};
+      obj = obj.have.property(currentProperty);
+      foundProperties.push(currentProperty);
+    }
+
+    this.params = {obj: this.obj, operator: 'to have property by path ' + allProps.join(', ')};
+
+    this.obj = obj.obj;
+  });
+};
+
+},{"../util":20,"should-equal":22}],17:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+module.exports = function(should, Assertion) {
+  /**
+   * Assert given string starts with prefix
+   * @name startWith
+   * @memberOf Assertion
+   * @category assertion strings
+   * @param {string} str Prefix
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * 'abc'.should.startWith('a');
+   */
+  Assertion.add('startWith', function(str, description) {
+    this.params = { operator: 'to start with ' + should.format(str), message: description };
+
+    this.assert(0 === this.obj.indexOf(str));
+  });
+
+  /**
+   * Assert given string starts with prefix
+   * @name endWith
+   * @memberOf Assertion
+   * @category assertion strings
+   * @param {string} str Prefix
+   * @param {string} [description] Optional message
+   * @example
+   *
+   * 'abca'.should.endWith('a');
+   */
+  Assertion.add('endWith', function(str, description) {
+    this.params = { operator: 'to end with ' + should.format(str), message: description };
+
+    this.assert(this.obj.indexOf(str, this.obj.length - str.length) >= 0);
+  });
+};
+
+},{}],18:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var util = require('../util');
+
+module.exports = function(should, Assertion) {
+  /**
+   * Assert given object is number
+   * @name Number
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Number', function() {
+    this.params = {operator: 'to be a number'};
+
+    this.have.type('number');
+  });
+
+  /**
+   * Assert given object is arguments
+   * @name arguments
+   * @alias Assertion#Arguments
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('arguments', function() {
+    this.params = {operator: 'to be arguments'};
+
+    this.have.class('Arguments');
+  });
+
+  Assertion.alias('arguments', 'Arguments');
+
+  /**
+   * Assert given object has some type using `typeof`
+   * @name type
+   * @memberOf Assertion
+   * @param {string} type Type name
+   * @param {string} [description] Optional message
+   * @category assertion types
+   */
+  Assertion.add('type', function(type, description) {
+    this.params = {operator: 'to have type ' + type, message: description};
+
+    should(typeof this.obj).be.exactly(type);
+  });
+
+  /**
+   * Assert given object is instance of `constructor`
+   * @name instanceof
+   * @alias Assertion#instanceOf
+   * @memberOf Assertion
+   * @param {Function} constructor Constructor function
+   * @param {string} [description] Optional message
+   * @category assertion types
+   */
+  Assertion.add('instanceof', function(constructor, description) {
+    this.params = {operator: 'to be an instance of ' + util.functionName(constructor), message: description};
+
+    this.assert(Object(this.obj) instanceof constructor);
+  });
+
+  Assertion.alias('instanceof', 'instanceOf');
+
+  /**
+   * Assert given object is function
+   * @name Function
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Function', function() {
+    this.params = {operator: 'to be a function'};
+
+    this.have.type('function');
+  });
+
+  /**
+   * Assert given object is object
+   * @name Object
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Object', function() {
+    this.params = {operator: 'to be an object'};
+
+    this.is.not.null().and.have.type('object');
+  });
+
+  /**
+   * Assert given object is string
+   * @name String
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('String', function() {
+    this.params = {operator: 'to be a string'};
+
+    this.have.type('string');
+  });
+
+  /**
+   * Assert given object is array
+   * @name Array
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Array', function() {
+    this.params = {operator: 'to be an array'};
+
+    this.have.class('Array');
+  });
+
+  /**
+   * Assert given object is boolean
+   * @name Boolean
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Boolean', function() {
+    this.params = {operator: 'to be a boolean'};
+
+    this.have.type('boolean');
+  });
+
+  /**
+   * Assert given object is error
+   * @name Error
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('Error', function() {
+    this.params = {operator: 'to be an error'};
+
+    this.have.instanceOf(Error);
+  });
+
+  /**
+   * Assert given object is null
+   * @name null
+   * @alias Assertion#Null
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('null', function() {
+    this.params = {operator: 'to be null'};
+
+    this.assert(this.obj === null);
+  });
+
+  Assertion.alias('null', 'Null');
+
+  /**
+   * Assert given object has some internal [[Class]], via Object.prototype.toString call
+   * @name class
+   * @alias Assertion#Class
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('class', function(cls) {
+    this.params = {operator: 'to have [[Class]] ' + cls};
+
+    this.assert(Object.prototype.toString.call(this.obj) === '[object ' + cls + ']');
+  });
+
+  Assertion.alias('class', 'Class');
+
+  /**
+   * Assert given object is undefined
+   * @name undefined
+   * @alias Assertion#Undefined
+   * @memberOf Assertion
+   * @category assertion types
+   */
+  Assertion.add('undefined', function() {
+    this.params = {operator: 'to be undefined'};
+
+    this.assert(this.obj === void 0);
+  });
+
+  Assertion.alias('undefined', 'Undefined');
+
+  /**
+   * Assert given object supports es6 iterable protocol (just check
+   * that object has property Symbol.iterator, which is a function)
+   * @name iterable
+   * @memberOf Assertion
+   * @category assertion es6
+   */
+  Assertion.add('iterable', function() {
+    this.params = {operator: 'to be iterable'};
+
+    should(this.obj).have.property(Symbol.iterator).which.is.a.Function();
+  });
+
+  /**
+   * Assert given object supports es6 iterator protocol (just check
+   * that object has property next, which is a function)
+   * @name iterator
+   * @memberOf Assertion
+   * @category assertion es6
+   */
+  Assertion.add('iterator', function() {
+    this.params = {operator: 'to be iterator'};
+
+    should(this.obj).have.property('next').which.is.a.Function();
+  });
+
+  /**
+   * Assert given object is a generator object
+   * @name generator
+   * @memberOf Assertion
+   * @category assertion es6
+   */
+  Assertion.add('generator', function() {
+    this.params = {operator: 'to be generator'};
+
+    should(this.obj).be.iterable
+      .and.iterator
+      .and.it.is.equal(this.obj[Symbol.iterator]());
+  });
+};
+
+},{"../util":20}],19:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+
+var util = require('./util');
+
+/**
+ * Our function should
+ *
+ * @param {*} obj Object to assert
+ * @returns {should.Assertion} Returns new Assertion for beginning assertion chain
+ * @example
+ *
+ * var should = require('should');
+ * should('abc').be.a.String();
+ */
+function should(obj) {
+  return (new should.Assertion(obj));
+}
+
+should.AssertionError = require('./assertion-error');
+should.Assertion = require('./assertion');
+
+should.format = util.format;
+should.type = require('should-type');
+should.util = util;
+
+/**
+ * Object with configuration.
+ * It contains such properties:
+ * * `checkProtoEql` boolean - Affect if `.eql` will check objects prototypes
+ * Also it can contain options for should-format.
+ *
+ * @type {Object}
+ * @memberOf should
+ * @static
+ * @example
+ *
+ * var a = { a: 10 }, b = Object.create(null);
+ * b.a = 10;
+ *
+ * a.should.be.eql(b);
+ * //not throws
+ *
+ * should.config.checkProtoEql = true;
+ * a.should.be.eql(b);
+ * //throws AssertionError: expected { a: 10 } to equal { a: 10 } (because A and B have different prototypes)
+ */
+should.config = require('./config');
+
+// Expose should to external world.
+exports = module.exports = should;
+
+/**
+ * Allow to extend given prototype with should property using given name. This getter will **unwrap** all standard wrappers like `Number`, `Boolean`, `String`.
+ * Using `should(obj)` is the equivalent of using `obj.should` with known issues (like nulls and method calls etc).
+ *
+ * @param {string} [propertyName] Name of property to add. Default is `'should'`.
+ * @param {Object} [proto] Prototype to extend with. Default is `Object.prototype`.
+ * @memberOf should
+ * @returns {{ name: string, descriptor: Object, proto: Object }} Descriptor enough to return all back
+ * @static
+ * @example
+ *
+ * var prev = should.extend('must', Object.prototype);
+ *
+ * 'abc'.must.startWith('a');
+ *
+ * var should = should.noConflict(prev);
+ * should.not.exist(Object.prototype.must);
+ */
+should.extend = function(propertyName, proto) {
+  propertyName = propertyName || 'should';
+  proto = proto || Object.prototype;
+
+  var prevDescriptor = Object.getOwnPropertyDescriptor(proto, propertyName);
+
+  Object.defineProperty(proto, propertyName, {
+    set: function() {
+    },
+    get: function() {
+      return should(util.isWrapperType(this) ? this.valueOf() : this);
+    },
+    configurable: true
+  });
+
+  return { name: propertyName, descriptor: prevDescriptor, proto: proto };
+};
+
+/**
+ * Delete previous extension. If `desc` missing it will remove default extension.
+ *
+ * @param {{ name: string, descriptor: Object, proto: Object }} [desc] Returned from `should.extend` object
+ * @memberOf should
+ * @returns {Function} Returns should function
+ * @static
+ * @example
+ *
+ * var should = require('should').noConflict();
+ *
+ * should(Object.prototype).not.have.property('should');
+ *
+ * var prev = should.extend('must', Object.prototype);
+ * 'abc'.must.startWith('a');
+ * should.noConflict(prev);
+ *
+ * should(Object.prototype).not.have.property('must');
+ */
+should.noConflict = function(desc) {
+  desc = desc || should._prevShould;
+
+  if(desc) {
+    delete desc.proto[desc.name];
+
+    if(desc.descriptor) {
+      Object.defineProperty(desc.proto, desc.name, desc.descriptor);
+    }
+  }
+  return should;
+};
+
+/**
+ * Simple utility function for a bit more easier should assertion extension
+ * @param {Function} f So called plugin function. It should accept 2 arguments: `should` function and `Assertion` constructor
+ * @memberOf should
+ * @returns {Function} Returns `should` function
+ * @static
+ * @example
+ *
+ * should.use(function(should, Assertion) {
+ *   Assertion.add('asset', function() {
+ *      this.params = { operator: 'to be asset' };
+ *
+ *      this.obj.should.have.property('id').which.is.a.Number();
+ *      this.obj.should.have.property('path');
+ *  })
+ * })
+ */
+should.use = function(f) {
+  f(should, should.Assertion);
+  return this;
+};
+
+should
+  .use(require('./ext/assert'))
+  .use(require('./ext/chain'))
+  .use(require('./ext/bool'))
+  .use(require('./ext/number'))
+  .use(require('./ext/eql'))
+  .use(require('./ext/type'))
+  .use(require('./ext/string'))
+  .use(require('./ext/property'))
+  .use(require('./ext/error'))
+  .use(require('./ext/match'))
+  .use(require('./ext/contain'))
+  .use(require('./ext/promise'));
+
+},{"./assertion":4,"./assertion-error":3,"./config":5,"./ext/assert":7,"./ext/bool":8,"./ext/chain":9,"./ext/contain":10,"./ext/eql":11,"./ext/error":12,"./ext/match":13,"./ext/number":14,"./ext/promise":15,"./ext/property":16,"./ext/string":17,"./ext/type":18,"./util":20,"should-type":25}],20:[function(require,module,exports){
+/*
+ * Should
+ * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+var type = require('should-type');
+var config = require('./config');
+
+/**
+ * Check if given obj just a primitive type wrapper
+ * @param {Object} obj
+ * @returns {boolean}
+ * @private
+ */
+exports.isWrapperType = function(obj) {
+  return obj instanceof Number || obj instanceof String || obj instanceof Boolean;
+};
+
+exports.merge = function(a, b) {
+  if(a && b) {
+    for(var key in b) {
+      a[key] = b[key];
+    }
+  }
+  return a;
+};
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+exports.forEach = function forEach(obj, f, context) {
+  if(exports.isGeneratorFunction(obj)) {
+    return forEach(obj(), f, context);
+  } else if (exports.isGeneratorObject(obj)) {
+    var value = obj.next();
+    while(!value.done) {
+      if(f.call(context, value.value, 'value', obj) === false)
+        return;
+      value = obj.next();
+    }
+  } else {
+    for(var prop in obj) {
+      if(hasOwnProperty.call(obj, prop)) {
+        if(f.call(context, obj[prop], prop, obj) === false)
+          return;
+      }
+    }
+  }
+};
+
+exports.some = function(obj, f, context) {
+  var res = false;
+  exports.forEach(obj, function(value, key) {
+    if(f.call(context, value, key, obj)) {
+      res = true;
+      return false;
+    }
+  }, context);
+  return res;
+};
+
+exports.isEmptyObject = function(obj) {
+  for(var prop in obj) {
+    if(hasOwnProperty.call(obj, prop)) {
+      return false;
+    }
+  }
+  return true;
+};
+
+exports.isIndexable = function(obj) {
+  var t = type(obj);
+  return (t.type === type.OBJECT && t.cls === type.ARRAY) ||
+   (t.type === type.OBJECT && t.cls === type.BUFFER) ||
+   (t.type === type.OBJECT && t.cls === type.ARGUMENTS) ||
+   (t.type === type.OBJECT && t.cls === type.ARRAY_BUFFER) ||
+   (t.type === type.OBJECT && t.cls === type.TYPED_ARRAY) ||
+   (t.type === type.OBJECT && t.cls === type.DATA_VIEW) ||
+   (t.type === type.OBJECT && t.cls === type.STRING) ||
+   (t.type === type.STRING);
+};
+
+exports.length = function(obj) {
+  var t = type(obj);
+  switch(t.type) {
+    case type.STRING:
+      return obj.length;
+    case type.OBJECT:
+      switch(t.cls) {
+        case type.ARRAY_BUFFER:
+        case type.TYPED_ARRAY:
+        case type.DATA_VIEW:
+          return obj.byteLength;
+
+        case type.ARRAY:
+        case type.BUFFER:
+        case type.ARGUMENTS:
+        case type.FUNCTION:
+          return obj.length;
+      }
+  }
+};
+
+exports.convertPropertyName = function(name) {
+  if(typeof name == 'symbol') {
+    return name;
+  } else {
+    return String(name);
+  }
+};
+
+exports.isGeneratorObject = function(obj) {
+  if(!obj) return false;
+
+  return typeof obj.next == 'function' &&
+          typeof obj[Symbol.iterator] == 'function' &&
+          obj[Symbol.iterator]() === obj;
+};
+
+//TODO find better way
+exports.isGeneratorFunction = function(f) {
+  if(typeof f != 'function') return false;
+
+  return /^function\s*\*\s*/.test(f.toString());
+};
+
+exports.format = function(value, opts) {
+  return config.getFormatter(opts).format(value);
+};
+
+exports.functionName = require('should-format').Formatter.functionName;
+
+exports.formatProp = function(value) {
+  return config.getFormatter().formatPropertyName(String(value));
+};
+
+},{"./config":5,"should-format":23,"should-type":25}],21:[function(require,module,exports){
+module.exports = function format(msg) {
+  var args = arguments;
+  for(var i = 1, l = args.length; i < l; i++) {
+    msg = msg.replace(/%s/, args[i]);
+  }
+  return msg;
+}
+
+},{}],22:[function(require,module,exports){
+var getType = require('should-type');
+var format = require('./format');
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function makeResult(r, path, reason, a, b) {
+  var o = {result: r};
+  if(!r) {
+    o.path = path;
+    o.reason = reason;
+    o.a = a;
+    o.b = b;
+  }
+  return o;
+}
+
+var EQUALS = makeResult(true);
+
+function typeToString(t) {
+  return t.type + (t.cls ? '(' + t.cls + (t.sub ? ' ' + t.sub : '') + ')' : '');
+}
+
+
+
+var REASON = {
+  PLUS_0_AND_MINUS_0: '+0 is not equal to -0',
+  DIFFERENT_TYPES: 'A has type %s and B has type %s',
+  NAN_NUMBER: 'NaN is not equal to any number',
+  EQUALITY: 'A is not equal to B',
+  EQUALITY_PROTOTYPE: 'A and B have different prototypes',
+  WRAPPED_VALUE: 'A wrapped value is not equal to B wrapped value',
+  FUNCTION_SOURCES: 'function A is not equal to B by source code value (via .toString call)',
+  MISSING_KEY: '%s has no key %s',
+  CIRCULAR_VALUES: 'A has circular reference that was visited not in the same time as B',
+  SET_MAP_MISSING_KEY: 'Set/Map missing key',
+  MAP_VALUE_EQUALITY: 'Values of the same key in A and B is not equal'
+};
+
+function eqInternal(a, b, opts, stackA, stackB, path) {
+  var r = EQUALS;
+
+  function result(comparison, reason) {
+    return makeResult(comparison, path, reason, a, b);
+  }
+
+  function checkPropertyEquality(property) {
+    return eqInternal(a[property], b[property], opts, stackA, stackB, path.concat([property]));
+  }
+
+
+  // equal a and b exit early
+  if(a === b) {
+    // check for +0 !== -0;
+    return result(a !== 0 || (1 / a == 1 / b), REASON.PLUS_0_AND_MINUS_0);
+  }
+
+  var l, p;
+
+  var typeA = getType(a),
+    typeB = getType(b);
+
+  // if objects has different types they are not equals
+  var typeDifferents = typeA.type !== typeB.type || typeA.cls !== typeB.cls;
+
+  if(typeDifferents || ((opts.checkSubType && typeA.sub !== typeB.sub) || !opts.checkSubType)) {
+    return result(false, format(REASON.DIFFERENT_TYPES, typeToString(typeA), typeToString(typeB)));
+  }
+
+  //early checks for types
+  switch(typeA.type) {
+    case 'number':
+      // NaN !== NaN
+      return (a !== a) ? result(b !== b, REASON.NAN_NUMBER)
+        // but treat `+0` vs. `-0` as not equal
+        : (a === 0 ? result(1 / a === 1 / b, REASON.PLUS_0_AND_MINUS_0) : result(a === b, REASON.EQUALITY));
+
+    case 'boolean':
+    case 'string':
+      return result(a === b, REASON.EQUALITY);
+
+    case 'function':
+      var fA = a.toString(), fB = b.toString();
+      r = eqInternal(fA, fB, opts, stackA, stackB, path);
+      if(!r.result) {
+        r.reason = REASON.FUNCTION_SOURCES;
+        return r;
+      }
+
+      break;//check user properties
+
+    case 'object':
+      // additional checks for object instances
+      switch(typeA.cls) {
+        // check regexp flags
+        // TODO add es6 flags
+        case 'regexp':
+          p = ['source', 'global', 'multiline', 'lastIndex', 'ignoreCase'];
+          while(p.length) {
+            r = checkPropertyEquality(p.shift());
+            if(!r.result) return r;
+          }
+          break;//check user properties
+
+        //check by timestamp only
+        case 'date':
+          if(+a !== +b) {
+            return result(false, REASON.EQUALITY);
+          }
+          break;//check user properties
+
+        //primitive type wrappers
+        case 'number':
+        case 'boolean':
+        case 'string':
+          r = eqInternal(a.valueOf(), b.valueOf(), opts, stackA, stackB, path);
+          if(!r.result) {
+            r.reason = REASON.WRAPPED_VALUE;
+            return r;
+          }
+          break;//check user properties
+
+        //node buffer
+        case 'buffer':
+          //if length different it is obviously different
+          r = checkPropertyEquality('length');
+          if(!r.result) return r;
+
+          l = a.length;
+          while(l--) {
+            r = checkPropertyEquality(l);
+            if(!r.result) return r;
+          }
+
+          //we do not check for user properties because
+          //node Buffer have some strange hidden properties
+          return EQUALS;
+
+        case 'error':
+          //check defined properties
+          p = ['name', 'message'];
+          while(p.length) {
+            r = checkPropertyEquality(p.shift());
+            if(!r.result) return r;
+          }
+
+          break;//check user properties
+
+        case 'array':
+        case 'arguments':
+        case 'typed-array':
+          r = checkPropertyEquality('length');
+          if(!r.result) return r;
+
+          break;//check user properties
+
+        case 'array-buffer':
+          r = checkPropertyEquality('byteLength');
+          if(!r.result) return r;
+
+          break;//check user properties
+
+        case 'map':
+        case 'set':
+          r = checkPropertyEquality('size');
+          if(!r.result) return r;
+
+          stackA.push(a);
+          stackB.push(b);
+
+          var itA = a.entries();
+          var nextA = itA.next();
+
+          while(!nextA.done) {
+            var key = nextA.value[0];
+            //first check for primitive key if we can do light check
+            //using .has and .get
+            if(getType(key).type != 'object') {
+              if(b.has(key)) {
+                if(typeA.cls == 'map') {
+                  //for map we also check its value to be equal
+                  var value = b.get(key);
+                  r = eqInternal(nextA.value[1], value, opts, stackA, stackB, path);
+                  if(!r.result) {
+                    r.a = nextA.value;
+                    r.b = value;
+                    r.reason = REASON.MAP_VALUE_EQUALITY;
+
+                    break;
+                  }
+                }
+
+              } else {
+                r = result(false, REASON.SET_MAP_MISSING_KEY);
+                r.a = key;
+                r.b = key;
+
+                break;
+              }
+            } else {
+              //heavy check
+              //we search by iterator for key equality using equal
+              var itB = b.entries();
+              var nextB = itB.next();
+
+              while(!nextB.done) {
+                //first check for keys
+                r = eqInternal(nextA.value[0], nextB.value[0], opts, stackA, stackB, path);
+
+                if(!r.result) {
+                  r.reason = REASON.SET_MAP_MISSING_KEY;
+                  r.a = key;
+                  r.b = key;
+                } else {
+                  if(typeA.cls == 'map') {
+                    r = eqInternal(nextA.value[1], nextB.value[1], opts, stackA, stackB, path);
+
+                    if(!r.result) {
+                      r.a = nextA.value;
+                      r.b = nextB.value;
+                      r.reason = REASON.MAP_VALUE_EQUALITY;
+                    }
+                  }
+
+                  break;
+                }
+
+                nextB = itB.next();
+              }
+            }
+
+            if(!r.result) {
+              break;
+            }
+
+            nextA = itA.next();
+          }
+
+          stackA.pop();
+          stackB.pop();
+
+          if(!r.result) {
+            r.reason = REASON.SET_MAP_MISSING_ENTRY;
+            return r;
+          }
+
+          break; //check user properties
+      }
+  }
+
+  // compare deep objects and arrays
+  // stacks contain references only
+  //
+
+  l = stackA.length;
+  while(l--) {
+    if(stackA[l] == a) {
+      return result(stackB[l] == b, REASON.CIRCULAR_VALUES);
+    }
+  }
+
+  // add `a` and `b` to the stack of traversed objects
+  stackA.push(a);
+  stackB.push(b);
+
+  var key;
+
+  for(key in b) {
+    if(hasOwnProperty.call(b, key)) {
+      r = result(hasOwnProperty.call(a, key), format(REASON.MISSING_KEY, 'A', key));
+      if(!r.result) {
+        break;
+      }
+
+      if(r.result) {
+        r = checkPropertyEquality(key);
+        if(!r.result) {
+          break;
+        }
+      }
+    }
+  }
+
+  if(r.result) {
+    // ensure both objects have the same number of properties
+    for(key in a) {
+      if(hasOwnProperty.call(a, key)) {
+        r = result(hasOwnProperty.call(b, key), format(REASON.MISSING_KEY, 'B', key));
+        if(!r.result) {
+          return r;
+        }
+      }
+    }
+  }
+
+  stackA.pop();
+  stackB.pop();
+
+  if(!r.result) return r;
+
+  var prototypesEquals = false, canComparePrototypes = false;
+
+  if(opts.checkProtoEql) {
+    if(Object.getPrototypeOf) {//TODO should i check prototypes for === or use eq?
+      prototypesEquals = Object.getPrototypeOf(a) === Object.getPrototypeOf(b);
+      canComparePrototypes = true;
+    } else if(a.__proto__ && b.__proto__) {
+      prototypesEquals = a.__proto__ === b.__proto__;
+      canComparePrototypes = true;
+    }
+
+    if(canComparePrototypes && !prototypesEquals) {
+      r = result(prototypesEquals, REASON.EQUALITY_PROTOTYPE);
+      r.showReason = true;
+      if(!r.result) {
+        return r;
+      }
+    }
+  }
+
+  return EQUALS;
+}
+
+var defaultOptions = {
+  checkProtoEql: true,
+  checkSubType: true
+};
+
+function eq(a, b, opts) {
+  opts = opts || {};
+  if(typeof opts.checkProtoEql !== 'boolean')
+    opts.checkProtoEql = defaultOptions.checkProtoEql;
+  if(typeof opts.checkSubType !== 'boolean')
+    opts.checkSubType = defaultOptions.checkSubType;
+
+  var r = eqInternal(a, b, opts, [], [], []);
+  return r;
+}
+
+module.exports = eq;
+
+eq.r = REASON;
+
+},{"./format":21,"should-type":25}],23:[function(require,module,exports){
+var getType = require('should-type');
+var util = require('./util');
+
+function genKeysFunc(f) {
+  return function(value) {
+    var k = f(value);
+    k.sort();
+    return k;
+  };
+}
+
+
+function Formatter(opts) {
+  opts = opts || {};
+
+  this.seen = [];
+  this.keys = genKeysFunc(opts.keys === false ? Object.getOwnPropertyNames : Object.keys);
+
+  this.maxLineLength = typeof opts.maxLineLength === 'number' ? opts.maxLineLength : 60;
+  this.propSep = opts.propSep || ',';
+
+  this.isUTCdate = !!opts.isUTCdate;
+}
+
+Formatter.prototype = {
+  constructor: Formatter,
+
+  format: function(value) {
+    var t = getType(value);
+    var name1 = t.type, name2 = t.type;
+    if(t.cls) {
+      name1 += '_' + t.cls;
+      name2 += '_' + t.cls;
+    }
+    if(t.sub) {
+      name2 += '_' + t.sub;
+    }
+    var f = this['_format_' + name2] || this['_format_' + name1] || this['_format_' + t.type] || this.defaultFormat;
+    return f.call(this, value).trim();
+  },
+
+  _formatObject: function(value, opts) {
+    opts = opts || {};
+    var mainKeys = opts.keys || this.keys(value);
+
+    var len = 0;
+
+    var formatPropertyValue = opts.formatPropertyValue || this.formatPropertyValue;
+    var formatPropertyName = opts.formatPropertyName || this.formatPropertyName;
+    var keyValueSep = opts.keyValueSep || ': ';
+    var keyFilter = opts.keyFilter || function() { return true; };
+
+    this.seen.push(value);
+    var keys = [];
+
+    mainKeys.forEach(function(key) {
+      if(!keyFilter(key)) return;
+
+      var fName = formatPropertyName.call(this, key);
+
+      var f = (fName ? fName + keyValueSep : '') + formatPropertyValue.call(this, value, key);
+      len += f.length;
+      keys.push(f);
+    }, this);
+    this.seen.pop();
+
+    (opts.additionalProperties || []).forEach(function(keyValue) {
+      var f = keyValue[0] + keyValueSep + this.format(keyValue[1]);
+      len += f.length;
+      keys.push(f);
+    }, this);
+
+    var prefix = opts.prefix || Formatter.constructorName(value) || '';
+    if(prefix.length > 0) prefix += ' ';
+
+    var lbracket, rbracket;
+    if(Array.isArray(opts.brackets)) {
+      lbracket = opts.brackets && opts.brackets[0];
+      rbracket = opts.brackets && opts.brackets[1];
+    } else {
+      lbracket = '{';
+      rbracket = '}';
+    }
+
+    var rootValue = opts.value || '';
+
+    if(keys.length === 0)
+      return rootValue || (prefix + lbracket + rbracket);
+
+    if(len <= this.maxLineLength) {
+      return prefix + lbracket + ' ' + (rootValue ? rootValue + ' ' : '') + keys.join(this.propSep + ' ') + ' ' + rbracket;
+    } else {
+      return prefix + lbracket + '\n' + (rootValue ? '  ' + rootValue + '\n' : '') + keys.map(util.addSpaces).join(this.propSep + '\n') + '\n' + rbracket;
+    }
+  },
+
+  formatObject: function(value, prefix, props) {
+    props = props || this.keys(value);
+
+    var len = 0;
+
+    this.seen.push(value);
+    props = props.map(function(prop) {
+      var f = this.formatProperty(value, prop);
+      len += f.length;
+      return f;
+    }, this);
+    this.seen.pop();
+
+    if(props.length === 0) return '{}';
+
+    if(len <= this.maxLineLength) {
+      return '{ ' + (prefix ? prefix + ' ' : '') + props.join(this.propSep + ' ') + ' }';
+    } else {
+      return '{' + '\n' + (prefix ? '  ' + prefix + '\n' : '') + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
+    }
+  },
+
+  formatPropertyName: function(name) {
+    return name.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/) ? name : this.format(name);
+  },
+
+  formatProperty: function(value, prop) {
+    var desc = Formatter.getPropertyDescriptor(value, prop);
+
+    var propName = this.formatPropertyName(prop);
+
+    var propValue = desc.get && desc.set ?
+      '[Getter/Setter]' : desc.get ?
+      '[Getter]' : desc.set ?
+      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
+      '[Circular]' :
+      this.format(desc.value);
+
+    return propName + ': ' + propValue;
+  },
+
+  formatPropertyValue: function(value, prop) {
+    var desc = Formatter.getPropertyDescriptor(value, prop);
+
+    var propValue = desc.get && desc.set ?
+      '[Getter/Setter]' : desc.get ?
+      '[Getter]' : desc.set ?
+      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
+      '[Circular]' :
+      this.format(desc.value);
+
+    return propValue;
+  }
+};
+
+Formatter.add = function add(type, cls, sub, f) {
+  var args = Array.prototype.slice.call(arguments);
+  f = args.pop();
+  Formatter.prototype['_format_' + args.join('_')] = f;
+};
+
+Formatter.formatObjectWithPrefix = function formatObjectWithPrefix(f) {
+  return function(value) {
+    var prefix = f.call(this, value);
+    var props = this.keys(value);
+    if(props.length == 0) return prefix;
+    else return this.formatObject(value, prefix, props);
+  };
+};
+
+var functionNameRE = /^\s*function\s*(\S*)\s*\(/;
+
+Formatter.functionName = function functionName(f) {
+  if(f.name) {
+    return f.name;
+  }
+  var name = f.toString().match(functionNameRE)[1];
+  return name;
+};
+
+Formatter.constructorName = function(obj) {
+  while (obj) {
+    var descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor');
+    if (descriptor !== undefined &&
+        typeof descriptor.value === 'function') {
+
+        var name = Formatter.functionName(descriptor.value);
+        if(name !== '') {
+          return name;
+        }
+    }
+
+    obj = Object.getPrototypeOf(obj);
+  }
+};
+
+Formatter.getPropertyDescriptor = function(obj, value) {
+  var desc;
+  try {
+    desc = Object.getOwnPropertyDescriptor(obj, value) || {value: obj[value]};
+  } catch(e) {
+    desc = {value: e};
+  }
+  return desc;
+};
+
+Formatter.generateFunctionForIndexedArray = function generateFunctionForIndexedArray(lengthProp, name, padding) {
+  return function(value) {
+    var max = this.byteArrayMaxLength || 50;
+    var length = value[lengthProp];
+    var formattedValues = [];
+    var len = 0;
+    for(var i = 0; i < max && i < length; i++) {
+      var b = value[i] || 0;
+      var v = util.pad0(b.toString(16), padding);
+      len += v.length;
+      formattedValues.push(v);
+    }
+    var prefix = value.constructor.name || name || '';
+    if(prefix) prefix += ' ';
+
+    if(formattedValues.length === 0)
+      return prefix + '[]';
+
+    if(len <= this.maxLineLength) {
+      return prefix + '[ ' + formattedValues.join(this.propSep + ' ') + ' ' + ']';
+    } else {
+      return prefix + '[\n' + formattedValues.map(util.addSpaces).join(this.propSep + '\n') + '\n' + ']';
+    }
+  };
+};
+
+Formatter.add('undefined', function() { return 'undefined' });
+Formatter.add('null', function() { return 'null' });
+Formatter.add('boolean', function(value) { return value ? 'true': 'false' });
+Formatter.add('symbol', function(value) { return value.toString() });
+
+['number', 'boolean'].forEach(function(name) {
+  Formatter.add('object', name, function(value) {
+    return this._formatObject(value, {
+      additionalProperties: [['[[PrimitiveValue]]', value.valueOf()]]
+    });
+  });
+});
+
+Formatter.add('object', 'string', function(value) {
+  var realValue = value.valueOf();
+
+  return this._formatObject(value, {
+    keyFilter: function(key) {
+      //skip useless indexed properties
+      return !(key.match(/\d+/) && parseInt(key, 10) < realValue.length);
+    },
+    additionalProperties: [['[[PrimitiveValue]]', realValue]]
+  });
+});
+
+Formatter.add('object', 'regexp', function(value) {
+  return this._formatObject(value, {
+    value: String(value)
+  });
+});
+
+Formatter.add('number', function(value) {
+  if(value === 0 && 1 / value < 0) return '-0';
+  return String(value);
+});
+
+Formatter.add('string', function(value) {
+  return '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+      .replace(/'/g, "\\'")
+      .replace(/\\"/g, '"') + '\'';
+});
+
+Formatter.add('object', function(value) {
+  return this._formatObject(value);
+});
+
+Formatter.add('object', 'arguments', function(value) {
+  return this._formatObject(value, {
+    prefix: 'Arguments',
+    formatPropertyName: function(key) {
+      if(!key.match(/\d+/)) {
+        return this.formatPropertyName(key);
+      }
+    },
+    brackets: ['[', ']']
+  });
+});
+
+Formatter.add('object', 'array', function(value) {
+  return this._formatObject(value, {
+    formatPropertyName: function(key) {
+      if(!key.match(/\d+/)) {
+        return this.formatPropertyName(key);
+      }
+    },
+    brackets: ['[', ']']
+  });
+});
+
+
+function formatDate(value, isUTC) {
+  var prefix = isUTC ? 'UTC' : '';
+
+  var date = value['get' + prefix + 'FullYear']() +
+    '-' +
+    util.pad0(value['get' + prefix + 'Month']() + 1, 2) +
+    '-' +
+    util.pad0(value['get' + prefix + 'Date'](), 2);
+
+  var time = util.pad0(value['get' + prefix + 'Hours'](), 2) +
+    ':' +
+    util.pad0(value['get' + prefix + 'Minutes'](), 2) +
+    ':' +
+    util.pad0(value['get' + prefix + 'Seconds'](), 2) +
+    '.' +
+    util.pad0(value['get' + prefix + 'Milliseconds'](), 3);
+
+  var to = value.getTimezoneOffset();
+  var absTo = Math.abs(to);
+  var hours = Math.floor(absTo / 60);
+  var minutes = absTo - hours * 60;
+  var tzFormat = (to < 0 ? '+' : '-') + util.pad0(hours, 2) + util.pad0(minutes, 2);
+
+  return date + ' ' + time + (isUTC ? '' : ' ' + tzFormat);
+}
+
+Formatter.add('object', 'date', function(value) {
+  return this._formatObject(value, { value: formatDate(value, this.isUTCdate) });
+});
+
+Formatter.add('function', function(value) {
+  return this._formatObject(value, {
+    additionalProperties: [['name', Formatter.functionName(value)]]
+  });
+});
+
+Formatter.add('object', 'error', function(value) {
+  return this._formatObject(value, {
+    prefix: value.name,
+    additionalProperties: [['message', value.message]]
+  });
+});
+
+Formatter.add('object', 'buffer', Formatter.generateFunctionForIndexedArray('length', 'Buffer', 2));
+
+Formatter.add('object', 'array-buffer', Formatter.generateFunctionForIndexedArray('byteLength', 'ArrayBuffer', 2));
+
+Formatter.add('object', 'typed-array', 'int8', Formatter.generateFunctionForIndexedArray('length', 'Int8Array', 2));
+Formatter.add('object', 'typed-array', 'uint8', Formatter.generateFunctionForIndexedArray('length', 'Uint8Array', 2));
+Formatter.add('object', 'typed-array', 'uint8clamped', Formatter.generateFunctionForIndexedArray('length', 'Uint8ClampedArray', 2));
+
+Formatter.add('object', 'typed-array', 'int16', Formatter.generateFunctionForIndexedArray('length', 'Int16Array', 4));
+Formatter.add('object', 'typed-array', 'uint16', Formatter.generateFunctionForIndexedArray('length', 'Uint16Array', 4));
+
+Formatter.add('object', 'typed-array', 'int32', Formatter.generateFunctionForIndexedArray('length', 'Int32Array', 8));
+Formatter.add('object', 'typed-array', 'uint32', Formatter.generateFunctionForIndexedArray('length', 'Uint32Array', 8));
+
+//TODO add float32 and float64
+
+Formatter.add('object', 'promise', function() {
+  return '[Promise]';//TODO it could be nice to inspect its state and value
+});
+
+Formatter.add('object', 'xhr', function() {
+  return '[XMLHttpRequest]';//TODO it could be nice to inspect its state
+});
+
+Formatter.add('object', 'html-element', function(value) {
+  return value.outerHTML;
+});
+
+Formatter.add('object', 'html-element', '#text', function(value) {
+  return value.nodeValue;
+});
+
+Formatter.add('object', 'html-element', '#document', function(value) {
+  return value.documentElement.outerHTML;
+});
+
+Formatter.add('object', 'host', function() {
+  return '[Host]';
+});
+
+Formatter.add('object', 'set', function(value) {
+  var iter = value.values();
+  var len = 0;
+
+  this.seen.push(value);
+
+  var props = [];
+
+  var next = iter.next();
+  while(!next.done) {
+    var val = next.value;
+    var f = this.format(val);
+    len += f.length;
+    props.push(f);
+
+    next = iter.next();
+  }
+
+  this.seen.pop();
+
+  if(props.length === 0) return 'Set {}';
+
+  if(len <= this.maxLineLength) {
+    return 'Set { ' + props.join(this.propSep + ' ') + ' }';
+  } else {
+    return 'Set {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
+  }
+});
+
+Formatter.add('object', 'map', function(value) {
+  var iter = value.entries();
+  var len = 0;
+
+  this.seen.push(value);
+
+  var props = [];
+
+  var next = iter.next();
+  while(!next.done) {
+    var val = next.value;
+    var fK = this.format(val[0]);
+    var fV = this.format(val[1]);
+
+    var f;
+    if((fK.length + fV.length + 4) <= this.maxLineLength) {
+      f = fK + ' => ' + fV;
+    } else {
+      f = fK + ' =>\n' + fV;
+    }
+
+    len += fK.length + fV.length + 4;
+    props.push(f);
+
+    next = iter.next();
+  }
+
+  this.seen.pop();
+
+  if(props.length === 0) return 'Map {}';
+
+  if(len <= this.maxLineLength) {
+    return 'Map { ' + props.join(this.propSep + ' ') + ' }';
+  } else {
+    return 'Map {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
+  }
+});
+
+Formatter.prototype.defaultFormat = Formatter.prototype._format_object;
+
+function defaultFormat(value, opts) {
+  return new Formatter(opts).format(value);
+}
+
+defaultFormat.Formatter = Formatter;
+module.exports = defaultFormat;
+
+},{"./util":24,"should-type":25}],24:[function(require,module,exports){
+function addSpaces(v) {
+  return v.split('\n').map(function(vv) { return '  ' + vv; }).join('\n');
+}
+
+function pad(str, value, filler) {
+  str = String(str)
+  var isRight = false;
+
+  if(value < 0) {
+    isRight = true;
+    value = -value;
+  }
+
+  if(str.length < value) {
+    var padding = new Array(value - str.length + 1).join(filler);
+    return isRight ? str + padding : padding + str;
+  } else{
+    return str;
+  }
+}
+
+module.exports = {
+  addSpaces: addSpaces,
+  pad: pad,
+  pad0: function(str, value) {
+    return pad(str, value, '0');
+  }
+};
+
+},{}],25:[function(require,module,exports){
+var toString = Object.prototype.toString;
+
+var types = require('./types');
+
+/**
+ * Simple data function to store type information
+ * @param {string} type Usually what is returned from typeof
+ * @param {string} cls  Sanitized @Class via Object.prototype.toString
+ * @param {string} sub  If type and cls the same, and need to specify somehow
+ * @private
+ * @example
+ *
+ * //for null
+ * new Type('null');
+ *
+ * //for Date
+ * new Type('object', 'date');
+ *
+ * //for Uint8Array
+ *
+ * new Type('object', 'typed-array', 'uint8');
+ */
+function Type(type, cls, sub) {
+  this.type = type;
+  this.cls = cls;
+  this.sub = sub;
+}
+
+/**
+ * Function to store type checks
+ * @private
+ */
+function TypeChecker() {
+  this.checks = [];
+}
+
+TypeChecker.prototype = {
+  add: function(func) {
+    this.checks.push(func);
+    return this;
+  },
+
+  addTypeOf: function(type, res) {
+    return this.add(function(obj, tpeOf) {
+      if(tpeOf === type) {
+        return new Type(res);
+      }
+    });
+  },
+
+  addClass: function(cls, res, sub) {
+    return this.add(function(obj, tpeOf, objCls) {
+      if(objCls === cls) {
+        return new Type(types.OBJECT, res, sub);
+      }
+    });
+  },
+
+  getType: function(obj) {
+    var typeOf = typeof obj;
+    var cls = toString.call(obj);
+
+    for(var i = 0, l = this.checks.length; i < l; i++) {
+      var res = this.checks[i].call(this, obj, typeOf, cls);
+      if(typeof res !== 'undefined') return res;
+    }
+
+  }
+};
+
+var main = new TypeChecker();
+
+//TODO add iterators
+
+main
+  .addTypeOf(types.NUMBER, types.NUMBER)
+  .addTypeOf(types.UNDEFINED, types.UNDEFINED)
+  .addTypeOf(types.STRING, types.STRING)
+  .addTypeOf(types.BOOLEAN, types.BOOLEAN)
+  .addTypeOf(types.FUNCTION, types.FUNCTION)
+  .addTypeOf(types.SYMBOL, types.SYMBOL)
+  .add(function(obj, tpeOf) {
+    if(obj === null) return new Type(types.NULL);
+  })
+  .addClass('[object String]', types.STRING)
+  .addClass('[object Boolean]', types.BOOLEAN)
+  .addClass('[object Number]', types.NUMBER)
+  .addClass('[object Array]', types.ARRAY)
+  .addClass('[object RegExp]', types.REGEXP)
+  .addClass('[object Error]', types.ERROR)
+  .addClass('[object Date]', types.DATE)
+  .addClass('[object Arguments]', types.ARGUMENTS)
+  .addClass('[object Math]')
+  .addClass('[object JSON]')
+  .addClass('[object ArrayBuffer]', types.ARRAY_BUFFER)
+  .addClass('[object Int8Array]', types.TYPED_ARRAY, 'int8')
+  .addClass('[object Uint8Array]', types.TYPED_ARRAY, 'uint8')
+  .addClass('[object Uint8ClampedArray]', types.TYPED_ARRAY, 'uint8clamped')
+  .addClass('[object Int16Array]', types.TYPED_ARRAY, 'int16')
+  .addClass('[object Uint16Array]', types.TYPED_ARRAY, 'uint16')
+  .addClass('[object Int32Array]', types.TYPED_ARRAY, 'int32')
+  .addClass('[object Uint32Array]', types.TYPED_ARRAY, 'uint32')
+  .addClass('[object Float32Array]', types.TYPED_ARRAY, 'float32')
+  .addClass('[object Float64Array]', types.TYPED_ARRAY, 'float64')
+  .addClass('[object DataView]', types.DATA_VIEW)
+  .addClass('[object Map]', types.MAP)
+  .addClass('[object WeakMap]', types.WEAK_MAP)
+  .addClass('[object Set]', types.SET)
+  .addClass('[object WeakSet]', types.WEAK_SET)
+  .addClass('[object Promise]', types.PROMISE)
+  .addClass('[object Blob]', types.BLOB)
+  .addClass('[object File]', types.FILE)
+  .addClass('[object FileList]', types.FILE_LIST)
+  .addClass('[object XMLHttpRequest]', types.XHR)
+  .add(function(obj) {
+    if((typeof Promise === types.FUNCTION && obj instanceof Promise) ||
+        (typeof obj.then === types.FUNCTION)) {
+          return new Type(types.OBJECT, types.PROMISE);
+        }
+  })
+  .add(function(obj) {
+    if(typeof Buffer !== 'undefined' && obj instanceof Buffer) {
+      return new Type(types.OBJECT, types.BUFFER);
+    }
+  })
+  .add(function(obj) {
+    if(typeof Node !== 'undefined' && obj instanceof Node) {
+      return new Type(types.OBJECT, types.HTML_ELEMENT, obj.nodeName);
+    }
+  })
+  .add(function(obj) {
+    // probably at the begginging should be enough these checks
+    if(obj.Boolean === Boolean && obj.Number === Number && obj.String === String && obj.Date === Date) {
+      return new Type(types.OBJECT, types.HOST);
+    }
+  })
+  .add(function() {
+    return new Type(types.OBJECT);
+  });
+
+/**
+ * Get type information of anything
+ *
+ * @param  {any} obj Anything that could require type information
+ * @return {Type}    type info
+ */
+function getGlobalType(obj) {
+  return main.getType(obj);
+}
+
+getGlobalType.checker = main;
+getGlobalType.TypeChecker = TypeChecker;
+getGlobalType.Type = Type;
+
+Object.keys(types).forEach(function(typeName) {
+  getGlobalType[typeName] = types[typeName];
+});
+
+module.exports = getGlobalType;
+
+},{"./types":26}],26:[function(require,module,exports){
+var types = {
+  NUMBER: 'number',
+  UNDEFINED: 'undefined',
+  STRING: 'string',
+  BOOLEAN: 'boolean',
+  OBJECT: 'object',
+  FUNCTION: 'function',
+  NULL: 'null',
+  ARRAY: 'array',
+  REGEXP: 'regexp',
+  DATE: 'date',
+  ERROR: 'error',
+  ARGUMENTS: 'arguments',
+  SYMBOL: 'symbol',
+  ARRAY_BUFFER: 'array-buffer',
+  TYPED_ARRAY: 'typed-array',
+  DATA_VIEW: 'data-view',
+  MAP: 'map',
+  SET: 'set',
+  WEAK_SET: 'weak-set',
+  WEAK_MAP: 'weak-map',
+  PROMISE: 'promise',
+
+// node buffer
+  BUFFER: 'buffer',
+
+// dom html element
+  HTML_ELEMENT: 'html-element',
+  HTML_ELEMENT_TEXT: 'html-element-text',
+  DOCUMENT: 'document',
+  WINDOW: 'window',
+  FILE: 'file',
+  FILE_LIST: 'file-list',
+  BLOB: 'blob',
+
+  HOST: 'host',
+
+  XHR: 'xhr'
+};
+
+module.exports = types;
+
+},{}]},{},[1])(1)
+});
\ No newline at end of file
diff --git a/node_modules/should/should.min.js b/node_modules/should/should.min.js
new file mode 100644
index 0000000..f09afef
--- /dev/null
+++ b/node_modules/should/should.min.js
@@ -0,0 +1,9 @@
+/*!
+ * should - test framework agnostic BDD-style assertions
+ * @version v8.0.1
+ * @author TJ Holowaychuk <tj@vision-media.ca> and contributors
+ * @link https://github.com/shouldjs/should.js
+ * @license MIT
+ */
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Should=t()}}(function(){return function t(e,r,n){function a(s,i){if(!r[s]){if(!e[s]){var u="function"==typeof require&&require;if(!i&&u)return u(s,!0);if(o)return o(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var h=r[s]={exports:{}};e[s][0].call(h.exports,function(t){var r=e[s][1][t];return a(r?r:t)},h,h.exports,t,e,r,n)}return r[s].exports}for(var o="function"==typeof require&&require,s=0;s<n.length;s++)a(n[s]);return a}({1:[function(t,e,r){window.Should=t("./index"),Object.defineProperty(window,"should",{enumerable:!1,configurable:!0,value:window.Should})},{"./index":2}],2:[function(t,e,r){var n=t("./lib/should"),a=Object.prototype,o="should";try{var s=n.extend(o,a);n._prevShould=s}catch(i){}e.exports=n},{"./lib/should":19}],3:[function(t,e,r){function n(t){return i+t}function a(t){return t.split("\n").map(n).join("\n")}var o=t("./util"),s=function(t){if(o.merge(this,t),t.message||Object.defineProperty(this,"message",{get:function(){return this._message||(this._message=this.generateMessage(),this.generatedMessage=!0),this._message},configurable:!0,enumerable:!1}),Error.captureStackTrace)Error.captureStackTrace(this,this.stackStartFunction);else{var e=new Error;if(e.stack){var r=e.stack;if(this.stackStartFunction){var n=o.functionName(this.stackStartFunction),a=r.indexOf("\n"+n);if(a>=0){var s=r.indexOf("\n",a+1);r=r.substring(s+1)}}this.stack=r}}},i="    ";s.prototype=Object.create(Error.prototype,{name:{value:"AssertionError"},generateMessage:{value:function(){if(!this.operator&&this.previous)return this.previous.message;var t=o.format(this.actual),e="expected"in this?" "+o.format(this.expected):"",r="details"in this&&this.details?" ("+this.details+")":"",n=this.previous?"\n"+a(this.previous.message):"";return"expected "+t+(this.negate?" not ":" ")+this.operator+e+r+n}}}),e.exports=s},{"./util":20}],4:[function(t,e,r){function n(t){this.obj=t,this.anyOne=!1,this.negate=!1,this.params={actual:t}}function a(){n.apply(this,arguments)}var o=t("./assertion-error");n.prototype={constructor:n,assert:function(t){if(t)return this;var e=this.params;throw"obj"in e&&!("actual"in e)?e.actual=e.obj:"obj"in e||"actual"in e||(e.actual=this.obj),e.stackStartFunction=e.stackStartFunction||this.assert,e.negate=this.negate,e.assertion=this,new o(e)},fail:function(){return this.assert(!1)}},a.prototype.then=function(t,e){return this.obj.then(t,e)},n.add=function(t,e){Object.defineProperty(n.prototype,t,{enumerable:!0,configurable:!0,value:function(){var r=new n(this.obj,this,t);r.anyOne=this.anyOne;try{e.apply(r,arguments)}catch(a){if(a instanceof o){if(this.negate)return this.obj=r.obj,this.negate=!1,this;r!==a.assertion&&(r.params.previous=a),r.negate=!1,r.fail()}throw a}return this.negate&&(r.negate=!0,r.params.details="false negative fail",r.fail()),this.params.operator||(this.params=r.params),this.obj=r.obj,this.negate=!1,this}}),Object.defineProperty(a.prototype,t,{enumerable:!0,configurable:!0,value:function(){var e=arguments;return this.obj=this.obj.then(function(r){return r[t].apply(r,e)}),this}})},n.addChain=function(t,e){e=e||function(){},Object.defineProperty(n.prototype,t,{get:function(){return e.call(this),this},enumerable:!0}),Object.defineProperty(a.prototype,t,{enumerable:!0,configurable:!0,get:function(){return this.obj=this.obj.then(function(e){return e[t]}),this}})},n.alias=function(t,e){var r=Object.getOwnPropertyDescriptor(n.prototype,t);if(!r)throw new Error("Alias "+t+" -> "+e+" could not be created as "+t+" not defined");Object.defineProperty(n.prototype,e,r);var o=Object.getOwnPropertyDescriptor(a.prototype,t);o&&Object.defineProperty(a.prototype,e,o)},n.addChain("not",function(){this.negate=!this.negate}),n.addChain("any",function(){this.anyOne=!0}),e.exports=n,e.exports.PromisedAssertion=a},{"./assertion-error":3}],5:[function(t,e,r){var n=t("should-format").Formatter,a={checkProtoEql:!1,getFormatter:function(t){return new n(t||a)}};e.exports=a},{"should-format":23}],6:[function(t,e,r){function n(t,e,r,a,o){var s=new i(t);s.params={operator:a,expected:e,message:r,stackStartFunction:o||n},s.fail()}function a(t,e){t||n(t,!0,e,"==",h.ok)}function o(t,e){return t&&e?"[object RegExp]"==Object.prototype.toString.call(e)?e.test(t):t instanceof e?!0:e.call({},t)===!0?!0:!1:!1}function s(t,e,r,a){var s;"string"==typeof r&&(a=r,r=null);try{e()}catch(i){s=i}if(a=(r&&r.name?" ("+r.name+")":".")+(a?" "+a:"."),t&&!s&&n(s,r,"Missing expected exception"+a),!t&&o(s,r)&&n(s,r,"Got unwanted exception"+a),t&&s&&r&&!o(s,r)||!t&&s)throw s}var i=t("./../assertion"),u=t("should-equal"),c=Array.prototype.slice,h=e.exports=a;h.fail=n,h.ok=a,h.equal=function(t,e,r){t!=e&&n(t,e,r,"==",h.equal)},h.notEqual=function(t,e,r){t==e&&n(t,e,r,"!=",h.notEqual)},h.deepEqual=function(t,e,r){u(t,e).result||n(t,e,r,"deepEqual",h.deepEqual)},h.notDeepEqual=function(t,e,r){u(t,e).result&&n(t,e,r,"notDeepEqual",h.notDeepEqual)},h.strictEqual=function(t,e,r){t!==e&&n(t,e,r,"===",h.strictEqual)},h.notStrictEqual=function(t,e,r){t===e&&n(t,e,r,"!==",h.notStrictEqual)},h["throws"]=function(t,e,r){s.apply(this,[!0].concat(c.call(arguments)))},h.doesNotThrow=function(t,e){s.apply(this,[!1].concat(c.call(arguments)))},h.ifError=function(t){if(t)throw t}},{"./../assertion":4,"should-equal":22}],7:[function(t,e,r){var n=t("../util"),a=t("./_assert"),o=t("../assertion-error");e.exports=function(t){var e=t.format;n.merge(t,a),t.exist=t.exists=function(r,n){if(null==r)throw new o({message:n||"expected "+e(r)+" to exist",stackStartFunction:t.exist})},t.not={},t.not.exist=t.not.exists=function(r,n){if(null!=r)throw new o({message:n||"expected "+e(r)+" to not exist",stackStartFunction:t.not.exist})}}},{"../assertion-error":3,"../util":20,"./_assert":6}],8:[function(t,e,r){e.exports=function(t,e){e.add("true",function(){this.is.exactly(!0)}),e.alias("true","True"),e.add("false",function(){this.is.exactly(!1)}),e.alias("false","False"),e.add("ok",function(){this.params={operator:"to be truthy"},this.assert(this.obj)})}},{}],9:[function(t,e,r){e.exports=function(t,e){["an","of","a","and","be","has","have","with","is","which","the","it"].forEach(function(t){e.addChain(t)})}},{}],10:[function(t,e,r){var n=t("../util"),a=t("should-equal");e.exports=function(t,e){var r=t.format;e.add("containEql",function(t){this.params={operator:"to contain "+r(t)},this.is.not["null"]().and.not.undefined();var e=this.obj;"string"==typeof e?this.assert(e.indexOf(String(t))>=0):n.isIndexable(e)?this.assert(n.some(e,function(e){return a(e,t).result})):this.have.properties(t)}),e.add("containDeepOrdered",function(e){this.params={operator:"to contain "+r(e)};var a=this.obj;if("string"==typeof a)this.is.equal(String(e));else if(n.isIndexable(a)&&n.isIndexable(e)){for(var o=0,s=0,i=n.length(a),u=n.length(e);i>o&&u>s;o++)try{t(a[o]).containDeepOrdered(e[s]),s++}catch(c){if(c instanceof t.AssertionError)continue;throw c}this.assert(s===u)}else null!=a&&null!=e&&"object"==typeof a&&"object"==typeof e?(n.forEach(e,function(e,r){t(a[r]).containDeepOrdered(e)}),n.isEmptyObject(e)&&this.eql(e)):this.eql(e)}),e.add("containDeep",function(e){this.params={operator:"to contain "+r(e)};var a=this.obj;if("string"==typeof a)this.is.equal(String(e));else if(n.isIndexable(a)&&n.isIndexable(e)){var o={};n.forEach(e,function(e){this.assert(n.some(a,function(r,n){if(n in o)return!1;try{return t(r).containDeep(e),o[n]=!0,!0}catch(a){if(a instanceof t.AssertionError)return!1;throw a}}))},this)}else null!=a&&null!=e&&"object"==typeof a&&"object"==typeof e?(n.forEach(e,function(e,r){t(a[r]).containDeep(e)}),n.isEmptyObject(e)&&this.eql(e)):this.eql(e)})}},{"../util":20,"should-equal":22}],11:[function(t,e,r){function n(t,e,r){return((t.path.length>0?"at "+t.path.map(s.formatProp).join(" -> "):"")+(t.a===e?"":", A has "+s.format(t.a))+(t.b===r?"":" and B has "+s.format(t.b))+(t.showReason?" because "+t.reason:"")).trim()}var a=t("should-equal"),o=t("should-type"),s=t("../util");e.exports=function(t,e){function r(r,n,a){e.add(r,function(e){1!==arguments.length?e=Array.prototype.slice.call(arguments):t(e).be.Array(),this.params={operator:n,expected:e};var r=this.obj,o=!1;s.forEach(e,function(e){try{return t(e)[a](r),o=!0,!1}catch(n){if(n instanceof t.AssertionError)return;throw n}}),this.assert(o)})}e.add("eql",function(e,r){this.params={operator:"to equal",expected:e,message:r};var s=a(this.obj,e,t.config);this.params.details=s.result?"":n(s,this.obj,e),this.params.showDiff=a(o(this.obj),o(e)).result,this.assert(s.result)}),e.add("equal",function(t,e){this.params={operator:"to be",expected:t,message:e},this.params.showDiff=a(o(this.obj),o(t)).result,this.assert(t===this.obj)}),e.alias("equal","exactly"),e.alias("eql","deepEqual"),r("equalOneOf","to be equals one of","equal"),r("oneOf","to be one of","eql")}},{"../util":20,"should-equal":22,"should-type":25}],12:[function(t,e,r){var n=t("../util");e.exports=function(t,e){var r=t.format;e.add("throw",function(e,a){var o=this.obj,s={},i="",u=!1;if(n.isGeneratorFunction(o))return t(o())["throw"](e,a);if(n.isGeneratorObject(o))return t(o.next.bind(o))["throw"](e,a);this.is.a.Function();var c=!0;try{o()}catch(h){u=!0,s=h}if(u)if(e){if("string"==typeof e)c=e==s.message;else if(e instanceof RegExp)c=e.test(s.message);else if("function"==typeof e)c=s instanceof e;else if(null!=e)try{t(s).match(e)}catch(h){if(!(h instanceof t.AssertionError))throw h;i=": "+h.message,c=!1}if(c){if("function"==typeof e&&a)try{t(s).match(a)}catch(h){if(!(h instanceof t.AssertionError))throw h;i=": "+h.message,c=!1}}else"string"==typeof e||e instanceof RegExp?i=" with a message matching "+r(e)+", but got '"+s.message+"'":"function"==typeof e&&(i=" of type "+n.functionName(e)+", but got "+n.functionName(s.constructor))}else i=" (got "+r(s)+")";this.params={operator:"to throw exception"+i},this.assert(u),this.assert(c)}),e.alias("throw","throwError")}},{"../util":20}],13:[function(t,e,r){var n=t("../util"),a=t("should-equal");e.exports=function(t,e){var r=t.format;e.add("match",function(e,o){if(this.params={operator:"to match "+r(e),message:o},!a(this.obj,e).result)if(e instanceof RegExp){if("string"==typeof this.obj)this.assert(e.exec(this.obj));else if(n.isIndexable(this.obj))n.forEach(this.obj,function(t){this.assert(e.exec(t))},this);else if(null!=this.obj&&"object"==typeof this.obj){var s=[],i=[];n.forEach(this.obj,function(t,a){e.exec(t)?i.push(n.formatProp(a)):s.push(n.formatProp(a)+" ("+r(t)+")")},this),s.length&&(this.params.operator+="\n    not matched properties: "+s.join(", ")),i.length&&(this.params.operator+="\n    matched properties: "+i.join(", ")),this.assert(0===s.length)}}else if("function"==typeof e){var u;u=e(this.obj),"boolean"==typeof u&&this.assert(u)}else null!=e&&null!=this.obj&&"object"==typeof e?(s=[],i=[],n.forEach(e,function(e,a){try{t(this.obj).have.property(a).which.match(e),i.push(n.formatProp(a))}catch(o){if(!(o instanceof t.AssertionError))throw o;s.push(n.formatProp(a)+" ("+r(this.obj[a])+")")}},this),s.length&&(this.params.operator+="\n    not matched properties: "+s.join(", ")),i.length&&(this.params.operator+="\n    matched properties: "+i.join(", ")),this.assert(0===s.length)):this.assert(!1)}),e.add("matchEach",function(e,a){this.params={operator:"to match each "+r(e),message:a},n.forEach(this.obj,function(r){t(r).match(e)},this)}),e.add("matchAny",function(e,a){this.params={operator:"to match any "+r(e),message:a},this.assert(n.some(this.obj,function(r){try{return t(r).match(e),!0}catch(n){if(n instanceof t.AssertionError)return!1;throw n}}))}),e.alias("matchAny","matchSome"),e.alias("matchEach","matchEvery")}},{"../util":20,"should-equal":22}],14:[function(t,e,r){e.exports=function(t,e){e.add("NaN",function(){this.params={operator:"to be NaN"},this.assert(this.obj!==this.obj)}),e.add("Infinity",function(){this.params={operator:"to be Infinity"},this.is.a.Number().and.not.a.NaN().and.assert(!isFinite(this.obj))}),e.add("within",function(t,e,r){this.params={operator:"to be within "+t+".."+e,message:r},this.assert(this.obj>=t&&this.obj<=e)}),e.add("approximately",function(t,e,r){this.params={operator:"to be approximately "+t+" ±"+e,message:r},this.assert(Math.abs(this.obj-t)<=e)}),e.add("above",function(t,e){this.params={operator:"to be above "+t,message:e},this.assert(this.obj>t)}),e.add("below",function(t,e){this.params={operator:"to be below "+t,message:e},this.assert(this.obj<t)}),e.alias("above","greaterThan"),e.alias("below","lessThan"),e.add("aboveOrEqual",function(t,e){this.params={operator:"to be above or equal"+t,message:e},this.assert(this.obj>=t)}),e.add("belowOrEqual",function(t,e){this.params={operator:"to be below or equal"+t,message:e},this.assert(this.obj<=t)}),e.alias("aboveOrEqual","greaterThanOrEqual"),e.alias("belowOrEqual","lessThanOrEqual")}},{}],15:[function(t,e,r){var n=t("../util"),a=t("../assertion").PromisedAssertion,o=t("../assertion");e.exports=function(t){o.add("Promise",function(){this.params={operator:"to be promise"};var e=this.obj;t(e).have.property("then").which.is.a.Function()}),o.prototype.fulfilled=function(){this.params={operator:"to be fulfilled"},t(this.obj).be.a.Promise();var e=this;return this.obj.then(function(t){return e.negate&&e.fail(),t},function(t){return e.negate||e.fail(),t})},o.prototype.rejected=function(){this.params={operator:"to be rejected"},t(this.obj).be.a.Promise();var e=this;return this.obj.then(function(t){return e.negate||e.fail(),t},function(t){return e.negate&&e.fail(),t})},o.prototype.fulfilledWith=function(e){this.params={operator:"to be fulfilled"},t(this.obj).be.a.Promise();var r=this;return this.obj.then(function(n){return r.negate&&r.fail(),t(n).eql(e),n},function(t){return r.negate||r.fail(),t})},o.prototype.rejectedWith=function(e,r){this.params={operator:"to be rejected"},t(this.obj).be.a.Promise();var a=this;return this.obj.then(function(t){return a.negate||a.fail(),t},function(o){a.negate&&a.fail();var s=!0,i="";if("string"==typeof e)s=e===o.message;else if(e instanceof RegExp)s=e.test(o.message);else if("function"==typeof e)s=o instanceof e;else if(null!==e&&"object"==typeof e)try{t(o).match(e)}catch(u){if(!(u instanceof t.AssertionError))throw u;i=": "+u.message,s=!1}if(s){if("function"==typeof e&&r)try{t(o).match(r)}catch(u){if(!(u instanceof t.AssertionError))throw u;i=": "+u.message,s=!1}}else"string"==typeof e||e instanceof RegExp?i=" with a message matching "+t.format(e)+", but got '"+o.message+"'":"function"==typeof e&&(i=" of type "+n.functionName(e)+", but got "+n.functionName(o.constructor));return a.params.operator+=i,a.assert(s),o})},Object.defineProperty(o.prototype,"finally",{get:function(){t(this.obj).be.a.Promise();var e=this;return new a(this.obj.then(function(r){var n=t(r);return n.negate=e.negate,n.anyOne=e.anyOne,n}))}}),o.alias("finally","eventually")}},{"../assertion":4,"../util":20}],16:[function(t,e,r){var n=t("../util"),a=t("should-equal"),o=Array.prototype.slice;e.exports=function(t,e){function r(){var t={};if(arguments.length>1)t.names=o.call(arguments);else{var e=arguments[0];"string"==typeof e?t.names=[e]:n.isIndexable(e)?t.names=e:(t.names=Object.keys(e),t.values=e)}return t}var s=t.format;e.add("propertyWithDescriptor",function(e,r){this.params={actual:this.obj,operator:"to have own property with descriptor "+s(r)};var n=this.obj;this.have.ownProperty(e),t(Object.getOwnPropertyDescriptor(Object(n),e)).have.properties(r)}),e.add("enumerable",function(t,e){t=n.convertPropertyName(t),this.params={operator:"to have enumerable property "+n.formatProp(t)+(arguments.length>1?" equal to "+s(e):"")};var r={enumerable:!0};arguments.length>1&&(r.value=e),this.have.propertyWithDescriptor(t,r)}),e.add("enumerables",function(e){var a=r.apply(null,arguments);this.params={operator:"to have enumerables "+a.names.map(n.formatProp)};var o=this.obj;a.names.forEach(function(e){t(o).have.enumerable(e)})}),e.add("property",function(t,e){if(t=n.convertPropertyName(t),arguments.length>1){var r={};r[t]=e,this.have.properties(r)}else this.have.properties(t);this.obj=this.obj[t]}),e.add("properties",function(t){var e={};arguments.length>1?t=o.call(arguments):Array.isArray(t)||("string"==typeof t||"symbol"==typeof t?t=[t]:(e=t,t=Object.keys(t)));var r=Object(this.obj),i=[];t.forEach(function(t){t in r||i.push(n.formatProp(t))});var u=i;0===u.length?u=t.map(n.formatProp):this.anyOne&&(u=t.filter(function(t){return i.indexOf(n.formatProp(t))<0}).map(n.formatProp));var c=(1===u.length?"to have property ":"to have "+(this.anyOne?"any of ":"")+"properties ")+u.join(", ");this.params={obj:this.obj,operator:c},this.assert(0===i.length||this.anyOne&&i.length!=t.length);var h=Object.keys(e);if(h.length){var f=[];u=[],h.forEach(function(t){var o=e[t];a(r[t],o).result?u.push(n.formatProp(t)+" of "+s(o)):f.push(n.formatProp(t)+" of "+s(o)+" (got "+s(r[t])+")")}),(0!==f.length&&!this.anyOne||this.anyOne&&0===u.length)&&(u=f),c=(1===u.length?"to have property ":"to have "+(this.anyOne?"any of ":"")+"properties ")+u.join(", "),this.params={obj:this.obj,operator:c},this.assert(0===f.length||this.anyOne&&f.length!=h.length)}}),e.add("length",function(t,e){this.have.property("length",t,e)}),e.alias("length","lengthOf");var i=Object.prototype.hasOwnProperty;e.add("ownProperty",function(t,e){t=n.convertPropertyName(t),this.params={actual:this.obj,operator:"to have own property "+n.formatProp(t),message:e},this.assert(i.call(this.obj,t)),this.obj=this.obj[t]}),e.alias("ownProperty","hasOwnProperty"),e.add("empty",function(){if(this.params={operator:"to be empty"},void 0!==n.length(this.obj))t(this.obj).have.property("length",0);else{var e=Object(this.obj);for(var r in e)t(this.obj).not.have.ownProperty(r)}},!0),e.add("keys",function(t){arguments.length>1?t=o.call(arguments):1===arguments.length&&"string"==typeof t?t=[t]:0===arguments.length&&(t=[]),t=t.map(String);var e=Object(this.obj),r=[];t.forEach(function(t){i.call(this.obj,t)||r.push(n.formatProp(t))},this);var a=[];Object.keys(e).forEach(function(e){t.indexOf(e)<0&&a.push(n.formatProp(e))});var s=0===t.length?"to be empty":"to have "+(1===t.length?"key ":"keys ");this.params={operator:s+t.map(n.formatProp).join(", ")},r.length>0&&(this.params.operator+="\n	missing keys: "+r.join(", ")),a.length>0&&(this.params.operator+="\n	extra keys: "+a.join(", ")),this.assert(0===r.length&&0===a.length)}),e.alias("keys","key"),e.add("propertyByPath",function(e){arguments.length>1?e=o.call(arguments):1===arguments.length&&"string"==typeof e?e=[e]:0===arguments.length&&(e=[]);var r=e.map(n.formatProp);e=e.map(String);for(var a,s=t(Object(this.obj)),i=[];a=e.shift();)this.params={operator:"to have property by path "+r.join(", ")+" - failed on "+n.formatProp(a)},s=s.have.property(a),i.push(a);this.params={obj:this.obj,operator:"to have property by path "+r.join(", ")},this.obj=s.obj})}},{"../util":20,"should-equal":22}],17:[function(t,e,r){e.exports=function(t,e){e.add("startWith",function(e,r){this.params={operator:"to start with "+t.format(e),message:r},this.assert(0===this.obj.indexOf(e))}),e.add("endWith",function(e,r){this.params={operator:"to end with "+t.format(e),message:r},this.assert(this.obj.indexOf(e,this.obj.length-e.length)>=0)})}},{}],18:[function(t,e,r){var n=t("../util");e.exports=function(t,e){e.add("Number",function(){this.params={operator:"to be a number"},this.have.type("number")}),e.add("arguments",function(){this.params={operator:"to be arguments"},this.have["class"]("Arguments")}),e.alias("arguments","Arguments"),e.add("type",function(e,r){this.params={operator:"to have type "+e,message:r},t(typeof this.obj).be.exactly(e)}),e.add("instanceof",function(t,e){this.params={operator:"to be an instance of "+n.functionName(t),message:e},this.assert(Object(this.obj)instanceof t)}),e.alias("instanceof","instanceOf"),e.add("Function",function(){this.params={operator:"to be a function"},this.have.type("function")}),e.add("Object",function(){this.params={operator:"to be an object"},this.is.not["null"]().and.have.type("object")}),e.add("String",function(){this.params={operator:"to be a string"},this.have.type("string")}),e.add("Array",function(){this.params={operator:"to be an array"},this.have["class"]("Array")}),e.add("Boolean",function(){this.params={operator:"to be a boolean"},this.have.type("boolean")}),e.add("Error",function(){this.params={operator:"to be an error"},this.have.instanceOf(Error)}),e.add("null",function(){this.params={operator:"to be null"},this.assert(null===this.obj)}),e.alias("null","Null"),e.add("class",function(t){this.params={operator:"to have [[Class]] "+t},this.assert(Object.prototype.toString.call(this.obj)==="[object "+t+"]")}),e.alias("class","Class"),e.add("undefined",function(){this.params={operator:"to be undefined"},this.assert(void 0===this.obj)}),e.alias("undefined","Undefined"),e.add("iterable",function(){this.params={operator:"to be iterable"},t(this.obj).have.property(Symbol.iterator).which.is.a.Function()}),e.add("iterator",function(){this.params={operator:"to be iterator"},t(this.obj).have.property("next").which.is.a.Function()}),e.add("generator",function(){this.params={operator:"to be generator"},t(this.obj).be.iterable.and.iterator.and.it.is.equal(this.obj[Symbol.iterator]())})}},{"../util":20}],19:[function(t,e,r){function n(t){return new n.Assertion(t)}var a=t("./util");n.AssertionError=t("./assertion-error"),n.Assertion=t("./assertion"),n.format=a.format,n.type=t("should-type"),n.util=a,n.config=t("./config"),r=e.exports=n,n.extend=function(t,e){t=t||"should",e=e||Object.prototype;var r=Object.getOwnPropertyDescriptor(e,t);return Object.defineProperty(e,t,{set:function(){},get:function(){return n(a.isWrapperType(this)?this.valueOf():this)},configurable:!0}),{name:t,descriptor:r,proto:e}},n.noConflict=function(t){return t=t||n._prevShould,t&&(delete t.proto[t.name],t.descriptor&&Object.defineProperty(t.proto,t.name,t.descriptor)),n},n.use=function(t){return t(n,n.Assertion),this},n.use(t("./ext/assert")).use(t("./ext/chain")).use(t("./ext/bool")).use(t("./ext/number")).use(t("./ext/eql")).use(t("./ext/type")).use(t("./ext/string")).use(t("./ext/property")).use(t("./ext/error")).use(t("./ext/match")).use(t("./ext/contain")).use(t("./ext/promise"))},{"./assertion":4,"./assertion-error":3,"./config":5,"./ext/assert":7,"./ext/bool":8,"./ext/chain":9,"./ext/contain":10,"./ext/eql":11,"./ext/error":12,"./ext/match":13,"./ext/number":14,"./ext/promise":15,"./ext/property":16,"./ext/string":17,"./ext/type":18,"./util":20,"should-type":25}],20:[function(t,e,r){var n=t("should-type"),a=t("./config");r.isWrapperType=function(t){return t instanceof Number||t instanceof String||t instanceof Boolean},r.merge=function(t,e){if(t&&e)for(var r in e)t[r]=e[r];return t};var o=Object.prototype.hasOwnProperty;r.forEach=function s(t,e,n){if(r.isGeneratorFunction(t))return s(t(),e,n);if(r.isGeneratorObject(t))for(var a=t.next();!a.done;){if(e.call(n,a.value,"value",t)===!1)return;a=t.next()}else for(var i in t)if(o.call(t,i)&&e.call(n,t[i],i,t)===!1)return},r.some=function(t,e,n){var a=!1;return r.forEach(t,function(r,o){return e.call(n,r,o,t)?(a=!0,!1):void 0},n),a},r.isEmptyObject=function(t){for(var e in t)if(o.call(t,e))return!1;return!0},r.isIndexable=function(t){var e=n(t);return e.type===n.OBJECT&&e.cls===n.ARRAY||e.type===n.OBJECT&&e.cls===n.BUFFER||e.type===n.OBJECT&&e.cls===n.ARGUMENTS||e.type===n.OBJECT&&e.cls===n.ARRAY_BUFFER||e.type===n.OBJECT&&e.cls===n.TYPED_ARRAY||e.type===n.OBJECT&&e.cls===n.DATA_VIEW||e.type===n.OBJECT&&e.cls===n.STRING||e.type===n.STRING},r.length=function(t){var e=n(t);switch(e.type){case n.STRING:return t.length;case n.OBJECT:switch(e.cls){case n.ARRAY_BUFFER:case n.TYPED_ARRAY:case n.DATA_VIEW:return t.byteLength;case n.ARRAY:case n.BUFFER:case n.ARGUMENTS:case n.FUNCTION:return t.length}}},r.convertPropertyName=function(t){return"symbol"==typeof t?t:String(t)},r.isGeneratorObject=function(t){return t?"function"==typeof t.next&&"function"==typeof t[Symbol.iterator]&&t[Symbol.iterator]()===t:!1},r.isGeneratorFunction=function(t){return"function"!=typeof t?!1:/^function\s*\*\s*/.test(t.toString())},r.format=function(t,e){return a.getFormatter(e).format(t)},r.functionName=t("should-format").Formatter.functionName,r.formatProp=function(t){return a.getFormatter().formatPropertyName(String(t))}},{"./config":5,"should-format":23,"should-type":25}],21:[function(t,e,r){e.exports=function(t){for(var e=arguments,r=1,n=e.length;n>r;r++)t=t.replace(/%s/,e[r]);return t}},{}],22:[function(t,e,r){function n(t,e,r,n,a){var o={result:t};return t||(o.path=e,o.reason=r,o.a=n,o.b=a),o}function a(t){return t.type+(t.cls?"("+t.cls+(t.sub?" "+t.sub:"")+")":"")}function o(t,e,r,s,p,l){function d(r,a){return n(r,l,a,t,e)}function m(n){return o(t[n],e[n],r,s,p,l.concat([n]))}var b=h;if(t===e)return d(0!==t||1/t==1/e,f.PLUS_0_AND_MINUS_0);var y,g,j=i(t),v=i(e),E=j.type!==v.type||j.cls!==v.cls;if(E||r.checkSubType&&j.sub!==v.sub||!r.checkSubType)return d(!1,u(f.DIFFERENT_TYPES,a(j),a(v)));switch(j.type){case"number":return t!==t?d(e!==e,f.NAN_NUMBER):0===t?d(1/t===1/e,f.PLUS_0_AND_MINUS_0):d(t===e,f.EQUALITY);case"boolean":case"string":return d(t===e,f.EQUALITY);case"function":var O=t.toString(),A=e.toString();if(b=o(O,A,r,s,p,l),!b.result)return b.reason=f.FUNCTION_SOURCES,b;break;case"object":switch(j.cls){case"regexp":for(g=["source","global","multiline","lastIndex","ignoreCase"];g.length;)if(b=m(g.shift()),!b.result)return b;break;case"date":if(+t!==+e)return d(!1,f.EQUALITY);break;case"number":case"boolean":case"string":if(b=o(t.valueOf(),e.valueOf(),r,s,p,l),!b.result)return b.reason=f.WRAPPED_VALUE,b;break;case"buffer":if(b=m("length"),!b.result)return b;for(y=t.length;y--;)if(b=m(y),!b.result)return b;return h;case"error":for(g=["name","message"];g.length;)if(b=m(g.shift()),!b.result)return b;break;case"array":case"arguments":case"typed-array":if(b=m("length"),!b.result)return b;break;case"array-buffer":if(b=m("byteLength"),!b.result)return b;break;case"map":case"set":if(b=m("size"),!b.result)return b;s.push(t),p.push(e);for(var x=t.entries(),S=x.next();!S.done;){var P=S.value[0];if("object"!=i(P).type){if(!e.has(P)){b=d(!1,f.SET_MAP_MISSING_KEY),b.a=P,b.b=P;break}if("map"==j.cls){var T=e.get(P);if(b=o(S.value[1],T,r,s,p,l),!b.result){b.a=S.value,b.b=T,b.reason=f.MAP_VALUE_EQUALITY;break}}}else for(var _=e.entries(),N=_.next();!N.done;){if(b=o(S.value[0],N.value[0],r,s,p,l),b.result){"map"==j.cls&&(b=o(S.value[1],N.value[1],r,s,p,l),b.result||(b.a=S.value,b.b=N.value,b.reason=f.MAP_VALUE_EQUALITY));break}b.reason=f.SET_MAP_MISSING_KEY,b.a=P,b.b=P,N=_.next()}if(!b.result)break;S=x.next()}if(s.pop(),p.pop(),!b.result)return b.reason=f.SET_MAP_MISSING_ENTRY,b}}for(y=s.length;y--;)if(s[y]==t)return d(p[y]==e,f.CIRCULAR_VALUES);s.push(t),p.push(e);var P;for(P in e)if(c.call(e,P)){if(b=d(c.call(t,P),u(f.MISSING_KEY,"A",P)),!b.result)break;if(b.result&&(b=m(P),!b.result))break}if(b.result)for(P in t)if(c.call(t,P)&&(b=d(c.call(e,P),u(f.MISSING_KEY,"B",P)),!b.result))return b;if(s.pop(),p.pop(),!b.result)return b;var w=!1,R=!1;return r.checkProtoEql&&(Object.getPrototypeOf?(w=Object.getPrototypeOf(t)===Object.getPrototypeOf(e),R=!0):t.__proto__&&e.__proto__&&(w=t.__proto__===e.__proto__,R=!0),R&&!w&&(b=d(w,f.EQUALITY_PROTOTYPE),b.showReason=!0,!b.result))?b:h}function s(t,e,r){r=r||{},"boolean"!=typeof r.checkProtoEql&&(r.checkProtoEql=p.checkProtoEql),"boolean"!=typeof r.checkSubType&&(r.checkSubType=p.checkSubType);var n=o(t,e,r,[],[],[]);return n}var i=t("should-type"),u=t("./format"),c=Object.prototype.hasOwnProperty,h=n(!0),f={PLUS_0_AND_MINUS_0:"+0 is not equal to -0",DIFFERENT_TYPES:"A has type %s and B has type %s",NAN_NUMBER:"NaN is not equal to any number",EQUALITY:"A is not equal to B",EQUALITY_PROTOTYPE:"A and B have different prototypes",WRAPPED_VALUE:"A wrapped value is not equal to B wrapped value",FUNCTION_SOURCES:"function A is not equal to B by source code value (via .toString call)",MISSING_KEY:"%s has no key %s",CIRCULAR_VALUES:"A has circular reference that was visited not in the same time as B",SET_MAP_MISSING_KEY:"Set/Map missing key",MAP_VALUE_EQUALITY:"Values of the same key in A and B is not equal"},p={checkProtoEql:!0,checkSubType:!0};e.exports=s,s.r=f},{"./format":21,"should-type":25}],23:[function(t,e,r){function n(t){return function(e){var r=t(e);return r.sort(),r}}function a(t){t=t||{},this.seen=[],this.keys=n(t.keys===!1?Object.getOwnPropertyNames:Object.keys),this.maxLineLength="number"==typeof t.maxLineLength?t.maxLineLength:60,this.propSep=t.propSep||",",this.isUTCdate=!!t.isUTCdate}function o(t,e){var r=e?"UTC":"",n=t["get"+r+"FullYear"]()+"-"+u.pad0(t["get"+r+"Month"]()+1,2)+"-"+u.pad0(t["get"+r+"Date"](),2),a=u.pad0(t["get"+r+"Hours"](),2)+":"+u.pad0(t["get"+r+"Minutes"](),2)+":"+u.pad0(t["get"+r+"Seconds"](),2)+"."+u.pad0(t["get"+r+"Milliseconds"](),3),o=t.getTimezoneOffset(),s=Math.abs(o),i=Math.floor(s/60),c=s-60*i,h=(0>o?"+":"-")+u.pad0(i,2)+u.pad0(c,2);return n+" "+a+(e?"":" "+h)}function s(t,e){return new a(e).format(t)}var i=t("should-type"),u=t("./util");a.prototype={constructor:a,format:function(t){var e=i(t),r=e.type,n=e.type;e.cls&&(r+="_"+e.cls,n+="_"+e.cls),e.sub&&(n+="_"+e.sub);var a=this["_format_"+n]||this["_format_"+r]||this["_format_"+e.type]||this.defaultFormat;return a.call(this,t).trim()},_formatObject:function(t,e){e=e||{};var r=e.keys||this.keys(t),n=0,o=e.formatPropertyValue||this.formatPropertyValue,s=e.formatPropertyName||this.formatPropertyName,i=e.keyValueSep||": ",c=e.keyFilter||function(){return!0};this.seen.push(t);var h=[];r.forEach(function(e){if(c(e)){var r=s.call(this,e),a=(r?r+i:"")+o.call(this,t,e);n+=a.length,h.push(a)}},this),this.seen.pop(),(e.additionalProperties||[]).forEach(function(t){var e=t[0]+i+this.format(t[1]);n+=e.length,h.push(e)},this);var f=e.prefix||a.constructorName(t)||"";f.length>0&&(f+=" ");var p,l;Array.isArray(e.brackets)?(p=e.brackets&&e.brackets[0],l=e.brackets&&e.brackets[1]):(p="{",l="}");var d=e.value||"";return 0===h.length?d||f+p+l:n<=this.maxLineLength?f+p+" "+(d?d+" ":"")+h.join(this.propSep+" ")+" "+l:f+p+"\n"+(d?"  "+d+"\n":"")+h.map(u.addSpaces).join(this.propSep+"\n")+"\n"+l},formatObject:function(t,e,r){r=r||this.keys(t);var n=0;return this.seen.push(t),r=r.map(function(e){var r=this.formatProperty(t,e);return n+=r.length,r},this),this.seen.pop(),0===r.length?"{}":n<=this.maxLineLength?"{ "+(e?e+" ":"")+r.join(this.propSep+" ")+" }":"{\n"+(e?"  "+e+"\n":"")+r.map(u.addSpaces).join(this.propSep+"\n")+"\n}"},formatPropertyName:function(t){return t.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/)?t:this.format(t)},formatProperty:function(t,e){var r=a.getPropertyDescriptor(t,e),n=this.formatPropertyName(e),o=r.get&&r.set?"[Getter/Setter]":r.get?"[Getter]":r.set?"[Setter]":this.seen.indexOf(r.value)>=0?"[Circular]":this.format(r.value);return n+": "+o},formatPropertyValue:function(t,e){var r=a.getPropertyDescriptor(t,e),n=r.get&&r.set?"[Getter/Setter]":r.get?"[Getter]":r.set?"[Setter]":this.seen.indexOf(r.value)>=0?"[Circular]":this.format(r.value);return n}},a.add=function(t,e,r,n){var o=Array.prototype.slice.call(arguments);n=o.pop(),a.prototype["_format_"+o.join("_")]=n},a.formatObjectWithPrefix=function(t){return function(e){var r=t.call(this,e),n=this.keys(e);return 0==n.length?r:this.formatObject(e,r,n)}};var c=/^\s*function\s*(\S*)\s*\(/;a.functionName=function(t){if(t.name)return t.name;var e=t.toString().match(c)[1];return e},a.constructorName=function(t){for(;t;){var e=Object.getOwnPropertyDescriptor(t,"constructor");if(void 0!==e&&"function"==typeof e.value){var r=a.functionName(e.value);if(""!==r)return r}t=Object.getPrototypeOf(t)}},a.getPropertyDescriptor=function(t,e){var r;try{
+r=Object.getOwnPropertyDescriptor(t,e)||{value:t[e]}}catch(n){r={value:n}}return r},a.generateFunctionForIndexedArray=function(t,e,r){return function(n){for(var a=this.byteArrayMaxLength||50,o=n[t],s=[],i=0,c=0;a>c&&o>c;c++){var h=n[c]||0,f=u.pad0(h.toString(16),r);i+=f.length,s.push(f)}var p=n.constructor.name||e||"";return p&&(p+=" "),0===s.length?p+"[]":i<=this.maxLineLength?p+"[ "+s.join(this.propSep+" ")+" ]":p+"[\n"+s.map(u.addSpaces).join(this.propSep+"\n")+"\n]"}},a.add("undefined",function(){return"undefined"}),a.add("null",function(){return"null"}),a.add("boolean",function(t){return t?"true":"false"}),a.add("symbol",function(t){return t.toString()}),["number","boolean"].forEach(function(t){a.add("object",t,function(t){return this._formatObject(t,{additionalProperties:[["[[PrimitiveValue]]",t.valueOf()]]})})}),a.add("object","string",function(t){var e=t.valueOf();return this._formatObject(t,{keyFilter:function(t){return!(t.match(/\d+/)&&parseInt(t,10)<e.length)},additionalProperties:[["[[PrimitiveValue]]",e]]})}),a.add("object","regexp",function(t){return this._formatObject(t,{value:String(t)})}),a.add("number",function(t){return 0===t&&0>1/t?"-0":String(t)}),a.add("string",function(t){return"'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'"}),a.add("object",function(t){return this._formatObject(t)}),a.add("object","arguments",function(t){return this._formatObject(t,{prefix:"Arguments",formatPropertyName:function(t){return t.match(/\d+/)?void 0:this.formatPropertyName(t)},brackets:["[","]"]})}),a.add("object","array",function(t){return this._formatObject(t,{formatPropertyName:function(t){return t.match(/\d+/)?void 0:this.formatPropertyName(t)},brackets:["[","]"]})}),a.add("object","date",function(t){return this._formatObject(t,{value:o(t,this.isUTCdate)})}),a.add("function",function(t){return this._formatObject(t,{additionalProperties:[["name",a.functionName(t)]]})}),a.add("object","error",function(t){return this._formatObject(t,{prefix:t.name,additionalProperties:[["message",t.message]]})}),a.add("object","buffer",a.generateFunctionForIndexedArray("length","Buffer",2)),a.add("object","array-buffer",a.generateFunctionForIndexedArray("byteLength","ArrayBuffer",2)),a.add("object","typed-array","int8",a.generateFunctionForIndexedArray("length","Int8Array",2)),a.add("object","typed-array","uint8",a.generateFunctionForIndexedArray("length","Uint8Array",2)),a.add("object","typed-array","uint8clamped",a.generateFunctionForIndexedArray("length","Uint8ClampedArray",2)),a.add("object","typed-array","int16",a.generateFunctionForIndexedArray("length","Int16Array",4)),a.add("object","typed-array","uint16",a.generateFunctionForIndexedArray("length","Uint16Array",4)),a.add("object","typed-array","int32",a.generateFunctionForIndexedArray("length","Int32Array",8)),a.add("object","typed-array","uint32",a.generateFunctionForIndexedArray("length","Uint32Array",8)),a.add("object","promise",function(){return"[Promise]"}),a.add("object","xhr",function(){return"[XMLHttpRequest]"}),a.add("object","html-element",function(t){return t.outerHTML}),a.add("object","html-element","#text",function(t){return t.nodeValue}),a.add("object","html-element","#document",function(t){return t.documentElement.outerHTML}),a.add("object","host",function(){return"[Host]"}),a.add("object","set",function(t){var e=t.values(),r=0;this.seen.push(t);for(var n=[],a=e.next();!a.done;){var o=a.value,s=this.format(o);r+=s.length,n.push(s),a=e.next()}return this.seen.pop(),0===n.length?"Set {}":r<=this.maxLineLength?"Set { "+n.join(this.propSep+" ")+" }":"Set {\n"+n.map(u.addSpaces).join(this.propSep+"\n")+"\n}"}),a.add("object","map",function(t){var e=t.entries(),r=0;this.seen.push(t);for(var n=[],a=e.next();!a.done;){var o,s=a.value,i=this.format(s[0]),c=this.format(s[1]);o=i.length+c.length+4<=this.maxLineLength?i+" => "+c:i+" =>\n"+c,r+=i.length+c.length+4,n.push(o),a=e.next()}return this.seen.pop(),0===n.length?"Map {}":r<=this.maxLineLength?"Map { "+n.join(this.propSep+" ")+" }":"Map {\n"+n.map(u.addSpaces).join(this.propSep+"\n")+"\n}"}),a.prototype.defaultFormat=a.prototype._format_object,s.Formatter=a,e.exports=s},{"./util":24,"should-type":25}],24:[function(t,e,r){function n(t){return t.split("\n").map(function(t){return"  "+t}).join("\n")}function a(t,e,r){t=String(t);var n=!1;if(0>e&&(n=!0,e=-e),t.length<e){var a=new Array(e-t.length+1).join(r);return n?t+a:a+t}return t}e.exports={addSpaces:n,pad:a,pad0:function(t,e){return a(t,e,"0")}}},{}],25:[function(t,e,r){function n(t,e,r){this.type=t,this.cls=e,this.sub=r}function a(){this.checks=[]}function o(t){return u.getType(t)}var s=Object.prototype.toString,i=t("./types");a.prototype={add:function(t){return this.checks.push(t),this},addTypeOf:function(t,e){return this.add(function(r,a){return a===t?new n(e):void 0})},addClass:function(t,e,r){return this.add(function(a,o,s){return s===t?new n(i.OBJECT,e,r):void 0})},getType:function(t){for(var e=typeof t,r=s.call(t),n=0,a=this.checks.length;a>n;n++){var o=this.checks[n].call(this,t,e,r);if("undefined"!=typeof o)return o}}};var u=new a;u.addTypeOf(i.NUMBER,i.NUMBER).addTypeOf(i.UNDEFINED,i.UNDEFINED).addTypeOf(i.STRING,i.STRING).addTypeOf(i.BOOLEAN,i.BOOLEAN).addTypeOf(i.FUNCTION,i.FUNCTION).addTypeOf(i.SYMBOL,i.SYMBOL).add(function(t,e){return null===t?new n(i.NULL):void 0}).addClass("[object String]",i.STRING).addClass("[object Boolean]",i.BOOLEAN).addClass("[object Number]",i.NUMBER).addClass("[object Array]",i.ARRAY).addClass("[object RegExp]",i.REGEXP).addClass("[object Error]",i.ERROR).addClass("[object Date]",i.DATE).addClass("[object Arguments]",i.ARGUMENTS).addClass("[object Math]").addClass("[object JSON]").addClass("[object ArrayBuffer]",i.ARRAY_BUFFER).addClass("[object Int8Array]",i.TYPED_ARRAY,"int8").addClass("[object Uint8Array]",i.TYPED_ARRAY,"uint8").addClass("[object Uint8ClampedArray]",i.TYPED_ARRAY,"uint8clamped").addClass("[object Int16Array]",i.TYPED_ARRAY,"int16").addClass("[object Uint16Array]",i.TYPED_ARRAY,"uint16").addClass("[object Int32Array]",i.TYPED_ARRAY,"int32").addClass("[object Uint32Array]",i.TYPED_ARRAY,"uint32").addClass("[object Float32Array]",i.TYPED_ARRAY,"float32").addClass("[object Float64Array]",i.TYPED_ARRAY,"float64").addClass("[object DataView]",i.DATA_VIEW).addClass("[object Map]",i.MAP).addClass("[object WeakMap]",i.WEAK_MAP).addClass("[object Set]",i.SET).addClass("[object WeakSet]",i.WEAK_SET).addClass("[object Promise]",i.PROMISE).addClass("[object Blob]",i.BLOB).addClass("[object File]",i.FILE).addClass("[object FileList]",i.FILE_LIST).addClass("[object XMLHttpRequest]",i.XHR).add(function(t){return typeof Promise===i.FUNCTION&&t instanceof Promise||typeof t.then===i.FUNCTION?new n(i.OBJECT,i.PROMISE):void 0}).add(function(t){return"undefined"!=typeof Buffer&&t instanceof Buffer?new n(i.OBJECT,i.BUFFER):void 0}).add(function(t){return"undefined"!=typeof Node&&t instanceof Node?new n(i.OBJECT,i.HTML_ELEMENT,t.nodeName):void 0}).add(function(t){return t.Boolean===Boolean&&t.Number===Number&&t.String===String&&t.Date===Date?new n(i.OBJECT,i.HOST):void 0}).add(function(){return new n(i.OBJECT)}),o.checker=u,o.TypeChecker=a,o.Type=n,Object.keys(i).forEach(function(t){o[t]=i[t]}),e.exports=o},{"./types":26}],26:[function(t,e,r){var n={NUMBER:"number",UNDEFINED:"undefined",STRING:"string",BOOLEAN:"boolean",OBJECT:"object",FUNCTION:"function",NULL:"null",ARRAY:"array",REGEXP:"regexp",DATE:"date",ERROR:"error",ARGUMENTS:"arguments",SYMBOL:"symbol",ARRAY_BUFFER:"array-buffer",TYPED_ARRAY:"typed-array",DATA_VIEW:"data-view",MAP:"map",SET:"set",WEAK_SET:"weak-set",WEAK_MAP:"weak-map",PROMISE:"promise",BUFFER:"buffer",HTML_ELEMENT:"html-element",HTML_ELEMENT_TEXT:"html-element-text",DOCUMENT:"document",WINDOW:"window",FILE:"file",FILE_LIST:"file-list",BLOB:"blob",HOST:"host",XHR:"xhr"};e.exports=n},{}]},{},[1])(1)});
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..180fd39
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,45 @@
+{
+  "name": "deephas",
+  "version": "1.0.5",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "should": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/should/-/should-8.0.1.tgz",
+      "integrity": "sha1-OjpxF9RfKaNnvBKch4owPsHvZAo=",
+      "dev": true,
+      "requires": {
+        "should-equal": "0.5.0",
+        "should-format": "0.3.1",
+        "should-type": "0.2.0"
+      },
+      "dependencies": {
+        "should-equal": {
+          "version": "0.5.0",
+          "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-0.5.0.tgz",
+          "integrity": "sha1-x5fxNfMGf+tp6+zbMGscP+IbPm8=",
+          "dev": true,
+          "requires": {
+            "should-type": "0.2.0"
+          }
+        },
+        "should-format": {
+          "version": "0.3.1",
+          "resolved": "https://registry.npmjs.org/should-format/-/should-format-0.3.1.tgz",
+          "integrity": "sha1-LLt4JGFnCs5CkrKx7EaNuM+Z4zA=",
+          "dev": true,
+          "requires": {
+            "should-type": "0.2.0"
+          }
+        },
+        "should-type": {
+          "version": "0.2.0",
+          "resolved": "https://registry.npmjs.org/should-type/-/should-type-0.2.0.tgz",
+          "integrity": "sha1-ZwfvlVKdmJ3MCY/gdTqx+RNrt/Y=",
+          "dev": true
+        }
+      }
+    }
+  }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..9f41db2
--- /dev/null
+++ b/package.json
@@ -0,0 +1,27 @@
+{
+  "name": "deephas",
+  "version": "1.0.6",
+  "description": "get, set or test for a value in a javascript object",
+  "main": "deepHas.js",
+  "scripts": {
+    "test": "./runTests.sh"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git@github.com:sharpred/deepHas.git"
+  },
+  "keywords": [
+    "nested",
+    "object",
+    "key"
+  ],
+  "author": "Paul Ryan <paul.ryan@stepupsoftware.co.uk>",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/sharpred/deepHas/issues"
+  },
+  "homepage": "https://github.com/sharpred/deepHas",
+  "devDependencies": {
+    "should": ">=8.0.1"
+  }
+}
diff --git a/poc.js b/poc.js
new file mode 100644
index 0000000..0f0716c
--- /dev/null
+++ b/poc.js
@@ -0,0 +1,5 @@
+var dh = require("./deepHas");
+var obj = {};
+console.log(obj.isAdmin);
+dh.set(obj,'__proto__.isAdmin','true');
+console.log(obj.isAdmin);
\ No newline at end of file
diff --git a/runTests.sh b/runTests.sh
new file mode 100755
index 0000000..a3be498
--- /dev/null
+++ b/runTests.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+node tests/testHas.js
+node tests/testGet.js
+node tests/testExports.js
+node tests/testSet.js
+node tests/testVulnerability.js
\ No newline at end of file
diff --git a/tests/testExports.js b/tests/testExports.js
new file mode 100644
index 0000000..e14504d
--- /dev/null
+++ b/tests/testExports.js
@@ -0,0 +1,15 @@
+var dh = require("../deepHas"),
+    should = require("should");
+
+/*
+ * Test of exports
+ * public functions should be visible (hasProperty and getProperty)
+ * private function should be hidden(deepProperty)
+ */
+dh.should.be.an.instanceOf(Object).and.have.property('has');
+dh.should.have.property('get');
+dh.should.have.property('set');
+dh.should.be.an.instanceOf(Object).and.not.have.property('deep');
+dh.has.should.be.an.instanceOf(Function);
+dh.get.should.be.an.instanceOf(Function);
+dh.set.should.be.an.instanceOf(Function);
\ No newline at end of file
diff --git a/tests/testGet.js b/tests/testGet.js
new file mode 100644
index 0000000..9bed3e9
--- /dev/null
+++ b/tests/testGet.js
@@ -0,0 +1,59 @@
+var dh = require("../deepHas"),
+    should = require("should");
+
+/*
+ * Test get
+ */
+var test1,
+    test2,
+    test3,
+    test4,
+    test5,
+    test6,
+    test7,
+    test8,
+    test9,
+    test10,
+    test11,
+    test12,
+    getObj;
+
+getObj = {
+    "top" : {
+        "middle" : {
+            "bottom" : {
+            }
+        }
+    },
+    "truthy" : true,
+    "falsey" : false
+};
+//data
+test1 = dh.get(getObj, "top");
+test2 = dh.get(getObj, "top.middle");
+test3 = dh.get(getObj, "top.middle.bottom");
+test4 = dh.get(getObj, "bottom");
+test5 = dh.get(getObj, "bottom.middle");
+test6 = dh.get(getObj, "bottom.middle.top");
+test7 = dh.get();
+test8 = dh.get(getObj);
+test9 = dh.get("top");
+test10 = dh.get({}, "top");
+test11 = dh.get(getObj, "truthy");
+test12 = dh.get(getObj, "falsey");
+
+//assertions
+should(test1).have.property("middle", {
+    "bottom" : {}
+});
+should(test2).have.property("bottom", {});
+test3.should.be.an.instanceOf(Object);
+should.not.exist(test4);
+should.not.exist(test5);
+should.not.exist(test6);
+should.not.exist(test7);
+should.not.exist(test8);
+should.not.exist(test9);
+should.not.exist(test10);
+test11.should.be.exactly(true);
+test12.should.be.exactly(false);
\ No newline at end of file
diff --git a/tests/testHas.js b/tests/testHas.js
new file mode 100644
index 0000000..aa74c02
--- /dev/null
+++ b/tests/testHas.js
@@ -0,0 +1,59 @@
+var dh = require("../deepHas"),
+    should = require("should");
+
+/*
+ * Test has
+ */
+var test1,
+    test2,
+    test3,
+    test4,
+    test5,
+    test6,
+    test7,
+    test8,
+    test9,
+    test10,
+    test11,
+    test12,
+    hasObj;
+
+hasObj = {
+    "top" : {
+        "middle" : {
+            "bottom" : {
+            }
+        }
+    },
+    "truthy" : true,
+    "falsey" : false
+};
+//data
+test1 = dh.has(hasObj, "top");
+test2 = dh.has(hasObj, "top.middle");
+test3 = dh.has(hasObj, "top.middle.bottom");
+test4 = dh.has(hasObj, "bottom");
+test5 = dh.has(hasObj, "bottom.middle");
+test6 = dh.has(hasObj, "bottom.middle.top");
+test7 = dh.has();
+test8 = dh.has(hasObj);
+test9 = dh.has("top");
+test10 = dh.has({}, "top");
+test11 = dh.has(hasObj, "truthy");
+test12 = dh.has(hasObj, "falsey");
+test13 = dh.has(hasObj, "middle");
+
+//assertions
+test1.should.be.exactly(true);
+test2.should.be.exactly(true);
+test3.should.be.exactly(true);
+test4.should.be.exactly(false);
+test5.should.be.exactly(false);
+test6.should.be.exactly(false);
+test7.should.be.exactly(false);
+test8.should.be.exactly(false);
+test9.should.be.exactly(false);
+test10.should.be.exactly(false);
+test11.should.be.exactly(true);
+test12.should.be.exactly(true);
+test13.should.be.exactly(false);
\ No newline at end of file
diff --git a/tests/testSet.js b/tests/testSet.js
new file mode 100644
index 0000000..431cf3b
--- /dev/null
+++ b/tests/testSet.js
@@ -0,0 +1,154 @@
+var dh = require("../deepHas"),
+    should = require("should"),
+    obj,
+    obj2,
+    test2;
+
+obj = {
+    "top" : {
+        "middle" : {
+            "bottom" : {
+                "val" : "1"
+            }
+        }
+    },
+    "truthy" : true,
+    "falsey" : false
+};
+
+dh.set(obj, "top.middle.bottom", {
+    "val" : "2"
+});
+
+//assertions
+JSON.stringify(obj).should.equal(JSON.stringify({
+    "top" : {
+        "middle" : {
+            "bottom" : {
+                "val" : "2"
+            }
+        }
+    },
+    "truthy" : true,
+    "falsey" : false
+}));
+
+dh.set(obj, "top.middle.left", {
+    "val" : "1"
+});
+
+JSON.stringify(obj).should.equal(JSON.stringify({
+    "top" : {
+        "middle" : {
+            "bottom" : {
+                "val" : "2"
+            },
+            "left" : {
+                "val" : "1"
+            }
+        }
+    },
+    "truthy" : true,
+    "falsey" : false
+}));
+
+dh.set(obj, "top.middle.right", {
+    "val" : "1"
+});
+
+JSON.stringify(obj).should.equal(JSON.stringify({
+    "top" : {
+        "middle" : {
+            "bottom" : {
+                "val" : "2"
+            },
+            "left" : {
+                "val" : "1"
+            },
+            "right" : {
+                "val" : "1"
+            }
+        }
+    },
+    "truthy" : true,
+    "falsey" : false
+}));
+
+dh.set(obj, "top.bottom.right", {
+    "val" : "1"
+});
+
+JSON.stringify(obj).should.equal(JSON.stringify({
+    "top" : {
+        "middle" : {
+            "bottom" : {
+                "val" : "2"
+            },
+            "left" : {
+                "val" : "1"
+            },
+            "right" : {
+                "val" : "1"
+            }
+        },
+        "bottom" : {
+            "right" : {
+                "val" : "1"
+            }
+        }
+    },
+    "truthy" : true,
+    "falsey" : false
+}));
+
+dh.set(obj, "bottom.middle.top", {
+    "val" : "1"
+});
+
+JSON.stringify(obj).should.equal(JSON.stringify({
+    "top" : {
+        "middle" : {
+            "bottom" : {
+                "val" : "2"
+            },
+            "left" : {
+                "val" : "1"
+            },
+            "right" : {
+                "val" : "1"
+            }
+        },
+        "bottom" : {
+            "right" : {
+                "val" : "1"
+            }
+        }
+    },
+    "truthy" : true,
+    "falsey" : false,
+    "bottom" : {
+        "middle" : {
+            "top" : {
+                "val" : "1"
+            }
+        }
+    }
+}));
+var test2 = {
+    "bottom" : {
+        "middle" : {
+            "top" : ["paul", 1, {
+                "test" : "test"
+            }]
+        }
+    }
+};
+
+obj2 = {
+
+};
+dh.set(obj2, "bottom.middle.top", ["paul", 1, {
+    "test" : "test"
+}]);
+
+JSON.stringify(obj2).should.equal(JSON.stringify(test2));
diff --git a/tests/testVulnerability.js b/tests/testVulnerability.js
new file mode 100644
index 0000000..0bc2f90
--- /dev/null
+++ b/tests/testVulnerability.js
@@ -0,0 +1,10 @@
+var dh = require("../deepHas"),
+    should = require("should"),
+    obj;
+
+obj = {};
+
+dh.set(obj,'__proto__.isAdmin',true);
+
+should.not.exist(obj.isAdmin);
+obj.hasOwnProperty('isAdmin').should.equal(false);
\ No newline at end of file

Fixed code: tests/**
{
    "bitwise": true,
    "globals": {
        "Alloy": false,
        "_": false,
        "L": false,
        "Ti": false,
        "Titanium": false,
        "require": false,
        "module": false,
        "$": false,
        "Backbone": false,
        "exports": false,
        "L": false,
        "WPATH": false,
        "OS_ANDROID": false,
        "OS_IOS": false,
        "ENV_DEV": false,
        "ENV_TEST": false,
        "clearInterval": false,
        "setInterval": false,
        "clearTimeout": false,
        "setTimeout": false,
        "console": false,
        "process": false
    },
    "camelcase": false,
    "eqeqeq": true,
    "indent": 4,
    "unused": true,
    "undef" : true,
    "curly" : true,
    "immed" : true,
    "undef": true,
    "latedef": true,
    "trailing": true,
    "newcap": false,
    "sub": true,
    "shadow": false,
    "laxcomma": false,
    "maxcomplexity": 10,
    "predef": [
        "require",
        "module",
        "$",
        "Ti",
        "_",
        "Backbone",
        "Titanium",
        "Alloy",
        "exports",
        "L",
        "WPATH",
        "OS_ANDROID",
        "OS_IOS",
        "ENV_DEV",
        "ENV_TEST",
        "setTimeout",
        "console",
        "process",
        "alert"
    ]
}
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>deepHas</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
	</buildSpec>
	<natures>
		<nature>com.aptana.projects.webnature</nature>
	</natures>
</projectDescription>
eclipse.preferences.version=1
included=//deepHas.js
projectSpecificOptions=true
eclipse.preferences.version=1
encoding/.jshintrc=UTF-8
language: node_js
node_js:
- node
install: npm install
deploy:
  provider: npm
  email: paul.ryan@stepupsoftware.co.uk
  api_key:
    secure: Um2/kvcWM2cEVPwq2kGCACk2VMoPZJb3W0KNBzFwPTDxUs4D96erb0mh/1dv7Jpz8qQpw2Ldrk873N96mEC2HRA8z13EuslpMm7XXPHCzLY2Sx5XFgYrDoec9Wn2A3wVuDLsRd79m/E+MZyBu5+qbfk8JqSs2x43IqFU/eBKgeZn8mnI1hoHFBfPeJ70hzscoYj87PbrHc0YyVfQpXZCB3vKkYXmeBGcQIkloQhSr7z2TzH+IlXWDgDBxeASb6k+aTKypaRC/sglmFme0O7oWAmkC0MIoXkO1rm9+MnAc9kYDe2pUBjgFuQRGDQD51jLobanqrsgosbtHeNB25ALJTrFR1O6GWR1Pmw1gdJvAfMGx2i4ofpsX8pSV2ocJwxLx6Q8d7f9wTRp4E0oFNdG8YGbY9fRV7d4Bk4brWi/Yq3XAjDqWCc/JGoNI20nJe2TScSdh33qHvyMGSioTMDbFVmeFNA4SADVgPxg59pFs6f+BKoJ5pwOSNP612GsW2yMuGvNY4AzZoARqFsKzPgtE2MZDC9/OVPFXnKFsS1oNF10EfsDd1EYZlrS63jsnpeYFzsU3g+zO/CWCiUNJBA1/BqpN8GzHfSBXdgZP1qpx5zMZfaP699B/Vf0vJS3wRN9pwfz4lvXU6MYwJ7WZgAvYwPLWYLfRJc+dmC3HP1MWPE=
  on:
    tags: true
    repo: sharpred/deepHas
    branch: master
![Build Status](https://travis-ci.org/sharpred/deepHas.svg?branch=master)
# deepHas

test for existence of nested object key and optionally return that key

##Installation
npm install deephas

or just drop deepHas.js into your project.

##Usage

`dh = require("deepHas");\n`
`var obj = {"some": {"nested": {"property":""your value here"}}};`

### dh.has(obj, 'some.nested.property')

Returns true or false if 'some.nested.property' exists or not.

### dh.get(obj, 'some.nested.property')

Returns the value or undefined if it does not exist.

### dh.set(obj, 'some.nested.newproperty', "your value here")

Adds a new property or object.
var indexFalse,
    indexTrue,
    indexer,
    reduce,
    add,
    has,
    get,
    set;

function indexer(set) {
    return function (obj, i) {
        "use strict";
        try {
            if (obj && i && obj.hasOwnProperty(i)) {
                return obj[i];
            } else if (obj && i && set) {
                obj[i] = {};
                return obj[i];
            }
            return;
        } catch (ex) {
            console.error(ex);
            return;
        }
    };
}

indexTrue = indexer(true);
indexFalse = indexer(false);

function reduce(obj, str) {
    "use strict";
    try {
        if (typeof str !== "string") {
            return;
        }
        if (typeof obj !== "object") {
            return;
        }
        return str.split('.').reduce(indexFalse, obj);

    } catch (ex) {
        console.error(ex);
        return;
    }

}

function add(obj, str, val) {
    "use strict";
    try {
        if (typeof str !== "string") {
            return;
        }
        if (str.indexOf('__proto__') != -1) {
            throw "cannot modify prototype property";
        }
        if (typeof obj !== "object") {
            return;
        }
        if (!val) {
            return;
        }
        var items = str.split('.');
        console.log(str);
        var initial = items.slice(0, items.length - 1);
        var last = items.slice(items.length - 1);
        var test = initial.reduce(indexTrue, obj);
        test[last] = val;

    } catch (ex) {
        console.error(ex);
        return;
    }
}

function has(target, path) {
    "use strict";
    try {
        var test = reduce(target, path);
        if (typeof test !== "undefined") {
            return true;
        }
        return false;
    } catch (ex) {
        console.error(ex);
        return;
    }
}

function get(target, path) {
    "use strict";
    try {
        return reduce(target, path);
    } catch (ex) {
        console.error(ex);
        return;
    }
}

function set(target, path, val) {
    "use strict";
    try {
        return add(target, path, val);
    } catch (ex) {
        console.error(ex);
        return;
    }
}

exports.has = has;
exports.get = get;
exports.set = set;
{
  "extends": "eslint",
  "env": {
    "node": true,
    "browser": true,
    "mocha": true,
    "es6": true
  },
  "rules": {
    "valid-jsdoc": 0,
    "strict": 0,
    "quotes": 0,
    "indent": 0,
    "yoda": 0,
    "new-cap": 0,
    "space-after-keywords": 0
  }
}
examples
test
.idea
language: node_js
node_js:
- '0.12'
script:
- test $SAUCE_USERNAME && npm run zuul || echo 'not running on saucelabs'
- npm test
env:
  global:
  - secure: aB4+vAj+mJHqQfnq9x10eZ5//erfxecs3l9u/oSJX1Ok+WLrpUW0x3qpaC1bEEPq4bkAuIifxohnPv0XTE3m8GyTfRHzqmeNnNQNsnex3IzunbU4aG7QyS3jFa6gjT5OrgPA+eHobNXBvwASZczighlWtoYKD5RW7Uak4E8EpPs=
  - secure: kJaOWFzFnSGEZ4keShHST18OC6z+rmvnnht0SwqmhPlBX4nBQ2bdBR09n0O/GVQ0uAzohn1oObouQH0yuXpbgmk4whMVZgt8RPztusLskt88fE9EOPFNA+YOWNpmcelDiXsMXv7vN2bBlZJSrILUgUppuHIqsdqTGWut08l3Zhg=
ui: mocha-bdd
browsers:
  - name: chrome
    version: 38..latest
  - name: ie
    version: 9..latest
  - name: firefox
    version: 33..latest
  - name: safari
    version: 6..latest
Before contribute something:

Follow simple rules:

- Not violate [DRY](http://programmer.97things.oreilly.com/wiki/index.php/Don%27t_Repeat_Yourself).
- [Boy Scout Rule](http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule) needs to have been applied.

1. Your code should look like all the other code - this project should look like it was written by one man, always.
2. If you want to propose something - just create an issue and describe your question with as much description as you can.
3. Please never send issues or pull requests about code style, jshint violations etc - I do not accept it (and you will spend your time for free).
4. If you think you have some general improvement, consider creating a pull request with it.
5. If you are not sure whether your improvement is general enough, just create your own plugin for should.js. (see should.use and Assertion.add usage).
6. If you add new code, it should be covered by tests. No tests - no code.
7. If you find a bug (or at least you think it is a bug), create an issue with the library version and test case that I can run and see what are you talking about, or at least full steps by which I can reproduce it.
8.0.1 / 2015-12-11
==================

  * Fix throwing TypeError in .match

8.0.0 / 2015-12-08
==================

  * Move should-promised to main repo
  * Expose window.should as should function and not a getter

7.1.1 / 2015-10-20
==================

  * Update format package to fix node 0.12 Symbol formatting

7.1.0 / 2015-08-28
==================

  * Added .aboveOrEqual and .belowOrEqual for numbers (<= and >=)
  * Added .oneOf and .equalOneOf to check equality of one of values
  * Added 'browser' field to package.json

7.0.4 / 2015-08-14
==================

  * Missing doc for .deepEqual
  * Fix .match and dependent assertions to check property in object-object matching

7.0.3 / 2015-08-09
==================

  * Add alias .deepEqual for .eql

7.0.2 / 2015-07-09
==================

  * Bug in browser script and build

7.0.1 / 2015-06-18
==================

  * Fixes in should-type for dom nodes, host object and promises

7.0.0 / 2015-06-18
==================

  * Added support to `.eql` es6 set, map and symbol (`should-type`, `should-format`, `should-equal`)
  * **Breaking Change** More accurate work with types (dom nodes, typed-arrays).
  * **Breaking Change** Change result of should-type to be more accurate and consistent.
  * Fixed should-equal options checks
  * Fixed should-format typed arrays (more then 8 bits)
  * Added aliases: .matchEach => .matchSome, .matchAny => .matchEvery (to be similar to array methods). See #65.
  * **Breaking Change (possibly)** .matchEach and .matchAny now uses internally .match. See #65.
  * **Breaking Change** No more getter assertions. No all assertions are functions.
  * **Breaking Change** No more proxy returning, to check property names.
  * **Breaking Change** `should-format` now looks more like chrome developer tools inpections.

6.0.3 / 2015-05-18
==================

  * Replace rest of usage after 6.0.2

6.0.2 / 2015-05-18
==================

  * Replace in all internal assertions `should` usage to non getter form

6.0.1 / 2015-04-15
==================

  * Remove dummy debug messages

6.0.0 / 2015-04-15
==================

  * From .containDeep* removed .indexOf checks for strings, now it is just equality checks (see #55)
  * Fix for .not.throws for generators

5.2.0 / 2015-03-12
==================

 * Added `.matchAny`, like `.matchEach` but with `some` semantics

5.1.0 / 2015-03-05
==================

 * Initial support of es6 generators, iterables, iterators and symbols
 * .throwError now support generator functions
 * Fix bug in .propertyByPath

5.0.1 / 2015-02-21
==================

 * Export utils via should.util

5.0.0 / 2015-02-10
==================

 * Remove old .eql implementation
 * Refactor nested errors
 * Added separate reporting message for false negative results like 10.should.not.equal(10)
 * Make error.message lazy fix old perfomance bottlenecks for constructing messages for big objects
 * Added .propertyWithDescriptor

4.6.5 / 2015-02-05
==================

 * Fix perfomance degradation on large objects

4.6.4 / 2015-02-05
==================

 * Fix end cases for .containDeep and .containDeepOrdered

4.6.3 / 2015-02-01
==================

 * Added small check for .noConflict
 * Fix end cases for .containDeep and .containDeepOrdered

4.6.2 / 2015-01-28
==================

 * Make assertion properties configurable

4.6.1 / 2015-01-18
==================

 * Bump deps
 * Set showDiff only if the same types

4.6.0 / 2015-01-13
==================

 * Wrap everywhere returned assertion with Proxy if available.

4.5.2 / 2015-01-13
==================

 * Fixed null properties in .containDeep and .containDeepOrdered

4.5.1 / 2015-01-13
==================

 * Fixed leaked \_eql

4.5.0 / 2015-01-11
==================

 * Added config flag .useOldDeepEqual to use old .eql implementation

4.4.4 / 2015-01-08
==================

 * Added .enumerables

4.4.3 / 2015-01-08
==================

 * Bump dependencies to get more accurate format of promise
 * Added a lot of jsdocs

4.4.2 / 2014-12-27
==================

 * Remove breaking change with should-equal that check also object prototypes. Instead document how get both behaviours in .eql docs.

4.4.1 / 2014-12-13
==================

 * bump deps

4.4.0 / 2014-12-12
==================

 * assert methods reimplemented via assertion, deepEqual done via should-equal. To avoid possible confusion between should.deepEqual and a.should.eql(b)
 * Possible fix for error tests

4.3.1 / 2014-12-08
==================

 * `.throw()` check if given object is a function

4.3.0 / 2014-11-10
==================

 * Remove node's version of .eql
 * Added reason why .eql failed

4.2.1 / 2014-11-07
==================

 * Move inspection from .formattedObj to be in .getMessage - to make inspection as late as possible.

4.2.0 / 2014-11-06
==================

 * Remove node util.inspect and use instead own inspection module with type detection and browser types compatibility

4.1.0 / 2014-10-19
==================

 * As inspect function was moved to repo, refine how it show Dates (added millis via custom format)
 * Added warnings for potential shoot in the leg: eql non strict and should unwrapping primitive wrappers
 * Added possibility to disable any warnings via environment variable SHOULDJS_WARN and should.warn = false
 * Added new deep equality check function
 * Nested assertions can contribute to parent assertions own messages

4.0.4 / 2014-06-09
==================

 * Make all assertions enumerable in Assertion.prototype

4.0.3 / 2014-06-09
==================

 * Fix wrong/strange behaviour of .containDeep with equal keys. Now it check to contain element once.
 * Added util.formatProp to format properties more accurate

4.0.1 / 2014-06-04
==================

 * Missing name in browser script

4.0.0 / 2014-05-29
==================

 * Breaking change: Move non core assertions out
 * Added casting in properties assertions to String for all property names
 * Added .propertyByPath assertion
 * Breaking change: Remove deprecated .includeEql and .include
 * Breaking change: .containDeep now do not check order for 2 arrays case
 * Added .containDeepOrdered for old .containDeep
 * Added support of array-like objects
 * Added to .throw matching by error properties with .match

3.3.2 / 2014-05-23
==================

 * Fix for should.format

3.3.1 / 2014-04-16
==================

 * Added aliases for es reserved words
 * Fix bug with ownProperty alias
 * Fix bug with not function alias

3.3.0 / 2014-04-07
==================

 * Added .enumerable(name, val)

3.2.0 / 2014-03-29
==================

 * Added first version of .any modifier that affect assertions with multiple parameters
 * .header now have more nice message
 * assertion can now override how to show object

3.1.4 / 2014-03-18
==================

 * .Error now do not throw assertion error for custom errors.

3.1.3 / 2014-02-25
==================

 * Fix TypeError in .containEql

3.1.2 / 2014-01-28
==================

 * Fix for adding .inspect for JQuery object only in case when it is exist

3.1.1 / 2014-01-28
==================

 * Fix for HTMLElement in DOM less environments

3.1.0 / 2014-01-23
==================

 * Added jquery based browser extension

3.0.1 / 2014-01-17
==================

 * Fix: .lengthOf()

3.0.0 / 2014-01-17
==================

 * Split everything to smaller files
 * Added huge extension to .match and .matchEach. Thanks @alsotang for initial code and idea.
 * Added .containDeep and .containEql
 * Separate build for browser and node.js
 * Basic plugin system
 * Breaking change: .Object now do not fail on arrays
 * Breaking change: Additional messages now replaces generated and do not added
 * Breaking change: .keys now check as is - no keys in args means no keys in object
 * Deprecated: assert extension
 * Deprecated: .include and .includeEql
 * Now all assertions define only positive cases, should.js take care about negations and chains

2.1.1 / 2013-12-05
==================

 * Move date formatting out of should.inspect

2.1.0 / 2013-11-11
==================

 * Override .inspect for Date's to convert them to ISOString

2.0.2 / 2013-10-21
==================

 * Add '#of' as getter for chaining.
 * Exclude browser script for .npmignore.

2.0.1 / 2013-10-10
==================

 * Fix wrong path in .npmignore.

2.0.0 / 2013-10-10
==================

 * breaking change: #a now getter like #an. Was replaced with #type(str)
 * breaking change: #empty does not check length for objects. Now it check if object do not have own properties.
 * #properties check if object have some properties
 * util.inspect now exposed as should.inspect
 * assertions for NaN, Infinity, Array, Object, String, Boolean, Number, Error, Function
 * #equal got alias #exactly

1.3.0 / 2013-09-13
==================

 * fix doc for .keys. Closes #108.
 * add #endWith()
 * add .startWith (#119)

1.2.2 / 2013-02-19
==================

  * fix should.be.instanceOf() failure on Date

1.2.1 / 2012-11-02
==================

  * add .showDiff
  * Make instanceOf and throwError be aliased like others [alFReD-NSH]
  * Fix should[.not].exist not having stack trace #84 [alFReD-NSH]

1.2.0 / 2012-09-21
==================

  * Added #approximately(value, delta, description) for doing assertions on results of operations with numbers. [titarenko]

1.1.1 / 2012-09-19
==================

  * add .type for eql()s assert

1.1.0 / 2012-07-30
==================

  * add enclosing of failure message functions. Closes #81
  * add mocha .actual / .expected string support for all assertion values

0.7.0 / 2012-07-17
==================

  * add `.throw(Constructor)` support [snakamura]

0.6.3 / 2012-04-26
==================

  * Added object inclusion support back

0.6.2 / 2012-04-26
==================

  * Added homepage to package.json
  * Fixed .equal() with dates. Closes #63

0.6.1 / 2012-04-10
==================

  * package: add "repository" section [TooTallNate]
  * use valueOf() to get the reference the object [TooTallNate]

0.6.0 / 2012-03-01
==================

  * Added `err.actual` and `err.expected` for .{eql,equal}()
  * Added 'return this;' to 'get json' and 'get html' in order to provide chaining for should.be.json and should.be.html

0.5.1 / 2012-01-13
==================

  * Added better `.json`
  * Added better `.html`

0.5.0 / 2012-01-12
==================

  * Added string matching to `.throw()` [serby]
  * Added regexp matching to `.throw()` [serby]
  * Added `.includeEql()` [RubenVerborgh]
  * Added `.should.be.html`
  * Added `.should.be.json`
  * Added optional description args to most matchers [Mike Swift]

0.4.2 / 2011-12-17
==================

  * Fixed .header() for realzzz

0.4.1 / 2011-12-16
==================

  * Fixed: chain .header() to retain negation

0.4.0 / 2011-12-16
==================

  * Added `.should.throw()`
  * Added `.include()` support for strings
  * Added `.include()` support for arrays
  * Removed `keys()` `.include` modifier support
  * Removed `.object()`
  * Removed `.string()`
  * Removed `.contain()`
  * Removed `.respondTo()` rubyism
  * expresso -> mocha

0.3.2 / 2011-10-24
==================

  * Fixed tests for 0.5.x
  * Fixed sys warning

0.3.1 / 2011-08-22
==================

  * configurable

0.3.0 / 2011-08-20
==================

  * Added assertion for inclusion of an object: `foo.should.include.object({ foo: 'bar' })`

0.2.1 / 2011-05-13
==================

  * Fixed .status(code). Closes #18

0.2.0 / 2011-04-17
==================

  * Added `res.should.have.status(code)` method
  * Added `res.should.have.header(field, val)` method

0.1.0 / 2011-04-06
==================

  * Added `should.exist(obj)` [aseemk]
  * Added `should.not.exist(obj)` [aseemk]

0.0.4 / 2010-11-24
==================

  * Added `.ok` to assert truthfulness
  * Added `.arguments`
  * Fixed double required bug. [thanks dominictarr]

0.0.3 / 2010-11-19
==================

  * Added `true` / `false` assertions

0.0.2 / 2010-11-19
==================

  * Added chaining support

0.0.1 / 2010-11-19
==================

  * Initial release
Copyright (c) 2010-2014 TJ Holowaychuk <tj@vision-media.ca>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# should.js

[![Join the chat at https://gitter.im/shouldjs/should.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/shouldjs/should.js)

[![Build Status](https://travis-ci.org/shouldjs/should.js.svg?branch=master)](https://travis-ci.org/shouldjs/should.js)

[![Selenium Test Status](https://saucelabs.com/browser-matrix/shouldjs.svg)](https://saucelabs.com/u/shouldjs)

_should_ is an expressive, readable, framework-agnostic assertion library. The main goals of this library are __to be expressive__ and __to be helpful__. It keeps your test code clean, and your error messages helpful.

By default (when you `require('should')`) _should_ extends the `Object.prototype` with a single non-enumerable getter that allows you to express how that object should behave. It also returns itself when required with `require`.

It is also possible to use should.js without getter (it will not even try to extend Object.prototype), just `require('should/as-function')`. Or if you already use version that auto add getter, you can call `.noConflict` function.

**Results of `(something).should` getter and `should(something)` in most situations are the same**

### Upgrading instructions

Please check [wiki page](https://github.com/shouldjs/should.js/wiki/Breaking-changes) for upgrading instructions.

### FAQ

You can take look in [FAQ](https://github.com/shouldjs/should.js/wiki/FAQ).

## Example
```javascript
var should = require('should');

var user = {
    name: 'tj'
  , pets: ['tobi', 'loki', 'jane', 'bandit']
};

user.should.have.property('name', 'tj');
user.should.have.property('pets').with.lengthOf(4);

// If the object was created with Object.create(null)
// then it doesn't inherit `Object.prototype`, so it will not have `.should` getter
// so you can do:
should(user).have.property('name', 'tj');

// also you can test in that way for null's
should(null).not.be.ok();

someAsyncTask(foo, function(err, result){
  should.not.exist(err);
  should.exist(result);
  result.bar.should.equal(foo);
});
```
## To begin

 1. Install it:

    ```bash
    $ npm install should --save-dev
    ```

 2. Require it and use:

    ```js
    var should = require('should');

    (5).should.be.exactly(5).and.be.a.Number();
    ```

    ```js
    var should = require('should/as-function');

    should(10).be.exactly(5).and.be.a.Number();
    ```

## In browser

Well, even when browsers by complains of authors has 100% es5 support, it does not mean it has no bugs. Please see [wiki](https://github.com/shouldjs/should.js/wiki/Known-Bugs) for known bugs.

If you want to use _should_ in browser, use the `should.js` file in the root of this repository, or build it yourself. To build a fresh version:

```bash
$ npm install
$ gulp script
```

The script is exported to `window.should`:

```js
should(10).be.exactly(10)
```

You can easy install it with npm or bower:

```sh
npm install should -D
# or
bower install shouldjs/should.js
```

## API docs

Actual api docs generated by jsdoc comments and available at [http://shouldjs.github.io](http://shouldjs.github.io).

## Usage examples

Please look on usage in [examples](https://github.com/shouldjs/examples)

## .not

`.not` negates the current assertion.

## .any

`.any` allow for assertions with multiple parameters to assert any of the parameters (but not all). This is similar to the native JavaScript [array.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some).

# Assertions
## chaining assertions

Every assertion will return a `should.js`-wrapped Object, so assertions can be chained.
To help chained assertions read more clearly, you can use the following helpers anywhere in your chain: `.an`, `.of`, `.a`, `.and`, `.be`, `.have`, `.with`, `.is`, `.which`. Use them for better readability; they do nothing at all.
For example:
```js
user.should.be.an.instanceOf(Object).and.have.property('name', 'tj');
user.pets.should.be.instanceof(Array).and.have.lengthOf(4);
```
Almost all assertions return the same object - so you can easy chain them. But some (eg: `.length` and `.property`) move the assertion object to a property value, so be careful.

## Adding own assertions

Adding own assertion is pretty easy. You need to call `should.Assertion.add` function. It accept 2 arguments:

1. name of assertion method (string)
2. assertion function (function)

What assertion function should do. It should check only positive case. `should` will handle `.not` itself.
`this` in assertion function will be instance of `should.Assertion` and you **must** define in any way this.params object
 in your assertion function call before assertion check happen.

`params` object can contain several fields:

- `operator` - it is string which describe your assertion
- `actual` it is actual value, you can assume it is your own this.obj if you need to define you own
- `expected` it is any value that expected to be matched this.obj

You can assume its usage in generating AssertionError message like: expected `obj`? || this.obj not? `operator` `expected`?

In `should` sources appeared 2 kinds of usage of this method.

First not preferred and used **only** for shortcuts to other assertions, e.g how `.should.be.true()` defined:

```javascript
Assertion.add('true', function() {
    this.is.exactly(true);
});
```
There you can see that assertion function do not define own `this.params` and instead call within the same assertion `.exactly`
that will fill `this.params`. **You should use this way very carefully, but you can use it**.

Second way preferred and i assume you will use it instead of first.

```javascript
Assertion.add('true', function() {
    this.params = { operator: 'to be true', expected: true };

    should(this.obj).be.exactly(true);
});
```
in this case this.params defined and then used new assertion context (because called `.should`). Internally this way does not
 create any edge cases as first.

```javascript
Assertion.add('asset', function() {
    this.params = { operator: 'to be asset' };

    this.obj.should.have.property('id').which.is.a.Number();
    this.obj.should.have.property('path');
})

//then
> ({ id: '10' }).should.be.an.asset();
AssertionError: expected { id: '10' } to be asset
    expected '10' to be a number

> ({ id: 10 }).should.be.an.asset();
AssertionError: expected { id: 10 } to be asset
    expected { id: 10 } to have property path
```


## Contributions

[Actual list of contributors](https://github.com/visionmedia/should.js/graphs/contributors) if you want to show it your friends.

To run the tests for _should_ simply run:

    $ npm test

See also [CONTRIBUTING](./CONTRIBUTING.md).

## OMG IT EXTENDS OBJECT???!?!@

Yes, yes it does, with a single getter _should_, and no it won't break your code, because it does this **properly** with a non-enumerable property.

Also it is possible use it without extension.

## License

MIT &copy; 2010-2014 TJ Holowaychuk
module.exports = require('./lib/should');
{
  "name": "should",
  "main": "should.js",
  "homepage": "https://github.com/shouldjs/should.js",
  "repository": {
    "type": "git",
    "url": "git://github.com/shouldjs/should.js.git"
  },
  "authors": [
    "TJ Holowaychuk <tj@vision-media.ca> and contributors"
  ],
  "description": "test framework agnostic BDD-style assertions",
  "keywords": [
    "test",
    "bdd",
    "assert",
    "should"
  ],
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "test",
    "*.md",
    "LICENSE",
    "package.json"
  ]
}
window.Should = require('./index');

Object.defineProperty(window, 'should', {
  enumerable: false,
  configurable: true,
  value: window.Should
});
var gulp = require('gulp');

var header = require('gulp-header');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');

var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');

var browserify = require('browserify');

var pkg = require('./package.json');

var banner = [
  '/*!',
  ' * <%= pkg.name %> - <%= pkg.description %>',
  ' * @version v<%= pkg.version %>',
  ' * @author <%= pkg.author %>',
  ' * @link <%= pkg.homepage %>',
  ' * @license <%= pkg.license %>',
  ' */',
  ''].join('\n');

gulp.task('script', function() {
  var bundleStream = browserify({
    entries: './browser-entry',
    builtins: null,
    insertGlobals: false,
    detectGlobals: false,
    standalone: 'Should',
    fullPaths: false
  })
    .bundle();

  return bundleStream
    .pipe(source('should.js'))
    .pipe(buffer())
    .pipe(header(banner, {pkg: pkg}))
    .pipe(gulp.dest('./'))
    .pipe(uglify({ preserveComments: 'some' }))
    .pipe(rename('should.min.js'))
    .pipe(gulp.dest('./'));
});
var should = require('./lib/should');

var defaultProto = Object.prototype;
var defaultProperty = 'should';

//Expose api via `Object#should`.
try {
  var prevShould = should.extend(defaultProperty, defaultProto);
  should._prevShould = prevShould;
} catch(e) {
  //ignore errors
}

module.exports = should;
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('./util');

/**
 * should AssertionError
 * @param {Object} options
 * @constructor
 * @memberOf should
 * @static
 */
var AssertionError = function AssertionError(options) {
  util.merge(this, options);

  if(!options.message) {
    Object.defineProperty(this, 'message', {
        get: function() {
          if(!this._message) {
            this._message = this.generateMessage();
            this.generatedMessage = true;
          }
          return this._message;
        },
        configurable: true,
        enumerable: false
      }
    );
  }

  if(Error.captureStackTrace) {
    Error.captureStackTrace(this, this.stackStartFunction);
  } else {
    // non v8 browsers so we can have a stacktrace
    var err = new Error();
    if(err.stack) {
      var out = err.stack;

      if(this.stackStartFunction) {
        // try to strip useless frames
        var fn_name = util.functionName(this.stackStartFunction);
        var idx = out.indexOf('\n' + fn_name);
        if(idx >= 0) {
          // once we have located the function frame
          // we need to strip out everything before it (and its line)
          var next_line = out.indexOf('\n', idx + 1);
          out = out.substring(next_line + 1);
        }
      }

      this.stack = out;
    }
  }
};


var indent = '    ';
function prependIndent(line) {
  return indent + line;
}

function indentLines(text) {
  return text.split('\n').map(prependIndent).join('\n');
}


// assert.AssertionError instanceof Error
AssertionError.prototype = Object.create(Error.prototype, {
  name: {
    value: 'AssertionError'
  },

  generateMessage: {
    value: function() {
      if(!this.operator && this.previous) {
        return this.previous.message;
      }
      var actual = util.format(this.actual);
      var expected = 'expected' in this ? ' ' + util.format(this.expected) : '';
      var details = 'details' in this && this.details ? ' (' + this.details + ')' : '';

      var previous = this.previous ? '\n' + indentLines(this.previous.message) : '';

      return 'expected ' + actual + (this.negate ? ' not ' : ' ') + this.operator + expected + details + previous;
    }
  }
});

module.exports = AssertionError;
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var AssertionError = require('./assertion-error');

/**
 * should Assertion
 * @param {*} obj Given object for assertion
 * @constructor
 * @memberOf should
 * @static
 */
function Assertion(obj) {
  this.obj = obj;

  this.anyOne = false;
  this.negate = false;

  this.params = {actual: obj};
}

Assertion.prototype = {
  constructor: Assertion,

  /**
   * Base method for assertions.
   *
   * Before calling this method need to fill Assertion#params object. This method usually called from other assertion methods.
   * `Assertion#params` can contain such properties:
   * * `operator` - required string containing description of this assertion
   * * `obj` - optional replacement for this.obj, it usefull if you prepare more clear object then given
   * * `message` - if this property filled with string any others will be ignored and this one used as assertion message
   * * `expected` - any object used when you need to assert relation between given object and expected. Like given == expected (== is a relation)
   * * `details` - additional string with details to generated message
   *
   * @memberOf Assertion
   * @category assertion
   * @param {*} expr Any expression that will be used as a condition for asserting.
   * @example
   *
   * var a = new should.Assertion(42);
   *
   * a.params = {
   *  operator: 'to be magic number',
   * }
   *
   * a.assert(false);
   * //throws AssertionError: expected 42 to be magic number
   */
  assert: function(expr) {
    if(expr) {
      return this;
    }

    var params = this.params;

    if('obj' in params && !('actual' in params)) {
      params.actual = params.obj;
    } else if(!('obj' in params) && !('actual' in params)) {
      params.actual = this.obj;
    }

    params.stackStartFunction = params.stackStartFunction || this.assert;
    params.negate = this.negate;

    params.assertion = this;

    throw new AssertionError(params);
  },

  /**
   * Shortcut for `Assertion#assert(false)`.
   *
   * @memberOf Assertion
   * @category assertion
   * @example
   *
   * var a = new should.Assertion(42);
   *
   * a.params = {
   *  operator: 'to be magic number',
   * }
   *
   * a.fail();
   * //throws AssertionError: expected 42 to be magic number
   */
  fail: function() {
    return this.assert(false);
  }
};



/**
 * Assertion used to delegate calls of Assertion methods inside of Promise.
 * It has almost all methods of Assertion.prototype
 *
 * @param {Promise} obj
 */
function PromisedAssertion(/* obj */) {
  Assertion.apply(this, arguments);
}

/**
 * Make PromisedAssertion to look like promise. Delegate resolve and reject to given promise.
 * 
 * @private
 * @returns {Promise}
 */
PromisedAssertion.prototype.then = function(resolve, reject) {
  return this.obj.then(resolve, reject);
};

/**
 * Way to extend Assertion function. It uses some logic
 * to define only positive assertions and itself rule with negative assertion.
 *
 * All actions happen in subcontext and this method take care about negation.
 * Potentially we can add some more modifiers that does not depends from state of assertion.
 *
 * @memberOf Assertion
 * @static
 * @param {String} name Name of assertion. It will be used for defining method or getter on Assertion.prototype
 * @param {Function} func Function that will be called on executing assertion
 * @example
 *
 * Assertion.add('asset', function() {
 *      this.params = { operator: 'to be asset' }
 *
 *      this.obj.should.have.property('id').which.is.a.Number()
 *      this.obj.should.have.property('path')
 * })
 */
Assertion.add = function(name, func) {
  Object.defineProperty(Assertion.prototype, name, {
    enumerable: true,
    configurable: true,
    value: function() {
      var context = new Assertion(this.obj, this, name);
      context.anyOne = this.anyOne;

      try {
        func.apply(context, arguments);
      } catch (e) {
        // check for fail
        if (e instanceof AssertionError) {
          // negative fail
          if (this.negate) {
            this.obj = context.obj;
            this.negate = false;
            return this;
          }

          if (context !== e.assertion) {
            context.params.previous = e;
          }

          // positive fail
          context.negate = false;
          context.fail();
        }
        // throw if it is another exception
        throw e;
      }

      // negative pass
      if (this.negate) {
        context.negate = true; // because .fail will set negate
        context.params.details = 'false negative fail';
        context.fail();
      }

      // positive pass
      if (!this.params.operator) {
        this.params = context.params; // shortcut
      }
      this.obj = context.obj;
      this.negate = false;
      return this;
    }
  });

  Object.defineProperty(PromisedAssertion.prototype, name, {
    enumerable: true,
    configurable: true,
    value: function() {
      var args = arguments;
      this.obj = this.obj.then(function(a) {
        return a[name].apply(a, args);
      });

      return this;
    }
  });
};

/**
 * Add chaining getter to Assertion like .a, .which etc
 * 
 * @memberOf Assertion
 * @static
 * @param  {string} name   name of getter
 * @param  {function} [onCall] optional function to call
 */
Assertion.addChain = function(name, onCall) {
  onCall = onCall || function() {};
  Object.defineProperty(Assertion.prototype, name, {
    get: function() {
      onCall.call(this);
      return this;
    },
    enumerable: true
  });

  Object.defineProperty(PromisedAssertion.prototype, name, {
    enumerable: true,
    configurable: true,
    get: function() {
      this.obj = this.obj.then(function(a) {
        return a[name];
      });

      return this;
    }
  });
};

/**
 * Create alias for some `Assertion` property
 *
 * @memberOf Assertion
 * @static
 * @param {String} from Name of to map
 * @param {String} to Name of alias
 * @example
 *
 * Assertion.alias('true', 'True')
 */
Assertion.alias = function(from, to) {
  var desc = Object.getOwnPropertyDescriptor(Assertion.prototype, from);
  if (!desc) throw new Error('Alias ' + from + ' -> ' + to + ' could not be created as ' + from + ' not defined');
  Object.defineProperty(Assertion.prototype, to, desc);

  var desc2 = Object.getOwnPropertyDescriptor(PromisedAssertion.prototype, from);
  if (desc2) {
    Object.defineProperty(PromisedAssertion.prototype, to, desc2);
  }
};
/**
 * Negation modifier. Current assertion chain become negated. Each call invert negation on current assertion.
 *
 * @name not
 * @property
 * @memberOf Assertion
 * @category assertion
 */
Assertion.addChain('not', function() {
  this.negate = !this.negate;
});

/**
 * Any modifier - it affect on execution of sequenced assertion to do not `check all`, but `check any of`.
 *
 * @name any
 * @property
 * @memberOf Assertion
 * @category assertion
 */
Assertion.addChain('any', function() {
  this.anyOne = true;
});

module.exports = Assertion;
module.exports.PromisedAssertion = PromisedAssertion;
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var Formatter = require('should-format').Formatter;

var config = {
  checkProtoEql: false,

  getFormatter: function(opts) {
    return new Formatter(opts || config);
  }
};

module.exports = config;
// implement assert interface using already written peaces of should.js

// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// when used in node, this will actually load the util module we depend on
// versus loading the builtin util module as happens otherwise
// this is a bug in node module loading as far as I am concerned
var Assertion = require('./../assertion');

var _deepEqual = require('should-equal');

var pSlice = Array.prototype.slice;

// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.

var assert = module.exports = ok;

// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided.  All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
/**
 * Node.js standard [`assert.fail`](http://nodejs.org/api/assert.html#assert_assert_fail_actual_expected_message_operator).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual Actual object
 * @param {*} expected Expected object
 * @param {string} message Message for assertion
 * @param {string} operator Operator text
 */
function fail(actual, expected, message, operator, stackStartFunction) {
  var a = new Assertion(actual);
  a.params = {
    operator: operator,
    expected: expected,
    message: message,
    stackStartFunction: stackStartFunction || fail
  };

  a.fail();
}

// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;

// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
/**
 * Node.js standard [`assert.ok`](http://nodejs.org/api/assert.html#assert_assert_value_message_assert_ok_value_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} value
 * @param {string} [message]
 */
function ok(value, message) {
  if(!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;

// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);

/**
 * Node.js standard [`assert.equal`](http://nodejs.org/api/assert.html#assert_assert_equal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.equal = function equal(actual, expected, message) {
  if(actual != expected) fail(actual, expected, message, '==', assert.equal);
};

// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
/**
 * Node.js standard [`assert.notEqual`](http://nodejs.org/api/assert.html#assert_assert_notequal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.notEqual = function notEqual(actual, expected, message) {
  if(actual == expected) {
    fail(actual, expected, message, '!=', assert.notEqual);
  }
};

// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
/**
 * Node.js standard [`assert.deepEqual`](http://nodejs.org/api/assert.html#assert_assert_deepequal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.deepEqual = function deepEqual(actual, expected, message) {
  if(!_deepEqual(actual, expected).result) {
    fail(actual, expected, message, 'deepEqual', assert.deepEqual);
  }
};


// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
/**
 * Node.js standard [`assert.notDeepEqual`](http://nodejs.org/api/assert.html#assert_assert_notdeepequal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
  if(_deepEqual(actual, expected).result) {
    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
  }
};

// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
/**
 * Node.js standard [`assert.strictEqual`](http://nodejs.org/api/assert.html#assert_assert_strictequal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.strictEqual = function strictEqual(actual, expected, message) {
  if(actual !== expected) {
    fail(actual, expected, message, '===', assert.strictEqual);
  }
};

// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);
/**
 * Node.js standard [`assert.notStrictEqual`](http://nodejs.org/api/assert.html#assert_assert_notstrictequal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
  if(actual === expected) {
    fail(actual, expected, message, '!==', assert.notStrictEqual);
  }
};

function expectedException(actual, expected) {
  if(!actual || !expected) {
    return false;
  }

  if(Object.prototype.toString.call(expected) == '[object RegExp]') {
    return expected.test(actual);
  } else if(actual instanceof expected) {
    return true;
  } else if(expected.call({}, actual) === true) {
    return true;
  }

  return false;
}

function _throws(shouldThrow, block, expected, message) {
  var actual;

  if(typeof expected == 'string') {
    message = expected;
    expected = null;
  }

  try {
    block();
  } catch(e) {
    actual = e;
  }

  message = (expected && expected.name ? ' (' + expected.name + ')' : '.') +
  (message ? ' ' + message : '.');

  if(shouldThrow && !actual) {
    fail(actual, expected, 'Missing expected exception' + message);
  }

  if(!shouldThrow && expectedException(actual, expected)) {
    fail(actual, expected, 'Got unwanted exception' + message);
  }

  if((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) {
    throw actual;
  }
}

// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
/**
 * Node.js standard [`assert.throws`](http://nodejs.org/api/assert.html#assert_assert_throws_block_error_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {Function} block
 * @param {Function} [error]
 * @param {String} [message]
 */
assert.throws = function(block, /*optional*/error, /*optional*/message) {
  _throws.apply(this, [true].concat(pSlice.call(arguments)));
};

// EXTENSION! This is annoying to write outside this module.
/**
 * Node.js standard [`assert.doesNotThrow`](http://nodejs.org/api/assert.html#assert_assert_doesnotthrow_block_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {Function} block
 * @param {String} [message]
 */
assert.doesNotThrow = function(block, /*optional*/message) {
  _throws.apply(this, [false].concat(pSlice.call(arguments)));
};

/**
 * Node.js standard [`assert.ifError`](http://nodejs.org/api/assert.html#assert_assert_iferror_value).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {Error} err
 */
assert.ifError = function(err) {
  if(err) {
    throw err;
  }
};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util')
  , assert = require('./_assert')
  , AssertionError = require('../assertion-error');

module.exports = function(should) {
  var i = should.format;

  /*
   * Expose assert to should
   *
   * This allows you to do things like below
   * without require()ing the assert module.
   *
   *    should.equal(foo.bar, undefined);
   *
   */
  util.merge(should, assert);

  /**
   * Assert _obj_ exists, with optional message.
   *
   * @static
   * @memberOf should
   * @category assertion assert
   * @alias should.exists
   * @param {*} obj
   * @param {String} [msg]
   * @example
   *
   * should.exist(1);
   * should.exist(new Date());
   */
  should.exist = should.exists = function(obj, msg) {
    if(null == obj) {
      throw new AssertionError({
        message: msg || ('expected ' + i(obj) + ' to exist'), stackStartFunction: should.exist
      });
    }
  };

  should.not = {};
  /**
   * Asserts _obj_ does not exist, with optional message.
   *
   * @name not.exist
   * @static
   * @memberOf should
   * @category assertion assert
   * @alias should.not.exists
   * @param {*} obj
   * @param {String} [msg]
   * @example
   *
   * should.not.exist(null);
   * should.not.exist(void 0);
   */
  should.not.exist = should.not.exists = function(obj, msg) {
    if(null != obj) {
      throw new AssertionError({
        message: msg || ('expected ' + i(obj) + ' to not exist'), stackStartFunction: should.not.exist
      });
    }
  };
};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

module.exports = function(should, Assertion) {
  /**
   * Assert given object is exactly `true`.
   *
   * @name true
   * @memberOf Assertion
   * @category assertion bool
   * @alias Assertion#True
   * @example
   *
   * (true).should.be.true();
   * false.should.not.be.true();
   *
   * ({ a: 10}).should.not.be.true();
   */
  Assertion.add('true', function() {
    this.is.exactly(true);
  });

  Assertion.alias('true', 'True');

  /**
   * Assert given object is exactly `false`.
   *
   * @name false
   * @memberOf Assertion
   * @category assertion bool
   * @alias Assertion#False
   * @example
   *
   * (true).should.not.be.false();
   * false.should.be.false();
   */
  Assertion.add('false', function() {
    this.is.exactly(false);
  });

  Assertion.alias('false', 'False');

  /**
   * Assert given object is thuthy according javascript type conversions.
   *
   * @name ok
   * @memberOf Assertion
   * @category assertion bool
   * @example
   *
   * (true).should.be.ok();
   * ''.should.not.be.ok();
   * should(null).not.be.ok();
   * should(void 0).not.be.ok();
   *
   * (10).should.be.ok();
   * (0).should.not.be.ok();
   */
  Assertion.add('ok', function() {
    this.params = { operator: 'to be truthy' };

    this.assert(this.obj);
  });
};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

module.exports = function(should, Assertion) {
  /**
   * Simple chaining. It actually do nothing.
   *
   * @memberOf Assertion
   * @name be
   * @property {should.Assertion} be
   * @alias Assertion#an
   * @alias Assertion#of
   * @alias Assertion#a
   * @alias Assertion#and
   * @alias Assertion#have
   * @alias Assertion#has
   * @alias Assertion#with
   * @alias Assertion#is
   * @alias Assertion#which
   * @alias Assertion#the
   * @alias Assertion#it
   * @category assertion chaining
   */
  ['an', 'of', 'a', 'and', 'be', 'has', 'have', 'with', 'is', 'which', 'the', 'it'].forEach(function(name) {
    Assertion.addChain(name);
  });
};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util');
var eql = require('should-equal');

module.exports = function(should, Assertion) {
  var i = should.format;

  /**
   * Assert that given object contain something that equal to `other`. It uses `should-equal` for equality checks.
   * If given object is array it search that one of elements was equal to `other`.
   * If given object is string it checks if `other` is a substring - expected that `other` is a string.
   * If given object is Object it checks that `other` is a subobject - expected that `other` is a object.
   *
   * @name containEql
   * @memberOf Assertion
   * @category assertion contain
   * @param {*} other Nested object
   * @example
   *
   * [1, 2, 3].should.containEql(1);
   * [{ a: 1 }, 'a', 10].should.containEql({ a: 1 });
   *
   * 'abc'.should.containEql('b');
   * 'ab1c'.should.containEql(1);
   *
   * ({ a: 10, c: { d: 10 }}).should.containEql({ a: 10 });
   * ({ a: 10, c: { d: 10 }}).should.containEql({ c: { d: 10 }});
   * ({ a: 10, c: { d: 10 }}).should.containEql({ b: 10 });
   * // throws AssertionError: expected { a: 10, c: { d: 10 } } to contain { b: 10 }
   * //            expected { a: 10, c: { d: 10 } } to have property b
   */
  Assertion.add('containEql', function(other) {
    this.params = {operator: 'to contain ' + i(other)};

    this.is.not.null().and.not.undefined();

    var obj = this.obj;

    if(typeof obj == 'string') {
      this.assert(obj.indexOf(String(other)) >= 0);
    } else if(util.isIndexable(obj)) {
      this.assert(util.some(obj, function(v) {
        return eql(v, other).result;
      }));
    } else {
      this.have.properties(other);
    }
  });

  /**
   * Assert that given object is contain equally structured object on the same depth level.
   * If given object is an array and `other` is an array it checks that the eql elements is going in the same sequence in given array (recursive)
   * If given object is an object it checks that the same keys contain deep equal values (recursive)
   * On other cases it try to check with `.eql`
   *
   * @name containDeepOrdered
   * @memberOf Assertion
   * @category assertion contain
   * @param {*} other Nested object
   * @example
   *
   * [ 1, 2, 3].should.containDeepOrdered([1, 2]);
   * [ 1, 2, [ 1, 2, 3 ]].should.containDeepOrdered([ 1, [ 2, 3 ]]);
   *
   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({a: 10});
   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {c: 10}});
   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {d: [1, 3]}});
   */
  Assertion.add('containDeepOrdered', function(other) {
    this.params = {operator: 'to contain ' + i(other)};

    var obj = this.obj;
    if(typeof obj == 'string') {// expect other to be string
      this.is.equal(String(other));
    } else if(util.isIndexable(obj) && util.isIndexable(other)) {
      for(var objIdx = 0, otherIdx = 0, objLength = util.length(obj), otherLength = util.length(other); objIdx < objLength && otherIdx < otherLength; objIdx++) {
        try {
          should(obj[objIdx]).containDeepOrdered(other[otherIdx]);
          otherIdx++;
        } catch(e) {
          if(e instanceof should.AssertionError) {
            continue;
          }
          throw e;
        }
      }

      this.assert(otherIdx === otherLength);
    } else if(obj != null && other != null && typeof obj == 'object' && typeof other == 'object') {// object contains object case
      util.forEach(other, function(value, key) {
        should(obj[key]).containDeepOrdered(value);
      });

      // if both objects is empty means we finish traversing - and we need to compare for hidden values
      if(util.isEmptyObject(other)) {
        this.eql(other);
      }
    } else {
      this.eql(other);
    }
  });

  /**
   * The same like `Assertion#containDeepOrdered` but all checks on arrays without order.
   *
   * @name containDeep
   * @memberOf Assertion
   * @category assertion contain
   * @param {*} other Nested object
   * @example
   *
   * [ 1, 2, 3].should.containDeep([2, 1]);
   * [ 1, 2, [ 1, 2, 3 ]].should.containDeep([ 1, [ 3, 1 ]]);
   */
  Assertion.add('containDeep', function(other) {
    this.params = {operator: 'to contain ' + i(other)};

    var obj = this.obj;
    if(typeof obj == 'string') {// expect other to be string
      this.is.equal(String(other));
    } else if(util.isIndexable(obj) && util.isIndexable(other)) {
      var usedKeys = {};
      util.forEach(other, function(otherItem) {
        this.assert(util.some(obj, function(item, index) {
          if(index in usedKeys) return false;

          try {
            should(item).containDeep(otherItem);
            usedKeys[index] = true;
            return true;
          } catch(e) {
            if(e instanceof should.AssertionError) {
              return false;
            }
            throw e;
          }
        }));
      }, this);
    } else if(obj != null && other != null && typeof obj == 'object' && typeof other == 'object') {// object contains object case
      util.forEach(other, function(value, key) {
        should(obj[key]).containDeep(value);
      });

      // if both objects is empty means we finish traversing - and we need to compare for hidden values
      if(util.isEmptyObject(other)) {
        this.eql(other);
      }
    } else {
      this.eql(other);
    }
  });

};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var eql = require('should-equal');
var type = require('should-type');
var util = require('../util');

function formatEqlResult(r, a, b) {
  return ((r.path.length > 0 ? 'at ' + r.path.map(util.formatProp).join(' -> ') : '') +
  (r.a === a ? '' : ', A has ' + util.format(r.a)) +
  (r.b === b ? '' : ' and B has ' + util.format(r.b)) +
  (r.showReason ? ' because ' + r.reason : '')).trim();
}

module.exports = function(should, Assertion) {

  /**
   * Deep object equality comparison. For full spec see [`should-equal tests`](https://github.com/shouldjs/equal/blob/master/test.js).
   *
   * @name eql
   * @memberOf Assertion
   * @category assertion equality
   * @alias Assertion#deepEqual
   * @param {*} val Expected value
   * @param {string} [description] Optional message
   * @example
   *
   * (10).should.be.eql(10);
   * ('10').should.not.be.eql(10);
   * (-0).should.not.be.eql(+0);
   *
   * NaN.should.be.eql(NaN);
   *
   * ({ a: 10}).should.be.eql({ a: 10 });
   * [ 'a' ].should.not.be.eql({ '0': 'a' });
   */
  Assertion.add('eql', function(val, description) {
    this.params = {operator: 'to equal', expected: val, message: description};

    var result = eql(this.obj, val, should.config);
    this.params.details = result.result ? '' : formatEqlResult(result, this.obj, val);

    this.params.showDiff = eql(type(this.obj), type(val)).result;

    this.assert(result.result);
  });

  /**
   * Exact comparison using ===.
   *
   * @name equal
   * @memberOf Assertion
   * @category assertion equality
   * @alias Assertion#exactly
   * @param {*} val Expected value
   * @param {string} [description] Optional message
   * @example
   *
   * 10.should.be.equal(10);
   * 'a'.should.be.exactly('a');
   *
   * should(null).be.exactly(null);
   */
  Assertion.add('equal', function(val, description) {
    this.params = {operator: 'to be', expected: val, message: description};

    this.params.showDiff = eql(type(this.obj), type(val)).result;

    this.assert(val === this.obj);
  });

  Assertion.alias('equal', 'exactly');
  Assertion.alias('eql', 'deepEqual');

  function addOneOf(name, message, method) {
    Assertion.add(name, function(vals) {
      if(arguments.length !== 1) {
        vals = Array.prototype.slice.call(arguments);
      } else {
        should(vals).be.Array();
      }

      this.params = {operator: message, expected: vals};

      var obj = this.obj;
      var found = false;

      util.forEach(vals, function(val) {
        try {
          should(val)[method](obj);
          found = true;
          return false;
        } catch(e) {
          if(e instanceof should.AssertionError) {
            return;//do nothing
          }
          throw e;
        }
      });

      this.assert(found);
    });
  }

  /**
   * Exact comparison using === to be one of supplied objects.
   *
   * @name equalOneOf
   * @memberOf Assertion
   * @category assertion equality
   * @param {Array|*} vals Expected values
   * @example
   *
   * 'ab'.should.be.equalOneOf('a', 10, 'ab');
   * 'ab'.should.be.equalOneOf(['a', 10, 'ab']);
   */
  addOneOf('equalOneOf', 'to be equals one of', 'equal');

  /**
   * Exact comparison using .eql to be one of supplied objects.
   *
   * @name oneOf
   * @memberOf Assertion
   * @category assertion equality
   * @param {Array|*} vals Expected values
   * @example
   *
   * ({a: 10}).should.be.oneOf('a', 10, 'ab', {a: 10});
   * ({a: 10}).should.be.oneOf(['a', 10, 'ab', {a: 10}]);
   */
  addOneOf('oneOf', 'to be one of', 'eql');

};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */
var util = require('../util');

module.exports = function(should, Assertion) {
  var i = should.format;

  /**
   * Assert given function throws error with such message.
   *
   * @name throw
   * @memberOf Assertion
   * @category assertion errors
   * @alias Assertion#throwError
   * @param {string|RegExp|Function|Object|GeneratorFunction|GeneratorObject} [message] Message to match or properties
   * @param {Object} [properties] Optional properties that will be matched to thrown error
   * @example
   *
   * (function(){ throw new Error('fail') }).should.throw();
   * (function(){ throw new Error('fail') }).should.throw('fail');
   * (function(){ throw new Error('fail') }).should.throw(/fail/);
   *
   * (function(){ throw new Error('fail') }).should.throw(Error);
   * var error = new Error();
   * error.a = 10;
   * (function(){ throw error; }).should.throw(Error, { a: 10 });
   * (function(){ throw error; }).should.throw({ a: 10 });
   * (function*() {
   *   yield throwError();
   * }).should.throw();
   */
  Assertion.add('throw', function(message, properties) {
    var fn = this.obj
      , err = {}
      , errorInfo = ''
      , thrown = false;

    if(util.isGeneratorFunction(fn)) {
      return should(fn()).throw(message, properties);
    } else if(util.isGeneratorObject(fn)) {
      return should(fn.next.bind(fn)).throw(message, properties);
    }

    this.is.a.Function();

    var errorMatched = true;

    try {
      fn();
    } catch(e) {
      thrown = true;
      err = e;
    }

    if(thrown) {
      if(message) {
        if('string' == typeof message) {
          errorMatched = message == err.message;
        } else if(message instanceof RegExp) {
          errorMatched = message.test(err.message);
        } else if('function' == typeof message) {
          errorMatched = err instanceof message;
        } else if(null != message) {
          try {
            should(err).match(message);
          } catch(e) {
            if(e instanceof should.AssertionError) {
              errorInfo = ": " + e.message;
              errorMatched = false;
            } else {
              throw e;
            }
          }
        }

        if(!errorMatched) {
          if('string' == typeof message || message instanceof RegExp) {
            errorInfo = " with a message matching " + i(message) + ", but got '" + err.message + "'";
          } else if('function' == typeof message) {
            errorInfo = " of type " + util.functionName(message) + ", but got " + util.functionName(err.constructor);
          }
        } else if('function' == typeof message && properties) {
          try {
            should(err).match(properties);
          } catch(e) {
            if(e instanceof should.AssertionError) {
              errorInfo = ": " + e.message;
              errorMatched = false;
            } else {
              throw e;
            }
          }
        }
      } else {
        errorInfo = " (got " + i(err) + ")";
      }
    }

    this.params = { operator: 'to throw exception' + errorInfo };

    this.assert(thrown);
    this.assert(errorMatched);
  });

  Assertion.alias('throw', 'throwError');
};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util');
var eql = require('should-equal');

module.exports = function(should, Assertion) {
  var i = should.format;

  /**
   * Asserts if given object match `other` object, using some assumptions:
   * First object matched if they are equal,
   * If `other` is a regexp and given object is a string check on matching with regexp
   * If `other` is a regexp and given object is an array check if all elements matched regexp
   * If `other` is a regexp and given object is an object check values on matching regexp
   * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
   * If `other` is an object check if the same keys matched with above rules
   * All other cases failed.
   *
   * Usually it is right idea to add pre type assertions, like `.String()` or `.Object()` to be sure assertions will do what you are expecting.
   * Object iteration happen by keys (properties with enumerable: true), thus some objects can cause small pain. Typical example is js
   * Error - it by default has 2 properties `name` and `message`, but they both non-enumerable. In this case make sure you specify checking props (see examples).
   *
   * @name match
   * @memberOf Assertion
   * @category assertion matching
   * @param {*} other Object to match
   * @param {string} [description] Optional message
   * @example
   * 'foobar'.should.match(/^foo/);
   * 'foobar'.should.not.match(/^bar/);
   *
   * ({ a: 'foo', c: 'barfoo' }).should.match(/foo$/);
   *
   * ['a', 'b', 'c'].should.match(/[a-z]/);
   *
   * (5).should.not.match(function(n) {
   *   return n < 0;
   * });
   * (5).should.not.match(function(it) {
   *    it.should.be.an.Array();
   * });
   * ({ a: 10, b: 'abc', c: { d: 10 }, d: 0 }).should
   * .match({ a: 10, b: /c$/, c: function(it) {
   *    return it.should.have.property('d', 10);
   * }});
   *
   * [10, 'abc', { d: 10 }, 0].should
   * .match({ '0': 10, '1': /c$/, '2': function(it) {
   *    return it.should.have.property('d', 10);
   * }});
   *
   * var myString = 'abc';
   *
   * myString.should.be.a.String().and.match(/abc/);
   *
   * myString = {};
   *
   * myString.should.match(/abc/); //yes this will pass
   * //better to do
   * myString.should.be.an.Object().and.not.empty().and.match(/abc/);//fixed
   *
   * (new Error('boom')).should.match(/abc/);//passed because no keys
   * (new Error('boom')).should.not.match({ message: /abc/ });//check specified property
   */
  Assertion.add('match', function(other, description) {
    this.params = {operator: 'to match ' + i(other), message: description};

    if(!eql(this.obj, other).result) {
      if(other instanceof RegExp) { // something - regex

        if(typeof this.obj == 'string') {

          this.assert(other.exec(this.obj));
        } else if(util.isIndexable(this.obj)) {
          util.forEach(this.obj, function(item) {
            this.assert(other.exec(item));// should we try to convert to String and exec?
          }, this);
        } else if(null != this.obj && typeof this.obj == 'object') {

          var notMatchedProps = [], matchedProps = [];
          util.forEach(this.obj, function(value, name) {
            if(other.exec(value)) matchedProps.push(util.formatProp(name));
            else notMatchedProps.push(util.formatProp(name) + ' (' + i(value) + ')');
          }, this);

          if(notMatchedProps.length)
            this.params.operator += '\n    not matched properties: ' + notMatchedProps.join(', ');
          if(matchedProps.length)
            this.params.operator += '\n    matched properties: ' + matchedProps.join(', ');

          this.assert(notMatchedProps.length === 0);
        } // should we try to convert to String and exec?
      } else if(typeof other == 'function') {
        var res;

        res = other(this.obj);

        //if(res instanceof Assertion) {
        //  this.params.operator += '\n    ' + res.getMessage();
        //}

        //if we throw exception ok - it is used .should inside
        if(typeof res == 'boolean') {
          this.assert(res); // if it is just boolean function assert on it
        }
      } else if(other != null && this.obj != null && typeof other == 'object') { // try to match properties (for Object and Array)
        notMatchedProps = [];
        matchedProps = [];

        util.forEach(other, function(value, key) {
          try {
            should(this.obj).have.property(key).which.match(value);
            matchedProps.push(util.formatProp(key));
          } catch(e) {
            if(e instanceof should.AssertionError) {
              notMatchedProps.push(util.formatProp(key) + ' (' + i(this.obj[key]) + ')');
            } else {
              throw e;
            }
          }
        }, this);

        if(notMatchedProps.length)
          this.params.operator += '\n    not matched properties: ' + notMatchedProps.join(', ');
        if(matchedProps.length)
          this.params.operator += '\n    matched properties: ' + matchedProps.join(', ');

        this.assert(notMatchedProps.length === 0);
      } else {
        this.assert(false);
      }
    }
  });

  /**
   * Asserts if given object values or array elements all match `other` object, using some assumptions:
   * First object matched if they are equal,
   * If `other` is a regexp - matching with regexp
   * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
   * All other cases check if this `other` equal to each element
   *
   * @name matchEach
   * @memberOf Assertion
   * @category assertion matching
   * @alias Assertion#matchSome
   * @param {*} other Object to match
   * @param {string} [description] Optional message
   * @example
   * [ 'a', 'b', 'c'].should.matchEach(/\w+/);
   * [ 'a', 'a', 'a'].should.matchEach('a');
   *
   * [ 'a', 'a', 'a'].should.matchEach(function(value) { value.should.be.eql('a') });
   *
   * { a: 'a', b: 'a', c: 'a' }.should.matchEach(function(value) { value.should.be.eql('a') });
   */
  Assertion.add('matchEach', function(other, description) {
    this.params = {operator: 'to match each ' + i(other), message: description};

    util.forEach(this.obj, function(value) {
      should(value).match(other);
    }, this);
  });

  /**
  * Asserts if any of given object values or array elements match `other` object, using some assumptions:
  * First object matched if they are equal,
  * If `other` is a regexp - matching with regexp
  * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
  * All other cases check if this `other` equal to each element
  *
  * @name matchAny
  * @memberOf Assertion
  * @category assertion matching
  * @param {*} other Object to match
  * @alias Assertion#matchEvery
  * @param {string} [description] Optional message
  * @example
  * [ 'a', 'b', 'c'].should.matchAny(/\w+/);
  * [ 'a', 'b', 'c'].should.matchAny('a');
  *
  * [ 'a', 'b', 'c'].should.matchAny(function(value) { value.should.be.eql('a') });
  *
  * { a: 'a', b: 'b', c: 'c' }.should.matchAny(function(value) { value.should.be.eql('a') });
  */
  Assertion.add('matchAny', function(other, description) {
    this.params = {operator: 'to match any ' + i(other), message: description};

    this.assert(util.some(this.obj, function(value) {
      try {
        should(value).match(other);
        return true;
      } catch(e) {
        if(e instanceof should.AssertionError) {
          // Caught an AssertionError, return false to the iterator
          return false;
        }
        throw e;
      }
    }));
  });

  Assertion.alias('matchAny', 'matchSome');
  Assertion.alias('matchEach', 'matchEvery');
};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

module.exports = function(should, Assertion) {

  /**
   * Assert given object is NaN
   * @name NaN
   * @memberOf Assertion
   * @category assertion numbers
   * @example
   *
   * (10).should.not.be.NaN();
   * NaN.should.be.NaN();
   */
  Assertion.add('NaN', function() {
    this.params = { operator: 'to be NaN' };

    this.assert(this.obj !== this.obj);
  });

  /**
   * Assert given object is not finite (positive or negative)
   *
   * @name Infinity
   * @memberOf Assertion
   * @category assertion numbers
   * @example
   *
   * (10).should.not.be.Infinity();
   * NaN.should.not.be.Infinity();
   */
  Assertion.add('Infinity', function() {
    this.params = { operator: 'to be Infinity' };

    this.is.a.Number()
      .and.not.a.NaN()
      .and.assert(!isFinite(this.obj));
  });

  /**
   * Assert given number between `start` and `finish` or equal one of them.
   *
   * @name within
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} start Start number
   * @param {number} finish Finish number
   * @param {string} [description] Optional message
   * @example
   *
   * (10).should.be.within(0, 20);
   */
  Assertion.add('within', function(start, finish, description) {
    this.params = { operator: 'to be within ' + start + '..' + finish, message: description };

    this.assert(this.obj >= start && this.obj <= finish);
  });

  /**
   * Assert given number near some other `value` within `delta`
   *
   * @name approximately
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} value Center number
   * @param {number} delta Radius
   * @param {string} [description] Optional message
   * @example
   *
   * (9.99).should.be.approximately(10, 0.1);
   */
  Assertion.add('approximately', function(value, delta, description) {
    this.params = { operator: 'to be approximately ' + value + ' ±' + delta, message: description };

    this.assert(Math.abs(this.obj - value) <= delta);
  });

  /**
   * Assert given number above `n`.
   *
   * @name above
   * @alias Assertion#greaterThan
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} n Margin number
   * @param {string} [description] Optional message
   * @example
   *
   * (10).should.be.above(0);
   */
  Assertion.add('above', function(n, description) {
    this.params = { operator: 'to be above ' + n, message: description };

    this.assert(this.obj > n);
  });

  /**
   * Assert given number below `n`.
   *
   * @name below
   * @alias Assertion#lessThan
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} n Margin number
   * @param {string} [description] Optional message
   * @example
   *
   * (0).should.be.below(10);
   */
  Assertion.add('below', function(n, description) {
    this.params = { operator: 'to be below ' + n, message: description };

    this.assert(this.obj < n);
  });

  Assertion.alias('above', 'greaterThan');
  Assertion.alias('below', 'lessThan');

  /**
   * Assert given number above `n`.
   *
   * @name aboveOrEqual
   * @alias Assertion#greaterThanOrEqual
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} n Margin number
   * @param {string} [description] Optional message
   * @example
   *
   * (10).should.be.aboveOrEqual(0);
   * (10).should.be.aboveOrEqual(10);
   */
  Assertion.add('aboveOrEqual', function(n, description) {
    this.params = { operator: 'to be above or equal' + n, message: description };

    this.assert(this.obj >= n);
  });

  /**
   * Assert given number below `n`.
   *
   * @name belowOrEqual
   * @alias Assertion#lessThanOrEqual
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} n Margin number
   * @param {string} [description] Optional message
   * @example
   *
   * (0).should.be.belowOrEqual(10);
   * (0).should.be.belowOrEqual(0);
   */
  Assertion.add('belowOrEqual', function(n, description) {
    this.params = { operator: 'to be below or equal' + n, message: description };

    this.assert(this.obj <= n);
  });

  Assertion.alias('aboveOrEqual', 'greaterThanOrEqual');
  Assertion.alias('belowOrEqual', 'lessThanOrEqual');

};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util');
var PromisedAssertion = require('../assertion').PromisedAssertion;
var Assertion = require('../assertion');

module.exports = function(should) {
  /**
   * Assert given object is a Promise
   *
   * @name Promise
   * @memberOf Assertion
   * @category assertion promises
   * @example
   *
   * promise.should.be.Promise()
   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.a.Promise()
   * (10).should.not.be.a.Promise()
   */
  Assertion.add('Promise', function() {
    this.params = {operator: 'to be promise'};

    var obj = this.obj;

    should(obj).have.property('then')
      .which.is.a.Function();
  });

  /**
   * Assert given promise will be fulfilled
   *
   * @name fulfilled
   * @memberOf Assertion
   * @returns {Promise}
   * @category assertion promises
   * @example
   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.fulfilled()
   */
  Assertion.prototype.fulfilled = function Assertion$fulfilled() {
    this.params = {operator: 'to be fulfilled'};

    should(this.obj).be.a.Promise();

    var that = this;
    return this.obj.then(function next$onResolve(value) {
      if (that.negate) {
        that.fail();
      }
      return value;
    }, function next$onReject(err) {
      if (!that.negate) {
        that.fail();
      }
      return err;
    });
  };

  /**
   * Assert given promise will be rejected
   *
   * @name rejected
   * @memberOf Assertion
   * @category assertion promises
   * @returns {Promise}
   * @example
   * (new Promise(function(resolve, reject) { resolve(10); })).should.not.be.rejected()
   */
  Assertion.prototype.rejected = function() {
    this.params = {operator: 'to be rejected'};

    should(this.obj).be.a.Promise();

    var that = this;
    return this.obj.then(function(value) {
      if (!that.negate) {
        that.fail();
      }
      return value;
    }, function next$onError(err) {
      if (that.negate) {
        that.fail();
      }
      return err;
    });
  };

  /**
   * Assert given promise will be fulfilled with some expected value.
   *
   * @name fulfilledWith
   * @memberOf Assertion
   * @category assertion promises
   * @returns {Promise}
   * @example
   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.fulfilledWith(10)
   */
  Assertion.prototype.fulfilledWith = function(expectedValue) {
    this.params = {operator: 'to be fulfilled'};

    should(this.obj).be.a.Promise();

    var that = this;
    return this.obj.then(function(value) {
      if (that.negate) {
        that.fail();
      }
      should(value).eql(expectedValue);
      return value;
    }, function next$onError(err) {
      if (!that.negate) {
        that.fail();
      }
      return err;
    });
  };

  /**
   * Assert given promise will be rejected with some sort of error. Arguments is the same for Assertion#throw
   *
   * @name rejectedWith
   * @memberOf Assertion
   * @category assertion promises
   * @returns {Promise}
   * @example
   *
   * function failedPromise() {
  *   return new Promise(function(resolve, reject) {
  *     reject(new Error('boom'))
  *   })
  * }
   * failedPromise().should.be.rejectedWith(Error)
   * failedPromise().should.be.rejectedWith('boom')
   * failedPromise().should.be.rejectedWith(/boom/)
   * failedPromise().should.be.rejectedWith(Error, { message: 'boom' })
   * failedPromise().should.be.rejectedWith({ message: 'boom' })
   */
  Assertion.prototype.rejectedWith = function(message, properties) {
    this.params = {operator: 'to be rejected'};

    should(this.obj).be.a.Promise();

    var that = this;
    return this.obj.then(function(value) {
      if (!that.negate) {
        that.fail();
      }
      return value;
    }, function next$onError(err) {
      if (that.negate) {
        that.fail();
      }

      var errorMatched = true;
      var errorInfo = '';

      if ('string' === typeof message) {
        errorMatched = message === err.message;
      } else if (message instanceof RegExp) {
        errorMatched = message.test(err.message);
      } else if ('function' === typeof message) {
        errorMatched = err instanceof message;
      } else if (message !== null && typeof message === 'object') {
        try {
          should(err).match(message);
        } catch (e) {
          if (e instanceof should.AssertionError) {
            errorInfo = ': ' + e.message;
            errorMatched = false;
          } else {
            throw e;
          }
        }
      }

      if (!errorMatched) {
        if ( typeof message === 'string' || message instanceof RegExp) {
          errorInfo = ' with a message matching ' + should.format(message) + ", but got '" + err.message + "'";
        } else if ('function' === typeof message) {
          errorInfo = ' of type ' + util.functionName(message) + ', but got ' + util.functionName(err.constructor);
        }
      } else if ('function' === typeof message && properties) {
        try {
          should(err).match(properties);
        } catch (e) {
          if (e instanceof should.AssertionError) {
            errorInfo = ': ' + e.message;
            errorMatched = false;
          } else {
            throw e;
          }
        }
      }

      that.params.operator += errorInfo;

      that.assert(errorMatched);

      return err;
    });
  };

  /**
   * Assert given object is promise and wrap it in PromisedAssertion, which has all properties of Assertion. That means you can chain as with usual Assertion.
   *
   * @name finally
   * @memberOf Assertion
   * @alias Assertion#eventually
   * @category assertion promises
   * @returns {PromisedAssertion} Like Assertion, but .then this.obj in Assertion
   * @example
   *
   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.eventually.equal(10)
   */
  Object.defineProperty(Assertion.prototype, 'finally', {
    get: function() {
      should(this.obj).be.a.Promise();

      var that = this;

      return new PromisedAssertion(this.obj.then(function(obj) {
        var a = should(obj);

        a.negate = that.negate;
        a.anyOne = that.anyOne;

        return a;
      }));
    }
  });

  Assertion.alias('finally', 'eventually');
};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util');
var eql = require('should-equal');

var aSlice = Array.prototype.slice;

module.exports = function(should, Assertion) {
  var i = should.format;
  /**
   * Asserts given object has some descriptor. **On success it change given object to be value of property**.
   *
   * @name propertyWithDescriptor
   * @memberOf Assertion
   * @category assertion property
   * @param {string} name Name of property
   * @param {Object} desc Descriptor like used in Object.defineProperty (not required to add all properties)
   * @example
   *
   * ({ a: 10 }).should.have.propertyWithDescriptor('a', { enumerable: true });
   */
  Assertion.add('propertyWithDescriptor', function(name, desc) {
    this.params = {actual: this.obj, operator: 'to have own property with descriptor ' + i(desc)};
    var obj = this.obj;
    this.have.ownProperty(name);
    should(Object.getOwnPropertyDescriptor(Object(obj), name)).have.properties(desc);
  });

  function processPropsArgs() {
    var args = {};
    if(arguments.length > 1) {
      args.names = aSlice.call(arguments);
    } else {
      var arg = arguments[0];
      if(typeof arg === 'string') {
        args.names = [arg];
      } else if(util.isIndexable(arg)) {
        args.names = arg;
      } else {
        args.names = Object.keys(arg);
        args.values = arg;
      }
    }
    return args;
  }


  /**
   * Asserts given object has enumerable property with optionally value. **On success it change given object to be value of property**.
   *
   * @name enumerable
   * @memberOf Assertion
   * @category assertion property
   * @param {string} name Name of property
   * @param {*} [val] Optional property value to check
   * @example
   *
   * ({ a: 10 }).should.have.enumerable('a');
   */
  Assertion.add('enumerable', function(name, val) {
    name = util.convertPropertyName(name);

    this.params = {
      operator: "to have enumerable property " + util.formatProp(name) + (arguments.length > 1 ? " equal to " + i(val): "")
    };

    var desc = { enumerable: true };
    if(arguments.length > 1) desc.value = val;
    this.have.propertyWithDescriptor(name, desc);
  });

  /**
   * Asserts given object has enumerable properties
   *
   * @name enumerables
   * @memberOf Assertion
   * @category assertion property
   * @param {Array|...string|Object} names Names of property
   * @example
   *
   * ({ a: 10, b: 10 }).should.have.enumerables('a');
   */
  Assertion.add('enumerables', function(names) {
    var args = processPropsArgs.apply(null, arguments);

    this.params = {
      operator: "to have enumerables " + args.names.map(util.formatProp)
    };

    var obj = this.obj;
    args.names.forEach(function(name) {
      should(obj).have.enumerable(name);
    });
  });

  /**
   * Asserts given object has property with optionally value. **On success it change given object to be value of property**.
   *
   * @name property
   * @memberOf Assertion
   * @category assertion property
   * @param {string} name Name of property
   * @param {*} [val] Optional property value to check
   * @example
   *
   * ({ a: 10 }).should.have.property('a');
   */
  Assertion.add('property', function(name, val) {
    name = util.convertPropertyName(name);
    if(arguments.length > 1) {
      var p = {};
      p[name] = val;
      this.have.properties(p);
    } else {
      this.have.properties(name);
    }
    this.obj = this.obj[name];
  });

  /**
   * Asserts given object has properties. On this method affect .any modifier, which allow to check not all properties.
   *
   * @name properties
   * @memberOf Assertion
   * @category assertion property
   * @param {Array|...string|Object} names Names of property
   * @example
   *
   * ({ a: 10 }).should.have.properties('a');
   * ({ a: 10, b: 20 }).should.have.properties([ 'a' ]);
   * ({ a: 10, b: 20 }).should.have.properties({ b: 20 });
   */
  Assertion.add('properties', function(names) {
    var values = {};
    if(arguments.length > 1) {
      names = aSlice.call(arguments);
    } else if(!Array.isArray(names)) {
      if(typeof names == 'string' || typeof names == 'symbol') {
        names = [names];
      } else {
        values = names;
        names = Object.keys(names);
      }
    }

    var obj = Object(this.obj), missingProperties = [];

    //just enumerate properties and check if they all present
    names.forEach(function(name) {
      if(!(name in obj)) missingProperties.push(util.formatProp(name));
    });

    var props = missingProperties;
    if(props.length === 0) {
      props = names.map(util.formatProp);
    } else if(this.anyOne) {
      props = names.filter(function(name) {
        return missingProperties.indexOf(util.formatProp(name)) < 0;
      }).map(util.formatProp);
    }

    var operator = (props.length === 1 ?
        'to have property ' : 'to have ' + (this.anyOne ? 'any of ' : '') + 'properties ') + props.join(', ');

    this.params = {obj: this.obj, operator: operator};

    //check that all properties presented
    //or if we request one of them that at least one them presented
    this.assert(missingProperties.length === 0 || (this.anyOne && missingProperties.length != names.length));

    // check if values in object matched expected
    var valueCheckNames = Object.keys(values);
    if(valueCheckNames.length) {
      var wrongValues = [];
      props = [];

      // now check values, as there we have all properties
      valueCheckNames.forEach(function(name) {
        var value = values[name];
        if(!eql(obj[name], value).result) {
          wrongValues.push(util.formatProp(name) + ' of ' + i(value) + ' (got ' + i(obj[name]) + ')');
        } else {
          props.push(util.formatProp(name) + ' of ' + i(value));
        }
      });

      if((wrongValues.length !== 0 && !this.anyOne) || (this.anyOne && props.length === 0)) {
        props = wrongValues;
      }

      operator = (props.length === 1 ?
        'to have property ' : 'to have ' + (this.anyOne ? 'any of ' : '') + 'properties ') + props.join(', ');

      this.params = {obj: this.obj, operator: operator};

      //if there is no not matched values
      //or there is at least one matched
      this.assert(wrongValues.length === 0 || (this.anyOne && wrongValues.length != valueCheckNames.length));
    }
  });

  /**
   * Asserts given object has property `length` with given value `n`
   *
   * @name length
   * @alias Assertion#lengthOf
   * @memberOf Assertion
   * @category assertion property
   * @param {number} n Expected length
   * @param {string} [description] Optional message
   * @example
   *
   * [1, 2].should.have.length(2);
   */
  Assertion.add('length', function(n, description) {
    this.have.property('length', n, description);
  });

  Assertion.alias('length', 'lengthOf');

  var hasOwnProperty = Object.prototype.hasOwnProperty;

  /**
   * Asserts given object has own property. **On success it change given object to be value of property**.
   *
   * @name ownProperty
   * @alias Assertion#hasOwnProperty
   * @memberOf Assertion
   * @category assertion property
   * @param {string} name Name of property
   * @param {string} [description] Optional message
   * @example
   *
   * ({ a: 10 }).should.have.ownProperty('a');
   */
  Assertion.add('ownProperty', function(name, description) {
    name = util.convertPropertyName(name);
    this.params = {
      actual: this.obj,
      operator: 'to have own property ' + util.formatProp(name),
      message: description
    };

    this.assert(hasOwnProperty.call(this.obj, name));

    this.obj = this.obj[name];
  });

  Assertion.alias('ownProperty', 'hasOwnProperty');

  /**
   * Asserts given object is empty. For strings, arrays and arguments it checks .length property, for objects it checks keys.
   *
   * @name empty
   * @memberOf Assertion
   * @category assertion property
   * @example
   *
   * ''.should.be.empty();
   * [].should.be.empty();
   * ({}).should.be.empty();
   */
  Assertion.add('empty', function() {
    this.params = {operator: 'to be empty'};

    if(util.length(this.obj) !== void 0) {
      should(this.obj).have.property('length', 0);
    } else {
      var obj = Object(this.obj); // wrap to reference for booleans and numbers
      for(var prop in obj) {
        should(this.obj).not.have.ownProperty(prop);
      }
    }
  }, true);

  /**
   * Asserts given object has exact keys. Compared to `properties`, `keys` does not accept Object as a argument.
   *
   * @name keys
   * @alias Assertion#key
   * @memberOf Assertion
   * @category assertion property
   * @param {Array|...string} [keys] Keys to check
   * @example
   *
   * ({ a: 10 }).should.have.keys('a');
   * ({ a: 10, b: 20 }).should.have.keys('a', 'b');
   * ({ a: 10, b: 20 }).should.have.keys([ 'a', 'b' ]);
   * ({}).should.have.keys();
   */
  Assertion.add('keys', function(keys) {
    if(arguments.length > 1) keys = aSlice.call(arguments);
    else if(arguments.length === 1 && typeof keys === 'string') keys = [keys];
    else if(arguments.length === 0) keys = [];

    keys = keys.map(String);

    var obj = Object(this.obj);

    // first check if some keys are missing
    var missingKeys = [];
    keys.forEach(function(key) {
      if(!hasOwnProperty.call(this.obj, key))
        missingKeys.push(util.formatProp(key));
    }, this);

    // second check for extra keys
    var extraKeys = [];
    Object.keys(obj).forEach(function(key) {
      if(keys.indexOf(key) < 0) {
        extraKeys.push(util.formatProp(key));
      }
    });

    var verb = keys.length === 0 ? 'to be empty' :
    'to have ' + (keys.length === 1 ? 'key ' : 'keys ');

    this.params = {operator: verb + keys.map(util.formatProp).join(', ')};

    if(missingKeys.length > 0)
      this.params.operator += '\n\tmissing keys: ' + missingKeys.join(', ');

    if(extraKeys.length > 0)
      this.params.operator += '\n\textra keys: ' + extraKeys.join(', ');

    this.assert(missingKeys.length === 0 && extraKeys.length === 0);
  });

  Assertion.alias("keys", "key");

  /**
   * Asserts given object has nested property in depth by path. **On success it change given object to be value of final property**.
   *
   * @name propertyByPath
   * @memberOf Assertion
   * @category assertion property
   * @param {Array|...string} properties Properties path to search
   * @example
   *
   * ({ a: {b: 10}}).should.have.propertyByPath('a', 'b').eql(10);
   */
  Assertion.add('propertyByPath', function(properties) {
    if(arguments.length > 1) properties = aSlice.call(arguments);
    else if(arguments.length === 1 && typeof properties == 'string') properties = [properties];
    else if(arguments.length === 0) properties = [];

    var allProps = properties.map(util.formatProp);

    properties = properties.map(String);

    var obj = should(Object(this.obj));

    var foundProperties = [];

    var currentProperty;
    while(currentProperty = properties.shift()) {
      this.params = {operator: 'to have property by path ' + allProps.join(', ') + ' - failed on ' + util.formatProp(currentProperty)};
      obj = obj.have.property(currentProperty);
      foundProperties.push(currentProperty);
    }

    this.params = {obj: this.obj, operator: 'to have property by path ' + allProps.join(', ')};

    this.obj = obj.obj;
  });
};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

module.exports = function(should, Assertion) {
  /**
   * Assert given string starts with prefix
   * @name startWith
   * @memberOf Assertion
   * @category assertion strings
   * @param {string} str Prefix
   * @param {string} [description] Optional message
   * @example
   *
   * 'abc'.should.startWith('a');
   */
  Assertion.add('startWith', function(str, description) {
    this.params = { operator: 'to start with ' + should.format(str), message: description };

    this.assert(0 === this.obj.indexOf(str));
  });

  /**
   * Assert given string starts with prefix
   * @name endWith
   * @memberOf Assertion
   * @category assertion strings
   * @param {string} str Prefix
   * @param {string} [description] Optional message
   * @example
   *
   * 'abca'.should.endWith('a');
   */
  Assertion.add('endWith', function(str, description) {
    this.params = { operator: 'to end with ' + should.format(str), message: description };

    this.assert(this.obj.indexOf(str, this.obj.length - str.length) >= 0);
  });
};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util');

module.exports = function(should, Assertion) {
  /**
   * Assert given object is number
   * @name Number
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Number', function() {
    this.params = {operator: 'to be a number'};

    this.have.type('number');
  });

  /**
   * Assert given object is arguments
   * @name arguments
   * @alias Assertion#Arguments
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('arguments', function() {
    this.params = {operator: 'to be arguments'};

    this.have.class('Arguments');
  });

  Assertion.alias('arguments', 'Arguments');

  /**
   * Assert given object has some type using `typeof`
   * @name type
   * @memberOf Assertion
   * @param {string} type Type name
   * @param {string} [description] Optional message
   * @category assertion types
   */
  Assertion.add('type', function(type, description) {
    this.params = {operator: 'to have type ' + type, message: description};

    should(typeof this.obj).be.exactly(type);
  });

  /**
   * Assert given object is instance of `constructor`
   * @name instanceof
   * @alias Assertion#instanceOf
   * @memberOf Assertion
   * @param {Function} constructor Constructor function
   * @param {string} [description] Optional message
   * @category assertion types
   */
  Assertion.add('instanceof', function(constructor, description) {
    this.params = {operator: 'to be an instance of ' + util.functionName(constructor), message: description};

    this.assert(Object(this.obj) instanceof constructor);
  });

  Assertion.alias('instanceof', 'instanceOf');

  /**
   * Assert given object is function
   * @name Function
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Function', function() {
    this.params = {operator: 'to be a function'};

    this.have.type('function');
  });

  /**
   * Assert given object is object
   * @name Object
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Object', function() {
    this.params = {operator: 'to be an object'};

    this.is.not.null().and.have.type('object');
  });

  /**
   * Assert given object is string
   * @name String
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('String', function() {
    this.params = {operator: 'to be a string'};

    this.have.type('string');
  });

  /**
   * Assert given object is array
   * @name Array
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Array', function() {
    this.params = {operator: 'to be an array'};

    this.have.class('Array');
  });

  /**
   * Assert given object is boolean
   * @name Boolean
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Boolean', function() {
    this.params = {operator: 'to be a boolean'};

    this.have.type('boolean');
  });

  /**
   * Assert given object is error
   * @name Error
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Error', function() {
    this.params = {operator: 'to be an error'};

    this.have.instanceOf(Error);
  });

  /**
   * Assert given object is null
   * @name null
   * @alias Assertion#Null
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('null', function() {
    this.params = {operator: 'to be null'};

    this.assert(this.obj === null);
  });

  Assertion.alias('null', 'Null');

  /**
   * Assert given object has some internal [[Class]], via Object.prototype.toString call
   * @name class
   * @alias Assertion#Class
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('class', function(cls) {
    this.params = {operator: 'to have [[Class]] ' + cls};

    this.assert(Object.prototype.toString.call(this.obj) === '[object ' + cls + ']');
  });

  Assertion.alias('class', 'Class');

  /**
   * Assert given object is undefined
   * @name undefined
   * @alias Assertion#Undefined
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('undefined', function() {
    this.params = {operator: 'to be undefined'};

    this.assert(this.obj === void 0);
  });

  Assertion.alias('undefined', 'Undefined');

  /**
   * Assert given object supports es6 iterable protocol (just check
   * that object has property Symbol.iterator, which is a function)
   * @name iterable
   * @memberOf Assertion
   * @category assertion es6
   */
  Assertion.add('iterable', function() {
    this.params = {operator: 'to be iterable'};

    should(this.obj).have.property(Symbol.iterator).which.is.a.Function();
  });

  /**
   * Assert given object supports es6 iterator protocol (just check
   * that object has property next, which is a function)
   * @name iterator
   * @memberOf Assertion
   * @category assertion es6
   */
  Assertion.add('iterator', function() {
    this.params = {operator: 'to be iterator'};

    should(this.obj).have.property('next').which.is.a.Function();
  });

  /**
   * Assert given object is a generator object
   * @name generator
   * @memberOf Assertion
   * @category assertion es6
   */
  Assertion.add('generator', function() {
    this.params = {operator: 'to be generator'};

    should(this.obj).be.iterable
      .and.iterator
      .and.it.is.equal(this.obj[Symbol.iterator]());
  });
};
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */


var util = require('./util');

/**
 * Our function should
 *
 * @param {*} obj Object to assert
 * @returns {should.Assertion} Returns new Assertion for beginning assertion chain
 * @example
 *
 * var should = require('should');
 * should('abc').be.a.String();
 */
function should(obj) {
  return (new should.Assertion(obj));
}

should.AssertionError = require('./assertion-error');
should.Assertion = require('./assertion');

should.format = util.format;
should.type = require('should-type');
should.util = util;

/**
 * Object with configuration.
 * It contains such properties:
 * * `checkProtoEql` boolean - Affect if `.eql` will check objects prototypes
 * Also it can contain options for should-format.
 *
 * @type {Object}
 * @memberOf should
 * @static
 * @example
 *
 * var a = { a: 10 }, b = Object.create(null);
 * b.a = 10;
 *
 * a.should.be.eql(b);
 * //not throws
 *
 * should.config.checkProtoEql = true;
 * a.should.be.eql(b);
 * //throws AssertionError: expected { a: 10 } to equal { a: 10 } (because A and B have different prototypes)
 */
should.config = require('./config');

// Expose should to external world.
exports = module.exports = should;

/**
 * Allow to extend given prototype with should property using given name. This getter will **unwrap** all standard wrappers like `Number`, `Boolean`, `String`.
 * Using `should(obj)` is the equivalent of using `obj.should` with known issues (like nulls and method calls etc).
 *
 * @param {string} [propertyName] Name of property to add. Default is `'should'`.
 * @param {Object} [proto] Prototype to extend with. Default is `Object.prototype`.
 * @memberOf should
 * @returns {{ name: string, descriptor: Object, proto: Object }} Descriptor enough to return all back
 * @static
 * @example
 *
 * var prev = should.extend('must', Object.prototype);
 *
 * 'abc'.must.startWith('a');
 *
 * var should = should.noConflict(prev);
 * should.not.exist(Object.prototype.must);
 */
should.extend = function(propertyName, proto) {
  propertyName = propertyName || 'should';
  proto = proto || Object.prototype;

  var prevDescriptor = Object.getOwnPropertyDescriptor(proto, propertyName);

  Object.defineProperty(proto, propertyName, {
    set: function() {
    },
    get: function() {
      return should(util.isWrapperType(this) ? this.valueOf() : this);
    },
    configurable: true
  });

  return { name: propertyName, descriptor: prevDescriptor, proto: proto };
};

/**
 * Delete previous extension. If `desc` missing it will remove default extension.
 *
 * @param {{ name: string, descriptor: Object, proto: Object }} [desc] Returned from `should.extend` object
 * @memberOf should
 * @returns {Function} Returns should function
 * @static
 * @example
 *
 * var should = require('should').noConflict();
 *
 * should(Object.prototype).not.have.property('should');
 *
 * var prev = should.extend('must', Object.prototype);
 * 'abc'.must.startWith('a');
 * should.noConflict(prev);
 *
 * should(Object.prototype).not.have.property('must');
 */
should.noConflict = function(desc) {
  desc = desc || should._prevShould;

  if(desc) {
    delete desc.proto[desc.name];

    if(desc.descriptor) {
      Object.defineProperty(desc.proto, desc.name, desc.descriptor);
    }
  }
  return should;
};

/**
 * Simple utility function for a bit more easier should assertion extension
 * @param {Function} f So called plugin function. It should accept 2 arguments: `should` function and `Assertion` constructor
 * @memberOf should
 * @returns {Function} Returns `should` function
 * @static
 * @example
 *
 * should.use(function(should, Assertion) {
 *   Assertion.add('asset', function() {
 *      this.params = { operator: 'to be asset' };
 *
 *      this.obj.should.have.property('id').which.is.a.Number();
 *      this.obj.should.have.property('path');
 *  })
 * })
 */
should.use = function(f) {
  f(should, should.Assertion);
  return this;
};

should
  .use(require('./ext/assert'))
  .use(require('./ext/chain'))
  .use(require('./ext/bool'))
  .use(require('./ext/number'))
  .use(require('./ext/eql'))
  .use(require('./ext/type'))
  .use(require('./ext/string'))
  .use(require('./ext/property'))
  .use(require('./ext/error'))
  .use(require('./ext/match'))
  .use(require('./ext/contain'))
  .use(require('./ext/promise'));
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var type = require('should-type');
var config = require('./config');

/**
 * Check if given obj just a primitive type wrapper
 * @param {Object} obj
 * @returns {boolean}
 * @private
 */
exports.isWrapperType = function(obj) {
  return obj instanceof Number || obj instanceof String || obj instanceof Boolean;
};

exports.merge = function(a, b) {
  if(a && b) {
    for(var key in b) {
      a[key] = b[key];
    }
  }
  return a;
};

var hasOwnProperty = Object.prototype.hasOwnProperty;

exports.forEach = function forEach(obj, f, context) {
  if(exports.isGeneratorFunction(obj)) {
    return forEach(obj(), f, context);
  } else if (exports.isGeneratorObject(obj)) {
    var value = obj.next();
    while(!value.done) {
      if(f.call(context, value.value, 'value', obj) === false)
        return;
      value = obj.next();
    }
  } else {
    for(var prop in obj) {
      if(hasOwnProperty.call(obj, prop)) {
        if(f.call(context, obj[prop], prop, obj) === false)
          return;
      }
    }
  }
};

exports.some = function(obj, f, context) {
  var res = false;
  exports.forEach(obj, function(value, key) {
    if(f.call(context, value, key, obj)) {
      res = true;
      return false;
    }
  }, context);
  return res;
};

exports.isEmptyObject = function(obj) {
  for(var prop in obj) {
    if(hasOwnProperty.call(obj, prop)) {
      return false;
    }
  }
  return true;
};

exports.isIndexable = function(obj) {
  var t = type(obj);
  return (t.type === type.OBJECT && t.cls === type.ARRAY) ||
   (t.type === type.OBJECT && t.cls === type.BUFFER) ||
   (t.type === type.OBJECT && t.cls === type.ARGUMENTS) ||
   (t.type === type.OBJECT && t.cls === type.ARRAY_BUFFER) ||
   (t.type === type.OBJECT && t.cls === type.TYPED_ARRAY) ||
   (t.type === type.OBJECT && t.cls === type.DATA_VIEW) ||
   (t.type === type.OBJECT && t.cls === type.STRING) ||
   (t.type === type.STRING);
};

exports.length = function(obj) {
  var t = type(obj);
  switch(t.type) {
    case type.STRING:
      return obj.length;
    case type.OBJECT:
      switch(t.cls) {
        case type.ARRAY_BUFFER:
        case type.TYPED_ARRAY:
        case type.DATA_VIEW:
          return obj.byteLength;

        case type.ARRAY:
        case type.BUFFER:
        case type.ARGUMENTS:
        case type.FUNCTION:
          return obj.length;
      }
  }
};

exports.convertPropertyName = function(name) {
  if(typeof name == 'symbol') {
    return name;
  } else {
    return String(name);
  }
};

exports.isGeneratorObject = function(obj) {
  if(!obj) return false;

  return typeof obj.next == 'function' &&
          typeof obj[Symbol.iterator] == 'function' &&
          obj[Symbol.iterator]() === obj;
};

//TODO find better way
exports.isGeneratorFunction = function(f) {
  if(typeof f != 'function') return false;

  return /^function\s*\*\s*/.test(f.toString());
};

exports.format = function(value, opts) {
  return config.getFormatter(opts).format(value);
};

exports.functionName = require('should-format').Formatter.functionName;

exports.formatProp = function(value) {
  return config.getFormatter().formatPropertyName(String(value));
};
{
  "env": {
    "node": true,
    "browser": true
  },
  "rules": {
    "quotes": false,
    "strict": false,
    "curly": false,
    "eqeqeq": false
  }
}
.idea
language: node_js
node_js:
- '0.10'
- '0.11'
script:
- npm test
The MIT License (MIT)

Copyright (c) 2014 

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
equal
=====

[![Build Status](https://travis-ci.org/shouldjs/equal.svg?branch=master)](https://travis-ci.org/shouldjs/equal)

Deep equality comparison implementation for should.js

Function return an object that have result of comparison and description of fail:

```js
> var a = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10},
... b = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:7,i:9,j:10};
undefined
> eql(a, b);
{ result: false,
  path: [ 'h' ],
  reason: 'A and B are not equal',
  a: 8,
  b: 7 }
```
module.exports = function format(msg) {
  var args = arguments;
  for(var i = 1, l = args.length; i < l; i++) {
    msg = msg.replace(/%s/, args[i]);
  }
  return msg;
}
var getType = require('should-type');
var format = require('./format');
var hasOwnProperty = Object.prototype.hasOwnProperty;

function makeResult(r, path, reason, a, b) {
  var o = {result: r};
  if(!r) {
    o.path = path;
    o.reason = reason;
    o.a = a;
    o.b = b;
  }
  return o;
}

var EQUALS = makeResult(true);

function typeToString(t) {
  return t.type + (t.cls ? '(' + t.cls + (t.sub ? ' ' + t.sub : '') + ')' : '');
}



var REASON = {
  PLUS_0_AND_MINUS_0: '+0 is not equal to -0',
  DIFFERENT_TYPES: 'A has type %s and B has type %s',
  NAN_NUMBER: 'NaN is not equal to any number',
  EQUALITY: 'A is not equal to B',
  EQUALITY_PROTOTYPE: 'A and B have different prototypes',
  WRAPPED_VALUE: 'A wrapped value is not equal to B wrapped value',
  FUNCTION_SOURCES: 'function A is not equal to B by source code value (via .toString call)',
  MISSING_KEY: '%s has no key %s',
  CIRCULAR_VALUES: 'A has circular reference that was visited not in the same time as B',
  SET_MAP_MISSING_KEY: 'Set/Map missing key',
  MAP_VALUE_EQUALITY: 'Values of the same key in A and B is not equal'
};

function eqInternal(a, b, opts, stackA, stackB, path) {
  var r = EQUALS;

  function result(comparison, reason) {
    return makeResult(comparison, path, reason, a, b);
  }

  function checkPropertyEquality(property) {
    return eqInternal(a[property], b[property], opts, stackA, stackB, path.concat([property]));
  }


  // equal a and b exit early
  if(a === b) {
    // check for +0 !== -0;
    return result(a !== 0 || (1 / a == 1 / b), REASON.PLUS_0_AND_MINUS_0);
  }

  var l, p;

  var typeA = getType(a),
    typeB = getType(b);

  // if objects has different types they are not equals
  var typeDifferents = typeA.type !== typeB.type || typeA.cls !== typeB.cls;

  if(typeDifferents || ((opts.checkSubType && typeA.sub !== typeB.sub) || !opts.checkSubType)) {
    return result(false, format(REASON.DIFFERENT_TYPES, typeToString(typeA), typeToString(typeB)));
  }

  //early checks for types
  switch(typeA.type) {
    case 'number':
      // NaN !== NaN
      return (a !== a) ? result(b !== b, REASON.NAN_NUMBER)
        // but treat `+0` vs. `-0` as not equal
        : (a === 0 ? result(1 / a === 1 / b, REASON.PLUS_0_AND_MINUS_0) : result(a === b, REASON.EQUALITY));

    case 'boolean':
    case 'string':
      return result(a === b, REASON.EQUALITY);

    case 'function':
      var fA = a.toString(), fB = b.toString();
      r = eqInternal(fA, fB, opts, stackA, stackB, path);
      if(!r.result) {
        r.reason = REASON.FUNCTION_SOURCES;
        return r;
      }

      break;//check user properties

    case 'object':
      // additional checks for object instances
      switch(typeA.cls) {
        // check regexp flags
        // TODO add es6 flags
        case 'regexp':
          p = ['source', 'global', 'multiline', 'lastIndex', 'ignoreCase'];
          while(p.length) {
            r = checkPropertyEquality(p.shift());
            if(!r.result) return r;
          }
          break;//check user properties

        //check by timestamp only
        case 'date':
          if(+a !== +b) {
            return result(false, REASON.EQUALITY);
          }
          break;//check user properties

        //primitive type wrappers
        case 'number':
        case 'boolean':
        case 'string':
          r = eqInternal(a.valueOf(), b.valueOf(), opts, stackA, stackB, path);
          if(!r.result) {
            r.reason = REASON.WRAPPED_VALUE;
            return r;
          }
          break;//check user properties

        //node buffer
        case 'buffer':
          //if length different it is obviously different
          r = checkPropertyEquality('length');
          if(!r.result) return r;

          l = a.length;
          while(l--) {
            r = checkPropertyEquality(l);
            if(!r.result) return r;
          }

          //we do not check for user properties because
          //node Buffer have some strange hidden properties
          return EQUALS;

        case 'error':
          //check defined properties
          p = ['name', 'message'];
          while(p.length) {
            r = checkPropertyEquality(p.shift());
            if(!r.result) return r;
          }

          break;//check user properties

        case 'array':
        case 'arguments':
        case 'typed-array':
          r = checkPropertyEquality('length');
          if(!r.result) return r;

          break;//check user properties

        case 'array-buffer':
          r = checkPropertyEquality('byteLength');
          if(!r.result) return r;

          break;//check user properties

        case 'map':
        case 'set':
          r = checkPropertyEquality('size');
          if(!r.result) return r;

          stackA.push(a);
          stackB.push(b);

          var itA = a.entries();
          var nextA = itA.next();

          while(!nextA.done) {
            var key = nextA.value[0];
            //first check for primitive key if we can do light check
            //using .has and .get
            if(getType(key).type != 'object') {
              if(b.has(key)) {
                if(typeA.cls == 'map') {
                  //for map we also check its value to be equal
                  var value = b.get(key);
                  r = eqInternal(nextA.value[1], value, opts, stackA, stackB, path);
                  if(!r.result) {
                    r.a = nextA.value;
                    r.b = value;
                    r.reason = REASON.MAP_VALUE_EQUALITY;

                    break;
                  }
                }

              } else {
                r = result(false, REASON.SET_MAP_MISSING_KEY);
                r.a = key;
                r.b = key;

                break;
              }
            } else {
              //heavy check
              //we search by iterator for key equality using equal
              var itB = b.entries();
              var nextB = itB.next();

              while(!nextB.done) {
                //first check for keys
                r = eqInternal(nextA.value[0], nextB.value[0], opts, stackA, stackB, path);

                if(!r.result) {
                  r.reason = REASON.SET_MAP_MISSING_KEY;
                  r.a = key;
                  r.b = key;
                } else {
                  if(typeA.cls == 'map') {
                    r = eqInternal(nextA.value[1], nextB.value[1], opts, stackA, stackB, path);

                    if(!r.result) {
                      r.a = nextA.value;
                      r.b = nextB.value;
                      r.reason = REASON.MAP_VALUE_EQUALITY;
                    }
                  }

                  break;
                }

                nextB = itB.next();
              }
            }

            if(!r.result) {
              break;
            }

            nextA = itA.next();
          }

          stackA.pop();
          stackB.pop();

          if(!r.result) {
            r.reason = REASON.SET_MAP_MISSING_ENTRY;
            return r;
          }

          break; //check user properties
      }
  }

  // compare deep objects and arrays
  // stacks contain references only
  //

  l = stackA.length;
  while(l--) {
    if(stackA[l] == a) {
      return result(stackB[l] == b, REASON.CIRCULAR_VALUES);
    }
  }

  // add `a` and `b` to the stack of traversed objects
  stackA.push(a);
  stackB.push(b);

  var key;

  for(key in b) {
    if(hasOwnProperty.call(b, key)) {
      r = result(hasOwnProperty.call(a, key), format(REASON.MISSING_KEY, 'A', key));
      if(!r.result) {
        break;
      }

      if(r.result) {
        r = checkPropertyEquality(key);
        if(!r.result) {
          break;
        }
      }
    }
  }

  if(r.result) {
    // ensure both objects have the same number of properties
    for(key in a) {
      if(hasOwnProperty.call(a, key)) {
        r = result(hasOwnProperty.call(b, key), format(REASON.MISSING_KEY, 'B', key));
        if(!r.result) {
          return r;
        }
      }
    }
  }

  stackA.pop();
  stackB.pop();

  if(!r.result) return r;

  var prototypesEquals = false, canComparePrototypes = false;

  if(opts.checkProtoEql) {
    if(Object.getPrototypeOf) {//TODO should i check prototypes for === or use eq?
      prototypesEquals = Object.getPrototypeOf(a) === Object.getPrototypeOf(b);
      canComparePrototypes = true;
    } else if(a.__proto__ && b.__proto__) {
      prototypesEquals = a.__proto__ === b.__proto__;
      canComparePrototypes = true;
    }

    if(canComparePrototypes && !prototypesEquals) {
      r = result(prototypesEquals, REASON.EQUALITY_PROTOTYPE);
      r.showReason = true;
      if(!r.result) {
        return r;
      }
    }
  }

  return EQUALS;
}

var defaultOptions = {
  checkProtoEql: true,
  checkSubType: true
};

function eq(a, b, opts) {
  opts = opts || {};
  if(typeof opts.checkProtoEql !== 'boolean')
    opts.checkProtoEql = defaultOptions.checkProtoEql;
  if(typeof opts.checkSubType !== 'boolean')
    opts.checkSubType = defaultOptions.checkSubType;

  var r = eqInternal(a, b, opts, [], [], []);
  return r;
}

module.exports = eq;

eq.r = REASON;
{
  "name": "should-equal",
  "version": "0.5.0",
  "description": "Deep comparison of 2 instances for should.js",
  "main": "index.js",
  "scripts": {
    "test": "mocha --ui bdd -R mocha-better-spec-reporter test.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/shouldjs/equal.git"
  },
  "keywords": [
    "should.js",
    "deep",
    "equal"
  ],
  "author": {
    "name": "Denis Bardadym",
    "email": "bardadymchik@gmail.com"
  },
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/shouldjs/equal/issues"
  },
  "homepage": "https://github.com/shouldjs/equal",
  "devDependencies": {
    "mocha": "latest",
    "mocha-better-spec-reporter": "latest"
  },
  "dependencies": {
    "should-type": "0.2.0"
  },
  "gitHead": "d0b73b18fd4a799765de477165caf60fee1f9397",
  "_id": "should-equal@0.5.0",
  "_shasum": "c797f135f3067feb69ebecdb306b1c3fe21b3e6f",
  "_from": "should-equal@0.5.0",
  "_npmVersion": "2.11.1",
  "_nodeVersion": "2.3.0",
  "_npmUser": {
    "name": "btd",
    "email": "bardadymchik@gmail.com"
  },
  "maintainers": [
    {
      "name": "btd",
      "email": "bardadymchik@gmail.com"
    }
  ],
  "dist": {
    "shasum": "c797f135f3067feb69ebecdb306b1c3fe21b3e6f",
    "tarball": "http://registry.npmjs.org/should-equal/-/should-equal-0.5.0.tgz"
  },
  "directories": {},
  "_resolved": "https://registry.npmjs.org/should-equal/-/should-equal-0.5.0.tgz",
  "readme": "ERROR: No README data found!"
}
var assert = require('assert');
var equal = require('./index');

function eq(a, b) {
  var r = equal(a, b);
  var msg = !r.result && (r.reason + ' at ' + r.path + ' ' + r.a + ' =/= ' + r.b);
  if(!r.result) {
    assert.equal(a, b, msg);
  }

}

function ne(a, b) {
  var r = equal(a, b);
  assert.ok(!r.result);
}

/* 1. simple tests */

/* 1.1. positive */
it("NaN eqs NaN", function() {
  return eq(NaN, NaN);
});
it("finite integer n eqs n", function() {
  return eq(1234, 1234);
});
it("empty list eqs empty list", function() {
  return eq([], []);
});
it("empty obj eqs empty obj", function() {
  return eq({}, {});
});
it("number eqs number of same value", function() {
  return eq(123.45678, 123.45678);
});
it("regex lit's w same pattern, flags are eq", function() {
  return eq(/^abc[a-zA-Z]/, /^abc[a-zA-Z]/);
});
it("pods w same properties are eq", function() {
  return eq({
    a: 'b',
    c: 'd'
  }, {
    a: 'b',
    c: 'd'
  });
});
it("pods that only differ wrt prop ord are eq", function() {
  return eq({
    a: 'b',
    c: 'd'
  }, {
    c: 'd',
    a: 'b'
  });
});

/* 1.2. negative */
it("obj doesn't eq list", function() {
  return ne({}, []);
});
it("obj in a list doesn't eq list in list", function() {
  return ne([{}], [[]]);
});
it("integer n doesn't eq rpr n", function() {
  return ne(1234, '1234');
});
it("integer n doesn't eq n + 1", function() {
  return ne(1234, 1235);
});
it("empty list doesn't eq false", function() {
  return ne([], false);
});
it("list w an integer doesn't eq one w rpr n", function() {
  return ne([3], ['3']);
});
it("regex lit's w diff. patterns, same flags aren't eq", function() {
  return ne(/^abc[a-zA-Z]/, /^abc[a-zA-Z]x/);
});
it("regex lit's w same patterns, diff. flags aren't eq", function() {
  return ne(/^abc[a-zA-Z]/, /^abc[a-zA-Z]/i);
});
it("+0 should ne -0", function() {
  return ne(+0, -0);
});
it("number obj not eqs primitive number of same value", function() {
  return ne(5, new Number(5));
});
it("string obj not eqs primitive string of same value", function() {
  return ne('helo', new String('helo'));
});
it("(1) bool obj not eqs primitive bool of same value", function() {
  return ne(false, new Boolean(false));
});
it("(2) bool obj not eqs primitive bool of same value", function() {
  return ne(true, new Boolean(true));
});
it("number obj eqs the same valued number object", function() {
  return eq(new Number(5), new Number(5));
});

/* 2. complex tests */
it("obj w undef member not eqs other obj w/out same member", function() {
  var d, e;
  d = {
    x: void 0
  };
  e = {};
  return ne(d, e);
});
it("fn1: functions w same source are eq", function() {
  var d, e;
  d = function( a, b, c ){ return a * b * c; };
  e = function( a, b, c ){ return a * b * c; };
  return eq(d, e);
});
it("fn2: functions w diff source aren't eq", function() {
  var d, e;
  d = function( a, b, c ){ return a * b * c; };
  e = function( a, b, c ){ return a  *  b  *  c; };
  return ne(d, e);
});
it("fn3: equal functions w equal props are eq", function() {
  var d, e;
  d = function() {
    return null;
  };
  d.foo = {
    some: 'meaningless',
    properties: 'here'
  };
  e = function() {
    return null;
  };
  e.foo = {
    some: 'meaningless',
    properties: 'here'
  };
  return eq(d, e);
});
it("fn4: equal functions w unequal props aren't eq", function() {
  var d, e;
  d = function() {
    return null;
  };
  d.foo = {
    some: 'meaningless',
    properties: 'here'
  };
  e = function() {
    return null;
  };
  e.foo = {
    some: 'meaningless',
    properties: 'here!!!'
  };
  return ne(d, e);
});
it("list w named member eqs other list w same member", function() {
  var d, e;
  d = ['foo', null, 3];
  d['extra'] = 42;
  e = ['foo', null, 3];
  e['extra'] = 42;
  return eq(d, e);
});
it("list w named member doesn't eq list w same member, other value", function() {
  var d, e;
  d = ['foo', null, 3];
  d['extra'] = 42;
  e = ['foo', null, 3];
  e['extra'] = 108;
  return ne(d, e);
});
it("date eqs other date pointing to same time", function() {
  var d, e;
  d = new Date("1995-12-17T03:24:00");
  e = new Date("1995-12-17T03:24:00");
  return eq(d, e);
});
it("date does not eq other date pointing to other time", function() {
  var d, e;
  d = new Date("1995-12-17T03:24:00");
  e = new Date("1995-12-17T03:24:01");
  return ne(d, e);
});
it("str obj w props eq same str, same props", function() {
  var d, e;
  d = new String("helo test");
  d['abc'] = 42;
  e = new String("helo test");
  e['abc'] = 42;
  return eq(d, e);
});
it("str obj w props not eq same str, other props", function() {
  var d, e;
  d = new String("helo test");
  d['abc'] = 42;
  e = new String("helo test");
  e['def'] = 42;
  return ne(d, e);
});
it("str obj w props eq same str, same props (circ)", function() {
  var c, d, e;
  c = ['a list'];
  c.push(c);
  d = new String("helo test");
  d['abc'] = c;
  e = new String("helo test");
  e['abc'] = c;
  return eq(d, e);
});
it("str obj w props not eq same str, other props (circ)", function() {
  var c, d, e;
  c = ['a list'];
  c.push(c);
  d = new String("helo test");
  d['abc'] = c;
  e = new String("helo test");
  e['def'] = c;
  return ne(d, e);
});
/*it("(1) circ arrays w similar layout, same values aren't eq"] = function() {
  var d, e;
  d = [1, 2, 3];
  d.push(d);
  e = [1, 2, 3];
  e.push(d);
  return ne(d, e);
};*/
it("(2) circ arrays w same layout, same values are eq", function() {
  var d, e;
  d = [1, 2, 3];
  d.push(d);
  e = [1, 2, 3];
  e.push(e);
  return eq(d, e);
});
it("(fkling1) arrays w eq subarrays are eq", function() {
  var a, b, bar, foo;
  a = [1, 2, 3];
  b = [1, 2, 3];
  foo = [a, a];
  bar = [b, b];
  return eq(foo, bar);
});
/*it("(fkling2) arrays w eq subarrays but diff distribution aren't eq"] = function() {
  var a, b, bar, foo;
  a = [1, 2, 3];
  b = [1, 2, 3];
  foo = [a, a];
  bar = [a, b];
  return ne(foo, bar);
};*/

/* joshwilsdon's test (https://github.com/joyent/node/issues/7161) */
it("joshwilsdon", function() {
  var count, d1, d2, errors, idx1, idx2, v1, v2, _i, _j, _len, _ref;
  d1 = [
    NaN, void 0, null, true, false, Infinity, 0, 1, "a", "b", {
      a: 1
    }, {
      a: "a"
    }, [
      {
        a: 1
      }
    ], [
      {
        a: true
      }
    ], {
      a: 1,
      b: 2
    }, [1, 2], [1, 2, 3], {
      a: "1"
    }, {
      a: "1",
      b: "2"
    }
  ];
  d2 = [
    NaN, void 0, null, true, false, Infinity, 0, 1, "a", "b", {
      a: 1
    }, {
      a: "a"
    }, [
      {
        a: 1
      }
    ], [
      {
        a: true
      }
    ], {
      a: 1,
      b: 2
    }, [1, 2], [1, 2, 3], {
      a: "1"
    }, {
      a: "1",
      b: "2"
    }
  ];
  errors = [];
  count = 0;
  for (idx1 = _i = 0, _len = d1.length; _i < _len; idx1 = ++_i) {
    v1 = d1[idx1];
    for (idx2 = _j = idx1, _ref = d2.length; idx1 <= _ref ? _j < _ref : _j > _ref; idx2 = idx1 <= _ref ? ++_j : --_j) {
      count += 1;
      v2 = d2[idx2];
      if (idx1 === idx2) {
        if (!eq(v1, v2)) {
          //errors.push("eq " + (rpr(v1)) + ", " + (rpr(v2)));
        }
      } else {
        if (!ne(v1, v2)) {
          //errors.push("ne " + (rpr(v1)) + ", " + (rpr(v2)));
        }
      }
    }
  }
  return [count, errors];
});
it('node buffer', function() {
  eq(new Buffer('abc'), new Buffer('abc'));
  ne(new Buffer('abc'), new Buffer('abc1'));
  ne(new Buffer('abd'), new Buffer('abc'));
});
it('RegExp with props', function() {
  var re1 = /a/;
  re1.lastIndex = 3;
  ne(re1, /a/);
});
it('Date with props', function() {
  var now = Date.now();

  var d1 = new Date(now);
  var d2 = new Date(now);

  d1.a = 10;

  ne(d1, d2);
});
it('Check object prototypes', function() {
  var nbRoot = {
    toString: function() { return this.first + ' ' + this.last; }
  };

  function nameBuilder(first, last) {
    this.first = first;
    this.last = last;
    return this;
  }
  nameBuilder.prototype = nbRoot;

  function nameBuilder2(first, last) {
    this.first = first;
    this.last = last;
    return this;
  }
  nameBuilder2.prototype = nbRoot;

  var nb1 = new nameBuilder('Ryan', 'Dahl');
  var nb2 = new nameBuilder2('Ryan', 'Dahl');

  eq(nb1, nb2);

  nameBuilder2.prototype = Object;
  nb2 = new nameBuilder2('Ryan', 'Dahl');

  ne(nb1, nb2);
});

it('typed arrays and array buffer', function() {
  if(typeof Uint8Array !== 'undefined') {
    var arr1 = new Uint8Array([21, 31]);
    var arr2 = new Uint8Array([21, 31]);

    eq(arr1, arr2);

    eq(arr1.buffer, arr2.buffer);
  }
});

it('es6 sets', function() {
  if(typeof Set !== 'undefined') {
    var s1 = new Set([1, 2, 3]);
    var s2 = new Set([1, 2, 3]);
    var s3 = new Set(['a', 'b', 'c']);
    var s4 = new Set([]);

    var s5 = new Set([{ a: 1}, { a: 1}, { a: 1}]);
    var s6 = new Set([{ a: 1}, { a: 1}, { a: 1}]);

    eq(s1, s2);
    ne(s1, s3);
    ne(s1, s4);
    ne(s1, s5);
    eq(s5, s6);
  }
});

it('es6 maps', function() {
  if(typeof Map !== 'undefined') {
    var m1 = new Map([[1, 1], [2, 2], [3, 3]]);
    var m2 = new Map([[1, 1], [2, 2], [3, 3]]);

    var m3 = new Map([[1, 2], [2, 3], [3, 4]]);
    var m4 = new Map([[{ a: 10}, 2], [{ a: 11}, 2], [{ a: 12}, 2]]);
    var m5 = new Map([[{ a: 11}, 2], [{ a: 12}, 2], [{ a: 13}, 2]]);
    var m6 = new Map([[{ a: 11}, 2], [{ a: 12}, 2], [{ a: 13}, 2]]);

    eq(m1, m1);
    eq(m1, m2);
    ne(m3, m2);
    ne(m4, m5);
    eq(m5, m6);
  }
});
{
  "env": {
    "browser": true,
    "node": true
  },

  "extends": "eslint:recommended"
}
.idea
language: node_js
node_js:
- '0.12'
- '4.0'
- '4.1'
- '4.2'
script:
- npm test
The MIT License (MIT)

Copyright (c) 2014 

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

format
======

[![Build Status](https://travis-ci.org/shouldjs/format.svg?branch=master)](https://travis-ci.org/shouldjs/format)

Module for text inspections for instances
var getType = require('should-type');
var util = require('./util');

function genKeysFunc(f) {
  return function(value) {
    var k = f(value);
    k.sort();
    return k;
  };
}


function Formatter(opts) {
  opts = opts || {};

  this.seen = [];
  this.keys = genKeysFunc(opts.keys === false ? Object.getOwnPropertyNames : Object.keys);

  this.maxLineLength = typeof opts.maxLineLength === 'number' ? opts.maxLineLength : 60;
  this.propSep = opts.propSep || ',';

  this.isUTCdate = !!opts.isUTCdate;
}

Formatter.prototype = {
  constructor: Formatter,

  format: function(value) {
    var t = getType(value);
    var name1 = t.type, name2 = t.type;
    if(t.cls) {
      name1 += '_' + t.cls;
      name2 += '_' + t.cls;
    }
    if(t.sub) {
      name2 += '_' + t.sub;
    }
    var f = this['_format_' + name2] || this['_format_' + name1] || this['_format_' + t.type] || this.defaultFormat;
    return f.call(this, value).trim();
  },

  _formatObject: function(value, opts) {
    opts = opts || {};
    var mainKeys = opts.keys || this.keys(value);

    var len = 0;

    var formatPropertyValue = opts.formatPropertyValue || this.formatPropertyValue;
    var formatPropertyName = opts.formatPropertyName || this.formatPropertyName;
    var keyValueSep = opts.keyValueSep || ': ';
    var keyFilter = opts.keyFilter || function() { return true; };

    this.seen.push(value);
    var keys = [];

    mainKeys.forEach(function(key) {
      if(!keyFilter(key)) return;

      var fName = formatPropertyName.call(this, key);

      var f = (fName ? fName + keyValueSep : '') + formatPropertyValue.call(this, value, key);
      len += f.length;
      keys.push(f);
    }, this);
    this.seen.pop();

    (opts.additionalProperties || []).forEach(function(keyValue) {
      var f = keyValue[0] + keyValueSep + this.format(keyValue[1]);
      len += f.length;
      keys.push(f);
    }, this);

    var prefix = opts.prefix || Formatter.constructorName(value) || '';
    if(prefix.length > 0) prefix += ' ';

    var lbracket, rbracket;
    if(Array.isArray(opts.brackets)) {
      lbracket = opts.brackets && opts.brackets[0];
      rbracket = opts.brackets && opts.brackets[1];
    } else {
      lbracket = '{';
      rbracket = '}';
    }

    var rootValue = opts.value || '';

    if(keys.length === 0)
      return rootValue || (prefix + lbracket + rbracket);

    if(len <= this.maxLineLength) {
      return prefix + lbracket + ' ' + (rootValue ? rootValue + ' ' : '') + keys.join(this.propSep + ' ') + ' ' + rbracket;
    } else {
      return prefix + lbracket + '\n' + (rootValue ? '  ' + rootValue + '\n' : '') + keys.map(util.addSpaces).join(this.propSep + '\n') + '\n' + rbracket;
    }
  },

  formatObject: function(value, prefix, props) {
    props = props || this.keys(value);

    var len = 0;

    this.seen.push(value);
    props = props.map(function(prop) {
      var f = this.formatProperty(value, prop);
      len += f.length;
      return f;
    }, this);
    this.seen.pop();

    if(props.length === 0) return '{}';

    if(len <= this.maxLineLength) {
      return '{ ' + (prefix ? prefix + ' ' : '') + props.join(this.propSep + ' ') + ' }';
    } else {
      return '{' + '\n' + (prefix ? '  ' + prefix + '\n' : '') + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
    }
  },

  formatPropertyName: function(name) {
    return name.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/) ? name : this.format(name);
  },

  formatProperty: function(value, prop) {
    var desc = Formatter.getPropertyDescriptor(value, prop);

    var propName = this.formatPropertyName(prop);

    var propValue = desc.get && desc.set ?
      '[Getter/Setter]' : desc.get ?
      '[Getter]' : desc.set ?
      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
      '[Circular]' :
      this.format(desc.value);

    return propName + ': ' + propValue;
  },

  formatPropertyValue: function(value, prop) {
    var desc = Formatter.getPropertyDescriptor(value, prop);

    var propValue = desc.get && desc.set ?
      '[Getter/Setter]' : desc.get ?
      '[Getter]' : desc.set ?
      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
      '[Circular]' :
      this.format(desc.value);

    return propValue;
  }
};

Formatter.add = function add(type, cls, sub, f) {
  var args = Array.prototype.slice.call(arguments);
  f = args.pop();
  Formatter.prototype['_format_' + args.join('_')] = f;
};

Formatter.formatObjectWithPrefix = function formatObjectWithPrefix(f) {
  return function(value) {
    var prefix = f.call(this, value);
    var props = this.keys(value);
    if(props.length == 0) return prefix;
    else return this.formatObject(value, prefix, props);
  };
};

var functionNameRE = /^\s*function\s*(\S*)\s*\(/;

Formatter.functionName = function functionName(f) {
  if(f.name) {
    return f.name;
  }
  var name = f.toString().match(functionNameRE)[1];
  return name;
};

Formatter.constructorName = function(obj) {
  while (obj) {
    var descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor');
    if (descriptor !== undefined &&
        typeof descriptor.value === 'function') {

        var name = Formatter.functionName(descriptor.value);
        if(name !== '') {
          return name;
        }
    }

    obj = Object.getPrototypeOf(obj);
  }
};

Formatter.getPropertyDescriptor = function(obj, value) {
  var desc;
  try {
    desc = Object.getOwnPropertyDescriptor(obj, value) || {value: obj[value]};
  } catch(e) {
    desc = {value: e};
  }
  return desc;
};

Formatter.generateFunctionForIndexedArray = function generateFunctionForIndexedArray(lengthProp, name, padding) {
  return function(value) {
    var max = this.byteArrayMaxLength || 50;
    var length = value[lengthProp];
    var formattedValues = [];
    var len = 0;
    for(var i = 0; i < max && i < length; i++) {
      var b = value[i] || 0;
      var v = util.pad0(b.toString(16), padding);
      len += v.length;
      formattedValues.push(v);
    }
    var prefix = value.constructor.name || name || '';
    if(prefix) prefix += ' ';

    if(formattedValues.length === 0)
      return prefix + '[]';

    if(len <= this.maxLineLength) {
      return prefix + '[ ' + formattedValues.join(this.propSep + ' ') + ' ' + ']';
    } else {
      return prefix + '[\n' + formattedValues.map(util.addSpaces).join(this.propSep + '\n') + '\n' + ']';
    }
  };
};

Formatter.add('undefined', function() { return 'undefined' });
Formatter.add('null', function() { return 'null' });
Formatter.add('boolean', function(value) { return value ? 'true': 'false' });
Formatter.add('symbol', function(value) { return value.toString() });

['number', 'boolean'].forEach(function(name) {
  Formatter.add('object', name, function(value) {
    return this._formatObject(value, {
      additionalProperties: [['[[PrimitiveValue]]', value.valueOf()]]
    });
  });
});

Formatter.add('object', 'string', function(value) {
  var realValue = value.valueOf();

  return this._formatObject(value, {
    keyFilter: function(key) {
      //skip useless indexed properties
      return !(key.match(/\d+/) && parseInt(key, 10) < realValue.length);
    },
    additionalProperties: [['[[PrimitiveValue]]', realValue]]
  });
});

Formatter.add('object', 'regexp', function(value) {
  return this._formatObject(value, {
    value: String(value)
  });
});

Formatter.add('number', function(value) {
  if(value === 0 && 1 / value < 0) return '-0';
  return String(value);
});

Formatter.add('string', function(value) {
  return '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
      .replace(/'/g, "\\'")
      .replace(/\\"/g, '"') + '\'';
});

Formatter.add('object', function(value) {
  return this._formatObject(value);
});

Formatter.add('object', 'arguments', function(value) {
  return this._formatObject(value, {
    prefix: 'Arguments',
    formatPropertyName: function(key) {
      if(!key.match(/\d+/)) {
        return this.formatPropertyName(key);
      }
    },
    brackets: ['[', ']']
  });
});

Formatter.add('object', 'array', function(value) {
  return this._formatObject(value, {
    formatPropertyName: function(key) {
      if(!key.match(/\d+/)) {
        return this.formatPropertyName(key);
      }
    },
    brackets: ['[', ']']
  });
});


function formatDate(value, isUTC) {
  var prefix = isUTC ? 'UTC' : '';

  var date = value['get' + prefix + 'FullYear']() +
    '-' +
    util.pad0(value['get' + prefix + 'Month']() + 1, 2) +
    '-' +
    util.pad0(value['get' + prefix + 'Date'](), 2);

  var time = util.pad0(value['get' + prefix + 'Hours'](), 2) +
    ':' +
    util.pad0(value['get' + prefix + 'Minutes'](), 2) +
    ':' +
    util.pad0(value['get' + prefix + 'Seconds'](), 2) +
    '.' +
    util.pad0(value['get' + prefix + 'Milliseconds'](), 3);

  var to = value.getTimezoneOffset();
  var absTo = Math.abs(to);
  var hours = Math.floor(absTo / 60);
  var minutes = absTo - hours * 60;
  var tzFormat = (to < 0 ? '+' : '-') + util.pad0(hours, 2) + util.pad0(minutes, 2);

  return date + ' ' + time + (isUTC ? '' : ' ' + tzFormat);
}

Formatter.add('object', 'date', function(value) {
  return this._formatObject(value, { value: formatDate(value, this.isUTCdate) });
});

Formatter.add('function', function(value) {
  return this._formatObject(value, {
    additionalProperties: [['name', Formatter.functionName(value)]]
  });
});

Formatter.add('object', 'error', function(value) {
  return this._formatObject(value, {
    prefix: value.name,
    additionalProperties: [['message', value.message]]
  });
});

Formatter.add('object', 'buffer', Formatter.generateFunctionForIndexedArray('length', 'Buffer', 2));

Formatter.add('object', 'array-buffer', Formatter.generateFunctionForIndexedArray('byteLength', 'ArrayBuffer', 2));

Formatter.add('object', 'typed-array', 'int8', Formatter.generateFunctionForIndexedArray('length', 'Int8Array', 2));
Formatter.add('object', 'typed-array', 'uint8', Formatter.generateFunctionForIndexedArray('length', 'Uint8Array', 2));
Formatter.add('object', 'typed-array', 'uint8clamped', Formatter.generateFunctionForIndexedArray('length', 'Uint8ClampedArray', 2));

Formatter.add('object', 'typed-array', 'int16', Formatter.generateFunctionForIndexedArray('length', 'Int16Array', 4));
Formatter.add('object', 'typed-array', 'uint16', Formatter.generateFunctionForIndexedArray('length', 'Uint16Array', 4));

Formatter.add('object', 'typed-array', 'int32', Formatter.generateFunctionForIndexedArray('length', 'Int32Array', 8));
Formatter.add('object', 'typed-array', 'uint32', Formatter.generateFunctionForIndexedArray('length', 'Uint32Array', 8));

//TODO add float32 and float64

Formatter.add('object', 'promise', function() {
  return '[Promise]';//TODO it could be nice to inspect its state and value
});

Formatter.add('object', 'xhr', function() {
  return '[XMLHttpRequest]';//TODO it could be nice to inspect its state
});

Formatter.add('object', 'html-element', function(value) {
  return value.outerHTML;
});

Formatter.add('object', 'html-element', '#text', function(value) {
  return value.nodeValue;
});

Formatter.add('object', 'html-element', '#document', function(value) {
  return value.documentElement.outerHTML;
});

Formatter.add('object', 'host', function() {
  return '[Host]';
});

Formatter.add('object', 'set', function(value) {
  var iter = value.values();
  var len = 0;

  this.seen.push(value);

  var props = [];

  var next = iter.next();
  while(!next.done) {
    var val = next.value;
    var f = this.format(val);
    len += f.length;
    props.push(f);

    next = iter.next();
  }

  this.seen.pop();

  if(props.length === 0) return 'Set {}';

  if(len <= this.maxLineLength) {
    return 'Set { ' + props.join(this.propSep + ' ') + ' }';
  } else {
    return 'Set {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
  }
});

Formatter.add('object', 'map', function(value) {
  var iter = value.entries();
  var len = 0;

  this.seen.push(value);

  var props = [];

  var next = iter.next();
  while(!next.done) {
    var val = next.value;
    var fK = this.format(val[0]);
    var fV = this.format(val[1]);

    var f;
    if((fK.length + fV.length + 4) <= this.maxLineLength) {
      f = fK + ' => ' + fV;
    } else {
      f = fK + ' =>\n' + fV;
    }

    len += fK.length + fV.length + 4;
    props.push(f);

    next = iter.next();
  }

  this.seen.pop();

  if(props.length === 0) return 'Map {}';

  if(len <= this.maxLineLength) {
    return 'Map { ' + props.join(this.propSep + ' ') + ' }';
  } else {
    return 'Map {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
  }
});

Formatter.prototype.defaultFormat = Formatter.prototype._format_object;

function defaultFormat(value, opts) {
  return new Formatter(opts).format(value);
}

defaultFormat.Formatter = Formatter;
module.exports = defaultFormat;
{
  "name": "should-format",
  "version": "0.3.1",
  "description": "Formatting of objects for should.js",
  "main": "index.js",
  "repository": {
    "type": "git",
    "url": "git://github.com/shouldjs/format.git"
  },
  "scripts": {
    "test": "mocha -R mocha-better-spec-reporter tests/test.js",
    "browserify": "rm tests/browser/tests.js && browserify tests/test.js >> tests/browser/tests.js"
  },
  "keywords": [
    "should",
    "format"
  ],
  "author": {
    "name": "Denis Bardadym",
    "email": "bardadymchik@gmail.com"
  },
  "license": "MIT",
  "devDependencies": {
    "browserify": "latest",
    "mocha": "latest",
    "mocha-better-spec-reporter": "latest"
  },
  "dependencies": {
    "should-type": "0.2.0"
  },
  "gitHead": "b0320d30cc16c860b4dc973675ea1f339cef9dce",
  "bugs": {
    "url": "https://github.com/shouldjs/format/issues"
  },
  "homepage": "https://github.com/shouldjs/format#readme",
  "_id": "should-format@0.3.1",
  "_shasum": "2cbb782461670ace4292b2b1ec468db8cf99e330",
  "_from": "should-format@0.3.1",
  "_npmVersion": "2.14.7",
  "_nodeVersion": "4.2.0",
  "_npmUser": {
    "name": "btd",
    "email": "bardadymchik@gmail.com"
  },
  "dist": {
    "shasum": "2cbb782461670ace4292b2b1ec468db8cf99e330",
    "tarball": "http://registry.npmjs.org/should-format/-/should-format-0.3.1.tgz"
  },
  "maintainers": [
    {
      "name": "btd",
      "email": "bardadymchik@gmail.com"
    }
  ],
  "directories": {},
  "_resolved": "https://registry.npmjs.org/should-format/-/should-format-0.3.1.tgz",
  "readme": "ERROR: No README data found!"
}
<!DOCTYPE html>
<html>
  <head>
    <title>Mocha</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="mocha.css" />
  </head>
  <body>
    <div id="mocha"></div>
    <script src="mocha.js"></script>
    <script>mocha.setup('bdd')</script>
    <script src="tests.js"></script>
    <script>
      mocha.run();
    </script>
  </body>
</html>
@charset "utf-8";

body {
  margin:0;
}

#mocha {
  font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
  margin: 60px 50px;
}

#mocha ul,
#mocha li {
  margin: 0;
  padding: 0;
}

#mocha ul {
  list-style: none;
}

#mocha h1,
#mocha h2 {
  margin: 0;
}

#mocha h1 {
  margin-top: 15px;
  font-size: 1em;
  font-weight: 200;
}

#mocha h1 a {
  text-decoration: none;
  color: inherit;
}

#mocha h1 a:hover {
  text-decoration: underline;
}

#mocha .suite .suite h1 {
  margin-top: 0;
  font-size: .8em;
}

#mocha .hidden {
  display: none;
}

#mocha h2 {
  font-size: 12px;
  font-weight: normal;
  cursor: pointer;
}

#mocha .suite {
  margin-left: 15px;
}

#mocha .test {
  margin-left: 15px;
  overflow: hidden;
}

#mocha .test.pending:hover h2::after {
  content: '(pending)';
  font-family: arial, sans-serif;
}

#mocha .test.pass.medium .duration {
  background: #c09853;
}

#mocha .test.pass.slow .duration {
  background: #b94a48;
}

#mocha .test.pass::before {
  content: '✓';
  font-size: 12px;
  display: block;
  float: left;
  margin-right: 5px;
  color: #00d6b2;
}

#mocha .test.pass .duration {
  font-size: 9px;
  margin-left: 5px;
  padding: 2px 5px;
  color: #fff;
  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
  -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
  box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -o-border-radius: 5px;
  border-radius: 5px;
}

#mocha .test.pass.fast .duration {
  display: none;
}

#mocha .test.pending {
  color: #0b97c4;
}

#mocha .test.pending::before {
  content: '◦';
  color: #0b97c4;
}

#mocha .test.fail {
  color: #c00;
}

#mocha .test.fail pre {
  color: black;
}

#mocha .test.fail::before {
  content: '✖';
  font-size: 12px;
  display: block;
  float: left;
  margin-right: 5px;
  color: #c00;
}

#mocha .test pre.error {
  color: #c00;
  max-height: 300px;
  overflow: auto;
}

/**
 * (1): approximate for browsers not supporting calc
 * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
 *      ^^ seriously
 */
#mocha .test pre {
  display: block;
  float: left;
  clear: left;
  font: 12px/1.5 monaco, monospace;
  margin: 5px;
  padding: 15px;
  border: 1px solid #eee;
  max-width: 85%; /*(1)*/
  max-width: calc(100% - 42px); /*(2)*/
  word-wrap: break-word;
  border-bottom-color: #ddd;
  -webkit-border-radius: 3px;
  -webkit-box-shadow: 0 1px 3px #eee;
  -moz-border-radius: 3px;
  -moz-box-shadow: 0 1px 3px #eee;
  border-radius: 3px;
}

#mocha .test h2 {
  position: relative;
}

#mocha .test a.replay {
  position: absolute;
  top: 3px;
  right: 0;
  text-decoration: none;
  vertical-align: middle;
  display: block;
  width: 15px;
  height: 15px;
  line-height: 15px;
  text-align: center;
  background: #eee;
  font-size: 15px;
  -moz-border-radius: 15px;
  border-radius: 15px;
  -webkit-transition: opacity 200ms;
  -moz-transition: opacity 200ms;
  transition: opacity 200ms;
  opacity: 0.3;
  color: #888;
}

#mocha .test:hover a.replay {
  opacity: 1;
}

#mocha-report.pass .test.fail {
  display: none;
}

#mocha-report.fail .test.pass {
  display: none;
}

#mocha-report.pending .test.pass,
#mocha-report.pending .test.fail {
  display: none;
}
#mocha-report.pending .test.pass.pending {
  display: block;
}

#mocha-error {
  color: #c00;
  font-size: 1.5em;
  font-weight: 100;
  letter-spacing: 1px;
}

#mocha-stats {
  position: fixed;
  top: 15px;
  right: 10px;
  font-size: 12px;
  margin: 0;
  color: #888;
  z-index: 1;
}

#mocha-stats .progress {
  float: right;
  padding-top: 0;
}

#mocha-stats em {
  color: black;
}

#mocha-stats a {
  text-decoration: none;
  color: inherit;
}

#mocha-stats a:hover {
  border-bottom: 1px solid #eee;
}

#mocha-stats li {
  display: inline-block;
  margin: 0 5px;
  list-style: none;
  padding-top: 11px;
}

#mocha-stats canvas {
  width: 40px;
  height: 40px;
}

#mocha code .comment { color: #ddd; }
#mocha code .init { color: #2f6fad; }
#mocha code .string { color: #5890ad; }
#mocha code .keyword { color: #8a6343; }
#mocha code .number { color: #2f6fad; }

@media screen and (max-device-width: 480px) {
  #mocha {
    margin: 60px 0px;
  }

  #mocha #stats {
    position: absolute;
  }
}
;(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.charAt(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("browser/debug.js", function(module, exports, require){
module.exports = function(type){
  return function(){
  }
};

}); // module: browser/debug.js

require.register("browser/diff.js", function(module, exports, require){
/* See LICENSE file for terms of use */

/*
 * Text diff implementation.
 *
 * This library supports the following APIS:
 * JsDiff.diffChars: Character by character diff
 * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
 * JsDiff.diffLines: Line based diff
 *
 * JsDiff.diffCss: Diff targeted at CSS content
 *
 * These methods are based on the implementation proposed in
 * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
 * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
 */
var JsDiff = (function() {
  /*jshint maxparams: 5*/
  function clonePath(path) {
    return { newPos: path.newPos, components: path.components.slice(0) };
  }
  function removeEmpty(array) {
    var ret = [];
    for (var i = 0; i < array.length; i++) {
      if (array[i]) {
        ret.push(array[i]);
      }
    }
    return ret;
  }
  function escapeHTML(s) {
    var n = s;
    n = n.replace(/&/g, '&amp;');
    n = n.replace(/</g, '&lt;');
    n = n.replace(/>/g, '&gt;');
    n = n.replace(/"/g, '&quot;');

    return n;
  }

  var Diff = function(ignoreWhitespace) {
    this.ignoreWhitespace = ignoreWhitespace;
  };
  Diff.prototype = {
      diff: function(oldString, newString) {
        // Handle the identity case (this is due to unrolling editLength == 0
        if (newString === oldString) {
          return [{ value: newString }];
        }
        if (!newString) {
          return [{ value: oldString, removed: true }];
        }
        if (!oldString) {
          return [{ value: newString, added: true }];
        }

        newString = this.tokenize(newString);
        oldString = this.tokenize(oldString);

        var newLen = newString.length, oldLen = oldString.length;
        var maxEditLength = newLen + oldLen;
        var bestPath = [{ newPos: -1, components: [] }];

        // Seed editLength = 0
        var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
        if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) {
          return bestPath[0].components;
        }

        for (var editLength = 1; editLength <= maxEditLength; editLength++) {
          for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) {
            var basePath;
            var addPath = bestPath[diagonalPath-1],
                removePath = bestPath[diagonalPath+1];
            oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
            if (addPath) {
              // No one else is going to attempt to use this value, clear it
              bestPath[diagonalPath-1] = undefined;
            }

            var canAdd = addPath && addPath.newPos+1 < newLen;
            var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
            if (!canAdd && !canRemove) {
              bestPath[diagonalPath] = undefined;
              continue;
            }

            // Select the diagonal that we want to branch from. We select the prior
            // path whose position in the new string is the farthest from the origin
            // and does not pass the bounds of the diff graph
            if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
              basePath = clonePath(removePath);
              this.pushComponent(basePath.components, oldString[oldPos], undefined, true);
            } else {
              basePath = clonePath(addPath);
              basePath.newPos++;
              this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);
            }

            var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);

            if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) {
              return basePath.components;
            } else {
              bestPath[diagonalPath] = basePath;
            }
          }
        }
      },

      pushComponent: function(components, value, added, removed) {
        var last = components[components.length-1];
        if (last && last.added === added && last.removed === removed) {
          // We need to clone here as the component clone operation is just
          // as shallow array clone
          components[components.length-1] =
            {value: this.join(last.value, value), added: added, removed: removed };
        } else {
          components.push({value: value, added: added, removed: removed });
        }
      },
      extractCommon: function(basePath, newString, oldString, diagonalPath) {
        var newLen = newString.length,
            oldLen = oldString.length,
            newPos = basePath.newPos,
            oldPos = newPos - diagonalPath;
        while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {
          newPos++;
          oldPos++;

          this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
        }
        basePath.newPos = newPos;
        return oldPos;
      },

      equals: function(left, right) {
        var reWhitespace = /\S/;
        if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
          return true;
        } else {
          return left === right;
        }
      },
      join: function(left, right) {
        return left + right;
      },
      tokenize: function(value) {
        return value;
      }
  };

  var CharDiff = new Diff();

  var WordDiff = new Diff(true);
  var WordWithSpaceDiff = new Diff();
  WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) {
    return removeEmpty(value.split(/(\s+|\b)/));
  };

  var CssDiff = new Diff(true);
  CssDiff.tokenize = function(value) {
    return removeEmpty(value.split(/([{}:;,]|\s+)/));
  };

  var LineDiff = new Diff();
  LineDiff.tokenize = function(value) {
    return value.split(/^/m);
  };

  return {
    Diff: Diff,

    diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
    diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },
    diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); },
    diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },

    diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },

    createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
      var ret = [];

      ret.push('Index: ' + fileName);
      ret.push('===================================================================');
      ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
      ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));

      var diff = LineDiff.diff(oldStr, newStr);
      if (!diff[diff.length-1].value) {
        diff.pop();   // Remove trailing newline add
      }
      diff.push({value: '', lines: []});   // Append an empty value to make cleanup easier

      function contextLines(lines) {
        return lines.map(function(entry) { return ' ' + entry; });
      }
      function eofNL(curRange, i, current) {
        var last = diff[diff.length-2],
            isLast = i === diff.length-2,
            isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);

        // Figure out if this is the last line for the given file and missing NL
        if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
          curRange.push('\\ No newline at end of file');
        }
      }

      var oldRangeStart = 0, newRangeStart = 0, curRange = [],
          oldLine = 1, newLine = 1;
      for (var i = 0; i < diff.length; i++) {
        var current = diff[i],
            lines = current.lines || current.value.replace(/\n$/, '').split('\n');
        current.lines = lines;

        if (current.added || current.removed) {
          if (!oldRangeStart) {
            var prev = diff[i-1];
            oldRangeStart = oldLine;
            newRangeStart = newLine;

            if (prev) {
              curRange = contextLines(prev.lines.slice(-4));
              oldRangeStart -= curRange.length;
              newRangeStart -= curRange.length;
            }
          }
          curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; }));
          eofNL(curRange, i, current);

          if (current.added) {
            newLine += lines.length;
          } else {
            oldLine += lines.length;
          }
        } else {
          if (oldRangeStart) {
            // Close out any changes that have been output (or join overlapping)
            if (lines.length <= 8 && i < diff.length-2) {
              // Overlapping
              curRange.push.apply(curRange, contextLines(lines));
            } else {
              // end the range and output
              var contextSize = Math.min(lines.length, 4);
              ret.push(
                  '@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)
                  + ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)
                  + ' @@');
              ret.push.apply(ret, curRange);
              ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
              if (lines.length <= 4) {
                eofNL(ret, i, current);
              }

              oldRangeStart = 0;  newRangeStart = 0; curRange = [];
            }
          }
          oldLine += lines.length;
          newLine += lines.length;
        }
      }

      return ret.join('\n') + '\n';
    },

    applyPatch: function(oldStr, uniDiff) {
      var diffstr = uniDiff.split('\n');
      var diff = [];
      var remEOFNL = false,
          addEOFNL = false;

      for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) {
        if(diffstr[i][0] === '@') {
          var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
          diff.unshift({
            start:meh[3],
            oldlength:meh[2],
            oldlines:[],
            newlength:meh[4],
            newlines:[]
          });
        } else if(diffstr[i][0] === '+') {
          diff[0].newlines.push(diffstr[i].substr(1));
        } else if(diffstr[i][0] === '-') {
          diff[0].oldlines.push(diffstr[i].substr(1));
        } else if(diffstr[i][0] === ' ') {
          diff[0].newlines.push(diffstr[i].substr(1));
          diff[0].oldlines.push(diffstr[i].substr(1));
        } else if(diffstr[i][0] === '\\') {
          if (diffstr[i-1][0] === '+') {
            remEOFNL = true;
          } else if(diffstr[i-1][0] === '-') {
            addEOFNL = true;
          }
        }
      }

      var str = oldStr.split('\n');
      for (var i = diff.length - 1; i >= 0; i--) {
        var d = diff[i];
        for (var j = 0; j < d.oldlength; j++) {
          if(str[d.start-1+j] !== d.oldlines[j]) {
            return false;
          }
        }
        Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
      }

      if (remEOFNL) {
        while (!str[str.length-1]) {
          str.pop();
        }
      } else if (addEOFNL) {
        str.push('');
      }
      return str.join('\n');
    },

    convertChangesToXML: function(changes){
      var ret = [];
      for ( var i = 0; i < changes.length; i++) {
        var change = changes[i];
        if (change.added) {
          ret.push('<ins>');
        } else if (change.removed) {
          ret.push('<del>');
        }

        ret.push(escapeHTML(change.value));

        if (change.added) {
          ret.push('</ins>');
        } else if (change.removed) {
          ret.push('</del>');
        }
      }
      return ret.join('');
    },

    // See: http://code.google.com/p/google-diff-match-patch/wiki/API
    convertChangesToDMP: function(changes){
      var ret = [], change;
      for ( var i = 0; i < changes.length; i++) {
        change = changes[i];
        ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);
      }
      return ret;
    }
  };
})();

if (typeof module !== 'undefined') {
    module.exports = JsDiff;
}

}); // module: browser/diff.js

require.register("browser/escape-string-regexp.js", function(module, exports, require){
'use strict';

var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;

module.exports = function (str) {
  if (typeof str !== 'string') {
    throw new TypeError('Expected a string');
  }

  return str.replace(matchOperatorsRe,  '\\$&');
};

}); // module: browser/escape-string-regexp.js

require.register("browser/events.js", function(module, exports, require){
/**
 * Module exports.
 */

exports.EventEmitter = EventEmitter;

/**
 * Check if `obj` is an array.
 */

function isArray(obj) {
  return '[object Array]' == {}.toString.call(obj);
}

/**
 * Event emitter constructor.
 *
 * @api public
 */

function EventEmitter(){};

/**
 * Adds a listener.
 *
 * @api public
 */

EventEmitter.prototype.on = function (name, fn) {
  if (!this.$events) {
    this.$events = {};
  }

  if (!this.$events[name]) {
    this.$events[name] = fn;
  } else if (isArray(this.$events[name])) {
    this.$events[name].push(fn);
  } else {
    this.$events[name] = [this.$events[name], fn];
  }

  return this;
};

EventEmitter.prototype.addListener = EventEmitter.prototype.on;

/**
 * Adds a volatile listener.
 *
 * @api public
 */

EventEmitter.prototype.once = function (name, fn) {
  var self = this;

  function on () {
    self.removeListener(name, on);
    fn.apply(this, arguments);
  };

  on.listener = fn;
  this.on(name, on);

  return this;
};

/**
 * Removes a listener.
 *
 * @api public
 */

EventEmitter.prototype.removeListener = function (name, fn) {
  if (this.$events && this.$events[name]) {
    var list = this.$events[name];

    if (isArray(list)) {
      var pos = -1;

      for (var i = 0, l = list.length; i < l; i++) {
        if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
          pos = i;
          break;
        }
      }

      if (pos < 0) {
        return this;
      }

      list.splice(pos, 1);

      if (!list.length) {
        delete this.$events[name];
      }
    } else if (list === fn || (list.listener && list.listener === fn)) {
      delete this.$events[name];
    }
  }

  return this;
};

/**
 * Removes all listeners for an event.
 *
 * @api public
 */

EventEmitter.prototype.removeAllListeners = function (name) {
  if (name === undefined) {
    this.$events = {};
    return this;
  }

  if (this.$events && this.$events[name]) {
    this.$events[name] = null;
  }

  return this;
};

/**
 * Gets all listeners for a certain event.
 *
 * @api public
 */

EventEmitter.prototype.listeners = function (name) {
  if (!this.$events) {
    this.$events = {};
  }

  if (!this.$events[name]) {
    this.$events[name] = [];
  }

  if (!isArray(this.$events[name])) {
    this.$events[name] = [this.$events[name]];
  }

  return this.$events[name];
};

/**
 * Emits an event.
 *
 * @api public
 */

EventEmitter.prototype.emit = function (name) {
  if (!this.$events) {
    return false;
  }

  var handler = this.$events[name];

  if (!handler) {
    return false;
  }

  var args = [].slice.call(arguments, 1);

  if ('function' == typeof handler) {
    handler.apply(this, args);
  } else if (isArray(handler)) {
    var listeners = handler.slice();

    for (var i = 0, l = listeners.length; i < l; i++) {
      listeners[i].apply(this, args);
    }
  } else {
    return false;
  }

  return true;
};

}); // module: browser/events.js

require.register("browser/fs.js", function(module, exports, require){

}); // module: browser/fs.js

require.register("browser/glob.js", function(module, exports, require){

}); // module: browser/glob.js

require.register("browser/path.js", function(module, exports, require){

}); // module: browser/path.js

require.register("browser/progress.js", function(module, exports, require){
/**
 * Expose `Progress`.
 */

module.exports = Progress;

/**
 * Initialize a new `Progress` indicator.
 */

function Progress() {
  this.percent = 0;
  this.size(0);
  this.fontSize(11);
  this.font('helvetica, arial, sans-serif');
}

/**
 * Set progress size to `n`.
 *
 * @param {Number} n
 * @return {Progress} for chaining
 * @api public
 */

Progress.prototype.size = function(n){
  this._size = n;
  return this;
};

/**
 * Set text to `str`.
 *
 * @param {String} str
 * @return {Progress} for chaining
 * @api public
 */

Progress.prototype.text = function(str){
  this._text = str;
  return this;
};

/**
 * Set font size to `n`.
 *
 * @param {Number} n
 * @return {Progress} for chaining
 * @api public
 */

Progress.prototype.fontSize = function(n){
  this._fontSize = n;
  return this;
};

/**
 * Set font `family`.
 *
 * @param {String} family
 * @return {Progress} for chaining
 */

Progress.prototype.font = function(family){
  this._font = family;
  return this;
};

/**
 * Update percentage to `n`.
 *
 * @param {Number} n
 * @return {Progress} for chaining
 */

Progress.prototype.update = function(n){
  this.percent = n;
  return this;
};

/**
 * Draw on `ctx`.
 *
 * @param {CanvasRenderingContext2d} ctx
 * @return {Progress} for chaining
 */

Progress.prototype.draw = function(ctx){
  try {
    var percent = Math.min(this.percent, 100)
      , size = this._size
      , half = size / 2
      , x = half
      , y = half
      , rad = half - 1
      , fontSize = this._fontSize;

    ctx.font = fontSize + 'px ' + this._font;

    var angle = Math.PI * 2 * (percent / 100);
    ctx.clearRect(0, 0, size, size);

    // outer circle
    ctx.strokeStyle = '#9f9f9f';
    ctx.beginPath();
    ctx.arc(x, y, rad, 0, angle, false);
    ctx.stroke();

    // inner circle
    ctx.strokeStyle = '#eee';
    ctx.beginPath();
    ctx.arc(x, y, rad - 1, 0, angle, true);
    ctx.stroke();

    // text
    var text = this._text || (percent | 0) + '%'
      , w = ctx.measureText(text).width;

    ctx.fillText(
        text
      , x - w / 2 + 1
      , y + fontSize / 2 - 1);
  } catch (ex) {} //don't fail if we can't render progress
  return this;
};

}); // module: browser/progress.js

require.register("browser/tty.js", function(module, exports, require){
exports.isatty = function(){
  return true;
};

exports.getWindowSize = function(){
  if ('innerHeight' in global) {
    return [global.innerHeight, global.innerWidth];
  } else {
    // In a Web Worker, the DOM Window is not available.
    return [640, 480];
  }
};

}); // module: browser/tty.js

require.register("context.js", function(module, exports, require){
/**
 * Expose `Context`.
 */

module.exports = Context;

/**
 * Initialize a new `Context`.
 *
 * @api private
 */

function Context(){}

/**
 * Set or get the context `Runnable` to `runnable`.
 *
 * @param {Runnable} runnable
 * @return {Context}
 * @api private
 */

Context.prototype.runnable = function(runnable){
  if (0 == arguments.length) return this._runnable;
  this.test = this._runnable = runnable;
  return this;
};

/**
 * Set test timeout `ms`.
 *
 * @param {Number} ms
 * @return {Context} self
 * @api private
 */

Context.prototype.timeout = function(ms){
  if (arguments.length === 0) return this.runnable().timeout();
  this.runnable().timeout(ms);
  return this;
};

/**
 * Set test timeout `enabled`.
 *
 * @param {Boolean} enabled
 * @return {Context} self
 * @api private
 */

Context.prototype.enableTimeouts = function (enabled) {
  this.runnable().enableTimeouts(enabled);
  return this;
};


/**
 * Set test slowness threshold `ms`.
 *
 * @param {Number} ms
 * @return {Context} self
 * @api private
 */

Context.prototype.slow = function(ms){
  this.runnable().slow(ms);
  return this;
};

/**
 * Inspect the context void of `._runnable`.
 *
 * @return {String}
 * @api private
 */

Context.prototype.inspect = function(){
  return JSON.stringify(this, function(key, val){
    if ('_runnable' == key) return;
    if ('test' == key) return;
    return val;
  }, 2);
};

}); // module: context.js

require.register("hook.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Runnable = require('./runnable');

/**
 * Expose `Hook`.
 */

module.exports = Hook;

/**
 * Initialize a new `Hook` with the given `title` and callback `fn`.
 *
 * @param {String} title
 * @param {Function} fn
 * @api private
 */

function Hook(title, fn) {
  Runnable.call(this, title, fn);
  this.type = 'hook';
}

/**
 * Inherit from `Runnable.prototype`.
 */

function F(){};
F.prototype = Runnable.prototype;
Hook.prototype = new F;
Hook.prototype.constructor = Hook;


/**
 * Get or set the test `err`.
 *
 * @param {Error} err
 * @return {Error}
 * @api public
 */

Hook.prototype.error = function(err){
  if (0 == arguments.length) {
    var err = this._error;
    this._error = null;
    return err;
  }

  this._error = err;
};

}); // module: hook.js

require.register("interfaces/bdd.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Suite = require('../suite')
  , Test = require('../test')
  , utils = require('../utils')
  , escapeRe = require('browser/escape-string-regexp');

/**
 * BDD-style interface:
 *
 *      describe('Array', function(){
 *        describe('#indexOf()', function(){
 *          it('should return -1 when not present', function(){
 *
 *          });
 *
 *          it('should return the index when present', function(){
 *
 *          });
 *        });
 *      });
 *
 */

module.exports = function(suite){
  var suites = [suite];

  suite.on('pre-require', function(context, file, mocha){

    /**
     * Execute before running tests.
     */

    context.before = function(name, fn){
      suites[0].beforeAll(name, fn);
    };

    /**
     * Execute after running tests.
     */

    context.after = function(name, fn){
      suites[0].afterAll(name, fn);
    };

    /**
     * Execute before each test case.
     */

    context.beforeEach = function(name, fn){
      suites[0].beforeEach(name, fn);
    };

    /**
     * Execute after each test case.
     */

    context.afterEach = function(name, fn){
      suites[0].afterEach(name, fn);
    };

    /**
     * Describe a "suite" with the given `title`
     * and callback `fn` containing nested suites
     * and/or tests.
     */

    context.describe = context.context = function(title, fn){
      var suite = Suite.create(suites[0], title);
      suite.file = file;
      suites.unshift(suite);
      fn.call(suite);
      suites.shift();
      return suite;
    };

    /**
     * Pending describe.
     */

    context.xdescribe =
    context.xcontext =
    context.describe.skip = function(title, fn){
      var suite = Suite.create(suites[0], title);
      suite.pending = true;
      suites.unshift(suite);
      fn.call(suite);
      suites.shift();
    };

    /**
     * Exclusive suite.
     */

    context.describe.only = function(title, fn){
      var suite = context.describe(title, fn);
      mocha.grep(suite.fullTitle());
      return suite;
    };

    /**
     * Describe a specification or test-case
     * with the given `title` and callback `fn`
     * acting as a thunk.
     */

    context.it = context.specify = function(title, fn){
      var suite = suites[0];
      if (suite.pending) fn = null;
      var test = new Test(title, fn);
      test.file = file;
      suite.addTest(test);
      return test;
    };

    /**
     * Exclusive test-case.
     */

    context.it.only = function(title, fn){
      var test = context.it(title, fn);
      var reString = '^' + escapeRe(test.fullTitle()) + '$';
      mocha.grep(new RegExp(reString));
      return test;
    };

    /**
     * Pending test case.
     */

    context.xit =
    context.xspecify =
    context.it.skip = function(title){
      context.it(title);
    };
  });
};

}); // module: interfaces/bdd.js

require.register("interfaces/exports.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Suite = require('../suite')
  , Test = require('../test');

/**
 * TDD-style interface:
 *
 *     exports.Array = {
 *       '#indexOf()': {
 *         'should return -1 when the value is not present': function(){
 *
 *         },
 *
 *         'should return the correct index when the value is present': function(){
 *
 *         }
 *       }
 *     };
 *
 */

module.exports = function(suite){
  var suites = [suite];

  suite.on('require', visit);

  function visit(obj, file) {
    var suite;
    for (var key in obj) {
      if ('function' == typeof obj[key]) {
        var fn = obj[key];
        switch (key) {
          case 'before':
            suites[0].beforeAll(fn);
            break;
          case 'after':
            suites[0].afterAll(fn);
            break;
          case 'beforeEach':
            suites[0].beforeEach(fn);
            break;
          case 'afterEach':
            suites[0].afterEach(fn);
            break;
          default:
            var test = new Test(key, fn);
            test.file = file;
            suites[0].addTest(test);
        }
      } else {
        suite = Suite.create(suites[0], key);
        suites.unshift(suite);
        visit(obj[key]);
        suites.shift();
      }
    }
  }
};

}); // module: interfaces/exports.js

require.register("interfaces/index.js", function(module, exports, require){
exports.bdd = require('./bdd');
exports.tdd = require('./tdd');
exports.qunit = require('./qunit');
exports.exports = require('./exports');

}); // module: interfaces/index.js

require.register("interfaces/qunit.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Suite = require('../suite')
  , Test = require('../test')
  , escapeRe = require('browser/escape-string-regexp')
  , utils = require('../utils');

/**
 * QUnit-style interface:
 *
 *     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);
 *     });
 *
 */

module.exports = function(suite){
  var suites = [suite];

  suite.on('pre-require', function(context, file, mocha){

    /**
     * Execute before running tests.
     */

    context.before = function(name, fn){
      suites[0].beforeAll(name, fn);
    };

    /**
     * Execute after running tests.
     */

    context.after = function(name, fn){
      suites[0].afterAll(name, fn);
    };

    /**
     * Execute before each test case.
     */

    context.beforeEach = function(name, fn){
      suites[0].beforeEach(name, fn);
    };

    /**
     * Execute after each test case.
     */

    context.afterEach = function(name, fn){
      suites[0].afterEach(name, fn);
    };

    /**
     * Describe a "suite" with the given `title`.
     */

    context.suite = function(title){
      if (suites.length > 1) suites.shift();
      var suite = Suite.create(suites[0], title);
      suite.file = file;
      suites.unshift(suite);
      return suite;
    };

    /**
     * Exclusive test-case.
     */

    context.suite.only = function(title, fn){
      var suite = context.suite(title, fn);
      mocha.grep(suite.fullTitle());
    };

    /**
     * Describe a specification or test-case
     * with the given `title` and callback `fn`
     * acting as a thunk.
     */

    context.test = function(title, fn){
      var test = new Test(title, fn);
      test.file = file;
      suites[0].addTest(test);
      return test;
    };

    /**
     * Exclusive test-case.
     */

    context.test.only = function(title, fn){
      var test = context.test(title, fn);
      var reString = '^' + escapeRe(test.fullTitle()) + '$';
      mocha.grep(new RegExp(reString));
    };

    /**
     * Pending test case.
     */

    context.test.skip = function(title){
      context.test(title);
    };
  });
};

}); // module: interfaces/qunit.js

require.register("interfaces/tdd.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Suite = require('../suite')
  , Test = require('../test')
  , escapeRe = require('browser/escape-string-regexp')
  , utils = require('../utils');

/**
 * TDD-style interface:
 *
 *      suite('Array', function(){
 *        suite('#indexOf()', function(){
 *          suiteSetup(function(){
 *
 *          });
 *
 *          test('should return -1 when not present', function(){
 *
 *          });
 *
 *          test('should return the index when present', function(){
 *
 *          });
 *
 *          suiteTeardown(function(){
 *
 *          });
 *        });
 *      });
 *
 */

module.exports = function(suite){
  var suites = [suite];

  suite.on('pre-require', function(context, file, mocha){

    /**
     * Execute before each test case.
     */

    context.setup = function(name, fn){
      suites[0].beforeEach(name, fn);
    };

    /**
     * Execute after each test case.
     */

    context.teardown = function(name, fn){
      suites[0].afterEach(name, fn);
    };

    /**
     * Execute before the suite.
     */

    context.suiteSetup = function(name, fn){
      suites[0].beforeAll(name, fn);
    };

    /**
     * Execute after the suite.
     */

    context.suiteTeardown = function(name, fn){
      suites[0].afterAll(name, fn);
    };

    /**
     * Describe a "suite" with the given `title`
     * and callback `fn` containing nested suites
     * and/or tests.
     */

    context.suite = function(title, fn){
      var suite = Suite.create(suites[0], title);
      suite.file = file;
      suites.unshift(suite);
      fn.call(suite);
      suites.shift();
      return suite;
    };

    /**
     * Pending suite.
     */
    context.suite.skip = function(title, fn) {
      var suite = Suite.create(suites[0], title);
      suite.pending = true;
      suites.unshift(suite);
      fn.call(suite);
      suites.shift();
    };

    /**
     * Exclusive test-case.
     */

    context.suite.only = function(title, fn){
      var suite = context.suite(title, fn);
      mocha.grep(suite.fullTitle());
    };

    /**
     * Describe a specification or test-case
     * with the given `title` and callback `fn`
     * acting as a thunk.
     */

    context.test = function(title, fn){
      var suite = suites[0];
      if (suite.pending) fn = null;
      var test = new Test(title, fn);
      test.file = file;
      suite.addTest(test);
      return test;
    };

    /**
     * Exclusive test-case.
     */

    context.test.only = function(title, fn){
      var test = context.test(title, fn);
      var reString = '^' + escapeRe(test.fullTitle()) + '$';
      mocha.grep(new RegExp(reString));
    };

    /**
     * Pending test case.
     */

    context.test.skip = function(title){
      context.test(title);
    };
  });
};

}); // module: interfaces/tdd.js

require.register("mocha.js", function(module, exports, require){
/*!
 * mocha
 * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var path = require('browser/path')
  , escapeRe = require('browser/escape-string-regexp')
  , utils = require('./utils');

/**
 * Expose `Mocha`.
 */

exports = module.exports = Mocha;

/**
 * To require local UIs and reporters when running in node.
 */

if (typeof process !== 'undefined' && typeof process.cwd === 'function') {
  var join = path.join
    , cwd = process.cwd();
  module.paths.push(cwd, join(cwd, 'node_modules'));
}

/**
 * Expose internals.
 */

exports.utils = utils;
exports.interfaces = require('./interfaces');
exports.reporters = require('./reporters');
exports.Runnable = require('./runnable');
exports.Context = require('./context');
exports.Runner = require('./runner');
exports.Suite = require('./suite');
exports.Hook = require('./hook');
exports.Test = require('./test');

/**
 * Return image `name` path.
 *
 * @param {String} name
 * @return {String}
 * @api private
 */

function image(name) {
  return __dirname + '/../images/' + name + '.png';
}

/**
 * Setup mocha with `options`.
 *
 * Options:
 *
 *   - `ui` name "bdd", "tdd", "exports" etc
 *   - `reporter` reporter instance, defaults to `mocha.reporters.spec`
 *   - `globals` array of accepted globals
 *   - `timeout` timeout in milliseconds
 *   - `bail` bail on the first test failure
 *   - `slow` milliseconds to wait before considering a test slow
 *   - `ignoreLeaks` ignore global leaks
 *   - `grep` string or regexp to filter tests with
 *
 * @param {Object} options
 * @api public
 */

function Mocha(options) {
  options = options || {};
  this.files = [];
  this.options = options;
  this.grep(options.grep);
  this.suite = new exports.Suite('', new exports.Context);
  this.ui(options.ui);
  this.bail(options.bail);
  this.reporter(options.reporter);
  if (null != options.timeout) this.timeout(options.timeout);
  this.useColors(options.useColors)
  if (options.enableTimeouts !== null) this.enableTimeouts(options.enableTimeouts);
  if (options.slow) this.slow(options.slow);

  this.suite.on('pre-require', function (context) {
    exports.afterEach = context.afterEach || context.teardown;
    exports.after = context.after || context.suiteTeardown;
    exports.beforeEach = context.beforeEach || context.setup;
    exports.before = context.before || context.suiteSetup;
    exports.describe = context.describe || context.suite;
    exports.it = context.it || context.test;
    exports.setup = context.setup || context.beforeEach;
    exports.suiteSetup = context.suiteSetup || context.before;
    exports.suiteTeardown = context.suiteTeardown || context.after;
    exports.suite = context.suite || context.describe;
    exports.teardown = context.teardown || context.afterEach;
    exports.test = context.test || context.it;
  });
}

/**
 * Enable or disable bailing on the first failure.
 *
 * @param {Boolean} [bail]
 * @api public
 */

Mocha.prototype.bail = function(bail){
  if (0 == arguments.length) bail = true;
  this.suite.bail(bail);
  return this;
};

/**
 * Add test `file`.
 *
 * @param {String} file
 * @api public
 */

Mocha.prototype.addFile = function(file){
  this.files.push(file);
  return this;
};

/**
 * Set reporter to `reporter`, defaults to "spec".
 *
 * @param {String|Function} reporter name or constructor
 * @api public
 */

Mocha.prototype.reporter = function(reporter){
  if ('function' == typeof reporter) {
    this._reporter = reporter;
  } else {
    reporter = reporter || 'spec';
    var _reporter;
    try { _reporter = require('./reporters/' + reporter); } catch (err) {};
    if (!_reporter) try { _reporter = require(reporter); } catch (err) {};
    if (!_reporter && reporter === 'teamcity')
      console.warn('The Teamcity reporter was moved to a package named ' +
        'mocha-teamcity-reporter ' +
        '(https://npmjs.org/package/mocha-teamcity-reporter).');
    if (!_reporter) throw new Error('invalid reporter "' + reporter + '"');
    this._reporter = _reporter;
  }
  return this;
};

/**
 * Set test UI `name`, defaults to "bdd".
 *
 * @param {String} bdd
 * @api public
 */

Mocha.prototype.ui = function(name){
  name = name || 'bdd';
  this._ui = exports.interfaces[name];
  if (!this._ui) try { this._ui = require(name); } catch (err) {};
  if (!this._ui) throw new Error('invalid interface "' + name + '"');
  this._ui = this._ui(this.suite);
  return this;
};

/**
 * Load registered files.
 *
 * @api private
 */

Mocha.prototype.loadFiles = function(fn){
  var self = this;
  var suite = this.suite;
  var pending = this.files.length;
  this.files.forEach(function(file){
    file = path.resolve(file);
    suite.emit('pre-require', global, file, self);
    suite.emit('require', require(file), file, self);
    suite.emit('post-require', global, file, self);
    --pending || (fn && fn());
  });
};

/**
 * Enable growl support.
 *
 * @api private
 */

Mocha.prototype._growl = function(runner, reporter) {
  var notify = require('growl');

  runner.on('end', function(){
    var stats = reporter.stats;
    if (stats.failures) {
      var msg = stats.failures + ' of ' + runner.total + ' tests failed';
      notify(msg, { name: 'mocha', title: 'Failed', image: image('error') });
    } else {
      notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
          name: 'mocha'
        , title: 'Passed'
        , image: image('ok')
      });
    }
  });
};

/**
 * Add regexp to grep, if `re` is a string it is escaped.
 *
 * @param {RegExp|String} re
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.grep = function(re){
  this.options.grep = 'string' == typeof re
    ? new RegExp(escapeRe(re))
    : re;
  return this;
};

/**
 * Invert `.grep()` matches.
 *
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.invert = function(){
  this.options.invert = true;
  return this;
};

/**
 * Ignore global leaks.
 *
 * @param {Boolean} ignore
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.ignoreLeaks = function(ignore){
  this.options.ignoreLeaks = !!ignore;
  return this;
};

/**
 * Enable global leak checking.
 *
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.checkLeaks = function(){
  this.options.ignoreLeaks = false;
  return this;
};

/**
 * Enable growl support.
 *
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.growl = function(){
  this.options.growl = true;
  return this;
};

/**
 * Ignore `globals` array or string.
 *
 * @param {Array|String} globals
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.globals = function(globals){
  this.options.globals = (this.options.globals || []).concat(globals);
  return this;
};

/**
 * Emit color output.
 *
 * @param {Boolean} colors
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.useColors = function(colors){
  this.options.useColors = arguments.length && colors != undefined
    ? colors
    : true;
  return this;
};

/**
 * Use inline diffs rather than +/-.
 *
 * @param {Boolean} inlineDiffs
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.useInlineDiffs = function(inlineDiffs) {
  this.options.useInlineDiffs = arguments.length && inlineDiffs != undefined
  ? inlineDiffs
  : false;
  return this;
};

/**
 * Set the timeout in milliseconds.
 *
 * @param {Number} timeout
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.timeout = function(timeout){
  this.suite.timeout(timeout);
  return this;
};

/**
 * Set slowness threshold in milliseconds.
 *
 * @param {Number} slow
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.slow = function(slow){
  this.suite.slow(slow);
  return this;
};

/**
 * Enable timeouts.
 *
 * @param {Boolean} enabled
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.enableTimeouts = function(enabled) {
  this.suite.enableTimeouts(arguments.length && enabled !== undefined
    ? enabled
    : true);
  return this
};

/**
 * Makes all tests async (accepting a callback)
 *
 * @return {Mocha}
 * @api public
 */

Mocha.prototype.asyncOnly = function(){
  this.options.asyncOnly = true;
  return this;
};

/**
 * Disable syntax highlighting (in browser).
 * @returns {Mocha}
 * @api public
 */
Mocha.prototype.noHighlighting = function() {
  this.options.noHighlighting = true;
  return this;
};

/**
 * Run tests and invoke `fn()` when complete.
 *
 * @param {Function} fn
 * @return {Runner}
 * @api public
 */

Mocha.prototype.run = function(fn){
  if (this.files.length) this.loadFiles();
  var suite = this.suite;
  var options = this.options;
  options.files = this.files;
  var runner = new exports.Runner(suite);
  var reporter = new this._reporter(runner, options);
  runner.ignoreLeaks = false !== options.ignoreLeaks;
  runner.asyncOnly = options.asyncOnly;
  if (options.grep) runner.grep(options.grep, options.invert);
  if (options.globals) runner.globals(options.globals);
  if (options.growl) this._growl(runner, reporter);
  exports.reporters.Base.useColors = options.useColors;
  exports.reporters.Base.inlineDiffs = options.useInlineDiffs;
  return runner.run(fn);
};

}); // module: mocha.js

require.register("ms.js", function(module, exports, require){
/**
 * Helpers.
 */

var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;

/**
 * Parse or format the given `val`.
 *
 * Options:
 *
 *  - `long` verbose formatting [false]
 *
 * @param {String|Number} val
 * @param {Object} options
 * @return {String|Number}
 * @api public
 */

module.exports = function(val, options){
  options = options || {};
  if ('string' == typeof val) return parse(val);
  return options['long'] ? longFormat(val) : shortFormat(val);
};

/**
 * Parse the given `str` and return milliseconds.
 *
 * @param {String} str
 * @return {Number}
 * @api private
 */

function parse(str) {
  var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
  if (!match) return;
  var n = parseFloat(match[1]);
  var type = (match[2] || 'ms').toLowerCase();
  switch (type) {
    case 'years':
    case 'year':
    case 'y':
      return n * y;
    case 'days':
    case 'day':
    case 'd':
      return n * d;
    case 'hours':
    case 'hour':
    case 'h':
      return n * h;
    case 'minutes':
    case 'minute':
    case 'm':
      return n * m;
    case 'seconds':
    case 'second':
    case 's':
      return n * s;
    case 'ms':
      return n;
  }
}

/**
 * Short format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function shortFormat(ms) {
  if (ms >= d) return Math.round(ms / d) + 'd';
  if (ms >= h) return Math.round(ms / h) + 'h';
  if (ms >= m) return Math.round(ms / m) + 'm';
  if (ms >= s) return Math.round(ms / s) + 's';
  return ms + 'ms';
}

/**
 * Long format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function longFormat(ms) {
  return plural(ms, d, 'day')
    || plural(ms, h, 'hour')
    || plural(ms, m, 'minute')
    || plural(ms, s, 'second')
    || ms + ' ms';
}

/**
 * Pluralization helper.
 */

function plural(ms, n, name) {
  if (ms < n) return;
  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
  return Math.ceil(ms / n) + ' ' + name + 's';
}

}); // module: ms.js

require.register("reporters/base.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var tty = require('browser/tty')
  , diff = require('browser/diff')
  , ms = require('../ms')
  , utils = require('../utils');

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */

var Date = global.Date
  , setTimeout = global.setTimeout
  , setInterval = global.setInterval
  , clearTimeout = global.clearTimeout
  , clearInterval = global.clearInterval;

/**
 * Check if both stdio streams are associated with a tty.
 */

var isatty = tty.isatty(1) && tty.isatty(2);

/**
 * Expose `Base`.
 */

exports = module.exports = Base;

/**
 * Enable coloring by default.
 */

exports.useColors = isatty || (process.env.MOCHA_COLORS !== undefined);

/**
 * Inline diffs instead of +/-
 */

exports.inlineDiffs = false;

/**
 * Default color map.
 */

exports.colors = {
    'pass': 90
  , 'fail': 31
  , 'bright pass': 92
  , 'bright fail': 91
  , 'bright yellow': 93
  , 'pending': 36
  , 'suite': 0
  , 'error title': 0
  , 'error message': 31
  , 'error stack': 90
  , 'checkmark': 32
  , 'fast': 90
  , 'medium': 33
  , 'slow': 31
  , 'green': 32
  , 'light': 90
  , 'diff gutter': 90
  , 'diff added': 42
  , 'diff removed': 41
};

/**
 * Default symbol map.
 */

exports.symbols = {
  ok: '✓',
  err: '✖',
  dot: '․'
};

// With node.js on Windows: use symbols available in terminal default fonts
if ('win32' == process.platform) {
  exports.symbols.ok = '\u221A';
  exports.symbols.err = '\u00D7';
  exports.symbols.dot = '.';
}

/**
 * Color `str` with the given `type`,
 * allowing colors to be disabled,
 * as well as user-defined color
 * schemes.
 *
 * @param {String} type
 * @param {String} str
 * @return {String}
 * @api private
 */

var color = exports.color = function(type, str) {
  if (!exports.useColors) return str;
  return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
};

/**
 * Expose term window size, with some
 * defaults for when stderr is not a tty.
 */

exports.window = {
  width: isatty
    ? process.stdout.getWindowSize
      ? process.stdout.getWindowSize(1)[0]
      : tty.getWindowSize()[1]
    : 75
};

/**
 * Expose some basic cursor interactions
 * that are common among reporters.
 */

exports.cursor = {
  hide: function(){
    isatty && process.stdout.write('\u001b[?25l');
  },

  show: function(){
    isatty && process.stdout.write('\u001b[?25h');
  },

  deleteLine: function(){
    isatty && process.stdout.write('\u001b[2K');
  },

  beginningOfLine: function(){
    isatty && process.stdout.write('\u001b[0G');
  },

  CR: function(){
    if (isatty) {
      exports.cursor.deleteLine();
      exports.cursor.beginningOfLine();
    } else {
      process.stdout.write('\r');
    }
  }
};

/**
 * Outut the given `failures` as a list.
 *
 * @param {Array} failures
 * @api public
 */

exports.list = function(failures){
  console.error();
  failures.forEach(function(test, i){
    // format
    var fmt = color('error title', '  %s) %s:\n')
      + color('error message', '     %s')
      + color('error stack', '\n%s\n');

    // msg
    var err = test.err
      , message = err.message || ''
      , stack = err.stack || message
      , index = stack.indexOf(message) + message.length
      , msg = stack.slice(0, index)
      , actual = err.actual
      , expected = err.expected
      , escape = true;

    // uncaught
    if (err.uncaught) {
      msg = 'Uncaught ' + msg;
    }

    // explicitly show diff
    if (err.showDiff && sameType(actual, expected)) {
      escape = false;
      err.actual = actual = utils.stringify(actual);
      err.expected = expected = utils.stringify(expected);
    }

    // actual / expected diff
    if (err.showDiff && 'string' == typeof actual && 'string' == typeof expected) {
      fmt = color('error title', '  %s) %s:\n%s') + color('error stack', '\n%s\n');
      var match = message.match(/^([^:]+): expected/);
      msg = '\n      ' + color('error message', match ? match[1] : msg);

      if (exports.inlineDiffs) {
        msg += inlineDiff(err, escape);
      } else {
        msg += unifiedDiff(err, escape);
      }
    }

    // indent stack trace without msg
    stack = stack.slice(index ? index + 1 : index)
      .replace(/^/gm, '  ');

    console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
  });
};

/**
 * Initialize a new `Base` reporter.
 *
 * All other reporters generally
 * inherit from this reporter, providing
 * stats such as test duration, number
 * of tests passed / failed etc.
 *
 * @param {Runner} runner
 * @api public
 */

function Base(runner) {
  var self = this
    , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }
    , failures = this.failures = [];

  if (!runner) return;
  this.runner = runner;

  runner.stats = stats;

  runner.on('start', function(){
    stats.start = new Date;
  });

  runner.on('suite', function(suite){
    stats.suites = stats.suites || 0;
    suite.root || stats.suites++;
  });

  runner.on('test end', function(test){
    stats.tests = stats.tests || 0;
    stats.tests++;
  });

  runner.on('pass', function(test){
    stats.passes = stats.passes || 0;

    var medium = test.slow() / 2;
    test.speed = test.duration > test.slow()
      ? 'slow'
      : test.duration > medium
        ? 'medium'
        : 'fast';

    stats.passes++;
  });

  runner.on('fail', function(test, err){
    stats.failures = stats.failures || 0;
    stats.failures++;
    test.err = err;
    failures.push(test);
  });

  runner.on('end', function(){
    stats.end = new Date;
    stats.duration = new Date - stats.start;
  });

  runner.on('pending', function(){
    stats.pending++;
  });
}

/**
 * Output common epilogue used by many of
 * the bundled reporters.
 *
 * @api public
 */

Base.prototype.epilogue = function(){
  var stats = this.stats;
  var tests;
  var fmt;

  console.log();

  // passes
  fmt = color('bright pass', ' ')
    + color('green', ' %d passing')
    + color('light', ' (%s)');

  console.log(fmt,
    stats.passes || 0,
    ms(stats.duration));

  // pending
  if (stats.pending) {
    fmt = color('pending', ' ')
      + color('pending', ' %d pending');

    console.log(fmt, stats.pending);
  }

  // failures
  if (stats.failures) {
    fmt = color('fail', '  %d failing');

    console.error(fmt,
      stats.failures);

    Base.list(this.failures);
    console.error();
  }

  console.log();
};

/**
 * Pad the given `str` to `len`.
 *
 * @param {String} str
 * @param {String} len
 * @return {String}
 * @api private
 */

function pad(str, len) {
  str = String(str);
  return Array(len - str.length + 1).join(' ') + str;
}


/**
 * Returns an inline diff between 2 strings with coloured ANSI output
 *
 * @param {Error} Error with actual/expected
 * @return {String} Diff
 * @api private
 */

function inlineDiff(err, escape) {
  var msg = errorDiff(err, 'WordsWithSpace', escape);

  // linenos
  var lines = msg.split('\n');
  if (lines.length > 4) {
    var width = String(lines.length).length;
    msg = lines.map(function(str, i){
      return pad(++i, width) + ' |' + ' ' + str;
    }).join('\n');
  }

  // legend
  msg = '\n'
    + color('diff removed', 'actual')
    + ' '
    + color('diff added', 'expected')
    + '\n\n'
    + msg
    + '\n';

  // indent
  msg = msg.replace(/^/gm, '      ');
  return msg;
}

/**
 * Returns a unified diff between 2 strings
 *
 * @param {Error} Error with actual/expected
 * @return {String} Diff
 * @api private
 */

function unifiedDiff(err, escape) {
  var indent = '      ';
  function cleanUp(line) {
    if (escape) {
      line = escapeInvisibles(line);
    }
    if (line[0] === '+') return indent + colorLines('diff added', line);
    if (line[0] === '-') return indent + colorLines('diff removed', line);
    if (line.match(/\@\@/)) return null;
    if (line.match(/\\ No newline/)) return null;
    else return indent + line;
  }
  function notBlank(line) {
    return line != null;
  }
  msg = diff.createPatch('string', err.actual, err.expected);
  var lines = msg.split('\n').splice(4);
  return '\n      '
         + colorLines('diff added',   '+ expected') + ' '
         + colorLines('diff removed', '- actual')
         + '\n\n'
         + lines.map(cleanUp).filter(notBlank).join('\n');
}

/**
 * Return a character diff for `err`.
 *
 * @param {Error} err
 * @return {String}
 * @api private
 */

function errorDiff(err, type, escape) {
  var actual   = escape ? escapeInvisibles(err.actual)   : err.actual;
  var expected = escape ? escapeInvisibles(err.expected) : err.expected;
  return diff['diff' + type](actual, expected).map(function(str){
    if (str.added) return colorLines('diff added', str.value);
    if (str.removed) return colorLines('diff removed', str.value);
    return str.value;
  }).join('');
}

/**
 * Returns a string with all invisible characters in plain text
 *
 * @param {String} line
 * @return {String}
 * @api private
 */
function escapeInvisibles(line) {
    return line.replace(/\t/g, '<tab>')
               .replace(/\r/g, '<CR>')
               .replace(/\n/g, '<LF>\n');
}

/**
 * Color lines for `str`, using the color `name`.
 *
 * @param {String} name
 * @param {String} str
 * @return {String}
 * @api private
 */

function colorLines(name, str) {
  return str.split('\n').map(function(str){
    return color(name, str);
  }).join('\n');
}

/**
 * Check that a / b have the same type.
 *
 * @param {Object} a
 * @param {Object} b
 * @return {Boolean}
 * @api private
 */

function sameType(a, b) {
  a = Object.prototype.toString.call(a);
  b = Object.prototype.toString.call(b);
  return a == b;
}

}); // module: reporters/base.js

require.register("reporters/doc.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , utils = require('../utils');

/**
 * Expose `Doc`.
 */

exports = module.exports = Doc;

/**
 * Initialize a new `Doc` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function Doc(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , total = runner.total
    , indents = 2;

  function indent() {
    return Array(indents).join('  ');
  }

  runner.on('suite', function(suite){
    if (suite.root) return;
    ++indents;
    console.log('%s<section class="suite">', indent());
    ++indents;
    console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title));
    console.log('%s<dl>', indent());
  });

  runner.on('suite end', function(suite){
    if (suite.root) return;
    console.log('%s</dl>', indent());
    --indents;
    console.log('%s</section>', indent());
    --indents;
  });

  runner.on('pass', function(test){
    console.log('%s  <dt>%s</dt>', indent(), utils.escape(test.title));
    var code = utils.escape(utils.clean(test.fn.toString()));
    console.log('%s  <dd><pre><code>%s</code></pre></dd>', indent(), code);
  });

  runner.on('fail', function(test, err){
    console.log('%s  <dt class="error">%s</dt>', indent(), utils.escape(test.title));
    var code = utils.escape(utils.clean(test.fn.toString()));
    console.log('%s  <dd class="error"><pre><code>%s</code></pre></dd>', indent(), code);
    console.log('%s  <dd class="error">%s</dd>', indent(), utils.escape(err));
  });
}

}); // module: reporters/doc.js

require.register("reporters/dot.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , color = Base.color;

/**
 * Expose `Dot`.
 */

exports = module.exports = Dot;

/**
 * Initialize a new `Dot` matrix test reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function Dot(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , width = Base.window.width * .75 | 0
    , n = -1;

  runner.on('start', function(){
    process.stdout.write('\n  ');
  });

  runner.on('pending', function(test){
    if (++n % width == 0) process.stdout.write('\n  ');
    process.stdout.write(color('pending', Base.symbols.dot));
  });

  runner.on('pass', function(test){
    if (++n % width == 0) process.stdout.write('\n  ');
    if ('slow' == test.speed) {
      process.stdout.write(color('bright yellow', Base.symbols.dot));
    } else {
      process.stdout.write(color(test.speed, Base.symbols.dot));
    }
  });

  runner.on('fail', function(test, err){
    if (++n % width == 0) process.stdout.write('\n  ');
    process.stdout.write(color('fail', Base.symbols.dot));
  });

  runner.on('end', function(){
    console.log();
    self.epilogue();
  });
}

/**
 * Inherit from `Base.prototype`.
 */

function F(){};
F.prototype = Base.prototype;
Dot.prototype = new F;
Dot.prototype.constructor = Dot;


}); // module: reporters/dot.js

require.register("reporters/html-cov.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var JSONCov = require('./json-cov')
  , fs = require('browser/fs');

/**
 * Expose `HTMLCov`.
 */

exports = module.exports = HTMLCov;

/**
 * Initialize a new `JsCoverage` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function HTMLCov(runner) {
  var jade = require('jade')
    , file = __dirname + '/templates/coverage.jade'
    , str = fs.readFileSync(file, 'utf8')
    , fn = jade.compile(str, { filename: file })
    , self = this;

  JSONCov.call(this, runner, false);

  runner.on('end', function(){
    process.stdout.write(fn({
        cov: self.cov
      , coverageClass: coverageClass
    }));
  });
}

/**
 * Return coverage class for `n`.
 *
 * @return {String}
 * @api private
 */

function coverageClass(n) {
  if (n >= 75) return 'high';
  if (n >= 50) return 'medium';
  if (n >= 25) return 'low';
  return 'terrible';
}

}); // module: reporters/html-cov.js

require.register("reporters/html.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , utils = require('../utils')
  , Progress = require('../browser/progress')
  , escape = utils.escape;

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */

var Date = global.Date
  , setTimeout = global.setTimeout
  , setInterval = global.setInterval
  , clearTimeout = global.clearTimeout
  , clearInterval = global.clearInterval;

/**
 * Expose `HTML`.
 */

exports = module.exports = HTML;

/**
 * Stats template.
 */

var statsTemplate = '<ul id="mocha-stats">'
  + '<li class="progress"><canvas width="40" height="40"></canvas></li>'
  + '<li class="passes"><a href="#">passes:</a> <em>0</em></li>'
  + '<li class="failures"><a href="#">failures:</a> <em>0</em></li>'
  + '<li class="duration">duration: <em>0</em>s</li>'
  + '</ul>';

/**
 * Initialize a new `HTML` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function HTML(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , total = runner.total
    , stat = fragment(statsTemplate)
    , items = stat.getElementsByTagName('li')
    , passes = items[1].getElementsByTagName('em')[0]
    , passesLink = items[1].getElementsByTagName('a')[0]
    , failures = items[2].getElementsByTagName('em')[0]
    , failuresLink = items[2].getElementsByTagName('a')[0]
    , duration = items[3].getElementsByTagName('em')[0]
    , canvas = stat.getElementsByTagName('canvas')[0]
    , report = fragment('<ul id="mocha-report"></ul>')
    , stack = [report]
    , progress
    , ctx
    , root = document.getElementById('mocha');

  if (canvas.getContext) {
    var ratio = window.devicePixelRatio || 1;
    canvas.style.width = canvas.width;
    canvas.style.height = canvas.height;
    canvas.width *= ratio;
    canvas.height *= ratio;
    ctx = canvas.getContext('2d');
    ctx.scale(ratio, ratio);
    progress = new Progress;
  }

  if (!root) return error('#mocha div missing, add it to your document');

  // pass toggle
  on(passesLink, 'click', function(){
    unhide();
    var name = /pass/.test(report.className) ? '' : ' pass';
    report.className = report.className.replace(/fail|pass/g, '') + name;
    if (report.className.trim()) hideSuitesWithout('test pass');
  });

  // failure toggle
  on(failuresLink, 'click', function(){
    unhide();
    var name = /fail/.test(report.className) ? '' : ' fail';
    report.className = report.className.replace(/fail|pass/g, '') + name;
    if (report.className.trim()) hideSuitesWithout('test fail');
  });

  root.appendChild(stat);
  root.appendChild(report);

  if (progress) progress.size(40);

  runner.on('suite', function(suite){
    if (suite.root) return;

    // suite
    var url = self.suiteURL(suite);
    var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, escape(suite.title));

    // container
    stack[0].appendChild(el);
    stack.unshift(document.createElement('ul'));
    el.appendChild(stack[0]);
  });

  runner.on('suite end', function(suite){
    if (suite.root) return;
    stack.shift();
  });

  runner.on('fail', function(test, err){
    if ('hook' == test.type) runner.emit('test end', test);
  });

  runner.on('test end', function(test){
    // TODO: add to stats
    var percent = stats.tests / this.total * 100 | 0;
    if (progress) progress.update(percent).draw(ctx);

    // update stats
    var ms = new Date - stats.start;
    text(passes, stats.passes);
    text(failures, stats.failures);
    text(duration, (ms / 1000).toFixed(2));

    // test
    if ('passed' == test.state) {
      var url = self.testURL(test);
      var el = fragment('<li class="test pass %e"><h2>%e<span class="duration">%ems</span> <a href="%s" class="replay">‣</a></h2></li>', test.speed, test.title, test.duration, url);
    } else if (test.pending) {
      var el = fragment('<li class="test pass pending"><h2>%e</h2></li>', test.title);
    } else {
      var el = fragment('<li class="test fail"><h2>%e <a href="?grep=%e" class="replay">‣</a></h2></li>', test.title, encodeURIComponent(test.fullTitle()));
      var str = test.err.stack || test.err.toString();

      // FF / Opera do not add the message
      if (!~str.indexOf(test.err.message)) {
        str = test.err.message + '\n' + str;
      }

      // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
      // check for the result of the stringifying.
      if ('[object Error]' == str) str = test.err.message;

      // Safari doesn't give you a stack. Let's at least provide a source line.
      if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
        str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
      }

      el.appendChild(fragment('<pre class="error">%e</pre>', str));
    }

    // toggle code
    // TODO: defer
    if (!test.pending) {
      var h2 = el.getElementsByTagName('h2')[0];

      on(h2, 'click', function(){
        pre.style.display = 'none' == pre.style.display
          ? 'block'
          : 'none';
      });

      var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString()));
      el.appendChild(pre);
      pre.style.display = 'none';
    }

    // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.
    if (stack[0]) stack[0].appendChild(el);
  });
}

/**
 * Makes a URL, preserving querystring ("search") parameters.
 * @param {string} s
 * @returns {string} your new URL
 */
var makeUrl = function makeUrl(s) {
  var search = window.location.search;
  return (search ? search + '&' : '?' ) + 'grep=' + encodeURIComponent(s);
};

/**
 * Provide suite URL
 *
 * @param {Object} [suite]
 */
HTML.prototype.suiteURL = function(suite){
  return makeUrl(suite.fullTitle());
};

/**
 * Provide test URL
 *
 * @param {Object} [test]
 */

HTML.prototype.testURL = function(test){
  return makeUrl(test.fullTitle());
};

/**
 * Display error `msg`.
 */

function error(msg) {
  document.body.appendChild(fragment('<div id="mocha-error">%s</div>', msg));
}

/**
 * Return a DOM fragment from `html`.
 */

function fragment(html) {
  var args = arguments
    , div = document.createElement('div')
    , i = 1;

  div.innerHTML = html.replace(/%([se])/g, function(_, type){
    switch (type) {
      case 's': return String(args[i++]);
      case 'e': return escape(args[i++]);
    }
  });

  return div.firstChild;
}

/**
 * Check for suites that do not have elements
 * with `classname`, and hide them.
 */

function hideSuitesWithout(classname) {
  var suites = document.getElementsByClassName('suite');
  for (var i = 0; i < suites.length; i++) {
    var els = suites[i].getElementsByClassName(classname);
    if (0 == els.length) suites[i].className += ' hidden';
  }
}

/**
 * Unhide .hidden suites.
 */

function unhide() {
  var els = document.getElementsByClassName('suite hidden');
  for (var i = 0; i < els.length; ++i) {
    els[i].className = els[i].className.replace('suite hidden', 'suite');
  }
}

/**
 * Set `el` text to `str`.
 */

function text(el, str) {
  if (el.textContent) {
    el.textContent = str;
  } else {
    el.innerText = str;
  }
}

/**
 * Listen on `event` with callback `fn`.
 */

function on(el, event, fn) {
  if (el.addEventListener) {
    el.addEventListener(event, fn, false);
  } else {
    el.attachEvent('on' + event, fn);
  }
}

}); // module: reporters/html.js

require.register("reporters/index.js", function(module, exports, require){
exports.Base = require('./base');
exports.Dot = require('./dot');
exports.Doc = require('./doc');
exports.TAP = require('./tap');
exports.JSON = require('./json');
exports.HTML = require('./html');
exports.List = require('./list');
exports.Min = require('./min');
exports.Spec = require('./spec');
exports.Nyan = require('./nyan');
exports.XUnit = require('./xunit');
exports.Markdown = require('./markdown');
exports.Progress = require('./progress');
exports.Landing = require('./landing');
exports.JSONCov = require('./json-cov');
exports.HTMLCov = require('./html-cov');
exports.JSONStream = require('./json-stream');

}); // module: reporters/index.js

require.register("reporters/json-cov.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base');

/**
 * Expose `JSONCov`.
 */

exports = module.exports = JSONCov;

/**
 * Initialize a new `JsCoverage` reporter.
 *
 * @param {Runner} runner
 * @param {Boolean} output
 * @api public
 */

function JSONCov(runner, output) {
  var self = this
    , output = 1 == arguments.length ? true : output;

  Base.call(this, runner);

  var tests = []
    , failures = []
    , passes = [];

  runner.on('test end', function(test){
    tests.push(test);
  });

  runner.on('pass', function(test){
    passes.push(test);
  });

  runner.on('fail', function(test){
    failures.push(test);
  });

  runner.on('end', function(){
    var cov = global._$jscoverage || {};
    var result = self.cov = map(cov);
    result.stats = self.stats;
    result.tests = tests.map(clean);
    result.failures = failures.map(clean);
    result.passes = passes.map(clean);
    if (!output) return;
    process.stdout.write(JSON.stringify(result, null, 2 ));
  });
}

/**
 * Map jscoverage data to a JSON structure
 * suitable for reporting.
 *
 * @param {Object} cov
 * @return {Object}
 * @api private
 */

function map(cov) {
  var ret = {
      instrumentation: 'node-jscoverage'
    , sloc: 0
    , hits: 0
    , misses: 0
    , coverage: 0
    , files: []
  };

  for (var filename in cov) {
    var data = coverage(filename, cov[filename]);
    ret.files.push(data);
    ret.hits += data.hits;
    ret.misses += data.misses;
    ret.sloc += data.sloc;
  }

  ret.files.sort(function(a, b) {
    return a.filename.localeCompare(b.filename);
  });

  if (ret.sloc > 0) {
    ret.coverage = (ret.hits / ret.sloc) * 100;
  }

  return ret;
}

/**
 * Map jscoverage data for a single source file
 * to a JSON structure suitable for reporting.
 *
 * @param {String} filename name of the source file
 * @param {Object} data jscoverage coverage data
 * @return {Object}
 * @api private
 */

function coverage(filename, data) {
  var ret = {
    filename: filename,
    coverage: 0,
    hits: 0,
    misses: 0,
    sloc: 0,
    source: {}
  };

  data.source.forEach(function(line, num){
    num++;

    if (data[num] === 0) {
      ret.misses++;
      ret.sloc++;
    } else if (data[num] !== undefined) {
      ret.hits++;
      ret.sloc++;
    }

    ret.source[num] = {
        source: line
      , coverage: data[num] === undefined
        ? ''
        : data[num]
    };
  });

  ret.coverage = ret.hits / ret.sloc * 100;

  return ret;
}

/**
 * Return a plain-object representation of `test`
 * free of cyclic properties etc.
 *
 * @param {Object} test
 * @return {Object}
 * @api private
 */

function clean(test) {
  return {
      title: test.title
    , fullTitle: test.fullTitle()
    , duration: test.duration
  }
}

}); // module: reporters/json-cov.js

require.register("reporters/json-stream.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , color = Base.color;

/**
 * Expose `List`.
 */

exports = module.exports = List;

/**
 * Initialize a new `List` test reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function List(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , total = runner.total;

  runner.on('start', function(){
    console.log(JSON.stringify(['start', { total: total }]));
  });

  runner.on('pass', function(test){
    console.log(JSON.stringify(['pass', clean(test)]));
  });

  runner.on('fail', function(test, err){
    test = clean(test);
    test.err = err.message;
    console.log(JSON.stringify(['fail', test]));
  });

  runner.on('end', function(){
    process.stdout.write(JSON.stringify(['end', self.stats]));
  });
}

/**
 * Return a plain-object representation of `test`
 * free of cyclic properties etc.
 *
 * @param {Object} test
 * @return {Object}
 * @api private
 */

function clean(test) {
  return {
      title: test.title
    , fullTitle: test.fullTitle()
    , duration: test.duration
  }
}

}); // module: reporters/json-stream.js

require.register("reporters/json.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , cursor = Base.cursor
  , color = Base.color;

/**
 * Expose `JSON`.
 */

exports = module.exports = JSONReporter;

/**
 * Initialize a new `JSON` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function JSONReporter(runner) {
  var self = this;
  Base.call(this, runner);

  var tests = []
    , pending = []
    , failures = []
    , passes = [];

  runner.on('test end', function(test){
    tests.push(test);
  });

  runner.on('pass', function(test){
    passes.push(test);
  });

  runner.on('fail', function(test){
    failures.push(test);
  });

  runner.on('pending', function(test){
    pending.push(test);
  });

  runner.on('end', function(){
    var obj = {
      stats: self.stats,
      tests: tests.map(clean),
      pending: pending.map(clean),
      failures: failures.map(clean),
      passes: passes.map(clean)
    };

    runner.testResults = obj;

    process.stdout.write(JSON.stringify(obj, null, 2));
  });
}

/**
 * Return a plain-object representation of `test`
 * free of cyclic properties etc.
 *
 * @param {Object} test
 * @return {Object}
 * @api private
 */

function clean(test) {
  return {
    title: test.title,
    fullTitle: test.fullTitle(),
    duration: test.duration,
    err: errorJSON(test.err || {})
  }
}

/**
 * Transform `error` into a JSON object.
 * @param {Error} err
 * @return {Object}
 */

function errorJSON(err) {
  var res = {};
  Object.getOwnPropertyNames(err).forEach(function(key) {
    res[key] = err[key];
  }, err);
  return res;
}

}); // module: reporters/json.js

require.register("reporters/landing.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , cursor = Base.cursor
  , color = Base.color;

/**
 * Expose `Landing`.
 */

exports = module.exports = Landing;

/**
 * Airplane color.
 */

Base.colors.plane = 0;

/**
 * Airplane crash color.
 */

Base.colors['plane crash'] = 31;

/**
 * Runway color.
 */

Base.colors.runway = 90;

/**
 * Initialize a new `Landing` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function Landing(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , width = Base.window.width * .75 | 0
    , total = runner.total
    , stream = process.stdout
    , plane = color('plane', '✈')
    , crashed = -1
    , n = 0;

  function runway() {
    var buf = Array(width).join('-');
    return '  ' + color('runway', buf);
  }

  runner.on('start', function(){
    stream.write('\n\n\n  ');
    cursor.hide();
  });

  runner.on('test end', function(test){
    // check if the plane crashed
    var col = -1 == crashed
      ? width * ++n / total | 0
      : crashed;

    // show the crash
    if ('failed' == test.state) {
      plane = color('plane crash', '✈');
      crashed = col;
    }

    // render landing strip
    stream.write('\u001b['+(width+1)+'D\u001b[2A');
    stream.write(runway());
    stream.write('\n  ');
    stream.write(color('runway', Array(col).join('⋅')));
    stream.write(plane)
    stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
    stream.write(runway());
    stream.write('\u001b[0m');
  });

  runner.on('end', function(){
    cursor.show();
    console.log();
    self.epilogue();
  });
}

/**
 * Inherit from `Base.prototype`.
 */

function F(){};
F.prototype = Base.prototype;
Landing.prototype = new F;
Landing.prototype.constructor = Landing;


}); // module: reporters/landing.js

require.register("reporters/list.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , cursor = Base.cursor
  , color = Base.color;

/**
 * Expose `List`.
 */

exports = module.exports = List;

/**
 * Initialize a new `List` test reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function List(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , n = 0;

  runner.on('start', function(){
    console.log();
  });

  runner.on('test', function(test){
    process.stdout.write(color('pass', '    ' + test.fullTitle() + ': '));
  });

  runner.on('pending', function(test){
    var fmt = color('checkmark', '  -')
      + color('pending', ' %s');
    console.log(fmt, test.fullTitle());
  });

  runner.on('pass', function(test){
    var fmt = color('checkmark', '  '+Base.symbols.dot)
      + color('pass', ' %s: ')
      + color(test.speed, '%dms');
    cursor.CR();
    console.log(fmt, test.fullTitle(), test.duration);
  });

  runner.on('fail', function(test, err){
    cursor.CR();
    console.log(color('fail', '  %d) %s'), ++n, test.fullTitle());
  });

  runner.on('end', self.epilogue.bind(self));
}

/**
 * Inherit from `Base.prototype`.
 */

function F(){};
F.prototype = Base.prototype;
List.prototype = new F;
List.prototype.constructor = List;


}); // module: reporters/list.js

require.register("reporters/markdown.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , utils = require('../utils');

/**
 * Expose `Markdown`.
 */

exports = module.exports = Markdown;

/**
 * Initialize a new `Markdown` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function Markdown(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , level = 0
    , buf = '';

  function title(str) {
    return Array(level).join('#') + ' ' + str;
  }

  function indent() {
    return Array(level).join('  ');
  }

  function mapTOC(suite, obj) {
    var ret = obj;
    obj = obj[suite.title] = obj[suite.title] || { suite: suite };
    suite.suites.forEach(function(suite){
      mapTOC(suite, obj);
    });
    return ret;
  }

  function stringifyTOC(obj, level) {
    ++level;
    var buf = '';
    var link;
    for (var key in obj) {
      if ('suite' == key) continue;
      if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
      if (key) buf += Array(level).join('  ') + link;
      buf += stringifyTOC(obj[key], level);
    }
    --level;
    return buf;
  }

  function generateTOC(suite) {
    var obj = mapTOC(suite, {});
    return stringifyTOC(obj, 0);
  }

  generateTOC(runner.suite);

  runner.on('suite', function(suite){
    ++level;
    var slug = utils.slug(suite.fullTitle());
    buf += '<a name="' + slug + '"></a>' + '\n';
    buf += title(suite.title) + '\n';
  });

  runner.on('suite end', function(suite){
    --level;
  });

  runner.on('pass', function(test){
    var code = utils.clean(test.fn.toString());
    buf += test.title + '.\n';
    buf += '\n```js\n';
    buf += code + '\n';
    buf += '```\n\n';
  });

  runner.on('end', function(){
    process.stdout.write('# TOC\n');
    process.stdout.write(generateTOC(runner.suite));
    process.stdout.write(buf);
  });
}

}); // module: reporters/markdown.js

require.register("reporters/min.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base');

/**
 * Expose `Min`.
 */

exports = module.exports = Min;

/**
 * Initialize a new `Min` minimal test reporter (best used with --watch).
 *
 * @param {Runner} runner
 * @api public
 */

function Min(runner) {
  Base.call(this, runner);

  runner.on('start', function(){
    // clear screen
    process.stdout.write('\u001b[2J');
    // set cursor position
    process.stdout.write('\u001b[1;3H');
  });

  runner.on('end', this.epilogue.bind(this));
}

/**
 * Inherit from `Base.prototype`.
 */

function F(){};
F.prototype = Base.prototype;
Min.prototype = new F;
Min.prototype.constructor = Min;


}); // module: reporters/min.js

require.register("reporters/nyan.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , color = Base.color;

/**
 * Expose `Dot`.
 */

exports = module.exports = NyanCat;

/**
 * Initialize a new `Dot` matrix test reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function NyanCat(runner) {
  Base.call(this, runner);
  var self = this
    , stats = this.stats
    , width = Base.window.width * .75 | 0
    , rainbowColors = this.rainbowColors = self.generateColors()
    , colorIndex = this.colorIndex = 0
    , numerOfLines = this.numberOfLines = 4
    , trajectories = this.trajectories = [[], [], [], []]
    , nyanCatWidth = this.nyanCatWidth = 11
    , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth)
    , scoreboardWidth = this.scoreboardWidth = 5
    , tick = this.tick = 0
    , n = 0;

  runner.on('start', function(){
    Base.cursor.hide();
    self.draw();
  });

  runner.on('pending', function(test){
    self.draw();
  });

  runner.on('pass', function(test){
    self.draw();
  });

  runner.on('fail', function(test, err){
    self.draw();
  });

  runner.on('end', function(){
    Base.cursor.show();
    for (var i = 0; i < self.numberOfLines; i++) write('\n');
    self.epilogue();
  });
}

/**
 * Draw the nyan cat
 *
 * @api private
 */

NyanCat.prototype.draw = function(){
  this.appendRainbow();
  this.drawScoreboard();
  this.drawRainbow();
  this.drawNyanCat();
  this.tick = !this.tick;
};

/**
 * Draw the "scoreboard" showing the number
 * of passes, failures and pending tests.
 *
 * @api private
 */

NyanCat.prototype.drawScoreboard = function(){
  var stats = this.stats;
  var colors = Base.colors;

  function draw(color, n) {
    write(' ');
    write('\u001b[' + color + 'm' + n + '\u001b[0m');
    write('\n');
  }

  draw(colors.green, stats.passes);
  draw(colors.fail, stats.failures);
  draw(colors.pending, stats.pending);
  write('\n');

  this.cursorUp(this.numberOfLines);
};

/**
 * Append the rainbow.
 *
 * @api private
 */

NyanCat.prototype.appendRainbow = function(){
  var segment = this.tick ? '_' : '-';
  var rainbowified = this.rainbowify(segment);

  for (var index = 0; index < this.numberOfLines; index++) {
    var trajectory = this.trajectories[index];
    if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift();
    trajectory.push(rainbowified);
  }
};

/**
 * Draw the rainbow.
 *
 * @api private
 */

NyanCat.prototype.drawRainbow = function(){
  var self = this;

  this.trajectories.forEach(function(line, index) {
    write('\u001b[' + self.scoreboardWidth + 'C');
    write(line.join(''));
    write('\n');
  });

  this.cursorUp(this.numberOfLines);
};

/**
 * Draw the nyan cat
 *
 * @api private
 */

NyanCat.prototype.drawNyanCat = function() {
  var self = this;
  var startWidth = this.scoreboardWidth + this.trajectories[0].length;
  var color = '\u001b[' + startWidth + 'C';
  var padding = '';

  write(color);
  write('_,------,');
  write('\n');

  write(color);
  padding = self.tick ? '  ' : '   ';
  write('_|' + padding + '/\\_/\\ ');
  write('\n');

  write(color);
  padding = self.tick ? '_' : '__';
  var tail = self.tick ? '~' : '^';
  var face;
  write(tail + '|' + padding + this.face() + ' ');
  write('\n');

  write(color);
  padding = self.tick ? ' ' : '  ';
  write(padding + '""  "" ');
  write('\n');

  this.cursorUp(this.numberOfLines);
};

/**
 * Draw nyan cat face.
 *
 * @return {String}
 * @api private
 */

NyanCat.prototype.face = function() {
  var stats = this.stats;
  if (stats.failures) {
    return '( x .x)';
  } else if (stats.pending) {
    return '( o .o)';
  } else if(stats.passes) {
    return '( ^ .^)';
  } else {
    return '( - .-)';
  }
};

/**
 * Move cursor up `n`.
 *
 * @param {Number} n
 * @api private
 */

NyanCat.prototype.cursorUp = function(n) {
  write('\u001b[' + n + 'A');
};

/**
 * Move cursor down `n`.
 *
 * @param {Number} n
 * @api private
 */

NyanCat.prototype.cursorDown = function(n) {
  write('\u001b[' + n + 'B');
};

/**
 * Generate rainbow colors.
 *
 * @return {Array}
 * @api private
 */

NyanCat.prototype.generateColors = function(){
  var colors = [];

  for (var i = 0; i < (6 * 7); i++) {
    var pi3 = Math.floor(Math.PI / 3);
    var n = (i * (1.0 / 6));
    var r = Math.floor(3 * Math.sin(n) + 3);
    var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);
    var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);
    colors.push(36 * r + 6 * g + b + 16);
  }

  return colors;
};

/**
 * Apply rainbow to the given `str`.
 *
 * @param {String} str
 * @return {String}
 * @api private
 */

NyanCat.prototype.rainbowify = function(str){
  var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];
  this.colorIndex += 1;
  return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m';
};

/**
 * Stdout helper.
 */

function write(string) {
  process.stdout.write(string);
}

/**
 * Inherit from `Base.prototype`.
 */

function F(){};
F.prototype = Base.prototype;
NyanCat.prototype = new F;
NyanCat.prototype.constructor = NyanCat;


}); // module: reporters/nyan.js

require.register("reporters/progress.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , cursor = Base.cursor
  , color = Base.color;

/**
 * Expose `Progress`.
 */

exports = module.exports = Progress;

/**
 * General progress bar color.
 */

Base.colors.progress = 90;

/**
 * Initialize a new `Progress` bar test reporter.
 *
 * @param {Runner} runner
 * @param {Object} options
 * @api public
 */

function Progress(runner, options) {
  Base.call(this, runner);

  var self = this
    , options = options || {}
    , stats = this.stats
    , width = Base.window.width * .50 | 0
    , total = runner.total
    , complete = 0
    , max = Math.max
    , lastN = -1;

  // default chars
  options.open = options.open || '[';
  options.complete = options.complete || '▬';
  options.incomplete = options.incomplete || Base.symbols.dot;
  options.close = options.close || ']';
  options.verbose = false;

  // tests started
  runner.on('start', function(){
    console.log();
    cursor.hide();
  });

  // tests complete
  runner.on('test end', function(){
    complete++;
    var incomplete = total - complete
      , percent = complete / total
      , n = width * percent | 0
      , i = width - n;

    if (lastN === n && !options.verbose) {
      // Don't re-render the line if it hasn't changed
      return;
    }
    lastN = n;

    cursor.CR();
    process.stdout.write('\u001b[J');
    process.stdout.write(color('progress', '  ' + options.open));
    process.stdout.write(Array(n).join(options.complete));
    process.stdout.write(Array(i).join(options.incomplete));
    process.stdout.write(color('progress', options.close));
    if (options.verbose) {
      process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
    }
  });

  // tests are complete, output some stats
  // and the failures if any
  runner.on('end', function(){
    cursor.show();
    console.log();
    self.epilogue();
  });
}

/**
 * Inherit from `Base.prototype`.
 */

function F(){};
F.prototype = Base.prototype;
Progress.prototype = new F;
Progress.prototype.constructor = Progress;


}); // module: reporters/progress.js

require.register("reporters/spec.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , cursor = Base.cursor
  , color = Base.color;

/**
 * Expose `Spec`.
 */

exports = module.exports = Spec;

/**
 * Initialize a new `Spec` test reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function Spec(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , indents = 0
    , n = 0;

  function indent() {
    return Array(indents).join('  ')
  }

  runner.on('start', function(){
    console.log();
  });

  runner.on('suite', function(suite){
    ++indents;
    console.log(color('suite', '%s%s'), indent(), suite.title);
  });

  runner.on('suite end', function(suite){
    --indents;
    if (1 == indents) console.log();
  });

  runner.on('pending', function(test){
    var fmt = indent() + color('pending', '  - %s');
    console.log(fmt, test.title);
  });

  runner.on('pass', function(test){
    if ('fast' == test.speed) {
      var fmt = indent()
        + color('checkmark', '  ' + Base.symbols.ok)
        + color('pass', ' %s ');
      cursor.CR();
      console.log(fmt, test.title);
    } else {
      var fmt = indent()
        + color('checkmark', '  ' + Base.symbols.ok)
        + color('pass', ' %s ')
        + color(test.speed, '(%dms)');
      cursor.CR();
      console.log(fmt, test.title, test.duration);
    }
  });

  runner.on('fail', function(test, err){
    cursor.CR();
    console.log(indent() + color('fail', '  %d) %s'), ++n, test.title);
  });

  runner.on('end', self.epilogue.bind(self));
}

/**
 * Inherit from `Base.prototype`.
 */

function F(){};
F.prototype = Base.prototype;
Spec.prototype = new F;
Spec.prototype.constructor = Spec;


}); // module: reporters/spec.js

require.register("reporters/tap.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , cursor = Base.cursor
  , color = Base.color;

/**
 * Expose `TAP`.
 */

exports = module.exports = TAP;

/**
 * Initialize a new `TAP` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function TAP(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , n = 1
    , passes = 0
    , failures = 0;

  runner.on('start', function(){
    var total = runner.grepTotal(runner.suite);
    console.log('%d..%d', 1, total);
  });

  runner.on('test end', function(){
    ++n;
  });

  runner.on('pending', function(test){
    console.log('ok %d %s # SKIP -', n, title(test));
  });

  runner.on('pass', function(test){
    passes++;
    console.log('ok %d %s', n, title(test));
  });

  runner.on('fail', function(test, err){
    failures++;
    console.log('not ok %d %s', n, title(test));
    if (err.stack) console.log(err.stack.replace(/^/gm, '  '));
  });

  runner.on('end', function(){
    console.log('# tests ' + (passes + failures));
    console.log('# pass ' + passes);
    console.log('# fail ' + failures);
  });
}

/**
 * Return a TAP-safe title of `test`
 *
 * @param {Object} test
 * @return {String}
 * @api private
 */

function title(test) {
  return test.fullTitle().replace(/#/g, '');
}

}); // module: reporters/tap.js

require.register("reporters/xunit.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Base = require('./base')
  , utils = require('../utils')
  , escape = utils.escape;

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */

var Date = global.Date
  , setTimeout = global.setTimeout
  , setInterval = global.setInterval
  , clearTimeout = global.clearTimeout
  , clearInterval = global.clearInterval;

/**
 * Expose `XUnit`.
 */

exports = module.exports = XUnit;

/**
 * Initialize a new `XUnit` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function XUnit(runner) {
  Base.call(this, runner);
  var stats = this.stats
    , tests = []
    , self = this;

  runner.on('pending', function(test){
    tests.push(test);
  });

  runner.on('pass', function(test){
    tests.push(test);
  });

  runner.on('fail', function(test){
    tests.push(test);
  });

  runner.on('end', function(){
    console.log(tag('testsuite', {
        name: 'Mocha Tests'
      , tests: stats.tests
      , failures: stats.failures
      , errors: stats.failures
      , skipped: stats.tests - stats.failures - stats.passes
      , timestamp: (new Date).toUTCString()
      , time: (stats.duration / 1000) || 0
    }, false));

    tests.forEach(test);
    console.log('</testsuite>');
  });
}

/**
 * Inherit from `Base.prototype`.
 */

function F(){};
F.prototype = Base.prototype;
XUnit.prototype = new F;
XUnit.prototype.constructor = XUnit;


/**
 * Output tag for the given `test.`
 */

function test(test) {
  var attrs = {
      classname: test.parent.fullTitle()
    , name: test.title
    , time: (test.duration / 1000) || 0
  };

  if ('failed' == test.state) {
    var err = test.err;
    console.log(tag('testcase', attrs, false, tag('failure', {}, false, cdata(escape(err.message) + "\n" + err.stack))));
  } else if (test.pending) {
    console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
  } else {
    console.log(tag('testcase', attrs, true) );
  }
}

/**
 * HTML tag helper.
 */

function tag(name, attrs, close, content) {
  var end = close ? '/>' : '>'
    , pairs = []
    , tag;

  for (var key in attrs) {
    pairs.push(key + '="' + escape(attrs[key]) + '"');
  }

  tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
  if (content) tag += content + '</' + name + end;
  return tag;
}

/**
 * Return cdata escaped CDATA `str`.
 */

function cdata(str) {
  return '<![CDATA[' + escape(str) + ']]>';
}

}); // module: reporters/xunit.js

require.register("runnable.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var EventEmitter = require('browser/events').EventEmitter
  , debug = require('browser/debug')('mocha:runnable')
  , milliseconds = require('./ms');

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */

var Date = global.Date
  , setTimeout = global.setTimeout
  , setInterval = global.setInterval
  , clearTimeout = global.clearTimeout
  , clearInterval = global.clearInterval;

/**
 * Object#toString().
 */

var toString = Object.prototype.toString;

/**
 * Expose `Runnable`.
 */

module.exports = Runnable;

/**
 * Initialize a new `Runnable` with the given `title` and callback `fn`.
 *
 * @param {String} title
 * @param {Function} fn
 * @api private
 */

function Runnable(title, fn) {
  this.title = title;
  this.fn = fn;
  this.async = fn && fn.length;
  this.sync = ! this.async;
  this._timeout = 2000;
  this._slow = 75;
  this._enableTimeouts = true;
  this.timedOut = false;
  this._trace = new Error('done() called multiple times')
}

/**
 * Inherit from `EventEmitter.prototype`.
 */

function F(){};
F.prototype = EventEmitter.prototype;
Runnable.prototype = new F;
Runnable.prototype.constructor = Runnable;


/**
 * Set & get timeout `ms`.
 *
 * @param {Number|String} ms
 * @return {Runnable|Number} ms or self
 * @api private
 */

Runnable.prototype.timeout = function(ms){
  if (0 == arguments.length) return this._timeout;
  if (ms === 0) this._enableTimeouts = false;
  if ('string' == typeof ms) ms = milliseconds(ms);
  debug('timeout %d', ms);
  this._timeout = ms;
  if (this.timer) this.resetTimeout();
  return this;
};

/**
 * Set & get slow `ms`.
 *
 * @param {Number|String} ms
 * @return {Runnable|Number} ms or self
 * @api private
 */

Runnable.prototype.slow = function(ms){
  if (0 === arguments.length) return this._slow;
  if ('string' == typeof ms) ms = milliseconds(ms);
  debug('timeout %d', ms);
  this._slow = ms;
  return this;
};

/**
 * Set and & get timeout `enabled`.
 *
 * @param {Boolean} enabled
 * @return {Runnable|Boolean} enabled or self
 * @api private
 */

Runnable.prototype.enableTimeouts = function(enabled){
  if (arguments.length === 0) return this._enableTimeouts;
  debug('enableTimeouts %s', enabled);
  this._enableTimeouts = enabled;
  return this;
};

/**
 * Return the full title generated by recursively
 * concatenating the parent's full title.
 *
 * @return {String}
 * @api public
 */

Runnable.prototype.fullTitle = function(){
  return this.parent.fullTitle() + ' ' + this.title;
};

/**
 * Clear the timeout.
 *
 * @api private
 */

Runnable.prototype.clearTimeout = function(){
  clearTimeout(this.timer);
};

/**
 * Inspect the runnable void of private properties.
 *
 * @return {String}
 * @api private
 */

Runnable.prototype.inspect = function(){
  return JSON.stringify(this, function(key, val){
    if ('_' == key[0]) return;
    if ('parent' == key) return '#<Suite>';
    if ('ctx' == key) return '#<Context>';
    return val;
  }, 2);
};

/**
 * Reset the timeout.
 *
 * @api private
 */

Runnable.prototype.resetTimeout = function(){
  var self = this;
  var ms = this.timeout() || 1e9;

  if (!this._enableTimeouts) return;
  this.clearTimeout();
  this.timer = setTimeout(function(){
    if (!self._enableTimeouts) return;
    self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
    self.timedOut = true;
  }, ms);
};

/**
 * Whitelist these globals for this test run
 *
 * @api private
 */
Runnable.prototype.globals = function(arr){
  var self = this;
  this._allowedGlobals = arr;
};

/**
 * Run the test and invoke `fn(err)`.
 *
 * @param {Function} fn
 * @api private
 */

Runnable.prototype.run = function(fn){
  var self = this
    , start = new Date
    , ctx = this.ctx
    , finished
    , emitted;

  // Some times the ctx exists but it is not runnable
  if (ctx && ctx.runnable) ctx.runnable(this);

  // called multiple times
  function multiple(err) {
    if (emitted) return;
    emitted = true;
    self.emit('error', err || new Error('done() called multiple times; stacktrace may be inaccurate'));
  }

  // finished
  function done(err) {
    var ms = self.timeout();
    if (self.timedOut) return;
    if (finished) return multiple(err || self._trace);
    self.clearTimeout();
    self.duration = new Date - start;
    finished = true;
    if (!err && self.duration > ms && self._enableTimeouts) err = new Error('timeout of ' + ms + 'ms exceeded');
    fn(err);
  }

  // for .resetTimeout()
  this.callback = done;

  // explicit async with `done` argument
  if (this.async) {
    this.resetTimeout();

    try {
      this.fn.call(ctx, function(err){
        if (err instanceof Error || toString.call(err) === "[object Error]") return done(err);
        if (null != err) {
          if (Object.prototype.toString.call(err) === '[object Object]') {
            return done(new Error('done() invoked with non-Error: ' + JSON.stringify(err)));
          } else {
            return done(new Error('done() invoked with non-Error: ' + err));
          }
        }
        done();
      });
    } catch (err) {
      done(err);
    }
    return;
  }

  if (this.asyncOnly) {
    return done(new Error('--async-only option in use without declaring `done()`'));
  }

  // sync or promise-returning
  try {
    if (this.pending) {
      done();
    } else {
      callFn(this.fn);
    }
  } catch (err) {
    done(err);
  }

  function callFn(fn) {
    var result = fn.call(ctx);
    if (result && typeof result.then === 'function') {
      self.resetTimeout();
      result
        .then(function() {
          done()
        },
        function(reason) {
          done(reason || new Error('Promise rejected with no or falsy reason'))
        });
    } else {
      done();
    }
  }
};

}); // module: runnable.js

require.register("runner.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var EventEmitter = require('browser/events').EventEmitter
  , debug = require('browser/debug')('mocha:runner')
  , Test = require('./test')
  , utils = require('./utils')
  , filter = utils.filter
  , keys = utils.keys;

/**
 * Non-enumerable globals.
 */

var globals = [
  'setTimeout',
  'clearTimeout',
  'setInterval',
  'clearInterval',
  'XMLHttpRequest',
  'Date'
];

/**
 * Expose `Runner`.
 */

module.exports = Runner;

/**
 * Initialize a `Runner` for the given `suite`.
 *
 * Events:
 *
 *   - `start`  execution started
 *   - `end`  execution complete
 *   - `suite`  (suite) test suite execution started
 *   - `suite end`  (suite) all tests (and sub-suites) have finished
 *   - `test`  (test) test execution started
 *   - `test end`  (test) test completed
 *   - `hook`  (hook) hook execution started
 *   - `hook end`  (hook) hook complete
 *   - `pass`  (test) test passed
 *   - `fail`  (test, err) test failed
 *   - `pending`  (test) test pending
 *
 * @api public
 */

function Runner(suite) {
  var self = this;
  this._globals = [];
  this._abort = false;
  this.suite = suite;
  this.total = suite.total();
  this.failures = 0;
  this.on('test end', function(test){ self.checkGlobals(test); });
  this.on('hook end', function(hook){ self.checkGlobals(hook); });
  this.grep(/.*/);
  this.globals(this.globalProps().concat(extraGlobals()));
}

/**
 * Wrapper for setImmediate, process.nextTick, or browser polyfill.
 *
 * @param {Function} fn
 * @api private
 */

Runner.immediately = global.setImmediate || process.nextTick;

/**
 * Inherit from `EventEmitter.prototype`.
 */

function F(){};
F.prototype = EventEmitter.prototype;
Runner.prototype = new F;
Runner.prototype.constructor = Runner;


/**
 * Run tests with full titles matching `re`. Updates runner.total
 * with number of tests matched.
 *
 * @param {RegExp} re
 * @param {Boolean} invert
 * @return {Runner} for chaining
 * @api public
 */

Runner.prototype.grep = function(re, invert){
  debug('grep %s', re);
  this._grep = re;
  this._invert = invert;
  this.total = this.grepTotal(this.suite);
  return this;
};

/**
 * Returns the number of tests matching the grep search for the
 * given suite.
 *
 * @param {Suite} suite
 * @return {Number}
 * @api public
 */

Runner.prototype.grepTotal = function(suite) {
  var self = this;
  var total = 0;

  suite.eachTest(function(test){
    var match = self._grep.test(test.fullTitle());
    if (self._invert) match = !match;
    if (match) total++;
  });

  return total;
};

/**
 * Return a list of global properties.
 *
 * @return {Array}
 * @api private
 */

Runner.prototype.globalProps = function() {
  var props = utils.keys(global);

  // non-enumerables
  for (var i = 0; i < globals.length; ++i) {
    if (~utils.indexOf(props, globals[i])) continue;
    props.push(globals[i]);
  }

  return props;
};

/**
 * Allow the given `arr` of globals.
 *
 * @param {Array} arr
 * @return {Runner} for chaining
 * @api public
 */

Runner.prototype.globals = function(arr){
  if (0 == arguments.length) return this._globals;
  debug('globals %j', arr);
  this._globals = this._globals.concat(arr);
  return this;
};

/**
 * Check for global variable leaks.
 *
 * @api private
 */

Runner.prototype.checkGlobals = function(test){
  if (this.ignoreLeaks) return;
  var ok = this._globals;

  var globals = this.globalProps();
  var leaks;

  if (test) {
    ok = ok.concat(test._allowedGlobals || []);
  }

  if(this.prevGlobalsLength == globals.length) return;
  this.prevGlobalsLength = globals.length;

  leaks = filterLeaks(ok, globals);
  this._globals = this._globals.concat(leaks);

  if (leaks.length > 1) {
    this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
  } else if (leaks.length) {
    this.fail(test, new Error('global leak detected: ' + leaks[0]));
  }
};

/**
 * Fail the given `test`.
 *
 * @param {Test} test
 * @param {Error} err
 * @api private
 */

Runner.prototype.fail = function(test, err){
  ++this.failures;
  test.state = 'failed';

  if ('string' == typeof err) {
    err = new Error('the string "' + err + '" was thrown, throw an Error :)');
  }

  this.emit('fail', test, err);
};

/**
 * Fail the given `hook` with `err`.
 *
 * Hook failures work in the following pattern:
 * - If bail, then exit
 * - Failed `before` hook skips all tests in a suite and subsuites,
 *   but jumps to corresponding `after` hook
 * - Failed `before each` hook skips remaining tests in a
 *   suite and jumps to corresponding `after each` hook,
 *   which is run only once
 * - Failed `after` hook does not alter
 *   execution order
 * - Failed `after each` hook skips remaining tests in a
 *   suite and subsuites, but executes other `after each`
 *   hooks
 *
 * @param {Hook} hook
 * @param {Error} err
 * @api private
 */

Runner.prototype.failHook = function(hook, err){
  this.fail(hook, err);
  if (this.suite.bail()) {
    this.emit('end');
  }
};

/**
 * Run hook `name` callbacks and then invoke `fn()`.
 *
 * @param {String} name
 * @param {Function} function
 * @api private
 */

Runner.prototype.hook = function(name, fn){
  var suite = this.suite
    , hooks = suite['_' + name]
    , self = this
    , timer;

  function next(i) {
    var hook = hooks[i];
    if (!hook) return fn();
    if (self.failures && suite.bail()) return fn();
    self.currentRunnable = hook;

    hook.ctx.currentTest = self.test;

    self.emit('hook', hook);

    hook.on('error', function(err){
      self.failHook(hook, err);
    });

    hook.run(function(err){
      hook.removeAllListeners('error');
      var testError = hook.error();
      if (testError) self.fail(self.test, testError);
      if (err) {
        self.failHook(hook, err);

        // stop executing hooks, notify callee of hook err
        return fn(err);
      }
      self.emit('hook end', hook);
      delete hook.ctx.currentTest;
      next(++i);
    });
  }

  Runner.immediately(function(){
    next(0);
  });
};

/**
 * Run hook `name` for the given array of `suites`
 * in order, and callback `fn(err, errSuite)`.
 *
 * @param {String} name
 * @param {Array} suites
 * @param {Function} fn
 * @api private
 */

Runner.prototype.hooks = function(name, suites, fn){
  var self = this
    , orig = this.suite;

  function next(suite) {
    self.suite = suite;

    if (!suite) {
      self.suite = orig;
      return fn();
    }

    self.hook(name, function(err){
      if (err) {
        var errSuite = self.suite;
        self.suite = orig;
        return fn(err, errSuite);
      }

      next(suites.pop());
    });
  }

  next(suites.pop());
};

/**
 * Run hooks from the top level down.
 *
 * @param {String} name
 * @param {Function} fn
 * @api private
 */

Runner.prototype.hookUp = function(name, fn){
  var suites = [this.suite].concat(this.parents()).reverse();
  this.hooks(name, suites, fn);
};

/**
 * Run hooks from the bottom up.
 *
 * @param {String} name
 * @param {Function} fn
 * @api private
 */

Runner.prototype.hookDown = function(name, fn){
  var suites = [this.suite].concat(this.parents());
  this.hooks(name, suites, fn);
};

/**
 * Return an array of parent Suites from
 * closest to furthest.
 *
 * @return {Array}
 * @api private
 */

Runner.prototype.parents = function(){
  var suite = this.suite
    , suites = [];
  while (suite = suite.parent) suites.push(suite);
  return suites;
};

/**
 * Run the current test and callback `fn(err)`.
 *
 * @param {Function} fn
 * @api private
 */

Runner.prototype.runTest = function(fn){
  var test = this.test
    , self = this;

  if (this.asyncOnly) test.asyncOnly = true;

  try {
    test.on('error', function(err){
      self.fail(test, err);
    });
    test.run(fn);
  } catch (err) {
    fn(err);
  }
};

/**
 * Run tests in the given `suite` and invoke
 * the callback `fn()` when complete.
 *
 * @param {Suite} suite
 * @param {Function} fn
 * @api private
 */

Runner.prototype.runTests = function(suite, fn){
  var self = this
    , tests = suite.tests.slice()
    , test;


  function hookErr(err, errSuite, after) {
    // before/after Each hook for errSuite failed:
    var orig = self.suite;

    // for failed 'after each' hook start from errSuite parent,
    // otherwise start from errSuite itself
    self.suite = after ? errSuite.parent : errSuite;

    if (self.suite) {
      // call hookUp afterEach
      self.hookUp('afterEach', function(err2, errSuite2) {
        self.suite = orig;
        // some hooks may fail even now
        if (err2) return hookErr(err2, errSuite2, true);
        // report error suite
        fn(errSuite);
      });
    } else {
      // there is no need calling other 'after each' hooks
      self.suite = orig;
      fn(errSuite);
    }
  }

  function next(err, errSuite) {
    // if we bail after first err
    if (self.failures && suite._bail) return fn();

    if (self._abort) return fn();

    if (err) return hookErr(err, errSuite, true);

    // next test
    test = tests.shift();

    // all done
    if (!test) return fn();

    // grep
    var match = self._grep.test(test.fullTitle());
    if (self._invert) match = !match;
    if (!match) return next();

    // pending
    if (test.pending) {
      self.emit('pending', test);
      self.emit('test end', test);
      return next();
    }

    // execute test and hook(s)
    self.emit('test', self.test = test);
    self.hookDown('beforeEach', function(err, errSuite){

      if (err) return hookErr(err, errSuite, false);

      self.currentRunnable = self.test;
      self.runTest(function(err){
        test = self.test;

        if (err) {
          self.fail(test, err);
          self.emit('test end', test);
          return self.hookUp('afterEach', next);
        }

        test.state = 'passed';
        self.emit('pass', test);
        self.emit('test end', test);
        self.hookUp('afterEach', next);
      });
    });
  }

  this.next = next;
  next();
};

/**
 * Run the given `suite` and invoke the
 * callback `fn()` when complete.
 *
 * @param {Suite} suite
 * @param {Function} fn
 * @api private
 */

Runner.prototype.runSuite = function(suite, fn){
  var total = this.grepTotal(suite)
    , self = this
    , i = 0;

  debug('run suite %s', suite.fullTitle());

  if (!total) return fn();

  this.emit('suite', this.suite = suite);

  function next(errSuite) {
    if (errSuite) {
      // current suite failed on a hook from errSuite
      if (errSuite == suite) {
        // if errSuite is current suite
        // continue to the next sibling suite
        return done();
      } else {
        // errSuite is among the parents of current suite
        // stop execution of errSuite and all sub-suites
        return done(errSuite);
      }
    }

    if (self._abort) return done();

    var curr = suite.suites[i++];
    if (!curr) return done();
    self.runSuite(curr, next);
  }

  function done(errSuite) {
    self.suite = suite;
    self.hook('afterAll', function(){
      self.emit('suite end', suite);
      fn(errSuite);
    });
  }

  this.hook('beforeAll', function(err){
    if (err) return done();
    self.runTests(suite, next);
  });
};

/**
 * Handle uncaught exceptions.
 *
 * @param {Error} err
 * @api private
 */

Runner.prototype.uncaught = function(err){
  if (err) {
    debug('uncaught exception %s', err !== function () {
      return this;
    }.call(err) ? err : ( err.message || err ));
  } else {
    debug('uncaught undefined exception');
    err = new Error('Caught undefined error, did you throw without specifying what?');
  }
  err.uncaught = true;

  var runnable = this.currentRunnable;
  if (!runnable) return;

  var wasAlreadyDone = runnable.state;
  this.fail(runnable, err);

  runnable.clearTimeout();

  if (wasAlreadyDone) return;

  // recover from test
  if ('test' == runnable.type) {
    this.emit('test end', runnable);
    this.hookUp('afterEach', this.next);
    return;
  }

  // bail on hooks
  this.emit('end');
};

/**
 * Run the root suite and invoke `fn(failures)`
 * on completion.
 *
 * @param {Function} fn
 * @return {Runner} for chaining
 * @api public
 */

Runner.prototype.run = function(fn){
  var self = this
    , fn = fn || function(){};

  function uncaught(err){
    self.uncaught(err);
  }

  debug('start');

  // callback
  this.on('end', function(){
    debug('end');
    process.removeListener('uncaughtException', uncaught);
    fn(self.failures);
  });

  // run suites
  this.emit('start');
  this.runSuite(this.suite, function(){
    debug('finished running');
    self.emit('end');
  });

  // uncaught exception
  process.on('uncaughtException', uncaught);

  return this;
};

/**
 * Cleanly abort execution
 *
 * @return {Runner} for chaining
 * @api public
 */
Runner.prototype.abort = function(){
  debug('aborting');
  this._abort = true;
};

/**
 * Filter leaks with the given globals flagged as `ok`.
 *
 * @param {Array} ok
 * @param {Array} globals
 * @return {Array}
 * @api private
 */

function filterLeaks(ok, globals) {
  return filter(globals, function(key){
    // Firefox and Chrome exposes iframes as index inside the window object
    if (/^d+/.test(key)) return false;

    // in firefox
    // if runner runs in an iframe, this iframe's window.getInterface method not init at first
    // it is assigned in some seconds
    if (global.navigator && /^getInterface/.test(key)) return false;

    // an iframe could be approached by window[iframeIndex]
    // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak
    if (global.navigator && /^\d+/.test(key)) return false;

    // Opera and IE expose global variables for HTML element IDs (issue #243)
    if (/^mocha-/.test(key)) return false;

    var matched = filter(ok, function(ok){
      if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);
      return key == ok;
    });
    return matched.length == 0 && (!global.navigator || 'onerror' !== key);
  });
}

/**
 * Array of globals dependent on the environment.
 *
 * @return {Array}
 * @api private
 */

 function extraGlobals() {
  if (typeof(process) === 'object' &&
      typeof(process.version) === 'string') {

    var nodeVersion = process.version.split('.').reduce(function(a, v) {
      return a << 8 | v;
    });

    // 'errno' was renamed to process._errno in v0.9.11.

    if (nodeVersion < 0x00090B) {
      return ['errno'];
    }
  }

  return [];
 }

}); // module: runner.js

require.register("suite.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var EventEmitter = require('browser/events').EventEmitter
  , debug = require('browser/debug')('mocha:suite')
  , milliseconds = require('./ms')
  , utils = require('./utils')
  , Hook = require('./hook');

/**
 * Expose `Suite`.
 */

exports = module.exports = Suite;

/**
 * Create a new `Suite` with the given `title`
 * and parent `Suite`. When a suite with the
 * same title is already present, that suite
 * is returned to provide nicer reporter
 * and more flexible meta-testing.
 *
 * @param {Suite} parent
 * @param {String} title
 * @return {Suite}
 * @api public
 */

exports.create = function(parent, title){
  var suite = new Suite(title, parent.ctx);
  suite.parent = parent;
  if (parent.pending) suite.pending = true;
  title = suite.fullTitle();
  parent.addSuite(suite);
  return suite;
};

/**
 * Initialize a new `Suite` with the given
 * `title` and `ctx`.
 *
 * @param {String} title
 * @param {Context} ctx
 * @api private
 */

function Suite(title, parentContext) {
  this.title = title;
  var context = function() {};
  context.prototype = parentContext;
  this.ctx = new context();
  this.suites = [];
  this.tests = [];
  this.pending = false;
  this._beforeEach = [];
  this._beforeAll = [];
  this._afterEach = [];
  this._afterAll = [];
  this.root = !title;
  this._timeout = 2000;
  this._enableTimeouts = true;
  this._slow = 75;
  this._bail = false;
}

/**
 * Inherit from `EventEmitter.prototype`.
 */

function F(){};
F.prototype = EventEmitter.prototype;
Suite.prototype = new F;
Suite.prototype.constructor = Suite;


/**
 * Return a clone of this `Suite`.
 *
 * @return {Suite}
 * @api private
 */

Suite.prototype.clone = function(){
  var suite = new Suite(this.title);
  debug('clone');
  suite.ctx = this.ctx;
  suite.timeout(this.timeout());
  suite.enableTimeouts(this.enableTimeouts());
  suite.slow(this.slow());
  suite.bail(this.bail());
  return suite;
};

/**
 * Set timeout `ms` or short-hand such as "2s".
 *
 * @param {Number|String} ms
 * @return {Suite|Number} for chaining
 * @api private
 */

Suite.prototype.timeout = function(ms){
  if (0 == arguments.length) return this._timeout;
  if (ms === 0) this._enableTimeouts = false;
  if ('string' == typeof ms) ms = milliseconds(ms);
  debug('timeout %d', ms);
  this._timeout = parseInt(ms, 10);
  return this;
};

/**
  * Set timeout `enabled`.
  *
  * @param {Boolean} enabled
  * @return {Suite|Boolean} self or enabled
  * @api private
  */

Suite.prototype.enableTimeouts = function(enabled){
  if (arguments.length === 0) return this._enableTimeouts;
  debug('enableTimeouts %s', enabled);
  this._enableTimeouts = enabled;
  return this;
};

/**
 * Set slow `ms` or short-hand such as "2s".
 *
 * @param {Number|String} ms
 * @return {Suite|Number} for chaining
 * @api private
 */

Suite.prototype.slow = function(ms){
  if (0 === arguments.length) return this._slow;
  if ('string' == typeof ms) ms = milliseconds(ms);
  debug('slow %d', ms);
  this._slow = ms;
  return this;
};

/**
 * Sets whether to bail after first error.
 *
 * @parma {Boolean} bail
 * @return {Suite|Number} for chaining
 * @api private
 */

Suite.prototype.bail = function(bail){
  if (0 == arguments.length) return this._bail;
  debug('bail %s', bail);
  this._bail = bail;
  return this;
};

/**
 * Run `fn(test[, done])` before running tests.
 *
 * @param {Function} fn
 * @return {Suite} for chaining
 * @api private
 */

Suite.prototype.beforeAll = function(title, fn){
  if (this.pending) return this;
  if ('function' === typeof title) {
    fn = title;
    title = fn.name;
  }
  title = '"before all" hook' + (title ? ': ' + title : '');

  var hook = new Hook(title, fn);
  hook.parent = this;
  hook.timeout(this.timeout());
  hook.enableTimeouts(this.enableTimeouts());
  hook.slow(this.slow());
  hook.ctx = this.ctx;
  this._beforeAll.push(hook);
  this.emit('beforeAll', hook);
  return this;
};

/**
 * Run `fn(test[, done])` after running tests.
 *
 * @param {Function} fn
 * @return {Suite} for chaining
 * @api private
 */

Suite.prototype.afterAll = function(title, fn){
  if (this.pending) return this;
  if ('function' === typeof title) {
    fn = title;
    title = fn.name;
  }
  title = '"after all" hook' + (title ? ': ' + title : '');

  var hook = new Hook(title, fn);
  hook.parent = this;
  hook.timeout(this.timeout());
  hook.enableTimeouts(this.enableTimeouts());
  hook.slow(this.slow());
  hook.ctx = this.ctx;
  this._afterAll.push(hook);
  this.emit('afterAll', hook);
  return this;
};

/**
 * Run `fn(test[, done])` before each test case.
 *
 * @param {Function} fn
 * @return {Suite} for chaining
 * @api private
 */

Suite.prototype.beforeEach = function(title, fn){
  if (this.pending) return this;
  if ('function' === typeof title) {
    fn = title;
    title = fn.name;
  }
  title = '"before each" hook' + (title ? ': ' + title : '');

  var hook = new Hook(title, fn);
  hook.parent = this;
  hook.timeout(this.timeout());
  hook.enableTimeouts(this.enableTimeouts());
  hook.slow(this.slow());
  hook.ctx = this.ctx;
  this._beforeEach.push(hook);
  this.emit('beforeEach', hook);
  return this;
};

/**
 * Run `fn(test[, done])` after each test case.
 *
 * @param {Function} fn
 * @return {Suite} for chaining
 * @api private
 */

Suite.prototype.afterEach = function(title, fn){
  if (this.pending) return this;
  if ('function' === typeof title) {
    fn = title;
    title = fn.name;
  }
  title = '"after each" hook' + (title ? ': ' + title : '');

  var hook = new Hook(title, fn);
  hook.parent = this;
  hook.timeout(this.timeout());
  hook.enableTimeouts(this.enableTimeouts());
  hook.slow(this.slow());
  hook.ctx = this.ctx;
  this._afterEach.push(hook);
  this.emit('afterEach', hook);
  return this;
};

/**
 * Add a test `suite`.
 *
 * @param {Suite} suite
 * @return {Suite} for chaining
 * @api private
 */

Suite.prototype.addSuite = function(suite){
  suite.parent = this;
  suite.timeout(this.timeout());
  suite.enableTimeouts(this.enableTimeouts());
  suite.slow(this.slow());
  suite.bail(this.bail());
  this.suites.push(suite);
  this.emit('suite', suite);
  return this;
};

/**
 * Add a `test` to this suite.
 *
 * @param {Test} test
 * @return {Suite} for chaining
 * @api private
 */

Suite.prototype.addTest = function(test){
  test.parent = this;
  test.timeout(this.timeout());
  test.enableTimeouts(this.enableTimeouts());
  test.slow(this.slow());
  test.ctx = this.ctx;
  this.tests.push(test);
  this.emit('test', test);
  return this;
};

/**
 * Return the full title generated by recursively
 * concatenating the parent's full title.
 *
 * @return {String}
 * @api public
 */

Suite.prototype.fullTitle = function(){
  if (this.parent) {
    var full = this.parent.fullTitle();
    if (full) return full + ' ' + this.title;
  }
  return this.title;
};

/**
 * Return the total number of tests.
 *
 * @return {Number}
 * @api public
 */

Suite.prototype.total = function(){
  return utils.reduce(this.suites, function(sum, suite){
    return sum + suite.total();
  }, 0) + this.tests.length;
};

/**
 * Iterates through each suite recursively to find
 * all tests. Applies a function in the format
 * `fn(test)`.
 *
 * @param {Function} fn
 * @return {Suite}
 * @api private
 */

Suite.prototype.eachTest = function(fn){
  utils.forEach(this.tests, fn);
  utils.forEach(this.suites, function(suite){
    suite.eachTest(fn);
  });
  return this;
};

}); // module: suite.js

require.register("test.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var Runnable = require('./runnable');

/**
 * Expose `Test`.
 */

module.exports = Test;

/**
 * Initialize a new `Test` with the given `title` and callback `fn`.
 *
 * @param {String} title
 * @param {Function} fn
 * @api private
 */

function Test(title, fn) {
  Runnable.call(this, title, fn);
  this.pending = !fn;
  this.type = 'test';
}

/**
 * Inherit from `Runnable.prototype`.
 */

function F(){};
F.prototype = Runnable.prototype;
Test.prototype = new F;
Test.prototype.constructor = Test;


}); // module: test.js

require.register("utils.js", function(module, exports, require){
/**
 * Module dependencies.
 */

var fs = require('browser/fs')
  , path = require('browser/path')
  , basename = path.basename
  , exists = fs.existsSync || path.existsSync
  , glob = require('browser/glob')
  , join = path.join
  , debug = require('browser/debug')('mocha:watch');

/**
 * Ignored directories.
 */

var ignore = ['node_modules', '.git'];

/**
 * Escape special characters in the given string of html.
 *
 * @param  {String} html
 * @return {String}
 * @api private
 */

exports.escape = function(html){
  return String(html)
    .replace(/&/g, '&amp;')
    .replace(/"/g, '&quot;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;');
};

/**
 * Array#forEach (<=IE8)
 *
 * @param {Array} array
 * @param {Function} fn
 * @param {Object} scope
 * @api private
 */

exports.forEach = function(arr, fn, scope){
  for (var i = 0, l = arr.length; i < l; i++)
    fn.call(scope, arr[i], i);
};

/**
 * Array#map (<=IE8)
 *
 * @param {Array} array
 * @param {Function} fn
 * @param {Object} scope
 * @api private
 */

exports.map = function(arr, fn, scope){
  var result = [];
  for (var i = 0, l = arr.length; i < l; i++)
    result.push(fn.call(scope, arr[i], i));
  return result;
};

/**
 * Array#indexOf (<=IE8)
 *
 * @parma {Array} arr
 * @param {Object} obj to find index of
 * @param {Number} start
 * @api private
 */

exports.indexOf = function(arr, obj, start){
  for (var i = start || 0, l = arr.length; i < l; i++) {
    if (arr[i] === obj)
      return i;
  }
  return -1;
};

/**
 * Array#reduce (<=IE8)
 *
 * @param {Array} array
 * @param {Function} fn
 * @param {Object} initial value
 * @api private
 */

exports.reduce = function(arr, fn, val){
  var rval = val;

  for (var i = 0, l = arr.length; i < l; i++) {
    rval = fn(rval, arr[i], i, arr);
  }

  return rval;
};

/**
 * Array#filter (<=IE8)
 *
 * @param {Array} array
 * @param {Function} fn
 * @api private
 */

exports.filter = function(arr, fn){
  var ret = [];

  for (var i = 0, l = arr.length; i < l; i++) {
    var val = arr[i];
    if (fn(val, i, arr)) ret.push(val);
  }

  return ret;
};

/**
 * Object.keys (<=IE8)
 *
 * @param {Object} obj
 * @return {Array} keys
 * @api private
 */

exports.keys = Object.keys || function(obj) {
  var keys = []
    , has = Object.prototype.hasOwnProperty // for `window` on <=IE8

  for (var key in obj) {
    if (has.call(obj, key)) {
      keys.push(key);
    }
  }

  return keys;
};

/**
 * Watch the given `files` for changes
 * and invoke `fn(file)` on modification.
 *
 * @param {Array} files
 * @param {Function} fn
 * @api private
 */

exports.watch = function(files, fn){
  var options = { interval: 100 };
  files.forEach(function(file){
    debug('file %s', file);
    fs.watchFile(file, options, function(curr, prev){
      if (prev.mtime < curr.mtime) fn(file);
    });
  });
};

/**
 * Ignored files.
 */

function ignored(path){
  return !~ignore.indexOf(path);
}

/**
 * Lookup files in the given `dir`.
 *
 * @return {Array}
 * @api private
 */

exports.files = function(dir, ext, ret){
  ret = ret || [];
  ext = ext || ['js'];

  var re = new RegExp('\\.(' + ext.join('|') + ')$');

  fs.readdirSync(dir)
  .filter(ignored)
  .forEach(function(path){
    path = join(dir, path);
    if (fs.statSync(path).isDirectory()) {
      exports.files(path, ext, ret);
    } else if (path.match(re)) {
      ret.push(path);
    }
  });

  return ret;
};

/**
 * Compute a slug from the given `str`.
 *
 * @param {String} str
 * @return {String}
 * @api private
 */

exports.slug = function(str){
  return str
    .toLowerCase()
    .replace(/ +/g, '-')
    .replace(/[^-\w]/g, '');
};

/**
 * Strip the function definition from `str`,
 * and re-indent for pre whitespace.
 */

exports.clean = function(str) {
  str = str
    .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '')
    .replace(/^function *\(.*\) *{|\(.*\) *=> *{?/, '')
    .replace(/\s+\}$/, '');

  var spaces = str.match(/^\n?( *)/)[1].length
    , tabs = str.match(/^\n?(\t*)/)[1].length
    , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm');

  str = str.replace(re, '');

  return exports.trim(str);
};

/**
 * Trim the given `str`.
 *
 * @param {String} str
 * @return {String}
 * @api private
 */

exports.trim = function(str){
  return str.replace(/^\s+|\s+$/g, '');
};

/**
 * Parse the given `qs`.
 *
 * @param {String} qs
 * @return {Object}
 * @api private
 */

exports.parseQuery = function(qs){
  return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){
    var i = pair.indexOf('=')
      , key = pair.slice(0, i)
      , val = pair.slice(++i);

    obj[key] = decodeURIComponent(val);
    return obj;
  }, {});
};

/**
 * Highlight the given string of `js`.
 *
 * @param {String} js
 * @return {String}
 * @api private
 */

function highlight(js) {
  return js
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
    .replace(/('.*?')/gm, '<span class="string">$1</span>')
    .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
    .replace(/(\d+)/gm, '<span class="number">$1</span>')
    .replace(/\bnew[ \t]+(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
    .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
}

/**
 * Highlight the contents of tag `name`.
 *
 * @param {String} name
 * @api private
 */

exports.highlightTags = function(name) {
  var code = document.getElementById('mocha').getElementsByTagName(name);
  for (var i = 0, len = code.length; i < len; ++i) {
    code[i].innerHTML = highlight(code[i].innerHTML);
  }
};


/**
 * Stringify `obj`.
 *
 * @param {Object} obj
 * @return {String}
 * @api private
 */

exports.stringify = function(obj) {
  if (obj instanceof RegExp) return obj.toString();
  return JSON.stringify(exports.canonicalize(obj), null, 2).replace(/,(\n|$)/g, '$1');
};

/**
 * Return a new object that has the keys in sorted order.
 * @param {Object} obj
 * @param {Array} [stack]
 * @return {Object}
 * @api private
 */

exports.canonicalize = function(obj, stack) {
  stack = stack || [];

  if (exports.indexOf(stack, obj) !== -1) return '[Circular]';

  var canonicalizedObj;

  if ({}.toString.call(obj) === '[object Array]') {
    stack.push(obj);
    canonicalizedObj = exports.map(obj, function (item) {
      return exports.canonicalize(item, stack);
    });
    stack.pop();
  } else if (typeof obj === 'object' && obj !== null) {
    stack.push(obj);
    canonicalizedObj = {};
    exports.forEach(exports.keys(obj).sort(), function (key) {
      canonicalizedObj[key] = exports.canonicalize(obj[key], stack);
    });
    stack.pop();
  } else {
    canonicalizedObj = obj;
  }

  return canonicalizedObj;
 };

/**
 * Lookup file names at the given `path`.
 */
exports.lookupFiles = function lookupFiles(path, extensions, recursive) {
  var files = [];
  var re = new RegExp('\\.(' + extensions.join('|') + ')$');

  if (!exists(path)) {
    if (exists(path + '.js')) {
      path += '.js';
    } else {
      files = glob.sync(path);
      if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'");
      return files;
    }
  }

  try {
    var stat = fs.statSync(path);
    if (stat.isFile()) return path;
  }
  catch (ignored) {
    return;
  }

  fs.readdirSync(path).forEach(function(file){
    file = join(path, file);
    try {
      var stat = fs.statSync(file);
      if (stat.isDirectory()) {
        if (recursive) {
          files = files.concat(lookupFiles(file, extensions, recursive));
        }
        return;
      }
    }
    catch (ignored) {
      return;
    }
    if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') return;
    files.push(file);
  });

  return files;
};

}); // module: utils.js
// The global object is "self" in Web Workers.
var global = (function() { return this; })();

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */

var Date = global.Date;
var setTimeout = global.setTimeout;
var setInterval = global.setInterval;
var clearTimeout = global.clearTimeout;
var clearInterval = global.clearInterval;

/**
 * Node shims.
 *
 * These are meant only to allow
 * mocha.js to run untouched, not
 * to allow running node code in
 * the browser.
 */

var process = {};
process.exit = function(status){};
process.stdout = {};

var uncaughtExceptionHandlers = [];

var originalOnerrorHandler = global.onerror;

/**
 * Remove uncaughtException listener.
 * Revert to original onerror handler if previously defined.
 */

process.removeListener = function(e, fn){
  if ('uncaughtException' == e) {
    if (originalOnerrorHandler) {
      global.onerror = originalOnerrorHandler;
    } else {
      global.onerror = function() {};
    }
    var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn);
    if (i != -1) { uncaughtExceptionHandlers.splice(i, 1); }
  }
};

/**
 * Implements uncaughtException listener.
 */

process.on = function(e, fn){
  if ('uncaughtException' == e) {
    global.onerror = function(err, url, line){
      fn(new Error(err + ' (' + url + ':' + line + ')'));
      return true;
    };
    uncaughtExceptionHandlers.push(fn);
  }
};

/**
 * Expose mocha.
 */

var Mocha = global.Mocha = require('mocha'),
    mocha = global.mocha = new Mocha({ reporter: 'html' });

// The BDD UI is registered by default, but no UI will be functional in the
// browser without an explicit call to the overridden `mocha.ui` (see below).
// Ensure that this default UI does not expose its methods to the global scope.
mocha.suite.removeAllListeners('pre-require');

var immediateQueue = []
  , immediateTimeout;

function timeslice() {
  var immediateStart = new Date().getTime();
  while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) {
    immediateQueue.shift()();
  }
  if (immediateQueue.length) {
    immediateTimeout = setTimeout(timeslice, 0);
  } else {
    immediateTimeout = null;
  }
}

/**
 * High-performance override of Runner.immediately.
 */

Mocha.Runner.immediately = function(callback) {
  immediateQueue.push(callback);
  if (!immediateTimeout) {
    immediateTimeout = setTimeout(timeslice, 0);
  }
};

/**
 * Function to allow assertion libraries to throw errors directly into mocha.
 * This is useful when running tests in a browser because window.onerror will
 * only receive the 'message' attribute of the Error.
 */
mocha.throwError = function(err) {
  Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) {
    fn(err);
  });
  throw err;
};

/**
 * Override ui to ensure that the ui functions are initialized.
 * Normally this would happen in Mocha.prototype.loadFiles.
 */

mocha.ui = function(ui){
  Mocha.prototype.ui.call(this, ui);
  this.suite.emit('pre-require', global, null, this);
  return this;
};

/**
 * Setup mocha with the given setting options.
 */

mocha.setup = function(opts){
  if ('string' == typeof opts) opts = { ui: opts };
  for (var opt in opts) this[opt](opts[opt]);
  return this;
};

/**
 * Run mocha, returning the Runner.
 */

mocha.run = function(fn){
  var options = mocha.options;
  mocha.globals('location');

  var query = Mocha.utils.parseQuery(global.location.search || '');
  if (query.grep) mocha.grep(query.grep);
  if (query.invert) mocha.invert();

  return Mocha.prototype.run.call(mocha, function(err){
    // The DOM Document is not available in Web Workers.
    var document = global.document;
    if (document && document.getElementById('mocha') && options.noHighlighting !== true) {
      Mocha.utils.highlightTags('code');
    }
    if (fn) fn(err);
  });
};

/**
 * Expose the process shim.
 */

Mocha.process = process;
})();
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var getType = require('should-type');
var util = require('./util');

function genKeysFunc(f) {
  return function(value) {
    var k = f(value);
    k.sort();
    return k;
  };
}


function Formatter(opts) {
  opts = opts || {};

  this.seen = [];
  this.keys = genKeysFunc(opts.keys === false ? Object.getOwnPropertyNames : Object.keys);

  this.maxLineLength = typeof opts.maxLineLength === 'number' ? opts.maxLineLength : 60;
  this.propSep = opts.propSep || ',';

  this.isUTCdate = !!opts.isUTCdate;
}

Formatter.prototype = {
  constructor: Formatter,

  format: function(value) {
    var t = getType(value);
    var name1 = t.type, name2 = t.type;
    if(t.cls) {
      name1 += '_' + t.cls;
      name2 += '_' + t.cls;
    }
    if(t.sub) {
      name2 += '_' + t.sub;
    }
    var f = this['_format_' + name2] || this['_format_' + name1] || this['_format_' + t.type] || this.defaultFormat;
    return f.call(this, value).trim();
  },

  _formatObject: function(value, opts) {
    opts = opts || {};
    var mainKeys = opts.keys || this.keys(value);

    var len = 0;

    var formatPropertyValue = opts.formatPropertyValue || this.formatPropertyValue;
    var formatPropertyName = opts.formatPropertyName || this.formatPropertyName;
    var keyValueSep = opts.keyValueSep || ': ';
    var keyFilter = opts.keyFilter || function() { return true; };

    this.seen.push(value);
    var keys = [];

    mainKeys.forEach(function(key) {
      if(!keyFilter(key)) return;

      var fName = formatPropertyName.call(this, key);

      var f = (fName ? fName + keyValueSep : '') + formatPropertyValue.call(this, value, key);
      len += f.length;
      keys.push(f);
    }, this);
    this.seen.pop();

    (opts.additionalProperties || []).forEach(function(keyValue) {
      var f = keyValue[0] + keyValueSep + this.format(keyValue[1]);
      len += f.length;
      keys.push(f);
    }, this);

    var prefix = opts.prefix || Formatter.constructorName(value) || '';
    if(prefix.length > 0) prefix += ' ';

    var lbracket, rbracket;
    if(Array.isArray(opts.brackets)) {
      lbracket = opts.brackets && opts.brackets[0];
      rbracket = opts.brackets && opts.brackets[1];
    } else {
      lbracket = '{';
      rbracket = '}';
    }

    var rootValue = opts.value || '';

    if(keys.length === 0)
      return rootValue || (prefix + lbracket + rbracket);

    if(len <= this.maxLineLength) {
      return prefix + lbracket + ' ' + (rootValue ? rootValue + ' ' : '') + keys.join(this.propSep + ' ') + ' ' + rbracket;
    } else {
      return prefix + lbracket + '\n' + (rootValue ? '  ' + rootValue + '\n' : '') + keys.map(util.addSpaces).join(this.propSep + '\n') + '\n' + rbracket;
    }
  },

  formatObject: function(value, prefix, props) {
    props = props || this.keys(value);

    var len = 0;

    this.seen.push(value);
    props = props.map(function(prop) {
      var f = this.formatProperty(value, prop);
      len += f.length;
      return f;
    }, this);
    this.seen.pop();

    if(props.length === 0) return '{}';

    if(len <= this.maxLineLength) {
      return '{ ' + (prefix ? prefix + ' ' : '') + props.join(this.propSep + ' ') + ' }';
    } else {
      return '{' + '\n' + (prefix ? '  ' + prefix + '\n' : '') + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
    }
  },

  formatPropertyName: function(name) {
    return name.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/) ? name : this.format(name);
  },

  formatProperty: function(value, prop) {
    var desc = Formatter.getPropertyDescriptor(value, prop);

    var propName = this.formatPropertyName(prop);

    var propValue = desc.get && desc.set ?
      '[Getter/Setter]' : desc.get ?
      '[Getter]' : desc.set ?
      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
      '[Circular]' :
      this.format(desc.value);

    return propName + ': ' + propValue;
  },

  formatPropertyValue: function(value, prop) {
    var desc = Formatter.getPropertyDescriptor(value, prop);

    var propValue = desc.get && desc.set ?
      '[Getter/Setter]' : desc.get ?
      '[Getter]' : desc.set ?
      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
      '[Circular]' :
      this.format(desc.value);

    return propValue;
  }
};

Formatter.add = function add(type, cls, sub, f) {
  var args = Array.prototype.slice.call(arguments);
  f = args.pop();
  Formatter.prototype['_format_' + args.join('_')] = f;
};

Formatter.formatObjectWithPrefix = function formatObjectWithPrefix(f) {
  return function(value) {
    var prefix = f.call(this, value);
    var props = this.keys(value);
    if(props.length == 0) return prefix;
    else return this.formatObject(value, prefix, props);
  };
};

var functionNameRE = /^\s*function\s*(\S*)\s*\(/;

Formatter.functionName = function functionName(f) {
  if(f.name) {
    return f.name;
  }
  var name = f.toString().match(functionNameRE)[1];
  return name;
};

Formatter.constructorName = function(obj) {
  while (obj) {
    var descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor');
    if (descriptor !== undefined &&
        typeof descriptor.value === 'function') {

        var name = Formatter.functionName(descriptor.value);
        if(name !== '') {
          return name;
        }
    }

    obj = Object.getPrototypeOf(obj);
  }
};

Formatter.getPropertyDescriptor = function(obj, value) {
  var desc;
  try {
    desc = Object.getOwnPropertyDescriptor(obj, value) || {value: obj[value]};
  } catch(e) {
    desc = {value: e};
  }
  return desc;
};

Formatter.generateFunctionForIndexedArray = function generateFunctionForIndexedArray(lengthProp, name, padding) {
  return function(value) {
    var max = this.byteArrayMaxLength || 50;
    var length = value[lengthProp];
    var formattedValues = [];
    var len = 0;
    for(var i = 0; i < max && i < length; i++) {
      var b = value[i] || 0;
      var v = util.pad0(b.toString(16), padding);
      len += v.length;
      formattedValues.push(v);
    }
    var prefix = value.constructor.name || name || '';
    if(prefix) prefix += ' ';

    if(formattedValues.length === 0)
      return prefix + '[]';

    if(len <= this.maxLineLength) {
      return prefix + '[ ' + formattedValues.join(this.propSep + ' ') + ' ' + ']';
    } else {
      return prefix + '[\n' + formattedValues.map(util.addSpaces).join(this.propSep + '\n') + '\n' + ']';
    }
  };
};

Formatter.add('undefined', function() { return 'undefined' });
Formatter.add('null', function() { return 'null' });
Formatter.add('boolean', function(value) { return value ? 'true': 'false' });
Formatter.add('symbol', function(value) { return value.toString() });

['number', 'boolean'].forEach(function(name) {
  Formatter.add('object', name, function(value) {
    return this._formatObject(value, {
      additionalProperties: [['[[PrimitiveValue]]', value.valueOf()]]
    });
  });
});

Formatter.add('object', 'string', function(value) {
  var realValue = value.valueOf();

  return this._formatObject(value, {
    keyFilter: function(key) {
      //skip useless indexed properties
      return !(key.match(/\d+/) && parseInt(key, 10) < realValue.length);
    },
    additionalProperties: [['[[PrimitiveValue]]', realValue]]
  });
});

Formatter.add('object', 'regexp', function(value) {
  return this._formatObject(value, {
    value: String(value)
  });
});

Formatter.add('number', function(value) {
  if(value === 0 && 1 / value < 0) return '-0';
  return String(value);
});

Formatter.add('string', function(value) {
  return '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
      .replace(/'/g, "\\'")
      .replace(/\\"/g, '"') + '\'';
});

Formatter.add('object', function(value) {
  return this._formatObject(value);
});

Formatter.add('object', 'arguments', function(value) {
  return this._formatObject(value, {
    prefix: 'Arguments',
    formatPropertyName: function(key) {
      if(!key.match(/\d+/)) {
        return this.formatPropertyName(key);
      }
    },
    brackets: ['[', ']']
  });
});

Formatter.add('object', 'array', function(value) {
  return this._formatObject(value, {
    formatPropertyName: function(key) {
      if(!key.match(/\d+/)) {
        return this.formatPropertyName(key);
      }
    },
    brackets: ['[', ']']
  });
});


function formatDate(value, isUTC) {
  var prefix = isUTC ? 'UTC' : '';

  var date = value['get' + prefix + 'FullYear']() +
    '-' +
    util.pad0(value['get' + prefix + 'Month']() + 1, 2) +
    '-' +
    util.pad0(value['get' + prefix + 'Date'](), 2);

  var time = util.pad0(value['get' + prefix + 'Hours'](), 2) +
    ':' +
    util.pad0(value['get' + prefix + 'Minutes'](), 2) +
    ':' +
    util.pad0(value['get' + prefix + 'Seconds'](), 2) +
    '.' +
    util.pad0(value['get' + prefix + 'Milliseconds'](), 3);

  var to = value.getTimezoneOffset();
  var absTo = Math.abs(to);
  var hours = Math.floor(absTo / 60);
  var minutes = absTo - hours * 60;
  var tzFormat = (to < 0 ? '+' : '-') + util.pad0(hours, 2) + util.pad0(minutes, 2);

  return date + ' ' + time + (isUTC ? '' : ' ' + tzFormat);
}

Formatter.add('object', 'date', function(value) {
  return this._formatObject(value, { value: formatDate(value, this.isUTCdate) });
});

Formatter.add('function', function(value) {
  return this._formatObject(value, {
    additionalProperties: [['name', Formatter.functionName(value)]]
  });
});

Formatter.add('object', 'error', function(value) {
  return this._formatObject(value, {
    prefix: value.name,
    additionalProperties: [['message', value.message]]
  });
});

Formatter.add('object', 'buffer', Formatter.generateFunctionForIndexedArray('length', 'Buffer', 2));

Formatter.add('object', 'array-buffer', Formatter.generateFunctionForIndexedArray('byteLength', 'ArrayBuffer', 2));

Formatter.add('object', 'typed-array', 'int8', Formatter.generateFunctionForIndexedArray('length', 'Int8Array', 2));
Formatter.add('object', 'typed-array', 'uint8', Formatter.generateFunctionForIndexedArray('length', 'Uint8Array', 2));
Formatter.add('object', 'typed-array', 'uint8clamped', Formatter.generateFunctionForIndexedArray('length', 'Uint8ClampedArray', 2));

Formatter.add('object', 'typed-array', 'int16', Formatter.generateFunctionForIndexedArray('length', 'Int16Array', 4));
Formatter.add('object', 'typed-array', 'uint16', Formatter.generateFunctionForIndexedArray('length', 'Uint16Array', 4));

Formatter.add('object', 'typed-array', 'int32', Formatter.generateFunctionForIndexedArray('length', 'Int32Array', 8));
Formatter.add('object', 'typed-array', 'uint32', Formatter.generateFunctionForIndexedArray('length', 'Uint32Array', 8));

//TODO add float32 and float64

Formatter.add('object', 'promise', function() {
  return '[Promise]';//TODO it could be nice to inspect its state and value
});

Formatter.add('object', 'xhr', function() {
  return '[XMLHttpRequest]';//TODO it could be nice to inspect its state
});

Formatter.add('object', 'html-element', function(value) {
  return value.outerHTML;
});

Formatter.add('object', 'html-element', '#text', function(value) {
  return value.nodeValue;
});

Formatter.add('object', 'html-element', '#document', function(value) {
  return value.documentElement.outerHTML;
});

Formatter.add('object', 'host', function() {
  return '[Host]';
});

Formatter.add('object', 'set', function(value) {
  var iter = value.values();
  var len = 0;

  this.seen.push(value);

  var props = [];

  var next = iter.next();
  while(!next.done) {
    var val = next.value;
    var f = this.format(val);
    len += f.length;
    props.push(f);

    next = iter.next();
  }

  this.seen.pop();

  if(props.length === 0) return 'Set {}';

  if(len <= this.maxLineLength) {
    return 'Set { ' + props.join(this.propSep + ' ') + ' }';
  } else {
    return 'Set {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
  }
});

Formatter.add('object', 'map', function(value) {
  var iter = value.entries();
  var len = 0;

  this.seen.push(value);

  var props = [];

  var next = iter.next();
  while(!next.done) {
    var val = next.value;
    var fK = this.format(val[0]);
    var fV = this.format(val[1]);

    var f;
    if((fK.length + fV.length + 4) <= this.maxLineLength) {
      f = fK + ' => ' + fV;
    } else {
      f = fK + ' =>\n' + fV;
    }

    len += fK.length + fV.length + 4;
    props.push(f);

    next = iter.next();
  }

  this.seen.pop();

  if(props.length === 0) return 'Map {}';

  if(len <= this.maxLineLength) {
    return 'Map { ' + props.join(this.propSep + ' ') + ' }';
  } else {
    return 'Map {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
  }
});

Formatter.prototype.defaultFormat = Formatter.prototype._format_object;

function defaultFormat(value, opts) {
  return new Formatter(opts).format(value);
}

defaultFormat.Formatter = Formatter;
module.exports = defaultFormat;

},{"./util":14,"should-type":11}],2:[function(require,module,exports){
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// when used in node, this will actually load the util module we depend on
// versus loading the builtin util module as happens otherwise
// this is a bug in node module loading as far as I am concerned
var util = require('util/');

var pSlice = Array.prototype.slice;
var hasOwn = Object.prototype.hasOwnProperty;

// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.

var assert = module.exports = ok;

// 2. The AssertionError is defined in assert.
// new assert.AssertionError({ message: message,
//                             actual: actual,
//                             expected: expected })

assert.AssertionError = function AssertionError(options) {
  this.name = 'AssertionError';
  this.actual = options.actual;
  this.expected = options.expected;
  this.operator = options.operator;
  if (options.message) {
    this.message = options.message;
    this.generatedMessage = false;
  } else {
    this.message = getMessage(this);
    this.generatedMessage = true;
  }
  var stackStartFunction = options.stackStartFunction || fail;

  if (Error.captureStackTrace) {
    Error.captureStackTrace(this, stackStartFunction);
  }
  else {
    // non v8 browsers so we can have a stacktrace
    var err = new Error();
    if (err.stack) {
      var out = err.stack;

      // try to strip useless frames
      var fn_name = stackStartFunction.name;
      var idx = out.indexOf('\n' + fn_name);
      if (idx >= 0) {
        // once we have located the function frame
        // we need to strip out everything before it (and its line)
        var next_line = out.indexOf('\n', idx + 1);
        out = out.substring(next_line + 1);
      }

      this.stack = out;
    }
  }
};

// assert.AssertionError instanceof Error
util.inherits(assert.AssertionError, Error);

function replacer(key, value) {
  if (util.isUndefined(value)) {
    return '' + value;
  }
  if (util.isNumber(value) && !isFinite(value)) {
    return value.toString();
  }
  if (util.isFunction(value) || util.isRegExp(value)) {
    return value.toString();
  }
  return value;
}

function truncate(s, n) {
  if (util.isString(s)) {
    return s.length < n ? s : s.slice(0, n);
  } else {
    return s;
  }
}

function getMessage(self) {
  return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
         self.operator + ' ' +
         truncate(JSON.stringify(self.expected, replacer), 128);
}

// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.

// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided.  All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.

function fail(actual, expected, message, operator, stackStartFunction) {
  throw new assert.AssertionError({
    message: message,
    actual: actual,
    expected: expected,
    operator: operator,
    stackStartFunction: stackStartFunction
  });
}

// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;

// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.

function ok(value, message) {
  if (!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;

// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);

assert.equal = function equal(actual, expected, message) {
  if (actual != expected) fail(actual, expected, message, '==', assert.equal);
};

// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);

assert.notEqual = function notEqual(actual, expected, message) {
  if (actual == expected) {
    fail(actual, expected, message, '!=', assert.notEqual);
  }
};

// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);

assert.deepEqual = function deepEqual(actual, expected, message) {
  if (!_deepEqual(actual, expected)) {
    fail(actual, expected, message, 'deepEqual', assert.deepEqual);
  }
};

function _deepEqual(actual, expected) {
  // 7.1. All identical values are equivalent, as determined by ===.
  if (actual === expected) {
    return true;

  } else if (util.isBuffer(actual) && util.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 (util.isDate(actual) && util.isDate(expected)) {
    return actual.getTime() === expected.getTime();

  // 7.3 If the expected value is a RegExp object, the actual value is
  // equivalent if it is also a RegExp object with the same source and
  // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
  } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
    return actual.source === expected.source &&
           actual.global === expected.global &&
           actual.multiline === expected.multiline &&
           actual.lastIndex === expected.lastIndex &&
           actual.ignoreCase === expected.ignoreCase;

  // 7.4. Other pairs that do not both pass typeof value == 'object',
  // equivalence is determined by ==.
  } else if (!util.isObject(actual) && !util.isObject(expected)) {
    return actual == expected;

  // 7.5 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 isArguments(object) {
  return Object.prototype.toString.call(object) == '[object Arguments]';
}

function objEquiv(a, b) {
  if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
    return false;
  // an identical 'prototype' property.
  if (a.prototype !== b.prototype) return false;
  // if one is a primitive, the other must be same
  if (util.isPrimitive(a) || util.isPrimitive(b)) {
    return a === b;
  }
  var aIsArgs = isArguments(a),
      bIsArgs = isArguments(b);
  if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
    return false;
  if (aIsArgs) {
    a = pSlice.call(a);
    b = pSlice.call(b);
    return _deepEqual(a, b);
  }
  var ka = objectKeys(a),
      kb = objectKeys(b),
      key, i;
  // 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;
}

// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);

assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
  if (_deepEqual(actual, expected)) {
    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
  }
};

// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);

assert.strictEqual = function strictEqual(actual, expected, message) {
  if (actual !== expected) {
    fail(actual, expected, message, '===', assert.strictEqual);
  }
};

// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);

assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
  if (actual === expected) {
    fail(actual, expected, message, '!==', assert.notStrictEqual);
  }
};

function expectedException(actual, expected) {
  if (!actual || !expected) {
    return false;
  }

  if (Object.prototype.toString.call(expected) == '[object RegExp]') {
    return expected.test(actual);
  } else if (actual instanceof expected) {
    return true;
  } else if (expected.call({}, actual) === true) {
    return true;
  }

  return false;
}

function _throws(shouldThrow, block, expected, message) {
  var actual;

  if (util.isString(expected)) {
    message = expected;
    expected = null;
  }

  try {
    block();
  } catch (e) {
    actual = e;
  }

  message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
            (message ? ' ' + message : '.');

  if (shouldThrow && !actual) {
    fail(actual, expected, 'Missing expected exception' + message);
  }

  if (!shouldThrow && expectedException(actual, expected)) {
    fail(actual, expected, 'Got unwanted exception' + message);
  }

  if ((shouldThrow && actual && expected &&
      !expectedException(actual, expected)) || (!shouldThrow && actual)) {
    throw actual;
  }
}

// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);

assert.throws = function(block, /*optional*/error, /*optional*/message) {
  _throws.apply(this, [true].concat(pSlice.call(arguments)));
};

// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/message) {
  _throws.apply(this, [false].concat(pSlice.call(arguments)));
};

assert.ifError = function(err) { if (err) {throw err;}};

var objectKeys = Object.keys || function (obj) {
  var keys = [];
  for (var key in obj) {
    if (hasOwn.call(obj, key)) keys.push(key);
  }
  return keys;
};

},{"util/":10}],3:[function(require,module,exports){
(function (global){
/*!
 * The buffer module from node.js, for the browser.
 *
 * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
 * @license  MIT
 */
/* eslint-disable no-proto */

var base64 = require('base64-js')
var ieee754 = require('ieee754')
var isArray = require('is-array')

exports.Buffer = Buffer
exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50
Buffer.poolSize = 8192 // not used by this implementation

var rootParent = {}

/**
 * If `Buffer.TYPED_ARRAY_SUPPORT`:
 *   === true    Use Uint8Array implementation (fastest)
 *   === false   Use Object implementation (most compatible, even IE6)
 *
 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
 * Opera 11.6+, iOS 4.2+.
 *
 * Due to various browser bugs, sometimes the Object implementation will be used even
 * when the browser supports typed arrays.
 *
 * Note:
 *
 *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
 *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
 *
 *   - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
 *     on objects.
 *
 *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
 *
 *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
 *     incorrect length in some situations.

 * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
 * get the Object implementation, which is slower but behaves correctly.
 */
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
  ? global.TYPED_ARRAY_SUPPORT
  : typedArraySupport()

function typedArraySupport () {
  function Bar () {}
  try {
    var arr = new Uint8Array(1)
    arr.foo = function () { return 42 }
    arr.constructor = Bar
    return arr.foo() === 42 && // typed array instances can be augmented
        arr.constructor === Bar && // constructor can be set
        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
  } catch (e) {
    return false
  }
}

function kMaxLength () {
  return Buffer.TYPED_ARRAY_SUPPORT
    ? 0x7fffffff
    : 0x3fffffff
}

/**
 * Class: Buffer
 * =============
 *
 * The Buffer constructor returns instances of `Uint8Array` that are augmented
 * with function properties for all the node `Buffer` API functions. We use
 * `Uint8Array` so that square bracket notation works as expected -- it returns
 * a single octet.
 *
 * By augmenting the instances, we can avoid modifying the `Uint8Array`
 * prototype.
 */
function Buffer (arg) {
  if (!(this instanceof Buffer)) {
    // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
    if (arguments.length > 1) return new Buffer(arg, arguments[1])
    return new Buffer(arg)
  }

  this.length = 0
  this.parent = undefined

  // Common case.
  if (typeof arg === 'number') {
    return fromNumber(this, arg)
  }

  // Slightly less common case.
  if (typeof arg === 'string') {
    return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
  }

  // Unusual.
  return fromObject(this, arg)
}

function fromNumber (that, length) {
  that = allocate(that, length < 0 ? 0 : checked(length) | 0)
  if (!Buffer.TYPED_ARRAY_SUPPORT) {
    for (var i = 0; i < length; i++) {
      that[i] = 0
    }
  }
  return that
}

function fromString (that, string, encoding) {
  if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'

  // Assumption: byteLength() return value is always < kMaxLength.
  var length = byteLength(string, encoding) | 0
  that = allocate(that, length)

  that.write(string, encoding)
  return that
}

function fromObject (that, object) {
  if (Buffer.isBuffer(object)) return fromBuffer(that, object)

  if (isArray(object)) return fromArray(that, object)

  if (object == null) {
    throw new TypeError('must start with number, buffer, array or string')
  }

  if (typeof ArrayBuffer !== 'undefined') {
    if (object.buffer instanceof ArrayBuffer) {
      return fromTypedArray(that, object)
    }
    if (object instanceof ArrayBuffer) {
      return fromArrayBuffer(that, object)
    }
  }

  if (object.length) return fromArrayLike(that, object)

  return fromJsonObject(that, object)
}

function fromBuffer (that, buffer) {
  var length = checked(buffer.length) | 0
  that = allocate(that, length)
  buffer.copy(that, 0, 0, length)
  return that
}

function fromArray (that, array) {
  var length = checked(array.length) | 0
  that = allocate(that, length)
  for (var i = 0; i < length; i += 1) {
    that[i] = array[i] & 255
  }
  return that
}

// Duplicate of fromArray() to keep fromArray() monomorphic.
function fromTypedArray (that, array) {
  var length = checked(array.length) | 0
  that = allocate(that, length)
  // Truncating the elements is probably not what people expect from typed
  // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
  // of the old Buffer constructor.
  for (var i = 0; i < length; i += 1) {
    that[i] = array[i] & 255
  }
  return that
}

function fromArrayBuffer (that, array) {
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    // Return an augmented `Uint8Array` instance, for best performance
    array.byteLength
    that = Buffer._augment(new Uint8Array(array))
  } else {
    // Fallback: Return an object instance of the Buffer class
    that = fromTypedArray(that, new Uint8Array(array))
  }
  return that
}

function fromArrayLike (that, array) {
  var length = checked(array.length) | 0
  that = allocate(that, length)
  for (var i = 0; i < length; i += 1) {
    that[i] = array[i] & 255
  }
  return that
}

// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
// Returns a zero-length buffer for inputs that don't conform to the spec.
function fromJsonObject (that, object) {
  var array
  var length = 0

  if (object.type === 'Buffer' && isArray(object.data)) {
    array = object.data
    length = checked(array.length) | 0
  }
  that = allocate(that, length)

  for (var i = 0; i < length; i += 1) {
    that[i] = array[i] & 255
  }
  return that
}

if (Buffer.TYPED_ARRAY_SUPPORT) {
  Buffer.prototype.__proto__ = Uint8Array.prototype
  Buffer.__proto__ = Uint8Array
}

function allocate (that, length) {
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    // Return an augmented `Uint8Array` instance, for best performance
    that = Buffer._augment(new Uint8Array(length))
    that.__proto__ = Buffer.prototype
  } else {
    // Fallback: Return an object instance of the Buffer class
    that.length = length
    that._isBuffer = true
  }

  var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
  if (fromPool) that.parent = rootParent

  return that
}

function checked (length) {
  // Note: cannot use `length < kMaxLength` here because that fails when
  // length is NaN (which is otherwise coerced to zero.)
  if (length >= kMaxLength()) {
    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
                         'size: 0x' + kMaxLength().toString(16) + ' bytes')
  }
  return length | 0
}

function SlowBuffer (subject, encoding) {
  if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)

  var buf = new Buffer(subject, encoding)
  delete buf.parent
  return buf
}

Buffer.isBuffer = function isBuffer (b) {
  return !!(b != null && b._isBuffer)
}

Buffer.compare = function compare (a, b) {
  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
    throw new TypeError('Arguments must be Buffers')
  }

  if (a === b) return 0

  var x = a.length
  var y = b.length

  var i = 0
  var len = Math.min(x, y)
  while (i < len) {
    if (a[i] !== b[i]) break

    ++i
  }

  if (i !== len) {
    x = a[i]
    y = b[i]
  }

  if (x < y) return -1
  if (y < x) return 1
  return 0
}

Buffer.isEncoding = function isEncoding (encoding) {
  switch (String(encoding).toLowerCase()) {
    case 'hex':
    case 'utf8':
    case 'utf-8':
    case 'ascii':
    case 'binary':
    case 'base64':
    case 'raw':
    case 'ucs2':
    case 'ucs-2':
    case 'utf16le':
    case 'utf-16le':
      return true
    default:
      return false
  }
}

Buffer.concat = function concat (list, length) {
  if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')

  if (list.length === 0) {
    return new Buffer(0)
  }

  var i
  if (length === undefined) {
    length = 0
    for (i = 0; i < list.length; i++) {
      length += list[i].length
    }
  }

  var buf = new Buffer(length)
  var pos = 0
  for (i = 0; i < list.length; i++) {
    var item = list[i]
    item.copy(buf, pos)
    pos += item.length
  }
  return buf
}

function byteLength (string, encoding) {
  if (typeof string !== 'string') string = '' + string

  var len = string.length
  if (len === 0) return 0

  // Use a for loop to avoid recursion
  var loweredCase = false
  for (;;) {
    switch (encoding) {
      case 'ascii':
      case 'binary':
      // Deprecated
      case 'raw':
      case 'raws':
        return len
      case 'utf8':
      case 'utf-8':
        return utf8ToBytes(string).length
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return len * 2
      case 'hex':
        return len >>> 1
      case 'base64':
        return base64ToBytes(string).length
      default:
        if (loweredCase) return utf8ToBytes(string).length // assume utf8
        encoding = ('' + encoding).toLowerCase()
        loweredCase = true
    }
  }
}
Buffer.byteLength = byteLength

// pre-set for values that may exist in the future
Buffer.prototype.length = undefined
Buffer.prototype.parent = undefined

function slowToString (encoding, start, end) {
  var loweredCase = false

  start = start | 0
  end = end === undefined || end === Infinity ? this.length : end | 0

  if (!encoding) encoding = 'utf8'
  if (start < 0) start = 0
  if (end > this.length) end = this.length
  if (end <= start) return ''

  while (true) {
    switch (encoding) {
      case 'hex':
        return hexSlice(this, start, end)

      case 'utf8':
      case 'utf-8':
        return utf8Slice(this, start, end)

      case 'ascii':
        return asciiSlice(this, start, end)

      case 'binary':
        return binarySlice(this, start, end)

      case 'base64':
        return base64Slice(this, start, end)

      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return utf16leSlice(this, start, end)

      default:
        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
        encoding = (encoding + '').toLowerCase()
        loweredCase = true
    }
  }
}

Buffer.prototype.toString = function toString () {
  var length = this.length | 0
  if (length === 0) return ''
  if (arguments.length === 0) return utf8Slice(this, 0, length)
  return slowToString.apply(this, arguments)
}

Buffer.prototype.equals = function equals (b) {
  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
  if (this === b) return true
  return Buffer.compare(this, b) === 0
}

Buffer.prototype.inspect = function inspect () {
  var str = ''
  var max = exports.INSPECT_MAX_BYTES
  if (this.length > 0) {
    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
    if (this.length > max) str += ' ... '
  }
  return '<Buffer ' + str + '>'
}

Buffer.prototype.compare = function compare (b) {
  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
  if (this === b) return 0
  return Buffer.compare(this, b)
}

Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
  if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
  else if (byteOffset < -0x80000000) byteOffset = -0x80000000
  byteOffset >>= 0

  if (this.length === 0) return -1
  if (byteOffset >= this.length) return -1

  // Negative offsets start from the end of the buffer
  if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)

  if (typeof val === 'string') {
    if (val.length === 0) return -1 // special case: looking for empty string always fails
    return String.prototype.indexOf.call(this, val, byteOffset)
  }
  if (Buffer.isBuffer(val)) {
    return arrayIndexOf(this, val, byteOffset)
  }
  if (typeof val === 'number') {
    if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
      return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
    }
    return arrayIndexOf(this, [ val ], byteOffset)
  }

  function arrayIndexOf (arr, val, byteOffset) {
    var foundIndex = -1
    for (var i = 0; byteOffset + i < arr.length; i++) {
      if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
        if (foundIndex === -1) foundIndex = i
        if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
      } else {
        foundIndex = -1
      }
    }
    return -1
  }

  throw new TypeError('val must be string, number or Buffer')
}

// `get` is deprecated
Buffer.prototype.get = function get (offset) {
  console.log('.get() is deprecated. Access using array indexes instead.')
  return this.readUInt8(offset)
}

// `set` is deprecated
Buffer.prototype.set = function set (v, offset) {
  console.log('.set() is deprecated. Access using array indexes instead.')
  return this.writeUInt8(v, offset)
}

function hexWrite (buf, string, offset, length) {
  offset = Number(offset) || 0
  var remaining = buf.length - offset
  if (!length) {
    length = remaining
  } else {
    length = Number(length)
    if (length > remaining) {
      length = remaining
    }
  }

  // must be an even number of digits
  var strLen = string.length
  if (strLen % 2 !== 0) throw new Error('Invalid hex string')

  if (length > strLen / 2) {
    length = strLen / 2
  }
  for (var i = 0; i < length; i++) {
    var parsed = parseInt(string.substr(i * 2, 2), 16)
    if (isNaN(parsed)) throw new Error('Invalid hex string')
    buf[offset + i] = parsed
  }
  return i
}

function utf8Write (buf, string, offset, length) {
  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
}

function asciiWrite (buf, string, offset, length) {
  return blitBuffer(asciiToBytes(string), buf, offset, length)
}

function binaryWrite (buf, string, offset, length) {
  return asciiWrite(buf, string, offset, length)
}

function base64Write (buf, string, offset, length) {
  return blitBuffer(base64ToBytes(string), buf, offset, length)
}

function ucs2Write (buf, string, offset, length) {
  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
}

Buffer.prototype.write = function write (string, offset, length, encoding) {
  // Buffer#write(string)
  if (offset === undefined) {
    encoding = 'utf8'
    length = this.length
    offset = 0
  // Buffer#write(string, encoding)
  } else if (length === undefined && typeof offset === 'string') {
    encoding = offset
    length = this.length
    offset = 0
  // Buffer#write(string, offset[, length][, encoding])
  } else if (isFinite(offset)) {
    offset = offset | 0
    if (isFinite(length)) {
      length = length | 0
      if (encoding === undefined) encoding = 'utf8'
    } else {
      encoding = length
      length = undefined
    }
  // legacy write(string, encoding, offset, length) - remove in v0.13
  } else {
    var swap = encoding
    encoding = offset
    offset = length | 0
    length = swap
  }

  var remaining = this.length - offset
  if (length === undefined || length > remaining) length = remaining

  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
    throw new RangeError('attempt to write outside buffer bounds')
  }

  if (!encoding) encoding = 'utf8'

  var loweredCase = false
  for (;;) {
    switch (encoding) {
      case 'hex':
        return hexWrite(this, string, offset, length)

      case 'utf8':
      case 'utf-8':
        return utf8Write(this, string, offset, length)

      case 'ascii':
        return asciiWrite(this, string, offset, length)

      case 'binary':
        return binaryWrite(this, string, offset, length)

      case 'base64':
        // Warning: maxLength not taken into account in base64Write
        return base64Write(this, string, offset, length)

      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return ucs2Write(this, string, offset, length)

      default:
        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
        encoding = ('' + encoding).toLowerCase()
        loweredCase = true
    }
  }
}

Buffer.prototype.toJSON = function toJSON () {
  return {
    type: 'Buffer',
    data: Array.prototype.slice.call(this._arr || this, 0)
  }
}

function base64Slice (buf, start, end) {
  if (start === 0 && end === buf.length) {
    return base64.fromByteArray(buf)
  } else {
    return base64.fromByteArray(buf.slice(start, end))
  }
}

function utf8Slice (buf, start, end) {
  end = Math.min(buf.length, end)
  var res = []

  var i = start
  while (i < end) {
    var firstByte = buf[i]
    var codePoint = null
    var bytesPerSequence = (firstByte > 0xEF) ? 4
      : (firstByte > 0xDF) ? 3
      : (firstByte > 0xBF) ? 2
      : 1

    if (i + bytesPerSequence <= end) {
      var secondByte, thirdByte, fourthByte, tempCodePoint

      switch (bytesPerSequence) {
        case 1:
          if (firstByte < 0x80) {
            codePoint = firstByte
          }
          break
        case 2:
          secondByte = buf[i + 1]
          if ((secondByte & 0xC0) === 0x80) {
            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
            if (tempCodePoint > 0x7F) {
              codePoint = tempCodePoint
            }
          }
          break
        case 3:
          secondByte = buf[i + 1]
          thirdByte = buf[i + 2]
          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
              codePoint = tempCodePoint
            }
          }
          break
        case 4:
          secondByte = buf[i + 1]
          thirdByte = buf[i + 2]
          fourthByte = buf[i + 3]
          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
              codePoint = tempCodePoint
            }
          }
      }
    }

    if (codePoint === null) {
      // we did not generate a valid codePoint so insert a
      // replacement char (U+FFFD) and advance only 1 byte
      codePoint = 0xFFFD
      bytesPerSequence = 1
    } else if (codePoint > 0xFFFF) {
      // encode to utf16 (surrogate pair dance)
      codePoint -= 0x10000
      res.push(codePoint >>> 10 & 0x3FF | 0xD800)
      codePoint = 0xDC00 | codePoint & 0x3FF
    }

    res.push(codePoint)
    i += bytesPerSequence
  }

  return decodeCodePointsArray(res)
}

// Based on http://stackoverflow.com/a/22747272/680742, the browser with
// the lowest limit is Chrome, with 0x10000 args.
// We go 1 magnitude less, for safety
var MAX_ARGUMENTS_LENGTH = 0x1000

function decodeCodePointsArray (codePoints) {
  var len = codePoints.length
  if (len <= MAX_ARGUMENTS_LENGTH) {
    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
  }

  // Decode in chunks to avoid "call stack size exceeded".
  var res = ''
  var i = 0
  while (i < len) {
    res += String.fromCharCode.apply(
      String,
      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
    )
  }
  return res
}

function asciiSlice (buf, start, end) {
  var ret = ''
  end = Math.min(buf.length, end)

  for (var i = start; i < end; i++) {
    ret += String.fromCharCode(buf[i] & 0x7F)
  }
  return ret
}

function binarySlice (buf, start, end) {
  var ret = ''
  end = Math.min(buf.length, end)

  for (var i = start; i < end; i++) {
    ret += String.fromCharCode(buf[i])
  }
  return ret
}

function hexSlice (buf, start, end) {
  var len = buf.length

  if (!start || start < 0) start = 0
  if (!end || end < 0 || end > len) end = len

  var out = ''
  for (var i = start; i < end; i++) {
    out += toHex(buf[i])
  }
  return out
}

function utf16leSlice (buf, start, end) {
  var bytes = buf.slice(start, end)
  var res = ''
  for (var i = 0; i < bytes.length; i += 2) {
    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
  }
  return res
}

Buffer.prototype.slice = function slice (start, end) {
  var len = this.length
  start = ~~start
  end = end === undefined ? len : ~~end

  if (start < 0) {
    start += len
    if (start < 0) start = 0
  } else if (start > len) {
    start = len
  }

  if (end < 0) {
    end += len
    if (end < 0) end = 0
  } else if (end > len) {
    end = len
  }

  if (end < start) end = start

  var newBuf
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    newBuf = Buffer._augment(this.subarray(start, end))
  } else {
    var sliceLen = end - start
    newBuf = new Buffer(sliceLen, undefined)
    for (var i = 0; i < sliceLen; i++) {
      newBuf[i] = this[i + start]
    }
  }

  if (newBuf.length) newBuf.parent = this.parent || this

  return newBuf
}

/*
 * Need to make sure that buffer isn't trying to write out of bounds.
 */
function checkOffset (offset, ext, length) {
  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
}

Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkOffset(offset, byteLength, this.length)

  var val = this[offset]
  var mul = 1
  var i = 0
  while (++i < byteLength && (mul *= 0x100)) {
    val += this[offset + i] * mul
  }

  return val
}

Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) {
    checkOffset(offset, byteLength, this.length)
  }

  var val = this[offset + --byteLength]
  var mul = 1
  while (byteLength > 0 && (mul *= 0x100)) {
    val += this[offset + --byteLength] * mul
  }

  return val
}

Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 1, this.length)
  return this[offset]
}

Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  return this[offset] | (this[offset + 1] << 8)
}

Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  return (this[offset] << 8) | this[offset + 1]
}

Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return ((this[offset]) |
      (this[offset + 1] << 8) |
      (this[offset + 2] << 16)) +
      (this[offset + 3] * 0x1000000)
}

Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return (this[offset] * 0x1000000) +
    ((this[offset + 1] << 16) |
    (this[offset + 2] << 8) |
    this[offset + 3])
}

Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkOffset(offset, byteLength, this.length)

  var val = this[offset]
  var mul = 1
  var i = 0
  while (++i < byteLength && (mul *= 0x100)) {
    val += this[offset + i] * mul
  }
  mul *= 0x80

  if (val >= mul) val -= Math.pow(2, 8 * byteLength)

  return val
}

Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkOffset(offset, byteLength, this.length)

  var i = byteLength
  var mul = 1
  var val = this[offset + --i]
  while (i > 0 && (mul *= 0x100)) {
    val += this[offset + --i] * mul
  }
  mul *= 0x80

  if (val >= mul) val -= Math.pow(2, 8 * byteLength)

  return val
}

Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 1, this.length)
  if (!(this[offset] & 0x80)) return (this[offset])
  return ((0xff - this[offset] + 1) * -1)
}

Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  var val = this[offset] | (this[offset + 1] << 8)
  return (val & 0x8000) ? val | 0xFFFF0000 : val
}

Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  var val = this[offset + 1] | (this[offset] << 8)
  return (val & 0x8000) ? val | 0xFFFF0000 : val
}

Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return (this[offset]) |
    (this[offset + 1] << 8) |
    (this[offset + 2] << 16) |
    (this[offset + 3] << 24)
}

Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return (this[offset] << 24) |
    (this[offset + 1] << 16) |
    (this[offset + 2] << 8) |
    (this[offset + 3])
}

Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)
  return ieee754.read(this, offset, true, 23, 4)
}

Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)
  return ieee754.read(this, offset, false, 23, 4)
}

Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 8, this.length)
  return ieee754.read(this, offset, true, 52, 8)
}

Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 8, this.length)
  return ieee754.read(this, offset, false, 52, 8)
}

function checkInt (buf, value, offset, ext, max, min) {
  if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
  if (value > max || value < min) throw new RangeError('value is out of bounds')
  if (offset + ext > buf.length) throw new RangeError('index out of range')
}

Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)

  var mul = 1
  var i = 0
  this[offset] = value & 0xFF
  while (++i < byteLength && (mul *= 0x100)) {
    this[offset + i] = (value / mul) & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)

  var i = byteLength - 1
  var mul = 1
  this[offset + i] = value & 0xFF
  while (--i >= 0 && (mul *= 0x100)) {
    this[offset + i] = (value / mul) & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
  this[offset] = (value & 0xff)
  return offset + 1
}

function objectWriteUInt16 (buf, value, offset, littleEndian) {
  if (value < 0) value = 0xffff + value + 1
  for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
      (littleEndian ? i : 1 - i) * 8
  }
}

Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
  } else {
    objectWriteUInt16(this, value, offset, true)
  }
  return offset + 2
}

Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 8)
    this[offset + 1] = (value & 0xff)
  } else {
    objectWriteUInt16(this, value, offset, false)
  }
  return offset + 2
}

function objectWriteUInt32 (buf, value, offset, littleEndian) {
  if (value < 0) value = 0xffffffff + value + 1
  for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
  }
}

Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset + 3] = (value >>> 24)
    this[offset + 2] = (value >>> 16)
    this[offset + 1] = (value >>> 8)
    this[offset] = (value & 0xff)
  } else {
    objectWriteUInt32(this, value, offset, true)
  }
  return offset + 4
}

Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 24)
    this[offset + 1] = (value >>> 16)
    this[offset + 2] = (value >>> 8)
    this[offset + 3] = (value & 0xff)
  } else {
    objectWriteUInt32(this, value, offset, false)
  }
  return offset + 4
}

Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) {
    var limit = Math.pow(2, 8 * byteLength - 1)

    checkInt(this, value, offset, byteLength, limit - 1, -limit)
  }

  var i = 0
  var mul = 1
  var sub = value < 0 ? 1 : 0
  this[offset] = value & 0xFF
  while (++i < byteLength && (mul *= 0x100)) {
    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) {
    var limit = Math.pow(2, 8 * byteLength - 1)

    checkInt(this, value, offset, byteLength, limit - 1, -limit)
  }

  var i = byteLength - 1
  var mul = 1
  var sub = value < 0 ? 1 : 0
  this[offset + i] = value & 0xFF
  while (--i >= 0 && (mul *= 0x100)) {
    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
  if (value < 0) value = 0xff + value + 1
  this[offset] = (value & 0xff)
  return offset + 1
}

Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
  } else {
    objectWriteUInt16(this, value, offset, true)
  }
  return offset + 2
}

Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 8)
    this[offset + 1] = (value & 0xff)
  } else {
    objectWriteUInt16(this, value, offset, false)
  }
  return offset + 2
}

Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
    this[offset + 2] = (value >>> 16)
    this[offset + 3] = (value >>> 24)
  } else {
    objectWriteUInt32(this, value, offset, true)
  }
  return offset + 4
}

Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
  if (value < 0) value = 0xffffffff + value + 1
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 24)
    this[offset + 1] = (value >>> 16)
    this[offset + 2] = (value >>> 8)
    this[offset + 3] = (value & 0xff)
  } else {
    objectWriteUInt32(this, value, offset, false)
  }
  return offset + 4
}

function checkIEEE754 (buf, value, offset, ext, max, min) {
  if (value > max || value < min) throw new RangeError('value is out of bounds')
  if (offset + ext > buf.length) throw new RangeError('index out of range')
  if (offset < 0) throw new RangeError('index out of range')
}

function writeFloat (buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
  }
  ieee754.write(buf, value, offset, littleEndian, 23, 4)
  return offset + 4
}

Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
  return writeFloat(this, value, offset, true, noAssert)
}

Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
  return writeFloat(this, value, offset, false, noAssert)
}

function writeDouble (buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
  }
  ieee754.write(buf, value, offset, littleEndian, 52, 8)
  return offset + 8
}

Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
  return writeDouble(this, value, offset, true, noAssert)
}

Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
  return writeDouble(this, value, offset, false, noAssert)
}

// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function copy (target, targetStart, start, end) {
  if (!start) start = 0
  if (!end && end !== 0) end = this.length
  if (targetStart >= target.length) targetStart = target.length
  if (!targetStart) targetStart = 0
  if (end > 0 && end < start) end = start

  // Copy 0 bytes; we're done
  if (end === start) return 0
  if (target.length === 0 || this.length === 0) return 0

  // Fatal error conditions
  if (targetStart < 0) {
    throw new RangeError('targetStart out of bounds')
  }
  if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
  if (end < 0) throw new RangeError('sourceEnd out of bounds')

  // Are we oob?
  if (end > this.length) end = this.length
  if (target.length - targetStart < end - start) {
    end = target.length - targetStart + start
  }

  var len = end - start
  var i

  if (this === target && start < targetStart && targetStart < end) {
    // descending copy from end
    for (i = len - 1; i >= 0; i--) {
      target[i + targetStart] = this[i + start]
    }
  } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
    // ascending copy from start
    for (i = 0; i < len; i++) {
      target[i + targetStart] = this[i + start]
    }
  } else {
    target._set(this.subarray(start, start + len), targetStart)
  }

  return len
}

// fill(value, start=0, end=buffer.length)
Buffer.prototype.fill = function fill (value, start, end) {
  if (!value) value = 0
  if (!start) start = 0
  if (!end) end = this.length

  if (end < start) throw new RangeError('end < start')

  // Fill 0 bytes; we're done
  if (end === start) return
  if (this.length === 0) return

  if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
  if (end < 0 || end > this.length) throw new RangeError('end out of bounds')

  var i
  if (typeof value === 'number') {
    for (i = start; i < end; i++) {
      this[i] = value
    }
  } else {
    var bytes = utf8ToBytes(value.toString())
    var len = bytes.length
    for (i = start; i < end; i++) {
      this[i] = bytes[i % len]
    }
  }

  return this
}

/**
 * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
 * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
 */
Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
  if (typeof Uint8Array !== 'undefined') {
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      return (new Buffer(this)).buffer
    } else {
      var buf = new Uint8Array(this.length)
      for (var i = 0, len = buf.length; i < len; i += 1) {
        buf[i] = this[i]
      }
      return buf.buffer
    }
  } else {
    throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
  }
}

// HELPER FUNCTIONS
// ================

var BP = Buffer.prototype

/**
 * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
 */
Buffer._augment = function _augment (arr) {
  arr.constructor = Buffer
  arr._isBuffer = true

  // save reference to original Uint8Array set method before overwriting
  arr._set = arr.set

  // deprecated
  arr.get = BP.get
  arr.set = BP.set

  arr.write = BP.write
  arr.toString = BP.toString
  arr.toLocaleString = BP.toString
  arr.toJSON = BP.toJSON
  arr.equals = BP.equals
  arr.compare = BP.compare
  arr.indexOf = BP.indexOf
  arr.copy = BP.copy
  arr.slice = BP.slice
  arr.readUIntLE = BP.readUIntLE
  arr.readUIntBE = BP.readUIntBE
  arr.readUInt8 = BP.readUInt8
  arr.readUInt16LE = BP.readUInt16LE
  arr.readUInt16BE = BP.readUInt16BE
  arr.readUInt32LE = BP.readUInt32LE
  arr.readUInt32BE = BP.readUInt32BE
  arr.readIntLE = BP.readIntLE
  arr.readIntBE = BP.readIntBE
  arr.readInt8 = BP.readInt8
  arr.readInt16LE = BP.readInt16LE
  arr.readInt16BE = BP.readInt16BE
  arr.readInt32LE = BP.readInt32LE
  arr.readInt32BE = BP.readInt32BE
  arr.readFloatLE = BP.readFloatLE
  arr.readFloatBE = BP.readFloatBE
  arr.readDoubleLE = BP.readDoubleLE
  arr.readDoubleBE = BP.readDoubleBE
  arr.writeUInt8 = BP.writeUInt8
  arr.writeUIntLE = BP.writeUIntLE
  arr.writeUIntBE = BP.writeUIntBE
  arr.writeUInt16LE = BP.writeUInt16LE
  arr.writeUInt16BE = BP.writeUInt16BE
  arr.writeUInt32LE = BP.writeUInt32LE
  arr.writeUInt32BE = BP.writeUInt32BE
  arr.writeIntLE = BP.writeIntLE
  arr.writeIntBE = BP.writeIntBE
  arr.writeInt8 = BP.writeInt8
  arr.writeInt16LE = BP.writeInt16LE
  arr.writeInt16BE = BP.writeInt16BE
  arr.writeInt32LE = BP.writeInt32LE
  arr.writeInt32BE = BP.writeInt32BE
  arr.writeFloatLE = BP.writeFloatLE
  arr.writeFloatBE = BP.writeFloatBE
  arr.writeDoubleLE = BP.writeDoubleLE
  arr.writeDoubleBE = BP.writeDoubleBE
  arr.fill = BP.fill
  arr.inspect = BP.inspect
  arr.toArrayBuffer = BP.toArrayBuffer

  return arr
}

var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g

function base64clean (str) {
  // Node strips out invalid characters like \n and \t from the string, base64-js does not
  str = stringtrim(str).replace(INVALID_BASE64_RE, '')
  // Node converts strings with length < 2 to ''
  if (str.length < 2) return ''
  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
  while (str.length % 4 !== 0) {
    str = str + '='
  }
  return str
}

function stringtrim (str) {
  if (str.trim) return str.trim()
  return str.replace(/^\s+|\s+$/g, '')
}

function toHex (n) {
  if (n < 16) return '0' + n.toString(16)
  return n.toString(16)
}

function utf8ToBytes (string, units) {
  units = units || Infinity
  var codePoint
  var length = string.length
  var leadSurrogate = null
  var bytes = []

  for (var i = 0; i < length; i++) {
    codePoint = string.charCodeAt(i)

    // is surrogate component
    if (codePoint > 0xD7FF && codePoint < 0xE000) {
      // last char was a lead
      if (!leadSurrogate) {
        // no lead yet
        if (codePoint > 0xDBFF) {
          // unexpected trail
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          continue
        } else if (i + 1 === length) {
          // unpaired lead
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          continue
        }

        // valid lead
        leadSurrogate = codePoint

        continue
      }

      // 2 leads in a row
      if (codePoint < 0xDC00) {
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
        leadSurrogate = codePoint
        continue
      }

      // valid surrogate pair
      codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
    } else if (leadSurrogate) {
      // valid bmp char, but last char was a lead
      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
    }

    leadSurrogate = null

    // encode utf8
    if (codePoint < 0x80) {
      if ((units -= 1) < 0) break
      bytes.push(codePoint)
    } else if (codePoint < 0x800) {
      if ((units -= 2) < 0) break
      bytes.push(
        codePoint >> 0x6 | 0xC0,
        codePoint & 0x3F | 0x80
      )
    } else if (codePoint < 0x10000) {
      if ((units -= 3) < 0) break
      bytes.push(
        codePoint >> 0xC | 0xE0,
        codePoint >> 0x6 & 0x3F | 0x80,
        codePoint & 0x3F | 0x80
      )
    } else if (codePoint < 0x110000) {
      if ((units -= 4) < 0) break
      bytes.push(
        codePoint >> 0x12 | 0xF0,
        codePoint >> 0xC & 0x3F | 0x80,
        codePoint >> 0x6 & 0x3F | 0x80,
        codePoint & 0x3F | 0x80
      )
    } else {
      throw new Error('Invalid code point')
    }
  }

  return bytes
}

function asciiToBytes (str) {
  var byteArray = []
  for (var i = 0; i < str.length; i++) {
    // Node's code seems to be doing this and not & 0x7F..
    byteArray.push(str.charCodeAt(i) & 0xFF)
  }
  return byteArray
}

function utf16leToBytes (str, units) {
  var c, hi, lo
  var byteArray = []
  for (var i = 0; i < str.length; i++) {
    if ((units -= 2) < 0) break

    c = str.charCodeAt(i)
    hi = c >> 8
    lo = c % 256
    byteArray.push(lo)
    byteArray.push(hi)
  }

  return byteArray
}

function base64ToBytes (str) {
  return base64.toByteArray(base64clean(str))
}

function blitBuffer (src, dst, offset, length) {
  for (var i = 0; i < length; i++) {
    if ((i + offset >= dst.length) || (i >= src.length)) break
    dst[i + offset] = src[i]
  }
  return i
}

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"base64-js":4,"ieee754":5,"is-array":6}],4:[function(require,module,exports){
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

;(function (exports) {
	'use strict';

  var Arr = (typeof Uint8Array !== 'undefined')
    ? Uint8Array
    : Array

	var PLUS   = '+'.charCodeAt(0)
	var SLASH  = '/'.charCodeAt(0)
	var NUMBER = '0'.charCodeAt(0)
	var LOWER  = 'a'.charCodeAt(0)
	var UPPER  = 'A'.charCodeAt(0)
	var PLUS_URL_SAFE = '-'.charCodeAt(0)
	var SLASH_URL_SAFE = '_'.charCodeAt(0)

	function decode (elt) {
		var code = elt.charCodeAt(0)
		if (code === PLUS ||
		    code === PLUS_URL_SAFE)
			return 62 // '+'
		if (code === SLASH ||
		    code === SLASH_URL_SAFE)
			return 63 // '/'
		if (code < NUMBER)
			return -1 //no match
		if (code < NUMBER + 10)
			return code - NUMBER + 26 + 26
		if (code < UPPER + 26)
			return code - UPPER
		if (code < LOWER + 26)
			return code - LOWER + 26
	}

	function b64ToByteArray (b64) {
		var i, j, l, tmp, placeHolders, arr

		if (b64.length % 4 > 0) {
			throw new Error('Invalid string. Length must be a multiple of 4')
		}

		// the number of equal signs (place holders)
		// if there are two placeholders, than the two characters before it
		// represent one byte
		// if there is only one, then the three characters before it represent 2 bytes
		// this is just a cheap hack to not do indexOf twice
		var len = b64.length
		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0

		// base64 is 4/3 + up to two characters of the original data
		arr = new Arr(b64.length * 3 / 4 - placeHolders)

		// if there are placeholders, only get up to the last complete 4 chars
		l = placeHolders > 0 ? b64.length - 4 : b64.length

		var L = 0

		function push (v) {
			arr[L++] = v
		}

		for (i = 0, j = 0; i < l; i += 4, j += 3) {
			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
			push((tmp & 0xFF0000) >> 16)
			push((tmp & 0xFF00) >> 8)
			push(tmp & 0xFF)
		}

		if (placeHolders === 2) {
			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
			push(tmp & 0xFF)
		} else if (placeHolders === 1) {
			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
			push((tmp >> 8) & 0xFF)
			push(tmp & 0xFF)
		}

		return arr
	}

	function uint8ToBase64 (uint8) {
		var i,
			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
			output = "",
			temp, length

		function encode (num) {
			return lookup.charAt(num)
		}

		function tripletToBase64 (num) {
			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
		}

		// go through the array every three bytes, we'll deal with trailing stuff later
		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
			output += tripletToBase64(temp)
		}

		// pad the end with zeros, but make sure to not forget the extra bytes
		switch (extraBytes) {
			case 1:
				temp = uint8[uint8.length - 1]
				output += encode(temp >> 2)
				output += encode((temp << 4) & 0x3F)
				output += '=='
				break
			case 2:
				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
				output += encode(temp >> 10)
				output += encode((temp >> 4) & 0x3F)
				output += encode((temp << 2) & 0x3F)
				output += '='
				break
		}

		return output
	}

	exports.toByteArray = b64ToByteArray
	exports.fromByteArray = uint8ToBase64
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))

},{}],5:[function(require,module,exports){
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
  var e, m
  var eLen = nBytes * 8 - mLen - 1
  var eMax = (1 << eLen) - 1
  var eBias = eMax >> 1
  var nBits = -7
  var i = isLE ? (nBytes - 1) : 0
  var d = isLE ? -1 : 1
  var s = buffer[offset + i]

  i += d

  e = s & ((1 << (-nBits)) - 1)
  s >>= (-nBits)
  nBits += eLen
  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}

  m = e & ((1 << (-nBits)) - 1)
  e >>= (-nBits)
  nBits += mLen
  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}

  if (e === 0) {
    e = 1 - eBias
  } else if (e === eMax) {
    return m ? NaN : ((s ? -1 : 1) * Infinity)
  } else {
    m = m + Math.pow(2, mLen)
    e = e - eBias
  }
  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
}

exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
  var e, m, c
  var eLen = nBytes * 8 - mLen - 1
  var eMax = (1 << eLen) - 1
  var eBias = eMax >> 1
  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
  var i = isLE ? 0 : (nBytes - 1)
  var d = isLE ? 1 : -1
  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0

  value = Math.abs(value)

  if (isNaN(value) || value === Infinity) {
    m = isNaN(value) ? 1 : 0
    e = eMax
  } else {
    e = Math.floor(Math.log(value) / Math.LN2)
    if (value * (c = Math.pow(2, -e)) < 1) {
      e--
      c *= 2
    }
    if (e + eBias >= 1) {
      value += rt / c
    } else {
      value += rt * Math.pow(2, 1 - eBias)
    }
    if (value * c >= 2) {
      e++
      c /= 2
    }

    if (e + eBias >= eMax) {
      m = 0
      e = eMax
    } else if (e + eBias >= 1) {
      m = (value * c - 1) * Math.pow(2, mLen)
      e = e + eBias
    } else {
      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
      e = 0
    }
  }

  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}

  e = (e << mLen) | m
  eLen += mLen
  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}

  buffer[offset + i - d] |= s * 128
}

},{}],6:[function(require,module,exports){

/**
 * isArray
 */

var isArray = Array.isArray;

/**
 * toString
 */

var str = Object.prototype.toString;

/**
 * Whether or not the given `val`
 * is an array.
 *
 * example:
 *
 *        isArray([]);
 *        // > true
 *        isArray(arguments);
 *        // > false
 *        isArray('');
 *        // > false
 *
 * @param {mixed} val
 * @return {bool}
 */

module.exports = isArray || function (val) {
  return !! val && '[object Array]' == str.call(val);
};

},{}],7:[function(require,module,exports){
if (typeof Object.create === 'function') {
  // implementation from standard node.js 'util' module
  module.exports = function inherits(ctor, superCtor) {
    ctor.super_ = superCtor
    ctor.prototype = Object.create(superCtor.prototype, {
      constructor: {
        value: ctor,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
  };
} else {
  // old school shim for old browsers
  module.exports = function inherits(ctor, superCtor) {
    ctor.super_ = superCtor
    var TempCtor = function () {}
    TempCtor.prototype = superCtor.prototype
    ctor.prototype = new TempCtor()
    ctor.prototype.constructor = ctor
  }
}

},{}],8:[function(require,module,exports){
// shim for using process in browser

var process = module.exports = {};
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;

function cleanUpNextTick() {
    draining = false;
    if (currentQueue.length) {
        queue = currentQueue.concat(queue);
    } else {
        queueIndex = -1;
    }
    if (queue.length) {
        drainQueue();
    }
}

function drainQueue() {
    if (draining) {
        return;
    }
    var timeout = setTimeout(cleanUpNextTick);
    draining = true;

    var len = queue.length;
    while(len) {
        currentQueue = queue;
        queue = [];
        while (++queueIndex < len) {
            if (currentQueue) {
                currentQueue[queueIndex].run();
            }
        }
        queueIndex = -1;
        len = queue.length;
    }
    currentQueue = null;
    draining = false;
    clearTimeout(timeout);
}

process.nextTick = function (fun) {
    var args = new Array(arguments.length - 1);
    if (arguments.length > 1) {
        for (var i = 1; i < arguments.length; i++) {
            args[i - 1] = arguments[i];
        }
    }
    queue.push(new Item(fun, args));
    if (queue.length === 1 && !draining) {
        setTimeout(drainQueue, 0);
    }
};

// v8 likes predictible objects
function Item(fun, array) {
    this.fun = fun;
    this.array = array;
}
Item.prototype.run = function () {
    this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};

function noop() {}

process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;

process.binding = function (name) {
    throw new Error('process.binding is not supported');
};

process.cwd = function () { return '/' };
process.chdir = function (dir) {
    throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };

},{}],9:[function(require,module,exports){
module.exports = function isBuffer(arg) {
  return arg && typeof arg === 'object'
    && typeof arg.copy === 'function'
    && typeof arg.fill === 'function'
    && typeof arg.readUInt8 === 'function';
}
},{}],10:[function(require,module,exports){
(function (process,global){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
  if (!isString(f)) {
    var objects = [];
    for (var i = 0; i < arguments.length; i++) {
      objects.push(inspect(arguments[i]));
    }
    return objects.join(' ');
  }

  var i = 1;
  var args = arguments;
  var len = args.length;
  var str = String(f).replace(formatRegExp, function(x) {
    if (x === '%%') return '%';
    if (i >= len) return x;
    switch (x) {
      case '%s': return String(args[i++]);
      case '%d': return Number(args[i++]);
      case '%j':
        try {
          return JSON.stringify(args[i++]);
        } catch (_) {
          return '[Circular]';
        }
      default:
        return x;
    }
  });
  for (var x = args[i]; i < len; x = args[++i]) {
    if (isNull(x) || !isObject(x)) {
      str += ' ' + x;
    } else {
      str += ' ' + inspect(x);
    }
  }
  return str;
};


// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
exports.deprecate = function(fn, msg) {
  // Allow for deprecating things in the process of starting up.
  if (isUndefined(global.process)) {
    return function() {
      return exports.deprecate(fn, msg).apply(this, arguments);
    };
  }

  if (process.noDeprecation === true) {
    return fn;
  }

  var warned = false;
  function deprecated() {
    if (!warned) {
      if (process.throwDeprecation) {
        throw new Error(msg);
      } else if (process.traceDeprecation) {
        console.trace(msg);
      } else {
        console.error(msg);
      }
      warned = true;
    }
    return fn.apply(this, arguments);
  }

  return deprecated;
};


var debugs = {};
var debugEnviron;
exports.debuglog = function(set) {
  if (isUndefined(debugEnviron))
    debugEnviron = process.env.NODE_DEBUG || '';
  set = set.toUpperCase();
  if (!debugs[set]) {
    if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
      var pid = process.pid;
      debugs[set] = function() {
        var msg = exports.format.apply(exports, arguments);
        console.error('%s %d: %s', set, pid, msg);
      };
    } else {
      debugs[set] = function() {};
    }
  }
  return debugs[set];
};


/**
 * 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 {Object} opts Optional options object that alters the output.
 */
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
  // default options
  var ctx = {
    seen: [],
    stylize: stylizeNoColor
  };
  // legacy...
  if (arguments.length >= 3) ctx.depth = arguments[2];
  if (arguments.length >= 4) ctx.colors = arguments[3];
  if (isBoolean(opts)) {
    // legacy...
    ctx.showHidden = opts;
  } else if (opts) {
    // got an "options" object
    exports._extend(ctx, opts);
  }
  // set default options
  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
  if (isUndefined(ctx.depth)) ctx.depth = 2;
  if (isUndefined(ctx.colors)) ctx.colors = false;
  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
  if (ctx.colors) ctx.stylize = stylizeWithColor;
  return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;


// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
  'bold' : [1, 22],
  'italic' : [3, 23],
  'underline' : [4, 24],
  'inverse' : [7, 27],
  'white' : [37, 39],
  'grey' : [90, 39],
  'black' : [30, 39],
  'blue' : [34, 39],
  'cyan' : [36, 39],
  'green' : [32, 39],
  'magenta' : [35, 39],
  'red' : [31, 39],
  'yellow' : [33, 39]
};

// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
  'special': 'cyan',
  'number': 'yellow',
  'boolean': 'yellow',
  'undefined': 'grey',
  'null': 'bold',
  'string': 'green',
  'date': 'magenta',
  // "name": intentionally not styling
  'regexp': 'red'
};


function stylizeWithColor(str, styleType) {
  var style = inspect.styles[styleType];

  if (style) {
    return '\u001b[' + inspect.colors[style][0] + 'm' + str +
           '\u001b[' + inspect.colors[style][1] + 'm';
  } else {
    return str;
  }
}


function stylizeNoColor(str, styleType) {
  return str;
}


function arrayToHash(array) {
  var hash = {};

  array.forEach(function(val, idx) {
    hash[val] = true;
  });

  return hash;
}


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 (ctx.customInspect &&
      value &&
      isFunction(value.inspect) &&
      // Filter out the util module, it's inspect function is special
      value.inspect !== exports.inspect &&
      // Also filter out any prototype objects using the circular check.
      !(value.constructor && value.constructor.prototype === value)) {
    var ret = value.inspect(recurseTimes, ctx);
    if (!isString(ret)) {
      ret = formatValue(ctx, ret, recurseTimes);
    }
    return ret;
  }

  // Primitive types cannot have properties
  var primitive = formatPrimitive(ctx, value);
  if (primitive) {
    return primitive;
  }

  // Look up the keys of the object.
  var keys = Object.keys(value);
  var visibleKeys = arrayToHash(keys);

  if (ctx.showHidden) {
    keys = Object.getOwnPropertyNames(value);
  }

  // IE doesn't make error fields non-enumerable
  // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
  if (isError(value)
      && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
    return formatError(value);
  }

  // Some type of object without properties can be shortcutted.
  if (keys.length === 0) {
    if (isFunction(value)) {
      var name = value.name ? ': ' + value.name : '';
      return ctx.stylize('[Function' + name + ']', 'special');
    }
    if (isRegExp(value)) {
      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
    }
    if (isDate(value)) {
      return ctx.stylize(Date.prototype.toString.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 (isFunction(value)) {
    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)) {
    base = ' ' + 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) {
  if (isUndefined(value))
    return ctx.stylize('undefined', 'undefined');
  if (isString(value)) {
    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                             .replace(/'/g, "\\'")
                                             .replace(/\\"/g, '"') + '\'';
    return ctx.stylize(simple, 'string');
  }
  if (isNumber(value))
    return ctx.stylize('' + value, 'number');
  if (isBoolean(value))
    return ctx.stylize('' + value, 'boolean');
  // For some reason typeof null is "object", so special case here.
  if (isNull(value))
    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 (hasOwnProperty(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, desc;
  desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
  if (desc.get) {
    if (desc.set) {
      str = ctx.stylize('[Getter/Setter]', 'special');
    } else {
      str = ctx.stylize('[Getter]', 'special');
    }
  } else {
    if (desc.set) {
      str = ctx.stylize('[Setter]', 'special');
    }
  }
  if (!hasOwnProperty(visibleKeys, key)) {
    name = '[' + key + ']';
  }
  if (!str) {
    if (ctx.seen.indexOf(desc.value) < 0) {
      if (isNull(recurseTimes)) {
        str = formatValue(ctx, desc.value, null);
      } else {
        str = formatValue(ctx, desc.value, 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 (isUndefined(name)) {
    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.replace(/\u001b\[\d\d?m/g, '').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];
}


// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
  return Array.isArray(ar);
}
exports.isArray = isArray;

function isBoolean(arg) {
  return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;

function isNull(arg) {
  return arg === null;
}
exports.isNull = isNull;

function isNullOrUndefined(arg) {
  return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;

function isNumber(arg) {
  return typeof arg === 'number';
}
exports.isNumber = isNumber;

function isString(arg) {
  return typeof arg === 'string';
}
exports.isString = isString;

function isSymbol(arg) {
  return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;

function isUndefined(arg) {
  return arg === void 0;
}
exports.isUndefined = isUndefined;

function isRegExp(re) {
  return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;

function isObject(arg) {
  return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;

function isDate(d) {
  return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;

function isError(e) {
  return isObject(e) &&
      (objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;

function isFunction(arg) {
  return typeof arg === 'function';
}
exports.isFunction = isFunction;

function isPrimitive(arg) {
  return arg === null ||
         typeof arg === 'boolean' ||
         typeof arg === 'number' ||
         typeof arg === 'string' ||
         typeof arg === 'symbol' ||  // ES6 symbol
         typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;

exports.isBuffer = require('./support/isBuffer');

function objectToString(o) {
  return Object.prototype.toString.call(o);
}


function pad(n) {
  return n < 10 ? '0' + n.toString(10) : n.toString(10);
}


var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
              'Oct', 'Nov', 'Dec'];

// 26 Feb 16:19:34
function timestamp() {
  var d = new Date();
  var time = [pad(d.getHours()),
              pad(d.getMinutes()),
              pad(d.getSeconds())].join(':');
  return [d.getDate(), months[d.getMonth()], time].join(' ');
}


// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function() {
  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};


/**
 * Inherit the prototype methods from one constructor into another.
 *
 * The Function.prototype.inherits from lang.js rewritten as a standalone
 * function (not on Function.prototype). NOTE: If this file is to be loaded
 * during bootstrapping this function needs to be rewritten using some native
 * functions as prototype setup using normal JavaScript does not work as
 * expected during bootstrapping (see mirror.js in r114903).
 *
 * @param {function} ctor Constructor function which needs to inherit the
 *     prototype.
 * @param {function} superCtor Constructor function to inherit prototype from.
 */
exports.inherits = require('inherits');

exports._extend = function(origin, add) {
  // Don't do anything if add isn't an object
  if (!add || !isObject(add)) return origin;

  var keys = Object.keys(add);
  var i = keys.length;
  while (i--) {
    origin[keys[i]] = add[keys[i]];
  }
  return origin;
};

function hasOwnProperty(obj, prop) {
  return Object.prototype.hasOwnProperty.call(obj, prop);
}

}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./support/isBuffer":9,"_process":8,"inherits":7}],11:[function(require,module,exports){
(function (Buffer){
var toString = Object.prototype.toString;

var types = require('./types');

/**
 * Simple data function to store type information
 * @param {string} type Usually what is returned from typeof
 * @param {string} cls  Sanitized @Class via Object.prototype.toString
 * @param {string} sub  If type and cls the same, and need to specify somehow
 * @private
 * @example
 *
 * //for null
 * new Type('null');
 *
 * //for Date
 * new Type('object', 'date');
 *
 * //for Uint8Array
 *
 * new Type('object', 'typed-array', 'uint8');
 */
function Type(type, cls, sub) {
  this.type = type;
  this.cls = cls;
  this.sub = sub;
}

/**
 * Function to store type checks
 * @private
 */
function TypeChecker() {
  this.checks = [];
}

TypeChecker.prototype = {
  add: function(func) {
    this.checks.push(func);
    return this;
  },

  addTypeOf: function(type, res) {
    return this.add(function(obj, tpeOf) {
      if(tpeOf === type) {
        return new Type(res);
      }
    });
  },

  addClass: function(cls, res, sub) {
    return this.add(function(obj, tpeOf, objCls) {
      if(objCls === cls) {
        return new Type(types.OBJECT, res, sub);
      }
    });
  },

  getType: function(obj) {
    var typeOf = typeof obj;
    var cls = toString.call(obj);

    for(var i = 0, l = this.checks.length; i < l; i++) {
      var res = this.checks[i].call(this, obj, typeOf, cls);
      if(typeof res !== 'undefined') return res;
    }

  }
};

var main = new TypeChecker();

//TODO add iterators

main
  .addTypeOf(types.NUMBER, types.NUMBER)
  .addTypeOf(types.UNDEFINED, types.UNDEFINED)
  .addTypeOf(types.STRING, types.STRING)
  .addTypeOf(types.BOOLEAN, types.BOOLEAN)
  .addTypeOf(types.FUNCTION, types.FUNCTION)
  .addTypeOf(types.SYMBOL, types.SYMBOL)
  .add(function(obj, tpeOf) {
    if(obj === null) return new Type(types.NULL);
  })
  .addClass('[object String]', types.STRING)
  .addClass('[object Boolean]', types.BOOLEAN)
  .addClass('[object Number]', types.NUMBER)
  .addClass('[object Array]', types.ARRAY)
  .addClass('[object RegExp]', types.REGEXP)
  .addClass('[object Error]', types.ERROR)
  .addClass('[object Date]', types.DATE)
  .addClass('[object Arguments]', types.ARGUMENTS)
  .addClass('[object Math]')
  .addClass('[object JSON]')
  .addClass('[object ArrayBuffer]', types.ARRAY_BUFFER)
  .addClass('[object Int8Array]', types.TYPED_ARRAY, 'int8')
  .addClass('[object Uint8Array]', types.TYPED_ARRAY, 'uint8')
  .addClass('[object Uint8ClampedArray]', types.TYPED_ARRAY, 'uint8clamped')
  .addClass('[object Int16Array]', types.TYPED_ARRAY, 'int16')
  .addClass('[object Uint16Array]', types.TYPED_ARRAY, 'uint16')
  .addClass('[object Int32Array]', types.TYPED_ARRAY, 'int32')
  .addClass('[object Uint32Array]', types.TYPED_ARRAY, 'uint32')
  .addClass('[object Float32Array]', types.TYPED_ARRAY, 'float32')
  .addClass('[object Float64Array]', types.TYPED_ARRAY, 'float64')
  .addClass('[object DataView]', types.DATA_VIEW)
  .addClass('[object Map]', types.MAP)
  .addClass('[object WeakMap]', types.WEAK_MAP)
  .addClass('[object Set]', types.SET)
  .addClass('[object WeakSet]', types.WEAK_SET)
  .addClass('[object Promise]', types.PROMISE)
  .addClass('[object Blob]', types.BLOB)
  .addClass('[object File]', types.FILE)
  .addClass('[object FileList]', types.FILE_LIST)
  .addClass('[object XMLHttpRequest]', types.XHR)
  .add(function(obj) {
    if((typeof Promise === types.FUNCTION && obj instanceof Promise) ||
        (typeof obj.then === types.FUNCTION)) {
          return new Type(types.OBJECT, types.PROMISE);
        }
  })
  .add(function(obj) {
    if(typeof Buffer !== 'undefined' && obj instanceof Buffer) {
      return new Type(types.OBJECT, types.BUFFER);
    }
  })
  .add(function(obj) {
    if(typeof Node !== 'undefined' && obj instanceof Node) {
      return new Type(types.OBJECT, types.HTML_ELEMENT, obj.nodeName);
    }
  })
  .add(function(obj) {
    // probably at the begginging should be enough these checks
    if(obj.Boolean === Boolean && obj.Number === Number && obj.String === String && obj.Date === Date) {
      return new Type(types.OBJECT, types.HOST);
    }
  })
  .add(function() {
    return new Type(types.OBJECT);
  });

/**
 * Get type information of anything
 *
 * @param  {any} obj Anything that could require type information
 * @return {Type}    type info
 */
function getGlobalType(obj) {
  return main.getType(obj);
}

getGlobalType.checker = main;
getGlobalType.TypeChecker = TypeChecker;
getGlobalType.Type = Type;

Object.keys(types).forEach(function(typeName) {
  getGlobalType[typeName] = types[typeName];
});

module.exports = getGlobalType;

}).call(this,require("buffer").Buffer)
},{"./types":12,"buffer":3}],12:[function(require,module,exports){
var types = {
  NUMBER: 'number',
  UNDEFINED: 'undefined',
  STRING: 'string',
  BOOLEAN: 'boolean',
  OBJECT: 'object',
  FUNCTION: 'function',
  NULL: 'null',
  ARRAY: 'array',
  REGEXP: 'regexp',
  DATE: 'date',
  ERROR: 'error',
  ARGUMENTS: 'arguments',
  SYMBOL: 'symbol',
  ARRAY_BUFFER: 'array-buffer',
  TYPED_ARRAY: 'typed-array',
  DATA_VIEW: 'data-view',
  MAP: 'map',
  SET: 'set',
  WEAK_SET: 'weak-set',
  WEAK_MAP: 'weak-map',
  PROMISE: 'promise',

// node buffer
  BUFFER: 'buffer',

// dom html element
  HTML_ELEMENT: 'html-element',
  HTML_ELEMENT_TEXT: 'html-element-text',
  DOCUMENT: 'document',
  WINDOW: 'window',
  FILE: 'file',
  FILE_LIST: 'file-list',
  BLOB: 'blob',

  HOST: 'host',

  XHR: 'xhr'
};

module.exports = types;

},{}],13:[function(require,module,exports){
(function (Buffer){
/*eslint-env mocha*/

var assert = require('assert');

var format = require('../');

it('should format numbers', function() {
  assert.equal(format(10), '10');
  assert.equal(format(0.1e-5), '0.000001');
  assert.equal(format(-0), '-0');
  assert.equal(format(Infinity), 'Infinity');
  assert.equal(format(-Infinity), '-Infinity');
  assert.equal(format(NaN), 'NaN');
});

it('should format undefined', function() {
  assert.equal(format(undefined), 'undefined');
  assert.equal(format(void 0), 'undefined');
});

it('should format null', function() {
  assert.equal(format(null), 'null');
});

it('should format string', function() {
  assert.equal(format('abc'), "'abc'");
  assert.equal(format('abc" \' '), "'abc\" \\' '");
});

it('should format boolean', function() {
  assert.equal(format(true), 'true');
  assert.equal(format(false), 'false');
});

it('should format Symbols', function() {
  if(typeof Symbol != 'undefined' && Symbol.for) {
    assert.equal(format(Symbol.for('react.element')), 'Symbol(react.element)')
  }
})

it('should format primitive wrappers', function() {
  assert.equal(format(new Number(10)), 'Number { [[PrimitiveValue]]: 10 }');
  assert.equal(format(new Boolean(true)), 'Boolean { [[PrimitiveValue]]: true }');
  assert.equal(format(new String('abc')), 'String { [[PrimitiveValue]]: \'abc\' }');
});

it('should format primitive wrappers with keys', function() {
  var b = new Boolean(true);
  b.abc = 10;
  assert.equal(format(b), 'Boolean { abc: 10, [[PrimitiveValue]]: true }');

  var s = new String('abc');
  s.abc = 10;
  assert.equal(format(s), 'String { abc: 10, [[PrimitiveValue]]: \'abc\' }');
});

it('should format regex', function() {
  assert.equal(format(/abc/gi), '/abc/gi');
  assert.equal(format(new RegExp('abc', 'gi')), '/abc/gi');
});

it('should format regex with keys', function() {
  var r = /abc/gi;
  r.abc = 10;
  assert.equal(format(r), 'RegExp { /abc/gi abc: 10 }');
});

function fff() {
}

it('should format function', function() {
  var f = function() {
  };
  assert.equal(format(f), 'Function { name: \'\' }');

  assert.equal(format(fff), 'Function { name: \'fff\' }');
});

var getter = Object.create(null, {
  a: {
    get: function() {
      return 'aaa';
    }
  }
});
var setter = Object.create(null, {
  b: {
    set: function() {
    }
  }
});
var getterAndSetter = Object.create(null, {
  c: {
    get: function() {
      return 'ccc';
    },
    set: function() {
    }
  }
});

it('should format object', function() {
  assert.equal(format({a: 10, b: '10', '123': 'asd'}), "Object { '123': 'asd', a: 10, b: '10' }");

  assert.equal(format(getter, {keys: false}), '{ a: [Getter] }');
  assert.equal(format(setter, {keys: false}), '{ b: [Setter] }');
  assert.equal(format(getterAndSetter, {keys: false}), '{ c: [Getter/Setter] }');

  var obj = {a: 10};
  obj.b = obj;
  assert.equal(format(obj), 'Object { a: 10, b: [Circular] }');

  var w = {
    '\\': 1,
    '\\\\': 2,
    '\\\\\\': 3,
    '\\\\\\\\': 4
  };

  var y = ['a', 'b', 'c'];
  y['\\\\\\'] = 'd';

  assert.ok(format(w),
    'Object { \'\\\': 1, \'\\\\\': 2, \'\\\\\\\': 3, \'\\\\\\\\\': 4 }');
  assert.ok(format(y), '[ \'a\', \'b\', \'c\', \'\\\\\\\': \'d\' ]');
});

it('should format arguments', function() {
  var f = function() {
    return arguments;
  };
  assert.equal(format(f(1, 2, 3)), 'Arguments [ 1, 2, 3 ]');
});

it('should format arrays', function() {
  assert.equal(format([1, 2, 'abc']), 'Array [ 1, 2, \'abc\' ]');
});

it('should format node buffer', function() {
  if(typeof Buffer !== 'undefined') {
    var b = new Buffer('abc');
    assert.equal(format(b), 'Buffer [ 61, 62, 63 ]');
  }
});

it('should format typed arrays', function() {
  if(typeof ArrayBuffer != 'undefined') {
    var buffer = new ArrayBuffer(8);
    for(var i = 0; i < buffer.byteLength; i++) buffer[i] = 0x00;
    buffer[1] = 0x20;
    buffer[2] = 0x2;
    assert.equal(format(buffer), 'ArrayBuffer [ 00, 20, 02, 00, 00, 00, 00, 00 ]');

    var int8 = new Int8Array(3);
    int8[0] = 0x20;
    int8[1] = 0x2;
    assert.equal(format(int8), 'Int8Array [ 20, 02, 00 ]');

    var int16 = new Int16Array(3);
    int16[0] = 0x201;
    int16[1] = 0x2;
    assert.equal(format(int16), 'Int16Array [ 0201, 0002, 0000 ]');

    //var dataView = new DataView(buffer);
    //assert.equal(format(dataView), '[DataView: 00 20 02 00 00 00 00 00]');
  }
});

it('should format html elements', function() {
  if(typeof window != 'undefined' && typeof document != 'undefined') {
    var btn = document.createElement("BUTTON");
    var t = document.createTextNode("CLICK ME");
    btn.appendChild(t);

    assert.equal(format(btn), '<button>CLICK ME</button>');

    assert.equal(format(t), 'CLICK ME');
  }
});

it('should correctly indent', function() {
  assert.equal(format({ a: { b: 'abc' }, d: 'abc'}, { maxLineLength: 0 }), 'Object {\n  a: Object {\n    b: \'abc\'\n  },\n  d: \'abc\'\n}');
});

it('should format set', function() {
  if(typeof Set !== 'undefined') {
    assert.equal(format(new Set([1, 2, { a: 10}, 'abc'])),
      'Set { 1, 2, Object { a: 10 }, \'abc\' }');
    assert.equal(format(new Set([1, 2, { a: 10}, 'abc']), { maxLineLength: 0 }),
      'Set {\n  1,\n  2,\n  Object {\n    a: 10\n  },\n  \'abc\'\n}');
  }
});

it('should format map', function() {
  if(typeof Map !== 'undefined') {
    assert.equal(format(new Map([[1, 2], [2, 'abc'], [{ a: 10}, new Set()], ['abc', null]])),
      'Map { 1 => 2, 2 => \'abc\', Object { a: 10 } => Set {}, \'abc\' => null }');
    assert.equal(format(new Map([[1, 2], [2, 'abc'], [{ a: 10}, new Set()], ['abc', null]]), { maxLineLength: 10 }),
      'Map {\n  1 => 2,\n  2 => \'abc\',\n  Object { a: 10 } =>\n  Set {},\n  \'abc\' =>\n  null\n}');
  }
});

}).call(this,require("buffer").Buffer)
},{"../":1,"assert":2,"buffer":3}],14:[function(require,module,exports){
function addSpaces(v) {
  return v.split('\n').map(function(vv) { return '  ' + vv; }).join('\n');
}

function pad(str, value, filler) {
  str = String(str)
  var isRight = false;

  if(value < 0) {
    isRight = true;
    value = -value;
  }

  if(str.length < value) {
    var padding = new Array(value - str.length + 1).join(filler);
    return isRight ? str + padding : padding + str;
  } else{
    return str;
  }
}

module.exports = {
  addSpaces: addSpaces,
  pad: pad,
  pad0: function(str, value) {
    return pad(str, value, '0');
  }
};

},{}]},{},[13]);
/*eslint-env mocha*/

var assert = require('assert');

var format = require('../');

it('should format numbers', function() {
  assert.equal(format(10), '10');
  assert.equal(format(0.1e-5), '0.000001');
  assert.equal(format(-0), '-0');
  assert.equal(format(Infinity), 'Infinity');
  assert.equal(format(-Infinity), '-Infinity');
  assert.equal(format(NaN), 'NaN');
});

it('should format undefined', function() {
  assert.equal(format(undefined), 'undefined');
  assert.equal(format(void 0), 'undefined');
});

it('should format null', function() {
  assert.equal(format(null), 'null');
});

it('should format string', function() {
  assert.equal(format('abc'), "'abc'");
  assert.equal(format('abc" \' '), "'abc\" \\' '");
});

it('should format boolean', function() {
  assert.equal(format(true), 'true');
  assert.equal(format(false), 'false');
});

it('should format Symbols', function() {
  if(typeof Symbol != 'undefined' && Symbol.for) {
    assert.equal(format(Symbol.for('react.element')), 'Symbol(react.element)')
  }
})

it('should format primitive wrappers', function() {
  assert.equal(format(new Number(10)), 'Number { [[PrimitiveValue]]: 10 }');
  assert.equal(format(new Boolean(true)), 'Boolean { [[PrimitiveValue]]: true }');
  assert.equal(format(new String('abc')), 'String { [[PrimitiveValue]]: \'abc\' }');
});

it('should format primitive wrappers with keys', function() {
  var b = new Boolean(true);
  b.abc = 10;
  assert.equal(format(b), 'Boolean { abc: 10, [[PrimitiveValue]]: true }');

  var s = new String('abc');
  s.abc = 10;
  assert.equal(format(s), 'String { abc: 10, [[PrimitiveValue]]: \'abc\' }');
});

it('should format regex', function() {
  assert.equal(format(/abc/gi), '/abc/gi');
  assert.equal(format(new RegExp('abc', 'gi')), '/abc/gi');
});

it('should format regex with keys', function() {
  var r = /abc/gi;
  r.abc = 10;
  assert.equal(format(r), 'RegExp { /abc/gi abc: 10 }');
});

function fff() {
}

it('should format function', function() {
  var f = function() {
  };
  assert.equal(format(f), 'Function { name: \'\' }');

  assert.equal(format(fff), 'Function { name: \'fff\' }');
});

var getter = Object.create(null, {
  a: {
    get: function() {
      return 'aaa';
    }
  }
});
var setter = Object.create(null, {
  b: {
    set: function() {
    }
  }
});
var getterAndSetter = Object.create(null, {
  c: {
    get: function() {
      return 'ccc';
    },
    set: function() {
    }
  }
});

it('should format object', function() {
  assert.equal(format({a: 10, b: '10', '123': 'asd'}), "Object { '123': 'asd', a: 10, b: '10' }");

  assert.equal(format(getter, {keys: false}), '{ a: [Getter] }');
  assert.equal(format(setter, {keys: false}), '{ b: [Setter] }');
  assert.equal(format(getterAndSetter, {keys: false}), '{ c: [Getter/Setter] }');

  var obj = {a: 10};
  obj.b = obj;
  assert.equal(format(obj), 'Object { a: 10, b: [Circular] }');

  var w = {
    '\\': 1,
    '\\\\': 2,
    '\\\\\\': 3,
    '\\\\\\\\': 4
  };

  var y = ['a', 'b', 'c'];
  y['\\\\\\'] = 'd';

  assert.ok(format(w),
    'Object { \'\\\': 1, \'\\\\\': 2, \'\\\\\\\': 3, \'\\\\\\\\\': 4 }');
  assert.ok(format(y), '[ \'a\', \'b\', \'c\', \'\\\\\\\': \'d\' ]');
});

it('should format arguments', function() {
  var f = function() {
    return arguments;
  };
  assert.equal(format(f(1, 2, 3)), 'Arguments [ 1, 2, 3 ]');
});

it('should format arrays', function() {
  assert.equal(format([1, 2, 'abc']), 'Array [ 1, 2, \'abc\' ]');
});

it('should format node buffer', function() {
  if(typeof Buffer !== 'undefined') {
    var b = new Buffer('abc');
    assert.equal(format(b), 'Buffer [ 61, 62, 63 ]');
  }
});

it('should format typed arrays', function() {
  if(typeof ArrayBuffer != 'undefined') {
    var buffer = new ArrayBuffer(8);
    for(var i = 0; i < buffer.byteLength; i++) buffer[i] = 0x00;
    buffer[1] = 0x20;
    buffer[2] = 0x2;
    assert.equal(format(buffer), 'ArrayBuffer [ 00, 20, 02, 00, 00, 00, 00, 00 ]');

    var int8 = new Int8Array(3);
    int8[0] = 0x20;
    int8[1] = 0x2;
    assert.equal(format(int8), 'Int8Array [ 20, 02, 00 ]');

    var int16 = new Int16Array(3);
    int16[0] = 0x201;
    int16[1] = 0x2;
    assert.equal(format(int16), 'Int16Array [ 0201, 0002, 0000 ]');

    //var dataView = new DataView(buffer);
    //assert.equal(format(dataView), '[DataView: 00 20 02 00 00 00 00 00]');
  }
});

it('should format html elements', function() {
  if(typeof window != 'undefined' && typeof document != 'undefined') {
    var btn = document.createElement("BUTTON");
    var t = document.createTextNode("CLICK ME");
    btn.appendChild(t);

    assert.equal(format(btn), '<button>CLICK ME</button>');

    assert.equal(format(t), 'CLICK ME');
  }
});

it('should correctly indent', function() {
  assert.equal(format({ a: { b: 'abc' }, d: 'abc'}, { maxLineLength: 0 }), 'Object {\n  a: Object {\n    b: \'abc\'\n  },\n  d: \'abc\'\n}');
});

it('should format set', function() {
  if(typeof Set !== 'undefined') {
    assert.equal(format(new Set([1, 2, { a: 10}, 'abc'])),
      'Set { 1, 2, Object { a: 10 }, \'abc\' }');
    assert.equal(format(new Set([1, 2, { a: 10}, 'abc']), { maxLineLength: 0 }),
      'Set {\n  1,\n  2,\n  Object {\n    a: 10\n  },\n  \'abc\'\n}');
  }
});

it('should format map', function() {
  if(typeof Map !== 'undefined') {
    assert.equal(format(new Map([[1, 2], [2, 'abc'], [{ a: 10}, new Set()], ['abc', null]])),
      'Map { 1 => 2, 2 => \'abc\', Object { a: 10 } => Set {}, \'abc\' => null }');
    assert.equal(format(new Map([[1, 2], [2, 'abc'], [{ a: 10}, new Set()], ['abc', null]]), { maxLineLength: 10 }),
      'Map {\n  1 => 2,\n  2 => \'abc\',\n  Object { a: 10 } =>\n  Set {},\n  \'abc\' =>\n  null\n}');
  }
});
function addSpaces(v) {
  return v.split('\n').map(function(vv) { return '  ' + vv; }).join('\n');
}

function pad(str, value, filler) {
  str = String(str)
  var isRight = false;

  if(value < 0) {
    isRight = true;
    value = -value;
  }

  if(str.length < value) {
    var padding = new Array(value - str.length + 1).join(filler);
    return isRight ? str + padding : padding + str;
  } else{
    return str;
  }
}

module.exports = {
  addSpaces: addSpaces,
  pad: pad,
  pad0: function(str, value) {
    return pad(str, value, '0');
  }
};
# Logs
logs
*.log

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directory
# Commenting this out is preferred by some people, see
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
node_modules

# Users Environment Variables
.lock-wscript

.idea
The MIT License (MIT)

Copyright (c) 2014 

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

type
====

Simple module to resolve types
var toString = Object.prototype.toString;

var types = require('./types');

/**
 * Simple data function to store type information
 * @param {string} type Usually what is returned from typeof
 * @param {string} cls  Sanitized @Class via Object.prototype.toString
 * @param {string} sub  If type and cls the same, and need to specify somehow
 * @private
 * @example
 *
 * //for null
 * new Type('null');
 *
 * //for Date
 * new Type('object', 'date');
 *
 * //for Uint8Array
 *
 * new Type('object', 'typed-array', 'uint8');
 */
function Type(type, cls, sub) {
  this.type = type;
  this.cls = cls;
  this.sub = sub;
}

/**
 * Function to store type checks
 * @private
 */
function TypeChecker() {
  this.checks = [];
}

TypeChecker.prototype = {
  add: function(func) {
    this.checks.push(func);
    return this;
  },

  addTypeOf: function(type, res) {
    return this.add(function(obj, tpeOf) {
      if(tpeOf === type) {
        return new Type(res);
      }
    });
  },

  addClass: function(cls, res, sub) {
    return this.add(function(obj, tpeOf, objCls) {
      if(objCls === cls) {
        return new Type(types.OBJECT, res, sub);
      }
    });
  },

  getType: function(obj) {
    var typeOf = typeof obj;
    var cls = toString.call(obj);

    for(var i = 0, l = this.checks.length; i < l; i++) {
      var res = this.checks[i].call(this, obj, typeOf, cls);
      if(typeof res !== 'undefined') return res;
    }

  }
};

var main = new TypeChecker();

//TODO add iterators

main
  .addTypeOf(types.NUMBER, types.NUMBER)
  .addTypeOf(types.UNDEFINED, types.UNDEFINED)
  .addTypeOf(types.STRING, types.STRING)
  .addTypeOf(types.BOOLEAN, types.BOOLEAN)
  .addTypeOf(types.FUNCTION, types.FUNCTION)
  .addTypeOf(types.SYMBOL, types.SYMBOL)
  .add(function(obj, tpeOf) {
    if(obj === null) return new Type(types.NULL);
  })
  .addClass('[object String]', types.STRING)
  .addClass('[object Boolean]', types.BOOLEAN)
  .addClass('[object Number]', types.NUMBER)
  .addClass('[object Array]', types.ARRAY)
  .addClass('[object RegExp]', types.REGEXP)
  .addClass('[object Error]', types.ERROR)
  .addClass('[object Date]', types.DATE)
  .addClass('[object Arguments]', types.ARGUMENTS)
  .addClass('[object Math]')
  .addClass('[object JSON]')
  .addClass('[object ArrayBuffer]', types.ARRAY_BUFFER)
  .addClass('[object Int8Array]', types.TYPED_ARRAY, 'int8')
  .addClass('[object Uint8Array]', types.TYPED_ARRAY, 'uint8')
  .addClass('[object Uint8ClampedArray]', types.TYPED_ARRAY, 'uint8clamped')
  .addClass('[object Int16Array]', types.TYPED_ARRAY, 'int16')
  .addClass('[object Uint16Array]', types.TYPED_ARRAY, 'uint16')
  .addClass('[object Int32Array]', types.TYPED_ARRAY, 'int32')
  .addClass('[object Uint32Array]', types.TYPED_ARRAY, 'uint32')
  .addClass('[object Float32Array]', types.TYPED_ARRAY, 'float32')
  .addClass('[object Float64Array]', types.TYPED_ARRAY, 'float64')
  .addClass('[object DataView]', types.DATA_VIEW)
  .addClass('[object Map]', types.MAP)
  .addClass('[object WeakMap]', types.WEAK_MAP)
  .addClass('[object Set]', types.SET)
  .addClass('[object WeakSet]', types.WEAK_SET)
  .addClass('[object Promise]', types.PROMISE)
  .addClass('[object Blob]', types.BLOB)
  .addClass('[object File]', types.FILE)
  .addClass('[object FileList]', types.FILE_LIST)
  .addClass('[object XMLHttpRequest]', types.XHR)
  .add(function(obj) {
    if((typeof Promise === types.FUNCTION && obj instanceof Promise) ||
        (typeof obj.then === types.FUNCTION)) {
          return new Type(types.OBJECT, types.PROMISE);
        }
  })
  .add(function(obj) {
    if(typeof Buffer !== 'undefined' && obj instanceof Buffer) {
      return new Type(types.OBJECT, types.BUFFER);
    }
  })
  .add(function(obj) {
    if(typeof Node !== 'undefined' && obj instanceof Node) {
      return new Type(types.OBJECT, types.HTML_ELEMENT, obj.nodeName);
    }
  })
  .add(function(obj) {
    // probably at the begginging should be enough these checks
    if(obj.Boolean === Boolean && obj.Number === Number && obj.String === String && obj.Date === Date) {
      return new Type(types.OBJECT, types.HOST);
    }
  })
  .add(function() {
    return new Type(types.OBJECT);
  });

/**
 * Get type information of anything
 *
 * @param  {any} obj Anything that could require type information
 * @return {Type}    type info
 */
function getGlobalType(obj) {
  return main.getType(obj);
}

getGlobalType.checker = main;
getGlobalType.TypeChecker = TypeChecker;
getGlobalType.Type = Type;

Object.keys(types).forEach(function(typeName) {
  getGlobalType[typeName] = types[typeName];
});

module.exports = getGlobalType;
{
  "name": "should-type",
  "version": "0.2.0",
  "description": "Simple module to get instance type. Like a bit more advanced version of typeof",
  "main": "index.js",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/shouldjs/type.git"
  },
  "keywords": [
    "should",
    "type"
  ],
  "author": {
    "name": "Denis Bardadym",
    "email": "bardadymchik@gmail.com"
  },
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/shouldjs/type/issues"
  },
  "homepage": "https://github.com/shouldjs/type",
  "gitHead": "3ae89bfac659a5c5afbb176622f9773bcabd0a66",
  "_id": "should-type@0.2.0",
  "scripts": {},
  "_shasum": "6707ef95529d989dcc098fe0753ab1f9136bb7f6",
  "_from": "should-type@0.2.0",
  "_npmVersion": "2.11.1",
  "_nodeVersion": "2.3.0",
  "_npmUser": {
    "name": "btd",
    "email": "bardadymchik@gmail.com"
  },
  "maintainers": [
    {
      "name": "btd",
      "email": "bardadymchik@gmail.com"
    }
  ],
  "dist": {
    "shasum": "6707ef95529d989dcc098fe0753ab1f9136bb7f6",
    "tarball": "http://registry.npmjs.org/should-type/-/should-type-0.2.0.tgz"
  },
  "directories": {},
  "_resolved": "https://registry.npmjs.org/should-type/-/should-type-0.2.0.tgz",
  "readme": "ERROR: No README data found!"
}
var types = {
  NUMBER: 'number',
  UNDEFINED: 'undefined',
  STRING: 'string',
  BOOLEAN: 'boolean',
  OBJECT: 'object',
  FUNCTION: 'function',
  NULL: 'null',
  ARRAY: 'array',
  REGEXP: 'regexp',
  DATE: 'date',
  ERROR: 'error',
  ARGUMENTS: 'arguments',
  SYMBOL: 'symbol',
  ARRAY_BUFFER: 'array-buffer',
  TYPED_ARRAY: 'typed-array',
  DATA_VIEW: 'data-view',
  MAP: 'map',
  SET: 'set',
  WEAK_SET: 'weak-set',
  WEAK_MAP: 'weak-map',
  PROMISE: 'promise',

// node buffer
  BUFFER: 'buffer',

// dom html element
  HTML_ELEMENT: 'html-element',
  HTML_ELEMENT_TEXT: 'html-element-text',
  DOCUMENT: 'document',
  WINDOW: 'window',
  FILE: 'file',
  FILE_LIST: 'file-list',
  BLOB: 'blob',

  HOST: 'host',

  XHR: 'xhr'
};

module.exports = types;
{
  "name": "should",
  "description": "test framework agnostic BDD-style assertions",
  "version": "8.0.1",
  "author": {
    "name": "TJ Holowaychuk",
    "email": "tj@vision-media.ca"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/shouldjs/should.js.git"
  },
  "homepage": "https://github.com/shouldjs/should.js",
  "scripts": {
    "test": "mocha -R mocha-better-spec-reporter --check-leaks ./test/*.test.js ./test/**/*.test.js",
    "zuul": "zuul -- ./test/**/*.test.js ./test/*.test.js",
    "browser": "gulp script"
  },
  "devDependencies": {
    "bluebird": "^3.0.6",
    "browserify": "latest",
    "eslint": "^1.10.3",
    "eslint-config-eslint": "^1.0.1",
    "gulp": "^3.8.10",
    "gulp-header": "^1.2.2",
    "gulp-rename": "^1.2.0",
    "gulp-uglify": "^1.0.1",
    "mocha": "latest",
    "mocha-better-spec-reporter": "latest",
    "vinyl-buffer": "^1.0.0",
    "vinyl-source-stream": "^1.1.0",
    "zuul": "latest"
  },
  "keywords": [
    "test",
    "bdd",
    "assert",
    "should"
  ],
  "main": "./index.js",
  "license": "MIT",
  "dependencies": {
    "should-equal": "0.5.0",
    "should-format": "0.3.1",
    "should-type": "0.2.0"
  },
  "gitHead": "49c4b55121a37500b2ec1755d10dff3f22b01380",
  "bugs": {
    "url": "https://github.com/shouldjs/should.js/issues"
  },
  "_id": "should@8.0.1",
  "_shasum": "3a3a7117d45f29a367bc129c878a303ec1ef640a",
  "_from": "should@8.0.1",
  "_npmVersion": "3.3.12",
  "_nodeVersion": "5.2.0",
  "_npmUser": {
    "name": "btd",
    "email": "bardadymchik@gmail.com"
  },
  "dist": {
    "shasum": "3a3a7117d45f29a367bc129c878a303ec1ef640a",
    "tarball": "http://registry.npmjs.org/should/-/should-8.0.1.tgz"
  },
  "maintainers": [
    {
      "name": "tjholowaychuk",
      "email": "tj@vision-media.ca"
    },
    {
      "name": "gjohnson",
      "email": "gjj391@gmail.com"
    },
    {
      "name": "travisjeffery",
      "email": "tj@travisjeffery.com"
    },
    {
      "name": "btd",
      "email": "bardadymchik@gmail.com"
    }
  ],
  "directories": {},
  "_resolved": "https://registry.npmjs.org/should/-/should-8.0.1.tgz"
}
/*!
 * should - test framework agnostic BDD-style assertions
 * @version v8.0.1
 * @author TJ Holowaychuk <tj@vision-media.ca> and contributors
 * @link https://github.com/shouldjs/should.js
 * @license MIT
 */
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Should = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
window.Should = require('./index');

Object.defineProperty(window, 'should', {
  enumerable: false,
  configurable: true,
  value: window.Should
});

},{"./index":2}],2:[function(require,module,exports){
var should = require('./lib/should');

var defaultProto = Object.prototype;
var defaultProperty = 'should';

//Expose api via `Object#should`.
try {
  var prevShould = should.extend(defaultProperty, defaultProto);
  should._prevShould = prevShould;
} catch(e) {
  //ignore errors
}

module.exports = should;

},{"./lib/should":19}],3:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('./util');

/**
 * should AssertionError
 * @param {Object} options
 * @constructor
 * @memberOf should
 * @static
 */
var AssertionError = function AssertionError(options) {
  util.merge(this, options);

  if(!options.message) {
    Object.defineProperty(this, 'message', {
        get: function() {
          if(!this._message) {
            this._message = this.generateMessage();
            this.generatedMessage = true;
          }
          return this._message;
        },
        configurable: true,
        enumerable: false
      }
    );
  }

  if(Error.captureStackTrace) {
    Error.captureStackTrace(this, this.stackStartFunction);
  } else {
    // non v8 browsers so we can have a stacktrace
    var err = new Error();
    if(err.stack) {
      var out = err.stack;

      if(this.stackStartFunction) {
        // try to strip useless frames
        var fn_name = util.functionName(this.stackStartFunction);
        var idx = out.indexOf('\n' + fn_name);
        if(idx >= 0) {
          // once we have located the function frame
          // we need to strip out everything before it (and its line)
          var next_line = out.indexOf('\n', idx + 1);
          out = out.substring(next_line + 1);
        }
      }

      this.stack = out;
    }
  }
};


var indent = '    ';
function prependIndent(line) {
  return indent + line;
}

function indentLines(text) {
  return text.split('\n').map(prependIndent).join('\n');
}


// assert.AssertionError instanceof Error
AssertionError.prototype = Object.create(Error.prototype, {
  name: {
    value: 'AssertionError'
  },

  generateMessage: {
    value: function() {
      if(!this.operator && this.previous) {
        return this.previous.message;
      }
      var actual = util.format(this.actual);
      var expected = 'expected' in this ? ' ' + util.format(this.expected) : '';
      var details = 'details' in this && this.details ? ' (' + this.details + ')' : '';

      var previous = this.previous ? '\n' + indentLines(this.previous.message) : '';

      return 'expected ' + actual + (this.negate ? ' not ' : ' ') + this.operator + expected + details + previous;
    }
  }
});

module.exports = AssertionError;

},{"./util":20}],4:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var AssertionError = require('./assertion-error');

/**
 * should Assertion
 * @param {*} obj Given object for assertion
 * @constructor
 * @memberOf should
 * @static
 */
function Assertion(obj) {
  this.obj = obj;

  this.anyOne = false;
  this.negate = false;

  this.params = {actual: obj};
}

Assertion.prototype = {
  constructor: Assertion,

  /**
   * Base method for assertions.
   *
   * Before calling this method need to fill Assertion#params object. This method usually called from other assertion methods.
   * `Assertion#params` can contain such properties:
   * * `operator` - required string containing description of this assertion
   * * `obj` - optional replacement for this.obj, it usefull if you prepare more clear object then given
   * * `message` - if this property filled with string any others will be ignored and this one used as assertion message
   * * `expected` - any object used when you need to assert relation between given object and expected. Like given == expected (== is a relation)
   * * `details` - additional string with details to generated message
   *
   * @memberOf Assertion
   * @category assertion
   * @param {*} expr Any expression that will be used as a condition for asserting.
   * @example
   *
   * var a = new should.Assertion(42);
   *
   * a.params = {
   *  operator: 'to be magic number',
   * }
   *
   * a.assert(false);
   * //throws AssertionError: expected 42 to be magic number
   */
  assert: function(expr) {
    if(expr) {
      return this;
    }

    var params = this.params;

    if('obj' in params && !('actual' in params)) {
      params.actual = params.obj;
    } else if(!('obj' in params) && !('actual' in params)) {
      params.actual = this.obj;
    }

    params.stackStartFunction = params.stackStartFunction || this.assert;
    params.negate = this.negate;

    params.assertion = this;

    throw new AssertionError(params);
  },

  /**
   * Shortcut for `Assertion#assert(false)`.
   *
   * @memberOf Assertion
   * @category assertion
   * @example
   *
   * var a = new should.Assertion(42);
   *
   * a.params = {
   *  operator: 'to be magic number',
   * }
   *
   * a.fail();
   * //throws AssertionError: expected 42 to be magic number
   */
  fail: function() {
    return this.assert(false);
  }
};



/**
 * Assertion used to delegate calls of Assertion methods inside of Promise.
 * It has almost all methods of Assertion.prototype
 *
 * @param {Promise} obj
 */
function PromisedAssertion(/* obj */) {
  Assertion.apply(this, arguments);
}

/**
 * Make PromisedAssertion to look like promise. Delegate resolve and reject to given promise.
 * 
 * @private
 * @returns {Promise}
 */
PromisedAssertion.prototype.then = function(resolve, reject) {
  return this.obj.then(resolve, reject);
};

/**
 * Way to extend Assertion function. It uses some logic
 * to define only positive assertions and itself rule with negative assertion.
 *
 * All actions happen in subcontext and this method take care about negation.
 * Potentially we can add some more modifiers that does not depends from state of assertion.
 *
 * @memberOf Assertion
 * @static
 * @param {String} name Name of assertion. It will be used for defining method or getter on Assertion.prototype
 * @param {Function} func Function that will be called on executing assertion
 * @example
 *
 * Assertion.add('asset', function() {
 *      this.params = { operator: 'to be asset' }
 *
 *      this.obj.should.have.property('id').which.is.a.Number()
 *      this.obj.should.have.property('path')
 * })
 */
Assertion.add = function(name, func) {
  Object.defineProperty(Assertion.prototype, name, {
    enumerable: true,
    configurable: true,
    value: function() {
      var context = new Assertion(this.obj, this, name);
      context.anyOne = this.anyOne;

      try {
        func.apply(context, arguments);
      } catch (e) {
        // check for fail
        if (e instanceof AssertionError) {
          // negative fail
          if (this.negate) {
            this.obj = context.obj;
            this.negate = false;
            return this;
          }

          if (context !== e.assertion) {
            context.params.previous = e;
          }

          // positive fail
          context.negate = false;
          context.fail();
        }
        // throw if it is another exception
        throw e;
      }

      // negative pass
      if (this.negate) {
        context.negate = true; // because .fail will set negate
        context.params.details = 'false negative fail';
        context.fail();
      }

      // positive pass
      if (!this.params.operator) {
        this.params = context.params; // shortcut
      }
      this.obj = context.obj;
      this.negate = false;
      return this;
    }
  });

  Object.defineProperty(PromisedAssertion.prototype, name, {
    enumerable: true,
    configurable: true,
    value: function() {
      var args = arguments;
      this.obj = this.obj.then(function(a) {
        return a[name].apply(a, args);
      });

      return this;
    }
  });
};

/**
 * Add chaining getter to Assertion like .a, .which etc
 * 
 * @memberOf Assertion
 * @static
 * @param  {string} name   name of getter
 * @param  {function} [onCall] optional function to call
 */
Assertion.addChain = function(name, onCall) {
  onCall = onCall || function() {};
  Object.defineProperty(Assertion.prototype, name, {
    get: function() {
      onCall.call(this);
      return this;
    },
    enumerable: true
  });

  Object.defineProperty(PromisedAssertion.prototype, name, {
    enumerable: true,
    configurable: true,
    get: function() {
      this.obj = this.obj.then(function(a) {
        return a[name];
      });

      return this;
    }
  });
};

/**
 * Create alias for some `Assertion` property
 *
 * @memberOf Assertion
 * @static
 * @param {String} from Name of to map
 * @param {String} to Name of alias
 * @example
 *
 * Assertion.alias('true', 'True')
 */
Assertion.alias = function(from, to) {
  var desc = Object.getOwnPropertyDescriptor(Assertion.prototype, from);
  if (!desc) throw new Error('Alias ' + from + ' -> ' + to + ' could not be created as ' + from + ' not defined');
  Object.defineProperty(Assertion.prototype, to, desc);

  var desc2 = Object.getOwnPropertyDescriptor(PromisedAssertion.prototype, from);
  if (desc2) {
    Object.defineProperty(PromisedAssertion.prototype, to, desc2);
  }
};
/**
 * Negation modifier. Current assertion chain become negated. Each call invert negation on current assertion.
 *
 * @name not
 * @property
 * @memberOf Assertion
 * @category assertion
 */
Assertion.addChain('not', function() {
  this.negate = !this.negate;
});

/**
 * Any modifier - it affect on execution of sequenced assertion to do not `check all`, but `check any of`.
 *
 * @name any
 * @property
 * @memberOf Assertion
 * @category assertion
 */
Assertion.addChain('any', function() {
  this.anyOne = true;
});

module.exports = Assertion;
module.exports.PromisedAssertion = PromisedAssertion;

},{"./assertion-error":3}],5:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var Formatter = require('should-format').Formatter;

var config = {
  checkProtoEql: false,

  getFormatter: function(opts) {
    return new Formatter(opts || config);
  }
};

module.exports = config;

},{"should-format":23}],6:[function(require,module,exports){
// implement assert interface using already written peaces of should.js

// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// when used in node, this will actually load the util module we depend on
// versus loading the builtin util module as happens otherwise
// this is a bug in node module loading as far as I am concerned
var Assertion = require('./../assertion');

var _deepEqual = require('should-equal');

var pSlice = Array.prototype.slice;

// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.

var assert = module.exports = ok;

// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided.  All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
/**
 * Node.js standard [`assert.fail`](http://nodejs.org/api/assert.html#assert_assert_fail_actual_expected_message_operator).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual Actual object
 * @param {*} expected Expected object
 * @param {string} message Message for assertion
 * @param {string} operator Operator text
 */
function fail(actual, expected, message, operator, stackStartFunction) {
  var a = new Assertion(actual);
  a.params = {
    operator: operator,
    expected: expected,
    message: message,
    stackStartFunction: stackStartFunction || fail
  };

  a.fail();
}

// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;

// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
/**
 * Node.js standard [`assert.ok`](http://nodejs.org/api/assert.html#assert_assert_value_message_assert_ok_value_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} value
 * @param {string} [message]
 */
function ok(value, message) {
  if(!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;

// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);

/**
 * Node.js standard [`assert.equal`](http://nodejs.org/api/assert.html#assert_assert_equal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.equal = function equal(actual, expected, message) {
  if(actual != expected) fail(actual, expected, message, '==', assert.equal);
};

// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
/**
 * Node.js standard [`assert.notEqual`](http://nodejs.org/api/assert.html#assert_assert_notequal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.notEqual = function notEqual(actual, expected, message) {
  if(actual == expected) {
    fail(actual, expected, message, '!=', assert.notEqual);
  }
};

// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
/**
 * Node.js standard [`assert.deepEqual`](http://nodejs.org/api/assert.html#assert_assert_deepequal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.deepEqual = function deepEqual(actual, expected, message) {
  if(!_deepEqual(actual, expected).result) {
    fail(actual, expected, message, 'deepEqual', assert.deepEqual);
  }
};


// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
/**
 * Node.js standard [`assert.notDeepEqual`](http://nodejs.org/api/assert.html#assert_assert_notdeepequal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
  if(_deepEqual(actual, expected).result) {
    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
  }
};

// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
/**
 * Node.js standard [`assert.strictEqual`](http://nodejs.org/api/assert.html#assert_assert_strictequal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.strictEqual = function strictEqual(actual, expected, message) {
  if(actual !== expected) {
    fail(actual, expected, message, '===', assert.strictEqual);
  }
};

// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);
/**
 * Node.js standard [`assert.notStrictEqual`](http://nodejs.org/api/assert.html#assert_assert_notstrictequal_actual_expected_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {*} actual
 * @param {*} expected
 * @param {string} [message]
 */
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
  if(actual === expected) {
    fail(actual, expected, message, '!==', assert.notStrictEqual);
  }
};

function expectedException(actual, expected) {
  if(!actual || !expected) {
    return false;
  }

  if(Object.prototype.toString.call(expected) == '[object RegExp]') {
    return expected.test(actual);
  } else if(actual instanceof expected) {
    return true;
  } else if(expected.call({}, actual) === true) {
    return true;
  }

  return false;
}

function _throws(shouldThrow, block, expected, message) {
  var actual;

  if(typeof expected == 'string') {
    message = expected;
    expected = null;
  }

  try {
    block();
  } catch(e) {
    actual = e;
  }

  message = (expected && expected.name ? ' (' + expected.name + ')' : '.') +
  (message ? ' ' + message : '.');

  if(shouldThrow && !actual) {
    fail(actual, expected, 'Missing expected exception' + message);
  }

  if(!shouldThrow && expectedException(actual, expected)) {
    fail(actual, expected, 'Got unwanted exception' + message);
  }

  if((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) {
    throw actual;
  }
}

// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
/**
 * Node.js standard [`assert.throws`](http://nodejs.org/api/assert.html#assert_assert_throws_block_error_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {Function} block
 * @param {Function} [error]
 * @param {String} [message]
 */
assert.throws = function(block, /*optional*/error, /*optional*/message) {
  _throws.apply(this, [true].concat(pSlice.call(arguments)));
};

// EXTENSION! This is annoying to write outside this module.
/**
 * Node.js standard [`assert.doesNotThrow`](http://nodejs.org/api/assert.html#assert_assert_doesnotthrow_block_message).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {Function} block
 * @param {String} [message]
 */
assert.doesNotThrow = function(block, /*optional*/message) {
  _throws.apply(this, [false].concat(pSlice.call(arguments)));
};

/**
 * Node.js standard [`assert.ifError`](http://nodejs.org/api/assert.html#assert_assert_iferror_value).
 * @static
 * @memberOf should
 * @category assertion assert
 * @param {Error} err
 */
assert.ifError = function(err) {
  if(err) {
    throw err;
  }
};

},{"./../assertion":4,"should-equal":22}],7:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util')
  , assert = require('./_assert')
  , AssertionError = require('../assertion-error');

module.exports = function(should) {
  var i = should.format;

  /*
   * Expose assert to should
   *
   * This allows you to do things like below
   * without require()ing the assert module.
   *
   *    should.equal(foo.bar, undefined);
   *
   */
  util.merge(should, assert);

  /**
   * Assert _obj_ exists, with optional message.
   *
   * @static
   * @memberOf should
   * @category assertion assert
   * @alias should.exists
   * @param {*} obj
   * @param {String} [msg]
   * @example
   *
   * should.exist(1);
   * should.exist(new Date());
   */
  should.exist = should.exists = function(obj, msg) {
    if(null == obj) {
      throw new AssertionError({
        message: msg || ('expected ' + i(obj) + ' to exist'), stackStartFunction: should.exist
      });
    }
  };

  should.not = {};
  /**
   * Asserts _obj_ does not exist, with optional message.
   *
   * @name not.exist
   * @static
   * @memberOf should
   * @category assertion assert
   * @alias should.not.exists
   * @param {*} obj
   * @param {String} [msg]
   * @example
   *
   * should.not.exist(null);
   * should.not.exist(void 0);
   */
  should.not.exist = should.not.exists = function(obj, msg) {
    if(null != obj) {
      throw new AssertionError({
        message: msg || ('expected ' + i(obj) + ' to not exist'), stackStartFunction: should.not.exist
      });
    }
  };
};
},{"../assertion-error":3,"../util":20,"./_assert":6}],8:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

module.exports = function(should, Assertion) {
  /**
   * Assert given object is exactly `true`.
   *
   * @name true
   * @memberOf Assertion
   * @category assertion bool
   * @alias Assertion#True
   * @example
   *
   * (true).should.be.true();
   * false.should.not.be.true();
   *
   * ({ a: 10}).should.not.be.true();
   */
  Assertion.add('true', function() {
    this.is.exactly(true);
  });

  Assertion.alias('true', 'True');

  /**
   * Assert given object is exactly `false`.
   *
   * @name false
   * @memberOf Assertion
   * @category assertion bool
   * @alias Assertion#False
   * @example
   *
   * (true).should.not.be.false();
   * false.should.be.false();
   */
  Assertion.add('false', function() {
    this.is.exactly(false);
  });

  Assertion.alias('false', 'False');

  /**
   * Assert given object is thuthy according javascript type conversions.
   *
   * @name ok
   * @memberOf Assertion
   * @category assertion bool
   * @example
   *
   * (true).should.be.ok();
   * ''.should.not.be.ok();
   * should(null).not.be.ok();
   * should(void 0).not.be.ok();
   *
   * (10).should.be.ok();
   * (0).should.not.be.ok();
   */
  Assertion.add('ok', function() {
    this.params = { operator: 'to be truthy' };

    this.assert(this.obj);
  });
};

},{}],9:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

module.exports = function(should, Assertion) {
  /**
   * Simple chaining. It actually do nothing.
   *
   * @memberOf Assertion
   * @name be
   * @property {should.Assertion} be
   * @alias Assertion#an
   * @alias Assertion#of
   * @alias Assertion#a
   * @alias Assertion#and
   * @alias Assertion#have
   * @alias Assertion#has
   * @alias Assertion#with
   * @alias Assertion#is
   * @alias Assertion#which
   * @alias Assertion#the
   * @alias Assertion#it
   * @category assertion chaining
   */
  ['an', 'of', 'a', 'and', 'be', 'has', 'have', 'with', 'is', 'which', 'the', 'it'].forEach(function(name) {
    Assertion.addChain(name);
  });
};

},{}],10:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util');
var eql = require('should-equal');

module.exports = function(should, Assertion) {
  var i = should.format;

  /**
   * Assert that given object contain something that equal to `other`. It uses `should-equal` for equality checks.
   * If given object is array it search that one of elements was equal to `other`.
   * If given object is string it checks if `other` is a substring - expected that `other` is a string.
   * If given object is Object it checks that `other` is a subobject - expected that `other` is a object.
   *
   * @name containEql
   * @memberOf Assertion
   * @category assertion contain
   * @param {*} other Nested object
   * @example
   *
   * [1, 2, 3].should.containEql(1);
   * [{ a: 1 }, 'a', 10].should.containEql({ a: 1 });
   *
   * 'abc'.should.containEql('b');
   * 'ab1c'.should.containEql(1);
   *
   * ({ a: 10, c: { d: 10 }}).should.containEql({ a: 10 });
   * ({ a: 10, c: { d: 10 }}).should.containEql({ c: { d: 10 }});
   * ({ a: 10, c: { d: 10 }}).should.containEql({ b: 10 });
   * // throws AssertionError: expected { a: 10, c: { d: 10 } } to contain { b: 10 }
   * //            expected { a: 10, c: { d: 10 } } to have property b
   */
  Assertion.add('containEql', function(other) {
    this.params = {operator: 'to contain ' + i(other)};

    this.is.not.null().and.not.undefined();

    var obj = this.obj;

    if(typeof obj == 'string') {
      this.assert(obj.indexOf(String(other)) >= 0);
    } else if(util.isIndexable(obj)) {
      this.assert(util.some(obj, function(v) {
        return eql(v, other).result;
      }));
    } else {
      this.have.properties(other);
    }
  });

  /**
   * Assert that given object is contain equally structured object on the same depth level.
   * If given object is an array and `other` is an array it checks that the eql elements is going in the same sequence in given array (recursive)
   * If given object is an object it checks that the same keys contain deep equal values (recursive)
   * On other cases it try to check with `.eql`
   *
   * @name containDeepOrdered
   * @memberOf Assertion
   * @category assertion contain
   * @param {*} other Nested object
   * @example
   *
   * [ 1, 2, 3].should.containDeepOrdered([1, 2]);
   * [ 1, 2, [ 1, 2, 3 ]].should.containDeepOrdered([ 1, [ 2, 3 ]]);
   *
   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({a: 10});
   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {c: 10}});
   * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {d: [1, 3]}});
   */
  Assertion.add('containDeepOrdered', function(other) {
    this.params = {operator: 'to contain ' + i(other)};

    var obj = this.obj;
    if(typeof obj == 'string') {// expect other to be string
      this.is.equal(String(other));
    } else if(util.isIndexable(obj) && util.isIndexable(other)) {
      for(var objIdx = 0, otherIdx = 0, objLength = util.length(obj), otherLength = util.length(other); objIdx < objLength && otherIdx < otherLength; objIdx++) {
        try {
          should(obj[objIdx]).containDeepOrdered(other[otherIdx]);
          otherIdx++;
        } catch(e) {
          if(e instanceof should.AssertionError) {
            continue;
          }
          throw e;
        }
      }

      this.assert(otherIdx === otherLength);
    } else if(obj != null && other != null && typeof obj == 'object' && typeof other == 'object') {// object contains object case
      util.forEach(other, function(value, key) {
        should(obj[key]).containDeepOrdered(value);
      });

      // if both objects is empty means we finish traversing - and we need to compare for hidden values
      if(util.isEmptyObject(other)) {
        this.eql(other);
      }
    } else {
      this.eql(other);
    }
  });

  /**
   * The same like `Assertion#containDeepOrdered` but all checks on arrays without order.
   *
   * @name containDeep
   * @memberOf Assertion
   * @category assertion contain
   * @param {*} other Nested object
   * @example
   *
   * [ 1, 2, 3].should.containDeep([2, 1]);
   * [ 1, 2, [ 1, 2, 3 ]].should.containDeep([ 1, [ 3, 1 ]]);
   */
  Assertion.add('containDeep', function(other) {
    this.params = {operator: 'to contain ' + i(other)};

    var obj = this.obj;
    if(typeof obj == 'string') {// expect other to be string
      this.is.equal(String(other));
    } else if(util.isIndexable(obj) && util.isIndexable(other)) {
      var usedKeys = {};
      util.forEach(other, function(otherItem) {
        this.assert(util.some(obj, function(item, index) {
          if(index in usedKeys) return false;

          try {
            should(item).containDeep(otherItem);
            usedKeys[index] = true;
            return true;
          } catch(e) {
            if(e instanceof should.AssertionError) {
              return false;
            }
            throw e;
          }
        }));
      }, this);
    } else if(obj != null && other != null && typeof obj == 'object' && typeof other == 'object') {// object contains object case
      util.forEach(other, function(value, key) {
        should(obj[key]).containDeep(value);
      });

      // if both objects is empty means we finish traversing - and we need to compare for hidden values
      if(util.isEmptyObject(other)) {
        this.eql(other);
      }
    } else {
      this.eql(other);
    }
  });

};

},{"../util":20,"should-equal":22}],11:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var eql = require('should-equal');
var type = require('should-type');
var util = require('../util');

function formatEqlResult(r, a, b) {
  return ((r.path.length > 0 ? 'at ' + r.path.map(util.formatProp).join(' -> ') : '') +
  (r.a === a ? '' : ', A has ' + util.format(r.a)) +
  (r.b === b ? '' : ' and B has ' + util.format(r.b)) +
  (r.showReason ? ' because ' + r.reason : '')).trim();
}

module.exports = function(should, Assertion) {

  /**
   * Deep object equality comparison. For full spec see [`should-equal tests`](https://github.com/shouldjs/equal/blob/master/test.js).
   *
   * @name eql
   * @memberOf Assertion
   * @category assertion equality
   * @alias Assertion#deepEqual
   * @param {*} val Expected value
   * @param {string} [description] Optional message
   * @example
   *
   * (10).should.be.eql(10);
   * ('10').should.not.be.eql(10);
   * (-0).should.not.be.eql(+0);
   *
   * NaN.should.be.eql(NaN);
   *
   * ({ a: 10}).should.be.eql({ a: 10 });
   * [ 'a' ].should.not.be.eql({ '0': 'a' });
   */
  Assertion.add('eql', function(val, description) {
    this.params = {operator: 'to equal', expected: val, message: description};

    var result = eql(this.obj, val, should.config);
    this.params.details = result.result ? '' : formatEqlResult(result, this.obj, val);

    this.params.showDiff = eql(type(this.obj), type(val)).result;

    this.assert(result.result);
  });

  /**
   * Exact comparison using ===.
   *
   * @name equal
   * @memberOf Assertion
   * @category assertion equality
   * @alias Assertion#exactly
   * @param {*} val Expected value
   * @param {string} [description] Optional message
   * @example
   *
   * 10.should.be.equal(10);
   * 'a'.should.be.exactly('a');
   *
   * should(null).be.exactly(null);
   */
  Assertion.add('equal', function(val, description) {
    this.params = {operator: 'to be', expected: val, message: description};

    this.params.showDiff = eql(type(this.obj), type(val)).result;

    this.assert(val === this.obj);
  });

  Assertion.alias('equal', 'exactly');
  Assertion.alias('eql', 'deepEqual');

  function addOneOf(name, message, method) {
    Assertion.add(name, function(vals) {
      if(arguments.length !== 1) {
        vals = Array.prototype.slice.call(arguments);
      } else {
        should(vals).be.Array();
      }

      this.params = {operator: message, expected: vals};

      var obj = this.obj;
      var found = false;

      util.forEach(vals, function(val) {
        try {
          should(val)[method](obj);
          found = true;
          return false;
        } catch(e) {
          if(e instanceof should.AssertionError) {
            return;//do nothing
          }
          throw e;
        }
      });

      this.assert(found);
    });
  }

  /**
   * Exact comparison using === to be one of supplied objects.
   *
   * @name equalOneOf
   * @memberOf Assertion
   * @category assertion equality
   * @param {Array|*} vals Expected values
   * @example
   *
   * 'ab'.should.be.equalOneOf('a', 10, 'ab');
   * 'ab'.should.be.equalOneOf(['a', 10, 'ab']);
   */
  addOneOf('equalOneOf', 'to be equals one of', 'equal');

  /**
   * Exact comparison using .eql to be one of supplied objects.
   *
   * @name oneOf
   * @memberOf Assertion
   * @category assertion equality
   * @param {Array|*} vals Expected values
   * @example
   *
   * ({a: 10}).should.be.oneOf('a', 10, 'ab', {a: 10});
   * ({a: 10}).should.be.oneOf(['a', 10, 'ab', {a: 10}]);
   */
  addOneOf('oneOf', 'to be one of', 'eql');

};

},{"../util":20,"should-equal":22,"should-type":25}],12:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */
var util = require('../util');

module.exports = function(should, Assertion) {
  var i = should.format;

  /**
   * Assert given function throws error with such message.
   *
   * @name throw
   * @memberOf Assertion
   * @category assertion errors
   * @alias Assertion#throwError
   * @param {string|RegExp|Function|Object|GeneratorFunction|GeneratorObject} [message] Message to match or properties
   * @param {Object} [properties] Optional properties that will be matched to thrown error
   * @example
   *
   * (function(){ throw new Error('fail') }).should.throw();
   * (function(){ throw new Error('fail') }).should.throw('fail');
   * (function(){ throw new Error('fail') }).should.throw(/fail/);
   *
   * (function(){ throw new Error('fail') }).should.throw(Error);
   * var error = new Error();
   * error.a = 10;
   * (function(){ throw error; }).should.throw(Error, { a: 10 });
   * (function(){ throw error; }).should.throw({ a: 10 });
   * (function*() {
   *   yield throwError();
   * }).should.throw();
   */
  Assertion.add('throw', function(message, properties) {
    var fn = this.obj
      , err = {}
      , errorInfo = ''
      , thrown = false;

    if(util.isGeneratorFunction(fn)) {
      return should(fn()).throw(message, properties);
    } else if(util.isGeneratorObject(fn)) {
      return should(fn.next.bind(fn)).throw(message, properties);
    }

    this.is.a.Function();

    var errorMatched = true;

    try {
      fn();
    } catch(e) {
      thrown = true;
      err = e;
    }

    if(thrown) {
      if(message) {
        if('string' == typeof message) {
          errorMatched = message == err.message;
        } else if(message instanceof RegExp) {
          errorMatched = message.test(err.message);
        } else if('function' == typeof message) {
          errorMatched = err instanceof message;
        } else if(null != message) {
          try {
            should(err).match(message);
          } catch(e) {
            if(e instanceof should.AssertionError) {
              errorInfo = ": " + e.message;
              errorMatched = false;
            } else {
              throw e;
            }
          }
        }

        if(!errorMatched) {
          if('string' == typeof message || message instanceof RegExp) {
            errorInfo = " with a message matching " + i(message) + ", but got '" + err.message + "'";
          } else if('function' == typeof message) {
            errorInfo = " of type " + util.functionName(message) + ", but got " + util.functionName(err.constructor);
          }
        } else if('function' == typeof message && properties) {
          try {
            should(err).match(properties);
          } catch(e) {
            if(e instanceof should.AssertionError) {
              errorInfo = ": " + e.message;
              errorMatched = false;
            } else {
              throw e;
            }
          }
        }
      } else {
        errorInfo = " (got " + i(err) + ")";
      }
    }

    this.params = { operator: 'to throw exception' + errorInfo };

    this.assert(thrown);
    this.assert(errorMatched);
  });

  Assertion.alias('throw', 'throwError');
};

},{"../util":20}],13:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util');
var eql = require('should-equal');

module.exports = function(should, Assertion) {
  var i = should.format;

  /**
   * Asserts if given object match `other` object, using some assumptions:
   * First object matched if they are equal,
   * If `other` is a regexp and given object is a string check on matching with regexp
   * If `other` is a regexp and given object is an array check if all elements matched regexp
   * If `other` is a regexp and given object is an object check values on matching regexp
   * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
   * If `other` is an object check if the same keys matched with above rules
   * All other cases failed.
   *
   * Usually it is right idea to add pre type assertions, like `.String()` or `.Object()` to be sure assertions will do what you are expecting.
   * Object iteration happen by keys (properties with enumerable: true), thus some objects can cause small pain. Typical example is js
   * Error - it by default has 2 properties `name` and `message`, but they both non-enumerable. In this case make sure you specify checking props (see examples).
   *
   * @name match
   * @memberOf Assertion
   * @category assertion matching
   * @param {*} other Object to match
   * @param {string} [description] Optional message
   * @example
   * 'foobar'.should.match(/^foo/);
   * 'foobar'.should.not.match(/^bar/);
   *
   * ({ a: 'foo', c: 'barfoo' }).should.match(/foo$/);
   *
   * ['a', 'b', 'c'].should.match(/[a-z]/);
   *
   * (5).should.not.match(function(n) {
   *   return n < 0;
   * });
   * (5).should.not.match(function(it) {
   *    it.should.be.an.Array();
   * });
   * ({ a: 10, b: 'abc', c: { d: 10 }, d: 0 }).should
   * .match({ a: 10, b: /c$/, c: function(it) {
   *    return it.should.have.property('d', 10);
   * }});
   *
   * [10, 'abc', { d: 10 }, 0].should
   * .match({ '0': 10, '1': /c$/, '2': function(it) {
   *    return it.should.have.property('d', 10);
   * }});
   *
   * var myString = 'abc';
   *
   * myString.should.be.a.String().and.match(/abc/);
   *
   * myString = {};
   *
   * myString.should.match(/abc/); //yes this will pass
   * //better to do
   * myString.should.be.an.Object().and.not.empty().and.match(/abc/);//fixed
   *
   * (new Error('boom')).should.match(/abc/);//passed because no keys
   * (new Error('boom')).should.not.match({ message: /abc/ });//check specified property
   */
  Assertion.add('match', function(other, description) {
    this.params = {operator: 'to match ' + i(other), message: description};

    if(!eql(this.obj, other).result) {
      if(other instanceof RegExp) { // something - regex

        if(typeof this.obj == 'string') {

          this.assert(other.exec(this.obj));
        } else if(util.isIndexable(this.obj)) {
          util.forEach(this.obj, function(item) {
            this.assert(other.exec(item));// should we try to convert to String and exec?
          }, this);
        } else if(null != this.obj && typeof this.obj == 'object') {

          var notMatchedProps = [], matchedProps = [];
          util.forEach(this.obj, function(value, name) {
            if(other.exec(value)) matchedProps.push(util.formatProp(name));
            else notMatchedProps.push(util.formatProp(name) + ' (' + i(value) + ')');
          }, this);

          if(notMatchedProps.length)
            this.params.operator += '\n    not matched properties: ' + notMatchedProps.join(', ');
          if(matchedProps.length)
            this.params.operator += '\n    matched properties: ' + matchedProps.join(', ');

          this.assert(notMatchedProps.length === 0);
        } // should we try to convert to String and exec?
      } else if(typeof other == 'function') {
        var res;

        res = other(this.obj);

        //if(res instanceof Assertion) {
        //  this.params.operator += '\n    ' + res.getMessage();
        //}

        //if we throw exception ok - it is used .should inside
        if(typeof res == 'boolean') {
          this.assert(res); // if it is just boolean function assert on it
        }
      } else if(other != null && this.obj != null && typeof other == 'object') { // try to match properties (for Object and Array)
        notMatchedProps = [];
        matchedProps = [];

        util.forEach(other, function(value, key) {
          try {
            should(this.obj).have.property(key).which.match(value);
            matchedProps.push(util.formatProp(key));
          } catch(e) {
            if(e instanceof should.AssertionError) {
              notMatchedProps.push(util.formatProp(key) + ' (' + i(this.obj[key]) + ')');
            } else {
              throw e;
            }
          }
        }, this);

        if(notMatchedProps.length)
          this.params.operator += '\n    not matched properties: ' + notMatchedProps.join(', ');
        if(matchedProps.length)
          this.params.operator += '\n    matched properties: ' + matchedProps.join(', ');

        this.assert(notMatchedProps.length === 0);
      } else {
        this.assert(false);
      }
    }
  });

  /**
   * Asserts if given object values or array elements all match `other` object, using some assumptions:
   * First object matched if they are equal,
   * If `other` is a regexp - matching with regexp
   * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
   * All other cases check if this `other` equal to each element
   *
   * @name matchEach
   * @memberOf Assertion
   * @category assertion matching
   * @alias Assertion#matchSome
   * @param {*} other Object to match
   * @param {string} [description] Optional message
   * @example
   * [ 'a', 'b', 'c'].should.matchEach(/\w+/);
   * [ 'a', 'a', 'a'].should.matchEach('a');
   *
   * [ 'a', 'a', 'a'].should.matchEach(function(value) { value.should.be.eql('a') });
   *
   * { a: 'a', b: 'a', c: 'a' }.should.matchEach(function(value) { value.should.be.eql('a') });
   */
  Assertion.add('matchEach', function(other, description) {
    this.params = {operator: 'to match each ' + i(other), message: description};

    util.forEach(this.obj, function(value) {
      should(value).match(other);
    }, this);
  });

  /**
  * Asserts if any of given object values or array elements match `other` object, using some assumptions:
  * First object matched if they are equal,
  * If `other` is a regexp - matching with regexp
  * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
  * All other cases check if this `other` equal to each element
  *
  * @name matchAny
  * @memberOf Assertion
  * @category assertion matching
  * @param {*} other Object to match
  * @alias Assertion#matchEvery
  * @param {string} [description] Optional message
  * @example
  * [ 'a', 'b', 'c'].should.matchAny(/\w+/);
  * [ 'a', 'b', 'c'].should.matchAny('a');
  *
  * [ 'a', 'b', 'c'].should.matchAny(function(value) { value.should.be.eql('a') });
  *
  * { a: 'a', b: 'b', c: 'c' }.should.matchAny(function(value) { value.should.be.eql('a') });
  */
  Assertion.add('matchAny', function(other, description) {
    this.params = {operator: 'to match any ' + i(other), message: description};

    this.assert(util.some(this.obj, function(value) {
      try {
        should(value).match(other);
        return true;
      } catch(e) {
        if(e instanceof should.AssertionError) {
          // Caught an AssertionError, return false to the iterator
          return false;
        }
        throw e;
      }
    }));
  });

  Assertion.alias('matchAny', 'matchSome');
  Assertion.alias('matchEach', 'matchEvery');
};

},{"../util":20,"should-equal":22}],14:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

module.exports = function(should, Assertion) {

  /**
   * Assert given object is NaN
   * @name NaN
   * @memberOf Assertion
   * @category assertion numbers
   * @example
   *
   * (10).should.not.be.NaN();
   * NaN.should.be.NaN();
   */
  Assertion.add('NaN', function() {
    this.params = { operator: 'to be NaN' };

    this.assert(this.obj !== this.obj);
  });

  /**
   * Assert given object is not finite (positive or negative)
   *
   * @name Infinity
   * @memberOf Assertion
   * @category assertion numbers
   * @example
   *
   * (10).should.not.be.Infinity();
   * NaN.should.not.be.Infinity();
   */
  Assertion.add('Infinity', function() {
    this.params = { operator: 'to be Infinity' };

    this.is.a.Number()
      .and.not.a.NaN()
      .and.assert(!isFinite(this.obj));
  });

  /**
   * Assert given number between `start` and `finish` or equal one of them.
   *
   * @name within
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} start Start number
   * @param {number} finish Finish number
   * @param {string} [description] Optional message
   * @example
   *
   * (10).should.be.within(0, 20);
   */
  Assertion.add('within', function(start, finish, description) {
    this.params = { operator: 'to be within ' + start + '..' + finish, message: description };

    this.assert(this.obj >= start && this.obj <= finish);
  });

  /**
   * Assert given number near some other `value` within `delta`
   *
   * @name approximately
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} value Center number
   * @param {number} delta Radius
   * @param {string} [description] Optional message
   * @example
   *
   * (9.99).should.be.approximately(10, 0.1);
   */
  Assertion.add('approximately', function(value, delta, description) {
    this.params = { operator: 'to be approximately ' + value + ' ±' + delta, message: description };

    this.assert(Math.abs(this.obj - value) <= delta);
  });

  /**
   * Assert given number above `n`.
   *
   * @name above
   * @alias Assertion#greaterThan
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} n Margin number
   * @param {string} [description] Optional message
   * @example
   *
   * (10).should.be.above(0);
   */
  Assertion.add('above', function(n, description) {
    this.params = { operator: 'to be above ' + n, message: description };

    this.assert(this.obj > n);
  });

  /**
   * Assert given number below `n`.
   *
   * @name below
   * @alias Assertion#lessThan
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} n Margin number
   * @param {string} [description] Optional message
   * @example
   *
   * (0).should.be.below(10);
   */
  Assertion.add('below', function(n, description) {
    this.params = { operator: 'to be below ' + n, message: description };

    this.assert(this.obj < n);
  });

  Assertion.alias('above', 'greaterThan');
  Assertion.alias('below', 'lessThan');

  /**
   * Assert given number above `n`.
   *
   * @name aboveOrEqual
   * @alias Assertion#greaterThanOrEqual
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} n Margin number
   * @param {string} [description] Optional message
   * @example
   *
   * (10).should.be.aboveOrEqual(0);
   * (10).should.be.aboveOrEqual(10);
   */
  Assertion.add('aboveOrEqual', function(n, description) {
    this.params = { operator: 'to be above or equal' + n, message: description };

    this.assert(this.obj >= n);
  });

  /**
   * Assert given number below `n`.
   *
   * @name belowOrEqual
   * @alias Assertion#lessThanOrEqual
   * @memberOf Assertion
   * @category assertion numbers
   * @param {number} n Margin number
   * @param {string} [description] Optional message
   * @example
   *
   * (0).should.be.belowOrEqual(10);
   * (0).should.be.belowOrEqual(0);
   */
  Assertion.add('belowOrEqual', function(n, description) {
    this.params = { operator: 'to be below or equal' + n, message: description };

    this.assert(this.obj <= n);
  });

  Assertion.alias('aboveOrEqual', 'greaterThanOrEqual');
  Assertion.alias('belowOrEqual', 'lessThanOrEqual');

};

},{}],15:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util');
var PromisedAssertion = require('../assertion').PromisedAssertion;
var Assertion = require('../assertion');

module.exports = function(should) {
  /**
   * Assert given object is a Promise
   *
   * @name Promise
   * @memberOf Assertion
   * @category assertion promises
   * @example
   *
   * promise.should.be.Promise()
   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.a.Promise()
   * (10).should.not.be.a.Promise()
   */
  Assertion.add('Promise', function() {
    this.params = {operator: 'to be promise'};

    var obj = this.obj;

    should(obj).have.property('then')
      .which.is.a.Function();
  });

  /**
   * Assert given promise will be fulfilled
   *
   * @name fulfilled
   * @memberOf Assertion
   * @returns {Promise}
   * @category assertion promises
   * @example
   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.fulfilled()
   */
  Assertion.prototype.fulfilled = function Assertion$fulfilled() {
    this.params = {operator: 'to be fulfilled'};

    should(this.obj).be.a.Promise();

    var that = this;
    return this.obj.then(function next$onResolve(value) {
      if (that.negate) {
        that.fail();
      }
      return value;
    }, function next$onReject(err) {
      if (!that.negate) {
        that.fail();
      }
      return err;
    });
  };

  /**
   * Assert given promise will be rejected
   *
   * @name rejected
   * @memberOf Assertion
   * @category assertion promises
   * @returns {Promise}
   * @example
   * (new Promise(function(resolve, reject) { resolve(10); })).should.not.be.rejected()
   */
  Assertion.prototype.rejected = function() {
    this.params = {operator: 'to be rejected'};

    should(this.obj).be.a.Promise();

    var that = this;
    return this.obj.then(function(value) {
      if (!that.negate) {
        that.fail();
      }
      return value;
    }, function next$onError(err) {
      if (that.negate) {
        that.fail();
      }
      return err;
    });
  };

  /**
   * Assert given promise will be fulfilled with some expected value.
   *
   * @name fulfilledWith
   * @memberOf Assertion
   * @category assertion promises
   * @returns {Promise}
   * @example
   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.fulfilledWith(10)
   */
  Assertion.prototype.fulfilledWith = function(expectedValue) {
    this.params = {operator: 'to be fulfilled'};

    should(this.obj).be.a.Promise();

    var that = this;
    return this.obj.then(function(value) {
      if (that.negate) {
        that.fail();
      }
      should(value).eql(expectedValue);
      return value;
    }, function next$onError(err) {
      if (!that.negate) {
        that.fail();
      }
      return err;
    });
  };

  /**
   * Assert given promise will be rejected with some sort of error. Arguments is the same for Assertion#throw
   *
   * @name rejectedWith
   * @memberOf Assertion
   * @category assertion promises
   * @returns {Promise}
   * @example
   *
   * function failedPromise() {
  *   return new Promise(function(resolve, reject) {
  *     reject(new Error('boom'))
  *   })
  * }
   * failedPromise().should.be.rejectedWith(Error)
   * failedPromise().should.be.rejectedWith('boom')
   * failedPromise().should.be.rejectedWith(/boom/)
   * failedPromise().should.be.rejectedWith(Error, { message: 'boom' })
   * failedPromise().should.be.rejectedWith({ message: 'boom' })
   */
  Assertion.prototype.rejectedWith = function(message, properties) {
    this.params = {operator: 'to be rejected'};

    should(this.obj).be.a.Promise();

    var that = this;
    return this.obj.then(function(value) {
      if (!that.negate) {
        that.fail();
      }
      return value;
    }, function next$onError(err) {
      if (that.negate) {
        that.fail();
      }

      var errorMatched = true;
      var errorInfo = '';

      if ('string' === typeof message) {
        errorMatched = message === err.message;
      } else if (message instanceof RegExp) {
        errorMatched = message.test(err.message);
      } else if ('function' === typeof message) {
        errorMatched = err instanceof message;
      } else if (message !== null && typeof message === 'object') {
        try {
          should(err).match(message);
        } catch (e) {
          if (e instanceof should.AssertionError) {
            errorInfo = ': ' + e.message;
            errorMatched = false;
          } else {
            throw e;
          }
        }
      }

      if (!errorMatched) {
        if ( typeof message === 'string' || message instanceof RegExp) {
          errorInfo = ' with a message matching ' + should.format(message) + ", but got '" + err.message + "'";
        } else if ('function' === typeof message) {
          errorInfo = ' of type ' + util.functionName(message) + ', but got ' + util.functionName(err.constructor);
        }
      } else if ('function' === typeof message && properties) {
        try {
          should(err).match(properties);
        } catch (e) {
          if (e instanceof should.AssertionError) {
            errorInfo = ': ' + e.message;
            errorMatched = false;
          } else {
            throw e;
          }
        }
      }

      that.params.operator += errorInfo;

      that.assert(errorMatched);

      return err;
    });
  };

  /**
   * Assert given object is promise and wrap it in PromisedAssertion, which has all properties of Assertion. That means you can chain as with usual Assertion.
   *
   * @name finally
   * @memberOf Assertion
   * @alias Assertion#eventually
   * @category assertion promises
   * @returns {PromisedAssertion} Like Assertion, but .then this.obj in Assertion
   * @example
   *
   * (new Promise(function(resolve, reject) { resolve(10); })).should.be.eventually.equal(10)
   */
  Object.defineProperty(Assertion.prototype, 'finally', {
    get: function() {
      should(this.obj).be.a.Promise();

      var that = this;

      return new PromisedAssertion(this.obj.then(function(obj) {
        var a = should(obj);

        a.negate = that.negate;
        a.anyOne = that.anyOne;

        return a;
      }));
    }
  });

  Assertion.alias('finally', 'eventually');
};

},{"../assertion":4,"../util":20}],16:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util');
var eql = require('should-equal');

var aSlice = Array.prototype.slice;

module.exports = function(should, Assertion) {
  var i = should.format;
  /**
   * Asserts given object has some descriptor. **On success it change given object to be value of property**.
   *
   * @name propertyWithDescriptor
   * @memberOf Assertion
   * @category assertion property
   * @param {string} name Name of property
   * @param {Object} desc Descriptor like used in Object.defineProperty (not required to add all properties)
   * @example
   *
   * ({ a: 10 }).should.have.propertyWithDescriptor('a', { enumerable: true });
   */
  Assertion.add('propertyWithDescriptor', function(name, desc) {
    this.params = {actual: this.obj, operator: 'to have own property with descriptor ' + i(desc)};
    var obj = this.obj;
    this.have.ownProperty(name);
    should(Object.getOwnPropertyDescriptor(Object(obj), name)).have.properties(desc);
  });

  function processPropsArgs() {
    var args = {};
    if(arguments.length > 1) {
      args.names = aSlice.call(arguments);
    } else {
      var arg = arguments[0];
      if(typeof arg === 'string') {
        args.names = [arg];
      } else if(util.isIndexable(arg)) {
        args.names = arg;
      } else {
        args.names = Object.keys(arg);
        args.values = arg;
      }
    }
    return args;
  }


  /**
   * Asserts given object has enumerable property with optionally value. **On success it change given object to be value of property**.
   *
   * @name enumerable
   * @memberOf Assertion
   * @category assertion property
   * @param {string} name Name of property
   * @param {*} [val] Optional property value to check
   * @example
   *
   * ({ a: 10 }).should.have.enumerable('a');
   */
  Assertion.add('enumerable', function(name, val) {
    name = util.convertPropertyName(name);

    this.params = {
      operator: "to have enumerable property " + util.formatProp(name) + (arguments.length > 1 ? " equal to " + i(val): "")
    };

    var desc = { enumerable: true };
    if(arguments.length > 1) desc.value = val;
    this.have.propertyWithDescriptor(name, desc);
  });

  /**
   * Asserts given object has enumerable properties
   *
   * @name enumerables
   * @memberOf Assertion
   * @category assertion property
   * @param {Array|...string|Object} names Names of property
   * @example
   *
   * ({ a: 10, b: 10 }).should.have.enumerables('a');
   */
  Assertion.add('enumerables', function(names) {
    var args = processPropsArgs.apply(null, arguments);

    this.params = {
      operator: "to have enumerables " + args.names.map(util.formatProp)
    };

    var obj = this.obj;
    args.names.forEach(function(name) {
      should(obj).have.enumerable(name);
    });
  });

  /**
   * Asserts given object has property with optionally value. **On success it change given object to be value of property**.
   *
   * @name property
   * @memberOf Assertion
   * @category assertion property
   * @param {string} name Name of property
   * @param {*} [val] Optional property value to check
   * @example
   *
   * ({ a: 10 }).should.have.property('a');
   */
  Assertion.add('property', function(name, val) {
    name = util.convertPropertyName(name);
    if(arguments.length > 1) {
      var p = {};
      p[name] = val;
      this.have.properties(p);
    } else {
      this.have.properties(name);
    }
    this.obj = this.obj[name];
  });

  /**
   * Asserts given object has properties. On this method affect .any modifier, which allow to check not all properties.
   *
   * @name properties
   * @memberOf Assertion
   * @category assertion property
   * @param {Array|...string|Object} names Names of property
   * @example
   *
   * ({ a: 10 }).should.have.properties('a');
   * ({ a: 10, b: 20 }).should.have.properties([ 'a' ]);
   * ({ a: 10, b: 20 }).should.have.properties({ b: 20 });
   */
  Assertion.add('properties', function(names) {
    var values = {};
    if(arguments.length > 1) {
      names = aSlice.call(arguments);
    } else if(!Array.isArray(names)) {
      if(typeof names == 'string' || typeof names == 'symbol') {
        names = [names];
      } else {
        values = names;
        names = Object.keys(names);
      }
    }

    var obj = Object(this.obj), missingProperties = [];

    //just enumerate properties and check if they all present
    names.forEach(function(name) {
      if(!(name in obj)) missingProperties.push(util.formatProp(name));
    });

    var props = missingProperties;
    if(props.length === 0) {
      props = names.map(util.formatProp);
    } else if(this.anyOne) {
      props = names.filter(function(name) {
        return missingProperties.indexOf(util.formatProp(name)) < 0;
      }).map(util.formatProp);
    }

    var operator = (props.length === 1 ?
        'to have property ' : 'to have ' + (this.anyOne ? 'any of ' : '') + 'properties ') + props.join(', ');

    this.params = {obj: this.obj, operator: operator};

    //check that all properties presented
    //or if we request one of them that at least one them presented
    this.assert(missingProperties.length === 0 || (this.anyOne && missingProperties.length != names.length));

    // check if values in object matched expected
    var valueCheckNames = Object.keys(values);
    if(valueCheckNames.length) {
      var wrongValues = [];
      props = [];

      // now check values, as there we have all properties
      valueCheckNames.forEach(function(name) {
        var value = values[name];
        if(!eql(obj[name], value).result) {
          wrongValues.push(util.formatProp(name) + ' of ' + i(value) + ' (got ' + i(obj[name]) + ')');
        } else {
          props.push(util.formatProp(name) + ' of ' + i(value));
        }
      });

      if((wrongValues.length !== 0 && !this.anyOne) || (this.anyOne && props.length === 0)) {
        props = wrongValues;
      }

      operator = (props.length === 1 ?
        'to have property ' : 'to have ' + (this.anyOne ? 'any of ' : '') + 'properties ') + props.join(', ');

      this.params = {obj: this.obj, operator: operator};

      //if there is no not matched values
      //or there is at least one matched
      this.assert(wrongValues.length === 0 || (this.anyOne && wrongValues.length != valueCheckNames.length));
    }
  });

  /**
   * Asserts given object has property `length` with given value `n`
   *
   * @name length
   * @alias Assertion#lengthOf
   * @memberOf Assertion
   * @category assertion property
   * @param {number} n Expected length
   * @param {string} [description] Optional message
   * @example
   *
   * [1, 2].should.have.length(2);
   */
  Assertion.add('length', function(n, description) {
    this.have.property('length', n, description);
  });

  Assertion.alias('length', 'lengthOf');

  var hasOwnProperty = Object.prototype.hasOwnProperty;

  /**
   * Asserts given object has own property. **On success it change given object to be value of property**.
   *
   * @name ownProperty
   * @alias Assertion#hasOwnProperty
   * @memberOf Assertion
   * @category assertion property
   * @param {string} name Name of property
   * @param {string} [description] Optional message
   * @example
   *
   * ({ a: 10 }).should.have.ownProperty('a');
   */
  Assertion.add('ownProperty', function(name, description) {
    name = util.convertPropertyName(name);
    this.params = {
      actual: this.obj,
      operator: 'to have own property ' + util.formatProp(name),
      message: description
    };

    this.assert(hasOwnProperty.call(this.obj, name));

    this.obj = this.obj[name];
  });

  Assertion.alias('ownProperty', 'hasOwnProperty');

  /**
   * Asserts given object is empty. For strings, arrays and arguments it checks .length property, for objects it checks keys.
   *
   * @name empty
   * @memberOf Assertion
   * @category assertion property
   * @example
   *
   * ''.should.be.empty();
   * [].should.be.empty();
   * ({}).should.be.empty();
   */
  Assertion.add('empty', function() {
    this.params = {operator: 'to be empty'};

    if(util.length(this.obj) !== void 0) {
      should(this.obj).have.property('length', 0);
    } else {
      var obj = Object(this.obj); // wrap to reference for booleans and numbers
      for(var prop in obj) {
        should(this.obj).not.have.ownProperty(prop);
      }
    }
  }, true);

  /**
   * Asserts given object has exact keys. Compared to `properties`, `keys` does not accept Object as a argument.
   *
   * @name keys
   * @alias Assertion#key
   * @memberOf Assertion
   * @category assertion property
   * @param {Array|...string} [keys] Keys to check
   * @example
   *
   * ({ a: 10 }).should.have.keys('a');
   * ({ a: 10, b: 20 }).should.have.keys('a', 'b');
   * ({ a: 10, b: 20 }).should.have.keys([ 'a', 'b' ]);
   * ({}).should.have.keys();
   */
  Assertion.add('keys', function(keys) {
    if(arguments.length > 1) keys = aSlice.call(arguments);
    else if(arguments.length === 1 && typeof keys === 'string') keys = [keys];
    else if(arguments.length === 0) keys = [];

    keys = keys.map(String);

    var obj = Object(this.obj);

    // first check if some keys are missing
    var missingKeys = [];
    keys.forEach(function(key) {
      if(!hasOwnProperty.call(this.obj, key))
        missingKeys.push(util.formatProp(key));
    }, this);

    // second check for extra keys
    var extraKeys = [];
    Object.keys(obj).forEach(function(key) {
      if(keys.indexOf(key) < 0) {
        extraKeys.push(util.formatProp(key));
      }
    });

    var verb = keys.length === 0 ? 'to be empty' :
    'to have ' + (keys.length === 1 ? 'key ' : 'keys ');

    this.params = {operator: verb + keys.map(util.formatProp).join(', ')};

    if(missingKeys.length > 0)
      this.params.operator += '\n\tmissing keys: ' + missingKeys.join(', ');

    if(extraKeys.length > 0)
      this.params.operator += '\n\textra keys: ' + extraKeys.join(', ');

    this.assert(missingKeys.length === 0 && extraKeys.length === 0);
  });

  Assertion.alias("keys", "key");

  /**
   * Asserts given object has nested property in depth by path. **On success it change given object to be value of final property**.
   *
   * @name propertyByPath
   * @memberOf Assertion
   * @category assertion property
   * @param {Array|...string} properties Properties path to search
   * @example
   *
   * ({ a: {b: 10}}).should.have.propertyByPath('a', 'b').eql(10);
   */
  Assertion.add('propertyByPath', function(properties) {
    if(arguments.length > 1) properties = aSlice.call(arguments);
    else if(arguments.length === 1 && typeof properties == 'string') properties = [properties];
    else if(arguments.length === 0) properties = [];

    var allProps = properties.map(util.formatProp);

    properties = properties.map(String);

    var obj = should(Object(this.obj));

    var foundProperties = [];

    var currentProperty;
    while(currentProperty = properties.shift()) {
      this.params = {operator: 'to have property by path ' + allProps.join(', ') + ' - failed on ' + util.formatProp(currentProperty)};
      obj = obj.have.property(currentProperty);
      foundProperties.push(currentProperty);
    }

    this.params = {obj: this.obj, operator: 'to have property by path ' + allProps.join(', ')};

    this.obj = obj.obj;
  });
};

},{"../util":20,"should-equal":22}],17:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

module.exports = function(should, Assertion) {
  /**
   * Assert given string starts with prefix
   * @name startWith
   * @memberOf Assertion
   * @category assertion strings
   * @param {string} str Prefix
   * @param {string} [description] Optional message
   * @example
   *
   * 'abc'.should.startWith('a');
   */
  Assertion.add('startWith', function(str, description) {
    this.params = { operator: 'to start with ' + should.format(str), message: description };

    this.assert(0 === this.obj.indexOf(str));
  });

  /**
   * Assert given string starts with prefix
   * @name endWith
   * @memberOf Assertion
   * @category assertion strings
   * @param {string} str Prefix
   * @param {string} [description] Optional message
   * @example
   *
   * 'abca'.should.endWith('a');
   */
  Assertion.add('endWith', function(str, description) {
    this.params = { operator: 'to end with ' + should.format(str), message: description };

    this.assert(this.obj.indexOf(str, this.obj.length - str.length) >= 0);
  });
};

},{}],18:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var util = require('../util');

module.exports = function(should, Assertion) {
  /**
   * Assert given object is number
   * @name Number
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Number', function() {
    this.params = {operator: 'to be a number'};

    this.have.type('number');
  });

  /**
   * Assert given object is arguments
   * @name arguments
   * @alias Assertion#Arguments
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('arguments', function() {
    this.params = {operator: 'to be arguments'};

    this.have.class('Arguments');
  });

  Assertion.alias('arguments', 'Arguments');

  /**
   * Assert given object has some type using `typeof`
   * @name type
   * @memberOf Assertion
   * @param {string} type Type name
   * @param {string} [description] Optional message
   * @category assertion types
   */
  Assertion.add('type', function(type, description) {
    this.params = {operator: 'to have type ' + type, message: description};

    should(typeof this.obj).be.exactly(type);
  });

  /**
   * Assert given object is instance of `constructor`
   * @name instanceof
   * @alias Assertion#instanceOf
   * @memberOf Assertion
   * @param {Function} constructor Constructor function
   * @param {string} [description] Optional message
   * @category assertion types
   */
  Assertion.add('instanceof', function(constructor, description) {
    this.params = {operator: 'to be an instance of ' + util.functionName(constructor), message: description};

    this.assert(Object(this.obj) instanceof constructor);
  });

  Assertion.alias('instanceof', 'instanceOf');

  /**
   * Assert given object is function
   * @name Function
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Function', function() {
    this.params = {operator: 'to be a function'};

    this.have.type('function');
  });

  /**
   * Assert given object is object
   * @name Object
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Object', function() {
    this.params = {operator: 'to be an object'};

    this.is.not.null().and.have.type('object');
  });

  /**
   * Assert given object is string
   * @name String
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('String', function() {
    this.params = {operator: 'to be a string'};

    this.have.type('string');
  });

  /**
   * Assert given object is array
   * @name Array
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Array', function() {
    this.params = {operator: 'to be an array'};

    this.have.class('Array');
  });

  /**
   * Assert given object is boolean
   * @name Boolean
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Boolean', function() {
    this.params = {operator: 'to be a boolean'};

    this.have.type('boolean');
  });

  /**
   * Assert given object is error
   * @name Error
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('Error', function() {
    this.params = {operator: 'to be an error'};

    this.have.instanceOf(Error);
  });

  /**
   * Assert given object is null
   * @name null
   * @alias Assertion#Null
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('null', function() {
    this.params = {operator: 'to be null'};

    this.assert(this.obj === null);
  });

  Assertion.alias('null', 'Null');

  /**
   * Assert given object has some internal [[Class]], via Object.prototype.toString call
   * @name class
   * @alias Assertion#Class
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('class', function(cls) {
    this.params = {operator: 'to have [[Class]] ' + cls};

    this.assert(Object.prototype.toString.call(this.obj) === '[object ' + cls + ']');
  });

  Assertion.alias('class', 'Class');

  /**
   * Assert given object is undefined
   * @name undefined
   * @alias Assertion#Undefined
   * @memberOf Assertion
   * @category assertion types
   */
  Assertion.add('undefined', function() {
    this.params = {operator: 'to be undefined'};

    this.assert(this.obj === void 0);
  });

  Assertion.alias('undefined', 'Undefined');

  /**
   * Assert given object supports es6 iterable protocol (just check
   * that object has property Symbol.iterator, which is a function)
   * @name iterable
   * @memberOf Assertion
   * @category assertion es6
   */
  Assertion.add('iterable', function() {
    this.params = {operator: 'to be iterable'};

    should(this.obj).have.property(Symbol.iterator).which.is.a.Function();
  });

  /**
   * Assert given object supports es6 iterator protocol (just check
   * that object has property next, which is a function)
   * @name iterator
   * @memberOf Assertion
   * @category assertion es6
   */
  Assertion.add('iterator', function() {
    this.params = {operator: 'to be iterator'};

    should(this.obj).have.property('next').which.is.a.Function();
  });

  /**
   * Assert given object is a generator object
   * @name generator
   * @memberOf Assertion
   * @category assertion es6
   */
  Assertion.add('generator', function() {
    this.params = {operator: 'to be generator'};

    should(this.obj).be.iterable
      .and.iterator
      .and.it.is.equal(this.obj[Symbol.iterator]());
  });
};

},{"../util":20}],19:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */


var util = require('./util');

/**
 * Our function should
 *
 * @param {*} obj Object to assert
 * @returns {should.Assertion} Returns new Assertion for beginning assertion chain
 * @example
 *
 * var should = require('should');
 * should('abc').be.a.String();
 */
function should(obj) {
  return (new should.Assertion(obj));
}

should.AssertionError = require('./assertion-error');
should.Assertion = require('./assertion');

should.format = util.format;
should.type = require('should-type');
should.util = util;

/**
 * Object with configuration.
 * It contains such properties:
 * * `checkProtoEql` boolean - Affect if `.eql` will check objects prototypes
 * Also it can contain options for should-format.
 *
 * @type {Object}
 * @memberOf should
 * @static
 * @example
 *
 * var a = { a: 10 }, b = Object.create(null);
 * b.a = 10;
 *
 * a.should.be.eql(b);
 * //not throws
 *
 * should.config.checkProtoEql = true;
 * a.should.be.eql(b);
 * //throws AssertionError: expected { a: 10 } to equal { a: 10 } (because A and B have different prototypes)
 */
should.config = require('./config');

// Expose should to external world.
exports = module.exports = should;

/**
 * Allow to extend given prototype with should property using given name. This getter will **unwrap** all standard wrappers like `Number`, `Boolean`, `String`.
 * Using `should(obj)` is the equivalent of using `obj.should` with known issues (like nulls and method calls etc).
 *
 * @param {string} [propertyName] Name of property to add. Default is `'should'`.
 * @param {Object} [proto] Prototype to extend with. Default is `Object.prototype`.
 * @memberOf should
 * @returns {{ name: string, descriptor: Object, proto: Object }} Descriptor enough to return all back
 * @static
 * @example
 *
 * var prev = should.extend('must', Object.prototype);
 *
 * 'abc'.must.startWith('a');
 *
 * var should = should.noConflict(prev);
 * should.not.exist(Object.prototype.must);
 */
should.extend = function(propertyName, proto) {
  propertyName = propertyName || 'should';
  proto = proto || Object.prototype;

  var prevDescriptor = Object.getOwnPropertyDescriptor(proto, propertyName);

  Object.defineProperty(proto, propertyName, {
    set: function() {
    },
    get: function() {
      return should(util.isWrapperType(this) ? this.valueOf() : this);
    },
    configurable: true
  });

  return { name: propertyName, descriptor: prevDescriptor, proto: proto };
};

/**
 * Delete previous extension. If `desc` missing it will remove default extension.
 *
 * @param {{ name: string, descriptor: Object, proto: Object }} [desc] Returned from `should.extend` object
 * @memberOf should
 * @returns {Function} Returns should function
 * @static
 * @example
 *
 * var should = require('should').noConflict();
 *
 * should(Object.prototype).not.have.property('should');
 *
 * var prev = should.extend('must', Object.prototype);
 * 'abc'.must.startWith('a');
 * should.noConflict(prev);
 *
 * should(Object.prototype).not.have.property('must');
 */
should.noConflict = function(desc) {
  desc = desc || should._prevShould;

  if(desc) {
    delete desc.proto[desc.name];

    if(desc.descriptor) {
      Object.defineProperty(desc.proto, desc.name, desc.descriptor);
    }
  }
  return should;
};

/**
 * Simple utility function for a bit more easier should assertion extension
 * @param {Function} f So called plugin function. It should accept 2 arguments: `should` function and `Assertion` constructor
 * @memberOf should
 * @returns {Function} Returns `should` function
 * @static
 * @example
 *
 * should.use(function(should, Assertion) {
 *   Assertion.add('asset', function() {
 *      this.params = { operator: 'to be asset' };
 *
 *      this.obj.should.have.property('id').which.is.a.Number();
 *      this.obj.should.have.property('path');
 *  })
 * })
 */
should.use = function(f) {
  f(should, should.Assertion);
  return this;
};

should
  .use(require('./ext/assert'))
  .use(require('./ext/chain'))
  .use(require('./ext/bool'))
  .use(require('./ext/number'))
  .use(require('./ext/eql'))
  .use(require('./ext/type'))
  .use(require('./ext/string'))
  .use(require('./ext/property'))
  .use(require('./ext/error'))
  .use(require('./ext/match'))
  .use(require('./ext/contain'))
  .use(require('./ext/promise'));

},{"./assertion":4,"./assertion-error":3,"./config":5,"./ext/assert":7,"./ext/bool":8,"./ext/chain":9,"./ext/contain":10,"./ext/eql":11,"./ext/error":12,"./ext/match":13,"./ext/number":14,"./ext/promise":15,"./ext/property":16,"./ext/string":17,"./ext/type":18,"./util":20,"should-type":25}],20:[function(require,module,exports){
/*
 * Should
 * Copyright(c) 2010-2015 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

var type = require('should-type');
var config = require('./config');

/**
 * Check if given obj just a primitive type wrapper
 * @param {Object} obj
 * @returns {boolean}
 * @private
 */
exports.isWrapperType = function(obj) {
  return obj instanceof Number || obj instanceof String || obj instanceof Boolean;
};

exports.merge = function(a, b) {
  if(a && b) {
    for(var key in b) {
      a[key] = b[key];
    }
  }
  return a;
};

var hasOwnProperty = Object.prototype.hasOwnProperty;

exports.forEach = function forEach(obj, f, context) {
  if(exports.isGeneratorFunction(obj)) {
    return forEach(obj(), f, context);
  } else if (exports.isGeneratorObject(obj)) {
    var value = obj.next();
    while(!value.done) {
      if(f.call(context, value.value, 'value', obj) === false)
        return;
      value = obj.next();
    }
  } else {
    for(var prop in obj) {
      if(hasOwnProperty.call(obj, prop)) {
        if(f.call(context, obj[prop], prop, obj) === false)
          return;
      }
    }
  }
};

exports.some = function(obj, f, context) {
  var res = false;
  exports.forEach(obj, function(value, key) {
    if(f.call(context, value, key, obj)) {
      res = true;
      return false;
    }
  }, context);
  return res;
};

exports.isEmptyObject = function(obj) {
  for(var prop in obj) {
    if(hasOwnProperty.call(obj, prop)) {
      return false;
    }
  }
  return true;
};

exports.isIndexable = function(obj) {
  var t = type(obj);
  return (t.type === type.OBJECT && t.cls === type.ARRAY) ||
   (t.type === type.OBJECT && t.cls === type.BUFFER) ||
   (t.type === type.OBJECT && t.cls === type.ARGUMENTS) ||
   (t.type === type.OBJECT && t.cls === type.ARRAY_BUFFER) ||
   (t.type === type.OBJECT && t.cls === type.TYPED_ARRAY) ||
   (t.type === type.OBJECT && t.cls === type.DATA_VIEW) ||
   (t.type === type.OBJECT && t.cls === type.STRING) ||
   (t.type === type.STRING);
};

exports.length = function(obj) {
  var t = type(obj);
  switch(t.type) {
    case type.STRING:
      return obj.length;
    case type.OBJECT:
      switch(t.cls) {
        case type.ARRAY_BUFFER:
        case type.TYPED_ARRAY:
        case type.DATA_VIEW:
          return obj.byteLength;

        case type.ARRAY:
        case type.BUFFER:
        case type.ARGUMENTS:
        case type.FUNCTION:
          return obj.length;
      }
  }
};

exports.convertPropertyName = function(name) {
  if(typeof name == 'symbol') {
    return name;
  } else {
    return String(name);
  }
};

exports.isGeneratorObject = function(obj) {
  if(!obj) return false;

  return typeof obj.next == 'function' &&
          typeof obj[Symbol.iterator] == 'function' &&
          obj[Symbol.iterator]() === obj;
};

//TODO find better way
exports.isGeneratorFunction = function(f) {
  if(typeof f != 'function') return false;

  return /^function\s*\*\s*/.test(f.toString());
};

exports.format = function(value, opts) {
  return config.getFormatter(opts).format(value);
};

exports.functionName = require('should-format').Formatter.functionName;

exports.formatProp = function(value) {
  return config.getFormatter().formatPropertyName(String(value));
};

},{"./config":5,"should-format":23,"should-type":25}],21:[function(require,module,exports){
module.exports = function format(msg) {
  var args = arguments;
  for(var i = 1, l = args.length; i < l; i++) {
    msg = msg.replace(/%s/, args[i]);
  }
  return msg;
}

},{}],22:[function(require,module,exports){
var getType = require('should-type');
var format = require('./format');
var hasOwnProperty = Object.prototype.hasOwnProperty;

function makeResult(r, path, reason, a, b) {
  var o = {result: r};
  if(!r) {
    o.path = path;
    o.reason = reason;
    o.a = a;
    o.b = b;
  }
  return o;
}

var EQUALS = makeResult(true);

function typeToString(t) {
  return t.type + (t.cls ? '(' + t.cls + (t.sub ? ' ' + t.sub : '') + ')' : '');
}



var REASON = {
  PLUS_0_AND_MINUS_0: '+0 is not equal to -0',
  DIFFERENT_TYPES: 'A has type %s and B has type %s',
  NAN_NUMBER: 'NaN is not equal to any number',
  EQUALITY: 'A is not equal to B',
  EQUALITY_PROTOTYPE: 'A and B have different prototypes',
  WRAPPED_VALUE: 'A wrapped value is not equal to B wrapped value',
  FUNCTION_SOURCES: 'function A is not equal to B by source code value (via .toString call)',
  MISSING_KEY: '%s has no key %s',
  CIRCULAR_VALUES: 'A has circular reference that was visited not in the same time as B',
  SET_MAP_MISSING_KEY: 'Set/Map missing key',
  MAP_VALUE_EQUALITY: 'Values of the same key in A and B is not equal'
};

function eqInternal(a, b, opts, stackA, stackB, path) {
  var r = EQUALS;

  function result(comparison, reason) {
    return makeResult(comparison, path, reason, a, b);
  }

  function checkPropertyEquality(property) {
    return eqInternal(a[property], b[property], opts, stackA, stackB, path.concat([property]));
  }


  // equal a and b exit early
  if(a === b) {
    // check for +0 !== -0;
    return result(a !== 0 || (1 / a == 1 / b), REASON.PLUS_0_AND_MINUS_0);
  }

  var l, p;

  var typeA = getType(a),
    typeB = getType(b);

  // if objects has different types they are not equals
  var typeDifferents = typeA.type !== typeB.type || typeA.cls !== typeB.cls;

  if(typeDifferents || ((opts.checkSubType && typeA.sub !== typeB.sub) || !opts.checkSubType)) {
    return result(false, format(REASON.DIFFERENT_TYPES, typeToString(typeA), typeToString(typeB)));
  }

  //early checks for types
  switch(typeA.type) {
    case 'number':
      // NaN !== NaN
      return (a !== a) ? result(b !== b, REASON.NAN_NUMBER)
        // but treat `+0` vs. `-0` as not equal
        : (a === 0 ? result(1 / a === 1 / b, REASON.PLUS_0_AND_MINUS_0) : result(a === b, REASON.EQUALITY));

    case 'boolean':
    case 'string':
      return result(a === b, REASON.EQUALITY);

    case 'function':
      var fA = a.toString(), fB = b.toString();
      r = eqInternal(fA, fB, opts, stackA, stackB, path);
      if(!r.result) {
        r.reason = REASON.FUNCTION_SOURCES;
        return r;
      }

      break;//check user properties

    case 'object':
      // additional checks for object instances
      switch(typeA.cls) {
        // check regexp flags
        // TODO add es6 flags
        case 'regexp':
          p = ['source', 'global', 'multiline', 'lastIndex', 'ignoreCase'];
          while(p.length) {
            r = checkPropertyEquality(p.shift());
            if(!r.result) return r;
          }
          break;//check user properties

        //check by timestamp only
        case 'date':
          if(+a !== +b) {
            return result(false, REASON.EQUALITY);
          }
          break;//check user properties

        //primitive type wrappers
        case 'number':
        case 'boolean':
        case 'string':
          r = eqInternal(a.valueOf(), b.valueOf(), opts, stackA, stackB, path);
          if(!r.result) {
            r.reason = REASON.WRAPPED_VALUE;
            return r;
          }
          break;//check user properties

        //node buffer
        case 'buffer':
          //if length different it is obviously different
          r = checkPropertyEquality('length');
          if(!r.result) return r;

          l = a.length;
          while(l--) {
            r = checkPropertyEquality(l);
            if(!r.result) return r;
          }

          //we do not check for user properties because
          //node Buffer have some strange hidden properties
          return EQUALS;

        case 'error':
          //check defined properties
          p = ['name', 'message'];
          while(p.length) {
            r = checkPropertyEquality(p.shift());
            if(!r.result) return r;
          }

          break;//check user properties

        case 'array':
        case 'arguments':
        case 'typed-array':
          r = checkPropertyEquality('length');
          if(!r.result) return r;

          break;//check user properties

        case 'array-buffer':
          r = checkPropertyEquality('byteLength');
          if(!r.result) return r;

          break;//check user properties

        case 'map':
        case 'set':
          r = checkPropertyEquality('size');
          if(!r.result) return r;

          stackA.push(a);
          stackB.push(b);

          var itA = a.entries();
          var nextA = itA.next();

          while(!nextA.done) {
            var key = nextA.value[0];
            //first check for primitive key if we can do light check
            //using .has and .get
            if(getType(key).type != 'object') {
              if(b.has(key)) {
                if(typeA.cls == 'map') {
                  //for map we also check its value to be equal
                  var value = b.get(key);
                  r = eqInternal(nextA.value[1], value, opts, stackA, stackB, path);
                  if(!r.result) {
                    r.a = nextA.value;
                    r.b = value;
                    r.reason = REASON.MAP_VALUE_EQUALITY;

                    break;
                  }
                }

              } else {
                r = result(false, REASON.SET_MAP_MISSING_KEY);
                r.a = key;
                r.b = key;

                break;
              }
            } else {
              //heavy check
              //we search by iterator for key equality using equal
              var itB = b.entries();
              var nextB = itB.next();

              while(!nextB.done) {
                //first check for keys
                r = eqInternal(nextA.value[0], nextB.value[0], opts, stackA, stackB, path);

                if(!r.result) {
                  r.reason = REASON.SET_MAP_MISSING_KEY;
                  r.a = key;
                  r.b = key;
                } else {
                  if(typeA.cls == 'map') {
                    r = eqInternal(nextA.value[1], nextB.value[1], opts, stackA, stackB, path);

                    if(!r.result) {
                      r.a = nextA.value;
                      r.b = nextB.value;
                      r.reason = REASON.MAP_VALUE_EQUALITY;
                    }
                  }

                  break;
                }

                nextB = itB.next();
              }
            }

            if(!r.result) {
              break;
            }

            nextA = itA.next();
          }

          stackA.pop();
          stackB.pop();

          if(!r.result) {
            r.reason = REASON.SET_MAP_MISSING_ENTRY;
            return r;
          }

          break; //check user properties
      }
  }

  // compare deep objects and arrays
  // stacks contain references only
  //

  l = stackA.length;
  while(l--) {
    if(stackA[l] == a) {
      return result(stackB[l] == b, REASON.CIRCULAR_VALUES);
    }
  }

  // add `a` and `b` to the stack of traversed objects
  stackA.push(a);
  stackB.push(b);

  var key;

  for(key in b) {
    if(hasOwnProperty.call(b, key)) {
      r = result(hasOwnProperty.call(a, key), format(REASON.MISSING_KEY, 'A', key));
      if(!r.result) {
        break;
      }

      if(r.result) {
        r = checkPropertyEquality(key);
        if(!r.result) {
          break;
        }
      }
    }
  }

  if(r.result) {
    // ensure both objects have the same number of properties
    for(key in a) {
      if(hasOwnProperty.call(a, key)) {
        r = result(hasOwnProperty.call(b, key), format(REASON.MISSING_KEY, 'B', key));
        if(!r.result) {
          return r;
        }
      }
    }
  }

  stackA.pop();
  stackB.pop();

  if(!r.result) return r;

  var prototypesEquals = false, canComparePrototypes = false;

  if(opts.checkProtoEql) {
    if(Object.getPrototypeOf) {//TODO should i check prototypes for === or use eq?
      prototypesEquals = Object.getPrototypeOf(a) === Object.getPrototypeOf(b);
      canComparePrototypes = true;
    } else if(a.__proto__ && b.__proto__) {
      prototypesEquals = a.__proto__ === b.__proto__;
      canComparePrototypes = true;
    }

    if(canComparePrototypes && !prototypesEquals) {
      r = result(prototypesEquals, REASON.EQUALITY_PROTOTYPE);
      r.showReason = true;
      if(!r.result) {
        return r;
      }
    }
  }

  return EQUALS;
}

var defaultOptions = {
  checkProtoEql: true,
  checkSubType: true
};

function eq(a, b, opts) {
  opts = opts || {};
  if(typeof opts.checkProtoEql !== 'boolean')
    opts.checkProtoEql = defaultOptions.checkProtoEql;
  if(typeof opts.checkSubType !== 'boolean')
    opts.checkSubType = defaultOptions.checkSubType;

  var r = eqInternal(a, b, opts, [], [], []);
  return r;
}

module.exports = eq;

eq.r = REASON;

},{"./format":21,"should-type":25}],23:[function(require,module,exports){
var getType = require('should-type');
var util = require('./util');

function genKeysFunc(f) {
  return function(value) {
    var k = f(value);
    k.sort();
    return k;
  };
}


function Formatter(opts) {
  opts = opts || {};

  this.seen = [];
  this.keys = genKeysFunc(opts.keys === false ? Object.getOwnPropertyNames : Object.keys);

  this.maxLineLength = typeof opts.maxLineLength === 'number' ? opts.maxLineLength : 60;
  this.propSep = opts.propSep || ',';

  this.isUTCdate = !!opts.isUTCdate;
}

Formatter.prototype = {
  constructor: Formatter,

  format: function(value) {
    var t = getType(value);
    var name1 = t.type, name2 = t.type;
    if(t.cls) {
      name1 += '_' + t.cls;
      name2 += '_' + t.cls;
    }
    if(t.sub) {
      name2 += '_' + t.sub;
    }
    var f = this['_format_' + name2] || this['_format_' + name1] || this['_format_' + t.type] || this.defaultFormat;
    return f.call(this, value).trim();
  },

  _formatObject: function(value, opts) {
    opts = opts || {};
    var mainKeys = opts.keys || this.keys(value);

    var len = 0;

    var formatPropertyValue = opts.formatPropertyValue || this.formatPropertyValue;
    var formatPropertyName = opts.formatPropertyName || this.formatPropertyName;
    var keyValueSep = opts.keyValueSep || ': ';
    var keyFilter = opts.keyFilter || function() { return true; };

    this.seen.push(value);
    var keys = [];

    mainKeys.forEach(function(key) {
      if(!keyFilter(key)) return;

      var fName = formatPropertyName.call(this, key);

      var f = (fName ? fName + keyValueSep : '') + formatPropertyValue.call(this, value, key);
      len += f.length;
      keys.push(f);
    }, this);
    this.seen.pop();

    (opts.additionalProperties || []).forEach(function(keyValue) {
      var f = keyValue[0] + keyValueSep + this.format(keyValue[1]);
      len += f.length;
      keys.push(f);
    }, this);

    var prefix = opts.prefix || Formatter.constructorName(value) || '';
    if(prefix.length > 0) prefix += ' ';

    var lbracket, rbracket;
    if(Array.isArray(opts.brackets)) {
      lbracket = opts.brackets && opts.brackets[0];
      rbracket = opts.brackets && opts.brackets[1];
    } else {
      lbracket = '{';
      rbracket = '}';
    }

    var rootValue = opts.value || '';

    if(keys.length === 0)
      return rootValue || (prefix + lbracket + rbracket);

    if(len <= this.maxLineLength) {
      return prefix + lbracket + ' ' + (rootValue ? rootValue + ' ' : '') + keys.join(this.propSep + ' ') + ' ' + rbracket;
    } else {
      return prefix + lbracket + '\n' + (rootValue ? '  ' + rootValue + '\n' : '') + keys.map(util.addSpaces).join(this.propSep + '\n') + '\n' + rbracket;
    }
  },

  formatObject: function(value, prefix, props) {
    props = props || this.keys(value);

    var len = 0;

    this.seen.push(value);
    props = props.map(function(prop) {
      var f = this.formatProperty(value, prop);
      len += f.length;
      return f;
    }, this);
    this.seen.pop();

    if(props.length === 0) return '{}';

    if(len <= this.maxLineLength) {
      return '{ ' + (prefix ? prefix + ' ' : '') + props.join(this.propSep + ' ') + ' }';
    } else {
      return '{' + '\n' + (prefix ? '  ' + prefix + '\n' : '') + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
    }
  },

  formatPropertyName: function(name) {
    return name.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/) ? name : this.format(name);
  },

  formatProperty: function(value, prop) {
    var desc = Formatter.getPropertyDescriptor(value, prop);

    var propName = this.formatPropertyName(prop);

    var propValue = desc.get && desc.set ?
      '[Getter/Setter]' : desc.get ?
      '[Getter]' : desc.set ?
      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
      '[Circular]' :
      this.format(desc.value);

    return propName + ': ' + propValue;
  },

  formatPropertyValue: function(value, prop) {
    var desc = Formatter.getPropertyDescriptor(value, prop);

    var propValue = desc.get && desc.set ?
      '[Getter/Setter]' : desc.get ?
      '[Getter]' : desc.set ?
      '[Setter]' : this.seen.indexOf(desc.value) >= 0 ?
      '[Circular]' :
      this.format(desc.value);

    return propValue;
  }
};

Formatter.add = function add(type, cls, sub, f) {
  var args = Array.prototype.slice.call(arguments);
  f = args.pop();
  Formatter.prototype['_format_' + args.join('_')] = f;
};

Formatter.formatObjectWithPrefix = function formatObjectWithPrefix(f) {
  return function(value) {
    var prefix = f.call(this, value);
    var props = this.keys(value);
    if(props.length == 0) return prefix;
    else return this.formatObject(value, prefix, props);
  };
};

var functionNameRE = /^\s*function\s*(\S*)\s*\(/;

Formatter.functionName = function functionName(f) {
  if(f.name) {
    return f.name;
  }
  var name = f.toString().match(functionNameRE)[1];
  return name;
};

Formatter.constructorName = function(obj) {
  while (obj) {
    var descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor');
    if (descriptor !== undefined &&
        typeof descriptor.value === 'function') {

        var name = Formatter.functionName(descriptor.value);
        if(name !== '') {
          return name;
        }
    }

    obj = Object.getPrototypeOf(obj);
  }
};

Formatter.getPropertyDescriptor = function(obj, value) {
  var desc;
  try {
    desc = Object.getOwnPropertyDescriptor(obj, value) || {value: obj[value]};
  } catch(e) {
    desc = {value: e};
  }
  return desc;
};

Formatter.generateFunctionForIndexedArray = function generateFunctionForIndexedArray(lengthProp, name, padding) {
  return function(value) {
    var max = this.byteArrayMaxLength || 50;
    var length = value[lengthProp];
    var formattedValues = [];
    var len = 0;
    for(var i = 0; i < max && i < length; i++) {
      var b = value[i] || 0;
      var v = util.pad0(b.toString(16), padding);
      len += v.length;
      formattedValues.push(v);
    }
    var prefix = value.constructor.name || name || '';
    if(prefix) prefix += ' ';

    if(formattedValues.length === 0)
      return prefix + '[]';

    if(len <= this.maxLineLength) {
      return prefix + '[ ' + formattedValues.join(this.propSep + ' ') + ' ' + ']';
    } else {
      return prefix + '[\n' + formattedValues.map(util.addSpaces).join(this.propSep + '\n') + '\n' + ']';
    }
  };
};

Formatter.add('undefined', function() { return 'undefined' });
Formatter.add('null', function() { return 'null' });
Formatter.add('boolean', function(value) { return value ? 'true': 'false' });
Formatter.add('symbol', function(value) { return value.toString() });

['number', 'boolean'].forEach(function(name) {
  Formatter.add('object', name, function(value) {
    return this._formatObject(value, {
      additionalProperties: [['[[PrimitiveValue]]', value.valueOf()]]
    });
  });
});

Formatter.add('object', 'string', function(value) {
  var realValue = value.valueOf();

  return this._formatObject(value, {
    keyFilter: function(key) {
      //skip useless indexed properties
      return !(key.match(/\d+/) && parseInt(key, 10) < realValue.length);
    },
    additionalProperties: [['[[PrimitiveValue]]', realValue]]
  });
});

Formatter.add('object', 'regexp', function(value) {
  return this._formatObject(value, {
    value: String(value)
  });
});

Formatter.add('number', function(value) {
  if(value === 0 && 1 / value < 0) return '-0';
  return String(value);
});

Formatter.add('string', function(value) {
  return '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
      .replace(/'/g, "\\'")
      .replace(/\\"/g, '"') + '\'';
});

Formatter.add('object', function(value) {
  return this._formatObject(value);
});

Formatter.add('object', 'arguments', function(value) {
  return this._formatObject(value, {
    prefix: 'Arguments',
    formatPropertyName: function(key) {
      if(!key.match(/\d+/)) {
        return this.formatPropertyName(key);
      }
    },
    brackets: ['[', ']']
  });
});

Formatter.add('object', 'array', function(value) {
  return this._formatObject(value, {
    formatPropertyName: function(key) {
      if(!key.match(/\d+/)) {
        return this.formatPropertyName(key);
      }
    },
    brackets: ['[', ']']
  });
});


function formatDate(value, isUTC) {
  var prefix = isUTC ? 'UTC' : '';

  var date = value['get' + prefix + 'FullYear']() +
    '-' +
    util.pad0(value['get' + prefix + 'Month']() + 1, 2) +
    '-' +
    util.pad0(value['get' + prefix + 'Date'](), 2);

  var time = util.pad0(value['get' + prefix + 'Hours'](), 2) +
    ':' +
    util.pad0(value['get' + prefix + 'Minutes'](), 2) +
    ':' +
    util.pad0(value['get' + prefix + 'Seconds'](), 2) +
    '.' +
    util.pad0(value['get' + prefix + 'Milliseconds'](), 3);

  var to = value.getTimezoneOffset();
  var absTo = Math.abs(to);
  var hours = Math.floor(absTo / 60);
  var minutes = absTo - hours * 60;
  var tzFormat = (to < 0 ? '+' : '-') + util.pad0(hours, 2) + util.pad0(minutes, 2);

  return date + ' ' + time + (isUTC ? '' : ' ' + tzFormat);
}

Formatter.add('object', 'date', function(value) {
  return this._formatObject(value, { value: formatDate(value, this.isUTCdate) });
});

Formatter.add('function', function(value) {
  return this._formatObject(value, {
    additionalProperties: [['name', Formatter.functionName(value)]]
  });
});

Formatter.add('object', 'error', function(value) {
  return this._formatObject(value, {
    prefix: value.name,
    additionalProperties: [['message', value.message]]
  });
});

Formatter.add('object', 'buffer', Formatter.generateFunctionForIndexedArray('length', 'Buffer', 2));

Formatter.add('object', 'array-buffer', Formatter.generateFunctionForIndexedArray('byteLength', 'ArrayBuffer', 2));

Formatter.add('object', 'typed-array', 'int8', Formatter.generateFunctionForIndexedArray('length', 'Int8Array', 2));
Formatter.add('object', 'typed-array', 'uint8', Formatter.generateFunctionForIndexedArray('length', 'Uint8Array', 2));
Formatter.add('object', 'typed-array', 'uint8clamped', Formatter.generateFunctionForIndexedArray('length', 'Uint8ClampedArray', 2));

Formatter.add('object', 'typed-array', 'int16', Formatter.generateFunctionForIndexedArray('length', 'Int16Array', 4));
Formatter.add('object', 'typed-array', 'uint16', Formatter.generateFunctionForIndexedArray('length', 'Uint16Array', 4));

Formatter.add('object', 'typed-array', 'int32', Formatter.generateFunctionForIndexedArray('length', 'Int32Array', 8));
Formatter.add('object', 'typed-array', 'uint32', Formatter.generateFunctionForIndexedArray('length', 'Uint32Array', 8));

//TODO add float32 and float64

Formatter.add('object', 'promise', function() {
  return '[Promise]';//TODO it could be nice to inspect its state and value
});

Formatter.add('object', 'xhr', function() {
  return '[XMLHttpRequest]';//TODO it could be nice to inspect its state
});

Formatter.add('object', 'html-element', function(value) {
  return value.outerHTML;
});

Formatter.add('object', 'html-element', '#text', function(value) {
  return value.nodeValue;
});

Formatter.add('object', 'html-element', '#document', function(value) {
  return value.documentElement.outerHTML;
});

Formatter.add('object', 'host', function() {
  return '[Host]';
});

Formatter.add('object', 'set', function(value) {
  var iter = value.values();
  var len = 0;

  this.seen.push(value);

  var props = [];

  var next = iter.next();
  while(!next.done) {
    var val = next.value;
    var f = this.format(val);
    len += f.length;
    props.push(f);

    next = iter.next();
  }

  this.seen.pop();

  if(props.length === 0) return 'Set {}';

  if(len <= this.maxLineLength) {
    return 'Set { ' + props.join(this.propSep + ' ') + ' }';
  } else {
    return 'Set {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
  }
});

Formatter.add('object', 'map', function(value) {
  var iter = value.entries();
  var len = 0;

  this.seen.push(value);

  var props = [];

  var next = iter.next();
  while(!next.done) {
    var val = next.value;
    var fK = this.format(val[0]);
    var fV = this.format(val[1]);

    var f;
    if((fK.length + fV.length + 4) <= this.maxLineLength) {
      f = fK + ' => ' + fV;
    } else {
      f = fK + ' =>\n' + fV;
    }

    len += fK.length + fV.length + 4;
    props.push(f);

    next = iter.next();
  }

  this.seen.pop();

  if(props.length === 0) return 'Map {}';

  if(len <= this.maxLineLength) {
    return 'Map { ' + props.join(this.propSep + ' ') + ' }';
  } else {
    return 'Map {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}';
  }
});

Formatter.prototype.defaultFormat = Formatter.prototype._format_object;

function defaultFormat(value, opts) {
  return new Formatter(opts).format(value);
}

defaultFormat.Formatter = Formatter;
module.exports = defaultFormat;

},{"./util":24,"should-type":25}],24:[function(require,module,exports){
function addSpaces(v) {
  return v.split('\n').map(function(vv) { return '  ' + vv; }).join('\n');
}

function pad(str, value, filler) {
  str = String(str)
  var isRight = false;

  if(value < 0) {
    isRight = true;
    value = -value;
  }

  if(str.length < value) {
    var padding = new Array(value - str.length + 1).join(filler);
    return isRight ? str + padding : padding + str;
  } else{
    return str;
  }
}

module.exports = {
  addSpaces: addSpaces,
  pad: pad,
  pad0: function(str, value) {
    return pad(str, value, '0');
  }
};

},{}],25:[function(require,module,exports){
var toString = Object.prototype.toString;

var types = require('./types');

/**
 * Simple data function to store type information
 * @param {string} type Usually what is returned from typeof
 * @param {string} cls  Sanitized @Class via Object.prototype.toString
 * @param {string} sub  If type and cls the same, and need to specify somehow
 * @private
 * @example
 *
 * //for null
 * new Type('null');
 *
 * //for Date
 * new Type('object', 'date');
 *
 * //for Uint8Array
 *
 * new Type('object', 'typed-array', 'uint8');
 */
function Type(type, cls, sub) {
  this.type = type;
  this.cls = cls;
  this.sub = sub;
}

/**
 * Function to store type checks
 * @private
 */
function TypeChecker() {
  this.checks = [];
}

TypeChecker.prototype = {
  add: function(func) {
    this.checks.push(func);
    return this;
  },

  addTypeOf: function(type, res) {
    return this.add(function(obj, tpeOf) {
      if(tpeOf === type) {
        return new Type(res);
      }
    });
  },

  addClass: function(cls, res, sub) {
    return this.add(function(obj, tpeOf, objCls) {
      if(objCls === cls) {
        return new Type(types.OBJECT, res, sub);
      }
    });
  },

  getType: function(obj) {
    var typeOf = typeof obj;
    var cls = toString.call(obj);

    for(var i = 0, l = this.checks.length; i < l; i++) {
      var res = this.checks[i].call(this, obj, typeOf, cls);
      if(typeof res !== 'undefined') return res;
    }

  }
};

var main = new TypeChecker();

//TODO add iterators

main
  .addTypeOf(types.NUMBER, types.NUMBER)
  .addTypeOf(types.UNDEFINED, types.UNDEFINED)
  .addTypeOf(types.STRING, types.STRING)
  .addTypeOf(types.BOOLEAN, types.BOOLEAN)
  .addTypeOf(types.FUNCTION, types.FUNCTION)
  .addTypeOf(types.SYMBOL, types.SYMBOL)
  .add(function(obj, tpeOf) {
    if(obj === null) return new Type(types.NULL);
  })
  .addClass('[object String]', types.STRING)
  .addClass('[object Boolean]', types.BOOLEAN)
  .addClass('[object Number]', types.NUMBER)
  .addClass('[object Array]', types.ARRAY)
  .addClass('[object RegExp]', types.REGEXP)
  .addClass('[object Error]', types.ERROR)
  .addClass('[object Date]', types.DATE)
  .addClass('[object Arguments]', types.ARGUMENTS)
  .addClass('[object Math]')
  .addClass('[object JSON]')
  .addClass('[object ArrayBuffer]', types.ARRAY_BUFFER)
  .addClass('[object Int8Array]', types.TYPED_ARRAY, 'int8')
  .addClass('[object Uint8Array]', types.TYPED_ARRAY, 'uint8')
  .addClass('[object Uint8ClampedArray]', types.TYPED_ARRAY, 'uint8clamped')
  .addClass('[object Int16Array]', types.TYPED_ARRAY, 'int16')
  .addClass('[object Uint16Array]', types.TYPED_ARRAY, 'uint16')
  .addClass('[object Int32Array]', types.TYPED_ARRAY, 'int32')
  .addClass('[object Uint32Array]', types.TYPED_ARRAY, 'uint32')
  .addClass('[object Float32Array]', types.TYPED_ARRAY, 'float32')
  .addClass('[object Float64Array]', types.TYPED_ARRAY, 'float64')
  .addClass('[object DataView]', types.DATA_VIEW)
  .addClass('[object Map]', types.MAP)
  .addClass('[object WeakMap]', types.WEAK_MAP)
  .addClass('[object Set]', types.SET)
  .addClass('[object WeakSet]', types.WEAK_SET)
  .addClass('[object Promise]', types.PROMISE)
  .addClass('[object Blob]', types.BLOB)
  .addClass('[object File]', types.FILE)
  .addClass('[object FileList]', types.FILE_LIST)
  .addClass('[object XMLHttpRequest]', types.XHR)
  .add(function(obj) {
    if((typeof Promise === types.FUNCTION && obj instanceof Promise) ||
        (typeof obj.then === types.FUNCTION)) {
          return new Type(types.OBJECT, types.PROMISE);
        }
  })
  .add(function(obj) {
    if(typeof Buffer !== 'undefined' && obj instanceof Buffer) {
      return new Type(types.OBJECT, types.BUFFER);
    }
  })
  .add(function(obj) {
    if(typeof Node !== 'undefined' && obj instanceof Node) {
      return new Type(types.OBJECT, types.HTML_ELEMENT, obj.nodeName);
    }
  })
  .add(function(obj) {
    // probably at the begginging should be enough these checks
    if(obj.Boolean === Boolean && obj.Number === Number && obj.String === String && obj.Date === Date) {
      return new Type(types.OBJECT, types.HOST);
    }
  })
  .add(function() {
    return new Type(types.OBJECT);
  });

/**
 * Get type information of anything
 *
 * @param  {any} obj Anything that could require type information
 * @return {Type}    type info
 */
function getGlobalType(obj) {
  return main.getType(obj);
}

getGlobalType.checker = main;
getGlobalType.TypeChecker = TypeChecker;
getGlobalType.Type = Type;

Object.keys(types).forEach(function(typeName) {
  getGlobalType[typeName] = types[typeName];
});

module.exports = getGlobalType;

},{"./types":26}],26:[function(require,module,exports){
var types = {
  NUMBER: 'number',
  UNDEFINED: 'undefined',
  STRING: 'string',
  BOOLEAN: 'boolean',
  OBJECT: 'object',
  FUNCTION: 'function',
  NULL: 'null',
  ARRAY: 'array',
  REGEXP: 'regexp',
  DATE: 'date',
  ERROR: 'error',
  ARGUMENTS: 'arguments',
  SYMBOL: 'symbol',
  ARRAY_BUFFER: 'array-buffer',
  TYPED_ARRAY: 'typed-array',
  DATA_VIEW: 'data-view',
  MAP: 'map',
  SET: 'set',
  WEAK_SET: 'weak-set',
  WEAK_MAP: 'weak-map',
  PROMISE: 'promise',

// node buffer
  BUFFER: 'buffer',

// dom html element
  HTML_ELEMENT: 'html-element',
  HTML_ELEMENT_TEXT: 'html-element-text',
  DOCUMENT: 'document',
  WINDOW: 'window',
  FILE: 'file',
  FILE_LIST: 'file-list',
  BLOB: 'blob',

  HOST: 'host',

  XHR: 'xhr'
};

module.exports = types;

},{}]},{},[1])(1)
});
/*!
 * should - test framework agnostic BDD-style assertions
 * @version v8.0.1
 * @author TJ Holowaychuk <tj@vision-media.ca> and contributors
 * @link https://github.com/shouldjs/should.js
 * @license MIT
 */
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Should=t()}}(function(){return function t(e,r,n){function a(s,i){if(!r[s]){if(!e[s]){var u="function"==typeof require&&require;if(!i&&u)return u(s,!0);if(o)return o(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var h=r[s]={exports:{}};e[s][0].call(h.exports,function(t){var r=e[s][1][t];return a(r?r:t)},h,h.exports,t,e,r,n)}return r[s].exports}for(var o="function"==typeof require&&require,s=0;s<n.length;s++)a(n[s]);return a}({1:[function(t,e,r){window.Should=t("./index"),Object.defineProperty(window,"should",{enumerable:!1,configurable:!0,value:window.Should})},{"./index":2}],2:[function(t,e,r){var n=t("./lib/should"),a=Object.prototype,o="should";try{var s=n.extend(o,a);n._prevShould=s}catch(i){}e.exports=n},{"./lib/should":19}],3:[function(t,e,r){function n(t){return i+t}function a(t){return t.split("\n").map(n).join("\n")}var o=t("./util"),s=function(t){if(o.merge(this,t),t.message||Object.defineProperty(this,"message",{get:function(){return this._message||(this._message=this.generateMessage(),this.generatedMessage=!0),this._message},configurable:!0,enumerable:!1}),Error.captureStackTrace)Error.captureStackTrace(this,this.stackStartFunction);else{var e=new Error;if(e.stack){var r=e.stack;if(this.stackStartFunction){var n=o.functionName(this.stackStartFunction),a=r.indexOf("\n"+n);if(a>=0){var s=r.indexOf("\n",a+1);r=r.substring(s+1)}}this.stack=r}}},i="    ";s.prototype=Object.create(Error.prototype,{name:{value:"AssertionError"},generateMessage:{value:function(){if(!this.operator&&this.previous)return this.previous.message;var t=o.format(this.actual),e="expected"in this?" "+o.format(this.expected):"",r="details"in this&&this.details?" ("+this.details+")":"",n=this.previous?"\n"+a(this.previous.message):"";return"expected "+t+(this.negate?" not ":" ")+this.operator+e+r+n}}}),e.exports=s},{"./util":20}],4:[function(t,e,r){function n(t){this.obj=t,this.anyOne=!1,this.negate=!1,this.params={actual:t}}function a(){n.apply(this,arguments)}var o=t("./assertion-error");n.prototype={constructor:n,assert:function(t){if(t)return this;var e=this.params;throw"obj"in e&&!("actual"in e)?e.actual=e.obj:"obj"in e||"actual"in e||(e.actual=this.obj),e.stackStartFunction=e.stackStartFunction||this.assert,e.negate=this.negate,e.assertion=this,new o(e)},fail:function(){return this.assert(!1)}},a.prototype.then=function(t,e){return this.obj.then(t,e)},n.add=function(t,e){Object.defineProperty(n.prototype,t,{enumerable:!0,configurable:!0,value:function(){var r=new n(this.obj,this,t);r.anyOne=this.anyOne;try{e.apply(r,arguments)}catch(a){if(a instanceof o){if(this.negate)return this.obj=r.obj,this.negate=!1,this;r!==a.assertion&&(r.params.previous=a),r.negate=!1,r.fail()}throw a}return this.negate&&(r.negate=!0,r.params.details="false negative fail",r.fail()),this.params.operator||(this.params=r.params),this.obj=r.obj,this.negate=!1,this}}),Object.defineProperty(a.prototype,t,{enumerable:!0,configurable:!0,value:function(){var e=arguments;return this.obj=this.obj.then(function(r){return r[t].apply(r,e)}),this}})},n.addChain=function(t,e){e=e||function(){},Object.defineProperty(n.prototype,t,{get:function(){return e.call(this),this},enumerable:!0}),Object.defineProperty(a.prototype,t,{enumerable:!0,configurable:!0,get:function(){return this.obj=this.obj.then(function(e){return e[t]}),this}})},n.alias=function(t,e){var r=Object.getOwnPropertyDescriptor(n.prototype,t);if(!r)throw new Error("Alias "+t+" -> "+e+" could not be created as "+t+" not defined");Object.defineProperty(n.prototype,e,r);var o=Object.getOwnPropertyDescriptor(a.prototype,t);o&&Object.defineProperty(a.prototype,e,o)},n.addChain("not",function(){this.negate=!this.negate}),n.addChain("any",function(){this.anyOne=!0}),e.exports=n,e.exports.PromisedAssertion=a},{"./assertion-error":3}],5:[function(t,e,r){var n=t("should-format").Formatter,a={checkProtoEql:!1,getFormatter:function(t){return new n(t||a)}};e.exports=a},{"should-format":23}],6:[function(t,e,r){function n(t,e,r,a,o){var s=new i(t);s.params={operator:a,expected:e,message:r,stackStartFunction:o||n},s.fail()}function a(t,e){t||n(t,!0,e,"==",h.ok)}function o(t,e){return t&&e?"[object RegExp]"==Object.prototype.toString.call(e)?e.test(t):t instanceof e?!0:e.call({},t)===!0?!0:!1:!1}function s(t,e,r,a){var s;"string"==typeof r&&(a=r,r=null);try{e()}catch(i){s=i}if(a=(r&&r.name?" ("+r.name+")":".")+(a?" "+a:"."),t&&!s&&n(s,r,"Missing expected exception"+a),!t&&o(s,r)&&n(s,r,"Got unwanted exception"+a),t&&s&&r&&!o(s,r)||!t&&s)throw s}var i=t("./../assertion"),u=t("should-equal"),c=Array.prototype.slice,h=e.exports=a;h.fail=n,h.ok=a,h.equal=function(t,e,r){t!=e&&n(t,e,r,"==",h.equal)},h.notEqual=function(t,e,r){t==e&&n(t,e,r,"!=",h.notEqual)},h.deepEqual=function(t,e,r){u(t,e).result||n(t,e,r,"deepEqual",h.deepEqual)},h.notDeepEqual=function(t,e,r){u(t,e).result&&n(t,e,r,"notDeepEqual",h.notDeepEqual)},h.strictEqual=function(t,e,r){t!==e&&n(t,e,r,"===",h.strictEqual)},h.notStrictEqual=function(t,e,r){t===e&&n(t,e,r,"!==",h.notStrictEqual)},h["throws"]=function(t,e,r){s.apply(this,[!0].concat(c.call(arguments)))},h.doesNotThrow=function(t,e){s.apply(this,[!1].concat(c.call(arguments)))},h.ifError=function(t){if(t)throw t}},{"./../assertion":4,"should-equal":22}],7:[function(t,e,r){var n=t("../util"),a=t("./_assert"),o=t("../assertion-error");e.exports=function(t){var e=t.format;n.merge(t,a),t.exist=t.exists=function(r,n){if(null==r)throw new o({message:n||"expected "+e(r)+" to exist",stackStartFunction:t.exist})},t.not={},t.not.exist=t.not.exists=function(r,n){if(null!=r)throw new o({message:n||"expected "+e(r)+" to not exist",stackStartFunction:t.not.exist})}}},{"../assertion-error":3,"../util":20,"./_assert":6}],8:[function(t,e,r){e.exports=function(t,e){e.add("true",function(){this.is.exactly(!0)}),e.alias("true","True"),e.add("false",function(){this.is.exactly(!1)}),e.alias("false","False"),e.add("ok",function(){this.params={operator:"to be truthy"},this.assert(this.obj)})}},{}],9:[function(t,e,r){e.exports=function(t,e){["an","of","a","and","be","has","have","with","is","which","the","it"].forEach(function(t){e.addChain(t)})}},{}],10:[function(t,e,r){var n=t("../util"),a=t("should-equal");e.exports=function(t,e){var r=t.format;e.add("containEql",function(t){this.params={operator:"to contain "+r(t)},this.is.not["null"]().and.not.undefined();var e=this.obj;"string"==typeof e?this.assert(e.indexOf(String(t))>=0):n.isIndexable(e)?this.assert(n.some(e,function(e){return a(e,t).result})):this.have.properties(t)}),e.add("containDeepOrdered",function(e){this.params={operator:"to contain "+r(e)};var a=this.obj;if("string"==typeof a)this.is.equal(String(e));else if(n.isIndexable(a)&&n.isIndexable(e)){for(var o=0,s=0,i=n.length(a),u=n.length(e);i>o&&u>s;o++)try{t(a[o]).containDeepOrdered(e[s]),s++}catch(c){if(c instanceof t.AssertionError)continue;throw c}this.assert(s===u)}else null!=a&&null!=e&&"object"==typeof a&&"object"==typeof e?(n.forEach(e,function(e,r){t(a[r]).containDeepOrdered(e)}),n.isEmptyObject(e)&&this.eql(e)):this.eql(e)}),e.add("containDeep",function(e){this.params={operator:"to contain "+r(e)};var a=this.obj;if("string"==typeof a)this.is.equal(String(e));else if(n.isIndexable(a)&&n.isIndexable(e)){var o={};n.forEach(e,function(e){this.assert(n.some(a,function(r,n){if(n in o)return!1;try{return t(r).containDeep(e),o[n]=!0,!0}catch(a){if(a instanceof t.AssertionError)return!1;throw a}}))},this)}else null!=a&&null!=e&&"object"==typeof a&&"object"==typeof e?(n.forEach(e,function(e,r){t(a[r]).containDeep(e)}),n.isEmptyObject(e)&&this.eql(e)):this.eql(e)})}},{"../util":20,"should-equal":22}],11:[function(t,e,r){function n(t,e,r){return((t.path.length>0?"at "+t.path.map(s.formatProp).join(" -> "):"")+(t.a===e?"":", A has "+s.format(t.a))+(t.b===r?"":" and B has "+s.format(t.b))+(t.showReason?" because "+t.reason:"")).trim()}var a=t("should-equal"),o=t("should-type"),s=t("../util");e.exports=function(t,e){function r(r,n,a){e.add(r,function(e){1!==arguments.length?e=Array.prototype.slice.call(arguments):t(e).be.Array(),this.params={operator:n,expected:e};var r=this.obj,o=!1;s.forEach(e,function(e){try{return t(e)[a](r),o=!0,!1}catch(n){if(n instanceof t.AssertionError)return;throw n}}),this.assert(o)})}e.add("eql",function(e,r){this.params={operator:"to equal",expected:e,message:r};var s=a(this.obj,e,t.config);this.params.details=s.result?"":n(s,this.obj,e),this.params.showDiff=a(o(this.obj),o(e)).result,this.assert(s.result)}),e.add("equal",function(t,e){this.params={operator:"to be",expected:t,message:e},this.params.showDiff=a(o(this.obj),o(t)).result,this.assert(t===this.obj)}),e.alias("equal","exactly"),e.alias("eql","deepEqual"),r("equalOneOf","to be equals one of","equal"),r("oneOf","to be one of","eql")}},{"../util":20,"should-equal":22,"should-type":25}],12:[function(t,e,r){var n=t("../util");e.exports=function(t,e){var r=t.format;e.add("throw",function(e,a){var o=this.obj,s={},i="",u=!1;if(n.isGeneratorFunction(o))return t(o())["throw"](e,a);if(n.isGeneratorObject(o))return t(o.next.bind(o))["throw"](e,a);this.is.a.Function();var c=!0;try{o()}catch(h){u=!0,s=h}if(u)if(e){if("string"==typeof e)c=e==s.message;else if(e instanceof RegExp)c=e.test(s.message);else if("function"==typeof e)c=s instanceof e;else if(null!=e)try{t(s).match(e)}catch(h){if(!(h instanceof t.AssertionError))throw h;i=": "+h.message,c=!1}if(c){if("function"==typeof e&&a)try{t(s).match(a)}catch(h){if(!(h instanceof t.AssertionError))throw h;i=": "+h.message,c=!1}}else"string"==typeof e||e instanceof RegExp?i=" with a message matching "+r(e)+", but got '"+s.message+"'":"function"==typeof e&&(i=" of type "+n.functionName(e)+", but got "+n.functionName(s.constructor))}else i=" (got "+r(s)+")";this.params={operator:"to throw exception"+i},this.assert(u),this.assert(c)}),e.alias("throw","throwError")}},{"../util":20}],13:[function(t,e,r){var n=t("../util"),a=t("should-equal");e.exports=function(t,e){var r=t.format;e.add("match",function(e,o){if(this.params={operator:"to match "+r(e),message:o},!a(this.obj,e).result)if(e instanceof RegExp){if("string"==typeof this.obj)this.assert(e.exec(this.obj));else if(n.isIndexable(this.obj))n.forEach(this.obj,function(t){this.assert(e.exec(t))},this);else if(null!=this.obj&&"object"==typeof this.obj){var s=[],i=[];n.forEach(this.obj,function(t,a){e.exec(t)?i.push(n.formatProp(a)):s.push(n.formatProp(a)+" ("+r(t)+")")},this),s.length&&(this.params.operator+="\n    not matched properties: "+s.join(", ")),i.length&&(this.params.operator+="\n    matched properties: "+i.join(", ")),this.assert(0===s.length)}}else if("function"==typeof e){var u;u=e(this.obj),"boolean"==typeof u&&this.assert(u)}else null!=e&&null!=this.obj&&"object"==typeof e?(s=[],i=[],n.forEach(e,function(e,a){try{t(this.obj).have.property(a).which.match(e),i.push(n.formatProp(a))}catch(o){if(!(o instanceof t.AssertionError))throw o;s.push(n.formatProp(a)+" ("+r(this.obj[a])+")")}},this),s.length&&(this.params.operator+="\n    not matched properties: "+s.join(", ")),i.length&&(this.params.operator+="\n    matched properties: "+i.join(", ")),this.assert(0===s.length)):this.assert(!1)}),e.add("matchEach",function(e,a){this.params={operator:"to match each "+r(e),message:a},n.forEach(this.obj,function(r){t(r).match(e)},this)}),e.add("matchAny",function(e,a){this.params={operator:"to match any "+r(e),message:a},this.assert(n.some(this.obj,function(r){try{return t(r).match(e),!0}catch(n){if(n instanceof t.AssertionError)return!1;throw n}}))}),e.alias("matchAny","matchSome"),e.alias("matchEach","matchEvery")}},{"../util":20,"should-equal":22}],14:[function(t,e,r){e.exports=function(t,e){e.add("NaN",function(){this.params={operator:"to be NaN"},this.assert(this.obj!==this.obj)}),e.add("Infinity",function(){this.params={operator:"to be Infinity"},this.is.a.Number().and.not.a.NaN().and.assert(!isFinite(this.obj))}),e.add("within",function(t,e,r){this.params={operator:"to be within "+t+".."+e,message:r},this.assert(this.obj>=t&&this.obj<=e)}),e.add("approximately",function(t,e,r){this.params={operator:"to be approximately "+t+" ±"+e,message:r},this.assert(Math.abs(this.obj-t)<=e)}),e.add("above",function(t,e){this.params={operator:"to be above "+t,message:e},this.assert(this.obj>t)}),e.add("below",function(t,e){this.params={operator:"to be below "+t,message:e},this.assert(this.obj<t)}),e.alias("above","greaterThan"),e.alias("below","lessThan"),e.add("aboveOrEqual",function(t,e){this.params={operator:"to be above or equal"+t,message:e},this.assert(this.obj>=t)}),e.add("belowOrEqual",function(t,e){this.params={operator:"to be below or equal"+t,message:e},this.assert(this.obj<=t)}),e.alias("aboveOrEqual","greaterThanOrEqual"),e.alias("belowOrEqual","lessThanOrEqual")}},{}],15:[function(t,e,r){var n=t("../util"),a=t("../assertion").PromisedAssertion,o=t("../assertion");e.exports=function(t){o.add("Promise",function(){this.params={operator:"to be promise"};var e=this.obj;t(e).have.property("then").which.is.a.Function()}),o.prototype.fulfilled=function(){this.params={operator:"to be fulfilled"},t(this.obj).be.a.Promise();var e=this;return this.obj.then(function(t){return e.negate&&e.fail(),t},function(t){return e.negate||e.fail(),t})},o.prototype.rejected=function(){this.params={operator:"to be rejected"},t(this.obj).be.a.Promise();var e=this;return this.obj.then(function(t){return e.negate||e.fail(),t},function(t){return e.negate&&e.fail(),t})},o.prototype.fulfilledWith=function(e){this.params={operator:"to be fulfilled"},t(this.obj).be.a.Promise();var r=this;return this.obj.then(function(n){return r.negate&&r.fail(),t(n).eql(e),n},function(t){return r.negate||r.fail(),t})},o.prototype.rejectedWith=function(e,r){this.params={operator:"to be rejected"},t(this.obj).be.a.Promise();var a=this;return this.obj.then(function(t){return a.negate||a.fail(),t},function(o){a.negate&&a.fail();var s=!0,i="";if("string"==typeof e)s=e===o.message;else if(e instanceof RegExp)s=e.test(o.message);else if("function"==typeof e)s=o instanceof e;else if(null!==e&&"object"==typeof e)try{t(o).match(e)}catch(u){if(!(u instanceof t.AssertionError))throw u;i=": "+u.message,s=!1}if(s){if("function"==typeof e&&r)try{t(o).match(r)}catch(u){if(!(u instanceof t.AssertionError))throw u;i=": "+u.message,s=!1}}else"string"==typeof e||e instanceof RegExp?i=" with a message matching "+t.format(e)+", but got '"+o.message+"'":"function"==typeof e&&(i=" of type "+n.functionName(e)+", but got "+n.functionName(o.constructor));return a.params.operator+=i,a.assert(s),o})},Object.defineProperty(o.prototype,"finally",{get:function(){t(this.obj).be.a.Promise();var e=this;return new a(this.obj.then(function(r){var n=t(r);return n.negate=e.negate,n.anyOne=e.anyOne,n}))}}),o.alias("finally","eventually")}},{"../assertion":4,"../util":20}],16:[function(t,e,r){var n=t("../util"),a=t("should-equal"),o=Array.prototype.slice;e.exports=function(t,e){function r(){var t={};if(arguments.length>1)t.names=o.call(arguments);else{var e=arguments[0];"string"==typeof e?t.names=[e]:n.isIndexable(e)?t.names=e:(t.names=Object.keys(e),t.values=e)}return t}var s=t.format;e.add("propertyWithDescriptor",function(e,r){this.params={actual:this.obj,operator:"to have own property with descriptor "+s(r)};var n=this.obj;this.have.ownProperty(e),t(Object.getOwnPropertyDescriptor(Object(n),e)).have.properties(r)}),e.add("enumerable",function(t,e){t=n.convertPropertyName(t),this.params={operator:"to have enumerable property "+n.formatProp(t)+(arguments.length>1?" equal to "+s(e):"")};var r={enumerable:!0};arguments.length>1&&(r.value=e),this.have.propertyWithDescriptor(t,r)}),e.add("enumerables",function(e){var a=r.apply(null,arguments);this.params={operator:"to have enumerables "+a.names.map(n.formatProp)};var o=this.obj;a.names.forEach(function(e){t(o).have.enumerable(e)})}),e.add("property",function(t,e){if(t=n.convertPropertyName(t),arguments.length>1){var r={};r[t]=e,this.have.properties(r)}else this.have.properties(t);this.obj=this.obj[t]}),e.add("properties",function(t){var e={};arguments.length>1?t=o.call(arguments):Array.isArray(t)||("string"==typeof t||"symbol"==typeof t?t=[t]:(e=t,t=Object.keys(t)));var r=Object(this.obj),i=[];t.forEach(function(t){t in r||i.push(n.formatProp(t))});var u=i;0===u.length?u=t.map(n.formatProp):this.anyOne&&(u=t.filter(function(t){return i.indexOf(n.formatProp(t))<0}).map(n.formatProp));var c=(1===u.length?"to have property ":"to have "+(this.anyOne?"any of ":"")+"properties ")+u.join(", ");this.params={obj:this.obj,operator:c},this.assert(0===i.length||this.anyOne&&i.length!=t.length);var h=Object.keys(e);if(h.length){var f=[];u=[],h.forEach(function(t){var o=e[t];a(r[t],o).result?u.push(n.formatProp(t)+" of "+s(o)):f.push(n.formatProp(t)+" of "+s(o)+" (got "+s(r[t])+")")}),(0!==f.length&&!this.anyOne||this.anyOne&&0===u.length)&&(u=f),c=(1===u.length?"to have property ":"to have "+(this.anyOne?"any of ":"")+"properties ")+u.join(", "),this.params={obj:this.obj,operator:c},this.assert(0===f.length||this.anyOne&&f.length!=h.length)}}),e.add("length",function(t,e){this.have.property("length",t,e)}),e.alias("length","lengthOf");var i=Object.prototype.hasOwnProperty;e.add("ownProperty",function(t,e){t=n.convertPropertyName(t),this.params={actual:this.obj,operator:"to have own property "+n.formatProp(t),message:e},this.assert(i.call(this.obj,t)),this.obj=this.obj[t]}),e.alias("ownProperty","hasOwnProperty"),e.add("empty",function(){if(this.params={operator:"to be empty"},void 0!==n.length(this.obj))t(this.obj).have.property("length",0);else{var e=Object(this.obj);for(var r in e)t(this.obj).not.have.ownProperty(r)}},!0),e.add("keys",function(t){arguments.length>1?t=o.call(arguments):1===arguments.length&&"string"==typeof t?t=[t]:0===arguments.length&&(t=[]),t=t.map(String);var e=Object(this.obj),r=[];t.forEach(function(t){i.call(this.obj,t)||r.push(n.formatProp(t))},this);var a=[];Object.keys(e).forEach(function(e){t.indexOf(e)<0&&a.push(n.formatProp(e))});var s=0===t.length?"to be empty":"to have "+(1===t.length?"key ":"keys ");this.params={operator:s+t.map(n.formatProp).join(", ")},r.length>0&&(this.params.operator+="\n	missing keys: "+r.join(", ")),a.length>0&&(this.params.operator+="\n	extra keys: "+a.join(", ")),this.assert(0===r.length&&0===a.length)}),e.alias("keys","key"),e.add("propertyByPath",function(e){arguments.length>1?e=o.call(arguments):1===arguments.length&&"string"==typeof e?e=[e]:0===arguments.length&&(e=[]);var r=e.map(n.formatProp);e=e.map(String);for(var a,s=t(Object(this.obj)),i=[];a=e.shift();)this.params={operator:"to have property by path "+r.join(", ")+" - failed on "+n.formatProp(a)},s=s.have.property(a),i.push(a);this.params={obj:this.obj,operator:"to have property by path "+r.join(", ")},this.obj=s.obj})}},{"../util":20,"should-equal":22}],17:[function(t,e,r){e.exports=function(t,e){e.add("startWith",function(e,r){this.params={operator:"to start with "+t.format(e),message:r},this.assert(0===this.obj.indexOf(e))}),e.add("endWith",function(e,r){this.params={operator:"to end with "+t.format(e),message:r},this.assert(this.obj.indexOf(e,this.obj.length-e.length)>=0)})}},{}],18:[function(t,e,r){var n=t("../util");e.exports=function(t,e){e.add("Number",function(){this.params={operator:"to be a number"},this.have.type("number")}),e.add("arguments",function(){this.params={operator:"to be arguments"},this.have["class"]("Arguments")}),e.alias("arguments","Arguments"),e.add("type",function(e,r){this.params={operator:"to have type "+e,message:r},t(typeof this.obj).be.exactly(e)}),e.add("instanceof",function(t,e){this.params={operator:"to be an instance of "+n.functionName(t),message:e},this.assert(Object(this.obj)instanceof t)}),e.alias("instanceof","instanceOf"),e.add("Function",function(){this.params={operator:"to be a function"},this.have.type("function")}),e.add("Object",function(){this.params={operator:"to be an object"},this.is.not["null"]().and.have.type("object")}),e.add("String",function(){this.params={operator:"to be a string"},this.have.type("string")}),e.add("Array",function(){this.params={operator:"to be an array"},this.have["class"]("Array")}),e.add("Boolean",function(){this.params={operator:"to be a boolean"},this.have.type("boolean")}),e.add("Error",function(){this.params={operator:"to be an error"},this.have.instanceOf(Error)}),e.add("null",function(){this.params={operator:"to be null"},this.assert(null===this.obj)}),e.alias("null","Null"),e.add("class",function(t){this.params={operator:"to have [[Class]] "+t},this.assert(Object.prototype.toString.call(this.obj)==="[object "+t+"]")}),e.alias("class","Class"),e.add("undefined",function(){this.params={operator:"to be undefined"},this.assert(void 0===this.obj)}),e.alias("undefined","Undefined"),e.add("iterable",function(){this.params={operator:"to be iterable"},t(this.obj).have.property(Symbol.iterator).which.is.a.Function()}),e.add("iterator",function(){this.params={operator:"to be iterator"},t(this.obj).have.property("next").which.is.a.Function()}),e.add("generator",function(){this.params={operator:"to be generator"},t(this.obj).be.iterable.and.iterator.and.it.is.equal(this.obj[Symbol.iterator]())})}},{"../util":20}],19:[function(t,e,r){function n(t){return new n.Assertion(t)}var a=t("./util");n.AssertionError=t("./assertion-error"),n.Assertion=t("./assertion"),n.format=a.format,n.type=t("should-type"),n.util=a,n.config=t("./config"),r=e.exports=n,n.extend=function(t,e){t=t||"should",e=e||Object.prototype;var r=Object.getOwnPropertyDescriptor(e,t);return Object.defineProperty(e,t,{set:function(){},get:function(){return n(a.isWrapperType(this)?this.valueOf():this)},configurable:!0}),{name:t,descriptor:r,proto:e}},n.noConflict=function(t){return t=t||n._prevShould,t&&(delete t.proto[t.name],t.descriptor&&Object.defineProperty(t.proto,t.name,t.descriptor)),n},n.use=function(t){return t(n,n.Assertion),this},n.use(t("./ext/assert")).use(t("./ext/chain")).use(t("./ext/bool")).use(t("./ext/number")).use(t("./ext/eql")).use(t("./ext/type")).use(t("./ext/string")).use(t("./ext/property")).use(t("./ext/error")).use(t("./ext/match")).use(t("./ext/contain")).use(t("./ext/promise"))},{"./assertion":4,"./assertion-error":3,"./config":5,"./ext/assert":7,"./ext/bool":8,"./ext/chain":9,"./ext/contain":10,"./ext/eql":11,"./ext/error":12,"./ext/match":13,"./ext/number":14,"./ext/promise":15,"./ext/property":16,"./ext/string":17,"./ext/type":18,"./util":20,"should-type":25}],20:[function(t,e,r){var n=t("should-type"),a=t("./config");r.isWrapperType=function(t){return t instanceof Number||t instanceof String||t instanceof Boolean},r.merge=function(t,e){if(t&&e)for(var r in e)t[r]=e[r];return t};var o=Object.prototype.hasOwnProperty;r.forEach=function s(t,e,n){if(r.isGeneratorFunction(t))return s(t(),e,n);if(r.isGeneratorObject(t))for(var a=t.next();!a.done;){if(e.call(n,a.value,"value",t)===!1)return;a=t.next()}else for(var i in t)if(o.call(t,i)&&e.call(n,t[i],i,t)===!1)return},r.some=function(t,e,n){var a=!1;return r.forEach(t,function(r,o){return e.call(n,r,o,t)?(a=!0,!1):void 0},n),a},r.isEmptyObject=function(t){for(var e in t)if(o.call(t,e))return!1;return!0},r.isIndexable=function(t){var e=n(t);return e.type===n.OBJECT&&e.cls===n.ARRAY||e.type===n.OBJECT&&e.cls===n.BUFFER||e.type===n.OBJECT&&e.cls===n.ARGUMENTS||e.type===n.OBJECT&&e.cls===n.ARRAY_BUFFER||e.type===n.OBJECT&&e.cls===n.TYPED_ARRAY||e.type===n.OBJECT&&e.cls===n.DATA_VIEW||e.type===n.OBJECT&&e.cls===n.STRING||e.type===n.STRING},r.length=function(t){var e=n(t);switch(e.type){case n.STRING:return t.length;case n.OBJECT:switch(e.cls){case n.ARRAY_BUFFER:case n.TYPED_ARRAY:case n.DATA_VIEW:return t.byteLength;case n.ARRAY:case n.BUFFER:case n.ARGUMENTS:case n.FUNCTION:return t.length}}},r.convertPropertyName=function(t){return"symbol"==typeof t?t:String(t)},r.isGeneratorObject=function(t){return t?"function"==typeof t.next&&"function"==typeof t[Symbol.iterator]&&t[Symbol.iterator]()===t:!1},r.isGeneratorFunction=function(t){return"function"!=typeof t?!1:/^function\s*\*\s*/.test(t.toString())},r.format=function(t,e){return a.getFormatter(e).format(t)},r.functionName=t("should-format").Formatter.functionName,r.formatProp=function(t){return a.getFormatter().formatPropertyName(String(t))}},{"./config":5,"should-format":23,"should-type":25}],21:[function(t,e,r){e.exports=function(t){for(var e=arguments,r=1,n=e.length;n>r;r++)t=t.replace(/%s/,e[r]);return t}},{}],22:[function(t,e,r){function n(t,e,r,n,a){var o={result:t};return t||(o.path=e,o.reason=r,o.a=n,o.b=a),o}function a(t){return t.type+(t.cls?"("+t.cls+(t.sub?" "+t.sub:"")+")":"")}function o(t,e,r,s,p,l){function d(r,a){return n(r,l,a,t,e)}function m(n){return o(t[n],e[n],r,s,p,l.concat([n]))}var b=h;if(t===e)return d(0!==t||1/t==1/e,f.PLUS_0_AND_MINUS_0);var y,g,j=i(t),v=i(e),E=j.type!==v.type||j.cls!==v.cls;if(E||r.checkSubType&&j.sub!==v.sub||!r.checkSubType)return d(!1,u(f.DIFFERENT_TYPES,a(j),a(v)));switch(j.type){case"number":return t!==t?d(e!==e,f.NAN_NUMBER):0===t?d(1/t===1/e,f.PLUS_0_AND_MINUS_0):d(t===e,f.EQUALITY);case"boolean":case"string":return d(t===e,f.EQUALITY);case"function":var O=t.toString(),A=e.toString();if(b=o(O,A,r,s,p,l),!b.result)return b.reason=f.FUNCTION_SOURCES,b;break;case"object":switch(j.cls){case"regexp":for(g=["source","global","multiline","lastIndex","ignoreCase"];g.length;)if(b=m(g.shift()),!b.result)return b;break;case"date":if(+t!==+e)return d(!1,f.EQUALITY);break;case"number":case"boolean":case"string":if(b=o(t.valueOf(),e.valueOf(),r,s,p,l),!b.result)return b.reason=f.WRAPPED_VALUE,b;break;case"buffer":if(b=m("length"),!b.result)return b;for(y=t.length;y--;)if(b=m(y),!b.result)return b;return h;case"error":for(g=["name","message"];g.length;)if(b=m(g.shift()),!b.result)return b;break;case"array":case"arguments":case"typed-array":if(b=m("length"),!b.result)return b;break;case"array-buffer":if(b=m("byteLength"),!b.result)return b;break;case"map":case"set":if(b=m("size"),!b.result)return b;s.push(t),p.push(e);for(var x=t.entries(),S=x.next();!S.done;){var P=S.value[0];if("object"!=i(P).type){if(!e.has(P)){b=d(!1,f.SET_MAP_MISSING_KEY),b.a=P,b.b=P;break}if("map"==j.cls){var T=e.get(P);if(b=o(S.value[1],T,r,s,p,l),!b.result){b.a=S.value,b.b=T,b.reason=f.MAP_VALUE_EQUALITY;break}}}else for(var _=e.entries(),N=_.next();!N.done;){if(b=o(S.value[0],N.value[0],r,s,p,l),b.result){"map"==j.cls&&(b=o(S.value[1],N.value[1],r,s,p,l),b.result||(b.a=S.value,b.b=N.value,b.reason=f.MAP_VALUE_EQUALITY));break}b.reason=f.SET_MAP_MISSING_KEY,b.a=P,b.b=P,N=_.next()}if(!b.result)break;S=x.next()}if(s.pop(),p.pop(),!b.result)return b.reason=f.SET_MAP_MISSING_ENTRY,b}}for(y=s.length;y--;)if(s[y]==t)return d(p[y]==e,f.CIRCULAR_VALUES);s.push(t),p.push(e);var P;for(P in e)if(c.call(e,P)){if(b=d(c.call(t,P),u(f.MISSING_KEY,"A",P)),!b.result)break;if(b.result&&(b=m(P),!b.result))break}if(b.result)for(P in t)if(c.call(t,P)&&(b=d(c.call(e,P),u(f.MISSING_KEY,"B",P)),!b.result))return b;if(s.pop(),p.pop(),!b.result)return b;var w=!1,R=!1;return r.checkProtoEql&&(Object.getPrototypeOf?(w=Object.getPrototypeOf(t)===Object.getPrototypeOf(e),R=!0):t.__proto__&&e.__proto__&&(w=t.__proto__===e.__proto__,R=!0),R&&!w&&(b=d(w,f.EQUALITY_PROTOTYPE),b.showReason=!0,!b.result))?b:h}function s(t,e,r){r=r||{},"boolean"!=typeof r.checkProtoEql&&(r.checkProtoEql=p.checkProtoEql),"boolean"!=typeof r.checkSubType&&(r.checkSubType=p.checkSubType);var n=o(t,e,r,[],[],[]);return n}var i=t("should-type"),u=t("./format"),c=Object.prototype.hasOwnProperty,h=n(!0),f={PLUS_0_AND_MINUS_0:"+0 is not equal to -0",DIFFERENT_TYPES:"A has type %s and B has type %s",NAN_NUMBER:"NaN is not equal to any number",EQUALITY:"A is not equal to B",EQUALITY_PROTOTYPE:"A and B have different prototypes",WRAPPED_VALUE:"A wrapped value is not equal to B wrapped value",FUNCTION_SOURCES:"function A is not equal to B by source code value (via .toString call)",MISSING_KEY:"%s has no key %s",CIRCULAR_VALUES:"A has circular reference that was visited not in the same time as B",SET_MAP_MISSING_KEY:"Set/Map missing key",MAP_VALUE_EQUALITY:"Values of the same key in A and B is not equal"},p={checkProtoEql:!0,checkSubType:!0};e.exports=s,s.r=f},{"./format":21,"should-type":25}],23:[function(t,e,r){function n(t){return function(e){var r=t(e);return r.sort(),r}}function a(t){t=t||{},this.seen=[],this.keys=n(t.keys===!1?Object.getOwnPropertyNames:Object.keys),this.maxLineLength="number"==typeof t.maxLineLength?t.maxLineLength:60,this.propSep=t.propSep||",",this.isUTCdate=!!t.isUTCdate}function o(t,e){var r=e?"UTC":"",n=t["get"+r+"FullYear"]()+"-"+u.pad0(t["get"+r+"Month"]()+1,2)+"-"+u.pad0(t["get"+r+"Date"](),2),a=u.pad0(t["get"+r+"Hours"](),2)+":"+u.pad0(t["get"+r+"Minutes"](),2)+":"+u.pad0(t["get"+r+"Seconds"](),2)+"."+u.pad0(t["get"+r+"Milliseconds"](),3),o=t.getTimezoneOffset(),s=Math.abs(o),i=Math.floor(s/60),c=s-60*i,h=(0>o?"+":"-")+u.pad0(i,2)+u.pad0(c,2);return n+" "+a+(e?"":" "+h)}function s(t,e){return new a(e).format(t)}var i=t("should-type"),u=t("./util");a.prototype={constructor:a,format:function(t){var e=i(t),r=e.type,n=e.type;e.cls&&(r+="_"+e.cls,n+="_"+e.cls),e.sub&&(n+="_"+e.sub);var a=this["_format_"+n]||this["_format_"+r]||this["_format_"+e.type]||this.defaultFormat;return a.call(this,t).trim()},_formatObject:function(t,e){e=e||{};var r=e.keys||this.keys(t),n=0,o=e.formatPropertyValue||this.formatPropertyValue,s=e.formatPropertyName||this.formatPropertyName,i=e.keyValueSep||": ",c=e.keyFilter||function(){return!0};this.seen.push(t);var h=[];r.forEach(function(e){if(c(e)){var r=s.call(this,e),a=(r?r+i:"")+o.call(this,t,e);n+=a.length,h.push(a)}},this),this.seen.pop(),(e.additionalProperties||[]).forEach(function(t){var e=t[0]+i+this.format(t[1]);n+=e.length,h.push(e)},this);var f=e.prefix||a.constructorName(t)||"";f.length>0&&(f+=" ");var p,l;Array.isArray(e.brackets)?(p=e.brackets&&e.brackets[0],l=e.brackets&&e.brackets[1]):(p="{",l="}");var d=e.value||"";return 0===h.length?d||f+p+l:n<=this.maxLineLength?f+p+" "+(d?d+" ":"")+h.join(this.propSep+" ")+" "+l:f+p+"\n"+(d?"  "+d+"\n":"")+h.map(u.addSpaces).join(this.propSep+"\n")+"\n"+l},formatObject:function(t,e,r){r=r||this.keys(t);var n=0;return this.seen.push(t),r=r.map(function(e){var r=this.formatProperty(t,e);return n+=r.length,r},this),this.seen.pop(),0===r.length?"{}":n<=this.maxLineLength?"{ "+(e?e+" ":"")+r.join(this.propSep+" ")+" }":"{\n"+(e?"  "+e+"\n":"")+r.map(u.addSpaces).join(this.propSep+"\n")+"\n}"},formatPropertyName:function(t){return t.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/)?t:this.format(t)},formatProperty:function(t,e){var r=a.getPropertyDescriptor(t,e),n=this.formatPropertyName(e),o=r.get&&r.set?"[Getter/Setter]":r.get?"[Getter]":r.set?"[Setter]":this.seen.indexOf(r.value)>=0?"[Circular]":this.format(r.value);return n+": "+o},formatPropertyValue:function(t,e){var r=a.getPropertyDescriptor(t,e),n=r.get&&r.set?"[Getter/Setter]":r.get?"[Getter]":r.set?"[Setter]":this.seen.indexOf(r.value)>=0?"[Circular]":this.format(r.value);return n}},a.add=function(t,e,r,n){var o=Array.prototype.slice.call(arguments);n=o.pop(),a.prototype["_format_"+o.join("_")]=n},a.formatObjectWithPrefix=function(t){return function(e){var r=t.call(this,e),n=this.keys(e);return 0==n.length?r:this.formatObject(e,r,n)}};var c=/^\s*function\s*(\S*)\s*\(/;a.functionName=function(t){if(t.name)return t.name;var e=t.toString().match(c)[1];return e},a.constructorName=function(t){for(;t;){var e=Object.getOwnPropertyDescriptor(t,"constructor");if(void 0!==e&&"function"==typeof e.value){var r=a.functionName(e.value);if(""!==r)return r}t=Object.getPrototypeOf(t)}},a.getPropertyDescriptor=function(t,e){var r;try{
r=Object.getOwnPropertyDescriptor(t,e)||{value:t[e]}}catch(n){r={value:n}}return r},a.generateFunctionForIndexedArray=function(t,e,r){return function(n){for(var a=this.byteArrayMaxLength||50,o=n[t],s=[],i=0,c=0;a>c&&o>c;c++){var h=n[c]||0,f=u.pad0(h.toString(16),r);i+=f.length,s.push(f)}var p=n.constructor.name||e||"";return p&&(p+=" "),0===s.length?p+"[]":i<=this.maxLineLength?p+"[ "+s.join(this.propSep+" ")+" ]":p+"[\n"+s.map(u.addSpaces).join(this.propSep+"\n")+"\n]"}},a.add("undefined",function(){return"undefined"}),a.add("null",function(){return"null"}),a.add("boolean",function(t){return t?"true":"false"}),a.add("symbol",function(t){return t.toString()}),["number","boolean"].forEach(function(t){a.add("object",t,function(t){return this._formatObject(t,{additionalProperties:[["[[PrimitiveValue]]",t.valueOf()]]})})}),a.add("object","string",function(t){var e=t.valueOf();return this._formatObject(t,{keyFilter:function(t){return!(t.match(/\d+/)&&parseInt(t,10)<e.length)},additionalProperties:[["[[PrimitiveValue]]",e]]})}),a.add("object","regexp",function(t){return this._formatObject(t,{value:String(t)})}),a.add("number",function(t){return 0===t&&0>1/t?"-0":String(t)}),a.add("string",function(t){return"'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'"}),a.add("object",function(t){return this._formatObject(t)}),a.add("object","arguments",function(t){return this._formatObject(t,{prefix:"Arguments",formatPropertyName:function(t){return t.match(/\d+/)?void 0:this.formatPropertyName(t)},brackets:["[","]"]})}),a.add("object","array",function(t){return this._formatObject(t,{formatPropertyName:function(t){return t.match(/\d+/)?void 0:this.formatPropertyName(t)},brackets:["[","]"]})}),a.add("object","date",function(t){return this._formatObject(t,{value:o(t,this.isUTCdate)})}),a.add("function",function(t){return this._formatObject(t,{additionalProperties:[["name",a.functionName(t)]]})}),a.add("object","error",function(t){return this._formatObject(t,{prefix:t.name,additionalProperties:[["message",t.message]]})}),a.add("object","buffer",a.generateFunctionForIndexedArray("length","Buffer",2)),a.add("object","array-buffer",a.generateFunctionForIndexedArray("byteLength","ArrayBuffer",2)),a.add("object","typed-array","int8",a.generateFunctionForIndexedArray("length","Int8Array",2)),a.add("object","typed-array","uint8",a.generateFunctionForIndexedArray("length","Uint8Array",2)),a.add("object","typed-array","uint8clamped",a.generateFunctionForIndexedArray("length","Uint8ClampedArray",2)),a.add("object","typed-array","int16",a.generateFunctionForIndexedArray("length","Int16Array",4)),a.add("object","typed-array","uint16",a.generateFunctionForIndexedArray("length","Uint16Array",4)),a.add("object","typed-array","int32",a.generateFunctionForIndexedArray("length","Int32Array",8)),a.add("object","typed-array","uint32",a.generateFunctionForIndexedArray("length","Uint32Array",8)),a.add("object","promise",function(){return"[Promise]"}),a.add("object","xhr",function(){return"[XMLHttpRequest]"}),a.add("object","html-element",function(t){return t.outerHTML}),a.add("object","html-element","#text",function(t){return t.nodeValue}),a.add("object","html-element","#document",function(t){return t.documentElement.outerHTML}),a.add("object","host",function(){return"[Host]"}),a.add("object","set",function(t){var e=t.values(),r=0;this.seen.push(t);for(var n=[],a=e.next();!a.done;){var o=a.value,s=this.format(o);r+=s.length,n.push(s),a=e.next()}return this.seen.pop(),0===n.length?"Set {}":r<=this.maxLineLength?"Set { "+n.join(this.propSep+" ")+" }":"Set {\n"+n.map(u.addSpaces).join(this.propSep+"\n")+"\n}"}),a.add("object","map",function(t){var e=t.entries(),r=0;this.seen.push(t);for(var n=[],a=e.next();!a.done;){var o,s=a.value,i=this.format(s[0]),c=this.format(s[1]);o=i.length+c.length+4<=this.maxLineLength?i+" => "+c:i+" =>\n"+c,r+=i.length+c.length+4,n.push(o),a=e.next()}return this.seen.pop(),0===n.length?"Map {}":r<=this.maxLineLength?"Map { "+n.join(this.propSep+" ")+" }":"Map {\n"+n.map(u.addSpaces).join(this.propSep+"\n")+"\n}"}),a.prototype.defaultFormat=a.prototype._format_object,s.Formatter=a,e.exports=s},{"./util":24,"should-type":25}],24:[function(t,e,r){function n(t){return t.split("\n").map(function(t){return"  "+t}).join("\n")}function a(t,e,r){t=String(t);var n=!1;if(0>e&&(n=!0,e=-e),t.length<e){var a=new Array(e-t.length+1).join(r);return n?t+a:a+t}return t}e.exports={addSpaces:n,pad:a,pad0:function(t,e){return a(t,e,"0")}}},{}],25:[function(t,e,r){function n(t,e,r){this.type=t,this.cls=e,this.sub=r}function a(){this.checks=[]}function o(t){return u.getType(t)}var s=Object.prototype.toString,i=t("./types");a.prototype={add:function(t){return this.checks.push(t),this},addTypeOf:function(t,e){return this.add(function(r,a){return a===t?new n(e):void 0})},addClass:function(t,e,r){return this.add(function(a,o,s){return s===t?new n(i.OBJECT,e,r):void 0})},getType:function(t){for(var e=typeof t,r=s.call(t),n=0,a=this.checks.length;a>n;n++){var o=this.checks[n].call(this,t,e,r);if("undefined"!=typeof o)return o}}};var u=new a;u.addTypeOf(i.NUMBER,i.NUMBER).addTypeOf(i.UNDEFINED,i.UNDEFINED).addTypeOf(i.STRING,i.STRING).addTypeOf(i.BOOLEAN,i.BOOLEAN).addTypeOf(i.FUNCTION,i.FUNCTION).addTypeOf(i.SYMBOL,i.SYMBOL).add(function(t,e){return null===t?new n(i.NULL):void 0}).addClass("[object String]",i.STRING).addClass("[object Boolean]",i.BOOLEAN).addClass("[object Number]",i.NUMBER).addClass("[object Array]",i.ARRAY).addClass("[object RegExp]",i.REGEXP).addClass("[object Error]",i.ERROR).addClass("[object Date]",i.DATE).addClass("[object Arguments]",i.ARGUMENTS).addClass("[object Math]").addClass("[object JSON]").addClass("[object ArrayBuffer]",i.ARRAY_BUFFER).addClass("[object Int8Array]",i.TYPED_ARRAY,"int8").addClass("[object Uint8Array]",i.TYPED_ARRAY,"uint8").addClass("[object Uint8ClampedArray]",i.TYPED_ARRAY,"uint8clamped").addClass("[object Int16Array]",i.TYPED_ARRAY,"int16").addClass("[object Uint16Array]",i.TYPED_ARRAY,"uint16").addClass("[object Int32Array]",i.TYPED_ARRAY,"int32").addClass("[object Uint32Array]",i.TYPED_ARRAY,"uint32").addClass("[object Float32Array]",i.TYPED_ARRAY,"float32").addClass("[object Float64Array]",i.TYPED_ARRAY,"float64").addClass("[object DataView]",i.DATA_VIEW).addClass("[object Map]",i.MAP).addClass("[object WeakMap]",i.WEAK_MAP).addClass("[object Set]",i.SET).addClass("[object WeakSet]",i.WEAK_SET).addClass("[object Promise]",i.PROMISE).addClass("[object Blob]",i.BLOB).addClass("[object File]",i.FILE).addClass("[object FileList]",i.FILE_LIST).addClass("[object XMLHttpRequest]",i.XHR).add(function(t){return typeof Promise===i.FUNCTION&&t instanceof Promise||typeof t.then===i.FUNCTION?new n(i.OBJECT,i.PROMISE):void 0}).add(function(t){return"undefined"!=typeof Buffer&&t instanceof Buffer?new n(i.OBJECT,i.BUFFER):void 0}).add(function(t){return"undefined"!=typeof Node&&t instanceof Node?new n(i.OBJECT,i.HTML_ELEMENT,t.nodeName):void 0}).add(function(t){return t.Boolean===Boolean&&t.Number===Number&&t.String===String&&t.Date===Date?new n(i.OBJECT,i.HOST):void 0}).add(function(){return new n(i.OBJECT)}),o.checker=u,o.TypeChecker=a,o.Type=n,Object.keys(i).forEach(function(t){o[t]=i[t]}),e.exports=o},{"./types":26}],26:[function(t,e,r){var n={NUMBER:"number",UNDEFINED:"undefined",STRING:"string",BOOLEAN:"boolean",OBJECT:"object",FUNCTION:"function",NULL:"null",ARRAY:"array",REGEXP:"regexp",DATE:"date",ERROR:"error",ARGUMENTS:"arguments",SYMBOL:"symbol",ARRAY_BUFFER:"array-buffer",TYPED_ARRAY:"typed-array",DATA_VIEW:"data-view",MAP:"map",SET:"set",WEAK_SET:"weak-set",WEAK_MAP:"weak-map",PROMISE:"promise",BUFFER:"buffer",HTML_ELEMENT:"html-element",HTML_ELEMENT_TEXT:"html-element-text",DOCUMENT:"document",WINDOW:"window",FILE:"file",FILE_LIST:"file-list",BLOB:"blob",HOST:"host",XHR:"xhr"};e.exports=n},{}]},{},[1])(1)});
{
  "name": "deephas",
  "version": "1.0.5",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "should": {
      "version": "8.0.1",
      "resolved": "https://registry.npmjs.org/should/-/should-8.0.1.tgz",
      "integrity": "sha1-OjpxF9RfKaNnvBKch4owPsHvZAo=",
      "dev": true,
      "requires": {
        "should-equal": "0.5.0",
        "should-format": "0.3.1",
        "should-type": "0.2.0"
      },
      "dependencies": {
        "should-equal": {
          "version": "0.5.0",
          "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-0.5.0.tgz",
          "integrity": "sha1-x5fxNfMGf+tp6+zbMGscP+IbPm8=",
          "dev": true,
          "requires": {
            "should-type": "0.2.0"
          }
        },
        "should-format": {
          "version": "0.3.1",
          "resolved": "https://registry.npmjs.org/should-format/-/should-format-0.3.1.tgz",
          "integrity": "sha1-LLt4JGFnCs5CkrKx7EaNuM+Z4zA=",
          "dev": true,
          "requires": {
            "should-type": "0.2.0"
          }
        },
        "should-type": {
          "version": "0.2.0",
          "resolved": "https://registry.npmjs.org/should-type/-/should-type-0.2.0.tgz",
          "integrity": "sha1-ZwfvlVKdmJ3MCY/gdTqx+RNrt/Y=",
          "dev": true
        }
      }
    }
  }
}
{
  "name": "deephas",
  "version": "1.0.6",
  "description": "get, set or test for a value in a javascript object",
  "main": "deepHas.js",
  "scripts": {
    "test": "./runTests.sh"
  },
  "repository": {
    "type": "git",
    "url": "git@github.com:sharpred/deepHas.git"
  },
  "keywords": [
    "nested",
    "object",
    "key"
  ],
  "author": "Paul Ryan <paul.ryan@stepupsoftware.co.uk>",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/sharpred/deepHas/issues"
  },
  "homepage": "https://github.com/sharpred/deepHas",
  "devDependencies": {
    "should": ">=8.0.1"
  }
}
var dh = require("./deepHas");
var obj = {};
console.log(obj.isAdmin);
dh.set(obj,'__proto__.isAdmin','true');
console.log(obj.isAdmin);
#!/bin/bash
node tests/testHas.js
node tests/testGet.js
node tests/testExports.js
node tests/testSet.js
node tests/testVulnerability.js
var dh = require("../deepHas"),
    should = require("should");

/*
 * Test of exports
 * public functions should be visible (hasProperty and getProperty)
 * private function should be hidden(deepProperty)
 */
dh.should.be.an.instanceOf(Object).and.have.property('has');
dh.should.have.property('get');
dh.should.have.property('set');
dh.should.be.an.instanceOf(Object).and.not.have.property('deep');
dh.has.should.be.an.instanceOf(Function);
dh.get.should.be.an.instanceOf(Function);
dh.set.should.be.an.instanceOf(Function);
var dh = require("../deepHas"),
    should = require("should");

/*
 * Test get
 */
var test1,
    test2,
    test3,
    test4,
    test5,
    test6,
    test7,
    test8,
    test9,
    test10,
    test11,
    test12,
    getObj;

getObj = {
    "top" : {
        "middle" : {
            "bottom" : {
            }
        }
    },
    "truthy" : true,
    "falsey" : false
};
//data
test1 = dh.get(getObj, "top");
test2 = dh.get(getObj, "top.middle");
test3 = dh.get(getObj, "top.middle.bottom");
test4 = dh.get(getObj, "bottom");
test5 = dh.get(getObj, "bottom.middle");
test6 = dh.get(getObj, "bottom.middle.top");
test7 = dh.get();
test8 = dh.get(getObj);
test9 = dh.get("top");
test10 = dh.get({}, "top");
test11 = dh.get(getObj, "truthy");
test12 = dh.get(getObj, "falsey");

//assertions
should(test1).have.property("middle", {
    "bottom" : {}
});
should(test2).have.property("bottom", {});
test3.should.be.an.instanceOf(Object);
should.not.exist(test4);
should.not.exist(test5);
should.not.exist(test6);
should.not.exist(test7);
should.not.exist(test8);
should.not.exist(test9);
should.not.exist(test10);
test11.should.be.exactly(true);
test12.should.be.exactly(false);
var dh = require("../deepHas"),
    should = require("should");

/*
 * Test has
 */
var test1,
    test2,
    test3,
    test4,
    test5,
    test6,
    test7,
    test8,
    test9,
    test10,
    test11,
    test12,
    hasObj;

hasObj = {
    "top" : {
        "middle" : {
            "bottom" : {
            }
        }
    },
    "truthy" : true,
    "falsey" : false
};
//data
test1 = dh.has(hasObj, "top");
test2 = dh.has(hasObj, "top.middle");
test3 = dh.has(hasObj, "top.middle.bottom");
test4 = dh.has(hasObj, "bottom");
test5 = dh.has(hasObj, "bottom.middle");
test6 = dh.has(hasObj, "bottom.middle.top");
test7 = dh.has();
test8 = dh.has(hasObj);
test9 = dh.has("top");
test10 = dh.has({}, "top");
test11 = dh.has(hasObj, "truthy");
test12 = dh.has(hasObj, "falsey");
test13 = dh.has(hasObj, "middle");

//assertions
test1.should.be.exactly(true);
test2.should.be.exactly(true);
test3.should.be.exactly(true);
test4.should.be.exactly(false);
test5.should.be.exactly(false);
test6.should.be.exactly(false);
test7.should.be.exactly(false);
test8.should.be.exactly(false);
test9.should.be.exactly(false);
test10.should.be.exactly(false);
test11.should.be.exactly(true);
test12.should.be.exactly(true);
test13.should.be.exactly(false);
var dh = require("../deepHas"),
    should = require("should"),
    obj,
    obj2,
    test2;

obj = {
    "top" : {
        "middle" : {
            "bottom" : {
                "val" : "1"
            }
        }
    },
    "truthy" : true,
    "falsey" : false
};

dh.set(obj, "top.middle.bottom", {
    "val" : "2"
});

//assertions
JSON.stringify(obj).should.equal(JSON.stringify({
    "top" : {
        "middle" : {
            "bottom" : {
                "val" : "2"
            }
        }
    },
    "truthy" : true,
    "falsey" : false
}));

dh.set(obj, "top.middle.left", {
    "val" : "1"
});

JSON.stringify(obj).should.equal(JSON.stringify({
    "top" : {
        "middle" : {
            "bottom" : {
                "val" : "2"
            },
            "left" : {
                "val" : "1"
            }
        }
    },
    "truthy" : true,
    "falsey" : false
}));

dh.set(obj, "top.middle.right", {
    "val" : "1"
});

JSON.stringify(obj).should.equal(JSON.stringify({
    "top" : {
        "middle" : {
            "bottom" : {
                "val" : "2"
            },
            "left" : {
                "val" : "1"
            },
            "right" : {
                "val" : "1"
            }
        }
    },
    "truthy" : true,
    "falsey" : false
}));

dh.set(obj, "top.bottom.right", {
    "val" : "1"
});

JSON.stringify(obj).should.equal(JSON.stringify({
    "top" : {
        "middle" : {
            "bottom" : {
                "val" : "2"
            },
            "left" : {
                "val" : "1"
            },
            "right" : {
                "val" : "1"
            }
        },
        "bottom" : {
            "right" : {
                "val" : "1"
            }
        }
    },
    "truthy" : true,
    "falsey" : false
}));

dh.set(obj, "bottom.middle.top", {
    "val" : "1"
});

JSON.stringify(obj).should.equal(JSON.stringify({
    "top" : {
        "middle" : {
            "bottom" : {
                "val" : "2"
            },
            "left" : {
                "val" : "1"
            },
            "right" : {
                "val" : "1"
            }
        },
        "bottom" : {
            "right" : {
                "val" : "1"
            }
        }
    },
    "truthy" : true,
    "falsey" : false,
    "bottom" : {
        "middle" : {
            "top" : {
                "val" : "1"
            }
        }
    }
}));
var test2 = {
    "bottom" : {
        "middle" : {
            "top" : ["paul", 1, {
                "test" : "test"
            }]
        }
    }
};

obj2 = {

};
dh.set(obj2, "bottom.middle.top", ["paul", 1, {
    "test" : "test"
}]);

JSON.stringify(obj2).should.equal(JSON.stringify(test2));
var dh = require("../deepHas"),
    should = require("should"),
    obj;

obj = {};

dh.set(obj,'__proto__.isAdmin',true);

should.not.exist(obj.isAdmin);
obj.hasOwnProperty('isAdmin').should.equal(false);