diff --git a/.travis.yml b/.travis.yml
index d5e87d1a6..d1c28050c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,13 @@
language: node_js
-script: 'if [ -n "$ARTIFACT" ]; then make test; else make test-sauce; fi'
node_js:
- '0.12'
+install:
+ - mkdir travis-phantomjs
+ - wget https://s3.amazonaws.com/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 -O $PWD/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2
+ - tar -xvf $PWD/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 -C $PWD/travis-phantomjs
+ - export PATH=$PWD/travis-phantomjs:$PATH
+script:
+ - 'if [ -n "$ARTIFACT" ]; then make test; else make test-sauce; fi'
before_script:
- 'if [ -n "$ARTIFACT" ]; then gem install travis-artifacts; fi'
after_success:
@@ -19,7 +25,10 @@ env:
- BROWSER: chrome
- BROWSER: firefox
- BROWSER: safari
- - BROWSER: ie9..11
- - BROWSER: ipad6..8
- - BROWSER: iphone6..8
+ - BROWSER: ie:11
+ - BROWSER: ie:10
+ - BROWSER: ie:9
+ - BROWSER: iphone:8
+ - BROWSER: iphone:7
+ - BROWSER: iphone:6
- ARTIFACT: 1
diff --git a/Makefile b/Makefile
index faab1a7f3..432a1ccb0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,28 +1,42 @@
BIN = node_modules/.bin
DUO = $(BIN)/duo
-MINIFY = $(BIN)/uglifyjs
-WATCH = $(BIN)/wr
-DELEGATE = test test-browser test-sauce test-coverage
+T = $(BIN)/duo-test -m test/api.js -R spec -P 8378
-BUILD = ./build
-WATCH_FILES = lib index.js component.json Makefile
+SRC = index.js $(shell find lib -type f -name '*.js')
+TESTS = $(wildcard test/*.test.js)
-build: node_modules
- @mkdir -p $(BUILD)
- @$(DUO) --quiet --stdout --global recurly index.js > $(BUILD)/recurly.js
- @$(MINIFY) $(BUILD)/recurly.js --output $(BUILD)/recurly.min.js
+test: test-phantomjs
+
+test-phantomjs: build/recurly.min.js build/test.js
+ @$(T) phantomjs
+
+test-browser: build/recurly.min.js build/test.js
+ @$(T) browser
+
+test-sauce: BROWSER ?= ie:9
+test-sauce: build/recurly.min.js build/test.js
+ @$(T) saucelabs -b $(BROWSER)
+
+build: build/recurly.min.js
+
+build/recurly.js: index.js $(SRC) node_modules component.json
+ @mkdir -p $(@D)
+ @$(DUO) --quiet --stdout --global recurly < $< > $@
+
+build/recurly.min.js: build/recurly.js
+ @$(BIN)/uglifyjs $< --output $@
+
+build/test.js: TESTFILE = $(foreach test, $(TESTS), 'require("./$(test)");')
+build/test.js: $(TESTS)
+ @echo $(TESTFILE) | $(DUO) --quiet --development --type js --stdout > $@
watch: node_modules
- @$(WATCH) make $(WATCH_FILES)
+ @$(BIN)/wr $(MAKE) component.json $(SRC)
node_modules: package.json
@npm install --silent
-$(DELEGATE): build
- @cd test && make $@
-
clean:
- @rm -rf node_modules components/duo.json $(BUILD)
- @cd test && make $@
+ @rm -rf node_modules components/duo.json build
-.PHONY: clean build test test-browser test-sauce test-coverage
+.PHONY: test watch clean
diff --git a/README.md b/README.md
index e228ea005..2feda219a 100644
--- a/README.md
+++ b/README.md
@@ -43,14 +43,14 @@ implementations.
## Build
```bash
-$ make
+$ make build
```
If you are having issues with the build, try `make clean`
## Test
```bash
-$ make test
+$ make
```
## Beta Features
diff --git a/component.json b/component.json
index 58ab42742..2f3380899 100644
--- a/component.json
+++ b/component.json
@@ -25,7 +25,7 @@
"webmodules/jsonp": "0.0.4",
"yields/cors-xhr": "1.0.1",
"yields/merge": "1.0.0",
- "visionmedia/debug": "2.1.3",
+ "visionmedia/debug": "2.2.0",
"then/promise": "6.0.0",
"kewah/mixin": "0.1.0",
"pluma/par": "0.3.0",
diff --git a/components/chrissrogers-noop@master/.gitignore b/components/chrissrogers-noop@master/.gitignore
new file mode 100644
index 000000000..48a2e246c
--- /dev/null
+++ b/components/chrissrogers-noop@master/.gitignore
@@ -0,0 +1,2 @@
+components
+build
diff --git a/components/chrissrogers-noop@master/History.md b/components/chrissrogers-noop@master/History.md
new file mode 100644
index 000000000..e69de29bb
diff --git a/components/chrissrogers-noop@master/Makefile b/components/chrissrogers-noop@master/Makefile
new file mode 100644
index 000000000..c8dd98352
--- /dev/null
+++ b/components/chrissrogers-noop@master/Makefile
@@ -0,0 +1,11 @@
+
+build: components index.js
+ @component build --dev
+
+components: component.json
+ @component install --dev
+
+clean:
+ rm -rf build components
+
+.PHONY: clean
diff --git a/components/chrissrogers-noop@master/README.md b/components/chrissrogers-noop@master/README.md
new file mode 100644
index 000000000..7d80c4975
--- /dev/null
+++ b/components/chrissrogers-noop@master/README.md
@@ -0,0 +1,12 @@
+noop
+====
+
+ever just want to do nothing?
+
+```js
+var noop = require('noop');
+
+noop('into the void');
+
+myProcessor(data, noop);
+```
diff --git a/components/chrissrogers-noop@master/component.json b/components/chrissrogers-noop@master/component.json
new file mode 100644
index 000000000..013b16f05
--- /dev/null
+++ b/components/chrissrogers-noop@master/component.json
@@ -0,0 +1,14 @@
+{
+ "name": "noop",
+ "repo": "chrissrogers/noop",
+ "description": "noop function",
+ "version": "0.0.1",
+ "keywords": [
+ "function"
+ ],
+ "license": "MIT",
+ "main": "index.js",
+ "scripts": [
+ "index.js"
+ ]
+}
diff --git a/components/chrissrogers-noop@master/index.js b/components/chrissrogers-noop@master/index.js
new file mode 100644
index 000000000..ea41b01de
--- /dev/null
+++ b/components/chrissrogers-noop@master/index.js
@@ -0,0 +1 @@
+module.exports = function () {};
diff --git a/components/component-assert@0.5.0/.gitignore b/components/component-assert@0.5.0/.gitignore
new file mode 100644
index 000000000..aa10b93e4
--- /dev/null
+++ b/components/component-assert@0.5.0/.gitignore
@@ -0,0 +1,3 @@
+build
+components
+node_modules
diff --git a/components/component-assert@0.5.0/History.md b/components/component-assert@0.5.0/History.md
new file mode 100644
index 000000000..4f445e47c
--- /dev/null
+++ b/components/component-assert@0.5.0/History.md
@@ -0,0 +1,37 @@
+
+0.5.0 / 2014-10-07
+==================
+
+ * index: Fix .throws() and .doesNotThrow()
+ * add mocha diff
+
+0.4.0 / 2014-06-30
+==================
+
+ * fix default assertion messages
+ * add testing server
+
+0.3.1 / 2014-06-03
+==================
+
+ * fix custom assertion messages being ignored
+
+0.3.0 / 2013-12-10
+==================
+
+ * add node assert methods
+
+0.2.0 / 2013-08-15
+==================
+
+ * update to work with latest component/stack.
+
+0.1.1 / 2012-10-09
+==================
+
+ * fix paren balancing with greedy capture
+
+0.1.0 / 2012-10-09
+==================
+
+ * add callsite support for auto-generated messages
diff --git a/components/component-assert@0.5.0/Makefile b/components/component-assert@0.5.0/Makefile
new file mode 100644
index 000000000..b737af6b2
--- /dev/null
+++ b/components/component-assert@0.5.0/Makefile
@@ -0,0 +1,20 @@
+
+build: components index.js
+ @component build --dev
+
+components: component.json
+ @component install --dev
+
+clean:
+ @rm -fr build components
+
+node_modules: package.json
+ @npm install
+
+server: node_modules build
+ @node test/server.js
+
+test: build
+ @open http://localhost:7575
+
+.PHONY: clean server test
diff --git a/components/component-assert@0.5.0/Readme.md b/components/component-assert@0.5.0/Readme.md
new file mode 100644
index 000000000..a72c3d12a
--- /dev/null
+++ b/components/component-assert@0.5.0/Readme.md
@@ -0,0 +1,25 @@
+
+# assert
+
+ C-style assertion lib.
+
+## Example
+
+ With custom assertion message:
+
+```js
+var assert = require('assert');
+assert(expr, 'oh no it broke');
+```
+
+ Or auto-generated assertion message in
+ browsers that support `Error.captureStackTrace()`:
+
+```js
+var assert = require('assert');
+assert(user.name == 'Tobi');
+```
+
+## License
+
+ MIT
\ No newline at end of file
diff --git a/components/component-assert@0.5.0/component.json b/components/component-assert@0.5.0/component.json
new file mode 100644
index 000000000..3132f1f82
--- /dev/null
+++ b/components/component-assert@0.5.0/component.json
@@ -0,0 +1,15 @@
+{
+ "name": "assert",
+ "repo": "component/assert",
+ "description": "Assertion lib",
+ "version": "0.5.0",
+ "keywords": ["assert", "test"],
+ "dependencies": {
+ "component/stack": "*",
+ "jkroso/equals": "*",
+ "yields/fmt": "0.0.2"
+ },
+ "scripts": [
+ "index.js"
+ ]
+}
diff --git a/components/component-assert@0.5.0/example.html b/components/component-assert@0.5.0/example.html
new file mode 100644
index 000000000..c7b5e5ba4
--- /dev/null
+++ b/components/component-assert@0.5.0/example.html
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/component-assert@0.5.0/example.js b/components/component-assert@0.5.0/example.js
new file mode 100644
index 000000000..881537670
--- /dev/null
+++ b/components/component-assert@0.5.0/example.js
@@ -0,0 +1,13 @@
+
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert');
+
+function test() {
+ var user = { name: 'Tobi' };
+ assert(user.name == 'tobi');
+}
+
+test();
\ No newline at end of file
diff --git a/components/component-assert@0.5.0/index.js b/components/component-assert@0.5.0/index.js
new file mode 100644
index 000000000..bba2cc307
--- /dev/null
+++ b/components/component-assert@0.5.0/index.js
@@ -0,0 +1,203 @@
+
+/**
+ * Module dependencies.
+ */
+
+var equals = require('equals');
+var fmt = require('fmt');
+var stack = require('stack');
+
+/**
+ * Assert `expr` with optional failure `msg`.
+ *
+ * @param {Mixed} expr
+ * @param {String} [msg]
+ * @api public
+ */
+
+module.exports = exports = function (expr, msg) {
+ if (expr) return;
+ throw error(msg || message());
+};
+
+/**
+ * Assert `actual` is weak equal to `expected`.
+ *
+ * @param {Mixed} actual
+ * @param {Mixed} expected
+ * @param {String} [msg]
+ * @api public
+ */
+
+exports.equal = function (actual, expected, msg) {
+ if (actual == expected) return;
+ throw error(msg || fmt('Expected %o to equal %o.', actual, expected), actual, expected);
+};
+
+/**
+ * Assert `actual` is not weak equal to `expected`.
+ *
+ * @param {Mixed} actual
+ * @param {Mixed} expected
+ * @param {String} [msg]
+ * @api public
+ */
+
+exports.notEqual = function (actual, expected, msg) {
+ if (actual != expected) return;
+ throw error(msg || fmt('Expected %o not to equal %o.', actual, expected));
+};
+
+/**
+ * Assert `actual` is deep equal to `expected`.
+ *
+ * @param {Mixed} actual
+ * @param {Mixed} expected
+ * @param {String} [msg]
+ * @api public
+ */
+
+exports.deepEqual = function (actual, expected, msg) {
+ if (equals(actual, expected)) return;
+ throw error(msg || fmt('Expected %o to deeply equal %o.', actual, expected), actual, expected);
+};
+
+/**
+ * Assert `actual` is not deep equal to `expected`.
+ *
+ * @param {Mixed} actual
+ * @param {Mixed} expected
+ * @param {String} [msg]
+ * @api public
+ */
+
+exports.notDeepEqual = function (actual, expected, msg) {
+ if (!equals(actual, expected)) return;
+ throw error(msg || fmt('Expected %o not to deeply equal %o.', actual, expected));
+};
+
+/**
+ * Assert `actual` is strict equal to `expected`.
+ *
+ * @param {Mixed} actual
+ * @param {Mixed} expected
+ * @param {String} [msg]
+ * @api public
+ */
+
+exports.strictEqual = function (actual, expected, msg) {
+ if (actual === expected) return;
+ throw error(msg || fmt('Expected %o to strictly equal %o.', actual, expected), actual, expected);
+};
+
+/**
+ * Assert `actual` is not strict equal to `expected`.
+ *
+ * @param {Mixed} actual
+ * @param {Mixed} expected
+ * @param {String} [msg]
+ * @api public
+ */
+
+exports.notStrictEqual = function (actual, expected, msg) {
+ if (actual !== expected) return;
+ throw error(msg || fmt('Expected %o not to strictly equal %o.', actual, expected));
+};
+
+/**
+ * Assert `block` throws an `error`.
+ *
+ * @param {Function} block
+ * @param {Function} [error]
+ * @param {String} [msg]
+ * @api public
+ */
+
+exports.throws = function (block, err, msg) {
+ var threw;
+ try {
+ block();
+ } catch (e) {
+ threw = e;
+ }
+
+ if (!threw) throw error(msg || fmt('Expected %s to throw an error.', block.toString()));
+ if (err && !(threw instanceof err)) {
+ throw error(msg || fmt('Expected %s to throw an %o.', block.toString(), err));
+ }
+};
+
+/**
+ * Assert `block` doesn't throw an `error`.
+ *
+ * @param {Function} block
+ * @param {Function} [error]
+ * @param {String} [msg]
+ * @api public
+ */
+
+exports.doesNotThrow = function (block, err, msg) {
+ var threw;
+ try {
+ block();
+ } catch (e) {
+ threw = e;
+ }
+
+ if (threw) throw error(msg || fmt('Expected %s not to throw an error.', block.toString()));
+ if (err && (threw instanceof err)) {
+ throw error(msg || fmt('Expected %s not to throw an %o.', block.toString(), err));
+ }
+};
+
+/**
+ * Create a message from the call stack.
+ *
+ * @return {String}
+ * @api private
+ */
+
+function message() {
+ if (!Error.captureStackTrace) return 'assertion failed';
+ var callsite = stack()[2];
+ var fn = callsite.getFunctionName();
+ var file = callsite.getFileName();
+ var line = callsite.getLineNumber() - 1;
+ var col = callsite.getColumnNumber() - 1;
+ var src = get(file);
+ line = src.split('\n')[line].slice(col);
+ var m = line.match(/assert\((.*)\)/);
+ return m && m[1].trim();
+}
+
+/**
+ * Load contents of `script`.
+ *
+ * @param {String} script
+ * @return {String}
+ * @api private
+ */
+
+function get(script) {
+ var xhr = new XMLHttpRequest;
+ xhr.open('GET', script, false);
+ xhr.send(null);
+ return xhr.responseText;
+}
+
+/**
+ * Error with `msg`, `actual` and `expected`.
+ *
+ * @param {String} msg
+ * @param {Mixed} actual
+ * @param {Mixed} expected
+ * @return {Error}
+ */
+
+function error(msg, actual, expected){
+ var err = new Error(msg);
+ err.showDiff = 3 == arguments.length;
+ err.actual = actual;
+ err.expected = expected;
+ return err;
+}
diff --git a/components/component-assert@0.5.0/package.json b/components/component-assert@0.5.0/package.json
new file mode 100644
index 000000000..e709e43da
--- /dev/null
+++ b/components/component-assert@0.5.0/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "assert",
+ "private": true,
+ "dependencies": {
+ "express": "^4.4.5",
+ "hbs": "^2.7.0"
+ }
+}
diff --git a/components/component-assert@0.5.0/test/index.html b/components/component-assert@0.5.0/test/index.html
new file mode 100644
index 000000000..bf3d45e42
--- /dev/null
+++ b/components/component-assert@0.5.0/test/index.html
@@ -0,0 +1,14 @@
+
+
+ assert tests
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/component-assert@0.5.0/test/index.js b/components/component-assert@0.5.0/test/index.js
new file mode 100644
index 000000000..850cf8e87
--- /dev/null
+++ b/components/component-assert@0.5.0/test/index.js
@@ -0,0 +1,350 @@
+
+var assert = require('assert')
+var equals = require('equals');
+
+describe('assert', function(){
+ it('should pass', function(){
+ try {
+ assert(true);
+ } catch (e) {
+ throw new Error('fail');
+ }
+ });
+
+ it('should fail', function(){
+ try {
+ assert(false);
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ }
+ });
+
+ it('should supply a default message', function(){
+ try {
+ assert(0 + 0);
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('0 + 0' != e.message) throw new Error('fail');
+ }
+ });
+
+ it('should respect a custom message', function(){
+ try {
+ assert(false, 'message');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('message' != e.message) throw new Error('fail');
+ }
+ });
+
+ describe('.equal', function(){
+ it('should pass', function(){
+ assert.equal(true, true);
+ });
+
+ it('should fail', function(){
+ try {
+ assert.equal({}, {});
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ }
+ });
+
+ it('should supply a default message', function(){
+ try {
+ assert.equal(1, 42);
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('Expected 1 to equal 42.' != e.message) throw new Error('fail');
+ }
+ });
+
+ it('should respect a custom message', function(){
+ try {
+ assert.equal(1, 42, 'message');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('message' != e.message) throw new Error('fail');
+ }
+ });
+ });
+
+ describe('.notEqual', function(){
+ it('should pass', function(){
+ try {
+ assert.notEqual({}, {});
+ } catch (e) {
+ throw new Error('fail');
+ }
+ });
+
+ it('should fail', function(){
+ try {
+ assert.notEqual(true, true);
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ }
+ });
+
+ it('should supply a default message', function(){
+ try {
+ assert.notEqual(true, true);
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('Expected true not to equal true.' != e.message) throw new Error('fail');
+ }
+ });
+
+ it('should respect a custom message', function(){
+ try {
+ assert.notEqual(true, true, 'message');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('message' != e.message) throw new Error('fail');
+ }
+ });
+ });
+
+ describe('.deepEqual', function(){
+ it('should pass', function(){
+ try {
+ assert.deepEqual(['a', 'b'], ['a', 'b']);
+ } catch (e) {
+ throw new Error('fail');
+ }
+ });
+
+ it('should fail', function(){
+ try {
+ assert.deepEqual(['a', 'b'], [1, 2]);
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ }
+ });
+
+ it('should supply a default message', function(){
+ try {
+ assert.deepEqual(['a', 'b'], [1, 2]);
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('Expected ["a","b"] to deeply equal [1,2].' != e.message) throw new Error('fail');
+ }
+ });
+
+ it('should respect a custom message', function(){
+ try {
+ assert.deepEqual(['a', 'b'], [1, 2], 'message');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('message' != e.message) throw new Error('fail');
+ }
+ });
+ });
+
+ describe('.notDeepEqual', function(){
+ it('should pass', function(){
+ try {
+ assert.notDeepEqual(['a', 'b'], [1, 2]);
+ } catch (e) {
+ throw new Error('fail');
+ }
+ });
+
+ it('should fail', function(){
+ try {
+ assert.notDeepEqual(['a', 'b'], ['a', 'b']);
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ }
+ });
+
+ it('should supply a default message', function(){
+ try {
+ assert.notDeepEqual(['a', 'b'], ['a', 'b']);
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('Expected ["a","b"] not to deeply equal ["a","b"].' != e.message) throw new Error('fail');
+ }
+ });
+
+ it('should respect a custom message', function(){
+ try {
+ assert.notDeepEqual(['a', 'b'], ['a', 'b'], 'message');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('message' != e.message) throw new Error('fail');
+ }
+ });
+ });
+
+ describe('.strictEqual', function(){
+ it('should pass', function(){
+ try {
+ assert.strictEqual('1', '1');
+ } catch (e) {
+ throw new Error('fail');
+ }
+ });
+
+ it('should fail', function(){
+ try {
+ assert.strictEqual(1, '1');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ }
+ });
+
+ it('should supply a default message', function(){
+ try {
+ assert.strictEqual(1, '1');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('Expected 1 to strictly equal "1".' != e.message) throw new Error('fail');
+ }
+ });
+
+ it('should respect a custom message', function(){
+ try {
+ assert.strictEqual(1, '1', 'message');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('message' != e.message) throw new Error('fail');
+ }
+ });
+ });
+
+ describe('.notStrictEqual', function(){
+ it('should pass', function(){
+ try {
+ assert.notStrictEqual(1, '1');
+ } catch (e) {
+ throw new Error('fail');
+ }
+ });
+
+ it('should fail', function(){
+ try {
+ var err = assert.notStrictEqual('1', '1');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ }
+ });
+
+ it('should supply a default message', function(){
+ try {
+ var err = assert.notStrictEqual('1', '1');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('Expected "1" not to strictly equal "1".' != e.message) throw new Error('fail');
+ }
+ });
+
+ it('should respect a custom message', function(){
+ try {
+ var err = assert.notStrictEqual('1', '1', 'message');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('message' != e.message) throw new Error('fail');
+ }
+ });
+ });
+
+ describe('.throws', function(){
+ it('should pass', function(){
+ try {
+ assert.throws(function(){ throw new Error; });
+ } catch (e) {
+ throw new Error('fail');
+ }
+ });
+
+ it('should fail', function(){
+ try {
+ assert.throws(function(){});
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ }
+ });
+
+ it('should supply a default message', function(){
+ try {
+ assert.throws(function(){});
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('Expected function (){} to throw an error.' != e.message) throw new Error('fail');
+ }
+ });
+
+ it('should respect a custom message', function(){
+ try {
+ assert.throws(function(){}, Error, 'message');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('message' != e.message) throw new Error('fail');
+ }
+ });
+ });
+
+ describe('.doesNotThrow', function(){
+ it('should pass', function(){
+ try {
+ assert.doesNotThrow(function(){});
+ } catch (e) {
+ throw new Error('fail');
+ }
+ });
+
+ it('should fail', function(){
+ try {
+ assert.doesNotThrow(function(){ throw new Error; });
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ }
+ });
+
+ it('should supply a default message', function(){
+ try {
+ assert.doesNotThrow(function(){ throw new Error; });
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('Expected function (){ throw new Error; } not to throw an error.' != e.message) throw new Error('fail');
+ }
+ });
+
+ it('should respect a custom message', function(){
+ try {
+ assert.doesNotThrow(function(){ throw new Error; }, Error, 'message');
+ throw new Error('fail');
+ } catch (e) {
+ if ('fail' == e.message) throw e;
+ if ('message' != e.message) throw new Error('fail');
+ }
+ });
+ });
+});
diff --git a/test/server/mocha.css b/components/component-assert@0.5.0/test/mocha.css
similarity index 82%
rename from test/server/mocha.css
rename to components/component-assert@0.5.0/test/mocha.css
index 274b97762..3b8afb1a0 100644
--- a/test/server/mocha.css
+++ b/components/component-assert@0.5.0/test/mocha.css
@@ -1,12 +1,8 @@
@charset "utf-8";
body {
- margin:0;
-}
-
-#mocha {
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
- margin: 60px 50px;
+ padding: 60px 50px;
}
#mocha ul, #mocha li {
@@ -42,7 +38,7 @@ body {
font-size: .8em;
}
-#mocha .hidden {
+.hidden {
display: none;
}
@@ -63,7 +59,7 @@ body {
#mocha .test.pending:hover h2::after {
content: '(pending)';
- font-family: arial, sans-serif;
+ font-family: arial;
}
#mocha .test.pass.medium .duration {
@@ -147,7 +143,6 @@ body {
-webkit-box-shadow: 0 1px 3px #eee;
-moz-border-radius: 3px;
-moz-box-shadow: 0 1px 3px #eee;
- border-radius: 3px;
}
#mocha .test h2 {
@@ -188,17 +183,9 @@ body {
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-size: 1.5 em;
font-weight: 100;
letter-spacing: 1px;
}
@@ -210,7 +197,6 @@ body {
font-size: 12px;
margin: 0;
color: #888;
- z-index: 1;
}
#mocha-stats .progress {
@@ -238,23 +224,8 @@ body {
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;
- }
-}
+code .comment { color: #ddd }
+code .init { color: #2F6FAD }
+code .string { color: #5890AD }
+code .keyword { color: #8A6343 }
+code .number { color: #2F6FAD }
diff --git a/components/component-assert@0.5.0/test/mocha.js b/components/component-assert@0.5.0/test/mocha.js
new file mode 100644
index 000000000..2e40cae64
--- /dev/null
+++ b/components/component-assert@0.5.0/test/mocha.js
@@ -0,0 +1,5340 @@
+;(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.txt for terms of usage */
+
+/*
+ * 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() {
+ 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, "&");
+ n = n.replace(//g, ">");
+ n = n.replace(/"/g, """);
+
+ return n;
+ }
+
+
+ var fbDiff = function(ignoreWhitespace) {
+ this.ignoreWhitespace = ignoreWhitespace;
+ };
+ fbDiff.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 fbDiff();
+
+ var WordDiff = new fbDiff(true);
+ WordDiff.tokenize = function(value) {
+ return removeEmpty(value.split(/(\s+|\b)/));
+ };
+
+ var CssDiff = new fbDiff(true);
+ CssDiff.tokenize = function(value) {
+ return removeEmpty(value.split(/([{}:;,]|\s+)/));
+ };
+
+ var LineDiff = new fbDiff();
+ LineDiff.tokenize = function(value) {
+ return value.split(/^/m);
+ };
+
+ return {
+ diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
+ diffWords: function(oldStr, newStr) { return WordDiff.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';
+ },
+
+ convertChangesToXML: function(changes){
+ var ret = [];
+ for ( var i = 0; i < changes.length; i++) {
+ var change = changes[i];
+ if (change.added) {
+ ret.push("");
+ } else if (change.removed) {
+ ret.push("");
+ }
+
+ ret.push(escapeHTML(change.value));
+
+ if (change.added) {
+ ret.push(" ");
+ } else if (change.removed) {
+ ret.push("");
+ }
+ }
+ return ret.join("");
+ }
+ };
+})();
+
+if (typeof module !== "undefined") {
+ module.exports = JsDiff;
+}
+
+}); // module: browser/diff.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/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){
+ 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);
+
+ return this;
+};
+
+}); // module: browser/progress.js
+
+require.register("browser/tty.js", function(module, exports, require){
+
+exports.isatty = function(){
+ return true;
+};
+
+exports.getWindowSize = function(){
+ return [window.innerHeight, window.innerWidth];
+};
+}); // 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){
+ this.runnable().timeout(ms);
+ 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');
+
+/**
+ * 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(fn){
+ suites[0].beforeAll(fn);
+ };
+
+ /**
+ * Execute after running tests.
+ */
+
+ context.after = function(fn){
+ suites[0].afterAll(fn);
+ };
+
+ /**
+ * Execute before each test case.
+ */
+
+ context.beforeEach = function(fn){
+ suites[0].beforeEach(fn);
+ };
+
+ /**
+ * Execute after each test case.
+ */
+
+ context.afterEach = function(fn){
+ suites[0].afterEach(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);
+ 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());
+ };
+
+ /**
+ * 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) var fn = null;
+ var test = new Test(title, fn);
+ suite.addTest(test);
+ return test;
+ };
+
+ /**
+ * Exclusive test-case.
+ */
+
+ context.it.only = function(title, fn){
+ var test = context.it(title, fn);
+ mocha.grep(test.fullTitle());
+ };
+
+ /**
+ * 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) {
+ 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:
+ suites[0].addTest(new Test(key, fn));
+ }
+ } else {
+ var 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');
+
+/**
+ * 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){
+
+ /**
+ * Execute before running tests.
+ */
+
+ context.before = function(fn){
+ suites[0].beforeAll(fn);
+ };
+
+ /**
+ * Execute after running tests.
+ */
+
+ context.after = function(fn){
+ suites[0].afterAll(fn);
+ };
+
+ /**
+ * Execute before each test case.
+ */
+
+ context.beforeEach = function(fn){
+ suites[0].beforeEach(fn);
+ };
+
+ /**
+ * Execute after each test case.
+ */
+
+ context.afterEach = function(fn){
+ suites[0].afterEach(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);
+ suites.unshift(suite);
+ };
+
+ /**
+ * Describe a specification or test-case
+ * with the given `title` and callback `fn`
+ * acting as a thunk.
+ */
+
+ context.test = function(title, fn){
+ suites[0].addTest(new Test(title, fn));
+ };
+ });
+};
+
+}); // module: interfaces/qunit.js
+
+require.register("interfaces/tdd.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+ , Test = require('../test');
+
+/**
+ * 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(fn){
+ suites[0].beforeEach(fn);
+ };
+
+ /**
+ * Execute after each test case.
+ */
+
+ context.teardown = function(fn){
+ suites[0].afterEach(fn);
+ };
+
+ /**
+ * Execute before the suite.
+ */
+
+ context.suiteSetup = function(fn){
+ suites[0].beforeAll(fn);
+ };
+
+ /**
+ * Execute after the suite.
+ */
+
+ context.suiteTeardown = function(fn){
+ suites[0].afterAll(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);
+ suites.unshift(suite);
+ fn.call(suite);
+ suites.shift();
+ 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);
+ suites[0].addTest(test);
+ return test;
+ };
+
+ /**
+ * Exclusive test-case.
+ */
+
+ context.test.only = function(title, fn){
+ var test = context.test(title, fn);
+ mocha.grep(test.fullTitle());
+ };
+
+ /**
+ * 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
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var path = require('browser/path')
+ , utils = require('./utils');
+
+/**
+ * Expose `Mocha`.
+ */
+
+exports = module.exports = Mocha;
+
+/**
+ * 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.Dot`
+ * - `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 (options.timeout) this.timeout(options.timeout);
+ if (options.slow) this.slow(options.slow);
+}
+
+/**
+ * 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 "dot".
+ *
+ * @param {String|Function} reporter name or constructor
+ * @api public
+ */
+
+Mocha.prototype.reporter = function(reporter){
+ if ('function' == typeof reporter) {
+ this._reporter = reporter;
+ } else {
+ reporter = reporter || 'dot';
+ try {
+ this._reporter = require('./reporters/' + reporter);
+ } catch (err) {
+ this._reporter = require(reporter);
+ }
+ if (!this._reporter) throw new Error('invalid 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) 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(utils.escapeRegexp(re))
+ : re;
+ return this;
+};
+
+/**
+ * Invert `.grep()` matches.
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.invert = function(){
+ this.options.invert = true;
+ return this;
+};
+
+/**
+ * Ignore global leaks.
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.ignoreLeaks = function(){
+ this.options.ignoreLeaks = true;
+ 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;
+};
+
+/**
+ * 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;
+};
+
+/**
+ * Makes all tests async (accepting a callback)
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.asyncOnly = function(){
+ this.options.asyncOnly = 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;
+ var runner = new exports.Runner(suite);
+ var reporter = new this._reporter(runner);
+ runner.ignoreLeaks = 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);
+ 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;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * @param {String|Number} val
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val){
+ if ('string' == typeof val) return parse(val);
+ return format(val);
+}
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+ var m = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
+ if (!m) return;
+ var n = parseFloat(m[1]);
+ var type = (m[2] || 'ms').toLowerCase();
+ switch (type) {
+ case 'years':
+ case 'year':
+ case 'y':
+ return n * 31557600000;
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * 86400000;
+ case 'hours':
+ case 'hour':
+ case 'h':
+ return n * 3600000;
+ case 'minutes':
+ case 'minute':
+ case 'm':
+ return n * 60000;
+ case 'seconds':
+ case 'second':
+ case 's':
+ return n * 1000;
+ case 'ms':
+ return n;
+ }
+}
+
+/**
+ * Format the given `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api public
+ */
+
+function format(ms) {
+ if (ms == d) return Math.round(ms / d) + ' day';
+ if (ms > d) return Math.round(ms / d) + ' days';
+ if (ms == h) return Math.round(ms / h) + ' hour';
+ if (ms > h) return Math.round(ms / h) + ' hours';
+ if (ms == m) return Math.round(ms / m) + ' minute';
+ if (ms > m) return Math.round(ms / m) + ' minutes';
+ if (ms == s) return Math.round(ms / s) + ' second';
+ if (ms > s) return Math.round(ms / s) + ' seconds';
+ return ms + ' ms';
+}
+}); // 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');
+
+/**
+ * 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;
+
+/**
+ * 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(){
+ process.stdout.write('\u001b[?25l');
+ },
+
+ show: function(){
+ process.stdout.write('\u001b[?25h');
+ },
+
+ deleteLine: function(){
+ process.stdout.write('\u001b[2K');
+ },
+
+ beginningOfLine: function(){
+ process.stdout.write('\u001b[0G');
+ },
+
+ CR: function(){
+ exports.cursor.deleteLine();
+ exports.cursor.beginningOfLine();
+ }
+};
+
+/**
+ * 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;
+
+ // explicitly show diff
+ if (err.showDiff) {
+ escape = false;
+ err.actual = actual = JSON.stringify(actual, null, 2);
+ err.expected = expected = JSON.stringify(expected, null, 2);
+ }
+
+ // actual / expected diff
+ if ('string' == typeof actual && 'string' == typeof expected) {
+ var len = Math.max(actual.length, expected.length);
+
+ if (len < 20) msg = errorDiff(err, 'Chars', escape);
+ else msg = errorDiff(err, 'Words', 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, ' ');
+
+ fmt = color('error title', ' %s) %s:\n%s')
+ + color('error stack', '\n%s\n');
+ }
+
+ // 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
+ , fmt
+ , tests;
+
+ console.log();
+
+ function pluralize(n) {
+ return 1 == n ? 'test' : 'tests';
+ }
+
+ // failure
+ if (stats.failures) {
+ fmt = color('bright fail', ' ' + exports.symbols.err)
+ + color('fail', ' %d of %d %s failed')
+ + color('light', ':')
+
+ console.error(fmt,
+ stats.failures,
+ this.runner.total,
+ pluralize(this.runner.total));
+
+ Base.list(this.failures);
+ console.error();
+ return;
+ }
+
+ // pass
+ fmt = color('bright pass', ' ')
+ + color('green', ' %d %s complete')
+ + color('light', ' (%s)');
+
+ console.log(fmt,
+ stats.tests || 0,
+ pluralize(stats.tests),
+ ms(stats.duration));
+
+ // pending
+ if (stats.pending) {
+ fmt = color('pending', ' ')
+ + color('pending', ' %d %s pending');
+
+ console.log(fmt, stats.pending, pluralize(stats.pending));
+ }
+
+ 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;
+}
+
+/**
+ * Return a character diff for `err`.
+ *
+ * @param {Error} err
+ * @return {String}
+ * @api private
+ */
+
+function errorDiff(err, type, escape) {
+ return diff['diff' + type](err.actual, err.expected).map(function(str){
+ if (escape) {
+ str.value = str.value
+ .replace(/\t/g, '')
+ .replace(/\r/g, '')
+ .replace(/\n/g, '\n');
+ }
+ if (str.added) return colorLines('diff added', str.value);
+ if (str.removed) return colorLines('diff removed', str.value);
+ return str.value;
+ }).join('');
+}
+
+/**
+ * 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');
+}
+
+}); // 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', indent());
+ ++indents;
+ console.log('%s%s ', indent(), utils.escape(suite.title));
+ console.log('%s', indent());
+ });
+
+ runner.on('suite end', function(suite){
+ if (suite.root) return;
+ console.log('%s ', indent());
+ --indents;
+ console.log('%s ', indent());
+ --indents;
+ });
+
+ runner.on('pass', function(test){
+ console.log('%s %s ', indent(), utils.escape(test.title));
+ var code = utils.escape(utils.clean(test.fn.toString()));
+ console.log('%s %s
', indent(), code);
+ });
+}
+
+}); // 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 = 0;
+
+ runner.on('start', function(){
+ process.stdout.write('\n ');
+ });
+
+ runner.on('pending', function(test){
+ 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 `Doc`.
+ */
+
+exports = module.exports = HTML;
+
+/**
+ * Stats template.
+ */
+
+var statsTemplate = '';
+
+/**
+ * Initialize a new `Doc` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function HTML(runner, root) {
+ 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('')
+ , stack = [report]
+ , progress
+ , ctx
+
+ root = 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 = '?grep=' + encodeURIComponent(suite.fullTitle());
+ var el = fragment(' ', 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){
+ window.scrollTo(0, document.body.scrollHeight);
+
+ // 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 el = fragment('%e%ems ‣ ', test.speed, test.title, test.duration, encodeURIComponent(test.fullTitle()));
+ } else if (test.pending) {
+ var el = fragment('%e ', test.title);
+ } else {
+ var el = fragment(' ', 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('%e ', 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('%e
', 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);
+ });
+}
+
+/**
+ * Display error `msg`.
+ */
+
+function error(msg) {
+ document.body.appendChild(fragment('%s
', 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');
+exports.Teamcity = require('./teamcity');
+
+}); // 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){
+ console.log(JSON.stringify(['fail', clean(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 = []
+ , 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 obj = {
+ stats: self.stats
+ , tests: tests.map(clean)
+ , failures: failures.map(clean)
+ , passes: passes.map(clean)
+ };
+
+ 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
+ }
+}
+}); // 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 ');
+ 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[4F\n\n');
+ 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 += ' ' + '\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('start');
+ });
+
+ runner.on('pending', function(test){
+ self.draw('pending');
+ });
+
+ runner.on('pass', function(test){
+ self.draw('pass');
+ });
+
+ runner.on('fail', function(test, err){
+ self.draw('fail');
+ });
+
+ runner.on('end', function(){
+ Base.cursor.show();
+ for (var i = 0; i < self.numberOfLines; i++) write('\n');
+ self.epilogue();
+ });
+}
+
+/**
+ * Draw the nyan cat with runner `status`.
+ *
+ * @param {String} status
+ * @api private
+ */
+
+NyanCat.prototype.draw = function(status){
+ this.appendRainbow();
+ this.drawScoreboard();
+ this.drawRainbow();
+ this.drawNyanCat(status);
+ 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 with `status`.
+ *
+ * @param {String} status
+ * @api private
+ */
+
+NyanCat.prototype.drawNyanCat = function(status) {
+ var self = this;
+ var startWidth = this.scoreboardWidth + this.trajectories[0].length;
+
+ [0, 1, 2, 3].forEach(function(index) {
+ write('\u001b[' + startWidth + 'C');
+
+ switch (index) {
+ case 0:
+ write('_,------,');
+ write('\n');
+ break;
+ case 1:
+ var padding = self.tick ? ' ' : ' ';
+ write('_|' + padding + '/\\_/\\ ');
+ write('\n');
+ break;
+ case 2:
+ var padding = self.tick ? '_' : '__';
+ var tail = self.tick ? '~' : '^';
+ var face;
+ switch (status) {
+ case 'pass':
+ face = '( ^ .^)';
+ break;
+ case 'fail':
+ face = '( o .o)';
+ break;
+ default:
+ face = '( - .-)';
+ }
+ write(tail + '|' + padding + face + ' ');
+ write('\n');
+ break;
+ case 3:
+ var padding = self.tick ? ' ' : ' ';
+ write(padding + '"" "" ');
+ write('\n');
+ break;
+ }
+ });
+
+ this.cursorUp(this.numberOfLines);
+};
+
+/**
+ * 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;
+
+ // 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;
+
+ 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('test', function(test){
+ process.stdout.write(indent() + color('pass', ' â—¦ ' + test.title + ': '));
+ });
+
+ 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/teamcity.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `Teamcity`.
+ */
+
+exports = module.exports = Teamcity;
+
+/**
+ * Initialize a new `Teamcity` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Teamcity(runner) {
+ Base.call(this, runner);
+ var stats = this.stats;
+
+ runner.on('start', function() {
+ console.log("##teamcity[testSuiteStarted name='mocha.suite']");
+ });
+
+ runner.on('test', function(test) {
+ console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']");
+ });
+
+ runner.on('fail', function(test, err) {
+ console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']");
+ });
+
+ runner.on('pending', function(test) {
+ console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']");
+ });
+
+ runner.on('test end', function(test) {
+ console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']");
+ });
+
+ runner.on('end', function() {
+ console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']");
+ });
+}
+
+/**
+ * Escape the given `str`.
+ */
+
+function escape(str) {
+ return str
+ .replace(/\|/g, "||")
+ .replace(/\n/g, "|n")
+ .replace(/\r/g, "|r")
+ .replace(/\[/g, "|[")
+ .replace(/\]/g, "|]")
+ .replace(/\u0085/g, "|x")
+ .replace(/\u2028/g, "|l")
+ .replace(/\u2029/g, "|p")
+ .replace(/'/g, "|'");
+}
+
+}); // module: reporters/teamcity.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('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
+ , skip: stats.tests - stats.failures - stats.passes
+ , timestamp: (new Date).toUTCString()
+ , time: stats.duration / 1000
+ }, false));
+
+ tests.forEach(test);
+ console.log('');
+ });
+}
+
+/**
+ * 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
+ };
+
+ if ('failed' == test.state) {
+ var err = test.err;
+ attrs.message = escape(err.message);
+ console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(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 '';
+}
+
+}); // 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.timedOut = false;
+}
+
+/**
+ * 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 ('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;
+};
+
+/**
+ * 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 '#';
+ if ('ctx' == key) return '#';
+ return val;
+ }, 2);
+};
+
+/**
+ * Reset the timeout.
+ *
+ * @api private
+ */
+
+Runnable.prototype.resetTimeout = function(){
+ var self = this
+ , ms = this.timeout();
+
+ this.clearTimeout();
+ if (ms) {
+ this.timer = setTimeout(function(){
+ self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
+ self.timedOut = true;
+ }, ms);
+ }
+};
+
+/**
+ * Run the test and invoke `fn(err)`.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+
+Runnable.prototype.run = function(fn){
+ var self = this
+ , ms = this.timeout()
+ , start = new Date
+ , ctx = this.ctx
+ , finished
+ , emitted;
+
+ if (ctx) ctx.runnable(this);
+
+ // timeout
+ if (this.async) {
+ if (ms) {
+ this.timer = setTimeout(function(){
+ done(new Error('timeout of ' + ms + 'ms exceeded'));
+ self.timedOut = true;
+ }, ms);
+ }
+ }
+
+ // called multiple times
+ function multiple(err) {
+ if (emitted) return;
+ emitted = true;
+ self.emit('error', err || new Error('done() called multiple times'));
+ }
+
+ // finished
+ function done(err) {
+ if (self.timedOut) return;
+ if (finished) return multiple(err);
+ self.clearTimeout();
+ self.duration = new Date - start;
+ finished = true;
+ fn(err);
+ }
+
+ // for .resetTimeout()
+ this.callback = done;
+
+ // async
+ if (this.async) {
+ try {
+ this.fn.call(ctx, function(err){
+ if (err instanceof Error || toString.call(err) === "[object Error]") return done(err);
+ if (null != err) 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
+ try {
+ if (!this.pending) this.fn.call(ctx);
+ this.duration = new Date - start;
+ fn();
+ } catch (err) {
+ fn(err);
+ }
+};
+
+}); // 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
+ , noop = function(){};
+
+/**
+ * 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
+ *
+ * @api public
+ */
+
+function Runner(suite) {
+ var self = this;
+ this._globals = [];
+ 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(['errno']));
+}
+
+/**
+ * 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);
+ utils.forEach(arr, function(arr){
+ this._globals.push(arr);
+ }, this);
+ 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 isNode = process.kill;
+ var leaks;
+
+ // check length - 2 ('errno' and 'location' globals)
+ if (isNode && 1 == ok.length - globals.length) return
+ else if (2 == ok.length - globals.length) return;
+
+ 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 (currently) hard-end due
+ * to that fact that a failing hook will
+ * surely cause subsequent tests to fail,
+ * causing jumbled reporting.
+ *
+ * @param {Hook} hook
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.failHook = function(hook, err){
+ this.fail(hook, err);
+ 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();
+ self.currentRunnable = hook;
+
+ 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) return self.failHook(hook, err);
+ self.emit('hook end', hook);
+ next(++i);
+ });
+ }
+
+ process.nextTick(function(){
+ next(0);
+ });
+};
+
+/**
+ * Run hook `name` for the given array of `suites`
+ * in order, and callback `fn(err)`.
+ *
+ * @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) {
+ self.suite = orig;
+ return fn(err);
+ }
+
+ 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 next(err) {
+ // if we bail after first err
+ if (self.failures && suite._bail) return fn();
+
+ // 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(){
+ 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() {
+ var curr = suite.suites[i++];
+ if (!curr) return done();
+ self.runSuite(curr, next);
+ }
+
+ function done() {
+ self.suite = suite;
+ self.hook('afterAll', function(){
+ self.emit('suite end', suite);
+ fn();
+ });
+ }
+
+ this.hook('beforeAll', function(){
+ self.runTests(suite, next);
+ });
+};
+
+/**
+ * Handle uncaught exceptions.
+ *
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.uncaught = function(err){
+ debug('uncaught exception %s', err.message);
+ var runnable = this.currentRunnable;
+ if (!runnable || 'failed' == runnable.state) return;
+ runnable.clearTimeout();
+ err.uncaught = true;
+ this.fail(runnable, err);
+
+ // 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(){};
+
+ debug('start');
+
+ // callback
+ this.on('end', function(){
+ debug('end');
+ process.removeListener('uncaughtException', function(err){
+ self.uncaught(err);
+ });
+ fn(self.failures);
+ });
+
+ // run suites
+ this.emit('start');
+ this.runSuite(this.suite, function(){
+ debug('finished running');
+ self.emit('end');
+ });
+
+ // uncaught exception
+ process.on('uncaughtException', function(err){
+ self.uncaught(err);
+ });
+
+ return this;
+};
+
+/**
+ * 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){
+ var matched = filter(ok, function(ok){
+ if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);
+ // Opera and IE expose global variables for HTML element IDs (issue #243)
+ if (/^mocha-/.test(key)) return true;
+ return key == ok;
+ });
+ return matched.length == 0 && (!global.navigator || 'onerror' !== key);
+ });
+}
+
+}); // 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, ctx) {
+ this.title = title;
+ this.ctx = ctx;
+ this.suites = [];
+ this.tests = [];
+ this.pending = false;
+ this._beforeEach = [];
+ this._beforeAll = [];
+ this._afterEach = [];
+ this._afterAll = [];
+ this.root = !title;
+ this._timeout = 2000;
+ 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.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 ('string' == typeof ms) ms = milliseconds(ms);
+ debug('timeout %d', ms);
+ this._timeout = parseInt(ms, 10);
+ 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(fn){
+ if (this.pending) return this;
+ var hook = new Hook('"before all" hook', fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ 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(fn){
+ if (this.pending) return this;
+ var hook = new Hook('"after all" hook', fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ 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(fn){
+ if (this.pending) return this;
+ var hook = new Hook('"before each" hook', fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ 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(fn){
+ if (this.pending) return this;
+ var hook = new Hook('"after each" hook', fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ 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.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.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')
+ , 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, '&')
+ .replace(/"/g, '"')
+ .replace(//g, '>');
+};
+
+/**
+ * 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#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, ret){
+ ret = ret || [];
+
+ fs.readdirSync(dir)
+ .filter(ignored)
+ .forEach(function(path){
+ path = join(dir, path);
+ if (fs.statSync(path).isDirectory()) {
+ exports.files(path, ret);
+ } else if (path.match(/\.(js|coffee)$/)) {
+ 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(/^function *\(.*\) *{/, '')
+ .replace(/\s+\}$/, '');
+
+ var spaces = str.match(/^\n?( *)/)[1].length
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
+
+ str = str.replace(re, '');
+
+ return exports.trim(str);
+};
+
+/**
+ * Escape regular expression characters in `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+exports.escapeRegexp = function(str){
+ return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
+};
+
+/**
+ * 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, '>')
+ .replace(/\/\/(.*)/gm, '')
+ .replace(/('.*?')/gm, '$1 ')
+ .replace(/(\d+\.\d+)/gm, '$1 ')
+ .replace(/(\d+)/gm, '$1 ')
+ .replace(/\bnew *(\w+)/gm, 'new $1 ')
+ .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1 ')
+}
+
+/**
+ * Highlight the contents of tag `name`.
+ *
+ * @param {String} name
+ * @api private
+ */
+
+exports.highlightTags = function(name) {
+ var code = document.getElementsByTagName(name);
+ for (var i = 0, len = code.length; i < len; ++i) {
+ code[i].innerHTML = highlight(code[i].innerHTML);
+ }
+};
+
+}); // module: utils.js
+/**
+ * Node shims.
+ *
+ * These are meant only to allow
+ * mocha.js to run untouched, not
+ * to allow running node code in
+ * the browser.
+ */
+
+process = {};
+process.exit = function(status){};
+process.stdout = {};
+global = window;
+
+/**
+ * next tick implementation.
+ */
+
+process.nextTick = (function(){
+ // postMessage behaves badly on IE8
+ if (window.ActiveXObject || !window.postMessage) {
+ return function(fn){ fn() };
+ }
+
+ // based on setZeroTimeout by David Baron
+ // - http://dbaron.org/log/20100309-faster-timeouts
+ var timeouts = []
+ , name = 'mocha-zero-timeout'
+
+ window.addEventListener('message', function(e){
+ if (e.source == window && e.data == name) {
+ if (e.stopPropagation) e.stopPropagation();
+ if (timeouts.length) timeouts.shift()();
+ }
+ }, true);
+
+ return function(fn){
+ timeouts.push(fn);
+ window.postMessage(name, '*');
+ }
+})();
+
+/**
+ * Remove uncaughtException listener.
+ */
+
+process.removeListener = function(e){
+ if ('uncaughtException' == e) {
+ window.onerror = null;
+ }
+};
+
+/**
+ * Implements uncaughtException listener.
+ */
+
+process.on = function(e, fn){
+ if ('uncaughtException' == e) {
+ window.onerror = function(err, url, line){
+ fn(new Error(err + ' (' + url + ':' + line + ')'));
+ };
+ }
+};
+
+// boot
+;(function(){
+
+ /**
+ * Expose mocha.
+ */
+
+ var Mocha = window.Mocha = require('mocha'),
+ mocha = window.mocha = new Mocha({ reporter: 'html' });
+
+ /**
+ * 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', window, 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(window.location.search || '');
+ if (query.grep) mocha.grep(query.grep);
+ if (query.invert) mocha.invert();
+
+ return Mocha.prototype.run.call(mocha, function(){
+ Mocha.utils.highlightTags('code');
+ if (fn) fn();
+ });
+ };
+})();
+})();
\ No newline at end of file
diff --git a/components/component-assert@0.5.0/test/server.js b/components/component-assert@0.5.0/test/server.js
new file mode 100644
index 000000000..f02d6dc6c
--- /dev/null
+++ b/components/component-assert@0.5.0/test/server.js
@@ -0,0 +1,22 @@
+
+/**
+ * Module dependencies.
+ */
+
+var express = require('express');
+var hbs = require('hbs');
+
+/**
+ * App.
+ */
+
+express()
+ .use(express.static(__dirname + '/..'))
+ .set('views', __dirname)
+ .engine('html', hbs.__express)
+ .get('*', function (req, res) { res.render('index.html'); })
+ .listen(7575, function(){
+ console.log();
+ console.log(' Tests running at http://localhost:7575/ ...');
+ console.log();
+ });
\ No newline at end of file
diff --git a/components/component-stack@0.0.1/.gitignore b/components/component-stack@0.0.1/.gitignore
new file mode 100644
index 000000000..48a2e246c
--- /dev/null
+++ b/components/component-stack@0.0.1/.gitignore
@@ -0,0 +1,2 @@
+components
+build
diff --git a/components/component-stack@0.0.1/Makefile b/components/component-stack@0.0.1/Makefile
new file mode 100644
index 000000000..84395cdd3
--- /dev/null
+++ b/components/component-stack@0.0.1/Makefile
@@ -0,0 +1,11 @@
+
+build: components index.js
+ @component build --dev
+
+components:
+ @component install --dev
+
+clean:
+ rm -fr build components template.js
+
+.PHONY: clean
diff --git a/components/component-stack@0.0.1/Readme.md b/components/component-stack@0.0.1/Readme.md
new file mode 100644
index 000000000..5eb869038
--- /dev/null
+++ b/components/component-stack@0.0.1/Readme.md
@@ -0,0 +1,12 @@
+
+# stack
+
+ Get a stack of `CallSite` objects
+
+## Installation
+
+ $ component install component/stack
+
+## License
+
+ MIT
diff --git a/components/component-stack@0.0.1/component.json b/components/component-stack@0.0.1/component.json
new file mode 100644
index 000000000..4c84147e4
--- /dev/null
+++ b/components/component-stack@0.0.1/component.json
@@ -0,0 +1,12 @@
+{
+ "name": "stack",
+ "repo": "component/stack",
+ "description": "Get a stack of CallSite objects",
+ "version": "0.0.1",
+ "keywords": ["stack", "error", "callsite", "debug"],
+ "dependencies": {},
+ "development": {},
+ "scripts": [
+ "index.js"
+ ]
+}
\ No newline at end of file
diff --git a/components/component-stack@0.0.1/index.js b/components/component-stack@0.0.1/index.js
new file mode 100644
index 000000000..4741054d3
--- /dev/null
+++ b/components/component-stack@0.0.1/index.js
@@ -0,0 +1,23 @@
+
+/**
+ * Expose `stack()`.
+ */
+
+module.exports = stack;
+
+/**
+ * Return the stack.
+ *
+ * @return {Array}
+ * @api public
+ */
+
+function stack() {
+ var orig = Error.prepareStackTrace;
+ Error.prepareStackTrace = function(_, stack){ return stack; };
+ var err = new Error;
+ Error.captureStackTrace(err, arguments.callee);
+ var stack = err.stack;
+ Error.prepareStackTrace = orig;
+ return stack;
+}
\ No newline at end of file
diff --git a/components/jkroso-equals@1.0.0/.gitignore b/components/jkroso-equals@1.0.0/.gitignore
new file mode 100644
index 000000000..00b61ef79
--- /dev/null
+++ b/components/jkroso-equals@1.0.0/.gitignore
@@ -0,0 +1,7 @@
+/build
+/components
+/node_modules
+/test/built.js
+/dist
+*.sublime-project
+*.sublime-workspace
diff --git a/components/jkroso-equals@1.0.0/License b/components/jkroso-equals@1.0.0/License
new file mode 100644
index 000000000..1add9924d
--- /dev/null
+++ b/components/jkroso-equals@1.0.0/License
@@ -0,0 +1,23 @@
+
+(MIT)
+
+Copyright (c) 2013 Jake Rosoman <jkroso@gmail.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 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/components/jkroso-equals@1.0.0/Makefile b/components/jkroso-equals@1.0.0/Makefile
new file mode 100644
index 000000000..a1e6aeeeb
--- /dev/null
+++ b/components/jkroso-equals@1.0.0/Makefile
@@ -0,0 +1,14 @@
+
+serve: node_modules
+ @node_modules/serve/bin/serve -Slojp 0
+
+test: node_modules
+ @sed "s/'equals'/'.\/'/" Readme.md | node_modules/jsmd/bin/jsmd
+ @node_modules/hydro/bin/hydro test/*.test.js \
+ --formatter node_modules/hydro-dot \
+ --setup test/hydro.conf.js
+
+node_modules: package.json
+ @packin install --meta $< --folder $@
+
+.PHONY: serve test
diff --git a/components/jkroso-equals@1.0.0/Readme.md b/components/jkroso-equals@1.0.0/Readme.md
new file mode 100644
index 000000000..bbf883636
--- /dev/null
+++ b/components/jkroso-equals@1.0.0/Readme.md
@@ -0,0 +1,63 @@
+
+# equals
+
+ compare values of any type for equility
+
+## Installation
+
+With your favorite package manager:
+
+- [packin](//github.com/jkroso/packin): `packin add equals`
+- [component](//github.com/component/component#installing-packages): `component install jkroso/equals`
+- [npm](//npmjs.org/doc/cli/npm-install.html): `npm install equals`
+
+then in your app:
+
+```js
+var equal = require('equals')
+```
+
+## API
+
+### equal(a, b, [memos])
+
+`equal` takes as many arguments as you like of any type you like and returns a boolean result. Primitive types are equal if they are `===`. While composite types, i.e. Objects and Arrays, are considered equal if they have both the same structure and each sub-value is also `equal`. Circular references in composite structures are supported.
+
+Same structure:
+```js
+equal(
+ { a : [ 2, 3 ], b : [ 4 ] },
+ { a : [ 2, 3 ], b : [ 4 ] }
+) // => true
+```
+
+Different Structure:
+```js
+equal(
+ { x : 5, y : [6] },
+ { x : 5}
+) // => false
+```
+
+Same structure, different values:
+
+```js
+equal(
+ { a: [ 1, 2 ], b : [ 4 ]},
+ { a: [ 2, 3 ], b : [ 4 ]}
+) // => false
+```
+
+Primitives:
+
+```js
+equal(new Date(0), new Date(1)) // => false
+```
+
+Some possible gotchas:
+- `null` __is not__ equal to `undefined`.
+- `NaN` __is__ equal to `NaN` (normally not the case).
+- `-0` __is__ equal to `+0`.
+- Strings will __not__ coerce to numbers.
+- Non enumerable properties will not be checked. They can't be.
+- `arguments.callee` is not considered when comparing arguments
diff --git a/components/jkroso-equals@1.0.0/component.json b/components/jkroso-equals@1.0.0/component.json
new file mode 100644
index 000000000..c17682c6f
--- /dev/null
+++ b/components/jkroso-equals@1.0.0/component.json
@@ -0,0 +1,19 @@
+{
+ "name": "equals",
+ "repo": "jkroso/equals",
+ "description": "Check if two values are deeply equivalent",
+ "keywords": [
+ "equality",
+ "equal",
+ "same",
+ "equivalent",
+ "equivalence",
+ "=",
+ "equals"
+ ],
+ "dependencies": {
+ "jkroso/type": "*"
+ },
+ "scripts": ["index.js"],
+ "license": "MIT"
+}
diff --git a/components/jkroso-equals@1.0.0/index.js b/components/jkroso-equals@1.0.0/index.js
new file mode 100644
index 000000000..5c0336ae1
--- /dev/null
+++ b/components/jkroso-equals@1.0.0/index.js
@@ -0,0 +1,120 @@
+var type = require('type')
+
+// (any, any, [array]) -> boolean
+function equal(a, b, memos){
+ // All identical values are equivalent
+ if (a === b) return true
+ var fnA = types[type(a)]
+ var fnB = types[type(b)]
+ return fnA && fnA === fnB
+ ? fnA(a, b, memos)
+ : false
+}
+
+var types = {}
+
+// (Number) -> boolean
+types.number = function(a, b){
+ return a !== a && b !== b/*Nan check*/
+}
+
+// (function, function, array) -> boolean
+types['function'] = function(a, b, memos){
+ return a.toString() === b.toString()
+ // Functions can act as objects
+ && types.object(a, b, memos)
+ && equal(a.prototype, b.prototype)
+}
+
+// (date, date) -> boolean
+types.date = function(a, b){
+ return +a === +b
+}
+
+// (regexp, regexp) -> boolean
+types.regexp = function(a, b){
+ return a.toString() === b.toString()
+}
+
+// (DOMElement, DOMElement) -> boolean
+types.element = function(a, b){
+ return a.outerHTML === b.outerHTML
+}
+
+// (textnode, textnode) -> boolean
+types.textnode = function(a, b){
+ return a.textContent === b.textContent
+}
+
+// decorate `fn` to prevent it re-checking objects
+// (function) -> function
+function memoGaurd(fn){
+ return function(a, b, memos){
+ if (!memos) return fn(a, b, [])
+ var i = memos.length, memo
+ while (memo = memos[--i]) {
+ if (memo[0] === a && memo[1] === b) return true
+ }
+ return fn(a, b, memos)
+ }
+}
+
+types['arguments'] =
+types.array = memoGaurd(arrayEqual)
+
+// (array, array, array) -> boolean
+function arrayEqual(a, b, memos){
+ var i = a.length
+ if (i !== b.length) return false
+ memos.push([a, b])
+ while (i--) {
+ if (!equal(a[i], b[i], memos)) return false
+ }
+ return true
+}
+
+types.object = memoGaurd(objectEqual)
+
+// (object, object, array) -> boolean
+function objectEqual(a, b, memos) {
+ if (typeof a.equal == 'function') {
+ memos.push([a, b])
+ return a.equal(b, memos)
+ }
+ var ka = getEnumerableProperties(a)
+ var kb = getEnumerableProperties(b)
+ var i = ka.length
+
+ // same number of properties
+ if (i !== kb.length) return false
+
+ // although not necessarily the same order
+ ka.sort()
+ kb.sort()
+
+ // cheap key test
+ while (i--) if (ka[i] !== kb[i]) return false
+
+ // remember
+ memos.push([a, b])
+
+ // iterate again this time doing a thorough check
+ i = ka.length
+ while (i--) {
+ var key = ka[i]
+ if (!equal(a[key], b[key], memos)) return false
+ }
+
+ return true
+}
+
+// (object) -> array
+function getEnumerableProperties (object) {
+ var result = []
+ for (var k in object) if (k !== 'constructor') {
+ result.push(k)
+ }
+ return result
+}
+
+module.exports = equal
diff --git a/components/jkroso-equals@1.0.0/package.json b/components/jkroso-equals@1.0.0/package.json
new file mode 100644
index 000000000..14e919192
--- /dev/null
+++ b/components/jkroso-equals@1.0.0/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "equals",
+ "version": "1.0.0",
+ "description": "Check if two values are deeply equivalent",
+ "dependencies": {
+ "type": "jkroso/type"
+ },
+ "devDependencies": {
+ "serve": "jkroso/serve",
+ "hydro-html": "*",
+ "hydro-chai": "*",
+ "hydro-dot": "*",
+ "hydro-bdd": "*",
+ "hydro": "*",
+ "jsmd": "*",
+ "chai": "*"
+ },
+ "repository": "git://github.com/jkroso/equals.git",
+ "keywords": ["equality", "equal", "equivalent", "equivalence", "="],
+ "files": ["index.js"],
+ "author": "Jake Rosoman",
+ "license": "MIT"
+}
diff --git a/components/jkroso-equals@1.0.0/test/equals.test.js b/components/jkroso-equals@1.0.0/test/equals.test.js
new file mode 100644
index 000000000..306de83ca
--- /dev/null
+++ b/components/jkroso-equals@1.0.0/test/equals.test.js
@@ -0,0 +1,210 @@
+
+var eql = require('..')
+
+describe('Object strucures', function () {
+ it('when structures match', function () {
+ eql(
+ { a : [ 2, 3 ], b : [ 4 ] },
+ { a : [ 2, 3 ], b : [ 4 ] }
+ ).should.be.true
+ })
+
+ it('when structures don\'t match', function () {
+ eql(
+ { x : 5, y : [6] },
+ { x : 5, y : 6 }
+ ).should.be.false
+ })
+
+ it('should handle nested nulls', function () {
+ eql([ null, null, null ], [ null, null, null ]).should.be.true
+ eql([ null, null, null ], [ null, 'null', null ]).should.be.false
+ })
+
+ it('should handle nested NaNs', function () {
+ eql([ NaN, NaN, NaN ], [ NaN, NaN, NaN ]).should.be.true
+ eql([ NaN, NaN, NaN ], [ NaN, 'NaN', NaN ]).should.be.false
+ })
+
+ it('custom equal methods', function(){
+ eql({equal: function(){ return true }}, {}).should.be.true
+ eql({equal: function(){ return false }}, {}).should.be.false
+ })
+})
+
+describe('Comparing arguments', function () {
+ var a = (function a(a,b,c) {return arguments}(1,2,3))
+ var b = (function b(a,b,c) {return arguments}(1,2,3))
+ var c = (function c(a,b,c) {return arguments}(2,2,3))
+
+ it('should not consider the callee', function () {
+ eql(a,b).should.be.true
+ eql(a,c).should.be.false
+ })
+
+ it('should be comparable to an Array', function () {
+ eql(a,[1,2,3]).should.be.true
+ eql(a,[1,2,4]).should.be.false
+ eql(a,[1,2]).should.be.false
+ })
+
+ it('should be comparable to an Object', function () {
+ eql(a, {0:1,1:2,2:3,length:3}).should.be.true
+ eql(a, {0:1,1:2,2:3,length:4}).should.be.false
+ eql(a, {0:1,1:2,2:4,length:3}).should.be.false
+ eql(a, {0:1,1:2,length:2}).should.be.false
+ }).skip()
+})
+
+describe('Numbers', function () {
+ it('should not coerce strings', function () {
+ eql('1', 1).should.equal(false)
+ })
+ it('-0 should equal +0', function () {
+ eql(-0, +0).should.be.true
+ })
+ describe('NaN', function () {
+ it('should equal Nan', function () {
+ eql(NaN, NaN).should.be.true
+ })
+ it('NaN should not equal undefined', function () {
+ eql(NaN, undefined).should.be.false
+ })
+ it('NaN should not equal null', function () {
+ eql(NaN, null).should.be.false
+ })
+ it('NaN should not equal empty string', function () {
+ eql(NaN, '').should.be.false
+ })
+ it('should not equal zero', function () {
+ eql(NaN, 0).should.be.false
+ })
+ })
+})
+
+describe('Strings', function () {
+ it('should be case sensitive', function () {
+ eql('hi', 'Hi').should.equal(false)
+ eql('hi', 'hi').should.equal(true)
+ })
+
+ it('empty string should equal empty string', function () {
+ eql('', "").should.be.true
+ })
+})
+
+describe('undefined', function () {
+ it('should equal only itself', function () {
+ eql(undefined, null).should.be.false
+ eql(undefined, '').should.be.false
+ eql(undefined, 0).should.be.false
+ eql(undefined, []).should.be.false
+ eql(undefined, undefined).should.be.true
+ eql(undefined, NaN).should.be.false
+ })
+})
+
+describe('null', function () {
+ it('should equal only itself', function () {
+ eql(null, undefined).should.be.false
+ eql(null, '').should.be.false
+ eql(null, 0).should.be.false
+ eql(null, []).should.be.false
+ eql(null, null).should.be.true
+ eql(null, NaN).should.be.false
+ })
+})
+
+describe('Cyclic structures', function () {
+ it('should not go into an infinite loop', function () {
+ var a = {}
+ var b = {}
+ a.self = a
+ b.self = b
+ eql(a, b).should.equal(true)
+ })
+})
+
+describe('functions', function () {
+ it('should fail if they have different names', function () {
+ eql(function a() {}, function b() {}).should.be.false
+ })
+
+ it('should pass if they are both anonamous', function () {
+ eql(function () {}, function () {}).should.be.true
+ })
+
+ it('handle the case where they have different argument names', function () {
+ eql(function (b) {return b}, function (a) {return a}).should.be.true
+ }).skip()
+
+ it('should compare them as objects', function () {
+ var a = function () {}
+ var b = function () {}
+ a.title = 'sometitle'
+ eql(a, b).should.be.false
+ })
+
+ it('should compare their prototypes', function () {
+ var a = function () {}
+ var b = function () {}
+ a.prototype.a = 1
+ eql(a,b).should.be.false
+ })
+
+ it('should be able to compare object methods', function () {
+ eql(
+ {noop: function () {}},
+ {noop: function () {}}
+ ).should.be.true
+ eql(
+ {noop: function (a) {}},
+ {noop: function () {}}
+ ).should.be.false
+ })
+})
+
+describe('Buffer', function () {
+ it('should compare on content', function () {
+ eql(new Buffer('abc'), new Buffer('abc')).should.be.true
+ eql(new Buffer('a'), new Buffer('b')).should.be.false
+ eql(new Buffer('a'), new Buffer('ab')).should.be.false
+ })
+
+ it('should fail against anything other than a buffer', function () {
+ eql(new Buffer('abc'), [97,98,99]).should.be.false
+ eql(new Buffer('abc'), {0:97,1:98,2:99,length:3}).should.be.false
+ eql([97,98,99], new Buffer('abc')).should.be.false
+ eql({0:97,1:98,2:99,length:3}, new Buffer('abc')).should.be.false
+ })
+}).skip(typeof Buffer == 'undefined')
+
+describe('possible regressions', function () {
+ it('should handle objects with no constructor property', function () {
+ var a = Object.create(null)
+ eql(a, {}).should.be.true
+ eql({}, a).should.be.true
+ eql(a, {a:1}).should.be.false
+ eql({a:1}, a).should.be.false
+ })
+
+ it('when comparing primitives to composites', function () {
+ eql({}, undefined).should.be.false
+ eql(undefined, {}).should.be.false
+
+ eql(new String, {}).should.be.false
+ eql({}, new String).should.be.false
+
+ eql({}, new Number).should.be.false
+ eql(new Number, {}).should.be.false
+
+ eql(new Boolean, {}).should.be.false
+ eql({}, new Boolean).should.be.false
+
+ eql(new Date, {}).should.be.false
+ eql({}, new Date).should.be.false
+
+ eql(new RegExp, {}).should.be.false
+ eql({}, new RegExp).should.be.false
+ })
+})
diff --git a/components/jkroso-equals@1.0.0/test/hydro.conf.js b/components/jkroso-equals@1.0.0/test/hydro.conf.js
new file mode 100644
index 000000000..ac262db57
--- /dev/null
+++ b/components/jkroso-equals@1.0.0/test/hydro.conf.js
@@ -0,0 +1,22 @@
+
+/**
+ * Hydro configuration
+ *
+ * @param {Hydro} hydro
+ */
+
+module.exports = function(hydro) {
+ hydro.set({
+ suite: 'equals',
+ timeout: 500,
+ plugins: [
+ require('hydro-chai'),
+ require('hydro-bdd')
+ ],
+ chai: {
+ chai: require('chai'),
+ styles: ['should'],
+ stack: true
+ }
+ })
+}
diff --git a/components/jkroso-equals@1.0.0/test/index.html b/components/jkroso-equals@1.0.0/test/index.html
new file mode 100644
index 000000000..0347d0080
--- /dev/null
+++ b/components/jkroso-equals@1.0.0/test/index.html
@@ -0,0 +1,18 @@
+
+equals tests
+
+
+
+
+
diff --git a/components/jkroso-type@1.1.0/.gitignore b/components/jkroso-type@1.1.0/.gitignore
new file mode 100644
index 000000000..665aa2197
--- /dev/null
+++ b/components/jkroso-type@1.1.0/.gitignore
@@ -0,0 +1,3 @@
+components
+build
+node_modules
diff --git a/components/jkroso-type@1.1.0/History.md b/components/jkroso-type@1.1.0/History.md
new file mode 100644
index 000000000..e26eb876e
--- /dev/null
+++ b/components/jkroso-type@1.1.0/History.md
@@ -0,0 +1,10 @@
+
+1.1.0 / 2014-02-20
+==================
+
+ * return 'bit-array' for all types of bit array
+
+1.0.0
+==================
+
+ * initial
\ No newline at end of file
diff --git a/components/jkroso-type@1.1.0/License b/components/jkroso-type@1.1.0/License
new file mode 100644
index 000000000..c9b77ebb4
--- /dev/null
+++ b/components/jkroso-type@1.1.0/License
@@ -0,0 +1,23 @@
+
+The MIT License
+
+Copyright (c) 2013 Jake Rosoman
+
+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/components/jkroso-type@1.1.0/Makefile b/components/jkroso-type@1.1.0/Makefile
new file mode 100644
index 000000000..6097f2dcc
--- /dev/null
+++ b/components/jkroso-type@1.1.0/Makefile
@@ -0,0 +1,17 @@
+REPORTER=dot
+
+serve: node_modules
+ @node_modules/serve/bin/serve -Slojp 0
+
+test: node_modules
+ @node_modules/mocha/bin/mocha test/*.test.js \
+ --reporter $(REPORTER) \
+ --timeout 500 \
+ --check-leaks \
+ --bail
+ @sed "s/'type/'.\//" Readme.md | node_modules/jsmd/bin/jsmd
+
+node_modules: package.json
+ @packin install --meta $< --folder $@
+
+.PHONY: serve test
\ No newline at end of file
diff --git a/components/jkroso-type@1.1.0/Readme.md b/components/jkroso-type@1.1.0/Readme.md
new file mode 100644
index 000000000..ac4cf13bb
--- /dev/null
+++ b/components/jkroso-type@1.1.0/Readme.md
@@ -0,0 +1,34 @@
+# type
+
+ Type assertions aka less-broken `typeof`.
+
+## Example
+
+```js
+var type = require('type');
+
+var obj = new Date;
+if (type(obj) == 'date') ...
+```
+
+## API
+
+```js
+type(new Date) == 'date'
+type({}) == 'object'
+type(null) == 'null'
+type(undefined) == 'undefined'
+type("hey") == 'string'
+type(true) == 'boolean'
+type(false) == 'boolean'
+type(12) == 'number'
+type(type) == 'function'
+type(/asdf/) == 'regexp'
+type((function(){ return arguments })()) == 'arguments'
+type([]) == 'array'
+type(document.createElement('div')) == 'element'
+```
+
+## License
+
+ MIT
diff --git a/components/jkroso-type@1.1.0/component.json b/components/jkroso-type@1.1.0/component.json
new file mode 100644
index 000000000..cc7616ae3
--- /dev/null
+++ b/components/jkroso-type@1.1.0/component.json
@@ -0,0 +1,7 @@
+{
+ "name": "type",
+ "description": "less broken typeof",
+ "keywords": ["typeof", "type", "utility"],
+ "dependencies": {},
+ "scripts": ["index.js"]
+}
diff --git a/components/jkroso-type@1.1.0/index.js b/components/jkroso-type@1.1.0/index.js
new file mode 100644
index 000000000..823c95731
--- /dev/null
+++ b/components/jkroso-type@1.1.0/index.js
@@ -0,0 +1,50 @@
+
+var toString = {}.toString
+var DomNode = typeof window != 'undefined'
+ ? window.Node
+ : Function
+
+/**
+ * Return the type of `val`.
+ *
+ * @param {Mixed} val
+ * @return {String}
+ * @api public
+ */
+
+module.exports = exports = function(x){
+ var type = typeof x
+ if (type != 'object') return type
+ type = types[toString.call(x)]
+ if (type) return type
+ if (x instanceof DomNode) switch (x.nodeType) {
+ case 1: return 'element'
+ case 3: return 'text-node'
+ case 9: return 'document'
+ case 11: return 'document-fragment'
+ default: return 'dom-node'
+ }
+}
+
+var types = exports.types = {
+ '[object Function]': 'function',
+ '[object Date]': 'date',
+ '[object RegExp]': 'regexp',
+ '[object Arguments]': 'arguments',
+ '[object Array]': 'array',
+ '[object String]': 'string',
+ '[object Null]': 'null',
+ '[object Undefined]': 'undefined',
+ '[object Number]': 'number',
+ '[object Boolean]': 'boolean',
+ '[object Object]': 'object',
+ '[object Text]': 'text-node',
+ '[object Uint8Array]': 'bit-array',
+ '[object Uint16Array]': 'bit-array',
+ '[object Uint32Array]': 'bit-array',
+ '[object Uint8ClampedArray]': 'bit-array',
+ '[object Error]': 'error',
+ '[object FormData]': 'form-data',
+ '[object File]': 'file',
+ '[object Blob]': 'blob'
+}
diff --git a/components/jkroso-type@1.1.0/package.json b/components/jkroso-type@1.1.0/package.json
new file mode 100644
index 000000000..f71e80c8f
--- /dev/null
+++ b/components/jkroso-type@1.1.0/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "type",
+ "description": "less broken typeof",
+ "version": "1.1.0",
+ "dependencies": {},
+ "devDependencies": {
+ "assert": "jkroso/assert#0.2.1",
+ "serve": "jkroso/serve#1.5.3",
+ "mocha": "*",
+ "jsmd": "*"
+ },
+ "keywords": ["typeof", "type", "utility"],
+ "files": ["index.js"]
+}
diff --git a/components/jkroso-type@1.1.0/test/index.html b/components/jkroso-type@1.1.0/test/index.html
new file mode 100644
index 000000000..9ddb06e2f
--- /dev/null
+++ b/components/jkroso-type@1.1.0/test/index.html
@@ -0,0 +1,17 @@
+
+
+ Mocha
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/jkroso-type@1.1.0/test/mocha.css b/components/jkroso-type@1.1.0/test/mocha.css
new file mode 100644
index 000000000..3b8afb1a0
--- /dev/null
+++ b/components/jkroso-type@1.1.0/test/mocha.css
@@ -0,0 +1,231 @@
+@charset "utf-8";
+
+body {
+ font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ padding: 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;
+}
+
+.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;
+}
+
+#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: white;
+ -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;
+}
+
+#mocha .test pre {
+ display: block;
+ float: left;
+ clear: left;
+ font: 12px/1.5 monaco, monospace;
+ margin: 5px;
+ padding: 15px;
+ border: 1px solid #eee;
+ 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;
+}
+
+#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-error {
+ color: #c00;
+ font-size: 1.5 em;
+ font-weight: 100;
+ letter-spacing: 1px;
+}
+
+#mocha-stats {
+ position: fixed;
+ top: 15px;
+ right: 10px;
+ font-size: 12px;
+ margin: 0;
+ color: #888;
+}
+
+#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;
+}
+
+code .comment { color: #ddd }
+code .init { color: #2F6FAD }
+code .string { color: #5890AD }
+code .keyword { color: #8A6343 }
+code .number { color: #2F6FAD }
diff --git a/components/jkroso-type@1.1.0/test/mocha.js b/components/jkroso-type@1.1.0/test/mocha.js
new file mode 100644
index 000000000..2e40cae64
--- /dev/null
+++ b/components/jkroso-type@1.1.0/test/mocha.js
@@ -0,0 +1,5340 @@
+;(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.txt for terms of usage */
+
+/*
+ * 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() {
+ 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, "&");
+ n = n.replace(//g, ">");
+ n = n.replace(/"/g, """);
+
+ return n;
+ }
+
+
+ var fbDiff = function(ignoreWhitespace) {
+ this.ignoreWhitespace = ignoreWhitespace;
+ };
+ fbDiff.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 fbDiff();
+
+ var WordDiff = new fbDiff(true);
+ WordDiff.tokenize = function(value) {
+ return removeEmpty(value.split(/(\s+|\b)/));
+ };
+
+ var CssDiff = new fbDiff(true);
+ CssDiff.tokenize = function(value) {
+ return removeEmpty(value.split(/([{}:;,]|\s+)/));
+ };
+
+ var LineDiff = new fbDiff();
+ LineDiff.tokenize = function(value) {
+ return value.split(/^/m);
+ };
+
+ return {
+ diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
+ diffWords: function(oldStr, newStr) { return WordDiff.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';
+ },
+
+ convertChangesToXML: function(changes){
+ var ret = [];
+ for ( var i = 0; i < changes.length; i++) {
+ var change = changes[i];
+ if (change.added) {
+ ret.push("");
+ } else if (change.removed) {
+ ret.push("");
+ }
+
+ ret.push(escapeHTML(change.value));
+
+ if (change.added) {
+ ret.push(" ");
+ } else if (change.removed) {
+ ret.push("");
+ }
+ }
+ return ret.join("");
+ }
+ };
+})();
+
+if (typeof module !== "undefined") {
+ module.exports = JsDiff;
+}
+
+}); // module: browser/diff.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/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){
+ 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);
+
+ return this;
+};
+
+}); // module: browser/progress.js
+
+require.register("browser/tty.js", function(module, exports, require){
+
+exports.isatty = function(){
+ return true;
+};
+
+exports.getWindowSize = function(){
+ return [window.innerHeight, window.innerWidth];
+};
+}); // 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){
+ this.runnable().timeout(ms);
+ 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');
+
+/**
+ * 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(fn){
+ suites[0].beforeAll(fn);
+ };
+
+ /**
+ * Execute after running tests.
+ */
+
+ context.after = function(fn){
+ suites[0].afterAll(fn);
+ };
+
+ /**
+ * Execute before each test case.
+ */
+
+ context.beforeEach = function(fn){
+ suites[0].beforeEach(fn);
+ };
+
+ /**
+ * Execute after each test case.
+ */
+
+ context.afterEach = function(fn){
+ suites[0].afterEach(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);
+ 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());
+ };
+
+ /**
+ * 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) var fn = null;
+ var test = new Test(title, fn);
+ suite.addTest(test);
+ return test;
+ };
+
+ /**
+ * Exclusive test-case.
+ */
+
+ context.it.only = function(title, fn){
+ var test = context.it(title, fn);
+ mocha.grep(test.fullTitle());
+ };
+
+ /**
+ * 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) {
+ 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:
+ suites[0].addTest(new Test(key, fn));
+ }
+ } else {
+ var 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');
+
+/**
+ * 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){
+
+ /**
+ * Execute before running tests.
+ */
+
+ context.before = function(fn){
+ suites[0].beforeAll(fn);
+ };
+
+ /**
+ * Execute after running tests.
+ */
+
+ context.after = function(fn){
+ suites[0].afterAll(fn);
+ };
+
+ /**
+ * Execute before each test case.
+ */
+
+ context.beforeEach = function(fn){
+ suites[0].beforeEach(fn);
+ };
+
+ /**
+ * Execute after each test case.
+ */
+
+ context.afterEach = function(fn){
+ suites[0].afterEach(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);
+ suites.unshift(suite);
+ };
+
+ /**
+ * Describe a specification or test-case
+ * with the given `title` and callback `fn`
+ * acting as a thunk.
+ */
+
+ context.test = function(title, fn){
+ suites[0].addTest(new Test(title, fn));
+ };
+ });
+};
+
+}); // module: interfaces/qunit.js
+
+require.register("interfaces/tdd.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+ , Test = require('../test');
+
+/**
+ * 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(fn){
+ suites[0].beforeEach(fn);
+ };
+
+ /**
+ * Execute after each test case.
+ */
+
+ context.teardown = function(fn){
+ suites[0].afterEach(fn);
+ };
+
+ /**
+ * Execute before the suite.
+ */
+
+ context.suiteSetup = function(fn){
+ suites[0].beforeAll(fn);
+ };
+
+ /**
+ * Execute after the suite.
+ */
+
+ context.suiteTeardown = function(fn){
+ suites[0].afterAll(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);
+ suites.unshift(suite);
+ fn.call(suite);
+ suites.shift();
+ 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);
+ suites[0].addTest(test);
+ return test;
+ };
+
+ /**
+ * Exclusive test-case.
+ */
+
+ context.test.only = function(title, fn){
+ var test = context.test(title, fn);
+ mocha.grep(test.fullTitle());
+ };
+
+ /**
+ * 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
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var path = require('browser/path')
+ , utils = require('./utils');
+
+/**
+ * Expose `Mocha`.
+ */
+
+exports = module.exports = Mocha;
+
+/**
+ * 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.Dot`
+ * - `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 (options.timeout) this.timeout(options.timeout);
+ if (options.slow) this.slow(options.slow);
+}
+
+/**
+ * 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 "dot".
+ *
+ * @param {String|Function} reporter name or constructor
+ * @api public
+ */
+
+Mocha.prototype.reporter = function(reporter){
+ if ('function' == typeof reporter) {
+ this._reporter = reporter;
+ } else {
+ reporter = reporter || 'dot';
+ try {
+ this._reporter = require('./reporters/' + reporter);
+ } catch (err) {
+ this._reporter = require(reporter);
+ }
+ if (!this._reporter) throw new Error('invalid 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) 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(utils.escapeRegexp(re))
+ : re;
+ return this;
+};
+
+/**
+ * Invert `.grep()` matches.
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.invert = function(){
+ this.options.invert = true;
+ return this;
+};
+
+/**
+ * Ignore global leaks.
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.ignoreLeaks = function(){
+ this.options.ignoreLeaks = true;
+ 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;
+};
+
+/**
+ * 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;
+};
+
+/**
+ * Makes all tests async (accepting a callback)
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.asyncOnly = function(){
+ this.options.asyncOnly = 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;
+ var runner = new exports.Runner(suite);
+ var reporter = new this._reporter(runner);
+ runner.ignoreLeaks = 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);
+ 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;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * @param {String|Number} val
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val){
+ if ('string' == typeof val) return parse(val);
+ return format(val);
+}
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+ var m = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
+ if (!m) return;
+ var n = parseFloat(m[1]);
+ var type = (m[2] || 'ms').toLowerCase();
+ switch (type) {
+ case 'years':
+ case 'year':
+ case 'y':
+ return n * 31557600000;
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * 86400000;
+ case 'hours':
+ case 'hour':
+ case 'h':
+ return n * 3600000;
+ case 'minutes':
+ case 'minute':
+ case 'm':
+ return n * 60000;
+ case 'seconds':
+ case 'second':
+ case 's':
+ return n * 1000;
+ case 'ms':
+ return n;
+ }
+}
+
+/**
+ * Format the given `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api public
+ */
+
+function format(ms) {
+ if (ms == d) return Math.round(ms / d) + ' day';
+ if (ms > d) return Math.round(ms / d) + ' days';
+ if (ms == h) return Math.round(ms / h) + ' hour';
+ if (ms > h) return Math.round(ms / h) + ' hours';
+ if (ms == m) return Math.round(ms / m) + ' minute';
+ if (ms > m) return Math.round(ms / m) + ' minutes';
+ if (ms == s) return Math.round(ms / s) + ' second';
+ if (ms > s) return Math.round(ms / s) + ' seconds';
+ return ms + ' ms';
+}
+}); // 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');
+
+/**
+ * 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;
+
+/**
+ * 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(){
+ process.stdout.write('\u001b[?25l');
+ },
+
+ show: function(){
+ process.stdout.write('\u001b[?25h');
+ },
+
+ deleteLine: function(){
+ process.stdout.write('\u001b[2K');
+ },
+
+ beginningOfLine: function(){
+ process.stdout.write('\u001b[0G');
+ },
+
+ CR: function(){
+ exports.cursor.deleteLine();
+ exports.cursor.beginningOfLine();
+ }
+};
+
+/**
+ * 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;
+
+ // explicitly show diff
+ if (err.showDiff) {
+ escape = false;
+ err.actual = actual = JSON.stringify(actual, null, 2);
+ err.expected = expected = JSON.stringify(expected, null, 2);
+ }
+
+ // actual / expected diff
+ if ('string' == typeof actual && 'string' == typeof expected) {
+ var len = Math.max(actual.length, expected.length);
+
+ if (len < 20) msg = errorDiff(err, 'Chars', escape);
+ else msg = errorDiff(err, 'Words', 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, ' ');
+
+ fmt = color('error title', ' %s) %s:\n%s')
+ + color('error stack', '\n%s\n');
+ }
+
+ // 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
+ , fmt
+ , tests;
+
+ console.log();
+
+ function pluralize(n) {
+ return 1 == n ? 'test' : 'tests';
+ }
+
+ // failure
+ if (stats.failures) {
+ fmt = color('bright fail', ' ' + exports.symbols.err)
+ + color('fail', ' %d of %d %s failed')
+ + color('light', ':')
+
+ console.error(fmt,
+ stats.failures,
+ this.runner.total,
+ pluralize(this.runner.total));
+
+ Base.list(this.failures);
+ console.error();
+ return;
+ }
+
+ // pass
+ fmt = color('bright pass', ' ')
+ + color('green', ' %d %s complete')
+ + color('light', ' (%s)');
+
+ console.log(fmt,
+ stats.tests || 0,
+ pluralize(stats.tests),
+ ms(stats.duration));
+
+ // pending
+ if (stats.pending) {
+ fmt = color('pending', ' ')
+ + color('pending', ' %d %s pending');
+
+ console.log(fmt, stats.pending, pluralize(stats.pending));
+ }
+
+ 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;
+}
+
+/**
+ * Return a character diff for `err`.
+ *
+ * @param {Error} err
+ * @return {String}
+ * @api private
+ */
+
+function errorDiff(err, type, escape) {
+ return diff['diff' + type](err.actual, err.expected).map(function(str){
+ if (escape) {
+ str.value = str.value
+ .replace(/\t/g, '')
+ .replace(/\r/g, '')
+ .replace(/\n/g, '\n');
+ }
+ if (str.added) return colorLines('diff added', str.value);
+ if (str.removed) return colorLines('diff removed', str.value);
+ return str.value;
+ }).join('');
+}
+
+/**
+ * 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');
+}
+
+}); // 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', indent());
+ ++indents;
+ console.log('%s%s ', indent(), utils.escape(suite.title));
+ console.log('%s', indent());
+ });
+
+ runner.on('suite end', function(suite){
+ if (suite.root) return;
+ console.log('%s ', indent());
+ --indents;
+ console.log('%s ', indent());
+ --indents;
+ });
+
+ runner.on('pass', function(test){
+ console.log('%s %s ', indent(), utils.escape(test.title));
+ var code = utils.escape(utils.clean(test.fn.toString()));
+ console.log('%s %s
', indent(), code);
+ });
+}
+
+}); // 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 = 0;
+
+ runner.on('start', function(){
+ process.stdout.write('\n ');
+ });
+
+ runner.on('pending', function(test){
+ 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 `Doc`.
+ */
+
+exports = module.exports = HTML;
+
+/**
+ * Stats template.
+ */
+
+var statsTemplate = '';
+
+/**
+ * Initialize a new `Doc` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function HTML(runner, root) {
+ 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('')
+ , stack = [report]
+ , progress
+ , ctx
+
+ root = 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 = '?grep=' + encodeURIComponent(suite.fullTitle());
+ var el = fragment(' ', 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){
+ window.scrollTo(0, document.body.scrollHeight);
+
+ // 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 el = fragment('%e%ems ‣ ', test.speed, test.title, test.duration, encodeURIComponent(test.fullTitle()));
+ } else if (test.pending) {
+ var el = fragment('%e ', test.title);
+ } else {
+ var el = fragment(' ', 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('%e ', 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('%e
', 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);
+ });
+}
+
+/**
+ * Display error `msg`.
+ */
+
+function error(msg) {
+ document.body.appendChild(fragment('%s
', 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');
+exports.Teamcity = require('./teamcity');
+
+}); // 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){
+ console.log(JSON.stringify(['fail', clean(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 = []
+ , 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 obj = {
+ stats: self.stats
+ , tests: tests.map(clean)
+ , failures: failures.map(clean)
+ , passes: passes.map(clean)
+ };
+
+ 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
+ }
+}
+}); // 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 ');
+ 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[4F\n\n');
+ 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 += ' ' + '\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('start');
+ });
+
+ runner.on('pending', function(test){
+ self.draw('pending');
+ });
+
+ runner.on('pass', function(test){
+ self.draw('pass');
+ });
+
+ runner.on('fail', function(test, err){
+ self.draw('fail');
+ });
+
+ runner.on('end', function(){
+ Base.cursor.show();
+ for (var i = 0; i < self.numberOfLines; i++) write('\n');
+ self.epilogue();
+ });
+}
+
+/**
+ * Draw the nyan cat with runner `status`.
+ *
+ * @param {String} status
+ * @api private
+ */
+
+NyanCat.prototype.draw = function(status){
+ this.appendRainbow();
+ this.drawScoreboard();
+ this.drawRainbow();
+ this.drawNyanCat(status);
+ 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 with `status`.
+ *
+ * @param {String} status
+ * @api private
+ */
+
+NyanCat.prototype.drawNyanCat = function(status) {
+ var self = this;
+ var startWidth = this.scoreboardWidth + this.trajectories[0].length;
+
+ [0, 1, 2, 3].forEach(function(index) {
+ write('\u001b[' + startWidth + 'C');
+
+ switch (index) {
+ case 0:
+ write('_,------,');
+ write('\n');
+ break;
+ case 1:
+ var padding = self.tick ? ' ' : ' ';
+ write('_|' + padding + '/\\_/\\ ');
+ write('\n');
+ break;
+ case 2:
+ var padding = self.tick ? '_' : '__';
+ var tail = self.tick ? '~' : '^';
+ var face;
+ switch (status) {
+ case 'pass':
+ face = '( ^ .^)';
+ break;
+ case 'fail':
+ face = '( o .o)';
+ break;
+ default:
+ face = '( - .-)';
+ }
+ write(tail + '|' + padding + face + ' ');
+ write('\n');
+ break;
+ case 3:
+ var padding = self.tick ? ' ' : ' ';
+ write(padding + '"" "" ');
+ write('\n');
+ break;
+ }
+ });
+
+ this.cursorUp(this.numberOfLines);
+};
+
+/**
+ * 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;
+
+ // 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;
+
+ 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('test', function(test){
+ process.stdout.write(indent() + color('pass', ' â—¦ ' + test.title + ': '));
+ });
+
+ 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/teamcity.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `Teamcity`.
+ */
+
+exports = module.exports = Teamcity;
+
+/**
+ * Initialize a new `Teamcity` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Teamcity(runner) {
+ Base.call(this, runner);
+ var stats = this.stats;
+
+ runner.on('start', function() {
+ console.log("##teamcity[testSuiteStarted name='mocha.suite']");
+ });
+
+ runner.on('test', function(test) {
+ console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']");
+ });
+
+ runner.on('fail', function(test, err) {
+ console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']");
+ });
+
+ runner.on('pending', function(test) {
+ console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']");
+ });
+
+ runner.on('test end', function(test) {
+ console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']");
+ });
+
+ runner.on('end', function() {
+ console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']");
+ });
+}
+
+/**
+ * Escape the given `str`.
+ */
+
+function escape(str) {
+ return str
+ .replace(/\|/g, "||")
+ .replace(/\n/g, "|n")
+ .replace(/\r/g, "|r")
+ .replace(/\[/g, "|[")
+ .replace(/\]/g, "|]")
+ .replace(/\u0085/g, "|x")
+ .replace(/\u2028/g, "|l")
+ .replace(/\u2029/g, "|p")
+ .replace(/'/g, "|'");
+}
+
+}); // module: reporters/teamcity.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('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
+ , skip: stats.tests - stats.failures - stats.passes
+ , timestamp: (new Date).toUTCString()
+ , time: stats.duration / 1000
+ }, false));
+
+ tests.forEach(test);
+ console.log('');
+ });
+}
+
+/**
+ * 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
+ };
+
+ if ('failed' == test.state) {
+ var err = test.err;
+ attrs.message = escape(err.message);
+ console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(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 '';
+}
+
+}); // 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.timedOut = false;
+}
+
+/**
+ * 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 ('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;
+};
+
+/**
+ * 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 '#';
+ if ('ctx' == key) return '#';
+ return val;
+ }, 2);
+};
+
+/**
+ * Reset the timeout.
+ *
+ * @api private
+ */
+
+Runnable.prototype.resetTimeout = function(){
+ var self = this
+ , ms = this.timeout();
+
+ this.clearTimeout();
+ if (ms) {
+ this.timer = setTimeout(function(){
+ self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
+ self.timedOut = true;
+ }, ms);
+ }
+};
+
+/**
+ * Run the test and invoke `fn(err)`.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+
+Runnable.prototype.run = function(fn){
+ var self = this
+ , ms = this.timeout()
+ , start = new Date
+ , ctx = this.ctx
+ , finished
+ , emitted;
+
+ if (ctx) ctx.runnable(this);
+
+ // timeout
+ if (this.async) {
+ if (ms) {
+ this.timer = setTimeout(function(){
+ done(new Error('timeout of ' + ms + 'ms exceeded'));
+ self.timedOut = true;
+ }, ms);
+ }
+ }
+
+ // called multiple times
+ function multiple(err) {
+ if (emitted) return;
+ emitted = true;
+ self.emit('error', err || new Error('done() called multiple times'));
+ }
+
+ // finished
+ function done(err) {
+ if (self.timedOut) return;
+ if (finished) return multiple(err);
+ self.clearTimeout();
+ self.duration = new Date - start;
+ finished = true;
+ fn(err);
+ }
+
+ // for .resetTimeout()
+ this.callback = done;
+
+ // async
+ if (this.async) {
+ try {
+ this.fn.call(ctx, function(err){
+ if (err instanceof Error || toString.call(err) === "[object Error]") return done(err);
+ if (null != err) 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
+ try {
+ if (!this.pending) this.fn.call(ctx);
+ this.duration = new Date - start;
+ fn();
+ } catch (err) {
+ fn(err);
+ }
+};
+
+}); // 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
+ , noop = function(){};
+
+/**
+ * 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
+ *
+ * @api public
+ */
+
+function Runner(suite) {
+ var self = this;
+ this._globals = [];
+ 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(['errno']));
+}
+
+/**
+ * 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);
+ utils.forEach(arr, function(arr){
+ this._globals.push(arr);
+ }, this);
+ 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 isNode = process.kill;
+ var leaks;
+
+ // check length - 2 ('errno' and 'location' globals)
+ if (isNode && 1 == ok.length - globals.length) return
+ else if (2 == ok.length - globals.length) return;
+
+ 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 (currently) hard-end due
+ * to that fact that a failing hook will
+ * surely cause subsequent tests to fail,
+ * causing jumbled reporting.
+ *
+ * @param {Hook} hook
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.failHook = function(hook, err){
+ this.fail(hook, err);
+ 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();
+ self.currentRunnable = hook;
+
+ 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) return self.failHook(hook, err);
+ self.emit('hook end', hook);
+ next(++i);
+ });
+ }
+
+ process.nextTick(function(){
+ next(0);
+ });
+};
+
+/**
+ * Run hook `name` for the given array of `suites`
+ * in order, and callback `fn(err)`.
+ *
+ * @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) {
+ self.suite = orig;
+ return fn(err);
+ }
+
+ 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 next(err) {
+ // if we bail after first err
+ if (self.failures && suite._bail) return fn();
+
+ // 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(){
+ 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() {
+ var curr = suite.suites[i++];
+ if (!curr) return done();
+ self.runSuite(curr, next);
+ }
+
+ function done() {
+ self.suite = suite;
+ self.hook('afterAll', function(){
+ self.emit('suite end', suite);
+ fn();
+ });
+ }
+
+ this.hook('beforeAll', function(){
+ self.runTests(suite, next);
+ });
+};
+
+/**
+ * Handle uncaught exceptions.
+ *
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.uncaught = function(err){
+ debug('uncaught exception %s', err.message);
+ var runnable = this.currentRunnable;
+ if (!runnable || 'failed' == runnable.state) return;
+ runnable.clearTimeout();
+ err.uncaught = true;
+ this.fail(runnable, err);
+
+ // 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(){};
+
+ debug('start');
+
+ // callback
+ this.on('end', function(){
+ debug('end');
+ process.removeListener('uncaughtException', function(err){
+ self.uncaught(err);
+ });
+ fn(self.failures);
+ });
+
+ // run suites
+ this.emit('start');
+ this.runSuite(this.suite, function(){
+ debug('finished running');
+ self.emit('end');
+ });
+
+ // uncaught exception
+ process.on('uncaughtException', function(err){
+ self.uncaught(err);
+ });
+
+ return this;
+};
+
+/**
+ * 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){
+ var matched = filter(ok, function(ok){
+ if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);
+ // Opera and IE expose global variables for HTML element IDs (issue #243)
+ if (/^mocha-/.test(key)) return true;
+ return key == ok;
+ });
+ return matched.length == 0 && (!global.navigator || 'onerror' !== key);
+ });
+}
+
+}); // 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, ctx) {
+ this.title = title;
+ this.ctx = ctx;
+ this.suites = [];
+ this.tests = [];
+ this.pending = false;
+ this._beforeEach = [];
+ this._beforeAll = [];
+ this._afterEach = [];
+ this._afterAll = [];
+ this.root = !title;
+ this._timeout = 2000;
+ 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.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 ('string' == typeof ms) ms = milliseconds(ms);
+ debug('timeout %d', ms);
+ this._timeout = parseInt(ms, 10);
+ 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(fn){
+ if (this.pending) return this;
+ var hook = new Hook('"before all" hook', fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ 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(fn){
+ if (this.pending) return this;
+ var hook = new Hook('"after all" hook', fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ 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(fn){
+ if (this.pending) return this;
+ var hook = new Hook('"before each" hook', fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ 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(fn){
+ if (this.pending) return this;
+ var hook = new Hook('"after each" hook', fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ 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.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.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')
+ , 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, '&')
+ .replace(/"/g, '"')
+ .replace(//g, '>');
+};
+
+/**
+ * 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#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, ret){
+ ret = ret || [];
+
+ fs.readdirSync(dir)
+ .filter(ignored)
+ .forEach(function(path){
+ path = join(dir, path);
+ if (fs.statSync(path).isDirectory()) {
+ exports.files(path, ret);
+ } else if (path.match(/\.(js|coffee)$/)) {
+ 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(/^function *\(.*\) *{/, '')
+ .replace(/\s+\}$/, '');
+
+ var spaces = str.match(/^\n?( *)/)[1].length
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
+
+ str = str.replace(re, '');
+
+ return exports.trim(str);
+};
+
+/**
+ * Escape regular expression characters in `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+exports.escapeRegexp = function(str){
+ return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
+};
+
+/**
+ * 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, '>')
+ .replace(/\/\/(.*)/gm, '')
+ .replace(/('.*?')/gm, '$1 ')
+ .replace(/(\d+\.\d+)/gm, '$1 ')
+ .replace(/(\d+)/gm, '$1 ')
+ .replace(/\bnew *(\w+)/gm, 'new $1 ')
+ .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1 ')
+}
+
+/**
+ * Highlight the contents of tag `name`.
+ *
+ * @param {String} name
+ * @api private
+ */
+
+exports.highlightTags = function(name) {
+ var code = document.getElementsByTagName(name);
+ for (var i = 0, len = code.length; i < len; ++i) {
+ code[i].innerHTML = highlight(code[i].innerHTML);
+ }
+};
+
+}); // module: utils.js
+/**
+ * Node shims.
+ *
+ * These are meant only to allow
+ * mocha.js to run untouched, not
+ * to allow running node code in
+ * the browser.
+ */
+
+process = {};
+process.exit = function(status){};
+process.stdout = {};
+global = window;
+
+/**
+ * next tick implementation.
+ */
+
+process.nextTick = (function(){
+ // postMessage behaves badly on IE8
+ if (window.ActiveXObject || !window.postMessage) {
+ return function(fn){ fn() };
+ }
+
+ // based on setZeroTimeout by David Baron
+ // - http://dbaron.org/log/20100309-faster-timeouts
+ var timeouts = []
+ , name = 'mocha-zero-timeout'
+
+ window.addEventListener('message', function(e){
+ if (e.source == window && e.data == name) {
+ if (e.stopPropagation) e.stopPropagation();
+ if (timeouts.length) timeouts.shift()();
+ }
+ }, true);
+
+ return function(fn){
+ timeouts.push(fn);
+ window.postMessage(name, '*');
+ }
+})();
+
+/**
+ * Remove uncaughtException listener.
+ */
+
+process.removeListener = function(e){
+ if ('uncaughtException' == e) {
+ window.onerror = null;
+ }
+};
+
+/**
+ * Implements uncaughtException listener.
+ */
+
+process.on = function(e, fn){
+ if ('uncaughtException' == e) {
+ window.onerror = function(err, url, line){
+ fn(new Error(err + ' (' + url + ':' + line + ')'));
+ };
+ }
+};
+
+// boot
+;(function(){
+
+ /**
+ * Expose mocha.
+ */
+
+ var Mocha = window.Mocha = require('mocha'),
+ mocha = window.mocha = new Mocha({ reporter: 'html' });
+
+ /**
+ * 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', window, 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(window.location.search || '');
+ if (query.grep) mocha.grep(query.grep);
+ if (query.invert) mocha.invert();
+
+ return Mocha.prototype.run.call(mocha, function(){
+ Mocha.utils.highlightTags('code');
+ if (fn) fn();
+ });
+ };
+})();
+})();
\ No newline at end of file
diff --git a/components/jkroso-type@1.1.0/test/type.test.js b/components/jkroso-type@1.1.0/test/type.test.js
new file mode 100644
index 000000000..35ef2079b
--- /dev/null
+++ b/components/jkroso-type@1.1.0/test/type.test.js
@@ -0,0 +1,91 @@
+
+var assert = require('assert/index')
+var type = require('..')
+
+describe('type', function(){
+ it('should match objects', function(){
+ function Foo(){}
+ assert('object' === type({}))
+ assert('object' === type(new Foo))
+ })
+
+ it('should match numbers', function(){
+ assert('number' === type(12))
+ assert('number' === type(new Number(12)))
+ })
+
+ it('should match strings', function(){
+ assert('string' === type("test"))
+ assert('string' === type(new String('whoop')))
+ })
+
+ it('should match dates', function(){
+ assert('date' === type(new Date))
+ })
+
+ it('should match booleans', function(){
+ assert('boolean' === type(true))
+ assert('boolean' === type(false))
+ assert('boolean' === type(new Boolean(false)))
+ })
+
+ it('should match null', function(){
+ assert('null' === type(null))
+ })
+
+ it('should match undefined', function(){
+ assert('undefined' === type(undefined))
+ })
+
+ it('should match arrays', function(){
+ assert('array' === type([]))
+ })
+
+ it('should match regexps', function(){
+ assert('regexp' === type(/asdf/))
+ assert('regexp' === type(new RegExp('weee')))
+ })
+
+ it('should match functions', function(){
+ assert('function' === type(function(){}))
+ })
+
+ it('should match arguments', function(){
+ assert('arguments' === type((function(){ return arguments })()))
+ })
+
+ it('should match typed arrays', function () {
+ assert('bit-array' === type(new Uint8Array))
+ assert('bit-array' === type(new Uint16Array))
+ assert('bit-array' === type(new Uint32Array))
+ })
+
+ it('should match errors', function(){
+ assert('error' === type(new Error))
+ assert('error' === type(new TypeError))
+ assert('error' === type(new RangeError))
+ assert('error' === type(new SyntaxError))
+ })
+
+ if (typeof window != 'undefined') describe('in browsers', function(){
+ it('should match elements', function(){
+ assert('element' === type(document.createElement('div')))
+ })
+
+ it('should match textnodes', function(){
+ assert('text-node' === type(document.createTextNode('div')))
+ })
+
+ if (typeof FormData == 'function') it('should match from data', function(){
+ assert('form-data' === type(new FormData))
+ })
+
+ if (typeof File == 'function') it.skip('should match files', function(){
+ assert('file' === type(new File)) // TODO: fix test
+ })
+
+ if (typeof Blob == 'function') it('should match blobs', function(){
+ assert('blob' === type(new Blob))
+ })
+ })
+})
diff --git a/components/rauchg-ms.js@0.7.1/.gitignore b/components/rauchg-ms.js@0.7.1/.gitignore
new file mode 100644
index 000000000..3c3629e64
--- /dev/null
+++ b/components/rauchg-ms.js@0.7.1/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/components/rauchg-ms.js@0.7.1/.npmignore b/components/rauchg-ms.js@0.7.1/.npmignore
new file mode 100644
index 000000000..d1aa0ce42
--- /dev/null
+++ b/components/rauchg-ms.js@0.7.1/.npmignore
@@ -0,0 +1,5 @@
+node_modules
+test
+History.md
+Makefile
+component.json
diff --git a/components/rauchg-ms.js@0.7.1/History.md b/components/rauchg-ms.js@0.7.1/History.md
new file mode 100644
index 000000000..32fdfc176
--- /dev/null
+++ b/components/rauchg-ms.js@0.7.1/History.md
@@ -0,0 +1,66 @@
+
+0.7.1 / 2015-04-20
+==================
+
+ * prevent extraordinary long inputs (@evilpacket)
+ * Fixed broken readme link
+
+0.7.0 / 2014-11-24
+==================
+
+ * add time abbreviations, updated tests and readme for the new units
+ * fix example in the readme.
+ * add LICENSE file
+
+0.6.2 / 2013-12-05
+==================
+
+ * Adding repository section to package.json to suppress warning from NPM.
+
+0.6.1 / 2013-05-10
+==================
+
+ * fix singularization [visionmedia]
+
+0.6.0 / 2013-03-15
+==================
+
+ * fix minutes
+
+0.5.1 / 2013-02-24
+==================
+
+ * add component namespace
+
+0.5.0 / 2012-11-09
+==================
+
+ * add short formatting as default and .long option
+ * add .license property to component.json
+ * add version to component.json
+
+0.4.0 / 2012-10-22
+==================
+
+ * add rounding to fix crazy decimals
+
+0.3.0 / 2012-09-07
+==================
+
+ * fix `ms()` [visionmedia]
+
+0.2.0 / 2012-09-03
+==================
+
+ * add component.json [visionmedia]
+ * add days support [visionmedia]
+ * add hours support [visionmedia]
+ * add minutes support [visionmedia]
+ * add seconds support [visionmedia]
+ * add ms string support [visionmedia]
+ * refactor tests to facilitate ms(number) [visionmedia]
+
+0.1.0 / 2012-03-07
+==================
+
+ * Initial release
diff --git a/components/rauchg-ms.js@0.7.1/LICENSE b/components/rauchg-ms.js@0.7.1/LICENSE
new file mode 100644
index 000000000..6c07561b6
--- /dev/null
+++ b/components/rauchg-ms.js@0.7.1/LICENSE
@@ -0,0 +1,20 @@
+(The MIT License)
+
+Copyright (c) 2014 Guillermo Rauch
+
+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/components/rauchg-ms.js@0.7.1/Makefile b/components/rauchg-ms.js@0.7.1/Makefile
new file mode 100644
index 000000000..0ae97b3ec
--- /dev/null
+++ b/components/rauchg-ms.js@0.7.1/Makefile
@@ -0,0 +1,8 @@
+
+test:
+ @./node_modules/.bin/mocha test/test.js
+
+test-browser:
+ ./node_modules/.bin/serve test/
+
+.PHONY: test
diff --git a/components/rauchg-ms.js@0.7.1/README.md b/components/rauchg-ms.js@0.7.1/README.md
new file mode 100644
index 000000000..9b4fd0358
--- /dev/null
+++ b/components/rauchg-ms.js@0.7.1/README.md
@@ -0,0 +1,35 @@
+# ms.js: miliseconds conversion utility
+
+```js
+ms('2 days') // 172800000
+ms('1d') // 86400000
+ms('10h') // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h') // 7200000
+ms('1m') // 60000
+ms('5s') // 5000
+ms('100') // 100
+```
+
+```js
+ms(60000) // "1m"
+ms(2 * 60000) // "2m"
+ms(ms('10 hours')) // "10h"
+```
+
+```js
+ms(60000, { long: true }) // "1 minute"
+ms(2 * 60000, { long: true }) // "2 minutes"
+ms(ms('10 hours'), { long: true }) // "10 hours"
+```
+
+- Node/Browser compatible. Published as [`ms`](https://www.npmjs.org/package/ms) in [NPM](http://nodejs.org/download).
+- If a number is supplied to `ms`, a string with a unit is returned.
+- If a string that contains the number is supplied, it returns it as
+a number (e.g: it returns `100` for `'100'`).
+- If you pass a string with a number and a valid unit, the number of
+equivalent ms is returned.
+
+## License
+
+MIT
diff --git a/components/rauchg-ms.js@0.7.1/component.json b/components/rauchg-ms.js@0.7.1/component.json
new file mode 100644
index 000000000..2d7bbff88
--- /dev/null
+++ b/components/rauchg-ms.js@0.7.1/component.json
@@ -0,0 +1,15 @@
+{
+ "name": "ms",
+ "repo": "guille/ms.js",
+ "version": "0.6.1",
+ "description": "ms parsing / formatting",
+ "keywords": [
+ "ms",
+ "parse",
+ "format"
+ ],
+ "scripts": [
+ "index.js"
+ ],
+ "license": "MIT"
+}
diff --git a/components/rauchg-ms.js@0.7.1/index.js b/components/rauchg-ms.js@0.7.1/index.js
new file mode 100644
index 000000000..4f9277169
--- /dev/null
+++ b/components/rauchg-ms.js@0.7.1/index.js
@@ -0,0 +1,125 @@
+/**
+ * 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
+ ? long(val)
+ : short(val);
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+ str = '' + str;
+ if (str.length > 10000) return;
+ var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|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 'yrs':
+ case 'yr':
+ case 'y':
+ return n * y;
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * d;
+ case 'hours':
+ case 'hour':
+ case 'hrs':
+ case 'hr':
+ case 'h':
+ return n * h;
+ case 'minutes':
+ case 'minute':
+ case 'mins':
+ case 'min':
+ case 'm':
+ return n * m;
+ case 'seconds':
+ case 'second':
+ case 'secs':
+ case 'sec':
+ case 's':
+ return n * s;
+ case 'milliseconds':
+ case 'millisecond':
+ case 'msecs':
+ case 'msec':
+ case 'ms':
+ return n;
+ }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function short(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 long(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';
+}
diff --git a/components/rauchg-ms.js@0.7.1/package.json b/components/rauchg-ms.js@0.7.1/package.json
new file mode 100644
index 000000000..a4e5bb603
--- /dev/null
+++ b/components/rauchg-ms.js@0.7.1/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "ms",
+ "version": "0.7.1",
+ "description": "Tiny ms conversion utility",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/guille/ms.js.git"
+ },
+ "main": "./index",
+ "devDependencies": {
+ "mocha": "*",
+ "expect.js": "*",
+ "serve": "*"
+ },
+ "component": {
+ "scripts": {
+ "ms/index.js": "index.js"
+ }
+ }
+}
diff --git a/components/rauchg-ms.js@0.7.1/test/test.js b/components/rauchg-ms.js@0.7.1/test/test.js
new file mode 100644
index 000000000..d7aa8d16a
--- /dev/null
+++ b/components/rauchg-ms.js@0.7.1/test/test.js
@@ -0,0 +1,157 @@
+
+/**
+ * Dependencies.
+ */
+
+if ('undefined' != typeof require) {
+ expect = require('expect.js');
+ ms = require('../');
+}
+
+// strings
+
+describe('ms(string)', function(){
+ it('should preserve ms', function () {
+ expect(ms('100')).to.be(100);
+ });
+
+ it('should convert from m to ms', function () {
+ expect(ms('1m')).to.be(60000);
+ });
+
+ it('should convert from h to ms', function () {
+ expect(ms('1h')).to.be(3600000);
+ });
+
+ it('should convert d to ms', function () {
+ expect(ms('2d')).to.be(172800000);
+ });
+
+ it('should convert s to ms', function () {
+ expect(ms('1s')).to.be(1000);
+ });
+
+ it('should convert ms to ms', function () {
+ expect(ms('100ms')).to.be(100);
+ });
+
+ it('should work with decimals', function () {
+ expect(ms('1.5h')).to.be(5400000);
+ });
+
+ it('should work with multiple spaces', function () {
+ expect(ms('1 s')).to.be(1000);
+ });
+
+ it('should return NaN if invalid', function () {
+ expect(isNaN(ms('☃'))).to.be(true);
+ });
+
+ it('should be case-insensitive', function () {
+ expect(ms('1.5H')).to.be(5400000);
+ });
+
+ it('should work with numbers starting with .', function () {
+ expect(ms('.5ms')).to.be(.5);
+ });
+})
+
+// long strings
+
+describe('ms(long string)', function(){
+ it('should convert milliseconds to ms', function () {
+ expect(ms('53 milliseconds')).to.be(53);
+ });
+
+ it('should convert msecs to ms', function () {
+ expect(ms('17 msecs')).to.be(17);
+ });
+
+ it('should convert sec to ms', function () {
+ expect(ms('1 sec')).to.be(1000);
+ });
+
+ it('should convert from min to ms', function () {
+ expect(ms('1 min')).to.be(60000);
+ });
+
+ it('should convert from hr to ms', function () {
+ expect(ms('1 hr')).to.be(3600000);
+ });
+
+ it('should convert days to ms', function () {
+ expect(ms('2 days')).to.be(172800000);
+ });
+
+ it('should work with decimals', function () {
+ expect(ms('1.5 hours')).to.be(5400000);
+ });
+})
+
+// numbers
+
+describe('ms(number, { long: true })', function(){
+ it('should support milliseconds', function(){
+ expect(ms(500, { long: true })).to.be('500 ms');
+ })
+
+ it('should support seconds', function(){
+ expect(ms(1000, { long: true })).to.be('1 second');
+ expect(ms(1200, { long: true })).to.be('1 second');
+ expect(ms(10000, { long: true })).to.be('10 seconds');
+ })
+
+ it('should support minutes', function(){
+ expect(ms(60 * 1000, { long: true })).to.be('1 minute');
+ expect(ms(60 * 1200, { long: true })).to.be('1 minute');
+ expect(ms(60 * 10000, { long: true })).to.be('10 minutes');
+ })
+
+ it('should support hours', function(){
+ expect(ms(60 * 60 * 1000, { long: true })).to.be('1 hour');
+ expect(ms(60 * 60 * 1200, { long: true })).to.be('1 hour');
+ expect(ms(60 * 60 * 10000, { long: true })).to.be('10 hours');
+ })
+
+ it('should support days', function(){
+ expect(ms(24 * 60 * 60 * 1000, { long: true })).to.be('1 day');
+ expect(ms(24 * 60 * 60 * 1200, { long: true })).to.be('1 day');
+ expect(ms(24 * 60 * 60 * 10000, { long: true })).to.be('10 days');
+ })
+
+ it('should round', function(){
+ expect(ms(234234234, { long: true })).to.be('3 days');
+ })
+})
+
+// numbers
+
+describe('ms(number)', function(){
+ it('should support milliseconds', function(){
+ expect(ms(500)).to.be('500ms');
+ })
+
+ it('should support seconds', function(){
+ expect(ms(1000)).to.be('1s');
+ expect(ms(10000)).to.be('10s');
+ })
+
+ it('should support minutes', function(){
+ expect(ms(60 * 1000)).to.be('1m');
+ expect(ms(60 * 10000)).to.be('10m');
+ })
+
+ it('should support hours', function(){
+ expect(ms(60 * 60 * 1000)).to.be('1h');
+ expect(ms(60 * 60 * 10000)).to.be('10h');
+ })
+
+ it('should support days', function(){
+ expect(ms(24 * 60 * 60 * 1000)).to.be('1d');
+ expect(ms(24 * 60 * 60 * 10000)).to.be('10d');
+ })
+
+ it('should round', function(){
+ expect(ms(234234234)).to.be('3d');
+ })
+})
diff --git a/components/segmentio-after@0.1.0/.gitignore b/components/segmentio-after@0.1.0/.gitignore
new file mode 100644
index 000000000..303d7e776
--- /dev/null
+++ b/components/segmentio-after@0.1.0/.gitignore
@@ -0,0 +1,5 @@
+.DS_Store
+node_modules
+components
+build
+*.sublime*
diff --git a/components/segmentio-after@0.1.0/History.md b/components/segmentio-after@0.1.0/History.md
new file mode 100644
index 000000000..88ee3fe8e
--- /dev/null
+++ b/components/segmentio-after@0.1.0/History.md
@@ -0,0 +1,8 @@
+0.1.0 - October 29, 2013
+------------------------
+* remove `0` case
+* change tests to run in browser
+
+0.0.1 - February 13, 2013
+-------------------------
+* hey there
\ No newline at end of file
diff --git a/components/segmentio-after@0.1.0/Makefile b/components/segmentio-after@0.1.0/Makefile
new file mode 100644
index 000000000..0c4abd8a6
--- /dev/null
+++ b/components/segmentio-after@0.1.0/Makefile
@@ -0,0 +1,14 @@
+
+build: components index.js
+ @component build --dev
+
+components: component.json
+ @component install --dev
+
+clean:
+ @rm -fr build components template.js
+
+test: build
+ @open test/index.html
+
+.PHONY: clean test
diff --git a/components/segmentio-after@0.1.0/Readme.md b/components/segmentio-after@0.1.0/Readme.md
new file mode 100644
index 000000000..05b69f0ee
--- /dev/null
+++ b/components/segmentio-after@0.1.0/Readme.md
@@ -0,0 +1,18 @@
+# after
+
+ After, just like in underscore.
+
+## Installation
+
+ $ component install segmentio/after
+
+## API
+
+### after(times, function)
+
+ Returns a function that will call the original `function`
+ after it has been called a certain number of `times`.
+
+## License
+
+ MIT
diff --git a/components/segmentio-after@0.1.0/component.json b/components/segmentio-after@0.1.0/component.json
new file mode 100644
index 000000000..3af5edf48
--- /dev/null
+++ b/components/segmentio-after@0.1.0/component.json
@@ -0,0 +1,13 @@
+{
+ "name": "after",
+ "repo": "segmentio/after",
+ "description": "After, just like in underscore.",
+ "version": "0.1.0",
+ "license": "MIT",
+ "development": {
+ "component/assert": "*"
+ },
+ "scripts": [
+ "index.js"
+ ]
+}
\ No newline at end of file
diff --git a/components/segmentio-after@0.1.0/index.js b/components/segmentio-after@0.1.0/index.js
new file mode 100644
index 000000000..ce8ba1eff
--- /dev/null
+++ b/components/segmentio-after@0.1.0/index.js
@@ -0,0 +1,21 @@
+
+/**
+ * Expose `after`.
+ */
+
+module.exports = after;
+
+
+/**
+ * Return the `fn` wrapped in logic that will only let it be called after
+ * it has been invoked a certain number of `times`.
+ *
+ * @param {Number} times
+ * @param {Function} fn
+ */
+
+function after (times, fn) {
+ return function () {
+ if (--times < 1) return fn.apply(this, arguments);
+ };
+}
\ No newline at end of file
diff --git a/components/segmentio-after@0.1.0/package.json b/components/segmentio-after@0.1.0/package.json
new file mode 100644
index 000000000..9f3635cad
--- /dev/null
+++ b/components/segmentio-after@0.1.0/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "after",
+ "version": "0.0.1",
+ "dependencies": {},
+ "devDependencies": {
+ "mocha": "*",
+ "should": "*"
+ }
+}
\ No newline at end of file
diff --git a/components/segmentio-after@0.1.0/test/index.html b/components/segmentio-after@0.1.0/test/index.html
new file mode 100644
index 000000000..fa7a1fca5
--- /dev/null
+++ b/components/segmentio-after@0.1.0/test/index.html
@@ -0,0 +1,14 @@
+
+
+ after tests
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/segmentio-after@0.1.0/test/index.js b/components/segmentio-after@0.1.0/test/index.js
new file mode 100644
index 000000000..e55f46d96
--- /dev/null
+++ b/components/segmentio-after@0.1.0/test/index.js
@@ -0,0 +1,16 @@
+
+describe('after', function () {
+
+ var after = require('after');
+ var assert = require('assert');
+
+ it('should work', function () {
+ var i = 0;
+ var fn = after(3, function(){ return ++i; });
+ assert(undefined === fn());
+ assert(undefined === fn());
+ assert(1 === fn());
+ assert(2 === fn());
+ });
+
+});
\ No newline at end of file
diff --git a/components/segmentio-after@0.1.0/test/mocha.css b/components/segmentio-after@0.1.0/test/mocha.css
new file mode 100644
index 000000000..8bed7cd1b
--- /dev/null
+++ b/components/segmentio-after@0.1.0/test/mocha.css
@@ -0,0 +1,231 @@
+@charset "utf-8";
+
+body {
+ font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ padding: 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;
+}
+
+.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;
+}
+
+#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: white;
+ -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;
+}
+
+#mocha .test pre {
+ display: block;
+ float: left;
+ clear: left;
+ font: 12px/1.5 monaco, monospace;
+ margin: 5px;
+ padding: 15px;
+ border: 1px solid #eee;
+ 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;
+}
+
+#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-error {
+ color: #c00;
+ font-size: 1.5 em;
+ font-weight: 100;
+ letter-spacing: 1px;
+}
+
+#mocha-stats {
+ position: fixed;
+ top: 15px;
+ right: 10px;
+ font-size: 12px;
+ margin: 0;
+ color: #888;
+}
+
+#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;
+}
+
+code .comment { color: #ddd }
+code .init { color: #2F6FAD }
+code .string { color: #5890AD }
+code .keyword { color: #8A6343 }
+code .number { color: #2F6FAD }
\ No newline at end of file
diff --git a/test/server/mocha.js b/components/segmentio-after@0.1.0/test/mocha.js
similarity index 87%
rename from test/server/mocha.js
rename to components/segmentio-after@0.1.0/test/mocha.js
index d5cb7f105..d10d73806 100644
--- a/test/server/mocha.js
+++ b/components/segmentio-after@0.1.0/test/mocha.js
@@ -1,5 +1,6 @@
;(function(){
+
// CommonJS require()
function require(p){
@@ -51,13 +52,13 @@ 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 */
+/* See license.txt for terms of usage */
/*
* Text diff implementation.
@@ -74,7 +75,6 @@ require.register("browser/diff.js", function(module, exports, require){
* 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) };
}
@@ -89,21 +89,22 @@ var JsDiff = (function() {
}
function escapeHTML(s) {
var n = s;
- n = n.replace(/&/g, '&');
- n = n.replace(//g, '>');
- n = n.replace(/"/g, '"');
+ n = n.replace(/&/g, "&");
+ n = n.replace(//g, ">");
+ n = n.replace(/"/g, """);
return n;
}
- var Diff = function(ignoreWhitespace) {
+
+ var fbDiff = function(ignoreWhitespace) {
this.ignoreWhitespace = ignoreWhitespace;
};
- Diff.prototype = {
+ fbDiff.prototype = {
diff: function(oldString, newString) {
// Handle the identity case (this is due to unrolling editLength == 0
- if (newString === oldString) {
+ if (newString == oldString) {
return [{ value: newString }];
}
if (!newString) {
@@ -198,7 +199,7 @@ var JsDiff = (function() {
if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
return true;
} else {
- return left === right;
+ return left == right;
}
},
join: function(left, right) {
@@ -209,30 +210,26 @@ var JsDiff = (function() {
}
};
- var CharDiff = new Diff();
+ var CharDiff = new fbDiff();
- var WordDiff = new Diff(true);
- var WordWithSpaceDiff = new Diff();
- WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) {
+ var WordDiff = new fbDiff(true);
+ WordDiff.tokenize = function(value) {
return removeEmpty(value.split(/(\s+|\b)/));
};
- var CssDiff = new Diff(true);
+ var CssDiff = new fbDiff(true);
CssDiff.tokenize = function(value) {
return removeEmpty(value.split(/([{}:;,]|\s+)/));
};
- var LineDiff = new Diff();
+ var LineDiff = new fbDiff();
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); },
@@ -240,16 +237,16 @@ var JsDiff = (function() {
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));
+ 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
+ diff.push({value: "", lines: []}); // Append an empty value to make cleanup easier
function contextLines(lines) {
return lines.map(function(entry) { return ' ' + entry; });
@@ -257,7 +254,7 @@ var JsDiff = (function() {
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);
+ 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)) {
@@ -269,7 +266,7 @@ var JsDiff = (function() {
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');
+ lines = current.lines || current.value.replace(/\n$/, "").split("\n");
current.lines = lines;
if (current.added || current.removed) {
@@ -284,7 +281,7 @@ var JsDiff = (function() {
newRangeStart -= curRange.length;
}
}
- curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; }));
+ curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?"+":"-") + entry; }));
eofNL(curRange, i, current);
if (current.added) {
@@ -302,9 +299,9 @@ var JsDiff = (function() {
// end the range and output
var contextSize = Math.min(lines.length, 4);
ret.push(
- '@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)
- + ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)
- + ' @@');
+ "@@ -" + 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) {
@@ -322,93 +319,30 @@ var JsDiff = (function() {
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('');
+ ret.push("");
} else if (change.removed) {
- ret.push('');
+ ret.push("");
}
ret.push(escapeHTML(change.value));
if (change.added) {
- ret.push(' ');
+ ret.push(" ");
} else if (change.removed) {
- ret.push('');
+ ret.push("");
}
}
- 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;
+ return ret.join("");
}
};
})();
-if (typeof module !== 'undefined') {
+if (typeof module !== "undefined") {
module.exports = JsDiff;
}
@@ -739,14 +673,8 @@ exports.isatty = function(){
};
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];
- }
+ return [window.innerHeight, window.innerWidth];
};
-
}); // module: browser/tty.js
require.register("context.js", function(module, exports, require){
@@ -877,6 +805,7 @@ Hook.prototype.error = function(err){
this._error = err;
};
+
}); // module: hook.js
require.register("interfaces/bdd.js", function(module, exports, require){
@@ -886,8 +815,7 @@ require.register("interfaces/bdd.js", function(module, exports, require){
*/
var Suite = require('../suite')
- , Test = require('../test')
- , utils = require('../utils');
+ , Test = require('../test');
/**
* BDD-style interface:
@@ -978,7 +906,6 @@ module.exports = function(suite){
context.describe.only = function(title, fn){
var suite = context.describe(title, fn);
mocha.grep(suite.fullTitle());
- return suite;
};
/**
@@ -1001,9 +928,7 @@ module.exports = function(suite){
context.it.only = function(title, fn){
var test = context.it(title, fn);
- var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
- mocha.grep(new RegExp(reString));
- return test;
+ mocha.grep(test.fullTitle());
};
/**
@@ -1081,7 +1006,6 @@ module.exports = function(suite){
}
}
};
-
}); // module: interfaces/exports.js
require.register("interfaces/index.js", function(module, exports, require){
@@ -1100,8 +1024,7 @@ require.register("interfaces/qunit.js", function(module, exports, require){
*/
var Suite = require('../suite')
- , Test = require('../test')
- , utils = require('../utils');
+ , Test = require('../test');
/**
* QUnit-style interface:
@@ -1131,7 +1054,7 @@ var Suite = require('../suite')
module.exports = function(suite){
var suites = [suite];
- suite.on('pre-require', function(context, file, mocha){
+ suite.on('pre-require', function(context){
/**
* Execute before running tests.
@@ -1173,16 +1096,6 @@ module.exports = function(suite){
if (suites.length > 1) suites.shift();
var suite = Suite.create(suites[0], title);
suites.unshift(suite);
- return suite;
- };
-
- /**
- * Exclusive test-case.
- */
-
- context.suite.only = function(title, fn){
- var suite = context.suite(title, fn);
- mocha.grep(suite.fullTitle());
};
/**
@@ -1192,27 +1105,7 @@ module.exports = function(suite){
*/
context.test = function(title, fn){
- var test = new Test(title, fn);
- suites[0].addTest(test);
- return test;
- };
-
- /**
- * Exclusive test-case.
- */
-
- context.test.only = function(title, fn){
- var test = context.test(title, fn);
- var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
- mocha.grep(new RegExp(reString));
- };
-
- /**
- * Pending test case.
- */
-
- context.test.skip = function(title){
- context.test(title);
+ suites[0].addTest(new Test(title, fn));
};
});
};
@@ -1226,8 +1119,7 @@ require.register("interfaces/tdd.js", function(module, exports, require){
*/
var Suite = require('../suite')
- , Test = require('../test')
- , utils = require('../utils');;
+ , Test = require('../test');
/**
* TDD-style interface:
@@ -1305,17 +1197,6 @@ module.exports = function(suite){
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.
*/
@@ -1332,10 +1213,8 @@ module.exports = function(suite){
*/
context.test = function(title, fn){
- var suite = suites[0];
- if (suite.pending) var fn = null;
var test = new Test(title, fn);
- suite.addTest(test);
+ suites[0].addTest(test);
return test;
};
@@ -1345,8 +1224,7 @@ module.exports = function(suite){
context.test.only = function(title, fn){
var test = context.test(title, fn);
- var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
- mocha.grep(new RegExp(reString));
+ mocha.grep(test.fullTitle());
};
/**
@@ -1434,7 +1312,7 @@ function Mocha(options) {
this.ui(options.ui);
this.bail(options.bail);
this.reporter(options.reporter);
- if (null != options.timeout) this.timeout(options.timeout);
+ if (options.timeout) this.timeout(options.timeout);
if (options.slow) this.slow(options.slow);
}
@@ -1573,13 +1451,12 @@ Mocha.prototype.invert = function(){
/**
* Ignore global leaks.
*
- * @param {Boolean} ignore
* @return {Mocha}
* @api public
*/
-Mocha.prototype.ignoreLeaks = function(ignore){
- this.options.ignoreLeaks = !!ignore;
+Mocha.prototype.ignoreLeaks = function(){
+ this.options.ignoreLeaks = true;
return this;
};
@@ -1672,7 +1549,7 @@ Mocha.prototype.run = function(fn){
var options = this.options;
var runner = new exports.Runner(suite);
var reporter = new this._reporter(runner);
- runner.ignoreLeaks = false !== options.ignoreLeaks;
+ runner.ignoreLeaks = options.ignoreLeaks;
runner.asyncOnly = options.asyncOnly;
if (options.grep) runner.grep(options.grep, options.invert);
if (options.globals) runner.globals(options.globals);
@@ -1683,6 +1560,7 @@ Mocha.prototype.run = function(fn){
}); // module: mocha.js
require.register("ms.js", function(module, exports, require){
+
/**
* Helpers.
*/
@@ -1691,28 +1569,19 @@ 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 || {};
+module.exports = function(val){
if ('string' == typeof val) return parse(val);
- return options.long
- ? long(val)
- : short(val);
-};
+ return format(val);
+}
/**
* Parse the given `str` and return milliseconds.
@@ -1723,78 +1592,55 @@ module.exports = function(val, options){
*/
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();
+ var m = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
+ if (!m) return;
+ var n = parseFloat(m[1]);
+ var type = (m[2] || 'ms').toLowerCase();
switch (type) {
case 'years':
case 'year':
case 'y':
- return n * y;
+ return n * 31557600000;
case 'days':
case 'day':
case 'd':
- return n * d;
+ return n * 86400000;
case 'hours':
case 'hour':
case 'h':
- return n * h;
+ return n * 3600000;
case 'minutes':
case 'minute':
case 'm':
- return n * m;
+ return n * 60000;
case 'seconds':
case 'second':
case 's':
- return n * s;
+ return n * 1000;
case 'ms':
return n;
}
}
/**
- * Short format for `ms`.
- *
- * @param {Number} ms
- * @return {String}
- * @api private
- */
-
-function short(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`.
+ * Format the given `ms`.
*
* @param {Number} ms
* @return {String}
- * @api private
- */
-
-function long(ms) {
- return plural(ms, d, 'day')
- || plural(ms, h, 'hour')
- || plural(ms, m, 'minute')
- || plural(ms, s, 'second')
- || ms + ' ms';
-}
-
-/**
- * Pluralization helper.
+ * @api public
*/
-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';
+function format(ms) {
+ if (ms == d) return Math.round(ms / d) + ' day';
+ if (ms > d) return Math.round(ms / d) + ' days';
+ if (ms == h) return Math.round(ms / h) + ' hour';
+ if (ms > h) return Math.round(ms / h) + ' hours';
+ if (ms == m) return Math.round(ms / m) + ' minute';
+ if (ms > m) return Math.round(ms / m) + ' minutes';
+ if (ms == s) return Math.round(ms / s) + ' second';
+ if (ms > s) return Math.round(ms / s) + ' seconds';
+ return ms + ' ms';
}
-
}); // module: ms.js
require.register("reporters/base.js", function(module, exports, require){
@@ -1833,13 +1679,7 @@ exports = module.exports = Base;
* Enable coloring by default.
*/
-exports.useColors = isatty || (process.env.MOCHA_COLORS !== undefined);
-
-/**
- * Inline diffs instead of +/-
- */
-
-exports.inlineDiffs = false;
+exports.useColors = isatty;
/**
* Default color map.
@@ -1967,26 +1807,43 @@ exports.list = function(failures){
, expected = err.expected
, escape = true;
- // uncaught
- if (err.uncaught) {
- msg = 'Uncaught ' + msg;
- }
-
// explicitly show diff
- if (err.showDiff && sameType(actual, expected)) {
+ if (err.showDiff) {
escape = false;
- err.actual = actual = stringify(actual);
- err.expected = expected = stringify(expected);
+ err.actual = actual = JSON.stringify(actual, null, 2);
+ err.expected = expected = JSON.stringify(expected, null, 2);
}
// actual / expected diff
if ('string' == typeof actual && 'string' == typeof expected) {
- fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
- if (exports.inlineDiffs) {
- msg = inlineDiff(err, escape);
- } else {
- msg = unifiedDiff(err, escape);
+ var len = Math.max(actual.length, expected.length);
+
+ if (len < 20) msg = errorDiff(err, 'Chars', escape);
+ else msg = errorDiff(err, 'Words', 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, ' ');
+
+ fmt = color('error title', ' %s) %s:\n%s')
+ + color('error stack', '\n%s\n');
}
// indent stack trace without msg
@@ -2071,38 +1928,48 @@ function Base(runner) {
*/
Base.prototype.epilogue = function(){
- var stats = this.stats;
- var tests;
- var fmt;
+ var stats = this.stats
+ , fmt
+ , tests;
console.log();
- // passes
+ function pluralize(n) {
+ return 1 == n ? 'test' : 'tests';
+ }
+
+ // failure
+ if (stats.failures) {
+ fmt = color('bright fail', ' ' + exports.symbols.err)
+ + color('fail', ' %d of %d %s failed')
+ + color('light', ':')
+
+ console.error(fmt,
+ stats.failures,
+ this.runner.total,
+ pluralize(this.runner.total));
+
+ Base.list(this.failures);
+ console.error();
+ return;
+ }
+
+ // pass
fmt = color('bright pass', ' ')
- + color('green', ' %d passing')
+ + color('green', ' %d %s complete')
+ color('light', ' (%s)');
console.log(fmt,
- stats.passes || 0,
+ stats.tests || 0,
+ pluralize(stats.tests),
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');
+ + color('pending', ' %d %s pending');
- console.error(fmt,
- stats.failures);
-
- Base.list(this.failures);
- console.error();
+ console.log(fmt, stats.pending, pluralize(stats.pending));
}
console.log();
@@ -2122,73 +1989,6 @@ function pad(str, len) {
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`.
*
@@ -2198,28 +1998,19 @@ function unifiedDiff(err, escape) {
*/
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){
+ return diff['diff' + type](err.actual, err.expected).map(function(str){
+ if (escape) {
+ str.value = str.value
+ .replace(/\t/g, '')
+ .replace(/\r/g, '')
+ .replace(/\n/g, '\n');
+ }
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, '')
- .replace(/\r/g, '')
- .replace(/\n/g, '\n');
-}
-
/**
* Color lines for `str`, using the color `name`.
*
@@ -2235,34 +2026,6 @@ function colorLines(name, str) {
}).join('\n');
}
-/**
- * Stringify `obj`.
- *
- * @param {Mixed} obj
- * @return {String}
- * @api private
- */
-
-function stringify(obj) {
- if (obj instanceof RegExp) return obj.toString();
- return JSON.stringify(obj, null, 2);
-}
-
-/**
- * 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){
@@ -2571,6 +2334,8 @@ function HTML(runner, root) {
});
runner.on('test end', function(test){
+ window.scrollTo(0, document.body.scrollHeight);
+
// TODO: add to stats
var percent = stats.tests / this.total * 100 | 0;
if (progress) progress.update(percent).draw(ctx);
@@ -2724,6 +2489,7 @@ exports.Landing = require('./landing');
exports.JSONCov = require('./json-cov');
exports.HTMLCov = require('./html-cov');
exports.JSONStream = require('./json-stream');
+exports.Teamcity = require('./teamcity');
}); // module: reporters/index.js
@@ -3334,10 +3100,10 @@ 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.
*/
@@ -3360,6 +3126,7 @@ exports = module.exports = NyanCat;
function NyanCat(runner) {
Base.call(this, runner);
+
var self = this
, stats = this.stats
, width = Base.window.width * .75 | 0
@@ -3375,19 +3142,19 @@ function NyanCat(runner) {
runner.on('start', function(){
Base.cursor.hide();
- self.draw();
+ self.draw('start');
});
runner.on('pending', function(test){
- self.draw();
+ self.draw('pending');
});
runner.on('pass', function(test){
- self.draw();
+ self.draw('pass');
});
runner.on('fail', function(test, err){
- self.draw();
+ self.draw('fail');
});
runner.on('end', function(){
@@ -3398,16 +3165,17 @@ function NyanCat(runner) {
}
/**
- * Draw the nyan cat
+ * Draw the nyan cat with runner `status`.
*
+ * @param {String} status
* @api private
*/
-NyanCat.prototype.draw = function(){
+NyanCat.prototype.draw = function(status){
this.appendRainbow();
this.drawScoreboard();
this.drawRainbow();
- this.drawNyanCat();
+ this.drawNyanCat(status);
this.tick = !this.tick;
};
@@ -3472,61 +3240,57 @@ NyanCat.prototype.drawRainbow = function(){
};
/**
- * Draw the nyan cat
+ * Draw the nyan cat with `status`.
*
+ * @param {String} status
* @api private
*/
-NyanCat.prototype.drawNyanCat = function() {
+NyanCat.prototype.drawNyanCat = function(status) {
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');
+ [0, 1, 2, 3].forEach(function(index) {
+ write('\u001b[' + startWidth + 'C');
+
+ switch (index) {
+ case 0:
+ write('_,------,');
+ write('\n');
+ break;
+ case 1:
+ var padding = self.tick ? ' ' : ' ';
+ write('_|' + padding + '/\\_/\\ ');
+ write('\n');
+ break;
+ case 2:
+ var padding = self.tick ? '_' : '__';
+ var tail = self.tick ? '~' : '^';
+ var face;
+ switch (status) {
+ case 'pass':
+ face = '( ^ .^)';
+ break;
+ case 'fail':
+ face = '( o .o)';
+ break;
+ default:
+ face = '( - .-)';
+ }
+ write(tail + '|' + padding + face + ' ');
+ write('\n');
+ break;
+ case 3:
+ var padding = self.tick ? ' ' : ' ';
+ write(padding + '"" "" ');
+ write('\n');
+ break;
+ }
+ });
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`.
*
@@ -3871,6 +3635,75 @@ function title(test) {
}); // module: reporters/tap.js
+require.register("reporters/teamcity.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `Teamcity`.
+ */
+
+exports = module.exports = Teamcity;
+
+/**
+ * Initialize a new `Teamcity` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Teamcity(runner) {
+ Base.call(this, runner);
+ var stats = this.stats;
+
+ runner.on('start', function() {
+ console.log("##teamcity[testSuiteStarted name='mocha.suite']");
+ });
+
+ runner.on('test', function(test) {
+ console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']");
+ });
+
+ runner.on('fail', function(test, err) {
+ console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']");
+ });
+
+ runner.on('pending', function(test) {
+ console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']");
+ });
+
+ runner.on('test end', function(test) {
+ console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']");
+ });
+
+ runner.on('end', function() {
+ console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']");
+ });
+}
+
+/**
+ * Escape the given `str`.
+ */
+
+function escape(str) {
+ return str
+ .replace(/\|/g, "||")
+ .replace(/\n/g, "|n")
+ .replace(/\r/g, "|r")
+ .replace(/\[/g, "|[")
+ .replace(/\]/g, "|]")
+ .replace(/\u0085/g, "|x")
+ .replace(/\u2028/g, "|l")
+ .replace(/\u2029/g, "|p")
+ .replace(/'/g, "|'");
+}
+
+}); // module: reporters/teamcity.js
+
require.register("reporters/xunit.js", function(module, exports, require){
/**
@@ -3924,9 +3757,9 @@ function XUnit(runner) {
, tests: stats.tests
, failures: stats.failures
, errors: stats.failures
- , skipped: stats.tests - stats.failures - stats.passes
+ , skip: stats.tests - stats.failures - stats.passes
, timestamp: (new Date).toUTCString()
- , time: (stats.duration / 1000) || 0
+ , time: stats.duration / 1000
}, false));
tests.forEach(test);
@@ -4132,14 +3965,16 @@ Runnable.prototype.inspect = function(){
*/
Runnable.prototype.resetTimeout = function(){
- var self = this;
- var ms = this.timeout() || 1e9;
+ var self = this
+ , ms = this.timeout();
this.clearTimeout();
- this.timer = setTimeout(function(){
- self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
- self.timedOut = true;
- }, ms);
+ if (ms) {
+ this.timer = setTimeout(function(){
+ self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
+ self.timedOut = true;
+ }, ms);
+ }
};
/**
@@ -4220,6 +4055,7 @@ Runnable.prototype.run = function(fn){
}); // module: runnable.js
require.register("runner.js", function(module, exports, require){
+
/**
* Module dependencies.
*/
@@ -4229,7 +4065,8 @@ var EventEmitter = require('browser/events').EventEmitter
, Test = require('./test')
, utils = require('./utils')
, filter = utils.filter
- , keys = utils.keys;
+ , keys = utils.keys
+ , noop = function(){};
/**
* Non-enumerable globals.
@@ -4265,7 +4102,6 @@ module.exports = Runner;
* - `hook end` (hook) hook complete
* - `pass` (test) test passed
* - `fail` (test, err) test failed
- * - `pending` (test) test pending
*
* @api public
*/
@@ -4282,15 +4118,6 @@ function Runner(suite) {
this.globals(this.globalProps().concat(['errno']));
}
-/**
- * Wrapper for setImmediate, process.nextTick, or browser polyfill.
- *
- * @param {Function} fn
- * @api private
- */
-
-Runner.immediately = global.setImmediate || process.nextTick;
-
/**
* Inherit from `EventEmitter.prototype`.
*/
@@ -4391,12 +4218,9 @@ Runner.prototype.checkGlobals = function(test){
var leaks;
// check length - 2 ('errno' and 'location' globals)
- if (isNode && 1 == ok.length - globals.length) return;
+ if (isNode && 1 == ok.length - globals.length) return
else if (2 == ok.length - globals.length) return;
- if(this.prevGlobalsLength == globals.length) return;
- this.prevGlobalsLength = globals.length;
-
leaks = filterLeaks(ok, globals);
this._globals = this._globals.concat(leaks);
@@ -4461,11 +4285,8 @@ Runner.prototype.hook = function(name, fn){
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){
@@ -4478,12 +4299,11 @@ Runner.prototype.hook = function(name, fn){
if (testError) self.fail(self.test, testError);
if (err) return self.failHook(hook, err);
self.emit('hook end', hook);
- delete hook.ctx.currentTest;
next(++i);
});
}
- Runner.immediately(function(){
+ process.nextTick(function(){
next(0);
});
};
@@ -4726,16 +4546,14 @@ 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);
+ process.removeListener('uncaughtException', function(err){
+ self.uncaught(err);
+ });
fn(self.failures);
});
@@ -4747,7 +4565,9 @@ Runner.prototype.run = function(fn){
});
// uncaught exception
- process.on('uncaughtException', uncaught);
+ process.on('uncaughtException', function(err){
+ self.uncaught(err);
+ });
return this;
};
@@ -4763,23 +4583,10 @@ Runner.prototype.run = function(fn){
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]);
+ // Opera and IE expose global variables for HTML element IDs (issue #243)
+ if (/^mocha-/.test(key)) return true;
return key == ok;
});
return matched.length == 0 && (!global.navigator || 'onerror' !== key);
@@ -5133,6 +4940,7 @@ Test.prototype.constructor = Test;
}); // module: test.js
require.register("utils.js", function(module, exports, require){
+
/**
* Module dependencies.
*/
@@ -5297,7 +5105,7 @@ exports.files = function(dir, ret){
path = join(dir, path);
if (fs.statSync(path).isDirectory()) {
exports.files(path, ret);
- } else if (path.match(/\.(js|coffee|litcoffee|coffee.md)$/)) {
+ } else if (path.match(/\.(js|coffee)$/)) {
ret.push(path);
}
});
@@ -5330,8 +5138,8 @@ exports.clean = function(str) {
.replace(/^function *\(.*\) *{/, '')
.replace(/\s+\}$/, '');
- var whitespace = str.match(/^\n?(\s*)/)[1]
- , re = new RegExp('^' + whitespace, 'gm');
+ var spaces = str.match(/^\n?( *)/)[1].length
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
str = str.replace(re, '');
@@ -5416,19 +5224,6 @@ exports.highlightTags = function(name) {
};
}); // module: utils.js
-// The global object is "self" in Web Workers.
-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.
*
@@ -5438,9 +5233,38 @@ var clearInterval = global.clearInterval;
* the browser.
*/
-var process = {};
+process = {};
process.exit = function(status){};
process.stdout = {};
+global = window;
+
+/**
+ * next tick implementation.
+ */
+
+process.nextTick = (function(){
+ // postMessage behaves badly on IE8
+ if (window.ActiveXObject || !window.postMessage) {
+ return function(fn){ fn() };
+ }
+
+ // based on setZeroTimeout by David Baron
+ // - http://dbaron.org/log/20100309-faster-timeouts
+ var timeouts = []
+ , name = 'mocha-zero-timeout'
+
+ window.addEventListener('message', function(e){
+ if (e.source == window && e.data == name) {
+ if (e.stopPropagation) e.stopPropagation();
+ if (timeouts.length) timeouts.shift()();
+ }
+ }, true);
+
+ return function(fn){
+ timeouts.push(fn);
+ window.postMessage(name, '*');
+ }
+})();
/**
* Remove uncaughtException listener.
@@ -5448,7 +5272,7 @@ process.stdout = {};
process.removeListener = function(e){
if ('uncaughtException' == e) {
- global.onerror = function() {};
+ window.onerror = null;
}
};
@@ -5458,90 +5282,59 @@ process.removeListener = function(e){
process.on = function(e, fn){
if ('uncaughtException' == e) {
- global.onerror = function(err, url, line){
+ window.onerror = function(err, url, line){
fn(new Error(err + ' (' + url + ':' + line + ')'));
};
}
};
-/**
- * Expose mocha.
- */
-
-var Mocha = global.Mocha = require('mocha'),
- mocha = global.mocha = new Mocha({ reporter: 'html' });
-
-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;
- }
-}
+// boot
+;(function(){
-/**
- * High-performance override of Runner.immediately.
- */
+ /**
+ * Expose mocha.
+ */
-Mocha.Runner.immediately = function(callback) {
- immediateQueue.push(callback);
- if (!immediateTimeout) {
- immediateTimeout = setTimeout(timeslice, 0);
- }
-};
+ var Mocha = window.Mocha = require('mocha'),
+ mocha = window.mocha = new Mocha({ reporter: 'html' });
-/**
- * Override ui to ensure that the ui functions are initialized.
- * Normally this would happen in Mocha.prototype.loadFiles.
- */
+ /**
+ * 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;
-};
+ mocha.ui = function(ui){
+ Mocha.prototype.ui.call(this, ui);
+ this.suite.emit('pre-require', window, null, this);
+ return this;
+ };
-/**
- * Setup mocha with the given setting options.
- */
+ /**
+ * 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;
-};
+ 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.
- */
+ /**
+ * Run mocha, returning the Runner.
+ */
-mocha.run = function(fn){
- var options = mocha.options;
- mocha.globals('location');
+ 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();
+ var query = Mocha.utils.parseQuery(window.location.search || '');
+ if (query.grep) mocha.grep(query.grep);
+ if (query.invert) mocha.invert();
- return Mocha.prototype.run.call(mocha, function(){
- // The DOM Document is not available in Web Workers.
- if (global.document) {
+ return Mocha.prototype.run.call(mocha, function(){
Mocha.utils.highlightTags('code');
- }
- if (fn) fn();
- });
-};
-
-/**
- * Expose the process shim.
- */
-
-Mocha.process = process;
+ if (fn) fn();
+ });
+ };
})();
+})();
\ No newline at end of file
diff --git a/components/visionmedia-debug@2.1.3/.gitignore b/components/visionmedia-debug@2.2.0/.gitignore
similarity index 100%
rename from components/visionmedia-debug@2.1.3/.gitignore
rename to components/visionmedia-debug@2.2.0/.gitignore
diff --git a/components/visionmedia-debug@2.1.3/.jshintrc b/components/visionmedia-debug@2.2.0/.jshintrc
similarity index 100%
rename from components/visionmedia-debug@2.1.3/.jshintrc
rename to components/visionmedia-debug@2.2.0/.jshintrc
diff --git a/components/visionmedia-debug@2.1.3/.npmignore b/components/visionmedia-debug@2.2.0/.npmignore
similarity index 100%
rename from components/visionmedia-debug@2.1.3/.npmignore
rename to components/visionmedia-debug@2.2.0/.npmignore
diff --git a/components/visionmedia-debug@2.1.3/History.md b/components/visionmedia-debug@2.2.0/History.md
similarity index 94%
rename from components/visionmedia-debug@2.1.3/History.md
rename to components/visionmedia-debug@2.2.0/History.md
index 770e4832d..854c9711c 100644
--- a/components/visionmedia-debug@2.1.3/History.md
+++ b/components/visionmedia-debug@2.2.0/History.md
@@ -1,4 +1,13 @@
+2.2.0 / 2015-05-09
+==================
+
+ * package: update "ms" to v0.7.1 (#202, @dougwilson)
+ * README: add logging to file example (#193, @DanielOchoa)
+ * README: fixed a typo (#191, @amir-s)
+ * browser: expose `storage` (#190, @stephenmathieson)
+ * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
2.1.3 / 2015-03-13
==================
diff --git a/components/visionmedia-debug@2.1.3/Makefile b/components/visionmedia-debug@2.2.0/Makefile
similarity index 87%
rename from components/visionmedia-debug@2.1.3/Makefile
rename to components/visionmedia-debug@2.2.0/Makefile
index b0bde6e63..5cf4a5962 100644
--- a/components/visionmedia-debug@2.1.3/Makefile
+++ b/components/visionmedia-debug@2.2.0/Makefile
@@ -16,7 +16,7 @@ all: dist/debug.js
install: node_modules
clean:
- @rm -rf node_modules dist
+ @rm -rf dist
dist:
@mkdir -p $@
@@ -26,8 +26,11 @@ dist/debug.js: node_modules browser.js debug.js dist
--standalone debug \
. > $@
+distclean: clean
+ @rm -rf node_modules
+
node_modules: package.json
@NODE_ENV= $(NPM) install
@touch node_modules
-.PHONY: all install clean
+.PHONY: all install clean distclean
diff --git a/components/visionmedia-debug@2.1.3/Readme.md b/components/visionmedia-debug@2.2.0/Readme.md
similarity index 96%
rename from components/visionmedia-debug@2.1.3/Readme.md
rename to components/visionmedia-debug@2.2.0/Readme.md
index 14222e0c2..b4f45e3cc 100644
--- a/components/visionmedia-debug@2.1.3/Readme.md
+++ b/components/visionmedia-debug@2.2.0/Readme.md
@@ -53,8 +53,8 @@ setInterval(function(){
#### Windows note
- On Windows the environment variable is set using the `set` command.
-
+ On Windows the environment variable is set using the `set` command.
+
```cmd
set DEBUG=*,-not_this
```
@@ -77,7 +77,7 @@ Then, run the program to be debugged as usual.
## Wildcards
- The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+ The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
@@ -147,6 +147,16 @@ error('now goes to stdout via console.info');
log('still goes to stdout, but via console.info now');
```
+### Save debug output to a file
+
+You can save all debug statements to a file by piping them.
+
+Example:
+
+```bash
+$ DEBUG_FD=3 node your-app.js 3> whatever.log
+```
+
## Authors
- TJ Holowaychuk
diff --git a/components/visionmedia-debug@2.1.3/bower.json b/components/visionmedia-debug@2.2.0/bower.json
similarity index 95%
rename from components/visionmedia-debug@2.1.3/bower.json
rename to components/visionmedia-debug@2.2.0/bower.json
index f7d3f6dc1..6af573ff5 100644
--- a/components/visionmedia-debug@2.1.3/bower.json
+++ b/components/visionmedia-debug@2.2.0/bower.json
@@ -1,7 +1,7 @@
{
"name": "visionmedia-debug",
"main": "dist/debug.js",
- "version": "2.1.3",
+ "version": "2.2.0",
"homepage": "https://github.com/visionmedia/debug",
"authors": [
"TJ Holowaychuk "
diff --git a/components/visionmedia-debug@2.1.3/browser.js b/components/visionmedia-debug@2.2.0/browser.js
similarity index 91%
rename from components/visionmedia-debug@2.1.3/browser.js
rename to components/visionmedia-debug@2.2.0/browser.js
index 55f4cf926..7c7645221 100644
--- a/components/visionmedia-debug@2.1.3/browser.js
+++ b/components/visionmedia-debug@2.2.0/browser.js
@@ -11,17 +11,10 @@ exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
-
-/**
- * Use chrome.storage.local if we are in an app
- */
-
-var storage;
-
-if (typeof chrome !== 'undefined' && typeof chrome.storage !== 'undefined')
- storage = chrome.storage.local;
-else
- storage = localstorage();
+exports.storage = 'undefined' != typeof chrome
+ && 'undefined' != typeof chrome.storage
+ ? chrome.storage.local
+ : localstorage();
/**
* Colors.
@@ -129,9 +122,9 @@ function log() {
function save(namespaces) {
try {
if (null == namespaces) {
- storage.removeItem('debug');
+ exports.storage.removeItem('debug');
} else {
- storage.debug = namespaces;
+ exports.storage.debug = namespaces;
}
} catch(e) {}
}
@@ -146,7 +139,7 @@ function save(namespaces) {
function load() {
var r;
try {
- r = storage.debug;
+ r = exports.storage.debug;
} catch(e) {}
return r;
}
diff --git a/components/visionmedia-debug@2.1.3/component.json b/components/visionmedia-debug@2.2.0/component.json
similarity index 83%
rename from components/visionmedia-debug@2.1.3/component.json
rename to components/visionmedia-debug@2.2.0/component.json
index 52ffd4224..ca1063724 100644
--- a/components/visionmedia-debug@2.1.3/component.json
+++ b/components/visionmedia-debug@2.2.0/component.json
@@ -2,7 +2,7 @@
"name": "debug",
"repo": "visionmedia/debug",
"description": "small debugging utility",
- "version": "2.1.3",
+ "version": "2.2.0",
"keywords": [
"debug",
"log",
@@ -14,6 +14,6 @@
"debug.js"
],
"dependencies": {
- "rauchg/ms.js": "0.7.0"
+ "rauchg/ms.js": "0.7.1"
}
}
diff --git a/components/visionmedia-debug@2.1.3/debug.js b/components/visionmedia-debug@2.2.0/debug.js
similarity index 100%
rename from components/visionmedia-debug@2.1.3/debug.js
rename to components/visionmedia-debug@2.2.0/debug.js
diff --git a/components/visionmedia-debug@2.1.3/dist/debug.js b/components/visionmedia-debug@2.2.0/dist/debug.js
similarity index 100%
rename from components/visionmedia-debug@2.1.3/dist/debug.js
rename to components/visionmedia-debug@2.2.0/dist/debug.js
diff --git a/components/visionmedia-debug@2.1.3/example/app.js b/components/visionmedia-debug@2.2.0/example/app.js
similarity index 100%
rename from components/visionmedia-debug@2.1.3/example/app.js
rename to components/visionmedia-debug@2.2.0/example/app.js
diff --git a/components/visionmedia-debug@2.1.3/example/browser.html b/components/visionmedia-debug@2.2.0/example/browser.html
similarity index 100%
rename from components/visionmedia-debug@2.1.3/example/browser.html
rename to components/visionmedia-debug@2.2.0/example/browser.html
diff --git a/components/visionmedia-debug@2.1.3/example/stdout.js b/components/visionmedia-debug@2.2.0/example/stdout.js
similarity index 100%
rename from components/visionmedia-debug@2.1.3/example/stdout.js
rename to components/visionmedia-debug@2.2.0/example/stdout.js
diff --git a/components/visionmedia-debug@2.1.3/example/wildcards.js b/components/visionmedia-debug@2.2.0/example/wildcards.js
similarity index 100%
rename from components/visionmedia-debug@2.1.3/example/wildcards.js
rename to components/visionmedia-debug@2.2.0/example/wildcards.js
diff --git a/components/visionmedia-debug@2.1.3/example/worker.js b/components/visionmedia-debug@2.2.0/example/worker.js
similarity index 100%
rename from components/visionmedia-debug@2.1.3/example/worker.js
rename to components/visionmedia-debug@2.2.0/example/worker.js
diff --git a/components/visionmedia-debug@2.1.3/node.js b/components/visionmedia-debug@2.2.0/node.js
similarity index 100%
rename from components/visionmedia-debug@2.1.3/node.js
rename to components/visionmedia-debug@2.2.0/node.js
diff --git a/components/visionmedia-debug@2.1.3/package.json b/components/visionmedia-debug@2.2.0/package.json
similarity index 94%
rename from components/visionmedia-debug@2.1.3/package.json
rename to components/visionmedia-debug@2.2.0/package.json
index dd8d8ba20..b9f033a77 100644
--- a/components/visionmedia-debug@2.1.3/package.json
+++ b/components/visionmedia-debug@2.2.0/package.json
@@ -1,6 +1,6 @@
{
"name": "debug",
- "version": "2.1.3",
+ "version": "2.2.0",
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/debug.git"
@@ -17,7 +17,7 @@
],
"license": "MIT",
"dependencies": {
- "ms": "0.7.0"
+ "ms": "0.7.1"
},
"devDependencies": {
"browserify": "9.0.3",
diff --git a/components/yields-fmt@0.0.2/.gitignore b/components/yields-fmt@0.0.2/.gitignore
new file mode 100644
index 000000000..48a2e246c
--- /dev/null
+++ b/components/yields-fmt@0.0.2/.gitignore
@@ -0,0 +1,2 @@
+components
+build
diff --git a/components/yields-fmt@0.0.2/History.md b/components/yields-fmt@0.0.2/History.md
new file mode 100644
index 000000000..11889c44b
--- /dev/null
+++ b/components/yields-fmt@0.0.2/History.md
@@ -0,0 +1,10 @@
+
+0.0.2 / 2013-12-11
+==================
+
+ * dev deps (typo)
+
+0.0.1 / 2013-12-11
+==================
+
+ * Initial commit
diff --git a/components/yields-fmt@0.0.2/Makefile b/components/yields-fmt@0.0.2/Makefile
new file mode 100644
index 000000000..1573c7975
--- /dev/null
+++ b/components/yields-fmt@0.0.2/Makefile
@@ -0,0 +1,14 @@
+
+build: components index.js
+ @component build --dev
+
+components: component.json
+ @component install --dev
+
+clean:
+ rm -fr build components template.js
+
+test: build
+ @open test/index.html
+
+.PHONY: clean test
diff --git a/components/yields-fmt@0.0.2/Readme.md b/components/yields-fmt@0.0.2/Readme.md
new file mode 100644
index 000000000..d6834f1fa
--- /dev/null
+++ b/components/yields-fmt@0.0.2/Readme.md
@@ -0,0 +1,38 @@
+
+# fmt
+
+ string format utility
+
+## Installation
+
+ Install with [component(1)](http://component.io):
+
+ $ component install yields/fmt
+
+## Example
+
+```js
+fmt('%d %s %o', '0n', 'str', {});
+// => "0 str {}"
+
+fmt.f = function(n){
+ return Number(n || 0).toFixed(2);
+};
+
+fmt('floats: %f', 1);
+// => "floats: 1.00"
+```
+
+## API
+
+### fmt(str, ...)
+
+ Format the given `str` with `...` args.
+
+ - `%o`: JSON.stringify
+ - `%d`: parseInt
+ - `%s`: String
+
+## License
+
+ MIT
diff --git a/components/yields-fmt@0.0.2/component.json b/components/yields-fmt@0.0.2/component.json
new file mode 100644
index 000000000..4319c9f18
--- /dev/null
+++ b/components/yields-fmt@0.0.2/component.json
@@ -0,0 +1,14 @@
+{
+ "name": "fmt",
+ "repo": "yields/fmt",
+ "description": "string format utility",
+ "version": "0.0.2",
+ "license": "MIT",
+ "main": "index.js",
+ "scripts": ["index.js"],
+ "development": {
+ "visionmedia/mocha-matrix": "*",
+ "visionmedia/mocha": "*",
+ "component/assert": "*"
+ }
+}
diff --git a/components/yields-fmt@0.0.2/index.js b/components/yields-fmt@0.0.2/index.js
new file mode 100644
index 000000000..3087b0d95
--- /dev/null
+++ b/components/yields-fmt@0.0.2/index.js
@@ -0,0 +1,34 @@
+
+/**
+ * Export `fmt`
+ */
+
+module.exports = fmt;
+
+/**
+ * Formatters
+ */
+
+fmt.o = JSON.stringify;
+fmt.s = String;
+fmt.d = parseInt;
+
+/**
+ * Format the given `str`.
+ *
+ * @param {String} str
+ * @param {...} args
+ * @return {String}
+ * @api public
+ */
+
+function fmt(str){
+ var args = [].slice.call(arguments, 1);
+ var j = 0;
+
+ return str.replace(/%([a-z])/gi, function(_, f){
+ return fmt[f]
+ ? fmt[f](args[j++])
+ : _ + f;
+ });
+}
diff --git a/components/yields-fmt@0.0.2/test/index.html b/components/yields-fmt@0.0.2/test/index.html
new file mode 100644
index 000000000..531958a76
--- /dev/null
+++ b/components/yields-fmt@0.0.2/test/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+ fmt
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/yields-fmt@0.0.2/test/test.js b/components/yields-fmt@0.0.2/test/test.js
new file mode 100644
index 000000000..ae0e7c283
--- /dev/null
+++ b/components/yields-fmt@0.0.2/test/test.js
@@ -0,0 +1,36 @@
+
+describe('fmt', function(){
+
+ var assert = require('assert')
+ , fmt = require('fmt');
+
+ it('%d', function(){
+ assert('number: 0' == fmt('number: %d', '0'));
+ })
+
+ it('%o', function(){
+ assert('object: {}' == fmt('object: %o', {}));
+ })
+
+ it('%o', function(){
+ assert('array: []' == fmt('array: %o', []));
+ })
+
+ it('%o', function(){
+ assert('array: [{"a":"b"}]' == fmt('array: %o', [{ a: 'b' }]));
+ })
+
+ it('%d %s %o', function(){
+ assert('0 string {}' == fmt('%d %s %o', '0number', 'string', {}))
+ })
+
+ it('extensible', function(){
+ fmt.f = format;
+ assert('floats: 1.00' == fmt('floats: 1.00', 1));
+
+ function format(s){
+ return Number(s || 0).toFixed(2);
+ }
+ })
+
+})
diff --git a/package.json b/package.json
index 6c1d333e4..53d779591 100644
--- a/package.json
+++ b/package.json
@@ -13,15 +13,12 @@
"node" : ">=0.11"
},
"devDependencies": {
- "mocha": "1.x",
- "should": "4.x",
"uglify-js": "2.4.x",
"duo": "0.x",
- "express": "3.x",
- "body-parser": "1.9.2",
- "jade": "1.x",
- "mocha-phantomjs": "3.5.2",
- "gravy": "0.x",
+ "duo-test": "0.x",
+ "koa-route": "2.x",
+ "koa-bodyparser": "2.x",
+ "ejs": "2.x",
"debug": "0.x",
"wr": "*"
}
diff --git a/test/Makefile b/test/Makefile
deleted file mode 100644
index 3c0509aec..000000000
--- a/test/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-PORT = 8989
-PID = server/pid.txt
-BIN = ../node_modules/.bin
-BROWSERS ?= 'chrome, safari, firefox'
-TEST = http://localhost:$(PORT)
-DUO = $(BIN)/duo
-GRAVY = $(BIN)/gravy
-PHANTOMJS = $(BIN)/mocha-phantomjs \
- --setting local-to-remote-url-access=true \
- --setting-web-security=false
-
-build:
- @$(DUO) --stdout index.js > build.js
-
-server: kill
- @PORT=$(PORT) node server &> /dev/null &
- @sleep 1
-
-test: build server
- @$(PHANTOMJS) $(TEST)
- -@make kill
-
-test-browser: build server
- @open $(TEST)
-
-test-coverage: build server
- @open $(TEST)/coverage
-
-test-sauce: build server
- @BROWSERS=$(BROWSERS) $(GRAVY) --url $(TEST)
-
-clean: kill
- @rm -rf components
-
-kill:
- -@test ! -e $(PID) || \
- (kill `cat $(PID)` && \
- rm -f $(PID))
-
-.PHONY: build
-.PHONY: test-sauce test-coverage
-.PHONY: test-browser test clean
diff --git a/test/api.js b/test/api.js
new file mode 100644
index 000000000..bdeda772e
--- /dev/null
+++ b/test/api.js
@@ -0,0 +1,69 @@
+var bodyParser = require('koa-bodyparser');
+var route = require('koa-route');
+var path = require('path');
+var ejs = require('ejs');
+
+module.exports = api;
+
+/**
+ * Recurly.js API mock
+ * @param {Object} app Koa app
+ */
+function api (app) {
+ app.use(cors);
+ app.use(contentTypeFix);
+ app.use(bodyParser());
+ app.use(route.get('/plans/:plan_code', json));
+ app.use(route.get('/plans/:plan_code/coupons/:coupon_code', json));
+ app.use(route.post('/token', json));
+ app.use(route.get('/token', json));
+ app.use(route.get('/tax', json));
+ app.use(route.get('/paypal/start', postMessage));
+ app.use(route.get('/relay', relay));
+}
+
+/**
+ * Utility functions.
+ */
+
+function* json () {
+ var data = fixture.apply(this);
+ if (this.query.callback) {
+ this.body = [this.query.callback, '(', JSON.stringify(data), ')'].join('');
+ } else {
+ this.body = data;
+ }
+}
+
+function* postMessage () {
+ this.body = ejs.render('post-message', {
+ message: {
+ recurly_event: this.query.event,
+ recurly_message: fixture.apply(this)
+ }
+ });
+}
+
+function* relay () {
+ this.body = ejs.render(fixture.apply({ path: 'relay.ejs' }));
+}
+
+function fixture () {
+ var fixture = require(path.join(__dirname, 'fixtures', this.path));
+ return typeof fixture === 'function'
+ ? fixture.apply(this)
+ : fixture;
+}
+
+function* cors (next) {
+ this.set('Access-Control-Allow-Origin', '*');
+ yield next;
+}
+
+// Corrects an incorrect Content-type header sent by IE9 XDomainRequests
+function* contentTypeFix (next) {
+ if (this.method === 'POST') {
+ this.req.headers['content-type'] = 'application/x-www-form-urlencoded';
+ }
+ yield next;
+}
diff --git a/test/unit/bank-account.test.js b/test/bank-account.test.js
similarity index 95%
rename from test/unit/bank-account.test.js
rename to test/bank-account.test.js
index e942c95d3..62aa5c079 100644
--- a/test/unit/bank-account.test.js
+++ b/test/bank-account.test.js
@@ -1,11 +1,10 @@
-
-var assert = require('assert');
-var merge = require('merge');
-var clone = require('clone');
-var each = require('each');
-var noop = require('noop');
-var after = require('after');
-var helpers = require('../support/helpers');
+var assert = require('component/assert');
+var clone = require('component/clone');
+var each = require('component/each');
+var noop = require('chrissrogers/noop');
+var after = require('segmentio/after');
+var merge = require('yields/merge');
+var helpers = require('./support/helpers');
helpers.apiTest(function (requestMethod) {
var Recurly = window.recurly.Recurly;
diff --git a/test/component.json b/test/component.json
deleted file mode 100644
index 30eb4aa08..000000000
--- a/test/component.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "name": "recurly-js-test",
- "main": "index.js",
- "scripts": [
- "index.js",
- "support/helpers.js",
- "unit/recurly.test.js",
- "unit/configure.test.js",
- "unit/coupon.test.js",
- "unit/open.test.js",
- "unit/plan.test.js",
- "unit/tax.test.js",
- "unit/token.test.js",
- "unit/validate.test.js"
- ],
- "dependencies": {
- "chrissrogers/noop": "*",
- "component/bind": "*",
- "component/assert": "*",
- "component/each": "*",
- "component/clone": "*",
- "component/indexof": "*",
- "segmentio/after": "*",
- "yields/merge": "*",
- "yields/gravy": "*"
- }
-}
diff --git a/test/unit/configure.test.js b/test/configure.test.js
similarity index 96%
rename from test/unit/configure.test.js
rename to test/configure.test.js
index 0fbd01940..b9df3e5c8 100644
--- a/test/unit/configure.test.js
+++ b/test/configure.test.js
@@ -1,7 +1,6 @@
-
-var assert = require('assert');
-var each = require('each');
-var bind = require('bind');
+var assert = require('component/assert');
+var each = require('component/each');
+var bind = require('component/bind');
describe('Recurly.configure', function () {
var Recurly = window.recurly.Recurly;
diff --git a/test/unit/coupon.test.js b/test/coupon.test.js
similarity index 94%
rename from test/unit/coupon.test.js
rename to test/coupon.test.js
index 66a8d908d..1ad8a1313 100644
--- a/test/unit/coupon.test.js
+++ b/test/coupon.test.js
@@ -1,8 +1,7 @@
-
-var assert = require('assert');
-var each = require('each');
-var noop = require('noop');
-var helpers = require('../support/helpers');
+var assert = require('component/assert');
+var each = require('component/each');
+var noop = require('chrissrogers/noop');
+var helpers = require('./support/helpers');
helpers.apiTest(function (requestMethod) {
describe('Recurly.coupon (' + requestMethod + ')', function () {
diff --git a/test/server/fixtures/paypal/start.json b/test/fixtures/paypal/start.json
similarity index 100%
rename from test/server/fixtures/paypal/start.json
rename to test/fixtures/paypal/start.json
diff --git a/test/server/fixtures/plans/basic/coupons/coop-invalid.json b/test/fixtures/plans/basic/coupons/coop-invalid.json
similarity index 100%
rename from test/server/fixtures/plans/basic/coupons/coop-invalid.json
rename to test/fixtures/plans/basic/coupons/coop-invalid.json
diff --git a/test/server/fixtures/plans/basic/coupons/coop-pct.json b/test/fixtures/plans/basic/coupons/coop-pct.json
similarity index 100%
rename from test/server/fixtures/plans/basic/coupons/coop-pct.json
rename to test/fixtures/plans/basic/coupons/coop-pct.json
diff --git a/test/server/fixtures/plans/basic/coupons/coop-single-use.json b/test/fixtures/plans/basic/coupons/coop-single-use.json
similarity index 100%
rename from test/server/fixtures/plans/basic/coupons/coop-single-use.json
rename to test/fixtures/plans/basic/coupons/coop-single-use.json
diff --git a/test/server/fixtures/plans/basic/coupons/coop.json b/test/fixtures/plans/basic/coupons/coop.json
similarity index 100%
rename from test/server/fixtures/plans/basic/coupons/coop.json
rename to test/fixtures/plans/basic/coupons/coop.json
diff --git a/test/server/fixtures/plans/basic/index.json b/test/fixtures/plans/basic/index.json
similarity index 100%
rename from test/server/fixtures/plans/basic/index.json
rename to test/fixtures/plans/basic/index.json
diff --git a/test/server/fixtures/plans/intermediate/coupons/coop-invalid.json b/test/fixtures/plans/intermediate/coupons/coop-invalid.json
similarity index 100%
rename from test/server/fixtures/plans/intermediate/coupons/coop-invalid.json
rename to test/fixtures/plans/intermediate/coupons/coop-invalid.json
diff --git a/test/server/fixtures/plans/intermediate/coupons/coop-pct.json b/test/fixtures/plans/intermediate/coupons/coop-pct.json
similarity index 100%
rename from test/server/fixtures/plans/intermediate/coupons/coop-pct.json
rename to test/fixtures/plans/intermediate/coupons/coop-pct.json
diff --git a/test/server/fixtures/plans/intermediate/coupons/coop.json b/test/fixtures/plans/intermediate/coupons/coop.json
similarity index 100%
rename from test/server/fixtures/plans/intermediate/coupons/coop.json
rename to test/fixtures/plans/intermediate/coupons/coop.json
diff --git a/test/server/fixtures/plans/intermediate/index.json b/test/fixtures/plans/intermediate/index.json
similarity index 100%
rename from test/server/fixtures/plans/intermediate/index.json
rename to test/fixtures/plans/intermediate/index.json
diff --git a/test/server/fixtures/plans/invalid/coupons/coop.json b/test/fixtures/plans/invalid/coupons/coop.json
similarity index 100%
rename from test/server/fixtures/plans/invalid/coupons/coop.json
rename to test/fixtures/plans/invalid/coupons/coop.json
diff --git a/test/server/fixtures/plans/invalid/index.json b/test/fixtures/plans/invalid/index.json
similarity index 100%
rename from test/server/fixtures/plans/invalid/index.json
rename to test/fixtures/plans/invalid/index.json
diff --git a/test/server/fixtures/plans/tax_exempt.json b/test/fixtures/plans/tax_exempt.json
similarity index 100%
rename from test/server/fixtures/plans/tax_exempt.json
rename to test/fixtures/plans/tax_exempt.json
diff --git a/test/server/post-message.jade b/test/fixtures/post-message.html.ejs
similarity index 92%
rename from test/server/post-message.jade
rename to test/fixtures/post-message.html.ejs
index e14852998..163781751 100644
--- a/test/server/post-message.jade
+++ b/test/fixtures/post-message.html.ejs
@@ -1,10 +1,9 @@
-doctype html
-html
- script.
+
+
+
+
diff --git a/test/fixtures/relay.html.ejs b/test/fixtures/relay.html.ejs
new file mode 100644
index 000000000..fcc75fd15
--- /dev/null
+++ b/test/fixtures/relay.html.ejs
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/test/server/fixtures/tax/index.js b/test/fixtures/tax/index.js
similarity index 69%
rename from test/server/fixtures/tax/index.js
rename to test/fixtures/tax/index.js
index bc25c0f7d..aea649990 100644
--- a/test/server/fixtures/tax/index.js
+++ b/test/fixtures/tax/index.js
@@ -36,11 +36,11 @@ var VAT_2015_COUNTRY = 'GB';
* - all other requests
*/
-module.exports = function tax (req, res) {
- if (req.query.country === 'US' && req.query.postal_code === USST_POSTAL_CODE) return usst;
- if (req.query.country === 'US' && req.query.postal_code === USST_POSTAL_CODE_WITH_REGION) return usstWithRegion;
- if (req.query.country === VAT_COUNTRY) return vat;
- if (req.query.country === VAT_2015_COUNTRY) return vat2015;
+module.exports = function tax () {
+ if (this.query.country === 'US' && this.query.postal_code === USST_POSTAL_CODE) return usst;
+ if (this.query.country === 'US' && this.query.postal_code === USST_POSTAL_CODE_WITH_REGION) return usstWithRegion;
+ if (this.query.country === VAT_COUNTRY) return vat;
+ if (this.query.country === VAT_2015_COUNTRY) return vat2015;
return none;
};
diff --git a/test/server/fixtures/token/index.js b/test/fixtures/token/index.js
similarity index 85%
rename from test/server/fixtures/token/index.js
rename to test/fixtures/token/index.js
index d6d7be203..e473ca37c 100644
--- a/test/server/fixtures/token/index.js
+++ b/test/fixtures/token/index.js
@@ -10,8 +10,8 @@
var DECLINE_CARD = '4000000000000002';
-module.exports = function token (req, res) {
- var params = req.method === 'GET' ? req.query : req.body;
+module.exports = function token () {
+ var params = this.method === 'GET' ? this.query : this.request.body;
if (params.number === DECLINE_CARD) return decline;
else return ok;
};
diff --git a/test/index.html b/test/index.html
new file mode 100644
index 000000000..4911ac971
--- /dev/null
+++ b/test/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+ recurly-js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/index.js b/test/index.js
deleted file mode 100644
index c45b80b7a..000000000
--- a/test/index.js
+++ /dev/null
@@ -1,13 +0,0 @@
-
-gravy = require('gravy');
-
-require('./unit/recurly.test.js');
-require('./unit/configure.test.js');
-require('./unit/coupon.test.js');
-require('./unit/open.test.js');
-require('./unit/plan.test.js');
-require('./unit/pricing.test.js');
-require('./unit/tax.test.js');
-require('./unit/token.test.js');
-require('./unit/bank-account.test.js');
-require('./unit/validate.test.js');
diff --git a/test/unit/open.test.js b/test/open.test.js
similarity index 96%
rename from test/unit/open.test.js
rename to test/open.test.js
index 97085c0c4..fe7664642 100644
--- a/test/unit/open.test.js
+++ b/test/open.test.js
@@ -1,7 +1,6 @@
-
-var assert = require('assert');
-var each = require('each');
-var noop = require('noop');
+var assert = require('component/assert');
+var each = require('component/each');
+var noop = require('chrissrogers/noop');
describe('Recurly.open', function () {
var Recurly = window.recurly.Recurly;
diff --git a/test/unit/plan.test.js b/test/plan.test.js
similarity index 92%
rename from test/unit/plan.test.js
rename to test/plan.test.js
index 989f7d3a2..ec6700821 100644
--- a/test/unit/plan.test.js
+++ b/test/plan.test.js
@@ -1,7 +1,6 @@
-
-var assert = require('assert');
-var noop = require('noop');
-var helpers = require('../support/helpers');
+var assert = require('component/assert');
+var noop = require('chrissrogers/noop');
+var helpers = require('./support/helpers');
helpers.apiTest(function (requestMethod) {
describe('Recurly.plan (' + requestMethod + ')', function () {
diff --git a/test/unit/pricing.test.js b/test/pricing.test.js
similarity index 97%
rename from test/unit/pricing.test.js
rename to test/pricing.test.js
index d29584f5f..c31943704 100644
--- a/test/unit/pricing.test.js
+++ b/test/pricing.test.js
@@ -1,5 +1,4 @@
-
-var assert = require('assert');
+var assert = require('component/assert');
describe('Recurly.Pricing', function () {
var Recurly = window.recurly.Recurly;
@@ -112,7 +111,7 @@ describe('Recurly.Pricing', function () {
});
});
- it('should append 20% of 49.00 to have a correct tax of $9.80', function (done) {
+ it('should append 20 pct. of 49.00 to have a correct tax of $9.80', function (done) {
pricing
.plan('intermediate', { quantity: 1 })
.address({
diff --git a/test/unit/recurly.test.js b/test/recurly.test.js
similarity index 93%
rename from test/unit/recurly.test.js
rename to test/recurly.test.js
index b944cfc48..e77245f85 100644
--- a/test/unit/recurly.test.js
+++ b/test/recurly.test.js
@@ -1,6 +1,5 @@
-
-var assert = require('assert');
-var noop = require('noop');
+var assert = require('component/assert');
+var noop = require('chrissrogers/noop');
describe('Recurly', function () {
var Recurly = window.recurly.Recurly;
diff --git a/test/server/coverage.jade b/test/server/coverage.jade
deleted file mode 100644
index dd70425f9..000000000
--- a/test/server/coverage.jade
+++ /dev/null
@@ -1,18 +0,0 @@
-doctype html
-html
- head
- title recurly.js coverage
- script(src='/test/server/mocha.js')
- script
- mocha.setup({ ui: 'bdd' })
- script(src='/test/build.js')
- script
- cov = require('coverage')('recurly');
- script(src='/recurly.js')
- body
- #coverage
- #mocha(style='display: none;')
- script
- mocha.run(function(){
- cov.render();
- });
diff --git a/test/server/index.jade b/test/server/index.jade
deleted file mode 100644
index 459fbd768..000000000
--- a/test/server/index.jade
+++ /dev/null
@@ -1,19 +0,0 @@
-doctype html
-html
- head
- title recurly.js tests
- link(rel='stylesheet', href='/test/server/mocha.css')
- script(src='/build/recurly.js')
- script(src='/test/server/sinon.js')
- script(src='/test/server/mocha.js')
- script.
- mocha.setup({ ui: 'bdd' });
- mocha.timeout(0);
- script(src='/test/build.js')
- body
- #mocha
- #dom-testbed
- script.
- var m = window.mochaPhantomJS || window.mocha;
- var g = window.gravy || function () {};
- g(m.run());
diff --git a/test/server/index.js b/test/server/index.js
deleted file mode 100644
index 7fc472422..000000000
--- a/test/server/index.js
+++ /dev/null
@@ -1,110 +0,0 @@
-
-/*!
- * Module dependencies.
- */
-
-var fs = require('fs');
-var path = require('path');
-var express = require('express');
-var bodyParser = require('body-parser');
-var app = module.exports = express();
-
-/**
- * Settings.
- */
-
-app.set('views', __dirname);
-app.set('view engine', 'jade');
-app.set('view options', { debug: true })
-app.set('port', process.env.PORT || 8989);
-app.set('jsonp callback name', 'callback');
-
-/**
- * Locals.
- */
-
-app.locals.pretty = true;
-
-/**
- * Middleware.
- */
-
-app.use(express.logger());
-
-// This corrects an incorrect Content-type header
-// sent by IE9 XDomainRequests
-app.use(function (req, res, next) {
- if (req.method === 'POST') {
- req.headers['content-type'] = 'application/x-www-form-urlencoded';
- }
- next();
-});
-
-app.use(express.bodyParser());
-app.use(express.static(path.resolve(__dirname + '/../..')));
-
-// CORS headers
-app.use(function (req, res, next) {
- res.set({
- 'Access-Control-Allow-Credentials': 'true',
- 'Access-Control-Allow-Headers': 'Accept, Accept-Encoding, Accept-Language, Content-Type, Origin, User-Agent, X-Requested-With',
- 'Access-Control-Allow-Origin': '*',
- 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS'
- });
- next();
-});
-
-/**
- * Fixtures.
- */
-
-app.get('/plans/:plan_code', json);
-app.get('/plans/:plan_code/coupons/:coupon_code', json);
-app.get('/token', json);
-app.post('/token', json);
-app.get('/tax', json);
-app.get('/paypal/start', postMessage);
-app.get('/relay', render('relay'));
-app.get('*', render('index'));
-
-/**
- * Listen.
- */
-
-app.listen(app.get('port'), function () {
- fs.writeFileSync(__dirname + '/pid.txt', process.pid, 'utf-8');
-});
-
-/**
- * Utility functions.
- */
-
-function render (view) {
- return function (req, res) {
- res.render(view);
- };
-}
-
-function json (req, res) {
- if (req.query.callback) {
- res.jsonp(fixture(req, res));
- } else {
- res.json(fixture(req, res));
- }
-}
-
-function postMessage (req, res) {
- res.render('post-message', {
- message: {
- recurly_event: req.query.event
- , recurly_message: fixture(req, res)
- }
- });
-}
-
-function fixture (req, res) {
- var fixture = require('./fixtures' + req.path);
- return 'function' === typeof fixture
- ? fixture(req, res)
- : fixture;
-}
diff --git a/test/server/relay.jade b/test/server/relay.jade
deleted file mode 100644
index 2100b46d8..000000000
--- a/test/server/relay.jade
+++ /dev/null
@@ -1,9 +0,0 @@
-doctype html
-html
- head
- script.
- function send (msg, origin) {
- setTimeout(function () {
- window.parent.postMessage(msg, origin);
- }, 0);
- }
diff --git a/test/server/sinon.js b/test/server/sinon.js
deleted file mode 100644
index 703414dd4..000000000
--- a/test/server/sinon.js
+++ /dev/null
@@ -1,5073 +0,0 @@
-/**
- * Sinon.JS 1.10.3, 2014/07/11
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
- *
- * (The BSD License)
- *
- * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of Christian Johansen nor the names of his contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-this.sinon = (function () {
-var samsam, formatio;
-function define(mod, deps, fn) { if (mod == "samsam") { samsam = deps(); } else if (typeof fn === "function") { formatio = fn(samsam); } }
-define.amd = {};
-((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
- (typeof module === "object" &&
- function (m) { module.exports = m(); }) || // Node
- function (m) { this.samsam = m(); } // Browser globals
-)(function () {
- var o = Object.prototype;
- var div = typeof document !== "undefined" && document.createElement("div");
-
- function isNaN(value) {
- // Unlike global isNaN, this avoids type coercion
- // typeof check avoids IE host object issues, hat tip to
- // lodash
- var val = value; // JsLint thinks value !== value is "weird"
- return typeof value === "number" && value !== val;
- }
-
- function getClass(value) {
- // Returns the internal [[Class]] by calling Object.prototype.toString
- // with the provided value as this. Return value is a string, naming the
- // internal class, e.g. "Array"
- return o.toString.call(value).split(/[ \]]/)[1];
- }
-
- /**
- * @name samsam.isArguments
- * @param Object object
- *
- * Returns ``true`` if ``object`` is an ``arguments`` object,
- * ``false`` otherwise.
- */
- function isArguments(object) {
- if (typeof object !== "object" || typeof object.length !== "number" ||
- getClass(object) === "Array") {
- return false;
- }
- if (typeof object.callee == "function") { return true; }
- try {
- object[object.length] = 6;
- delete object[object.length];
- } catch (e) {
- return true;
- }
- return false;
- }
-
- /**
- * @name samsam.isElement
- * @param Object object
- *
- * Returns ``true`` if ``object`` is a DOM element node. Unlike
- * Underscore.js/lodash, this function will return ``false`` if ``object``
- * is an *element-like* object, i.e. a regular object with a ``nodeType``
- * property that holds the value ``1``.
- */
- function isElement(object) {
- if (!object || object.nodeType !== 1 || !div) { return false; }
- try {
- object.appendChild(div);
- object.removeChild(div);
- } catch (e) {
- return false;
- }
- return true;
- }
-
- /**
- * @name samsam.keys
- * @param Object object
- *
- * Return an array of own property names.
- */
- function keys(object) {
- var ks = [], prop;
- for (prop in object) {
- if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
- }
- return ks;
- }
-
- /**
- * @name samsam.isDate
- * @param Object value
- *
- * Returns true if the object is a ``Date``, or *date-like*. Duck typing
- * of date objects work by checking that the object has a ``getTime``
- * function whose return value equals the return value from the object's
- * ``valueOf``.
- */
- function isDate(value) {
- return typeof value.getTime == "function" &&
- value.getTime() == value.valueOf();
- }
-
- /**
- * @name samsam.isNegZero
- * @param Object value
- *
- * Returns ``true`` if ``value`` is ``-0``.
- */
- function isNegZero(value) {
- return value === 0 && 1 / value === -Infinity;
- }
-
- /**
- * @name samsam.equal
- * @param Object obj1
- * @param Object obj2
- *
- * Returns ``true`` if two objects are strictly equal. Compared to
- * ``===`` there are two exceptions:
- *
- * - NaN is considered equal to NaN
- * - -0 and +0 are not considered equal
- */
- function identical(obj1, obj2) {
- if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
- return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
- }
- }
-
-
- /**
- * @name samsam.deepEqual
- * @param Object obj1
- * @param Object obj2
- *
- * Deep equal comparison. Two values are "deep equal" if:
- *
- * - They are equal, according to samsam.identical
- * - They are both date objects representing the same time
- * - They are both arrays containing elements that are all deepEqual
- * - They are objects with the same set of properties, and each property
- * in ``obj1`` is deepEqual to the corresponding property in ``obj2``
- *
- * Supports cyclic objects.
- */
- function deepEqualCyclic(obj1, obj2) {
-
- // used for cyclic comparison
- // contain already visited objects
- var objects1 = [],
- objects2 = [],
- // contain pathes (position in the object structure)
- // of the already visited objects
- // indexes same as in objects arrays
- paths1 = [],
- paths2 = [],
- // contains combinations of already compared objects
- // in the manner: { "$1['ref']$2['ref']": true }
- compared = {};
-
- /**
- * used to check, if the value of a property is an object
- * (cyclic logic is only needed for objects)
- * only needed for cyclic logic
- */
- function isObject(value) {
-
- if (typeof value === 'object' && value !== null &&
- !(value instanceof Boolean) &&
- !(value instanceof Date) &&
- !(value instanceof Number) &&
- !(value instanceof RegExp) &&
- !(value instanceof String)) {
-
- return true;
- }
-
- return false;
- }
-
- /**
- * returns the index of the given object in the
- * given objects array, -1 if not contained
- * only needed for cyclic logic
- */
- function getIndex(objects, obj) {
-
- var i;
- for (i = 0; i < objects.length; i++) {
- if (objects[i] === obj) {
- return i;
- }
- }
-
- return -1;
- }
-
- // does the recursion for the deep equal check
- return (function deepEqual(obj1, obj2, path1, path2) {
- var type1 = typeof obj1;
- var type2 = typeof obj2;
-
- // == null also matches undefined
- if (obj1 === obj2 ||
- isNaN(obj1) || isNaN(obj2) ||
- obj1 == null || obj2 == null ||
- type1 !== "object" || type2 !== "object") {
-
- return identical(obj1, obj2);
- }
-
- // Elements are only equal if identical(expected, actual)
- if (isElement(obj1) || isElement(obj2)) { return false; }
-
- var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
- if (isDate1 || isDate2) {
- if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
- return false;
- }
- }
-
- if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
- if (obj1.toString() !== obj2.toString()) { return false; }
- }
-
- var class1 = getClass(obj1);
- var class2 = getClass(obj2);
- var keys1 = keys(obj1);
- var keys2 = keys(obj2);
-
- if (isArguments(obj1) || isArguments(obj2)) {
- if (obj1.length !== obj2.length) { return false; }
- } else {
- if (type1 !== type2 || class1 !== class2 ||
- keys1.length !== keys2.length) {
- return false;
- }
- }
-
- var key, i, l,
- // following vars are used for the cyclic logic
- value1, value2,
- isObject1, isObject2,
- index1, index2,
- newPath1, newPath2;
-
- for (i = 0, l = keys1.length; i < l; i++) {
- key = keys1[i];
- if (!o.hasOwnProperty.call(obj2, key)) {
- return false;
- }
-
- // Start of the cyclic logic
-
- value1 = obj1[key];
- value2 = obj2[key];
-
- isObject1 = isObject(value1);
- isObject2 = isObject(value2);
-
- // determine, if the objects were already visited
- // (it's faster to check for isObject first, than to
- // get -1 from getIndex for non objects)
- index1 = isObject1 ? getIndex(objects1, value1) : -1;
- index2 = isObject2 ? getIndex(objects2, value2) : -1;
-
- // determine the new pathes of the objects
- // - for non cyclic objects the current path will be extended
- // by current property name
- // - for cyclic objects the stored path is taken
- newPath1 = index1 !== -1
- ? paths1[index1]
- : path1 + '[' + JSON.stringify(key) + ']';
- newPath2 = index2 !== -1
- ? paths2[index2]
- : path2 + '[' + JSON.stringify(key) + ']';
-
- // stop recursion if current objects are already compared
- if (compared[newPath1 + newPath2]) {
- return true;
- }
-
- // remember the current objects and their pathes
- if (index1 === -1 && isObject1) {
- objects1.push(value1);
- paths1.push(newPath1);
- }
- if (index2 === -1 && isObject2) {
- objects2.push(value2);
- paths2.push(newPath2);
- }
-
- // remember that the current objects are already compared
- if (isObject1 && isObject2) {
- compared[newPath1 + newPath2] = true;
- }
-
- // End of cyclic logic
-
- // neither value1 nor value2 is a cycle
- // continue with next level
- if (!deepEqual(value1, value2, newPath1, newPath2)) {
- return false;
- }
- }
-
- return true;
-
- }(obj1, obj2, '$1', '$2'));
- }
-
- var match;
-
- function arrayContains(array, subset) {
- if (subset.length === 0) { return true; }
- var i, l, j, k;
- for (i = 0, l = array.length; i < l; ++i) {
- if (match(array[i], subset[0])) {
- for (j = 0, k = subset.length; j < k; ++j) {
- if (!match(array[i + j], subset[j])) { return false; }
- }
- return true;
- }
- }
- return false;
- }
-
- /**
- * @name samsam.match
- * @param Object object
- * @param Object matcher
- *
- * Compare arbitrary value ``object`` with matcher.
- */
- match = function match(object, matcher) {
- if (matcher && typeof matcher.test === "function") {
- return matcher.test(object);
- }
-
- if (typeof matcher === "function") {
- return matcher(object) === true;
- }
-
- if (typeof matcher === "string") {
- matcher = matcher.toLowerCase();
- var notNull = typeof object === "string" || !!object;
- return notNull &&
- (String(object)).toLowerCase().indexOf(matcher) >= 0;
- }
-
- if (typeof matcher === "number") {
- return matcher === object;
- }
-
- if (typeof matcher === "boolean") {
- return matcher === object;
- }
-
- if (getClass(object) === "Array" && getClass(matcher) === "Array") {
- return arrayContains(object, matcher);
- }
-
- if (matcher && typeof matcher === "object") {
- var prop;
- for (prop in matcher) {
- if (!match(object[prop], matcher[prop])) {
- return false;
- }
- }
- return true;
- }
-
- throw new Error("Matcher was not a string, a number, a " +
- "function, a boolean or an object");
- };
-
- return {
- isArguments: isArguments,
- isElement: isElement,
- isDate: isDate,
- isNegZero: isNegZero,
- identical: identical,
- deepEqual: deepEqualCyclic,
- match: match,
- keys: keys
- };
-});
-((typeof define === "function" && define.amd && function (m) {
- define("formatio", ["samsam"], m);
-}) || (typeof module === "object" && function (m) {
- module.exports = m(require("samsam"));
-}) || function (m) { this.formatio = m(this.samsam); }
-)(function (samsam) {
-
- var formatio = {
- excludeConstructors: ["Object", /^.$/],
- quoteStrings: true
- };
-
- var hasOwn = Object.prototype.hasOwnProperty;
-
- var specialObjects = [];
- if (typeof global !== "undefined") {
- specialObjects.push({ object: global, value: "[object global]" });
- }
- if (typeof document !== "undefined") {
- specialObjects.push({
- object: document,
- value: "[object HTMLDocument]"
- });
- }
- if (typeof window !== "undefined") {
- specialObjects.push({ object: window, value: "[object Window]" });
- }
-
- function functionName(func) {
- if (!func) { return ""; }
- if (func.displayName) { return func.displayName; }
- if (func.name) { return func.name; }
- var matches = func.toString().match(/function\s+([^\(]+)/m);
- return (matches && matches[1]) || "";
- }
-
- function constructorName(f, object) {
- var name = functionName(object && object.constructor);
- var excludes = f.excludeConstructors ||
- formatio.excludeConstructors || [];
-
- var i, l;
- for (i = 0, l = excludes.length; i < l; ++i) {
- if (typeof excludes[i] === "string" && excludes[i] === name) {
- return "";
- } else if (excludes[i].test && excludes[i].test(name)) {
- return "";
- }
- }
-
- return name;
- }
-
- function isCircular(object, objects) {
- if (typeof object !== "object") { return false; }
- var i, l;
- for (i = 0, l = objects.length; i < l; ++i) {
- if (objects[i] === object) { return true; }
- }
- return false;
- }
-
- function ascii(f, object, processed, indent) {
- if (typeof object === "string") {
- var qs = f.quoteStrings;
- var quote = typeof qs !== "boolean" || qs;
- return processed || quote ? '"' + object + '"' : object;
- }
-
- if (typeof object === "function" && !(object instanceof RegExp)) {
- return ascii.func(object);
- }
-
- processed = processed || [];
-
- if (isCircular(object, processed)) { return "[Circular]"; }
-
- if (Object.prototype.toString.call(object) === "[object Array]") {
- return ascii.array.call(f, object, processed);
- }
-
- if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
- if (samsam.isElement(object)) { return ascii.element(object); }
-
- if (typeof object.toString === "function" &&
- object.toString !== Object.prototype.toString) {
- return object.toString();
- }
-
- var i, l;
- for (i = 0, l = specialObjects.length; i < l; i++) {
- if (object === specialObjects[i].object) {
- return specialObjects[i].value;
- }
- }
-
- return ascii.object.call(f, object, processed, indent);
- }
-
- ascii.func = function (func) {
- return "function " + functionName(func) + "() {}";
- };
-
- ascii.array = function (array, processed) {
- processed = processed || [];
- processed.push(array);
- var i, l, pieces = [];
- for (i = 0, l = array.length; i < l; ++i) {
- pieces.push(ascii(this, array[i], processed));
- }
- return "[" + pieces.join(", ") + "]";
- };
-
- ascii.object = function (object, processed, indent) {
- processed = processed || [];
- processed.push(object);
- indent = indent || 0;
- var pieces = [], properties = samsam.keys(object).sort();
- var length = 3;
- var prop, str, obj, i, l;
-
- for (i = 0, l = properties.length; i < l; ++i) {
- prop = properties[i];
- obj = object[prop];
-
- if (isCircular(obj, processed)) {
- str = "[Circular]";
- } else {
- str = ascii(this, obj, processed, indent + 2);
- }
-
- str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
- length += str.length;
- pieces.push(str);
- }
-
- var cons = constructorName(this, object);
- var prefix = cons ? "[" + cons + "] " : "";
- var is = "";
- for (i = 0, l = indent; i < l; ++i) { is += " "; }
-
- if (length + indent > 80) {
- return prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" +
- is + "}";
- }
- return prefix + "{ " + pieces.join(", ") + " }";
- };
-
- ascii.element = function (element) {
- var tagName = element.tagName.toLowerCase();
- var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
-
- for (i = 0, l = attrs.length; i < l; ++i) {
- attr = attrs.item(i);
- attrName = attr.nodeName.toLowerCase().replace("html:", "");
- val = attr.nodeValue;
- if (attrName !== "contenteditable" || val !== "inherit") {
- if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
- }
- }
-
- var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
- var content = element.innerHTML;
-
- if (content.length > 20) {
- content = content.substr(0, 20) + "[...]";
- }
-
- var res = formatted + pairs.join(" ") + ">" + content +
- "" + tagName + ">";
-
- return res.replace(/ contentEditable="inherit"/, "");
- };
-
- function Formatio(options) {
- for (var opt in options) {
- this[opt] = options[opt];
- }
- }
-
- Formatio.prototype = {
- functionName: functionName,
-
- configure: function (options) {
- return new Formatio(options);
- },
-
- constructorName: function (object) {
- return constructorName(this, object);
- },
-
- ascii: function (object, processed, indent) {
- return ascii(this, object, processed, indent);
- }
- };
-
- return Formatio.prototype;
-});
-/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
-/*global module, require, __dirname, document*/
-/**
- * Sinon core utilities. For internal use only.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-var sinon = (function (formatio) {
- var div = typeof document != "undefined" && document.createElement("div");
- var hasOwn = Object.prototype.hasOwnProperty;
-
- function isDOMNode(obj) {
- var success = false;
-
- try {
- obj.appendChild(div);
- success = div.parentNode == obj;
- } catch (e) {
- return false;
- } finally {
- try {
- obj.removeChild(div);
- } catch (e) {
- // Remove failed, not much we can do about that
- }
- }
-
- return success;
- }
-
- function isElement(obj) {
- return div && obj && obj.nodeType === 1 && isDOMNode(obj);
- }
-
- function isFunction(obj) {
- return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
- }
-
- function isReallyNaN(val) {
- return typeof val === 'number' && isNaN(val);
- }
-
- function mirrorProperties(target, source) {
- for (var prop in source) {
- if (!hasOwn.call(target, prop)) {
- target[prop] = source[prop];
- }
- }
- }
-
- function isRestorable (obj) {
- return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
- }
-
- var sinon = {
- wrapMethod: function wrapMethod(object, property, method) {
- if (!object) {
- throw new TypeError("Should wrap property of object");
- }
-
- if (typeof method != "function") {
- throw new TypeError("Method wrapper should be function");
- }
-
- var wrappedMethod = object[property],
- error;
-
- if (!isFunction(wrappedMethod)) {
- error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
- property + " as function");
- } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
- error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
- } else if (wrappedMethod.calledBefore) {
- var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
- error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
- }
-
- if (error) {
- if (wrappedMethod && wrappedMethod._stack) {
- error.stack += '\n--------------\n' + wrappedMethod._stack;
- }
- throw error;
- }
-
- // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
- // when using hasOwn.call on objects from other frames.
- var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
- object[property] = method;
- method.displayName = property;
- // Set up a stack trace which can be used later to find what line of
- // code the original method was created on.
- method._stack = (new Error('Stack Trace for original')).stack;
-
- method.restore = function () {
- // For prototype properties try to reset by delete first.
- // If this fails (ex: localStorage on mobile safari) then force a reset
- // via direct assignment.
- if (!owned) {
- delete object[property];
- }
- if (object[property] === method) {
- object[property] = wrappedMethod;
- }
- };
-
- method.restore.sinon = true;
- mirrorProperties(method, wrappedMethod);
-
- return method;
- },
-
- extend: function extend(target) {
- for (var i = 1, l = arguments.length; i < l; i += 1) {
- for (var prop in arguments[i]) {
- if (arguments[i].hasOwnProperty(prop)) {
- target[prop] = arguments[i][prop];
- }
-
- // DONT ENUM bug, only care about toString
- if (arguments[i].hasOwnProperty("toString") &&
- arguments[i].toString != target.toString) {
- target.toString = arguments[i].toString;
- }
- }
- }
-
- return target;
- },
-
- create: function create(proto) {
- var F = function () {};
- F.prototype = proto;
- return new F();
- },
-
- deepEqual: function deepEqual(a, b) {
- if (sinon.match && sinon.match.isMatcher(a)) {
- return a.test(b);
- }
-
- if (typeof a != 'object' || typeof b != 'object') {
- if (isReallyNaN(a) && isReallyNaN(b)) {
- return true;
- } else {
- return a === b;
- }
- }
-
- if (isElement(a) || isElement(b)) {
- return a === b;
- }
-
- if (a === b) {
- return true;
- }
-
- if ((a === null && b !== null) || (a !== null && b === null)) {
- return false;
- }
-
- if (a instanceof RegExp && b instanceof RegExp) {
- return (a.source === b.source) && (a.global === b.global) &&
- (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
- }
-
- var aString = Object.prototype.toString.call(a);
- if (aString != Object.prototype.toString.call(b)) {
- return false;
- }
-
- if (aString == "[object Date]") {
- return a.valueOf() === b.valueOf();
- }
-
- var prop, aLength = 0, bLength = 0;
-
- if (aString == "[object Array]" && a.length !== b.length) {
- return false;
- }
-
- for (prop in a) {
- aLength += 1;
-
- if (!(prop in b)) {
- return false;
- }
-
- if (!deepEqual(a[prop], b[prop])) {
- return false;
- }
- }
-
- for (prop in b) {
- bLength += 1;
- }
-
- return aLength == bLength;
- },
-
- functionName: function functionName(func) {
- var name = func.displayName || func.name;
-
- // Use function decomposition as a last resort to get function
- // name. Does not rely on function decomposition to work - if it
- // doesn't debugging will be slightly less informative
- // (i.e. toString will say 'spy' rather than 'myFunc').
- if (!name) {
- var matches = func.toString().match(/function ([^\s\(]+)/);
- name = matches && matches[1];
- }
-
- return name;
- },
-
- functionToString: function toString() {
- if (this.getCall && this.callCount) {
- var thisValue, prop, i = this.callCount;
-
- while (i--) {
- thisValue = this.getCall(i).thisValue;
-
- for (prop in thisValue) {
- if (thisValue[prop] === this) {
- return prop;
- }
- }
- }
- }
-
- return this.displayName || "sinon fake";
- },
-
- getConfig: function (custom) {
- var config = {};
- custom = custom || {};
- var defaults = sinon.defaultConfig;
-
- for (var prop in defaults) {
- if (defaults.hasOwnProperty(prop)) {
- config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
- }
- }
-
- return config;
- },
-
- format: function (val) {
- return "" + val;
- },
-
- defaultConfig: {
- injectIntoThis: true,
- injectInto: null,
- properties: ["spy", "stub", "mock", "clock", "server", "requests"],
- useFakeTimers: true,
- useFakeServer: true
- },
-
- timesInWords: function timesInWords(count) {
- return count == 1 && "once" ||
- count == 2 && "twice" ||
- count == 3 && "thrice" ||
- (count || 0) + " times";
- },
-
- calledInOrder: function (spies) {
- for (var i = 1, l = spies.length; i < l; i++) {
- if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
- return false;
- }
- }
-
- return true;
- },
-
- orderByFirstCall: function (spies) {
- return spies.sort(function (a, b) {
- // uuid, won't ever be equal
- var aCall = a.getCall(0);
- var bCall = b.getCall(0);
- var aId = aCall && aCall.callId || -1;
- var bId = bCall && bCall.callId || -1;
-
- return aId < bId ? -1 : 1;
- });
- },
-
- log: function () {},
-
- logError: function (label, err) {
- var msg = label + " threw exception: ";
- sinon.log(msg + "[" + err.name + "] " + err.message);
- if (err.stack) { sinon.log(err.stack); }
-
- setTimeout(function () {
- err.message = msg + err.message;
- throw err;
- }, 0);
- },
-
- typeOf: function (value) {
- if (value === null) {
- return "null";
- }
- else if (value === undefined) {
- return "undefined";
- }
- var string = Object.prototype.toString.call(value);
- return string.substring(8, string.length - 1).toLowerCase();
- },
-
- createStubInstance: function (constructor) {
- if (typeof constructor !== "function") {
- throw new TypeError("The constructor should be a function.");
- }
- return sinon.stub(sinon.create(constructor.prototype));
- },
-
- restore: function (object) {
- if (object !== null && typeof object === "object") {
- for (var prop in object) {
- if (isRestorable(object[prop])) {
- object[prop].restore();
- }
- }
- }
- else if (isRestorable(object)) {
- object.restore();
- }
- }
- };
-
- var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
- var isAMD = typeof define === 'function' && typeof define.amd === 'object' && define.amd;
-
- function makePublicAPI(require, exports, module) {
- module.exports = sinon;
- sinon.spy = require("./sinon/spy");
- sinon.spyCall = require("./sinon/call");
- sinon.behavior = require("./sinon/behavior");
- sinon.stub = require("./sinon/stub");
- sinon.mock = require("./sinon/mock");
- sinon.collection = require("./sinon/collection");
- sinon.assert = require("./sinon/assert");
- sinon.sandbox = require("./sinon/sandbox");
- sinon.test = require("./sinon/test");
- sinon.testCase = require("./sinon/test_case");
- sinon.match = require("./sinon/match");
- }
-
- if (isAMD) {
- define(makePublicAPI);
- } else if (isNode) {
- try {
- formatio = require("formatio");
- } catch (e) {}
- makePublicAPI(require, exports, module);
- }
-
- if (formatio) {
- var formatter = formatio.configure({ quoteStrings: false });
- sinon.format = function () {
- return formatter.ascii.apply(formatter, arguments);
- };
- } else if (isNode) {
- try {
- var util = require("util");
- sinon.format = function (value) {
- return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
- };
- } catch (e) {
- /* Node, but no util module - would be very old, but better safe than
- sorry */
- }
- }
-
- return sinon;
-}(typeof formatio == "object" && formatio));
-
-/* @depend ../sinon.js */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Match functions
- *
- * @author Maximilian Antoni (mail@maxantoni.de)
- * @license BSD
- *
- * Copyright (c) 2012 Maximilian Antoni
- */
-
-(function (sinon) {
- var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
-
- if (!sinon && commonJSModule) {
- sinon = require("../sinon");
- }
-
- if (!sinon) {
- return;
- }
-
- function assertType(value, type, name) {
- var actual = sinon.typeOf(value);
- if (actual !== type) {
- throw new TypeError("Expected type of " + name + " to be " +
- type + ", but was " + actual);
- }
- }
-
- var matcher = {
- toString: function () {
- return this.message;
- }
- };
-
- function isMatcher(object) {
- return matcher.isPrototypeOf(object);
- }
-
- function matchObject(expectation, actual) {
- if (actual === null || actual === undefined) {
- return false;
- }
- for (var key in expectation) {
- if (expectation.hasOwnProperty(key)) {
- var exp = expectation[key];
- var act = actual[key];
- if (match.isMatcher(exp)) {
- if (!exp.test(act)) {
- return false;
- }
- } else if (sinon.typeOf(exp) === "object") {
- if (!matchObject(exp, act)) {
- return false;
- }
- } else if (!sinon.deepEqual(exp, act)) {
- return false;
- }
- }
- }
- return true;
- }
-
- matcher.or = function (m2) {
- if (!arguments.length) {
- throw new TypeError("Matcher expected");
- } else if (!isMatcher(m2)) {
- m2 = match(m2);
- }
- var m1 = this;
- var or = sinon.create(matcher);
- or.test = function (actual) {
- return m1.test(actual) || m2.test(actual);
- };
- or.message = m1.message + ".or(" + m2.message + ")";
- return or;
- };
-
- matcher.and = function (m2) {
- if (!arguments.length) {
- throw new TypeError("Matcher expected");
- } else if (!isMatcher(m2)) {
- m2 = match(m2);
- }
- var m1 = this;
- var and = sinon.create(matcher);
- and.test = function (actual) {
- return m1.test(actual) && m2.test(actual);
- };
- and.message = m1.message + ".and(" + m2.message + ")";
- return and;
- };
-
- var match = function (expectation, message) {
- var m = sinon.create(matcher);
- var type = sinon.typeOf(expectation);
- switch (type) {
- case "object":
- if (typeof expectation.test === "function") {
- m.test = function (actual) {
- return expectation.test(actual) === true;
- };
- m.message = "match(" + sinon.functionName(expectation.test) + ")";
- return m;
- }
- var str = [];
- for (var key in expectation) {
- if (expectation.hasOwnProperty(key)) {
- str.push(key + ": " + expectation[key]);
- }
- }
- m.test = function (actual) {
- return matchObject(expectation, actual);
- };
- m.message = "match(" + str.join(", ") + ")";
- break;
- case "number":
- m.test = function (actual) {
- return expectation == actual;
- };
- break;
- case "string":
- m.test = function (actual) {
- if (typeof actual !== "string") {
- return false;
- }
- return actual.indexOf(expectation) !== -1;
- };
- m.message = "match(\"" + expectation + "\")";
- break;
- case "regexp":
- m.test = function (actual) {
- if (typeof actual !== "string") {
- return false;
- }
- return expectation.test(actual);
- };
- break;
- case "function":
- m.test = expectation;
- if (message) {
- m.message = message;
- } else {
- m.message = "match(" + sinon.functionName(expectation) + ")";
- }
- break;
- default:
- m.test = function (actual) {
- return sinon.deepEqual(expectation, actual);
- };
- }
- if (!m.message) {
- m.message = "match(" + expectation + ")";
- }
- return m;
- };
-
- match.isMatcher = isMatcher;
-
- match.any = match(function () {
- return true;
- }, "any");
-
- match.defined = match(function (actual) {
- return actual !== null && actual !== undefined;
- }, "defined");
-
- match.truthy = match(function (actual) {
- return !!actual;
- }, "truthy");
-
- match.falsy = match(function (actual) {
- return !actual;
- }, "falsy");
-
- match.same = function (expectation) {
- return match(function (actual) {
- return expectation === actual;
- }, "same(" + expectation + ")");
- };
-
- match.typeOf = function (type) {
- assertType(type, "string", "type");
- return match(function (actual) {
- return sinon.typeOf(actual) === type;
- }, "typeOf(\"" + type + "\")");
- };
-
- match.instanceOf = function (type) {
- assertType(type, "function", "type");
- return match(function (actual) {
- return actual instanceof type;
- }, "instanceOf(" + sinon.functionName(type) + ")");
- };
-
- function createPropertyMatcher(propertyTest, messagePrefix) {
- return function (property, value) {
- assertType(property, "string", "property");
- var onlyProperty = arguments.length === 1;
- var message = messagePrefix + "(\"" + property + "\"";
- if (!onlyProperty) {
- message += ", " + value;
- }
- message += ")";
- return match(function (actual) {
- if (actual === undefined || actual === null ||
- !propertyTest(actual, property)) {
- return false;
- }
- return onlyProperty || sinon.deepEqual(value, actual[property]);
- }, message);
- };
- }
-
- match.has = createPropertyMatcher(function (actual, property) {
- if (typeof actual === "object") {
- return property in actual;
- }
- return actual[property] !== undefined;
- }, "has");
-
- match.hasOwn = createPropertyMatcher(function (actual, property) {
- return actual.hasOwnProperty(property);
- }, "hasOwn");
-
- match.bool = match.typeOf("boolean");
- match.number = match.typeOf("number");
- match.string = match.typeOf("string");
- match.object = match.typeOf("object");
- match.func = match.typeOf("function");
- match.array = match.typeOf("array");
- match.regexp = match.typeOf("regexp");
- match.date = match.typeOf("date");
-
- sinon.match = match;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = match; });
- } else if (commonJSModule) {
- module.exports = match;
- }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend match.js
- */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Spy calls
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Maximilian Antoni (mail@maxantoni.de)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- * Copyright (c) 2013 Maximilian Antoni
- */
-
-(function (sinon) {
- var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
- if (!sinon && commonJSModule) {
- sinon = require("../sinon");
- }
-
- if (!sinon) {
- return;
- }
-
- function throwYieldError(proxy, text, args) {
- var msg = sinon.functionName(proxy) + text;
- if (args.length) {
- msg += " Received [" + slice.call(args).join(", ") + "]";
- }
- throw new Error(msg);
- }
-
- var slice = Array.prototype.slice;
-
- var callProto = {
- calledOn: function calledOn(thisValue) {
- if (sinon.match && sinon.match.isMatcher(thisValue)) {
- return thisValue.test(this.thisValue);
- }
- return this.thisValue === thisValue;
- },
-
- calledWith: function calledWith() {
- for (var i = 0, l = arguments.length; i < l; i += 1) {
- if (!sinon.deepEqual(arguments[i], this.args[i])) {
- return false;
- }
- }
-
- return true;
- },
-
- calledWithMatch: function calledWithMatch() {
- for (var i = 0, l = arguments.length; i < l; i += 1) {
- var actual = this.args[i];
- var expectation = arguments[i];
- if (!sinon.match || !sinon.match(expectation).test(actual)) {
- return false;
- }
- }
- return true;
- },
-
- calledWithExactly: function calledWithExactly() {
- return arguments.length == this.args.length &&
- this.calledWith.apply(this, arguments);
- },
-
- notCalledWith: function notCalledWith() {
- return !this.calledWith.apply(this, arguments);
- },
-
- notCalledWithMatch: function notCalledWithMatch() {
- return !this.calledWithMatch.apply(this, arguments);
- },
-
- returned: function returned(value) {
- return sinon.deepEqual(value, this.returnValue);
- },
-
- threw: function threw(error) {
- if (typeof error === "undefined" || !this.exception) {
- return !!this.exception;
- }
-
- return this.exception === error || this.exception.name === error;
- },
-
- calledWithNew: function calledWithNew() {
- return this.proxy.prototype && this.thisValue instanceof this.proxy;
- },
-
- calledBefore: function (other) {
- return this.callId < other.callId;
- },
-
- calledAfter: function (other) {
- return this.callId > other.callId;
- },
-
- callArg: function (pos) {
- this.args[pos]();
- },
-
- callArgOn: function (pos, thisValue) {
- this.args[pos].apply(thisValue);
- },
-
- callArgWith: function (pos) {
- this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
- },
-
- callArgOnWith: function (pos, thisValue) {
- var args = slice.call(arguments, 2);
- this.args[pos].apply(thisValue, args);
- },
-
- "yield": function () {
- this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
- },
-
- yieldOn: function (thisValue) {
- var args = this.args;
- for (var i = 0, l = args.length; i < l; ++i) {
- if (typeof args[i] === "function") {
- args[i].apply(thisValue, slice.call(arguments, 1));
- return;
- }
- }
- throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
- },
-
- yieldTo: function (prop) {
- this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
- },
-
- yieldToOn: function (prop, thisValue) {
- var args = this.args;
- for (var i = 0, l = args.length; i < l; ++i) {
- if (args[i] && typeof args[i][prop] === "function") {
- args[i][prop].apply(thisValue, slice.call(arguments, 2));
- return;
- }
- }
- throwYieldError(this.proxy, " cannot yield to '" + prop +
- "' since no callback was passed.", args);
- },
-
- toString: function () {
- var callStr = this.proxy.toString() + "(";
- var args = [];
-
- for (var i = 0, l = this.args.length; i < l; ++i) {
- args.push(sinon.format(this.args[i]));
- }
-
- callStr = callStr + args.join(", ") + ")";
-
- if (typeof this.returnValue != "undefined") {
- callStr += " => " + sinon.format(this.returnValue);
- }
-
- if (this.exception) {
- callStr += " !" + this.exception.name;
-
- if (this.exception.message) {
- callStr += "(" + this.exception.message + ")";
- }
- }
-
- return callStr;
- }
- };
-
- callProto.invokeCallback = callProto.yield;
-
- function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
- if (typeof id !== "number") {
- throw new TypeError("Call id is not a number");
- }
- var proxyCall = sinon.create(callProto);
- proxyCall.proxy = spy;
- proxyCall.thisValue = thisValue;
- proxyCall.args = args;
- proxyCall.returnValue = returnValue;
- proxyCall.exception = exception;
- proxyCall.callId = id;
-
- return proxyCall;
- }
- createSpyCall.toString = callProto.toString; // used by mocks
-
- sinon.spyCall = createSpyCall;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = createSpyCall; });
- } else if (commonJSModule) {
- module.exports = createSpyCall;
- }
-}(typeof sinon == "object" && sinon || null));
-
-
-/**
- * @depend ../sinon.js
- * @depend call.js
- */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Spy functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
- var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
- var push = Array.prototype.push;
- var slice = Array.prototype.slice;
- var callId = 0;
-
- if (!sinon && commonJSModule) {
- sinon = require("../sinon");
- }
-
- if (!sinon) {
- return;
- }
-
- function spy(object, property) {
- if (!property && typeof object == "function") {
- return spy.create(object);
- }
-
- if (!object && !property) {
- return spy.create(function () { });
- }
-
- var method = object[property];
- return sinon.wrapMethod(object, property, spy.create(method));
- }
-
- function matchingFake(fakes, args, strict) {
- if (!fakes) {
- return;
- }
-
- for (var i = 0, l = fakes.length; i < l; i++) {
- if (fakes[i].matches(args, strict)) {
- return fakes[i];
- }
- }
- }
-
- function incrementCallCount() {
- this.called = true;
- this.callCount += 1;
- this.notCalled = false;
- this.calledOnce = this.callCount == 1;
- this.calledTwice = this.callCount == 2;
- this.calledThrice = this.callCount == 3;
- }
-
- function createCallProperties() {
- this.firstCall = this.getCall(0);
- this.secondCall = this.getCall(1);
- this.thirdCall = this.getCall(2);
- this.lastCall = this.getCall(this.callCount - 1);
- }
-
- var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
- function createProxy(func) {
- // Retain the function length:
- var p;
- if (func.length) {
- eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
- ") { return p.invoke(func, this, slice.call(arguments)); });");
- }
- else {
- p = function proxy() {
- return p.invoke(func, this, slice.call(arguments));
- };
- }
- return p;
- }
-
- var uuid = 0;
-
- // Public API
- var spyApi = {
- reset: function () {
- this.called = false;
- this.notCalled = true;
- this.calledOnce = false;
- this.calledTwice = false;
- this.calledThrice = false;
- this.callCount = 0;
- this.firstCall = null;
- this.secondCall = null;
- this.thirdCall = null;
- this.lastCall = null;
- this.args = [];
- this.returnValues = [];
- this.thisValues = [];
- this.exceptions = [];
- this.callIds = [];
- if (this.fakes) {
- for (var i = 0; i < this.fakes.length; i++) {
- this.fakes[i].reset();
- }
- }
- },
-
- create: function create(func) {
- var name;
-
- if (typeof func != "function") {
- func = function () { };
- } else {
- name = sinon.functionName(func);
- }
-
- var proxy = createProxy(func);
-
- sinon.extend(proxy, spy);
- delete proxy.create;
- sinon.extend(proxy, func);
-
- proxy.reset();
- proxy.prototype = func.prototype;
- proxy.displayName = name || "spy";
- proxy.toString = sinon.functionToString;
- proxy._create = sinon.spy.create;
- proxy.id = "spy#" + uuid++;
-
- return proxy;
- },
-
- invoke: function invoke(func, thisValue, args) {
- var matching = matchingFake(this.fakes, args);
- var exception, returnValue;
-
- incrementCallCount.call(this);
- push.call(this.thisValues, thisValue);
- push.call(this.args, args);
- push.call(this.callIds, callId++);
-
- // Make call properties available from within the spied function:
- createCallProperties.call(this);
-
- try {
- if (matching) {
- returnValue = matching.invoke(func, thisValue, args);
- } else {
- returnValue = (this.func || func).apply(thisValue, args);
- }
-
- var thisCall = this.getCall(this.callCount - 1);
- if (thisCall.calledWithNew() && typeof returnValue !== 'object') {
- returnValue = thisValue;
- }
- } catch (e) {
- exception = e;
- }
-
- push.call(this.exceptions, exception);
- push.call(this.returnValues, returnValue);
-
- // Make return value and exception available in the calls:
- createCallProperties.call(this);
-
- if (exception !== undefined) {
- throw exception;
- }
-
- return returnValue;
- },
-
- named: function named(name) {
- this.displayName = name;
- return this;
- },
-
- getCall: function getCall(i) {
- if (i < 0 || i >= this.callCount) {
- return null;
- }
-
- return sinon.spyCall(this, this.thisValues[i], this.args[i],
- this.returnValues[i], this.exceptions[i],
- this.callIds[i]);
- },
-
- getCalls: function () {
- var calls = [];
- var i;
-
- for (i = 0; i < this.callCount; i++) {
- calls.push(this.getCall(i));
- }
-
- return calls;
- },
-
- calledBefore: function calledBefore(spyFn) {
- if (!this.called) {
- return false;
- }
-
- if (!spyFn.called) {
- return true;
- }
-
- return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
- },
-
- calledAfter: function calledAfter(spyFn) {
- if (!this.called || !spyFn.called) {
- return false;
- }
-
- return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
- },
-
- withArgs: function () {
- var args = slice.call(arguments);
-
- if (this.fakes) {
- var match = matchingFake(this.fakes, args, true);
-
- if (match) {
- return match;
- }
- } else {
- this.fakes = [];
- }
-
- var original = this;
- var fake = this._create();
- fake.matchingAguments = args;
- fake.parent = this;
- push.call(this.fakes, fake);
-
- fake.withArgs = function () {
- return original.withArgs.apply(original, arguments);
- };
-
- for (var i = 0; i < this.args.length; i++) {
- if (fake.matches(this.args[i])) {
- incrementCallCount.call(fake);
- push.call(fake.thisValues, this.thisValues[i]);
- push.call(fake.args, this.args[i]);
- push.call(fake.returnValues, this.returnValues[i]);
- push.call(fake.exceptions, this.exceptions[i]);
- push.call(fake.callIds, this.callIds[i]);
- }
- }
- createCallProperties.call(fake);
-
- return fake;
- },
-
- matches: function (args, strict) {
- var margs = this.matchingAguments;
-
- if (margs.length <= args.length &&
- sinon.deepEqual(margs, args.slice(0, margs.length))) {
- return !strict || margs.length == args.length;
- }
- },
-
- printf: function (format) {
- var spy = this;
- var args = slice.call(arguments, 1);
- var formatter;
-
- return (format || "").replace(/%(.)/g, function (match, specifyer) {
- formatter = spyApi.formatters[specifyer];
-
- if (typeof formatter == "function") {
- return formatter.call(null, spy, args);
- } else if (!isNaN(parseInt(specifyer, 10))) {
- return sinon.format(args[specifyer - 1]);
- }
-
- return "%" + specifyer;
- });
- }
- };
-
- function delegateToCalls(method, matchAny, actual, notCalled) {
- spyApi[method] = function () {
- if (!this.called) {
- if (notCalled) {
- return notCalled.apply(this, arguments);
- }
- return false;
- }
-
- var currentCall;
- var matches = 0;
-
- for (var i = 0, l = this.callCount; i < l; i += 1) {
- currentCall = this.getCall(i);
-
- if (currentCall[actual || method].apply(currentCall, arguments)) {
- matches += 1;
-
- if (matchAny) {
- return true;
- }
- }
- }
-
- return matches === this.callCount;
- };
- }
-
- delegateToCalls("calledOn", true);
- delegateToCalls("alwaysCalledOn", false, "calledOn");
- delegateToCalls("calledWith", true);
- delegateToCalls("calledWithMatch", true);
- delegateToCalls("alwaysCalledWith", false, "calledWith");
- delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
- delegateToCalls("calledWithExactly", true);
- delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
- delegateToCalls("neverCalledWith", false, "notCalledWith",
- function () { return true; });
- delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch",
- function () { return true; });
- delegateToCalls("threw", true);
- delegateToCalls("alwaysThrew", false, "threw");
- delegateToCalls("returned", true);
- delegateToCalls("alwaysReturned", false, "returned");
- delegateToCalls("calledWithNew", true);
- delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
- delegateToCalls("callArg", false, "callArgWith", function () {
- throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
- });
- spyApi.callArgWith = spyApi.callArg;
- delegateToCalls("callArgOn", false, "callArgOnWith", function () {
- throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
- });
- spyApi.callArgOnWith = spyApi.callArgOn;
- delegateToCalls("yield", false, "yield", function () {
- throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
- });
- // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
- spyApi.invokeCallback = spyApi.yield;
- delegateToCalls("yieldOn", false, "yieldOn", function () {
- throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
- });
- delegateToCalls("yieldTo", false, "yieldTo", function (property) {
- throw new Error(this.toString() + " cannot yield to '" + property +
- "' since it was not yet invoked.");
- });
- delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
- throw new Error(this.toString() + " cannot yield to '" + property +
- "' since it was not yet invoked.");
- });
-
- spyApi.formatters = {
- "c": function (spy) {
- return sinon.timesInWords(spy.callCount);
- },
-
- "n": function (spy) {
- return spy.toString();
- },
-
- "C": function (spy) {
- var calls = [];
-
- for (var i = 0, l = spy.callCount; i < l; ++i) {
- var stringifiedCall = " " + spy.getCall(i).toString();
- if (/\n/.test(calls[i - 1])) {
- stringifiedCall = "\n" + stringifiedCall;
- }
- push.call(calls, stringifiedCall);
- }
-
- return calls.length > 0 ? "\n" + calls.join("\n") : "";
- },
-
- "t": function (spy) {
- var objects = [];
-
- for (var i = 0, l = spy.callCount; i < l; ++i) {
- push.call(objects, sinon.format(spy.thisValues[i]));
- }
-
- return objects.join(", ");
- },
-
- "*": function (spy, args) {
- var formatted = [];
-
- for (var i = 0, l = args.length; i < l; ++i) {
- push.call(formatted, sinon.format(args[i]));
- }
-
- return formatted.join(", ");
- }
- };
-
- sinon.extend(spy, spyApi);
-
- spy.spyCall = sinon.spyCall;
- sinon.spy = spy;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = spy; });
- } else if (commonJSModule) {
- module.exports = spy;
- }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global module, require, sinon, process, setImmediate, setTimeout*/
-/**
- * Stub behavior
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Tim Fischbach (mail@timfischbach.de)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
- var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
-
- if (!sinon && commonJSModule) {
- sinon = require("../sinon");
- }
-
- if (!sinon) {
- return;
- }
-
- var slice = Array.prototype.slice;
- var join = Array.prototype.join;
- var proto;
-
- var nextTick = (function () {
- if (typeof process === "object" && typeof process.nextTick === "function") {
- return process.nextTick;
- } else if (typeof setImmediate === "function") {
- return setImmediate;
- } else {
- return function (callback) {
- setTimeout(callback, 0);
- };
- }
- })();
-
- function throwsException(error, message) {
- if (typeof error == "string") {
- this.exception = new Error(message || "");
- this.exception.name = error;
- } else if (!error) {
- this.exception = new Error("Error");
- } else {
- this.exception = error;
- }
-
- return this;
- }
-
- function getCallback(behavior, args) {
- var callArgAt = behavior.callArgAt;
-
- if (callArgAt < 0) {
- var callArgProp = behavior.callArgProp;
-
- for (var i = 0, l = args.length; i < l; ++i) {
- if (!callArgProp && typeof args[i] == "function") {
- return args[i];
- }
-
- if (callArgProp && args[i] &&
- typeof args[i][callArgProp] == "function") {
- return args[i][callArgProp];
- }
- }
-
- return null;
- }
-
- return args[callArgAt];
- }
-
- function getCallbackError(behavior, func, args) {
- if (behavior.callArgAt < 0) {
- var msg;
-
- if (behavior.callArgProp) {
- msg = sinon.functionName(behavior.stub) +
- " expected to yield to '" + behavior.callArgProp +
- "', but no object with such a property was passed.";
- } else {
- msg = sinon.functionName(behavior.stub) +
- " expected to yield, but no callback was passed.";
- }
-
- if (args.length > 0) {
- msg += " Received [" + join.call(args, ", ") + "]";
- }
-
- return msg;
- }
-
- return "argument at index " + behavior.callArgAt + " is not a function: " + func;
- }
-
- function callCallback(behavior, args) {
- if (typeof behavior.callArgAt == "number") {
- var func = getCallback(behavior, args);
-
- if (typeof func != "function") {
- throw new TypeError(getCallbackError(behavior, func, args));
- }
-
- if (behavior.callbackAsync) {
- nextTick(function() {
- func.apply(behavior.callbackContext, behavior.callbackArguments);
- });
- } else {
- func.apply(behavior.callbackContext, behavior.callbackArguments);
- }
- }
- }
-
- proto = {
- create: function(stub) {
- var behavior = sinon.extend({}, sinon.behavior);
- delete behavior.create;
- behavior.stub = stub;
-
- return behavior;
- },
-
- isPresent: function() {
- return (typeof this.callArgAt == 'number' ||
- this.exception ||
- typeof this.returnArgAt == 'number' ||
- this.returnThis ||
- this.returnValueDefined);
- },
-
- invoke: function(context, args) {
- callCallback(this, args);
-
- if (this.exception) {
- throw this.exception;
- } else if (typeof this.returnArgAt == 'number') {
- return args[this.returnArgAt];
- } else if (this.returnThis) {
- return context;
- }
-
- return this.returnValue;
- },
-
- onCall: function(index) {
- return this.stub.onCall(index);
- },
-
- onFirstCall: function() {
- return this.stub.onFirstCall();
- },
-
- onSecondCall: function() {
- return this.stub.onSecondCall();
- },
-
- onThirdCall: function() {
- return this.stub.onThirdCall();
- },
-
- withArgs: function(/* arguments */) {
- throw new Error('Defining a stub by invoking "stub.onCall(...).withArgs(...)" is not supported. ' +
- 'Use "stub.withArgs(...).onCall(...)" to define sequential behavior for calls with certain arguments.');
- },
-
- callsArg: function callsArg(pos) {
- if (typeof pos != "number") {
- throw new TypeError("argument index is not number");
- }
-
- this.callArgAt = pos;
- this.callbackArguments = [];
- this.callbackContext = undefined;
- this.callArgProp = undefined;
- this.callbackAsync = false;
-
- return this;
- },
-
- callsArgOn: function callsArgOn(pos, context) {
- if (typeof pos != "number") {
- throw new TypeError("argument index is not number");
- }
- if (typeof context != "object") {
- throw new TypeError("argument context is not an object");
- }
-
- this.callArgAt = pos;
- this.callbackArguments = [];
- this.callbackContext = context;
- this.callArgProp = undefined;
- this.callbackAsync = false;
-
- return this;
- },
-
- callsArgWith: function callsArgWith(pos) {
- if (typeof pos != "number") {
- throw new TypeError("argument index is not number");
- }
-
- this.callArgAt = pos;
- this.callbackArguments = slice.call(arguments, 1);
- this.callbackContext = undefined;
- this.callArgProp = undefined;
- this.callbackAsync = false;
-
- return this;
- },
-
- callsArgOnWith: function callsArgWith(pos, context) {
- if (typeof pos != "number") {
- throw new TypeError("argument index is not number");
- }
- if (typeof context != "object") {
- throw new TypeError("argument context is not an object");
- }
-
- this.callArgAt = pos;
- this.callbackArguments = slice.call(arguments, 2);
- this.callbackContext = context;
- this.callArgProp = undefined;
- this.callbackAsync = false;
-
- return this;
- },
-
- yields: function () {
- this.callArgAt = -1;
- this.callbackArguments = slice.call(arguments, 0);
- this.callbackContext = undefined;
- this.callArgProp = undefined;
- this.callbackAsync = false;
-
- return this;
- },
-
- yieldsOn: function (context) {
- if (typeof context != "object") {
- throw new TypeError("argument context is not an object");
- }
-
- this.callArgAt = -1;
- this.callbackArguments = slice.call(arguments, 1);
- this.callbackContext = context;
- this.callArgProp = undefined;
- this.callbackAsync = false;
-
- return this;
- },
-
- yieldsTo: function (prop) {
- this.callArgAt = -1;
- this.callbackArguments = slice.call(arguments, 1);
- this.callbackContext = undefined;
- this.callArgProp = prop;
- this.callbackAsync = false;
-
- return this;
- },
-
- yieldsToOn: function (prop, context) {
- if (typeof context != "object") {
- throw new TypeError("argument context is not an object");
- }
-
- this.callArgAt = -1;
- this.callbackArguments = slice.call(arguments, 2);
- this.callbackContext = context;
- this.callArgProp = prop;
- this.callbackAsync = false;
-
- return this;
- },
-
-
- "throws": throwsException,
- throwsException: throwsException,
-
- returns: function returns(value) {
- this.returnValue = value;
- this.returnValueDefined = true;
-
- return this;
- },
-
- returnsArg: function returnsArg(pos) {
- if (typeof pos != "number") {
- throw new TypeError("argument index is not number");
- }
-
- this.returnArgAt = pos;
-
- return this;
- },
-
- returnsThis: function returnsThis() {
- this.returnThis = true;
-
- return this;
- }
- };
-
- // create asynchronous versions of callsArg* and yields* methods
- for (var method in proto) {
- // need to avoid creating anotherasync versions of the newly added async methods
- if (proto.hasOwnProperty(method) &&
- method.match(/^(callsArg|yields)/) &&
- !method.match(/Async/)) {
- proto[method + 'Async'] = (function (syncFnName) {
- return function () {
- var result = this[syncFnName].apply(this, arguments);
- this.callbackAsync = true;
- return result;
- };
- })(method);
- }
- }
-
- sinon.behavior = proto;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = proto; });
- } else if (commonJSModule) {
- module.exports = proto;
- }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend spy.js
- * @depend behavior.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global module, require, sinon*/
-/**
- * Stub functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
- var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
-
- if (!sinon && commonJSModule) {
- sinon = require("../sinon");
- }
-
- if (!sinon) {
- return;
- }
-
- function stub(object, property, func) {
- if (!!func && typeof func != "function") {
- throw new TypeError("Custom stub should be function");
- }
-
- var wrapper;
-
- if (func) {
- wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
- } else {
- wrapper = stub.create();
- }
-
- if (!object && typeof property === "undefined") {
- return sinon.stub.create();
- }
-
- if (typeof property === "undefined" && typeof object == "object") {
- for (var prop in object) {
- if (typeof object[prop] === "function") {
- stub(object, prop);
- }
- }
-
- return object;
- }
-
- return sinon.wrapMethod(object, property, wrapper);
- }
-
- function getDefaultBehavior(stub) {
- return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
- }
-
- function getParentBehaviour(stub) {
- return (stub.parent && getCurrentBehavior(stub.parent));
- }
-
- function getCurrentBehavior(stub) {
- var behavior = stub.behaviors[stub.callCount - 1];
- return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
- }
-
- var uuid = 0;
-
- sinon.extend(stub, (function () {
- var proto = {
- create: function create() {
- var functionStub = function () {
- return getCurrentBehavior(functionStub).invoke(this, arguments);
- };
-
- functionStub.id = "stub#" + uuid++;
- var orig = functionStub;
- functionStub = sinon.spy.create(functionStub);
- functionStub.func = orig;
-
- sinon.extend(functionStub, stub);
- functionStub._create = sinon.stub.create;
- functionStub.displayName = "stub";
- functionStub.toString = sinon.functionToString;
-
- functionStub.defaultBehavior = null;
- functionStub.behaviors = [];
-
- return functionStub;
- },
-
- resetBehavior: function () {
- var i;
-
- this.defaultBehavior = null;
- this.behaviors = [];
-
- delete this.returnValue;
- delete this.returnArgAt;
- this.returnThis = false;
-
- if (this.fakes) {
- for (i = 0; i < this.fakes.length; i++) {
- this.fakes[i].resetBehavior();
- }
- }
- },
-
- onCall: function(index) {
- if (!this.behaviors[index]) {
- this.behaviors[index] = sinon.behavior.create(this);
- }
-
- return this.behaviors[index];
- },
-
- onFirstCall: function() {
- return this.onCall(0);
- },
-
- onSecondCall: function() {
- return this.onCall(1);
- },
-
- onThirdCall: function() {
- return this.onCall(2);
- }
- };
-
- for (var method in sinon.behavior) {
- if (sinon.behavior.hasOwnProperty(method) &&
- !proto.hasOwnProperty(method) &&
- method != 'create' &&
- method != 'withArgs' &&
- method != 'invoke') {
- proto[method] = (function(behaviorMethod) {
- return function() {
- this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
- this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
- return this;
- };
- }(method));
- }
- }
-
- return proto;
- }()));
-
- sinon.stub = stub;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = stub; });
- } else if (commonJSModule) {
- module.exports = stub;
- }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- */
-/*jslint eqeqeq: false, onevar: false, nomen: false*/
-/*global module, require, sinon*/
-/**
- * Mock functions.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
- var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
- var push = [].push;
- var match;
-
- if (!sinon && commonJSModule) {
- sinon = require("../sinon");
- }
-
- if (!sinon) {
- return;
- }
-
- match = sinon.match;
-
- if (!match && commonJSModule) {
- match = require("./match");
- }
-
- function mock(object) {
- if (!object) {
- return sinon.expectation.create("Anonymous mock");
- }
-
- return mock.create(object);
- }
-
- sinon.mock = mock;
-
- sinon.extend(mock, (function () {
- function each(collection, callback) {
- if (!collection) {
- return;
- }
-
- for (var i = 0, l = collection.length; i < l; i += 1) {
- callback(collection[i]);
- }
- }
-
- return {
- create: function create(object) {
- if (!object) {
- throw new TypeError("object is null");
- }
-
- var mockObject = sinon.extend({}, mock);
- mockObject.object = object;
- delete mockObject.create;
-
- return mockObject;
- },
-
- expects: function expects(method) {
- if (!method) {
- throw new TypeError("method is falsy");
- }
-
- if (!this.expectations) {
- this.expectations = {};
- this.proxies = [];
- }
-
- if (!this.expectations[method]) {
- this.expectations[method] = [];
- var mockObject = this;
-
- sinon.wrapMethod(this.object, method, function () {
- return mockObject.invokeMethod(method, this, arguments);
- });
-
- push.call(this.proxies, method);
- }
-
- var expectation = sinon.expectation.create(method);
- push.call(this.expectations[method], expectation);
-
- return expectation;
- },
-
- restore: function restore() {
- var object = this.object;
-
- each(this.proxies, function (proxy) {
- if (typeof object[proxy].restore == "function") {
- object[proxy].restore();
- }
- });
- },
-
- verify: function verify() {
- var expectations = this.expectations || {};
- var messages = [], met = [];
-
- each(this.proxies, function (proxy) {
- each(expectations[proxy], function (expectation) {
- if (!expectation.met()) {
- push.call(messages, expectation.toString());
- } else {
- push.call(met, expectation.toString());
- }
- });
- });
-
- this.restore();
-
- if (messages.length > 0) {
- sinon.expectation.fail(messages.concat(met).join("\n"));
- } else {
- sinon.expectation.pass(messages.concat(met).join("\n"));
- }
-
- return true;
- },
-
- invokeMethod: function invokeMethod(method, thisValue, args) {
- var expectations = this.expectations && this.expectations[method];
- var length = expectations && expectations.length || 0, i;
-
- for (i = 0; i < length; i += 1) {
- if (!expectations[i].met() &&
- expectations[i].allowsCall(thisValue, args)) {
- return expectations[i].apply(thisValue, args);
- }
- }
-
- var messages = [], available, exhausted = 0;
-
- for (i = 0; i < length; i += 1) {
- if (expectations[i].allowsCall(thisValue, args)) {
- available = available || expectations[i];
- } else {
- exhausted += 1;
- }
- push.call(messages, " " + expectations[i].toString());
- }
-
- if (exhausted === 0) {
- return available.apply(thisValue, args);
- }
-
- messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
- proxy: method,
- args: args
- }));
-
- sinon.expectation.fail(messages.join("\n"));
- }
- };
- }()));
-
- var times = sinon.timesInWords;
-
- sinon.expectation = (function () {
- var slice = Array.prototype.slice;
- var _invoke = sinon.spy.invoke;
-
- function callCountInWords(callCount) {
- if (callCount == 0) {
- return "never called";
- } else {
- return "called " + times(callCount);
- }
- }
-
- function expectedCallCountInWords(expectation) {
- var min = expectation.minCalls;
- var max = expectation.maxCalls;
-
- if (typeof min == "number" && typeof max == "number") {
- var str = times(min);
-
- if (min != max) {
- str = "at least " + str + " and at most " + times(max);
- }
-
- return str;
- }
-
- if (typeof min == "number") {
- return "at least " + times(min);
- }
-
- return "at most " + times(max);
- }
-
- function receivedMinCalls(expectation) {
- var hasMinLimit = typeof expectation.minCalls == "number";
- return !hasMinLimit || expectation.callCount >= expectation.minCalls;
- }
-
- function receivedMaxCalls(expectation) {
- if (typeof expectation.maxCalls != "number") {
- return false;
- }
-
- return expectation.callCount == expectation.maxCalls;
- }
-
- function verifyMatcher(possibleMatcher, arg){
- if (match && match.isMatcher(possibleMatcher)) {
- return possibleMatcher.test(arg);
- } else {
- return true;
- }
- }
-
- return {
- minCalls: 1,
- maxCalls: 1,
-
- create: function create(methodName) {
- var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
- delete expectation.create;
- expectation.method = methodName;
-
- return expectation;
- },
-
- invoke: function invoke(func, thisValue, args) {
- this.verifyCallAllowed(thisValue, args);
-
- return _invoke.apply(this, arguments);
- },
-
- atLeast: function atLeast(num) {
- if (typeof num != "number") {
- throw new TypeError("'" + num + "' is not number");
- }
-
- if (!this.limitsSet) {
- this.maxCalls = null;
- this.limitsSet = true;
- }
-
- this.minCalls = num;
-
- return this;
- },
-
- atMost: function atMost(num) {
- if (typeof num != "number") {
- throw new TypeError("'" + num + "' is not number");
- }
-
- if (!this.limitsSet) {
- this.minCalls = null;
- this.limitsSet = true;
- }
-
- this.maxCalls = num;
-
- return this;
- },
-
- never: function never() {
- return this.exactly(0);
- },
-
- once: function once() {
- return this.exactly(1);
- },
-
- twice: function twice() {
- return this.exactly(2);
- },
-
- thrice: function thrice() {
- return this.exactly(3);
- },
-
- exactly: function exactly(num) {
- if (typeof num != "number") {
- throw new TypeError("'" + num + "' is not a number");
- }
-
- this.atLeast(num);
- return this.atMost(num);
- },
-
- met: function met() {
- return !this.failed && receivedMinCalls(this);
- },
-
- verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
- if (receivedMaxCalls(this)) {
- this.failed = true;
- sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
- }
-
- if ("expectedThis" in this && this.expectedThis !== thisValue) {
- sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
- this.expectedThis);
- }
-
- if (!("expectedArguments" in this)) {
- return;
- }
-
- if (!args) {
- sinon.expectation.fail(this.method + " received no arguments, expected " +
- sinon.format(this.expectedArguments));
- }
-
- if (args.length < this.expectedArguments.length) {
- sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
- "), expected " + sinon.format(this.expectedArguments));
- }
-
- if (this.expectsExactArgCount &&
- args.length != this.expectedArguments.length) {
- sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
- "), expected " + sinon.format(this.expectedArguments));
- }
-
- for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
-
- if (!verifyMatcher(this.expectedArguments[i],args[i])) {
- sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
- ", didn't match " + this.expectedArguments.toString());
- }
-
- if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
- sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
- ", expected " + sinon.format(this.expectedArguments));
- }
- }
- },
-
- allowsCall: function allowsCall(thisValue, args) {
- if (this.met() && receivedMaxCalls(this)) {
- return false;
- }
-
- if ("expectedThis" in this && this.expectedThis !== thisValue) {
- return false;
- }
-
- if (!("expectedArguments" in this)) {
- return true;
- }
-
- args = args || [];
-
- if (args.length < this.expectedArguments.length) {
- return false;
- }
-
- if (this.expectsExactArgCount &&
- args.length != this.expectedArguments.length) {
- return false;
- }
-
- for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
- if (!verifyMatcher(this.expectedArguments[i],args[i])) {
- return false;
- }
-
- if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
- return false;
- }
- }
-
- return true;
- },
-
- withArgs: function withArgs() {
- this.expectedArguments = slice.call(arguments);
- return this;
- },
-
- withExactArgs: function withExactArgs() {
- this.withArgs.apply(this, arguments);
- this.expectsExactArgCount = true;
- return this;
- },
-
- on: function on(thisValue) {
- this.expectedThis = thisValue;
- return this;
- },
-
- toString: function () {
- var args = (this.expectedArguments || []).slice();
-
- if (!this.expectsExactArgCount) {
- push.call(args, "[...]");
- }
-
- var callStr = sinon.spyCall.toString.call({
- proxy: this.method || "anonymous mock expectation",
- args: args
- });
-
- var message = callStr.replace(", [...", "[, ...") + " " +
- expectedCallCountInWords(this);
-
- if (this.met()) {
- return "Expectation met: " + message;
- }
-
- return "Expected " + message + " (" +
- callCountInWords(this.callCount) + ")";
- },
-
- verify: function verify() {
- if (!this.met()) {
- sinon.expectation.fail(this.toString());
- } else {
- sinon.expectation.pass(this.toString());
- }
-
- return true;
- },
-
- pass: function(message) {
- sinon.assert.pass(message);
- },
- fail: function (message) {
- var exception = new Error(message);
- exception.name = "ExpectationError";
-
- throw exception;
- }
- };
- }());
-
- sinon.mock = mock;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = mock; });
- } else if (commonJSModule) {
- module.exports = mock;
- }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- * @depend mock.js
- */
-/*jslint eqeqeq: false, onevar: false, forin: true*/
-/*global module, require, sinon*/
-/**
- * Collections of stubs, spies and mocks.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
- var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
- var push = [].push;
- var hasOwnProperty = Object.prototype.hasOwnProperty;
-
- if (!sinon && commonJSModule) {
- sinon = require("../sinon");
- }
-
- if (!sinon) {
- return;
- }
-
- function getFakes(fakeCollection) {
- if (!fakeCollection.fakes) {
- fakeCollection.fakes = [];
- }
-
- return fakeCollection.fakes;
- }
-
- function each(fakeCollection, method) {
- var fakes = getFakes(fakeCollection);
-
- for (var i = 0, l = fakes.length; i < l; i += 1) {
- if (typeof fakes[i][method] == "function") {
- fakes[i][method]();
- }
- }
- }
-
- function compact(fakeCollection) {
- var fakes = getFakes(fakeCollection);
- var i = 0;
- while (i < fakes.length) {
- fakes.splice(i, 1);
- }
- }
-
- var collection = {
- verify: function resolve() {
- each(this, "verify");
- },
-
- restore: function restore() {
- each(this, "restore");
- compact(this);
- },
-
- verifyAndRestore: function verifyAndRestore() {
- var exception;
-
- try {
- this.verify();
- } catch (e) {
- exception = e;
- }
-
- this.restore();
-
- if (exception) {
- throw exception;
- }
- },
-
- add: function add(fake) {
- push.call(getFakes(this), fake);
- return fake;
- },
-
- spy: function spy() {
- return this.add(sinon.spy.apply(sinon, arguments));
- },
-
- stub: function stub(object, property, value) {
- if (property) {
- var original = object[property];
-
- if (typeof original != "function") {
- if (!hasOwnProperty.call(object, property)) {
- throw new TypeError("Cannot stub non-existent own property " + property);
- }
-
- object[property] = value;
-
- return this.add({
- restore: function () {
- object[property] = original;
- }
- });
- }
- }
- if (!property && !!object && typeof object == "object") {
- var stubbedObj = sinon.stub.apply(sinon, arguments);
-
- for (var prop in stubbedObj) {
- if (typeof stubbedObj[prop] === "function") {
- this.add(stubbedObj[prop]);
- }
- }
-
- return stubbedObj;
- }
-
- return this.add(sinon.stub.apply(sinon, arguments));
- },
-
- mock: function mock() {
- return this.add(sinon.mock.apply(sinon, arguments));
- },
-
- inject: function inject(obj) {
- var col = this;
-
- obj.spy = function () {
- return col.spy.apply(col, arguments);
- };
-
- obj.stub = function () {
- return col.stub.apply(col, arguments);
- };
-
- obj.mock = function () {
- return col.mock.apply(col, arguments);
- };
-
- return obj;
- }
- };
-
- sinon.collection = collection;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = collection; });
- } else if (commonJSModule) {
- module.exports = collection;
- }
-}(typeof sinon == "object" && sinon || null));
-
-/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
-/*global module, require, window*/
-/**
- * Fake timer API
- * setTimeout
- * setInterval
- * clearTimeout
- * clearInterval
- * tick
- * reset
- * Date
- *
- * Inspired by jsUnitMockTimeOut from JsUnit
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
- var sinon = {};
-}
-
-(function (global) {
- // node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
- // browsers, a number.
- // see https://github.com/cjohansen/Sinon.JS/pull/436
- var timeoutResult = setTimeout(function() {}, 0);
- var addTimerReturnsObject = typeof timeoutResult === 'object';
- clearTimeout(timeoutResult);
-
- var id = 1;
-
- function addTimer(args, recurring) {
- if (args.length === 0) {
- throw new Error("Function requires at least 1 parameter");
- }
-
- if (typeof args[0] === "undefined") {
- throw new Error("Callback must be provided to timer calls");
- }
-
- var toId = id++;
- var delay = args[1] || 0;
-
- if (!this.timeouts) {
- this.timeouts = {};
- }
-
- this.timeouts[toId] = {
- id: toId,
- func: args[0],
- callAt: this.now + delay,
- invokeArgs: Array.prototype.slice.call(args, 2)
- };
-
- if (recurring === true) {
- this.timeouts[toId].interval = delay;
- }
-
- if (addTimerReturnsObject) {
- return {
- id: toId,
- ref: function() {},
- unref: function() {}
- };
- }
- else {
- return toId;
- }
- }
-
- function parseTime(str) {
- if (!str) {
- return 0;
- }
-
- var strings = str.split(":");
- var l = strings.length, i = l;
- var ms = 0, parsed;
-
- if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
- throw new Error("tick only understands numbers and 'h:m:s'");
- }
-
- while (i--) {
- parsed = parseInt(strings[i], 10);
-
- if (parsed >= 60) {
- throw new Error("Invalid time " + str);
- }
-
- ms += parsed * Math.pow(60, (l - i - 1));
- }
-
- return ms * 1000;
- }
-
- function createObject(object) {
- var newObject;
-
- if (Object.create) {
- newObject = Object.create(object);
- } else {
- var F = function () {};
- F.prototype = object;
- newObject = new F();
- }
-
- newObject.Date.clock = newObject;
- return newObject;
- }
-
- sinon.clock = {
- now: 0,
-
- create: function create(now) {
- var clock = createObject(this);
-
- if (typeof now == "number") {
- clock.now = now;
- }
-
- if (!!now && typeof now == "object") {
- throw new TypeError("now should be milliseconds since UNIX epoch");
- }
-
- return clock;
- },
-
- setTimeout: function setTimeout(callback, timeout) {
- return addTimer.call(this, arguments, false);
- },
-
- clearTimeout: function clearTimeout(timerId) {
- if (!timerId) {
- // null appears to be allowed in most browsers, and appears to be relied upon by some libraries, like Bootstrap carousel
- return;
- }
- if (!this.timeouts) {
- this.timeouts = [];
- }
- // in Node, timerId is an object with .ref()/.unref(), and
- // its .id field is the actual timer id.
- if (typeof timerId === 'object') {
- timerId = timerId.id
- }
- if (timerId in this.timeouts) {
- delete this.timeouts[timerId];
- }
- },
-
- setInterval: function setInterval(callback, timeout) {
- return addTimer.call(this, arguments, true);
- },
-
- clearInterval: function clearInterval(timerId) {
- this.clearTimeout(timerId);
- },
-
- setImmediate: function setImmediate(callback) {
- var passThruArgs = Array.prototype.slice.call(arguments, 1);
-
- return addTimer.call(this, [callback, 0].concat(passThruArgs), false);
- },
-
- clearImmediate: function clearImmediate(timerId) {
- this.clearTimeout(timerId);
- },
-
- tick: function tick(ms) {
- ms = typeof ms == "number" ? ms : parseTime(ms);
- var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
- var timer = this.firstTimerInRange(tickFrom, tickTo);
-
- var firstException;
- while (timer && tickFrom <= tickTo) {
- if (this.timeouts[timer.id]) {
- tickFrom = this.now = timer.callAt;
- try {
- this.callTimer(timer);
- } catch (e) {
- firstException = firstException || e;
- }
- }
-
- timer = this.firstTimerInRange(previous, tickTo);
- previous = tickFrom;
- }
-
- this.now = tickTo;
-
- if (firstException) {
- throw firstException;
- }
-
- return this.now;
- },
-
- firstTimerInRange: function (from, to) {
- var timer, smallest = null, originalTimer;
-
- for (var id in this.timeouts) {
- if (this.timeouts.hasOwnProperty(id)) {
- if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
- continue;
- }
-
- if (smallest === null || this.timeouts[id].callAt < smallest) {
- originalTimer = this.timeouts[id];
- smallest = this.timeouts[id].callAt;
-
- timer = {
- func: this.timeouts[id].func,
- callAt: this.timeouts[id].callAt,
- interval: this.timeouts[id].interval,
- id: this.timeouts[id].id,
- invokeArgs: this.timeouts[id].invokeArgs
- };
- }
- }
- }
-
- return timer || null;
- },
-
- callTimer: function (timer) {
- if (typeof timer.interval == "number") {
- this.timeouts[timer.id].callAt += timer.interval;
- } else {
- delete this.timeouts[timer.id];
- }
-
- try {
- if (typeof timer.func == "function") {
- timer.func.apply(null, timer.invokeArgs);
- } else {
- eval(timer.func);
- }
- } catch (e) {
- var exception = e;
- }
-
- if (!this.timeouts[timer.id]) {
- if (exception) {
- throw exception;
- }
- return;
- }
-
- if (exception) {
- throw exception;
- }
- },
-
- reset: function reset() {
- this.timeouts = {};
- },
-
- Date: (function () {
- var NativeDate = Date;
-
- function ClockDate(year, month, date, hour, minute, second, ms) {
- // Defensive and verbose to avoid potential harm in passing
- // explicit undefined when user does not pass argument
- switch (arguments.length) {
- case 0:
- return new NativeDate(ClockDate.clock.now);
- case 1:
- return new NativeDate(year);
- case 2:
- return new NativeDate(year, month);
- case 3:
- return new NativeDate(year, month, date);
- case 4:
- return new NativeDate(year, month, date, hour);
- case 5:
- return new NativeDate(year, month, date, hour, minute);
- case 6:
- return new NativeDate(year, month, date, hour, minute, second);
- default:
- return new NativeDate(year, month, date, hour, minute, second, ms);
- }
- }
-
- return mirrorDateProperties(ClockDate, NativeDate);
- }())
- };
-
- function mirrorDateProperties(target, source) {
- if (source.now) {
- target.now = function now() {
- return target.clock.now;
- };
- } else {
- delete target.now;
- }
-
- if (source.toSource) {
- target.toSource = function toSource() {
- return source.toSource();
- };
- } else {
- delete target.toSource;
- }
-
- target.toString = function toString() {
- return source.toString();
- };
-
- target.prototype = source.prototype;
- target.parse = source.parse;
- target.UTC = source.UTC;
- target.prototype.toUTCString = source.prototype.toUTCString;
-
- for (var prop in source) {
- if (source.hasOwnProperty(prop)) {
- target[prop] = source[prop];
- }
- }
-
- return target;
- }
-
- var methods = ["Date", "setTimeout", "setInterval",
- "clearTimeout", "clearInterval"];
-
- if (typeof global.setImmediate !== "undefined") {
- methods.push("setImmediate");
- }
-
- if (typeof global.clearImmediate !== "undefined") {
- methods.push("clearImmediate");
- }
-
- function restore() {
- var method;
-
- for (var i = 0, l = this.methods.length; i < l; i++) {
- method = this.methods[i];
-
- if (global[method].hadOwnProperty) {
- global[method] = this["_" + method];
- } else {
- try {
- delete global[method];
- } catch (e) {}
- }
- }
-
- // Prevent multiple executions which will completely remove these props
- this.methods = [];
- }
-
- function stubGlobal(method, clock) {
- clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
- clock["_" + method] = global[method];
-
- if (method == "Date") {
- var date = mirrorDateProperties(clock[method], global[method]);
- global[method] = date;
- } else {
- global[method] = function () {
- return clock[method].apply(clock, arguments);
- };
-
- for (var prop in clock[method]) {
- if (clock[method].hasOwnProperty(prop)) {
- global[method][prop] = clock[method][prop];
- }
- }
- }
-
- global[method].clock = clock;
- }
-
- sinon.useFakeTimers = function useFakeTimers(now) {
- var clock = sinon.clock.create(now);
- clock.restore = restore;
- clock.methods = Array.prototype.slice.call(arguments,
- typeof now == "number" ? 1 : 0);
-
- if (clock.methods.length === 0) {
- clock.methods = methods;
- }
-
- for (var i = 0, l = clock.methods.length; i < l; i++) {
- stubGlobal(clock.methods[i], clock);
- }
-
- return clock;
- };
-}(typeof global != "undefined" && typeof global !== "function" ? global : this));
-
-sinon.timers = {
- setTimeout: setTimeout,
- clearTimeout: clearTimeout,
- setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
- clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
- setInterval: setInterval,
- clearInterval: clearInterval,
- Date: Date
-};
-
-if (typeof module !== 'undefined' && module.exports) {
- module.exports = sinon;
-}
-
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
-/**
- * Minimal Event interface implementation
- *
- * Original implementation by Sven Fuchs: https://gist.github.com/995028
- * Modifications and tests by Christian Johansen.
- *
- * @author Sven Fuchs (svenfuchs@artweb-design.de)
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2011 Sven Fuchs, Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
- this.sinon = {};
-}
-
-(function () {
- var push = [].push;
-
- sinon.Event = function Event(type, bubbles, cancelable, target) {
- this.initEvent(type, bubbles, cancelable, target);
- };
-
- sinon.Event.prototype = {
- initEvent: function(type, bubbles, cancelable, target) {
- this.type = type;
- this.bubbles = bubbles;
- this.cancelable = cancelable;
- this.target = target;
- },
-
- stopPropagation: function () {},
-
- preventDefault: function () {
- this.defaultPrevented = true;
- }
- };
-
- sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
- this.initEvent(type, false, false, target);
- this.loaded = progressEventRaw.loaded || null;
- this.total = progressEventRaw.total || null;
- };
-
- sinon.ProgressEvent.prototype = new sinon.Event();
-
- sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent;
-
- sinon.CustomEvent = function CustomEvent(type, customData, target) {
- this.initEvent(type, false, false, target);
- this.detail = customData.detail || null;
- };
-
- sinon.CustomEvent.prototype = new sinon.Event();
-
- sinon.CustomEvent.prototype.constructor = sinon.CustomEvent;
-
- sinon.EventTarget = {
- addEventListener: function addEventListener(event, listener) {
- this.eventListeners = this.eventListeners || {};
- this.eventListeners[event] = this.eventListeners[event] || [];
- push.call(this.eventListeners[event], listener);
- },
-
- removeEventListener: function removeEventListener(event, listener) {
- var listeners = this.eventListeners && this.eventListeners[event] || [];
-
- for (var i = 0, l = listeners.length; i < l; ++i) {
- if (listeners[i] == listener) {
- return listeners.splice(i, 1);
- }
- }
- },
-
- dispatchEvent: function dispatchEvent(event) {
- var type = event.type;
- var listeners = this.eventListeners && this.eventListeners[type] || [];
-
- for (var i = 0; i < listeners.length; i++) {
- if (typeof listeners[i] == "function") {
- listeners[i].call(this, event);
- } else {
- listeners[i].handleEvent(event);
- }
- }
-
- return !!event.defaultPrevented;
- }
- };
-}());
-
-/**
- * @depend ../../sinon.js
- * @depend event.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
-/**
- * Fake XMLHttpRequest object
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-// wrapper for global
-(function(global) {
- if (typeof sinon === "undefined") {
- global.sinon = {};
- }
-
- var supportsProgress = typeof ProgressEvent !== "undefined";
- var supportsCustomEvent = typeof CustomEvent !== "undefined";
- sinon.xhr = { XMLHttpRequest: global.XMLHttpRequest };
- var xhr = sinon.xhr;
- xhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
- xhr.GlobalActiveXObject = global.ActiveXObject;
- xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != "undefined";
- xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != "undefined";
- xhr.workingXHR = xhr.supportsXHR ? xhr.GlobalXMLHttpRequest : xhr.supportsActiveX
- ? function() { return new xhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
- xhr.supportsCORS = xhr.supportsXHR && 'withCredentials' in (new sinon.xhr.GlobalXMLHttpRequest());
-
- /*jsl:ignore*/
- var unsafeHeaders = {
- "Accept-Charset": true,
- "Accept-Encoding": true,
- "Connection": true,
- "Content-Length": true,
- "Cookie": true,
- "Cookie2": true,
- "Content-Transfer-Encoding": true,
- "Date": true,
- "Expect": true,
- "Host": true,
- "Keep-Alive": true,
- "Referer": true,
- "TE": true,
- "Trailer": true,
- "Transfer-Encoding": true,
- "Upgrade": true,
- "User-Agent": true,
- "Via": true
- };
- /*jsl:end*/
-
- function FakeXMLHttpRequest() {
- this.readyState = FakeXMLHttpRequest.UNSENT;
- this.requestHeaders = {};
- this.requestBody = null;
- this.status = 0;
- this.statusText = "";
- this.upload = new UploadProgress();
- if (sinon.xhr.supportsCORS) {
- this.withCredentials = false;
- }
-
-
- var xhr = this;
- var events = ["loadstart", "load", "abort", "loadend"];
-
- function addEventListener(eventName) {
- xhr.addEventListener(eventName, function (event) {
- var listener = xhr["on" + eventName];
-
- if (listener && typeof listener == "function") {
- listener.call(this, event);
- }
- });
- }
-
- for (var i = events.length - 1; i >= 0; i--) {
- addEventListener(events[i]);
- }
-
- if (typeof FakeXMLHttpRequest.onCreate == "function") {
- FakeXMLHttpRequest.onCreate(this);
- }
- }
-
- // An upload object is created for each
- // FakeXMLHttpRequest and allows upload
- // events to be simulated using uploadProgress
- // and uploadError.
- function UploadProgress() {
- this.eventListeners = {
- "progress": [],
- "load": [],
- "abort": [],
- "error": []
- }
- }
-
- UploadProgress.prototype.addEventListener = function(event, listener) {
- this.eventListeners[event].push(listener);
- };
-
- UploadProgress.prototype.removeEventListener = function(event, listener) {
- var listeners = this.eventListeners[event] || [];
-
- for (var i = 0, l = listeners.length; i < l; ++i) {
- if (listeners[i] == listener) {
- return listeners.splice(i, 1);
- }
- }
- };
-
- UploadProgress.prototype.dispatchEvent = function(event) {
- var listeners = this.eventListeners[event.type] || [];
-
- for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
- listener(event);
- }
- };
-
- function verifyState(xhr) {
- if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
- throw new Error("INVALID_STATE_ERR");
- }
-
- if (xhr.sendFlag) {
- throw new Error("INVALID_STATE_ERR");
- }
- }
-
- // filtering to enable a white-list version of Sinon FakeXhr,
- // where whitelisted requests are passed through to real XHR
- function each(collection, callback) {
- if (!collection) return;
- for (var i = 0, l = collection.length; i < l; i += 1) {
- callback(collection[i]);
- }
- }
- function some(collection, callback) {
- for (var index = 0; index < collection.length; index++) {
- if(callback(collection[index]) === true) return true;
- }
- return false;
- }
- // largest arity in XHR is 5 - XHR#open
- var apply = function(obj,method,args) {
- switch(args.length) {
- case 0: return obj[method]();
- case 1: return obj[method](args[0]);
- case 2: return obj[method](args[0],args[1]);
- case 3: return obj[method](args[0],args[1],args[2]);
- case 4: return obj[method](args[0],args[1],args[2],args[3]);
- case 5: return obj[method](args[0],args[1],args[2],args[3],args[4]);
- }
- };
-
- FakeXMLHttpRequest.filters = [];
- FakeXMLHttpRequest.addFilter = function(fn) {
- this.filters.push(fn)
- };
- var IE6Re = /MSIE 6/;
- FakeXMLHttpRequest.defake = function(fakeXhr,xhrArgs) {
- var xhr = new sinon.xhr.workingXHR();
- each(["open","setRequestHeader","send","abort","getResponseHeader",
- "getAllResponseHeaders","addEventListener","overrideMimeType","removeEventListener"],
- function(method) {
- fakeXhr[method] = function() {
- return apply(xhr,method,arguments);
- };
- });
-
- var copyAttrs = function(args) {
- each(args, function(attr) {
- try {
- fakeXhr[attr] = xhr[attr]
- } catch(e) {
- if(!IE6Re.test(navigator.userAgent)) throw e;
- }
- });
- };
-
- var stateChange = function() {
- fakeXhr.readyState = xhr.readyState;
- if(xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
- copyAttrs(["status","statusText"]);
- }
- if(xhr.readyState >= FakeXMLHttpRequest.LOADING) {
- copyAttrs(["responseText"]);
- }
- if(xhr.readyState === FakeXMLHttpRequest.DONE) {
- copyAttrs(["responseXML"]);
- }
- if(fakeXhr.onreadystatechange) fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
- };
- if(xhr.addEventListener) {
- for(var event in fakeXhr.eventListeners) {
- if(fakeXhr.eventListeners.hasOwnProperty(event)) {
- each(fakeXhr.eventListeners[event],function(handler) {
- xhr.addEventListener(event, handler);
- });
- }
- }
- xhr.addEventListener("readystatechange",stateChange);
- } else {
- xhr.onreadystatechange = stateChange;
- }
- apply(xhr,"open",xhrArgs);
- };
- FakeXMLHttpRequest.useFilters = false;
-
- function verifyRequestOpened(xhr) {
- if (xhr.readyState != FakeXMLHttpRequest.OPENED) {
- throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
- }
- }
-
- function verifyRequestSent(xhr) {
- if (xhr.readyState == FakeXMLHttpRequest.DONE) {
- throw new Error("Request done");
- }
- }
-
- function verifyHeadersReceived(xhr) {
- if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
- throw new Error("No headers received");
- }
- }
-
- function verifyResponseBodyType(body) {
- if (typeof body != "string") {
- var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
- body + ", which is not a string.");
- error.name = "InvalidBodyException";
- throw error;
- }
- }
-
- sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
- async: true,
-
- open: function open(method, url, async, username, password) {
- this.method = method;
- this.url = url;
- this.async = typeof async == "boolean" ? async : true;
- this.username = username;
- this.password = password;
- this.responseText = null;
- this.responseXML = null;
- this.requestHeaders = {};
- this.sendFlag = false;
- if(sinon.FakeXMLHttpRequest.useFilters === true) {
- var xhrArgs = arguments;
- var defake = some(FakeXMLHttpRequest.filters,function(filter) {
- return filter.apply(this,xhrArgs)
- });
- if (defake) {
- return sinon.FakeXMLHttpRequest.defake(this,arguments);
- }
- }
- this.readyStateChange(FakeXMLHttpRequest.OPENED);
- },
-
- readyStateChange: function readyStateChange(state) {
- this.readyState = state;
-
- if (typeof this.onreadystatechange == "function") {
- try {
- this.onreadystatechange();
- } catch (e) {
- sinon.logError("Fake XHR onreadystatechange handler", e);
- }
- }
-
- this.dispatchEvent(new sinon.Event("readystatechange"));
-
- switch (this.readyState) {
- case FakeXMLHttpRequest.DONE:
- this.dispatchEvent(new sinon.Event("load", false, false, this));
- this.dispatchEvent(new sinon.Event("loadend", false, false, this));
- this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
- if (supportsProgress) {
- this.upload.dispatchEvent(new sinon.ProgressEvent('progress', {loaded: 100, total: 100}));
- }
- break;
- }
- },
-
- setRequestHeader: function setRequestHeader(header, value) {
- verifyState(this);
-
- if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
- throw new Error("Refused to set unsafe header \"" + header + "\"");
- }
-
- if (this.requestHeaders[header]) {
- this.requestHeaders[header] += "," + value;
- } else {
- this.requestHeaders[header] = value;
- }
- },
-
- // Helps testing
- setResponseHeaders: function setResponseHeaders(headers) {
- verifyRequestOpened(this);
- this.responseHeaders = {};
-
- for (var header in headers) {
- if (headers.hasOwnProperty(header)) {
- this.responseHeaders[header] = headers[header];
- }
- }
-
- if (this.async) {
- this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
- } else {
- this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
- }
- },
-
- // Currently treats ALL data as a DOMString (i.e. no Document)
- send: function send(data) {
- verifyState(this);
-
- if (!/^(get|head)$/i.test(this.method)) {
- if (this.requestHeaders["Content-Type"]) {
- var value = this.requestHeaders["Content-Type"].split(";");
- this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
- } else {
- this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
- }
-
- this.requestBody = data;
- }
-
- this.errorFlag = false;
- this.sendFlag = this.async;
- this.readyStateChange(FakeXMLHttpRequest.OPENED);
-
- if (typeof this.onSend == "function") {
- this.onSend(this);
- }
-
- this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
- },
-
- abort: function abort() {
- this.aborted = true;
- this.responseText = null;
- this.errorFlag = true;
- this.requestHeaders = {};
-
- if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
- this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
- this.sendFlag = false;
- }
-
- this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
-
- this.dispatchEvent(new sinon.Event("abort", false, false, this));
-
- this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
-
- if (typeof this.onerror === "function") {
- this.onerror();
- }
- },
-
- getResponseHeader: function getResponseHeader(header) {
- if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
- return null;
- }
-
- if (/^Set-Cookie2?$/i.test(header)) {
- return null;
- }
-
- header = header.toLowerCase();
-
- for (var h in this.responseHeaders) {
- if (h.toLowerCase() == header) {
- return this.responseHeaders[h];
- }
- }
-
- return null;
- },
-
- getAllResponseHeaders: function getAllResponseHeaders() {
- if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
- return "";
- }
-
- var headers = "";
-
- for (var header in this.responseHeaders) {
- if (this.responseHeaders.hasOwnProperty(header) &&
- !/^Set-Cookie2?$/i.test(header)) {
- headers += header + ": " + this.responseHeaders[header] + "\r\n";
- }
- }
-
- return headers;
- },
-
- setResponseBody: function setResponseBody(body) {
- verifyRequestSent(this);
- verifyHeadersReceived(this);
- verifyResponseBodyType(body);
-
- var chunkSize = this.chunkSize || 10;
- var index = 0;
- this.responseText = "";
-
- do {
- if (this.async) {
- this.readyStateChange(FakeXMLHttpRequest.LOADING);
- }
-
- this.responseText += body.substring(index, index + chunkSize);
- index += chunkSize;
- } while (index < body.length);
-
- var type = this.getResponseHeader("Content-Type");
-
- if (this.responseText &&
- (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
- try {
- this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
- } catch (e) {
- // Unable to parse XML - no biggie
- }
- }
-
- if (this.async) {
- this.readyStateChange(FakeXMLHttpRequest.DONE);
- } else {
- this.readyState = FakeXMLHttpRequest.DONE;
- }
- },
-
- respond: function respond(status, headers, body) {
- this.status = typeof status == "number" ? status : 200;
- this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
- this.setResponseHeaders(headers || {});
- this.setResponseBody(body || "");
- },
-
- uploadProgress: function uploadProgress(progressEventRaw) {
- if (supportsProgress) {
- this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
- }
- },
-
- uploadError: function uploadError(error) {
- if (supportsCustomEvent) {
- this.upload.dispatchEvent(new sinon.CustomEvent("error", {"detail": error}));
- }
- }
- });
-
- sinon.extend(FakeXMLHttpRequest, {
- UNSENT: 0,
- OPENED: 1,
- HEADERS_RECEIVED: 2,
- LOADING: 3,
- DONE: 4
- });
-
- // Borrowed from JSpec
- FakeXMLHttpRequest.parseXML = function parseXML(text) {
- var xmlDoc;
-
- if (typeof DOMParser != "undefined") {
- var parser = new DOMParser();
- xmlDoc = parser.parseFromString(text, "text/xml");
- } else {
- xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
- xmlDoc.async = "false";
- xmlDoc.loadXML(text);
- }
-
- return xmlDoc;
- };
-
- FakeXMLHttpRequest.statusCodes = {
- 100: "Continue",
- 101: "Switching Protocols",
- 200: "OK",
- 201: "Created",
- 202: "Accepted",
- 203: "Non-Authoritative Information",
- 204: "No Content",
- 205: "Reset Content",
- 206: "Partial Content",
- 300: "Multiple Choice",
- 301: "Moved Permanently",
- 302: "Found",
- 303: "See Other",
- 304: "Not Modified",
- 305: "Use Proxy",
- 307: "Temporary Redirect",
- 400: "Bad Request",
- 401: "Unauthorized",
- 402: "Payment Required",
- 403: "Forbidden",
- 404: "Not Found",
- 405: "Method Not Allowed",
- 406: "Not Acceptable",
- 407: "Proxy Authentication Required",
- 408: "Request Timeout",
- 409: "Conflict",
- 410: "Gone",
- 411: "Length Required",
- 412: "Precondition Failed",
- 413: "Request Entity Too Large",
- 414: "Request-URI Too Long",
- 415: "Unsupported Media Type",
- 416: "Requested Range Not Satisfiable",
- 417: "Expectation Failed",
- 422: "Unprocessable Entity",
- 500: "Internal Server Error",
- 501: "Not Implemented",
- 502: "Bad Gateway",
- 503: "Service Unavailable",
- 504: "Gateway Timeout",
- 505: "HTTP Version Not Supported"
- };
-
- sinon.useFakeXMLHttpRequest = function () {
- sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
- if (xhr.supportsXHR) {
- global.XMLHttpRequest = xhr.GlobalXMLHttpRequest;
- }
-
- if (xhr.supportsActiveX) {
- global.ActiveXObject = xhr.GlobalActiveXObject;
- }
-
- delete sinon.FakeXMLHttpRequest.restore;
-
- if (keepOnCreate !== true) {
- delete sinon.FakeXMLHttpRequest.onCreate;
- }
- };
- if (xhr.supportsXHR) {
- global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
- }
-
- if (xhr.supportsActiveX) {
- global.ActiveXObject = function ActiveXObject(objId) {
- if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
-
- return new sinon.FakeXMLHttpRequest();
- }
-
- return new xhr.GlobalActiveXObject(objId);
- };
- }
-
- return sinon.FakeXMLHttpRequest;
- };
-
- sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
-
-})((function(){ return typeof global === "object" ? global : this; })());
-
-if (typeof module !== 'undefined' && module.exports) {
- module.exports = sinon;
-}
-
-/**
- * @depend fake_xml_http_request.js
- */
-/*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
-/*global module, require, window*/
-/**
- * The Sinon "server" mimics a web server that receives requests from
- * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
- * both synchronously and asynchronously. To respond synchronuously, canned
- * answers have to be provided upfront.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
- var sinon = {};
-}
-
-sinon.fakeServer = (function () {
- var push = [].push;
- function F() {}
-
- function create(proto) {
- F.prototype = proto;
- return new F();
- }
-
- function responseArray(handler) {
- var response = handler;
-
- if (Object.prototype.toString.call(handler) != "[object Array]") {
- response = [200, {}, handler];
- }
-
- if (typeof response[2] != "string") {
- throw new TypeError("Fake server response body should be string, but was " +
- typeof response[2]);
- }
-
- return response;
- }
-
- var wloc = typeof window !== "undefined" ? window.location : {};
- var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
-
- function matchOne(response, reqMethod, reqUrl) {
- var rmeth = response.method;
- var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
- var url = response.url;
- var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
-
- return matchMethod && matchUrl;
- }
-
- function match(response, request) {
- var requestUrl = request.url;
-
- if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
- requestUrl = requestUrl.replace(rCurrLoc, "");
- }
-
- if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
- if (typeof response.response == "function") {
- var ru = response.url;
- var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
- return response.response.apply(response, args);
- }
-
- return true;
- }
-
- return false;
- }
-
- return {
- create: function () {
- var server = create(this);
- this.xhr = sinon.useFakeXMLHttpRequest();
- server.requests = [];
-
- this.xhr.onCreate = function (xhrObj) {
- server.addRequest(xhrObj);
- };
-
- return server;
- },
-
- addRequest: function addRequest(xhrObj) {
- var server = this;
- push.call(this.requests, xhrObj);
-
- xhrObj.onSend = function () {
- server.handleRequest(this);
-
- if (server.autoRespond && !server.responding) {
- setTimeout(function () {
- server.responding = false;
- server.respond();
- }, server.autoRespondAfter || 10);
-
- server.responding = true;
- }
- };
- },
-
- getHTTPMethod: function getHTTPMethod(request) {
- if (this.fakeHTTPMethods && /post/i.test(request.method)) {
- var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
- return !!matches ? matches[1] : request.method;
- }
-
- return request.method;
- },
-
- handleRequest: function handleRequest(xhr) {
- if (xhr.async) {
- if (!this.queue) {
- this.queue = [];
- }
-
- push.call(this.queue, xhr);
- } else {
- this.processRequest(xhr);
- }
- },
-
- log: function(response, request) {
- var str;
-
- str = "Request:\n" + sinon.format(request) + "\n\n";
- str += "Response:\n" + sinon.format(response) + "\n\n";
-
- sinon.log(str);
- },
-
- respondWith: function respondWith(method, url, body) {
- if (arguments.length == 1 && typeof method != "function") {
- this.response = responseArray(method);
- return;
- }
-
- if (!this.responses) { this.responses = []; }
-
- if (arguments.length == 1) {
- body = method;
- url = method = null;
- }
-
- if (arguments.length == 2) {
- body = url;
- url = method;
- method = null;
- }
-
- push.call(this.responses, {
- method: method,
- url: url,
- response: typeof body == "function" ? body : responseArray(body)
- });
- },
-
- respond: function respond() {
- if (arguments.length > 0) this.respondWith.apply(this, arguments);
- var queue = this.queue || [];
- var requests = queue.splice(0, queue.length);
- var request;
-
- while(request = requests.shift()) {
- this.processRequest(request);
- }
- },
-
- processRequest: function processRequest(request) {
- try {
- if (request.aborted) {
- return;
- }
-
- var response = this.response || [404, {}, ""];
-
- if (this.responses) {
- for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
- if (match.call(this, this.responses[i], request)) {
- response = this.responses[i].response;
- break;
- }
- }
- }
-
- if (request.readyState != 4) {
- sinon.fakeServer.log(response, request);
-
- request.respond(response[0], response[1], response[2]);
- }
- } catch (e) {
- sinon.logError("Fake server request processing", e);
- }
- },
-
- restore: function restore() {
- return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
- }
- };
-}());
-
-if (typeof module !== 'undefined' && module.exports) {
- module.exports = sinon;
-}
-
-/**
- * @depend fake_server.js
- * @depend fake_timers.js
- */
-/*jslint browser: true, eqeqeq: false, onevar: false*/
-/*global sinon*/
-/**
- * Add-on for sinon.fakeServer that automatically handles a fake timer along with
- * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
- * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
- * it polls the object for completion with setInterval. Dispite the direct
- * motivation, there is nothing jQuery-specific in this file, so it can be used
- * in any environment where the ajax implementation depends on setInterval or
- * setTimeout.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function () {
- function Server() {}
- Server.prototype = sinon.fakeServer;
-
- sinon.fakeServerWithClock = new Server();
-
- sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
- if (xhr.async) {
- if (typeof setTimeout.clock == "object") {
- this.clock = setTimeout.clock;
- } else {
- this.clock = sinon.useFakeTimers();
- this.resetClock = true;
- }
-
- if (!this.longestTimeout) {
- var clockSetTimeout = this.clock.setTimeout;
- var clockSetInterval = this.clock.setInterval;
- var server = this;
-
- this.clock.setTimeout = function (fn, timeout) {
- server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
-
- return clockSetTimeout.apply(this, arguments);
- };
-
- this.clock.setInterval = function (fn, timeout) {
- server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
-
- return clockSetInterval.apply(this, arguments);
- };
- }
- }
-
- return sinon.fakeServer.addRequest.call(this, xhr);
- };
-
- sinon.fakeServerWithClock.respond = function respond() {
- var returnVal = sinon.fakeServer.respond.apply(this, arguments);
-
- if (this.clock) {
- this.clock.tick(this.longestTimeout || 0);
- this.longestTimeout = 0;
-
- if (this.resetClock) {
- this.clock.restore();
- this.resetClock = false;
- }
- }
-
- return returnVal;
- };
-
- sinon.fakeServerWithClock.restore = function restore() {
- if (this.clock) {
- this.clock.restore();
- }
-
- return sinon.fakeServer.restore.apply(this, arguments);
- };
-}());
-
-/**
- * @depend ../sinon.js
- * @depend collection.js
- * @depend util/fake_timers.js
- * @depend util/fake_server_with_clock.js
- */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global require, module*/
-/**
- * Manages fake collections as well as fake utilities such as Sinon's
- * timers and fake XHR implementation in one convenient object.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof module !== "undefined" && module.exports && typeof require == "function") {
- var sinon = require("../sinon");
- sinon.extend(sinon, require("./util/fake_timers"));
-}
-
-(function () {
- var push = [].push;
-
- function exposeValue(sandbox, config, key, value) {
- if (!value) {
- return;
- }
-
- if (config.injectInto && !(key in config.injectInto)) {
- config.injectInto[key] = value;
- sandbox.injectedKeys.push(key);
- } else {
- push.call(sandbox.args, value);
- }
- }
-
- function prepareSandboxFromConfig(config) {
- var sandbox = sinon.create(sinon.sandbox);
-
- if (config.useFakeServer) {
- if (typeof config.useFakeServer == "object") {
- sandbox.serverPrototype = config.useFakeServer;
- }
-
- sandbox.useFakeServer();
- }
-
- if (config.useFakeTimers) {
- if (typeof config.useFakeTimers == "object") {
- sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
- } else {
- sandbox.useFakeTimers();
- }
- }
-
- return sandbox;
- }
-
- sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
- useFakeTimers: function useFakeTimers() {
- this.clock = sinon.useFakeTimers.apply(sinon, arguments);
-
- return this.add(this.clock);
- },
-
- serverPrototype: sinon.fakeServer,
-
- useFakeServer: function useFakeServer() {
- var proto = this.serverPrototype || sinon.fakeServer;
-
- if (!proto || !proto.create) {
- return null;
- }
-
- this.server = proto.create();
- return this.add(this.server);
- },
-
- inject: function (obj) {
- sinon.collection.inject.call(this, obj);
-
- if (this.clock) {
- obj.clock = this.clock;
- }
-
- if (this.server) {
- obj.server = this.server;
- obj.requests = this.server.requests;
- }
-
- return obj;
- },
-
- restore: function () {
- sinon.collection.restore.apply(this, arguments);
- this.restoreContext();
- },
-
- restoreContext: function () {
- if (this.injectedKeys) {
- for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
- delete this.injectInto[this.injectedKeys[i]];
- }
- this.injectedKeys = [];
- }
- },
-
- create: function (config) {
- if (!config) {
- return sinon.create(sinon.sandbox);
- }
-
- var sandbox = prepareSandboxFromConfig(config);
- sandbox.args = sandbox.args || [];
- sandbox.injectedKeys = [];
- sandbox.injectInto = config.injectInto;
- var prop, value, exposed = sandbox.inject({});
-
- if (config.properties) {
- for (var i = 0, l = config.properties.length; i < l; i++) {
- prop = config.properties[i];
- value = exposed[prop] || prop == "sandbox" && sandbox;
- exposeValue(sandbox, config, prop, value);
- }
- } else {
- exposeValue(sandbox, config, "sandbox", value);
- }
-
- return sandbox;
- }
- });
-
- sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = sinon.sandbox; });
- } else if (typeof module !== 'undefined' && module.exports) {
- module.exports = sinon.sandbox;
- }
-}());
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- * @depend mock.js
- * @depend sandbox.js
- */
-/*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Test function, sandboxes fakes
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
- var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
-
- if (!sinon && commonJSModule) {
- sinon = require("../sinon");
- }
-
- if (!sinon) {
- return;
- }
-
- function test(callback) {
- var type = typeof callback;
-
- if (type != "function") {
- throw new TypeError("sinon.test needs to wrap a test function, got " + type);
- }
-
- function sinonSandboxedTest() {
- var config = sinon.getConfig(sinon.config);
- config.injectInto = config.injectIntoThis && this || config.injectInto;
- var sandbox = sinon.sandbox.create(config);
- var exception, result;
- var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
-
- try {
- result = callback.apply(this, args);
- } catch (e) {
- exception = e;
- }
-
- if (typeof exception !== "undefined") {
- sandbox.restore();
- throw exception;
- }
- else {
- sandbox.verifyAndRestore();
- }
-
- return result;
- };
-
- if (callback.length) {
- return function sinonAsyncSandboxedTest(callback) {
- return sinonSandboxedTest.apply(this, arguments);
- };
- }
-
- return sinonSandboxedTest;
- }
-
- test.config = {
- injectIntoThis: true,
- injectInto: null,
- properties: ["spy", "stub", "mock", "clock", "server", "requests"],
- useFakeTimers: true,
- useFakeServer: true
- };
-
- sinon.test = test;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = test; });
- } else if (commonJSModule) {
- module.exports = test;
- }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend test.js
- */
-/*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
-/*global module, require, sinon*/
-/**
- * Test case, sandboxes all test functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
- var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
-
- if (!sinon && commonJSModule) {
- sinon = require("../sinon");
- }
-
- if (!sinon || !Object.prototype.hasOwnProperty) {
- return;
- }
-
- function createTest(property, setUp, tearDown) {
- return function () {
- if (setUp) {
- setUp.apply(this, arguments);
- }
-
- var exception, result;
-
- try {
- result = property.apply(this, arguments);
- } catch (e) {
- exception = e;
- }
-
- if (tearDown) {
- tearDown.apply(this, arguments);
- }
-
- if (exception) {
- throw exception;
- }
-
- return result;
- };
- }
-
- function testCase(tests, prefix) {
- /*jsl:ignore*/
- if (!tests || typeof tests != "object") {
- throw new TypeError("sinon.testCase needs an object with test functions");
- }
- /*jsl:end*/
-
- prefix = prefix || "test";
- var rPrefix = new RegExp("^" + prefix);
- var methods = {}, testName, property, method;
- var setUp = tests.setUp;
- var tearDown = tests.tearDown;
-
- for (testName in tests) {
- if (tests.hasOwnProperty(testName)) {
- property = tests[testName];
-
- if (/^(setUp|tearDown)$/.test(testName)) {
- continue;
- }
-
- if (typeof property == "function" && rPrefix.test(testName)) {
- method = property;
-
- if (setUp || tearDown) {
- method = createTest(property, setUp, tearDown);
- }
-
- methods[testName] = sinon.test(method);
- } else {
- methods[testName] = tests[testName];
- }
- }
- }
-
- return methods;
- }
-
- sinon.testCase = testCase;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = testCase; });
- } else if (commonJSModule) {
- module.exports = testCase;
- }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- */
-/*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Assertions matching the test spy retrieval interface.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon, global) {
- var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
- var slice = Array.prototype.slice;
- var assert;
-
- if (!sinon && commonJSModule) {
- sinon = require("../sinon");
- }
-
- if (!sinon) {
- return;
- }
-
- function verifyIsStub() {
- var method;
-
- for (var i = 0, l = arguments.length; i < l; ++i) {
- method = arguments[i];
-
- if (!method) {
- assert.fail("fake is not a spy");
- }
-
- if (typeof method != "function") {
- assert.fail(method + " is not a function");
- }
-
- if (typeof method.getCall != "function") {
- assert.fail(method + " is not stubbed");
- }
- }
- }
-
- function failAssertion(object, msg) {
- object = object || global;
- var failMethod = object.fail || assert.fail;
- failMethod.call(object, msg);
- }
-
- function mirrorPropAsAssertion(name, method, message) {
- if (arguments.length == 2) {
- message = method;
- method = name;
- }
-
- assert[name] = function (fake) {
- verifyIsStub(fake);
-
- var args = slice.call(arguments, 1);
- var failed = false;
-
- if (typeof method == "function") {
- failed = !method(fake);
- } else {
- failed = typeof fake[method] == "function" ?
- !fake[method].apply(fake, args) : !fake[method];
- }
-
- if (failed) {
- failAssertion(this, fake.printf.apply(fake, [message].concat(args)));
- } else {
- assert.pass(name);
- }
- };
- }
-
- function exposedName(prefix, prop) {
- return !prefix || /^fail/.test(prop) ? prop :
- prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
- }
-
- assert = {
- failException: "AssertError",
-
- fail: function fail(message) {
- var error = new Error(message);
- error.name = this.failException || assert.failException;
-
- throw error;
- },
-
- pass: function pass(assertion) {},
-
- callOrder: function assertCallOrder() {
- verifyIsStub.apply(null, arguments);
- var expected = "", actual = "";
-
- if (!sinon.calledInOrder(arguments)) {
- try {
- expected = [].join.call(arguments, ", ");
- var calls = slice.call(arguments);
- var i = calls.length;
- while (i) {
- if (!calls[--i].called) {
- calls.splice(i, 1);
- }
- }
- actual = sinon.orderByFirstCall(calls).join(", ");
- } catch (e) {
- // If this fails, we'll just fall back to the blank string
- }
-
- failAssertion(this, "expected " + expected + " to be " +
- "called in order but were called as " + actual);
- } else {
- assert.pass("callOrder");
- }
- },
-
- callCount: function assertCallCount(method, count) {
- verifyIsStub(method);
-
- if (method.callCount != count) {
- var msg = "expected %n to be called " + sinon.timesInWords(count) +
- " but was called %c%C";
- failAssertion(this, method.printf(msg));
- } else {
- assert.pass("callCount");
- }
- },
-
- expose: function expose(target, options) {
- if (!target) {
- throw new TypeError("target is null or undefined");
- }
-
- var o = options || {};
- var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
- var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
-
- for (var method in this) {
- if (method != "export" && (includeFail || !/^(fail)/.test(method))) {
- target[exposedName(prefix, method)] = this[method];
- }
- }
-
- return target;
- },
-
- match: function match(actual, expectation) {
- var matcher = sinon.match(expectation);
- if (matcher.test(actual)) {
- assert.pass("match");
- } else {
- var formatted = [
- "expected value to match",
- " expected = " + sinon.format(expectation),
- " actual = " + sinon.format(actual)
- ]
- failAssertion(this, formatted.join("\n"));
- }
- }
- };
-
- mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
- mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
- "expected %n to not have been called but was called %c%C");
- mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
- mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
- mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
- mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
- mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
- mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
- mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
- mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
- mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
- mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
- mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
- mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
- mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
- mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
- mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
- mirrorPropAsAssertion("threw", "%n did not throw exception%C");
- mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
-
- sinon.assert = assert;
-
- if (typeof define === "function" && define.amd) {
- define(["module"], function(module) { module.exports = assert; });
- } else if (commonJSModule) {
- module.exports = assert;
- }
-}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
-
-/**
- * @depend ../../sinon.js
- * @depend event.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, XDomainRequest*/
-/**
- * Fake XDomainRequest object
- */
-
-if (typeof sinon == "undefined") {
- this.sinon = {};
-}
-sinon.xdr = { XDomainRequest: this.XDomainRequest };
-
-// wrapper for global
-(function (global) {
- var xdr = sinon.xdr;
- xdr.GlobalXDomainRequest = global.XDomainRequest;
- xdr.supportsXDR = typeof xdr.GlobalXDomainRequest != "undefined";
- xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false;
-
- function FakeXDomainRequest() {
- this.readyState = FakeXDomainRequest.UNSENT;
- this.requestBody = null;
- this.requestHeaders = {};
- this.status = 0;
- this.timeout = null;
-
- if (typeof FakeXDomainRequest.onCreate == "function") {
- FakeXDomainRequest.onCreate(this);
- }
- }
-
- function verifyState(xdr) {
- if (xdr.readyState !== FakeXDomainRequest.OPENED) {
- throw new Error("INVALID_STATE_ERR");
- }
-
- if (xdr.sendFlag) {
- throw new Error("INVALID_STATE_ERR");
- }
- }
-
- function verifyRequestSent(xdr) {
- if (xdr.readyState == FakeXDomainRequest.UNSENT) {
- throw new Error("Request not sent");
- }
- if (xdr.readyState == FakeXDomainRequest.DONE) {
- throw new Error("Request done");
- }
- }
-
- function verifyResponseBodyType(body) {
- if (typeof body != "string") {
- var error = new Error("Attempted to respond to fake XDomainRequest with " +
- body + ", which is not a string.");
- error.name = "InvalidBodyException";
- throw error;
- }
- }
-
- sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
- open: function open(method, url) {
- this.method = method;
- this.url = url;
-
- this.responseText = null;
- this.sendFlag = false;
-
- this.readyStateChange(FakeXDomainRequest.OPENED);
- },
-
- readyStateChange: function readyStateChange(state) {
- this.readyState = state;
- var eventName = '';
- switch (this.readyState) {
- case FakeXDomainRequest.UNSENT:
- break;
- case FakeXDomainRequest.OPENED:
- break;
- case FakeXDomainRequest.LOADING:
- if (this.sendFlag){
- //raise the progress event
- eventName = 'onprogress';
- }
- break;
- case FakeXDomainRequest.DONE:
- if (this.isTimeout){
- eventName = 'ontimeout'
- }
- else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
- eventName = 'onerror';
- }
- else {
- eventName = 'onload'
- }
- break;
- }
-
- // raising event (if defined)
- if (eventName) {
- if (typeof this[eventName] == "function") {
- try {
- this[eventName]();
- } catch (e) {
- sinon.logError("Fake XHR " + eventName + " handler", e);
- }
- }
- }
- },
-
- send: function send(data) {
- verifyState(this);
-
- if (!/^(get|head)$/i.test(this.method)) {
- this.requestBody = data;
- }
- this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
-
- this.errorFlag = false;
- this.sendFlag = true;
- this.readyStateChange(FakeXDomainRequest.OPENED);
-
- if (typeof this.onSend == "function") {
- this.onSend(this);
- }
- },
-
- abort: function abort() {
- this.aborted = true;
- this.responseText = null;
- this.errorFlag = true;
-
- if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
- this.readyStateChange(sinon.FakeXDomainRequest.DONE);
- this.sendFlag = false;
- }
- },
-
- setResponseBody: function setResponseBody(body) {
- verifyRequestSent(this);
- verifyResponseBodyType(body);
-
- var chunkSize = this.chunkSize || 10;
- var index = 0;
- this.responseText = "";
-
- do {
- this.readyStateChange(FakeXDomainRequest.LOADING);
- this.responseText += body.substring(index, index + chunkSize);
- index += chunkSize;
- } while (index < body.length);
-
- this.readyStateChange(FakeXDomainRequest.DONE);
- },
-
- respond: function respond(status, contentType, body) {
- // content-type ignored, since XDomainRequest does not carry this
- // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
- // test integration across browsers
- this.status = typeof status == "number" ? status : 200;
- this.setResponseBody(body || "");
- },
-
- simulatetimeout: function(){
- this.status = 0;
- this.isTimeout = true;
- // Access to this should actually throw an error
- this.responseText = undefined;
- this.readyStateChange(FakeXDomainRequest.DONE);
- }
- });
-
- sinon.extend(FakeXDomainRequest, {
- UNSENT: 0,
- OPENED: 1,
- LOADING: 3,
- DONE: 4
- });
-
- sinon.useFakeXDomainRequest = function () {
- sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
- if (xdr.supportsXDR) {
- global.XDomainRequest = xdr.GlobalXDomainRequest;
- }
-
- delete sinon.FakeXDomainRequest.restore;
-
- if (keepOnCreate !== true) {
- delete sinon.FakeXDomainRequest.onCreate;
- }
- };
- if (xdr.supportsXDR) {
- global.XDomainRequest = sinon.FakeXDomainRequest;
- }
- return sinon.FakeXDomainRequest;
- };
-
- sinon.FakeXDomainRequest = FakeXDomainRequest;
-})(this);
-
-if (typeof module == "object" && typeof require == "function") {
- module.exports = sinon;
-}
-
-return sinon;}.call(typeof window != 'undefined' && window || {}));
diff --git a/test/unit/tax.test.js b/test/tax.test.js
similarity index 96%
rename from test/unit/tax.test.js
rename to test/tax.test.js
index 89d7b89fc..61993fb5d 100644
--- a/test/unit/tax.test.js
+++ b/test/tax.test.js
@@ -1,6 +1,6 @@
-var assert = require('assert');
-var noop = require('noop');
-var helpers = require('../support/helpers');
+var assert = require('component/assert');
+var noop = require('chrissrogers/noop');
+var helpers = require('./support/helpers');
var sinon = window.sinon;
helpers.apiTest(function (requestMethod) {
diff --git a/test/unit/token.test.js b/test/token.test.js
similarity index 81%
rename from test/unit/token.test.js
rename to test/token.test.js
index c976356b4..f866e2e1d 100644
--- a/test/unit/token.test.js
+++ b/test/token.test.js
@@ -1,12 +1,11 @@
-
-var assert = require('assert');
-var merge = require('merge');
-var clone = require('clone');
-var each = require('each');
-var noop = require('noop');
-var after = require('after');
-var index = require('indexof');
-var helpers = require('../support/helpers');
+var assert = require('component/assert');
+var index = require('component/indexof');
+var clone = require('component/clone');
+var each = require('component/each');
+var noop = require('chrissrogers/noop');
+var after = require('segmentio/after');
+var merge = require('yields/merge');
+var helpers = require('./support/helpers');
helpers.apiTest(function (requestMethod) {
describe('Recurly.token (' + requestMethod + ')', function () {
@@ -223,7 +222,7 @@ helpers.apiTest(function (requestMethod) {
});
});
- describe('when given an required configured', function () {
+ describe('when given additional required fields', function () {
beforeEach(function () {
recurly = new Recurly();
recurly.configure({
@@ -234,7 +233,7 @@ helpers.apiTest(function (requestMethod) {
});
});
- describe('when given an blank value for required', function () {
+ describe('when given a blank required value', function () {
var examples = [
merge(clone(valid), {
country: '',
@@ -265,55 +264,6 @@ helpers.apiTest(function (requestMethod) {
});
});
});
-
- describe('when given valid values', function () {
- var examples = [
- merge(clone(valid), {
- postal_code: '94110',
- country: 'US'
- }),
- merge(clone(valid), {
- address1: '400 Alabama St.',
- address2: 'Suite 202',
- city: 'San Francisco',
- state: 'CA',
- postal_code: '94110',
- country: 'US',
- phone: '1-844-732-8759'
- })
- ];
-
- it('yields a token', function (done) {
- var part = after(examples.length, done);
-
- each(examples, function (example) {
- builder(example, function (example) {
- recurly.token(example, function (err, token) {
- assert(!err);
- assert(token.id);
- part();
- });
- });
- });
- });
-
- it('sets the value of a data-recurly="token" field', function (done) {
- var part = after(examples.length, done);
-
- each(examples, function (example) {
- builder(example, function (example) {
- recurly.token(example, function (err, token) {
- assert(!err);
- assert(token.id);
- if (example && example.nodeType === 3) {
- assert(example.querySelector('[data-recurly=token]').value === token.id);
- }
- part();
- });
- });
- });
- });
- });
});
};
});
diff --git a/test/unit/validate.test.js b/test/validate.test.js
similarity index 98%
rename from test/unit/validate.test.js
rename to test/validate.test.js
index 7175cfacf..452f07310 100644
--- a/test/unit/validate.test.js
+++ b/test/validate.test.js
@@ -1,5 +1,4 @@
-
-var assert = require('assert');
+var assert = require('component/assert');
describe('Recurly.validate', function () {
var Recurly = window.recurly.Recurly;