Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Giehl <stefan@piwik.org>2017-04-18 21:43:51 +0300
committerGitHub <noreply@github.com>2017-04-18 21:43:51 +0300
commit6a97e43ff69795c53c1b8dff63fc6a5cbdba8ca8 (patch)
tree5d3b8790c025ba8664a9fab1dbecfbb1f2b58dca /tests/lib/mocha-3.1.2/test
parentac9d6ab9ee5cf80ad2a769d40004c20410dc1053 (diff)
update mocha to 3.1.2 (#11625)
Diffstat (limited to 'tests/lib/mocha-3.1.2/test')
-rw-r--r--tests/lib/mocha-3.1.2/test/.eslintrc.yaml7
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/context.spec.js73
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/duration.spec.js27
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/fs.spec.js22
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/glob/glob.sh66
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/glob/glob.spec.js7
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/globals.spec.js43
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/http.spec.js18
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/interfaces/bdd.spec.js34
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/interfaces/exports.spec.js48
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/interfaces/qunit.spec.js25
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/interfaces/tdd.spec.js42
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/lookup-files.spec.js90
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/misc/exit.spec.js20
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/misc/many.spec.js28
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/misc/nontty.spec.js11
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/misc/only/bdd-require.spec.js20
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/misc/only/bdd.spec.js127
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/bdd.spec.js14
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/qunit.spec.js14
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/tdd.spec.js14
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/misc/only/qunit.spec.js75
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/misc/only/tdd.spec.js127
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/overspecified-async.spec.js10
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/require/a.js4
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/require/b.coffee2
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/require/c.js4
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/require/d.coffee2
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/require/require.spec.js11
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/required-tokens.spec.js12
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/root.spec.js13
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/test.coffee6
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/test.foo1
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/throw.spec.js108
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/timeout.spec.js79
-rw-r--r--tests/lib/mocha-3.1.2/test/acceptance/utils.spec.js418
-rw-r--r--tests/lib/mocha-3.1.2/test/browser-fixtures/bdd.fixture.js6
-rw-r--r--tests/lib/mocha-3.1.2/test/browser-fixtures/exports.fixture.js6
-rw-r--r--tests/lib/mocha-3.1.2/test/browser-fixtures/qunit.fixture.js6
-rw-r--r--tests/lib/mocha-3.1.2/test/browser-fixtures/tdd.fixture.js6
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/array.spec.js39
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/grep.html51
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/grep.spec.js110
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/index.html33
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/large.html24
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/large.spec.js49
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/multiple-done.spec.js18
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/opts.html30
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/opts.spec.js7
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/stack-trace.html24
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/stack-trace.spec.js22
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/ui.html46
-rw-r--r--tests/lib/mocha-3.1.2/test/browser/ui.spec.js33
-rw-r--r--tests/lib/mocha-3.1.2/test/color.spec.js20
-rw-r--r--tests/lib/mocha-3.1.2/test/compiler/foo.js10
-rw-r--r--tests/lib/mocha-3.1.2/test/grep.spec.js67
-rw-r--r--tests/lib/mocha-3.1.2/test/hook-async.spec.js135
-rw-r--r--tests/lib/mocha-3.1.2/test/hook-sync-nested.spec.js104
-rw-r--r--tests/lib/mocha-3.1.2/test/hook-sync.spec.js103
-rw-r--r--tests/lib/mocha-3.1.2/test/hook-timeout.spec.js10
-rw-r--r--tests/lib/mocha-3.1.2/test/http-meta-2.spec.js92
-rw-r--r--tests/lib/mocha-3.1.2/test/http-meta.spec.js65
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/diffs.spec.js46
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/cascade.fixture.js59
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.css.in9
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.css.out13
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.fixture.js113
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/output91
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/after-hook-async-error.fixture.js21
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/after-hook-error.fixture.js19
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/afterEach-hook-async-error.fixture.js21
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/afterEach-hook-error.fixture.js19
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-async-error-tip.fixture.js13
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-async-error.fixture.js21
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-error-tip.fixture.js11
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-error.fixture.js19
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/beforeEach-hook-async-error.fixture.js21
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/beforeEach-hook-error.fixture.js19
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/multiple-hook-async-error.fixture.js141
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/multiple-hook-error.fixture.js131
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-before.fixture.js12
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-beforeEach.fixture.js16
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-specs.fixture.js12
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done.fixture.js20
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/async-only-async.fixture.js5
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/async-only-sync.fixture.js3
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/bail.fixture.js23
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/delay-fail.fixture.js8
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/delay.fixture.js16
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/grep.fixture.js19
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/bdd.fixture.js72
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/qunit.fixture.js27
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/tdd.fixture.js37
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/retries.fixture.js7
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/sort-alpha.fixture.js9
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/options/sort-beta.fixture.js7
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/passing.fixture.js13
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-before.fixture.js18
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-beforeEach.fixture.js18
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-spec.fixture.js14
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-before.fixture.js15
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-beforeEach.fixture.js15
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-spec.fixture.js12
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/pending/spec.fixture.js5
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/regression/1794/issue-1794.fixture.js5
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/regression/1794/simple-ui.js28
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1327.fixture.js17
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1417.js22
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1991.fixture.js49
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2315.js11
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2406.fixture.js17
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2417.fixture.js9
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/retries/async.fixture.js30
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/retries/early-pass.fixture.js13
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/retries/hooks.fixture.js27
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/retries/nested.fixture.js11
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-no-callback.fixture.js3
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-skipped-callback.fixture.js3
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-skipped-no-callback.fixture.js3
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/timeout.fixture.js19
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/uncaught-hook.fixture.js15
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/fixtures/uncaught.fixture.js22
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/helpers.js193
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/hook-err.spec.js217
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/hooks.spec.js45
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/multiple-done.spec.js98
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/only.spec.js45
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/options.spec.js183
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/pending.spec.js102
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/regression.spec.js119
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/reporters.spec.js63
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/retries.spec.js108
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/suite.spec.js43
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/timeout.spec.js18
-rw-r--r--tests/lib/mocha-3.1.2/test/integration/uncaught.spec.js37
-rw-r--r--tests/lib/mocha-3.1.2/test/jsapi/index.js30
-rw-r--r--tests/lib/mocha-3.1.2/test/mocha.opts8
-rw-r--r--tests/lib/mocha-3.1.2/test/mocha.spec.js35
-rw-r--r--tests/lib/mocha-3.1.2/test/ms.spec.js82
-rw-r--r--tests/lib/mocha-3.1.2/test/reporters/base.spec.js213
-rw-r--r--tests/lib/mocha-3.1.2/test/reporters/json.spec.js63
-rw-r--r--tests/lib/mocha-3.1.2/test/reporters/nyan.spec.js31
-rw-r--r--tests/lib/mocha-3.1.2/test/runnable.spec.js466
-rw-r--r--tests/lib/mocha-3.1.2/test/runner.spec.js436
-rw-r--r--tests/lib/mocha-3.1.2/test/sanity/sanity.spec.js9
-rw-r--r--tests/lib/mocha-3.1.2/test/setup.js4
-rw-r--r--tests/lib/mocha-3.1.2/test/suite.spec.js440
-rw-r--r--tests/lib/mocha-3.1.2/test/test.spec.js77
-rw-r--r--tests/lib/mocha-3.1.2/test/utils.spec.js263
149 files changed, 7660 insertions, 0 deletions
diff --git a/tests/lib/mocha-3.1.2/test/.eslintrc.yaml b/tests/lib/mocha-3.1.2/test/.eslintrc.yaml
new file mode 100644
index 0000000000..1830a0b6f4
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/.eslintrc.yaml
@@ -0,0 +1,7 @@
+env:
+ mocha: true
+globals:
+ expect: false
+ assert: false
+ # https://github.com/sindresorhus/globals/pull/102
+ run: false
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/context.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/context.spec.js
new file mode 100644
index 0000000000..cbcdedb49d
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/context.spec.js
@@ -0,0 +1,73 @@
+'use strict';
+
+describe('Context', function () {
+ beforeEach(function () {
+ this.calls = ['before'];
+ });
+
+ describe('nested', function () {
+ beforeEach(function () {
+ this.calls.push('before two');
+ });
+
+ it('should work', function () {
+ expect(this.calls).to.eql(['before', 'before two']);
+ this.calls.push('test');
+ });
+
+ after(function () {
+ expect(this.calls).to.eql(['before', 'before two', 'test']);
+ this.calls.push('after two');
+ });
+ });
+
+ after(function () {
+ expect(this.calls).to.eql(['before', 'before two', 'test', 'after two']);
+ });
+});
+
+describe('Context Siblings', function () {
+ beforeEach(function () {
+ this.calls = ['before'];
+ });
+
+ describe('sequestered sibling', function () {
+ beforeEach(function () {
+ this.calls.push('before two');
+ this.hiddenFromSibling = 'This should be hidden';
+ });
+
+ it('should work', function () {
+ expect(this.hiddenFromSibling).to.eql('This should be hidden');
+ });
+ });
+
+ describe('sibling verifiction', function () {
+ beforeEach(function () {
+ this.calls.push('before sibling');
+ });
+
+ it('should not have value set within a sibling describe', function () {
+ expect('This should be hidden').not.to.eql(this.hiddenFromSibling);
+ this.visibleFromTestSibling = 'Visible from test sibling';
+ });
+
+ it('should allow test siblings to modify shared context', function () {
+ expect('Visible from test sibling').to.eql(this.visibleFromTestSibling);
+ });
+
+ it('should have reset this.calls before describe', function () {
+ expect(this.calls).to.eql(['before', 'before sibling']);
+ });
+ });
+
+ after(function () {
+ expect(this.calls).to.eql(['before', 'before sibling']);
+ });
+});
+
+describe('timeout()', function () {
+ it('should return the timeout', function () {
+ expect(this.timeout()).to.equal(200);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/duration.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/duration.spec.js
new file mode 100644
index 0000000000..0194d4408c
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/duration.spec.js
@@ -0,0 +1,27 @@
+'use strict';
+
+describe('durations', function () {
+ describe('when slow', function () {
+ it('should highlight in red', function (done) {
+ setTimeout(function () {
+ done();
+ }, 100);
+ });
+ });
+
+ describe('when reasonable', function () {
+ it('should highlight in yellow', function (done) {
+ setTimeout(function () {
+ done();
+ }, 50);
+ });
+ });
+
+ describe('when fast', function () {
+ it('should highlight in green', function (done) {
+ setTimeout(function () {
+ done();
+ }, 10);
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/fs.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/fs.spec.js
new file mode 100644
index 0000000000..9d0357c382
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/fs.spec.js
@@ -0,0 +1,22 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+var os = require('os');
+var tmpFile = path.join.bind(path, os.tmpdir());
+
+describe('fs.readFile()', function () {
+ describe('when the file exists', function () {
+ it('should succeed', function (done) {
+ fs.writeFile(tmpFile('mocha'), 'wahoo', done);
+ });
+ });
+
+ describe('when the file does not exist', function () {
+ it('should fail', function (done) {
+ // uncomment
+ // fs.readFile(tmpFile('does-not-exist'), done);
+ done();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/glob/glob.sh b/tests/lib/mocha-3.1.2/test/acceptance/glob/glob.sh
new file mode 100644
index 0000000000..823ba07fb9
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/glob/glob.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+REL_SCRIPT_DIR="`dirname \"$0\"`"
+SCRIPT_DIR="`( cd \"$REL_SCRIPT_DIR\" && pwd )`"
+
+cd $SCRIPT_DIR || {
+ echo Could not cd to $SCRIPT_DIR from `pwd`
+ exit 1
+}
+
+../../../bin/mocha -R json-stream ./*.js > /tmp/mocha-glob.txt || {
+ echo Globbing ./*.js in `pwd` failed.
+ exit 1
+}
+
+cat /tmp/mocha-glob.txt | grep -q -F '["end",{"suites":1,"tests":1,"passes":1,"pending":0,"failures":0,' || {
+ echo Globbing ./*.js in `pwd` should match glob.js with one test inside.
+ exit 1
+}
+
+../../../bin/mocha -R json-stream ./*-none.js 2> /tmp/mocha-glob.txt && {
+ echo Globbing './*-none.js' in `pwd` failed.
+ exit 1
+}
+
+cat /tmp/mocha-glob.txt | grep -q -F 'Could not find any test files matching pattern' || {
+ echo Globbing './*-none.js' in `pwd` should match no files and run no tests.
+ exit 1
+}
+
+../../../bin/mocha -R json-stream ./*.js ./*-none.js >& /tmp/mocha-glob.txt || {
+ echo Globbing ./*.js ./*-none.js in `pwd` failed.
+ exit 1
+}
+
+cat /tmp/mocha-glob.txt | grep -q -F '["end",{"suites":1,"tests":1,"passes":1,"pending":0,"failures":0,' &&
+cat /tmp/mocha-glob.txt | grep -q -F 'Could not find any test files matching pattern' || {
+ echo Globbing ./*.js ./*-none.js in `pwd` should match glob.js with one test inside and display one warning for the non-existing file.
+ exit 1
+}
+
+# Globbing in windows command-shell differs completely from unix-style globbing.
+# In bash, the shell expands globs and passes the result to executables.
+# In windows, the shell passes globs unexpanded, executables do expansion if they support it.
+# Adding single-quotes around the glob below makes bash pass glob unexpanded,
+# allowing us to test windows-style globbing in bash.
+../../../bin/mocha -R json-stream './*.js' > /tmp/mocha-glob.txt || {
+ echo Globbing './*.js' in `pwd` failed.
+ exit 1
+}
+
+cat /tmp/mocha-glob.txt | grep -q -F '["end",{"suites":1,"tests":1,"passes":1,"pending":0,"failures":0,' || {
+ echo Globbing './*.js' in `pwd` should match glob.js with one test inside.
+ exit 1
+}
+
+../../../bin/mocha -R json-stream './*-none.js' 2> /tmp/mocha-glob.txt && {
+ echo Globbing './*-none.js' in `pwd` failed.
+ exit 1
+}
+
+cat /tmp/mocha-glob.txt | grep -q -F 'Could not find any test files matching pattern' || {
+ echo Globbing './*-none.js' in `pwd` should match no files and run no tests.
+ exit 1
+}
+
+echo Glob-test passed.
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/glob/glob.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/glob/glob.spec.js
new file mode 100644
index 0000000000..eca3733898
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/glob/glob.spec.js
@@ -0,0 +1,7 @@
+'use strict';
+
+describe('globbing test', function () {
+ it('should find this test', function () {
+ // see glob.sh for details
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/globals.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/globals.spec.js
new file mode 100644
index 0000000000..b87df9fd99
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/globals.spec.js
@@ -0,0 +1,43 @@
+'use strict';
+
+describe('global leaks', function () {
+ before(function () {
+ // uncomment to test
+ // foo = 'hey';
+ // bar = 'hey';
+ });
+
+ beforeEach(function () {
+ // uncomment to test
+ // foo = 'bar'
+ });
+
+ it('should cause tests to fail', function () {
+ // uncomment to test
+ // foo = 'bar';
+ // bar = 'baz';
+ // baz = 'raz';
+ });
+
+ it('should pass when accepted', function () {
+ global.okGlobalA = 1;
+ global.okGlobalB = 1;
+ global.okGlobalC = 1;
+ });
+
+ it('should pass with wildcard', function () {
+ global.callback123 = 'foo';
+ global.callback345 = 'bar';
+ });
+
+ it('should pass when prefixed "mocha-"', function () {
+ // Opera and IE do this for HTML element IDs anyway
+ // but to sure we can assert this in any browser, simulate it.
+ global['mocha-example'] = { nodeType: 1 };
+ });
+
+ afterEach(function () {
+ // uncomment to test
+ // foo = 'bar'
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/http.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/http.spec.js
new file mode 100644
index 0000000000..b8bc2f7e26
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/http.spec.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var http = require('http');
+
+var server = http.createServer(function (req, res) {
+ res.end('Hello World\n');
+});
+
+server.listen(8888);
+
+describe('http', function () {
+ it('should provide an example', function (done) {
+ http.get({ path: '/', port: 8888 }, function (res) {
+ expect(res).to.have.property('statusCode', 200);
+ done();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/interfaces/bdd.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/interfaces/bdd.spec.js
new file mode 100644
index 0000000000..f6e24d88a8
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/interfaces/bdd.spec.js
@@ -0,0 +1,34 @@
+'use strict';
+
+describe('integer primitives', function () {
+ describe('arithmetic', function () {
+ it('should add', function () {
+ expect(1 + 1).to.equal(2);
+ expect(2 + 2).to.equal(4);
+ });
+
+ it('should subtract', function () {
+ expect(1 - 1).to.equal(0);
+ expect(2 - 1).to.equal(1);
+ });
+ });
+});
+
+describe('integer primitives', function () {
+ describe('arithmetic is not', function () {
+ it('should add', function () {
+ expect(1 + 1).not.to.equal(3);
+ expect(2 + 2).not.to.equal(5);
+ });
+ });
+});
+
+context('test suite', function () {
+ beforeEach(function () {
+ this.number = 5;
+ });
+
+ specify('share a property', function () {
+ expect(this.number).to.equal(5);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/interfaces/exports.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/interfaces/exports.spec.js
new file mode 100644
index 0000000000..f53c6a4ca0
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/interfaces/exports.spec.js
@@ -0,0 +1,48 @@
+'use strict';
+
+var calls = [];
+
+exports.Array = {
+ before: function () {
+ calls.push('before');
+ },
+
+ after: function () {
+ calls.push('after');
+ expect(calls)
+ .to
+ .eql([
+ 'before',
+ 'before each',
+ 'one',
+ 'after each',
+ 'before each',
+ 'two',
+ 'after each',
+ 'after'
+ ]);
+ },
+
+ '#indexOf()': {
+ beforeEach: function () {
+ calls.push('before each');
+ },
+
+ afterEach: function () {
+ calls.push('after each');
+ },
+
+ 'should return -1 when the value is not present': function () {
+ calls.push('one');
+ expect([1, 2, 3].indexOf(5)).to.equal(-1);
+ expect([1, 2, 3].indexOf(0)).to.equal(-1);
+ },
+
+ 'should return the correct index when the value is present': function () {
+ calls.push('two');
+ expect([1, 2, 3].indexOf(1)).to.equal(0);
+ expect([1, 2, 3].indexOf(2)).to.equal(1);
+ expect([1, 2, 3].indexOf(3)).to.equal(2);
+ }
+ }
+};
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/interfaces/qunit.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/interfaces/qunit.spec.js
new file mode 100644
index 0000000000..0d15272f0b
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/interfaces/qunit.spec.js
@@ -0,0 +1,25 @@
+'use strict';
+
+function ok (expr, msg) {
+ if (!expr) throw new Error(msg);
+}
+
+suite('integer primitives');
+
+test('should add', function () {
+ var number = 2 + 2;
+ ok(number === 4);
+});
+
+test('should decrement', function () {
+ var number = 3;
+ ok(--number === 2);
+ ok(--number === 1);
+ ok(--number === 0);
+});
+
+suite('String');
+
+test('#length', function () {
+ ok('foo'.length === 3);
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/interfaces/tdd.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/interfaces/tdd.spec.js
new file mode 100644
index 0000000000..c2db518d70
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/interfaces/tdd.spec.js
@@ -0,0 +1,42 @@
+'use strict';
+
+suite('integer primitives', function () {
+ suite('arithmetic', function () {
+ var initialValue = 41;
+
+ suiteSetup(function (done) {
+ expect(initialValue).to.eql(41);
+ initialValue += 1;
+ done();
+ });
+
+ test('should add', function () {
+ expect(initialValue).to.eql(42);
+ expect(1 + 1).to.equal(2);
+ expect(2 + 2).to.equal(4);
+ });
+
+ test('should subtract', function () {
+ expect(initialValue).to.eql(42);
+ expect(1 - 1).to.equal(0);
+ expect(2 - 1).to.equal(1);
+ });
+
+ test.skip('should skip this test', function () {
+ var zero = 0;
+ expect(zero).to.equal(1, 'this test should have been skipped');
+ });
+
+ suite.skip('should skip this suite', function () {
+ test('should skip this test', function () {
+ var zero = 0;
+ expect(zero).to.equal(1, 'this test should have been skipped');
+ });
+ });
+
+ suiteTeardown(function (done) {
+ expect(initialValue).to.eql(42);
+ done();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/lookup-files.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/lookup-files.spec.js
new file mode 100644
index 0000000000..faf31b1375
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/lookup-files.spec.js
@@ -0,0 +1,90 @@
+'use strict';
+
+var utils = require('../../lib/utils');
+var fs = require('fs');
+var path = require('path');
+var os = require('os');
+var mkdirp = require('mkdirp');
+var rimraf = require('rimraf');
+
+describe('lookupFiles', function () {
+ var tmpDir = path.join(os.tmpDir(), 'mocha-lookup-files');
+ var existsSync = fs.existsSync;
+ var tmpFile = path.join.bind(path, tmpDir);
+ var symlinkSupported = false;
+
+ (function testSymlinkSupport () {
+ makeTempDir();
+
+ fs.writeFileSync(tmpFile('mocha-utils.js'), 'yippy skippy ying yang yow');
+ try {
+ fs.symlinkSync(tmpFile('mocha-utils.js'), tmpFile('mocha-utils-link.js'));
+ symlinkSupported = true;
+ } catch (ignored) {
+ // ignored
+ } finally {
+ removeTempDir();
+ }
+ }());
+
+ beforeEach(function () {
+ makeTempDir();
+
+ fs.writeFileSync(tmpFile('mocha-utils.js'), 'yippy skippy ying yang yow');
+ if (symlinkSupported) {
+ fs.symlinkSync(tmpFile('mocha-utils.js'), tmpFile('mocha-utils-link.js'));
+ }
+ });
+
+ (symlinkSupported ? it : it.skip)('should not choke on symlinks', function () {
+ expect(utils.lookupFiles(tmpDir, ['js'], false))
+ .to
+ .contain(tmpFile('mocha-utils-link.js'))
+ .and
+ .contain(tmpFile('mocha-utils.js'))
+ .and
+ .have
+ .length(2);
+ expect(existsSync(tmpFile('mocha-utils-link.js')))
+ .to
+ .be(true);
+ fs.renameSync(tmpFile('mocha-utils.js'), tmpFile('bob'));
+ expect(existsSync(tmpFile('mocha-utils-link.js')))
+ .to
+ .be(false);
+ expect(utils.lookupFiles(tmpDir, ['js'], false))
+ .to
+ .eql([]);
+ });
+
+ it('should accept a glob "path" value', function () {
+ var res = utils.lookupFiles(tmpFile('mocha-utils*'), ['js'], false)
+ .map(path.normalize.bind(path));
+
+ var expectedLength = 0;
+ var ex = expect(res)
+ .to
+ .contain(tmpFile('mocha-utils.js'));
+ expectedLength++;
+
+ if (symlinkSupported) {
+ ex = ex.and
+ .contain(tmpFile('mocha-utils-link.js'));
+ expectedLength++;
+ }
+
+ ex.and
+ .have
+ .length(expectedLength);
+ });
+
+ afterEach(removeTempDir);
+
+ function makeTempDir () {
+ mkdirp.sync(tmpDir);
+ }
+
+ function removeTempDir () {
+ rimraf.sync(tmpDir);
+ }
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/misc/exit.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/misc/exit.spec.js
new file mode 100644
index 0000000000..916752f9b1
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/misc/exit.spec.js
@@ -0,0 +1,20 @@
+'use strict';
+
+describe('exit', function () {
+ // note --bail works nicely in that it still allows an 'early exit' in an error scenario
+ it('should not exit even in error scenario if called with --no-exit', function (done) {
+ done(new Error('failure'));
+ });
+
+ it('should take a long time to exit if called with --no-exit', function (done) {
+ done();
+ setTimeout(function () {
+ console.log('all done');
+ }, 2500);
+ });
+
+ it('should kill all processes when SIGINT received', function () {
+ // uncomment to test
+ // while (true) {}
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/misc/many.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/misc/many.spec.js
new file mode 100644
index 0000000000..d4e4a1e806
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/misc/many.spec.js
@@ -0,0 +1,28 @@
+'use strict';
+
+// Useful for testing SIGINT handler
+// use env.big_number to tune iterations so that you have time to ctrl+c
+
+describe('a load of tests', function () {
+ it('should fail the first test', function () {
+ throw new Error('this should appear in the summary');
+ });
+
+ var iterations = (process.env.big_number || 1e7);
+ function work () {
+ var a = 0;
+ for (var i = 0; i < iterations; ++i) {
+ a += i;
+ }
+ }
+
+ function addTest () {
+ it('should pass test ' + i, function () {
+ work();
+ });
+ }
+
+ for (var i = 0; i < 500; ++i) {
+ addTest();
+ }
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/misc/nontty.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/misc/nontty.spec.js
new file mode 100644
index 0000000000..ea57b9733f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/misc/nontty.spec.js
@@ -0,0 +1,11 @@
+'use strict';
+
+describe('tests for non-tty', function () {
+ it('should pass', function () {
+
+ });
+
+ it('should fail', function () {
+ throw new Error('oh noes');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/misc/only/bdd-require.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/bdd-require.spec.js
new file mode 100644
index 0000000000..14710c4cd2
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/bdd-require.spec.js
@@ -0,0 +1,20 @@
+'use strict';
+
+/* jshint node: true */
+
+var mocha = require('../../../../lib/mocha');
+
+var beforeEach = mocha.beforeEach;
+var it = mocha.it;
+var describe = mocha.describe;
+
+describe('it.only via require("mocha")', function () {
+ beforeEach(function () {
+ this.didRunBeforeEach = true;
+ });
+ describe('nested within a describe/context', function () {
+ it.only('should run all enclosing beforeEach hooks', function () {
+ require('assert').equal(this.didRunBeforeEach, true);
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/misc/only/bdd.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/bdd.spec.js
new file mode 100644
index 0000000000..639ab30e1b
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/bdd.spec.js
@@ -0,0 +1,127 @@
+'use strict';
+
+describe('should only run .only test in this bdd suite', function () {
+ it('should not run this test', function () {
+ (0).should.equal(1, 'this test should have been skipped');
+ });
+ it.only('should run this test', function () {
+ (0).should.equal(0, 'this .only test should run');
+ });
+ it('should run this test, not (includes the title of the .only test)', function () {
+ (0).should.equal(1, 'this test should have been skipped');
+ });
+});
+
+describe('should not run this suite', function () {
+ it('should not run this test', function () {
+ (true).should.equal(false);
+ });
+
+ it('should not run this test', function () {
+ (true).should.equal(false);
+ });
+
+ it('should not run this test', function () {
+ (true).should.equal(false);
+ });
+});
+
+describe.only('should run all tests in this bdd suite', function () {
+ it('should run this test #1', function () {
+ (true).should.equal(true);
+ });
+
+ it('should run this test #2', function () {
+ (1).should.equal(1);
+ });
+
+ it('should run this test #3', function () {
+ ('foo').should.equal('foo');
+ });
+});
+
+describe('should run only suites that marked as `only`', function () {
+ describe.only('should run all this tdd suite', function () {
+ it('should run this test #1', function () {
+ (true).should.equal(true);
+ });
+
+ it('should run this test #2', function () {
+ (true).should.equal(true);
+ });
+ });
+
+ describe('should not run this suite', function () {
+ it('should run this test', function () {
+ (true).should.equal(false);
+ });
+ });
+});
+
+// Nested situation
+describe('should not run parent tests', function () {
+ it('should not run this test', function () {
+ (true).should.equal(false);
+ });
+ describe('and not the child tests too', function () {
+ it('should not run this test', function () {
+ (true).should.equal(false);
+ });
+ describe.only('but run all the tests in this suite', function () {
+ it('should run this test #1', function () {
+ (true).should.equal(true);
+ });
+ it('should run this test #2', function () {
+ (true).should.equal(true);
+ });
+ });
+ });
+});
+
+// mark test as `only` override the suite behavior
+describe.only('should run only tests that marked as `only`', function () {
+ it('should not run this test #1', function () {
+ (false).should.equal(true);
+ });
+
+ it.only('should run this test #2', function () {
+ (true).should.equal(true);
+ });
+
+ it('should not run this test #3', function () {
+ (false).should.equal(true);
+ });
+
+ it.only('should run this test #4', function () {
+ (true).should.equal(true);
+ });
+});
+
+describe.only('Should run only test cases that mark as only', function () {
+ it.only('should runt his test', function () {
+ (true).should.equal(true);
+ });
+
+ it('should not run this test', function () {
+ (false).should.equal(true);
+ });
+
+ describe('should not run this suite', function () {
+ it('should not run this test', function () {
+ (false).should.equal(true);
+ });
+ });
+});
+
+// Root Suite
+it.only('#Root-Suite, should run this test-case #1', function () {
+ (true).should.equal(true);
+});
+
+it.only('#Root-Suite, should run this test-case #2', function () {
+ (true).should.equal(true);
+});
+
+it('#Root-Suite, should not run this test', function () {
+ (false).should.equal(true);
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/bdd.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/bdd.spec.js
new file mode 100644
index 0000000000..1fc3d14384
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/bdd.spec.js
@@ -0,0 +1,14 @@
+'use strict';
+
+// Root-only test cases
+it.only('#Root-Suite, should run this bdd test-case #1', function () {
+ (true).should.equal(true);
+});
+
+it('#Root-Suite, should not run this bdd test-case #2', function () {
+ (false).should.equal(true);
+});
+
+it('#Root-Suite, should not run this bdd test-case #3', function () {
+ (false).should.equal(true);
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/qunit.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/qunit.spec.js
new file mode 100644
index 0000000000..69bbd3467a
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/qunit.spec.js
@@ -0,0 +1,14 @@
+'use strict';
+
+// Root-only test cases
+test.only('#Root-Suite, should run this qunit test-case #1', function () {
+ (true).should.equal(true);
+});
+
+test('#Root-Suite, should not run this qunit test-case #2', function () {
+ (false).should.equal(true);
+});
+
+test('#Root-Suite, should not run this qunit test-case #3', function () {
+ (false).should.equal(true);
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/tdd.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/tdd.spec.js
new file mode 100644
index 0000000000..03fdea768f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/global/tdd.spec.js
@@ -0,0 +1,14 @@
+'use strict';
+
+// Root-only test cases
+test.only('#Root-Suite, should run this tdd test-case #1', function () {
+ (true).should.equal(true);
+});
+
+test('#Root-Suite, should not run this tdd test-case #2', function () {
+ (false).should.equal(true);
+});
+
+test('#Root-Suite, should not run this tdd test-case #3', function () {
+ (false).should.equal(true);
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/misc/only/qunit.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/qunit.spec.js
new file mode 100644
index 0000000000..77bdfcc64f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/qunit.spec.js
@@ -0,0 +1,75 @@
+'use strict';
+
+// Root Suite
+test.only('#Root-Suite, should run this test-case #1', function () {
+ (true).should.equal(true);
+});
+
+test.only('#Root-Suite, should run this test-case #2', function () {
+ (true).should.equal(true);
+});
+
+test('#Root-Suite, should not run this test', function () {
+ (false).should.equal(true);
+});
+
+suite('should only run .only test in this qunit suite');
+
+test('should not run this test', function () {
+ (0).should.equal(1, 'this test should have been skipped');
+});
+test.only('should run this test', function () {
+ (0).should.equal(0, 'this .only test should run');
+});
+test('should run this test, not (includes the title of the .only test)', function () {
+ (0).should.equal(1, 'this test should have been skipped');
+});
+
+// Mark suite
+suite.only('should run all tests in this suite');
+
+test('should run this test #1', function () {
+ (true).should.equal(true);
+});
+
+test('should run this test #2', function () {
+ (true).should.equal(true);
+});
+
+test('should run this test #3', function () {
+ (true).should.equal(true);
+});
+
+// Unmark this suite
+suite('should not run any of this suite\'s tests');
+
+test('should not run this test', function () {
+ (false).should.equal(true);
+});
+
+test('should not run this test', function () {
+ (false).should.equal(true);
+});
+
+test('should not run this test', function () {
+ (false).should.equal(true);
+});
+
+// Mark test as `only` override the suite behavior
+suite.only('should run only tests that marked as `only`');
+
+test('should not run this test #1', function () {
+ (false).should.equal(true);
+});
+
+test.only('should not run this test #2', function () {
+ (true).should.equal(true);
+});
+
+test('should not run this test #3', function () {
+ (false).should.equal(true);
+});
+
+test.only('should not run this test #4', function () {
+ (true).should.equal(true);
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/misc/only/tdd.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/tdd.spec.js
new file mode 100644
index 0000000000..da5f45b198
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/misc/only/tdd.spec.js
@@ -0,0 +1,127 @@
+'use strict';
+
+suite('should only run .only test in this tdd suite', function () {
+ test('should not run this test', function () {
+ (0).should.equal(1, 'this test should have been skipped');
+ });
+ test.only('should run this test', function () {
+ (0).should.equal(0, 'this .only test should run');
+ });
+ test('should run this test, not (includes the title of the .only test)', function () {
+ (0).should.equal(1, 'this test should have been skipped');
+ });
+});
+
+suite('should not run this suite', function () {
+ test('should not run this test', function () {
+ (true).should.equal(false);
+ });
+
+ test('should not run this test', function () {
+ (true).should.equal(false);
+ });
+
+ test('should not run this test', function () {
+ (true).should.equal(false);
+ });
+});
+
+suite.only('should run all tests in this tdd suite', function () {
+ test('should run this test #1', function () {
+ (true).should.equal(true);
+ });
+
+ test('should run this test #2', function () {
+ (1).should.equal(1);
+ });
+
+ test('should run this test #3', function () {
+ ('foo').should.equal('foo');
+ });
+});
+
+suite('should run only suites that marked as `only`', function () {
+ suite.only('should run all this tdd suite', function () {
+ test('should run this test #1', function () {
+ (true).should.equal(true);
+ });
+
+ test('should run this test #2', function () {
+ (true).should.equal(true);
+ });
+ });
+
+ suite('should not run this suite', function () {
+ test('should not run this test', function () {
+ (true).should.equal(false);
+ });
+ });
+});
+
+// Nested situation
+suite('should not run parent tests', function () {
+ test('should not run this test', function () {
+ (true).should.equal(false);
+ });
+ suite('and not the child tests too', function () {
+ test('should not run this test', function () {
+ (true).should.equal(false);
+ });
+ suite.only('but run all the tests in this suite', function () {
+ test('should run this test #1', function () {
+ (true).should.equal(true);
+ });
+ test('should run this test #2', function () {
+ (true).should.equal(true);
+ });
+ });
+ });
+});
+
+// mark test as `only` override the suite behavior
+suite.only('should run only tests that marked as `only`', function () {
+ test('should not run this test #1', function () {
+ (false).should.equal(true);
+ });
+
+ test.only('should run this test #2', function () {
+ (true).should.equal(true);
+ });
+
+ test('should not run this test #3', function () {
+ (false).should.equal(true);
+ });
+
+ test.only('should run this test #4', function () {
+ (true).should.equal(true);
+ });
+});
+
+suite.only('Should run only test cases that mark as only', function () {
+ test.only('should runt his test', function () {
+ (true).should.equal(true);
+ });
+
+ test('should not run this test', function () {
+ (false).should.equal(true);
+ });
+
+ suite('should not run this suite', function () {
+ test('should not run this test', function () {
+ (false).should.equal(true);
+ });
+ });
+});
+
+// Root Suite
+test.only('#Root-Suite, should run this test-case #1', function () {
+ (true).should.equal(true);
+});
+
+test.only('#Root-Suite, should run this test-case #2', function () {
+ (true).should.equal(true);
+});
+
+test('#Root-Suite, should not run this test', function () {
+ (false).should.equal(true);
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/overspecified-async.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/overspecified-async.spec.js
new file mode 100644
index 0000000000..0f9b6c9ff5
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/overspecified-async.spec.js
@@ -0,0 +1,10 @@
+'use strict';
+
+describe('overspecified asynchronous resolution method', function () {
+ it('should fail when multiple methods are used', function (done) {
+ setTimeout(done, 0);
+
+ // uncomment
+ // return { then: function() {} };
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/require/a.js b/tests/lib/mocha-3.1.2/test/acceptance/require/a.js
new file mode 100644
index 0000000000..949b8af2f0
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/require/a.js
@@ -0,0 +1,4 @@
+'use strict';
+
+global.required = (global.required || []);
+global.required.push('a.js');
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/require/b.coffee b/tests/lib/mocha-3.1.2/test/acceptance/require/b.coffee
new file mode 100644
index 0000000000..045cc7591b
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/require/b.coffee
@@ -0,0 +1,2 @@
+global.required ?= []
+global.required.push 'b.coffee'
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/require/c.js b/tests/lib/mocha-3.1.2/test/acceptance/require/c.js
new file mode 100644
index 0000000000..4d68dc4549
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/require/c.js
@@ -0,0 +1,4 @@
+'use strict';
+
+global.required = (global.required || []);
+global.required.push('c.js');
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/require/d.coffee b/tests/lib/mocha-3.1.2/test/acceptance/require/d.coffee
new file mode 100644
index 0000000000..d5ebbf60ed
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/require/d.coffee
@@ -0,0 +1,2 @@
+global.required ?= []
+global.required.push 'd.coffee'
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/require/require.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/require/require.spec.js
new file mode 100644
index 0000000000..f959a859a8
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/require/require.spec.js
@@ -0,0 +1,11 @@
+'use strict';
+
+describe('require test', function () {
+ it('should require args in order', function () {
+ var req = global.required;
+ expect(req.indexOf('a.js')).to.equal(0);
+ expect(req.indexOf('b.coffee')).to.equal(1);
+ expect(req.indexOf('c.js')).to.equal(2);
+ expect(req.indexOf('d.coffee')).to.equal(3);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/required-tokens.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/required-tokens.spec.js
new file mode 100644
index 0000000000..2b44dee59b
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/required-tokens.spec.js
@@ -0,0 +1,12 @@
+'use strict';
+
+var assert = require('assert');
+var describe = require('../..').describe;
+var it = require('../..').it;
+
+describe('using imported describe', function () {
+ it('using imported it', function (done) {
+ assert.ok(true);
+ done();
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/root.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/root.spec.js
new file mode 100644
index 0000000000..abd8d4192e
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/root.spec.js
@@ -0,0 +1,13 @@
+'use strict';
+
+var calls = [];
+
+before(function () {
+ calls.push('before');
+});
+
+describe('root', function () {
+ it('should be a valid suite', function () {
+ expect(calls).to.eql(['before']);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/test.coffee b/tests/lib/mocha-3.1.2/test/acceptance/test.coffee
new file mode 100644
index 0000000000..b8e309f515
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/test.coffee
@@ -0,0 +1,6 @@
+
+obj = foo: 'bar'
+
+describe 'coffeescript', ->
+ it 'should work', ->
+ expect(obj).to.eql foo: 'bar'
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/test.foo b/tests/lib/mocha-3.1.2/test/acceptance/test.foo
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/test.foo
@@ -0,0 +1 @@
+1
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/throw.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/throw.spec.js
new file mode 100644
index 0000000000..68e8cd2c1d
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/throw.spec.js
@@ -0,0 +1,108 @@
+'use strict';
+
+/* eslint no-throw-literal: off */
+
+var Suite = require('../../lib/suite');
+var Test = require('../../lib/test');
+var Runner = require('../../lib/runner');
+
+describe('a test that throws', function () {
+ var suite, runner;
+
+ beforeEach(function () {
+ suite = new Suite('Suite', 'root');
+ runner = new Runner(suite);
+ });
+
+ describe('undefined', function () {
+ it('should not pass if throwing sync and test is sync', function (done) {
+ var test = new Test('im sync and throw undefined sync', function () {
+ throw undefined;
+ });
+ suite.addTest(test);
+ runner = new Runner(suite);
+ runner.on('end', function () {
+ expect(runner.failures).to.equal(1);
+ expect(test.state).to.equal('failed');
+ done();
+ });
+ runner.run();
+ });
+
+ it('should not pass if throwing sync and test is async', function (done) {
+ var test = new Test('im async and throw undefined sync', function (done2) {
+ throw undefined;
+ });
+ suite.addTest(test);
+ runner = new Runner(suite);
+ runner.on('end', function () {
+ expect(runner.failures).to.equal(1);
+ expect(test.state).to.equal('failed');
+ done();
+ });
+ runner.run();
+ });
+
+ it('should not pass if throwing async and test is async', function (done) {
+ var test = new Test('im async and throw undefined async', function (done2) {
+ process.nexTick(function () {
+ throw undefined;
+ });
+ });
+ suite.addTest(test);
+ runner = new Runner(suite);
+ runner.on('end', function () {
+ expect(runner.failures).to.equal(1);
+ expect(test.state).to.equal('failed');
+ done();
+ });
+ runner.run();
+ });
+ });
+
+ describe('null', function () {
+ it('should not pass if throwing sync and test is sync', function (done) {
+ var test = new Test('im sync and throw null sync', function () {
+ throw null;
+ });
+ suite.addTest(test);
+ runner = new Runner(suite);
+ runner.on('end', function () {
+ expect(runner.failures).to.equal(1);
+ expect(test.state).to.equal('failed');
+ done();
+ });
+ runner.run();
+ });
+
+ it('should not pass if throwing sync and test is async', function (done) {
+ var test = new Test('im async and throw null sync', function (done2) {
+ throw null;
+ });
+ suite.addTest(test);
+ runner = new Runner(suite);
+ runner.on('end', function () {
+ expect(runner.failures).to.equal(1);
+ expect(test.state).to.equal('failed');
+ done();
+ });
+ runner.run();
+ });
+
+ it('should not pass if throwing async and test is async', function (done) {
+ var test = new Test('im async and throw null async', function (done2) {
+ process.nexTick(function () {
+ throw null;
+ });
+ });
+ suite.addTest(test);
+ runner = new Runner(suite);
+ runner.on('end', function () {
+ expect(runner.failures).to.equal(1);
+ expect(test.state).to.equal('failed');
+ done();
+ });
+ runner.run();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/timeout.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/timeout.spec.js
new file mode 100644
index 0000000000..b3fc632a0d
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/timeout.spec.js
@@ -0,0 +1,79 @@
+'use strict';
+
+describe('timeouts', function () {
+ beforeEach(function (done) {
+ // uncomment
+ // setTimeout(done, 3000);
+ done();
+ });
+
+ it('should error on timeout', function (done) {
+ // uncomment
+ // setTimeout(done, 3000);
+ done();
+ });
+
+ it('should allow overriding per-test', function (done) {
+ this.timeout(1000);
+ setTimeout(function () {
+ done();
+ }, 300);
+ });
+
+ describe('disabling', function () {
+ it('should allow overriding per-test', function (done) {
+ this.enableTimeouts(false);
+ this.timeout(1);
+ setTimeout(done, 2);
+ });
+
+ it('should work with timeout(0)', function (done) {
+ this.timeout(0);
+ setTimeout(done, 1);
+ });
+
+ describe('using beforeEach', function () {
+ beforeEach(function () {
+ this.timeout(0);
+ });
+
+ it('should work with timeout(0)', function (done) {
+ setTimeout(done, 1);
+ });
+ });
+
+ describe('using before', function () {
+ before(function () {
+ this.timeout(0);
+ });
+
+ it('should work with timeout(0)', function (done) {
+ setTimeout(done, 1);
+ });
+ });
+
+ describe('using enableTimeouts(false)', function () {
+ this.timeout(4);
+
+ it('should suppress timeout(4)', function (done) {
+ // The test is in the before() call.
+ this.enableTimeouts(false);
+ setTimeout(done, 50);
+ });
+ });
+
+ describe('suite-level', function () {
+ this.timeout(0);
+
+ it('should work with timeout(0)', function (done) {
+ setTimeout(done, 1);
+ });
+
+ describe('nested suite', function () {
+ it('should work with timeout(0)', function (done) {
+ setTimeout(done, 1);
+ });
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/acceptance/utils.spec.js b/tests/lib/mocha-3.1.2/test/acceptance/utils.spec.js
new file mode 100644
index 0000000000..545bdfd265
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/acceptance/utils.spec.js
@@ -0,0 +1,418 @@
+'use strict';
+
+var utils = require('../../lib/utils');
+var toISOString = require('../../lib/to-iso-string');
+var JSON = require('json3');
+
+describe('lib/utils', function () {
+ describe('clean', function () {
+ it('should format a single line test function', function () {
+ var fn = [
+ 'function () {',
+ ' var a = 1;',
+ '}'
+ ].join('\n');
+ expect(utils.clean(fn)).to.equal('var a = 1;');
+ });
+
+ it('should format a multi line test indented with spaces', function () {
+ // and no new lines after curly braces, shouldn't matter
+ var fn = [
+ 'function(){ var a = 1;',
+ // this one has more spaces
+ ' var b = 2;',
+ ' var c = 3; }'
+ ].join('\n');
+ expect(utils.clean(fn)).to.equal('var a = 1;\n var b = 2;\nvar c = 3;');
+ });
+
+ it('should format a multi line test indented with tabs', function () {
+ var fn = [
+ 'function (arg1, arg2) {',
+ '\tif (true) {',
+ '\t\tvar a = 1;',
+ '\t}',
+ '}'
+ ].join('\n');
+ expect(utils.clean(fn)).to.equal('if (true) {\n\tvar a = 1;\n}');
+ });
+
+ it('should format functions saved in windows style - spaces', function () {
+ var fn = [
+ 'function (one) {',
+ ' do {',
+ ' "nothing";',
+ ' } while (false);',
+ ' }'
+ ].join('\r\n');
+ expect(utils.clean(fn)).to.equal('do {\n "nothing";\n} while (false);');
+ });
+
+ it('should format functions saved in windows style - tabs', function () {
+ var fn = [
+ 'function ( ) {',
+ '\tif (false) {',
+ '\t\tvar json = {',
+ '\t\t\tone : 1',
+ '\t\t};',
+ '\t}',
+ '}'
+ ].join('\r\n');
+ expect(utils.clean(fn)).to.equal('if (false) {\n\tvar json = {\n\t\tone : 1\n\t};\n}');
+ });
+
+ it('should format es6 arrow functions', function () {
+ var fn = [
+ '() => {',
+ ' var a = 1;',
+ '}'
+ ].join('\n');
+ expect(utils.clean(fn)).to.equal('var a = 1;');
+ });
+
+ it('should format es6 arrow functions with implicit return', function () {
+ var fn = '() => foo()';
+ expect(utils.clean(fn)).to.equal('foo()');
+ });
+ });
+
+ describe('stringify', function () {
+ var stringify = utils.stringify;
+
+ it('should return an object representation of a string created with a String constructor', function () {
+ /* eslint no-new-wrappers: off */
+ expect(stringify(new String('foo'))).to.equal('{\n "0": "f"\n "1": "o"\n "2": "o"\n}');
+ });
+
+ it('should return Buffer with .toJSON representation', function () {
+ expect(stringify(new Buffer([0x01]))).to.equal('[\n 1\n]');
+ expect(stringify(new Buffer([0x01, 0x02]))).to.equal('[\n 1\n 2\n]');
+
+ expect(stringify(new Buffer('ABCD'))).to.equal('[\n 65\n 66\n 67\n 68\n]');
+ });
+
+ it('should return Date object with .toISOString() + string prefix', function () {
+ expect(stringify(new Date(0))).to.equal('[Date: ' + shimToISOString(new Date(0)) + ']');
+
+ var date = new Date(); // now
+ expect(stringify(date)).to.equal('[Date: ' + shimToISOString(date) + ']');
+
+ function shimToISOString (date) {
+ if (date.toISOString) {
+ return date.toISOString();
+ } else {
+ return toISOString(date);
+ }
+ }
+ });
+
+ it('should return invalid Date object with .toString() + string prefix', function () {
+ expect(stringify(new Date(''))).to.equal('[Date: ' + new Date('').toString() + ']');
+ });
+
+ describe('#Number', function () {
+ it('should show the handle -0 situations', function () {
+ expect(stringify(-0)).to.eql('-0');
+ expect(stringify(0)).to.eql('0');
+ expect(stringify('-0')).to.eql('"-0"');
+ });
+
+ it('should work well with `NaN` and `Infinity`', function () {
+ expect(stringify(NaN)).to.equal('NaN');
+ expect(stringify(Infinity)).to.equal('Infinity');
+ expect(stringify(-Infinity)).to.equal('-Infinity');
+ });
+
+ it('floats and ints', function () {
+ expect(stringify(1)).to.equal('1');
+ expect(stringify(1.2)).to.equal('1.2');
+ expect(stringify(1e9)).to.equal('1000000000');
+ });
+ });
+
+ describe('canonicalize example', function () {
+ it('should represent the actual full result', function () {
+ var expected = {
+ str: 'string',
+ int: 90,
+ float: 9.99,
+ boolean: false,
+ nil: null,
+ undef: undefined,
+ regex: /^[a-z|A-Z]/,
+ date: new Date(0),
+ func: function () {},
+ infi: Infinity,
+ nan: NaN,
+ zero: -0,
+ buffer: new Buffer([0x01, 0x02]),
+ array: [1, 2, 3],
+ empArr: [],
+ matrix: [[1],
+ [
+ 2,
+ 3,
+ 4
+ ]
+ ],
+ object: { a: 1, b: 2 },
+ canObj: { a: { b: 1, c: 2 }, b: {} },
+ empObj: {}
+ };
+ expected.circular = expected; // Make `Circular` situation
+ var actual = [
+ '{',
+ ' "array": [',
+ ' 1',
+ ' 2',
+ ' 3',
+ ' ]',
+ ' "boolean": false',
+ ' "buffer": [Buffer: [',
+ ' 1',
+ ' 2',
+ ' ]]',
+ ' "canObj": {',
+ ' "a": {',
+ ' "b": 1',
+ ' "c": 2',
+ ' }',
+ ' "b": {}',
+ ' }',
+ ' "circular": [Circular]',
+ ' "date": [Date: 1970-01-01T00:00:00.000Z]',
+ ' "empArr": []',
+ ' "empObj": {}',
+ ' "float": 9.99',
+ ' "func": [Function]',
+ ' "infi": Infinity',
+ ' "int": 90',
+ ' "matrix": [',
+ ' [',
+ ' 1',
+ ' ]',
+ ' [',
+ ' 2',
+ ' 3',
+ ' 4',
+ ' ]',
+ ' ]',
+ ' "nan": NaN',
+ ' "nil": [null]',
+ ' "object": {',
+ ' "a": 1',
+ ' "b": 2',
+ ' }',
+ ' "regex": /^[a-z|A-Z]/',
+ ' "str": "string"',
+ ' "undef": [undefined]',
+ ' "zero": -0',
+ '}'
+ ].join('\n');
+ expect(stringify(expected)).to.equal(actual);
+ });
+ });
+
+ it('should canonicalize the object', function () {
+ var travis = { name: 'travis', age: 24 };
+ var travis2 = { age: 24, name: 'travis' };
+
+ expect(stringify(travis)).to.equal(stringify(travis2));
+ });
+
+ it('should handle circular structures in objects', function () {
+ var travis = { name: 'travis' };
+ travis.whoami = travis;
+
+ expect(stringify(travis)).to.equal('{\n "name": "travis"\n "whoami": [Circular]\n}');
+ });
+
+ it('should handle circular structures in arrays', function () {
+ var travis = ['travis'];
+ travis.push(travis);
+
+ expect(stringify(travis)).to.equal('[\n "travis"\n [Circular]\n]');
+ });
+
+ it('should handle circular structures in functions', function () {
+ var travis = function () {};
+ travis.fn = travis;
+
+ expect(stringify(travis)).to.equal('{\n "fn": [Circular]\n}');
+ });
+
+ it('should handle various non-undefined, non-null, non-object, non-array, non-date, and non-function values', function () {
+ var regexp = new RegExp('(?:)');
+ var regExpObj = {regexp: regexp};
+ var regexpString = '/(?:)/';
+
+ expect(stringify(regExpObj)).to.equal('{\n "regexp": ' + regexpString + '\n}');
+ expect(stringify(regexp)).to.equal(regexpString);
+
+ var number = 1;
+ var numberObj = {number: number};
+ var numberString = '1';
+
+ expect(stringify(numberObj)).to.equal('{\n "number": ' + number + '\n}');
+ expect(stringify(number)).to.equal(numberString);
+
+ var boolean = false;
+ var booleanObj = {boolean: boolean};
+ var booleanString = 'false';
+
+ expect(stringify(booleanObj)).to.equal('{\n "boolean": ' + boolean + '\n}');
+ expect(stringify(boolean)).to.equal(booleanString);
+
+ var string = 'sneepy';
+ var stringObj = {string: string};
+
+ expect(stringify(stringObj)).to.equal('{\n "string": "' + string + '"\n}');
+ expect(stringify(string)).to.equal(JSON.stringify(string));
+
+ var nullValue = null;
+ var nullObj = {'null': null};
+ var nullString = '[null]';
+
+ expect(stringify(nullObj)).to.equal('{\n "null": [null]\n}');
+ expect(stringify(nullValue)).to.equal(nullString);
+ });
+
+ it('should handle arrays', function () {
+ var array = ['dave', 'dave', 'dave', 'dave'];
+ var arrayObj = {array: array};
+ var arrayString = ' "dave"\n "dave"\n "dave"\n "dave"';
+
+ expect(stringify(arrayObj)).to.equal('{\n "array": [\n' + arrayString + '\n ]\n}');
+ expect(stringify(array)).to.equal('[' + arrayString.replace(/\s+/g, '\n ') + '\n]');
+ });
+
+ it('should handle functions', function () {
+ var fn = function () {};
+ var fnObj = {fn: fn};
+ var fnString = '[Function]';
+
+ expect(stringify(fnObj)).to.equal('{\n "fn": ' + fnString + '\n}');
+ expect(stringify(fn)).to.equal('[Function]');
+ });
+
+ it('should handle empty objects', function () {
+ expect(stringify({})).to.equal('{}');
+ expect(stringify({foo: {}})).to.equal('{\n "foo": {}\n}');
+ });
+
+ it('should handle empty arrays', function () {
+ expect(stringify([])).to.equal('[]');
+ expect(stringify({foo: []})).to.equal('{\n "foo": []\n}');
+ });
+
+ it('should handle non-empty arrays', function () {
+ expect(stringify(['a', 'b', 'c'])).to.equal('[\n "a"\n "b"\n "c"\n]');
+ });
+
+ it('should handle empty functions (with no properties)', function () {
+ expect(stringify(function () {})).to.equal('[Function]');
+ expect(stringify({foo: function () {}})).to.equal('{\n "foo": [Function]\n}');
+ expect(stringify({foo: function () {}, bar: 'baz'})).to.equal('{\n "bar": "baz"\n "foo": [Function]\n}');
+ });
+
+ it('should handle functions w/ properties', function () {
+ var fn = function () {};
+ fn.bar = 'baz';
+ expect(stringify(fn)).to.equal('{\n "bar": "baz"\n}');
+ expect(stringify({foo: fn})).to.equal('{\n "foo": {\n "bar": "baz"\n }\n}');
+ });
+
+ it('should handle undefined values', function () {
+ expect(stringify({foo: undefined})).to.equal('{\n "foo": [undefined]\n}');
+ expect(stringify({foo: 'bar', baz: undefined})).to.equal('{\n "baz": [undefined]\n "foo": "bar"\n}');
+ expect(stringify()).to.equal('[undefined]');
+ });
+
+ it('should recurse', function () {
+ expect(stringify({foo: {bar: {baz: {quux: {herp: 'derp'}}}}})).to.equal('{\n "foo": {\n "bar": {\n "baz": {\n "quux": {\n "herp": "derp"\n }\n }\n }\n }\n}');
+ });
+
+ it('might get confusing', function () {
+ expect(stringify(null)).to.equal('[null]');
+ });
+
+ it('should not freak out if it sees a primitive twice', function () {
+ expect(stringify({foo: null, bar: null})).to.equal('{\n "bar": [null]\n "foo": [null]\n}');
+ expect(stringify({foo: 1, bar: 1})).to.equal('{\n "bar": 1\n "foo": 1\n}');
+ });
+
+ it('should stringify dates', function () {
+ var date = new Date(0);
+ expect(stringify(date)).to.equal('[Date: 1970-01-01T00:00:00.000Z]');
+ expect(stringify({date: date})).to.equal('{\n "date": [Date: 1970-01-01T00:00:00.000Z]\n}');
+ });
+
+ it('should handle object without an Object prototype', function () {
+ var a;
+ if (Object.create) {
+ a = Object.create(null);
+ } else {
+ a = {};
+ }
+ a.foo = 1;
+
+ expect(stringify(a)).to.equal('{\n "foo": 1\n}');
+ });
+
+ // In old version node.js, Symbol is not available by default.
+ if (typeof global.Symbol === 'function') {
+ it('should handle Symbol', function () {
+ var symbol = Symbol('value');
+ expect(stringify(symbol)).to.equal('Symbol(value)');
+ expect(stringify({symbol: symbol})).to.equal('{\n "symbol": Symbol(value)\n}');
+ });
+ }
+
+ it('should handle length properties that cannot be coerced to a number', function () {
+ expect(stringify({length: {nonBuiltinProperty: 0}})).to.equal('{\n "length": {\n "nonBuiltinProperty": 0\n }\n}');
+ expect(stringify({length: 'a string where length should be'})).to.equal('{\n "length": "a string where length should be"\n}');
+ });
+ });
+
+ describe('type', function () {
+ /* eslint no-extend-native: off */
+
+ var type = utils.type;
+ var toString = Object.prototype.toString;
+
+ beforeEach(function () {
+ // some JS engines such as PhantomJS 1.x exhibit this behavior
+ Object.prototype.toString = function () {
+ if (this === global) {
+ return '[object DOMWindow]';
+ }
+ return toString.call(this);
+ };
+ });
+
+ it('should recognize various types', function () {
+ expect(type({})).to.equal('object');
+ expect(type([])).to.equal('array');
+ expect(type(1)).to.equal('number');
+ expect(type(Infinity)).to.equal('number');
+ expect(type(null)).to.equal('null');
+ expect(type(undefined)).to.equal('undefined');
+ expect(type(new Date())).to.equal('date');
+ expect(type(/foo/)).to.equal('regexp');
+ expect(type('type')).to.equal('string');
+ expect(type(global)).to.equal('domwindow');
+ expect(type(true)).to.equal('boolean');
+ });
+
+ describe('when toString on null or undefined stringifies window', function () {
+ it('should recognize null and undefined', function () {
+ expect(type(null)).to.equal('null');
+ expect(type(undefined)).to.equal('undefined');
+ });
+ });
+
+ afterEach(function () {
+ Object.prototype.toString = toString;
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/browser-fixtures/bdd.fixture.js b/tests/lib/mocha-3.1.2/test/browser-fixtures/bdd.fixture.js
new file mode 100644
index 0000000000..d19993676a
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser-fixtures/bdd.fixture.js
@@ -0,0 +1,6 @@
+'use strict';
+
+/* eslint-env browser */
+
+window.mocha.timeout(200)
+ .ui('bdd');
diff --git a/tests/lib/mocha-3.1.2/test/browser-fixtures/exports.fixture.js b/tests/lib/mocha-3.1.2/test/browser-fixtures/exports.fixture.js
new file mode 100644
index 0000000000..97b8b97cbe
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser-fixtures/exports.fixture.js
@@ -0,0 +1,6 @@
+'use strict';
+
+/* eslint-env browser */
+
+window.mocha.timeout(200)
+ .ui('exports');
diff --git a/tests/lib/mocha-3.1.2/test/browser-fixtures/qunit.fixture.js b/tests/lib/mocha-3.1.2/test/browser-fixtures/qunit.fixture.js
new file mode 100644
index 0000000000..a3fd887940
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser-fixtures/qunit.fixture.js
@@ -0,0 +1,6 @@
+'use strict';
+
+/* eslint-env browser */
+
+window.mocha.timeout(200)
+ .ui('qunit');
diff --git a/tests/lib/mocha-3.1.2/test/browser-fixtures/tdd.fixture.js b/tests/lib/mocha-3.1.2/test/browser-fixtures/tdd.fixture.js
new file mode 100644
index 0000000000..0c36f0c54b
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser-fixtures/tdd.fixture.js
@@ -0,0 +1,6 @@
+'use strict';
+
+/* eslint-env browser */
+
+window.mocha.timeout(200)
+ .ui('tdd');
diff --git a/tests/lib/mocha-3.1.2/test/browser/array.spec.js b/tests/lib/mocha-3.1.2/test/browser/array.spec.js
new file mode 100644
index 0000000000..edf66ac458
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/array.spec.js
@@ -0,0 +1,39 @@
+'use strict';
+
+describe('Array', function () {
+ describe('#push()', function () {
+ it('should append a value', function () {
+ var arr = [];
+ arr.push('foo');
+ arr.push('bar');
+ arr.push('baz');
+ assert(arr[0] === 'foo'); // to test indentation
+ assert(arr[1] === 'bar');
+ assert(arr[2] === 'baz');
+ });
+
+ it('should return the length', function () {
+ var arr = [];
+ assert(arr.push('foo') === 1);
+ assert(arr.push('bar') === 2);
+ assert(arr.push('baz') === 3);
+ });
+ });
+});
+
+describe('Array', function () {
+ describe('#pop()', function () {
+ it('should remove and return the last value', function () {
+ var arr = [1, 2, 3];
+ assert(arr.pop() === 3);
+ assert(arr.pop() === 2);
+ assert(arr.pop() === -1);
+ });
+
+ it('should adjust .length', function () {
+ var arr = [1, 2, 3];
+ arr.pop();
+ assert(arr.length === 2);
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/browser/grep.html b/tests/lib/mocha-3.1.2/test/browser/grep.html
new file mode 100644
index 0000000000..0ba47c8533
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/grep.html
@@ -0,0 +1,51 @@
+<html>
+ <head>
+ <title>Mocha</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" href="../../mocha.css" />
+ <script src="../../mocha.js"></script>
+ <script>mocha.setup('bdd')</script>
+ <script>
+ function assert(expr, msg) {
+ if (!expr) throw new Error(msg || 'failed');
+ }
+ </script>
+ <script src="grep.js"></script>
+ </head>
+ <body>
+ <div id="mocha"></div>
+ <script>
+ (function(window) {
+ var location = window.location;
+ mocha.checkLeaks();
+ var runner = mocha.run();
+ setTimeout(run, 1000);
+
+ function run() {
+ var regex = [
+ '.*', // All
+ 'm{2}', // 'mm...m'
+ '\\d', // Contains number
+ '^\\d{2}(?=\\s\\d$)', // Start with 2 numbers and end with one
+ '^@.*(?=\\(\\)$)', // Run @Array and @Function suite, but only function
+ '^@(?!.*\\)$)', // Run @Array and @Function suite, but only properties
+ '^co', // Start with 'co'
+ 'first$', // Ends with 'first'
+ '^co.*(?=second$)', // Starts with 'co', ends with 'second'
+ '^Date:\\s01\/0(?:[1-4])\/2015$', // Run all tests between '01/[01-04]/2015'
+ encodeURIComponent('^#'), // Run encoded => start with '#'
+ encodeURIComponent('^[^a-z|0-9]+$') // Run encoded => only uppercase suites(include `it` fns), e.g: CONSTANTS
+ ]
+ , qs = location.search.replace('?grep=', '')
+ , re = ~qs.indexOf('%') ? qs : decodeURIComponent(qs)
+ , grep = regex[regex.indexOf(re) + 1];
+
+ return grep
+ ? location.search = 'grep=' + grep
+ : false;
+ }
+ })(window);
+ </script>
+ </body>
+</html>
diff --git a/tests/lib/mocha-3.1.2/test/browser/grep.spec.js b/tests/lib/mocha-3.1.2/test/browser/grep.spec.js
new file mode 100644
index 0000000000..6c5a83aeb5
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/grep.spec.js
@@ -0,0 +1,110 @@
+'use strict';
+
+// numbers
+describe('21', function () {
+ it('1', function () {
+ assert(true);
+ });
+ it('2', function () {
+ assert(true);
+ });
+});
+// symbols
+describe('@Array', function () {
+ it('.pop()', function () {
+ assert(true);
+ });
+ it('.push()', function () {
+ assert(true);
+ });
+ it('.length', function () {
+ assert(true);
+ });
+});
+
+describe('@Function', function () {
+ it('.call()', function () {
+ assert(true);
+ });
+ it('.apply()', function () {
+ assert(true);
+ });
+ it('.length', function () {
+ assert(true);
+ });
+ it('.name', function () {
+ assert(true);
+ });
+ it('.prototype', function () {
+ assert(true);
+ });
+});
+
+// url with hashtags
+describe('#Services', function () {
+ describe('#http', function () {
+ it('.createClient()', function () {
+ assert(true);
+ });
+ it('.Server()', function () {
+ assert(true);
+ });
+ });
+ describe('#crypto', function () {
+ it('.randomBytes()', function () {
+ assert(true);
+ });
+ it('.Hmac()', function () {
+ assert(true);
+ });
+ });
+});
+
+// Uppercase
+describe('CONSTANTS', function () {
+ it('.STATUS_CODES', function () {
+ assert(true);
+ });
+});
+
+// Dates
+describe('Date:', function () {
+ it('01/02/2015', function () {
+ assert(true);
+ });
+ it('01/03/2015', function () {
+ assert(true);
+ });
+ it('01/06/2015', function () {
+ assert(true);
+ });
+});
+
+// etc..
+describe('booking/summary', function () {
+ it('should be run last', function () {
+ assert(true);
+ });
+});
+
+describe('component/booking/summary', function () {
+ it('should be run second', function () {
+ assert(true);
+ });
+});
+
+describe('component/booking/intro', function () {
+ it('should be run first', function () {
+ assert(true);
+ });
+});
+
+describe('contains numbers', function () {
+ it('should run if the number 92 matching', function () {
+ assert(true);
+ });
+
+ it('should run if the number 8 matching', function () {
+ assert(true);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/browser/index.html b/tests/lib/mocha-3.1.2/test/browser/index.html
new file mode 100644
index 0000000000..9200b977e5
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/index.html
@@ -0,0 +1,33 @@
+<html>
+ <head>
+ <title>Mocha</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" href="../../mocha.css" />
+ <script src="../../mocha.js"></script>
+ <script>mocha.setup('bdd')</script>
+ <script>
+ function assert(expr, msg) {
+ if (!expr) throw new Error(msg || 'failed');
+ }
+ </script>
+ <script src="array.js"></script>
+ <script src="../acceptance/duration.js"></script>
+ <script src="../acceptance/timeout.js"></script>
+ <script src="multiple-done.js"></script>
+ <script>
+ onload = function(){
+ mocha.checkLeaks();
+ mocha.globals(['foo']);
+ var runner = mocha.run();
+
+ // runner.on('test end', function(test){
+ // console.log(test.fullTitle());
+ // });
+ };
+ </script>
+ </head>
+ <body>
+ <div id="mocha"></div>
+ </body>
+</html>
diff --git a/tests/lib/mocha-3.1.2/test/browser/large.html b/tests/lib/mocha-3.1.2/test/browser/large.html
new file mode 100644
index 0000000000..1804b3a000
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/large.html
@@ -0,0 +1,24 @@
+<html>
+ <head>
+ <title>Mocha</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" href="../../mocha.css" />
+ <script src="../../mocha.js"></script>
+ <script>mocha.setup('bdd')</script>
+ <script>
+ function assert(expr, msg) {
+ if (!expr) throw new Error(msg || 'failed');
+ }
+ </script>
+ <script src="large.js"></script>
+ <script>
+ onload = function(){
+ mocha.run();
+ };
+ </script>
+ </head>
+ <body>
+ <div id="mocha"></div>
+ </body>
+</html>
diff --git a/tests/lib/mocha-3.1.2/test/browser/large.spec.js b/tests/lib/mocha-3.1.2/test/browser/large.spec.js
new file mode 100644
index 0000000000..7dfa62f2a2
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/large.spec.js
@@ -0,0 +1,49 @@
+'use strict';
+
+var n = 30;
+while (n--) {
+ describe('Array ' + n, function () {
+ var arr;
+
+ beforeEach(function () {
+ arr = [1, 2, 3];
+ });
+
+ describe('#indexOf()', function () {
+ it('should return -1 when the value is not present', function () {
+ assert(arr.indexOf(5) === -1);
+ });
+
+ it('should return the correct index when the value is present', function (done) {
+ assert(arr.indexOf(1) === 0);
+ assert(arr.indexOf(2) === 1);
+ done();
+ });
+ });
+ });
+}
+
+describe('something', function () {
+ it('should provide a useful error', function (done) {
+ setTimeout(function () {
+ throw new Error('boom');
+ }, 1);
+ });
+
+ it('should provide an even better error on phantomjs', function (done) {
+ setTimeout(function () {
+ var AssertionError = function (message, actual, expected) {
+ this.message = message;
+ this.actual = actual;
+ this.expected = expected;
+ this.showDiff = true;
+ };
+ AssertionError.prototype = Object.create(Error.prototype);
+ AssertionError.prototype.name = 'AssertionError';
+ AssertionError.prototype.constructor = AssertionError;
+
+ mocha.throwError(new AssertionError('kabooom', 'text with a typo', 'text without a typo'));
+ done();
+ }, 1);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/browser/multiple-done.spec.js b/tests/lib/mocha-3.1.2/test/browser/multiple-done.spec.js
new file mode 100644
index 0000000000..ddb536735e
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/multiple-done.spec.js
@@ -0,0 +1,18 @@
+'use strict';
+
+describe('Multiple Done calls', function () {
+ it('should report an error if done was called more than once', function (done) {
+ done();
+ done();
+ });
+
+ it('should report an error if an exception happened async after done was called', function (done) {
+ done();
+ setTimeout(done, 50);
+ });
+
+ it('should report an error if an exception happened after done was called', function (done) {
+ done();
+ throw new Error('thrown error');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/browser/opts.html b/tests/lib/mocha-3.1.2/test/browser/opts.html
new file mode 100644
index 0000000000..ec49a418fc
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/opts.html
@@ -0,0 +1,30 @@
+<html>
+ <head>
+ <title>Mocha</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" href="../../mocha.css" />
+ <script src="../../mocha.js"></script>
+ <script>
+ mocha.setup({
+ ui: 'bdd',
+ globals: ['okGlobalA', 'okGlobalB', 'okGlobalC', 'callback*']
+ }).timeout(1500)
+ </script>
+ <script>
+ function assert(expr, msg) {
+ if (!expr) throw new Error(msg || 'failed');
+ }
+ </script>
+ <script src="opts.js"></script>
+ <script src="../acceptance/globals.js"></script>
+ <script>
+ onload = function(){
+ var runner = mocha.run();
+ };
+ </script>
+ </head>
+ <body>
+ <div id="mocha"></div>
+ </body>
+</html>
diff --git a/tests/lib/mocha-3.1.2/test/browser/opts.spec.js b/tests/lib/mocha-3.1.2/test/browser/opts.spec.js
new file mode 100644
index 0000000000..7b93f22615
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/opts.spec.js
@@ -0,0 +1,7 @@
+'use strict';
+
+describe('Options', function () {
+ it('should set timeout value', function () {
+ assert(this.test._timeout === 1500);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/browser/stack-trace.html b/tests/lib/mocha-3.1.2/test/browser/stack-trace.html
new file mode 100644
index 0000000000..0f267dab98
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/stack-trace.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+ <title>Mocha</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" href="../../mocha.css" />
+ <script src="../../mocha.js"></script>
+ <script>mocha.setup('bdd')</script>
+ <script>
+ function assert(expr, err) {
+ if (!expr) throw err;
+ }
+ </script>
+ <script src="stack-trace.js"></script>
+ <script>
+ onload = function() {
+ mocha.run();
+ };
+ </script>
+</head>
+<body>
+<div id="mocha"></div>
+</body>
+</html>
diff --git a/tests/lib/mocha-3.1.2/test/browser/stack-trace.spec.js b/tests/lib/mocha-3.1.2/test/browser/stack-trace.spec.js
new file mode 100644
index 0000000000..a4801bf32f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/stack-trace.spec.js
@@ -0,0 +1,22 @@
+'use strict';
+describe('Stack trace', function () {
+ it('should prettify the stack-trace', function () {
+ var err = new Error();
+ // We do this fake stack-trace because we under development,
+ // and our root isn't `node_modules`, `bower` or `components`
+ err.stack = [
+ 'Error: failed',
+ 'at assert (stack-trace.html:11:30)',
+ 'at Context.<anonymous> (stack-trace.js:5:5)',
+ 'at callFn (http://localhost:63342/node_modules/mocha.js:4546:21)',
+ 'at Test.require.register.Runnable.run (http://localhost:63342/node_modules/mocha.js:4539:7)',
+ 'at Runner.require.register.Runner.runTest (http://localhost:63342/node_modules/mocha.js:4958:10)',
+ 'at http://localhost:63342/bower_components/mocha.js:5041:12',
+ 'at next (http://localhost:63342/bower_components/mocha.js:4883:14)',
+ 'at http://localhost:63342/bower_components/mocha.js:4893:7',
+ 'at next (http://localhost:63342/bower_components/mocha.js:4828:23)',
+ 'at http://localhost:63342/bower_components/mocha.js:4860:5'
+ ].join('\n');
+ assert(false, err);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/browser/ui.html b/tests/lib/mocha-3.1.2/test/browser/ui.html
new file mode 100644
index 0000000000..071c7798a0
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/ui.html
@@ -0,0 +1,46 @@
+<html>
+ <head>
+ <title>Mocha</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" href="../../mocha.css" />
+ <script src="../../mocha.js"></script>
+ <script>mocha.setup('bdd')</script>
+ <script>
+ function assert(expr, msg) {
+ if (!expr) throw new Error(msg || 'failed');
+ }
+ </script>
+ <script src="ui.js"></script>
+ </head>
+ <body>
+ <div id="mocha"></div>
+ <script>
+ (function(window) {
+ var location = window.location;
+ mocha.checkLeaks();
+ var runner = mocha.run();
+ var count = 0;
+ setTimeout(run, 1000);
+
+ function run() {
+ var regex = [
+ '', // All
+ '%5C%24%5C.jQuery', // $.jQuery
+ '%5C%24%5C.jQuery%20%5C.on%5C(%5C)', // $.jQuery .on()
+ ]
+ , qs = location.search.replace('?grep=', '')
+ , re = ~qs.indexOf('%') ? qs : decodeURIComponent(qs)
+ , grep = regex[regex.indexOf(re) + 1]
+ , anchors = document.getElementsByTagName('a');
+
+ // Locate first 'a' element w/ matching grep param; click it
+ for (var i = 0; i < anchors.length; i++) {
+ if (anchors[i].href && anchors[i].href.indexOf(grep) > -1)
+ return void anchors[i].click();
+ }
+ }
+ })(window);
+ </script>
+ </body>
+</html>
diff --git a/tests/lib/mocha-3.1.2/test/browser/ui.spec.js b/tests/lib/mocha-3.1.2/test/browser/ui.spec.js
new file mode 100644
index 0000000000..159cab6d95
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/browser/ui.spec.js
@@ -0,0 +1,33 @@
+'use strict';
+
+// test titles containing regex-conflicting characters
+
+// leading $
+describe('$.jQuery', function () {
+ // parens
+ describe('.on()', function () {
+ it('should set an event', function () {
+ assert(true);
+ });
+ });
+
+ describe('.off()', function () {
+ it('should remove an event', function () {
+
+ });
+ });
+});
+
+// another generic describe block to verify it is absent
+// when greeping on $.jQuery
+describe('@Array', function () {
+ it('.pop()', function () {
+ assert(true);
+ });
+ it('.push()', function () {
+ assert(true);
+ });
+ it('.length', function () {
+ assert(true);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/color.spec.js b/tests/lib/mocha-3.1.2/test/color.spec.js
new file mode 100644
index 0000000000..bffd30e6eb
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/color.spec.js
@@ -0,0 +1,20 @@
+'use strict';
+
+var assert = require('assert');
+var childProcess = require('child_process');
+var path = require('path');
+
+describe('Mocha', function () {
+ this.timeout(2000);
+
+ it('should not output colors to pipe', function (cb) {
+ var command = [path.join('bin', 'mocha'), '--grep', 'missing-test'];
+ childProcess.execFile(process.execPath, command, function (err, stdout, stderr) {
+ if (err) return cb(err);
+
+ assert(stdout.indexOf('[90m') === -1);
+
+ cb(null);
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/compiler/foo.js b/tests/lib/mocha-3.1.2/test/compiler/foo.js
new file mode 100644
index 0000000000..753d08e740
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/compiler/foo.js
@@ -0,0 +1,10 @@
+'use strict';
+
+var fs = require('fs');
+require.extensions['.foo'] = function (module, filename) {
+ var content;
+ content = fs.readFileSync(filename, 'utf8');
+ var test = 'describe("custom compiler",function(){ it("should work",function() { ' +
+ content + '.should.eql(1); }); });';
+ return module._compile(test, filename);
+};
diff --git a/tests/lib/mocha-3.1.2/test/grep.spec.js b/tests/lib/mocha-3.1.2/test/grep.spec.js
new file mode 100644
index 0000000000..dd21cf0090
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/grep.spec.js
@@ -0,0 +1,67 @@
+'use strict';
+
+var Mocha = require('../');
+
+describe('Mocha', function () {
+ describe('"grep" option', function () {
+ it('should add a RegExp to the mocha.options object', function () {
+ var mocha = new Mocha({ grep: /foo.*/ });
+ mocha.options.grep.toString().should.equal('/foo.*/');
+ });
+
+ it('should convert string to a RegExp', function () {
+ var mocha = new Mocha({ grep: 'foo.*' });
+ mocha.options.grep.toString().should.equal('/foo.*/');
+ });
+ });
+
+ describe('"fgrep" option', function () {
+ it('should escape and convert string to a RegExp', function () {
+ var mocha = new Mocha({ fgrep: 'foo.*' });
+ mocha.options.grep.toString().should.equal('/foo\\.\\*/');
+ });
+ });
+
+ describe('.grep()', function () {
+ // Test helper
+ function testGrep (mocha) {
+ return function testGrep (grep, expected) {
+ mocha.grep(grep);
+ mocha.options.grep.toString().should.equal(expected);
+ };
+ }
+
+ it('should add a RegExp to the mocha.options object', function () {
+ var test = testGrep(new Mocha());
+ test(/foo/, '/foo/');
+ });
+
+ it('should convert grep string to a RegExp', function () {
+ var test = testGrep(new Mocha());
+ test('foo', '/foo/');
+ test('^foo.*bar$', '/^foo.*bar$/');
+ test('^@.*(?=\\(\\)$)', '/^@.*(?=\\(\\)$)/');
+ });
+
+ it('should covert grep regex-like string to a RegExp', function () {
+ var test = testGrep(new Mocha());
+ test('/foo/', '/foo/');
+ // Keep the flags
+ test('/baz/i', '/baz/i');
+ test('/bar/g', '/bar/g');
+ test('/^foo(.*)bar/g', '/^foo(.*)bar/g');
+ });
+
+ it('should return it\'s parent Mocha object for chainability', function () {
+ var mocha = new Mocha();
+ mocha.grep().should.equal(mocha);
+ });
+ });
+
+ describe('"invert" option', function () {
+ it('should add a Boolean to the mocha.options object', function () {
+ var mocha = new Mocha({ invert: true });
+ mocha.options.invert.should.be.ok;
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/hook-async.spec.js b/tests/lib/mocha-3.1.2/test/hook-async.spec.js
new file mode 100644
index 0000000000..a03821e32c
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/hook-async.spec.js
@@ -0,0 +1,135 @@
+'use strict';
+
+describe('async', function () {
+ var calls = [];
+
+ before(function () {
+ calls.push('root before all');
+ });
+
+ after(function () {
+ calls.push('root after all');
+ calls.should.eql([
+ 'root before all',
+ 'before all',
+ 'parent before',
+ 'before',
+ 'before test one',
+ 'one',
+ 'after',
+ 'after test one passed',
+ 'parent after',
+ 'parent before',
+ 'before',
+ 'before test two',
+ 'two',
+ 'after',
+ 'after test two passed',
+ 'parent after',
+ 'parent before',
+ 'before',
+ 'before test three',
+ 'three',
+ 'after',
+ 'after test three passed',
+ 'parent after',
+ 'after all',
+ 'root after all'
+ ]);
+ });
+
+ beforeEach(function () {
+ calls.push('parent before');
+ });
+
+ afterEach(function () {
+ calls.push('parent after');
+ });
+
+ describe('hooks', function () {
+ before(function () {
+ calls.push('before all');
+ });
+
+ after(function () {
+ calls.push('after all');
+ });
+
+ beforeEach(function (done) {
+ var ctx = this;
+ process.nextTick(function () {
+ calls.push('before');
+ if (ctx.currentTest) {
+ calls.push('before test ' + ctx.currentTest.title);
+ }
+ done();
+ });
+ });
+
+ it('one', function (done) {
+ calls.should.eql([
+ 'root before all',
+ 'before all',
+ 'parent before',
+ 'before',
+ 'before test one'
+ ]);
+ calls.push('one');
+ process.nextTick(done);
+ });
+
+ it('two', function () {
+ calls.should.eql([
+ 'root before all',
+ 'before all',
+ 'parent before',
+ 'before',
+ 'before test one',
+ 'one',
+ 'after',
+ 'after test one passed',
+ 'parent after',
+ 'parent before',
+ 'before',
+ 'before test two'
+ ]);
+ calls.push('two');
+ });
+
+ it('three', function () {
+ calls.should.eql([
+ 'root before all',
+ 'before all',
+ 'parent before',
+ 'before',
+ 'before test one',
+ 'one',
+ 'after',
+ 'after test one passed',
+ 'parent after',
+ 'parent before',
+ 'before',
+ 'before test two',
+ 'two',
+ 'after',
+ 'after test two passed',
+ 'parent after',
+ 'parent before',
+ 'before',
+ 'before test three'
+ ]);
+ calls.push('three');
+ });
+
+ afterEach(function (done) {
+ var ctx = this;
+ process.nextTick(function () {
+ calls.push('after');
+ if (ctx.currentTest) {
+ calls.push('after test ' + ctx.currentTest.title + ' ' + ctx.currentTest.state);
+ }
+ done();
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/hook-sync-nested.spec.js b/tests/lib/mocha-3.1.2/test/hook-sync-nested.spec.js
new file mode 100644
index 0000000000..3f1929f547
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/hook-sync-nested.spec.js
@@ -0,0 +1,104 @@
+'use strict';
+
+describe('serial', function () {
+ describe('nested', function () {
+ var calls = [];
+
+ beforeEach(function () {
+ calls.push('parent before');
+ if (this.currentTest) {
+ calls.push('parent before test ' + this.currentTest.title);
+ }
+ });
+
+ afterEach(function () {
+ calls.push('parent after');
+ if (this.currentTest) {
+ calls.push('parent after test ' + this.currentTest.title + ' ' + this.currentTest.state);
+ }
+ });
+
+ it('foo', function () {
+ calls.should.eql([
+ 'parent before',
+ 'parent before test foo'
+ ]);
+ calls.push('foo');
+ });
+
+ it('bar', function () {
+ calls.should.eql([
+ 'parent before',
+ 'parent before test foo',
+ 'foo',
+ 'parent after',
+ 'parent after test foo passed',
+ 'parent before',
+ 'parent before test bar'
+ ]);
+ });
+
+ describe('hooks', function () {
+ beforeEach(function () {
+ calls.push('before');
+ if (this.currentTest) {
+ calls.push('before test ' + this.currentTest.title);
+ }
+ });
+
+ it('one', function () {
+ calls.should.eql([
+ 'parent before',
+ 'parent before test foo',
+ 'foo',
+ 'parent after',
+ 'parent after test foo passed',
+ 'parent before',
+ 'parent before test bar',
+ 'parent after',
+ 'parent after test bar passed',
+ 'parent before',
+ 'parent before test one',
+ 'before',
+ 'before test one'
+ ]);
+ calls.push('one');
+ });
+
+ it('two', function () {
+ calls.should.eql([
+ 'parent before',
+ 'parent before test foo',
+ 'foo',
+ 'parent after',
+ 'parent after test foo passed',
+ 'parent before',
+ 'parent before test bar',
+ 'parent after',
+ 'parent after test bar passed',
+ 'parent before',
+ 'parent before test one',
+ 'before',
+ 'before test one',
+ 'one',
+ 'after',
+ 'after test one passed',
+ 'parent after',
+ 'parent after test one passed',
+ 'parent before',
+ 'parent before test two',
+ 'before',
+ 'before test two'
+ ]);
+ calls.push('two');
+ });
+
+ afterEach(function () {
+ calls.push('after');
+ if (this.currentTest) {
+ calls.push('after test ' + this.currentTest.title + ' ' + this.currentTest.state);
+ }
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/hook-sync.spec.js b/tests/lib/mocha-3.1.2/test/hook-sync.spec.js
new file mode 100644
index 0000000000..b1138a6db8
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/hook-sync.spec.js
@@ -0,0 +1,103 @@
+'use strict';
+
+describe('serial', function () {
+ var calls = [];
+
+ beforeEach(function () {
+ calls.push('parent before');
+ });
+
+ afterEach(function () {
+ calls.push('parent after');
+ });
+
+ describe('hooks', function () {
+ beforeEach(function () {
+ calls.push('before');
+ if (this.currentTest) {
+ calls.push('before test ' + this.currentTest.title);
+ }
+ });
+
+ it('one', function () {
+ calls.should.eql([
+ 'parent before',
+ 'before',
+ 'before test one'
+ ]);
+ calls.push('one');
+ });
+
+ it('two', function () {
+ calls.should.eql([
+ 'parent before',
+ 'before',
+ 'before test one',
+ 'one',
+ 'after',
+ 'after test one passed',
+ 'parent after',
+ 'parent before',
+ 'before',
+ 'before test two'
+ ]);
+ calls.push('two');
+ });
+
+ it('three', function () {
+ calls.should.eql([
+ 'parent before',
+ 'before',
+ 'before test one',
+ 'one',
+ 'after',
+ 'after test one passed',
+ 'parent after',
+ 'parent before',
+ 'before',
+ 'before test two',
+ 'two',
+ 'after',
+ 'after test two passed',
+ 'parent after',
+ 'parent before',
+ 'before',
+ 'before test three'
+ ]);
+ calls.push('three');
+ });
+
+ afterEach(function () {
+ calls.push('after');
+ if (this.currentTest) {
+ calls.push('after test ' + this.currentTest.title + ' ' + this.currentTest.state);
+ }
+ });
+
+ after(function () {
+ calls.should.eql([
+ 'parent before',
+ 'before',
+ 'before test one',
+ 'one',
+ 'after',
+ 'after test one passed',
+ 'parent after',
+ 'parent before',
+ 'before',
+ 'before test two',
+ 'two',
+ 'after',
+ 'after test two passed',
+ 'parent after',
+ 'parent before',
+ 'before',
+ 'before test three',
+ 'three',
+ 'after',
+ 'after test three passed',
+ 'parent after'
+ ]);
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/hook-timeout.spec.js b/tests/lib/mocha-3.1.2/test/hook-timeout.spec.js
new file mode 100644
index 0000000000..c16c3011fb
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/hook-timeout.spec.js
@@ -0,0 +1,10 @@
+'use strict';
+
+before(function (done) {
+ this.timeout(100);
+ setTimeout(done, 50);
+});
+
+it('should work', function (done) {
+ done();
+});
diff --git a/tests/lib/mocha-3.1.2/test/http-meta-2.spec.js b/tests/lib/mocha-3.1.2/test/http-meta-2.spec.js
new file mode 100644
index 0000000000..4530969041
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/http-meta-2.spec.js
@@ -0,0 +1,92 @@
+'use strict';
+
+var http = require('http');
+
+var PORT = 8899;
+
+var server = http.createServer(function (req, res) {
+ var accept = req.headers.accept || '';
+ var json = ~accept.indexOf('json');
+
+ switch (req.url) {
+ case '/':
+ res.end('hello');
+ break;
+ case '/users':
+ if (json) {
+ res.end('["tobi","loki","jane"]');
+ } else {
+ res.end('tobi, loki, jane');
+ }
+ break;
+ }
+});
+
+function get (url) {
+ var fields;
+ var expected;
+ var header = {};
+
+ function request (done) {
+ http.get({ path: url, port: PORT, headers: header }, function (res) {
+ var buf = '';
+ res.should.have.property('statusCode', 200);
+ res.setEncoding('utf8');
+ res.on('data', function (chunk) { buf += chunk; });
+ res.on('end', function () {
+ buf.should.equal(expected);
+ done();
+ });
+ });
+ }
+
+ return {
+ set: function (field, val) {
+ header[field] = val;
+ return this;
+ },
+
+ should: {
+ respond: function (body) {
+ fields = Object.keys(header).map(function (field) {
+ return field + ': ' + header[field];
+ }).join(', ');
+
+ expected = body;
+ describe('GET ' + url, function () {
+ this.timeout(500);
+ if (fields) {
+ describe('when given ' + fields, function () {
+ it('should respond with "' + body + '"', request);
+ });
+ } else {
+ it('should respond with "' + body + '"', request);
+ }
+ });
+ }
+ }
+ };
+}
+
+describe('http server', function () {
+ before(function (done) {
+ server.listen(PORT, done);
+ });
+
+ after(function () {
+ server.close();
+ });
+
+ get('/')
+ .should
+ .respond('hello');
+
+ get('/users')
+ .should
+ .respond('tobi, loki, jane');
+
+ get('/users')
+ .set('Accept', 'application/json')
+ .should
+ .respond('["tobi","loki","jane"]');
+});
diff --git a/tests/lib/mocha-3.1.2/test/http-meta.spec.js b/tests/lib/mocha-3.1.2/test/http-meta.spec.js
new file mode 100644
index 0000000000..c92dbd2307
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/http-meta.spec.js
@@ -0,0 +1,65 @@
+'use strict';
+
+var http = require('http');
+
+var PORT = 8889;
+
+var server = http.createServer(function (req, res) {
+ var accept = req.headers.accept || '';
+ var json = ~accept.indexOf('json');
+
+ switch (req.url) {
+ case '/':
+ res.end('hello');
+ break;
+ case '/users':
+ if (json) {
+ res.end('["tobi","loki","jane"]');
+ } else {
+ res.end('tobi, loki, jane');
+ }
+ break;
+ }
+});
+
+function get (url, body, header) {
+ return function (done) {
+ http.get({
+ path: url,
+ port: PORT,
+ headers: header || {}
+ }, function (res) {
+ var buf = '';
+ res.should.have.property('statusCode', 200);
+ res.setEncoding('utf8');
+ res.on('data', function (chunk) { buf += chunk; });
+ res.on('end', function () {
+ buf.should.equal(body);
+ done();
+ });
+ });
+ };
+}
+
+describe('http requests', function () {
+ before(function (done) {
+ server.listen(PORT, done);
+ });
+
+ after(function () {
+ server.close();
+ });
+
+ describe('GET /', function () {
+ it('should respond with hello',
+ get('/', 'hello'));
+ });
+
+ describe('GET /users', function () {
+ it('should respond with users',
+ get('/users', 'tobi, loki, jane'));
+
+ it('should respond with users',
+ get('/users', '["tobi","loki","jane"]', { Accept: 'application/json' }));
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/diffs.spec.js b/tests/lib/mocha-3.1.2/test/integration/diffs.spec.js
new file mode 100644
index 0000000000..7d620e7489
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/diffs.spec.js
@@ -0,0 +1,46 @@
+'use strict';
+
+var assert = require('assert');
+var helpers = require('./helpers');
+var run = helpers.runMocha;
+var fs = require('fs');
+var getDiffs = helpers.getDiffs;
+
+function getExpectedOutput () {
+ var output = fs.readFileSync('test/integration/fixtures/diffs/output', 'UTF8');
+
+ // Diffs are delimited in file by "// DIFF"
+ return output.split(/\s*\/\/ DIFF/).slice(1).map(function (diff) {
+ return diff.split('\n').filter(Boolean).join('\n');
+ });
+}
+
+describe('diffs', function () {
+ var diffs, expected;
+
+ before(function (done) {
+ run('diffs/diffs.fixture.js', ['-C'], function (err, res) {
+ expected = getExpectedOutput();
+ diffs = getDiffs(res.output);
+ done(err);
+ });
+ });
+
+ [
+ 'should display a diff for small strings',
+ 'should display a diff of canonicalized objects',
+ 'should display a diff for medium strings',
+ 'should display a diff for entire object dumps',
+ 'should display a diff for multi-line strings',
+ 'should display a diff for entire object dumps',
+ 'should display a full-comparison with escaped special characters',
+ 'should display a word diff for large strings',
+ 'should work with objects',
+ 'should show value diffs and not be affected by commas',
+ 'should display diff by data and not like an objects'
+ ].forEach(function (title, i) {
+ it(title, function () {
+ assert.equal(diffs[i], expected[i]);
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/cascade.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/cascade.fixture.js
new file mode 100644
index 0000000000..259c81af2d
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/cascade.fixture.js
@@ -0,0 +1,59 @@
+'use strict';
+
+describe('one', function () {
+ before(function () {
+ console.log('before one');
+ });
+
+ after(function () {
+ console.log('after one');
+ });
+
+ beforeEach(function () {
+ console.log(' before each one');
+ });
+
+ afterEach(function () {
+ console.log(' after each one');
+ });
+
+ describe('two', function () {
+ before(function () {
+ console.log(' before two');
+ });
+
+ after(function () {
+ console.log(' after two');
+ });
+
+ beforeEach(function () {
+ console.log(' before each two');
+ });
+
+ afterEach(function () {
+ console.log(' after each two');
+ });
+
+ describe('three', function () {
+ before(function () {
+ console.log(' before three');
+ });
+
+ after(function () {
+ console.log(' after three');
+ });
+
+ beforeEach(function () {
+ console.log(' before each three');
+ });
+
+ afterEach(function () {
+ console.log(' after each three');
+ });
+
+ it('should three', function () {
+ console.log(' TEST three');
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.css.in b/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.css.in
new file mode 100644
index 0000000000..09a3ca5363
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.css.in
@@ -0,0 +1,9 @@
+body {
+ font: "Helvetica Neue", Helvetica, arial, sans-serif;
+ background: black;
+ color: white;
+}
+
+a {
+ color: blue
+}
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.css.out b/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.css.out
new file mode 100644
index 0000000000..53b3ec906e
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.css.out
@@ -0,0 +1,13 @@
+body {
+ font: "Helvetica Neue", Helvetica, arial, sans-serif;
+ background: black;
+ color: #fff;
+}
+
+a {
+ color: blue;
+}
+
+foo {
+ bar: 'baz';
+}
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.fixture.js
new file mode 100644
index 0000000000..50ea00bee0
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/diffs.fixture.js
@@ -0,0 +1,113 @@
+'use strict';
+
+var fs = require('fs');
+var cssin = fs.readFileSync('test/integration/fixtures/diffs/diffs.css.in', 'ascii');
+var cssout = fs.readFileSync('test/integration/fixtures/diffs/diffs.css.out', 'ascii');
+
+describe('diffs', function () {
+ var actual, expected;
+
+ it('should display a diff for small strings', function () {
+ actual = 'foo rar baz';
+ expected = 'foo bar baz';
+ actual.should.equal(expected);
+ });
+
+ it('should display a diff of canonicalized objects', function () {
+ actual = { name: 'travis j', age: 23 };
+ expected = { age: 23, name: 'travis' };
+ actual.should.equal(expected);
+ });
+
+ it('should display a diff for medium strings', function () {
+ actual = 'foo bar baz\nfoo rar baz\nfoo bar raz';
+ expected = 'foo bar baz\nfoo bar baz\nfoo bar baz';
+ actual.should.equal(expected);
+ });
+
+ it('should display a diff for entire object dumps', function () {
+ actual = {
+ name: 'joel',
+ age: 30,
+ address: {
+ city: 'new york',
+ country: 'usa'
+ }
+ };
+ expected = {
+ name: 'joe',
+ age: 30,
+ address: {
+ city: 'new york',
+ country: 'us'
+ }
+ };
+ actual.should.equal(expected);
+ });
+
+ it('should display a diff for multi-line strings', function () {
+ actual = 'one two three\nfour zzzz six\nseven eight nine';
+ expected = 'one two three\nfour five six\nseven eight nine';
+ actual.should.equal(expected);
+ });
+
+ it('should display a diff for entire object dumps', function () {
+ actual = {
+ name: 'joel',
+ age: 30,
+ address: {
+ city: 'new york',
+ country: 'usa'
+ }
+ };
+ expected = {
+ name: 'joe',
+ age: 30,
+ address: {
+ city: 'new york',
+ country: 'us'
+ }
+ };
+ actual.should.equal(expected);
+ });
+
+ it('should display a full-comparison with escaped special characters', function () {
+ actual = 'one\ttab\ntwo\t\t\ttabs';
+ expected = 'one\ttab\ntwo\t\ttabs';
+ actual.should.equal(expected);
+ });
+
+ it('should display a word diff for large strings', function () {
+ cssin.should.equal(cssout);
+ });
+
+ it('should work with objects', function () {
+ actual = {
+ name: 'tobi',
+ species: 'ferret',
+ color: 'white',
+ age: 2
+ };
+
+ expected = {
+ name: 'loki',
+ species: 'ferret',
+ color: 'brown',
+ age: 2
+ };
+
+ actual.should.eql(expected);
+ });
+
+ it('should show value diffs and not be affected by commas', function () {
+ actual = { a: 123 };
+ expected = { a: 123, b: 456 };
+ actual.should.equal(expected);
+ });
+
+ it('should display diff by data and not like an objects', function () {
+ actual = new Buffer([0x01]);
+ expected = new Buffer([0x02]);
+ actual.should.equal(expected);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/output b/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/output
new file mode 100644
index 0000000000..bf56a96397
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/diffs/output
@@ -0,0 +1,91 @@
+// DIFF
+ -foo rar baz
+ +foo bar baz
+
+// DIFF
+ {
+ "age": 23
+ - "name": "travis j"
+ + "name": "travis"
+ }
+
+// DIFF
+ foo bar baz
+ -foo rar baz
+ -foo bar raz
+ +foo bar baz
+ +foo bar baz
+
+// DIFF
+ {
+ "address": {
+ "city": "new york"
+ - "country": "usa"
+ + "country": "us"
+ }
+ "age": 30
+ - "name": "joel"
+ + "name": "joe"
+ }
+
+// DIFF
+ one two three
+ -four zzzz six
+ +four five six
+ seven eight nine
+
+// DIFF
+ {
+ "address": {
+ "city": "new york"
+ - "country": "usa"
+ + "country": "us"
+ }
+ "age": 30
+ - "name": "joel"
+ + "name": "joe"
+ }
+
+// DIFF
+ one tab
+ -two tabs
+ +two tabs
+
+// DIFF
+ body {
+ font: "Helvetica Neue", Helvetica, arial, sans-serif;
+ background: black;
+ - color: white;
+ + color: #fff;
+ }
+
+ a {
+ - color: blue
+ + color: blue;
+ }
+ +
+ +foo {
+ + bar: 'baz';
+ +}
+
+// DIFF
+ {
+ "age": 2
+ - "color": "white"
+ - "name": "tobi"
+ + "color": "brown"
+ + "name": "loki"
+ "species": "ferret"
+ }
+
+// DIFF
+ {
+ "a": 123
+ + "b": 456
+ }
+
+// DIFF
+ [
+ - 1
+ + 2
+ ]
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/after-hook-async-error.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/after-hook-async-error.fixture.js
new file mode 100644
index 0000000000..f3dfe7e1ae
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/after-hook-async-error.fixture.js
@@ -0,0 +1,21 @@
+'use strict';
+
+describe('spec 1', function () {
+ after(function (done) {
+ console.log('after');
+ process.nextTick(function () {
+ throw new Error('after hook error');
+ });
+ });
+ it('should be called because error is in after hook', function () {
+ console.log('test 1');
+ });
+ it('should be called because error is in after hook', function () {
+ console.log('test 2');
+ });
+});
+describe('spec 2', function () {
+ it('should be called, because hook error was in a sibling suite', function () {
+ console.log('test 3');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/after-hook-error.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/after-hook-error.fixture.js
new file mode 100644
index 0000000000..7fc258f46d
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/after-hook-error.fixture.js
@@ -0,0 +1,19 @@
+'use strict';
+
+describe('spec 1', function () {
+ after(function () {
+ console.log('after');
+ throw new Error('after hook error');
+ });
+ it('should be called because error is in after hook', function () {
+ console.log('test 1');
+ });
+ it('should be called because error is in after hook', function () {
+ console.log('test 2');
+ });
+});
+describe('spec 2', function () {
+ it('should be called, because hook error was in a sibling suite', function () {
+ console.log('test 3');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/afterEach-hook-async-error.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/afterEach-hook-async-error.fixture.js
new file mode 100644
index 0000000000..442ad9321f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/afterEach-hook-async-error.fixture.js
@@ -0,0 +1,21 @@
+'use strict';
+
+describe('spec 1', function () {
+ afterEach(function (done) {
+ console.log('after');
+ process.nextTick(function () {
+ throw new Error('after each hook error');
+ });
+ });
+ it('should be called because error is in after each hook', function () {
+ console.log('test 1');
+ });
+ it('should not be called', function () {
+ console.log('test 2');
+ });
+});
+describe('spec 2', function () {
+ it('should be called, because hook error was in a sibling suite', function () {
+ console.log('test 3');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/afterEach-hook-error.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/afterEach-hook-error.fixture.js
new file mode 100644
index 0000000000..5fb9a36c8d
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/afterEach-hook-error.fixture.js
@@ -0,0 +1,19 @@
+'use strict';
+
+describe('spec 1', function () {
+ afterEach(function () {
+ console.log('after');
+ throw new Error('after each hook error');
+ });
+ it('should be called because error is in after each hook', function () {
+ console.log('test 1');
+ });
+ it('should not be called', function () {
+ console.log('test 2');
+ });
+});
+describe('spec 2', function () {
+ it('should be called, because hook error was in a sibling suite', function () {
+ console.log('test 3');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-async-error-tip.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-async-error-tip.fixture.js
new file mode 100644
index 0000000000..04801c1946
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-async-error-tip.fixture.js
@@ -0,0 +1,13 @@
+'use strict';
+
+describe('spec 1', function () {
+ it('should not blame me', function () { });
+});
+describe('spec 2', function () {
+ before(function (done) {
+ process.nextTick(function () {
+ throw new Error('before hook error');
+ });
+ });
+ it('skipped');
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-async-error.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-async-error.fixture.js
new file mode 100644
index 0000000000..2530eec783
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-async-error.fixture.js
@@ -0,0 +1,21 @@
+'use strict';
+
+describe('spec 1', function () {
+ before(function (done) {
+ console.log('before');
+ process.nextTick(function () {
+ throw new Error('before hook error');
+ });
+ });
+ it('should not be called because of error in before hook', function () {
+ console.log('test 1');
+ });
+ it('should not be called because of error in before hook', function () {
+ console.log('test 2');
+ });
+});
+describe('spec 2', function () {
+ it('should be called, because hook error was in a sibling suite', function () {
+ console.log('test 3');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-error-tip.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-error-tip.fixture.js
new file mode 100644
index 0000000000..64df731573
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-error-tip.fixture.js
@@ -0,0 +1,11 @@
+'use strict';
+
+describe('spec 1', function () {
+ it('should not blame me', function () { });
+});
+describe('spec 2', function () {
+ before(function () {
+ throw new Error('before hook error');
+ });
+ it('skipped');
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-error.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-error.fixture.js
new file mode 100644
index 0000000000..547e54a243
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/before-hook-error.fixture.js
@@ -0,0 +1,19 @@
+'use strict';
+
+describe('spec 1', function () {
+ before(function () {
+ console.log('before');
+ throw new Error('before hook error');
+ });
+ it('should not be called because of error in before hook', function () {
+ console.log('test 1');
+ });
+ it('should not be called because of error in before hook', function () {
+ console.log('test 2');
+ });
+});
+describe('spec 2', function () {
+ it('should be called, because hook error was in a sibling suite', function () {
+ console.log('test 3');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/beforeEach-hook-async-error.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/beforeEach-hook-async-error.fixture.js
new file mode 100644
index 0000000000..6ce27784a6
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/beforeEach-hook-async-error.fixture.js
@@ -0,0 +1,21 @@
+'use strict';
+
+describe('spec 1', function () {
+ beforeEach(function (done) {
+ console.log('before');
+ process.nextTick(function () {
+ throw new Error('before each hook error');
+ });
+ });
+ it('should not be called because of error in before each hook', function () {
+ console.log('test 1');
+ });
+ it('should not be called because of error in before each hook', function () {
+ console.log('test 2');
+ });
+});
+describe('spec 2', function () {
+ it('should be called, because hook error was in a sibling suite', function () {
+ console.log('test 3');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/beforeEach-hook-error.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/beforeEach-hook-error.fixture.js
new file mode 100644
index 0000000000..4c0ab2f237
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/beforeEach-hook-error.fixture.js
@@ -0,0 +1,19 @@
+'use strict';
+
+describe('spec 1', function () {
+ beforeEach(function () {
+ console.log('before');
+ throw new Error('before each hook error');
+ });
+ it('should not be called because of error in before each hook', function () {
+ console.log('test 1');
+ });
+ it('should not be called because of error in before each hook', function () {
+ console.log('test 2');
+ });
+});
+describe('spec 2', function () {
+ it('should be called, because hook error was in a sibling suite', function () {
+ console.log('test 3');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/multiple-hook-async-error.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/multiple-hook-async-error.fixture.js
new file mode 100644
index 0000000000..858bbb3c5e
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/multiple-hook-async-error.fixture.js
@@ -0,0 +1,141 @@
+'use strict';
+
+before(function () {
+ console.log('root before');
+});
+beforeEach(function () {
+ console.log('root before each');
+});
+describe('1', function () {
+ beforeEach(function () {
+ console.log('1 before each');
+ });
+
+ describe('1-1', function () {
+ before(function () {
+ console.log('1-1 before');
+ });
+ beforeEach(function (done) {
+ console.log('1-1 before each');
+ process.nextTick(function () {
+ throw new Error('1-1 before each hook failed');
+ });
+ });
+ it('1-1 test 1', function () {
+ console.log('1-1 test 1');
+ });
+ it('1-1 test 2', function () {
+ console.log('1-1 test 2');
+ });
+ afterEach(function () {
+ console.log('1-1 after each');
+ });
+ after(function (done) {
+ console.log('1-1 after');
+ process.nextTick(function () {
+ throw new Error('1-1 after hook failed');
+ });
+ });
+ });
+
+ describe('1-2', function () {
+ before(function () {
+ console.log('1-2 before');
+ });
+ beforeEach(function () {
+ console.log('1-2 before each');
+ });
+ it('1-2 test 1', function () {
+ console.log('1-2 test 1');
+ });
+ it('1-2 test 2', function () {
+ console.log('1-2 test 2');
+ });
+ afterEach(function (done) {
+ console.log('1-2 after each');
+ process.nextTick(function () {
+ throw new Error('1-2 after each hook failed');
+ });
+ });
+ after(function () {
+ console.log('1-2 after');
+ });
+ });
+
+ afterEach(function () {
+ console.log('1 after each');
+ });
+
+ after(function () {
+ console.log('1 after');
+ });
+});
+
+describe('2', function () {
+ beforeEach(function (done) {
+ console.log('2 before each');
+ process.nextTick(function () {
+ throw new Error('2 before each hook failed');
+ });
+ });
+
+ describe('2-1', function () {
+ before(function () {
+ console.log('2-1 before');
+ });
+ beforeEach(function () {
+ console.log('2-1 before each');
+ });
+ it('2-1 test 1', function () {
+ console.log('2-1 test 1');
+ });
+ it('2-1 test 2', function () {
+ console.log('2-1 test 2');
+ });
+ afterEach(function () {
+ console.log('2-1 after each');
+ });
+ after(function () {
+ console.log('2-1 after');
+ });
+ });
+
+ describe('2-2', function () {
+ before(function () {
+ console.log('2-2 before');
+ });
+ beforeEach(function () {
+ console.log('2-2 before each');
+ });
+ it('2-2 test 1', function () {
+ console.log('2-2 test 1');
+ });
+ it('2-2 test 2', function () {
+ console.log('2-2 test 2');
+ });
+ afterEach(function () {
+ console.log('2-2 after each');
+ });
+ after(function () {
+ console.log('2-2 after');
+ });
+ });
+
+ afterEach(function (done) {
+ console.log('2 after each');
+ process.nextTick(function () {
+ throw new Error('2 after each hook failed');
+ });
+ });
+
+ after(function () {
+ console.log('2 after');
+ });
+});
+
+after(function () {
+ console.log('root after');
+});
+afterEach(function () {
+ console.log('root after each');
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/multiple-hook-error.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/multiple-hook-error.fixture.js
new file mode 100644
index 0000000000..085978ef79
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/hooks/multiple-hook-error.fixture.js
@@ -0,0 +1,131 @@
+'use strict';
+
+before(function () {
+ console.log('root before');
+});
+beforeEach(function () {
+ console.log('root before each');
+});
+describe('1', function () {
+ beforeEach(function () {
+ console.log('1 before each');
+ });
+
+ describe('1-1', function () {
+ before(function () {
+ console.log('1-1 before');
+ });
+ beforeEach(function () {
+ console.log('1-1 before each');
+ throw new Error('1-1 before each hook failed');
+ });
+ it('1-1 test 1', function () {
+ console.log('1-1 test 1');
+ });
+ it('1-1 test 2', function () {
+ console.log('1-1 test 2');
+ });
+ afterEach(function () {
+ console.log('1-1 after each');
+ });
+ after(function () {
+ console.log('1-1 after');
+ throw new Error('1-1 after hook failed');
+ });
+ });
+
+ describe('1-2', function () {
+ before(function () {
+ console.log('1-2 before');
+ });
+ beforeEach(function () {
+ console.log('1-2 before each');
+ });
+ it('1-2 test 1', function () {
+ console.log('1-2 test 1');
+ });
+ it('1-2 test 2', function () {
+ console.log('1-2 test 2');
+ });
+ afterEach(function () {
+ console.log('1-2 after each');
+ throw new Error('1-2 after each hook failed');
+ });
+ after(function () {
+ console.log('1-2 after');
+ });
+ });
+
+ afterEach(function () {
+ console.log('1 after each');
+ });
+
+ after(function () {
+ console.log('1 after');
+ });
+});
+
+describe('2', function () {
+ beforeEach(function () {
+ console.log('2 before each');
+ throw new Error('2 before each hook failed');
+ });
+
+ describe('2-1', function () {
+ before(function () {
+ console.log('2-1 before');
+ });
+ beforeEach(function () {
+ console.log('2-1 before each');
+ });
+ it('2-1 test 1', function () {
+ console.log('2-1 test 1');
+ });
+ it('2-1 test 2', function () {
+ console.log('2-1 test 2');
+ });
+ afterEach(function () {
+ console.log('2-1 after each');
+ });
+ after(function () {
+ console.log('2-1 after');
+ });
+ });
+
+ describe('2-2', function () {
+ before(function () {
+ console.log('2-2 before');
+ });
+ beforeEach(function () {
+ console.log('2-2 before each');
+ });
+ it('2-2 test 1', function () {
+ console.log('2-2 test 1');
+ });
+ it('2-2 test 2', function () {
+ console.log('2-2 test 2');
+ });
+ afterEach(function () {
+ console.log('2-2 after each');
+ });
+ after(function () {
+ console.log('2-2 after');
+ });
+ });
+
+ afterEach(function () {
+ console.log('2 after each');
+ throw new Error('2 after each hook failed');
+ });
+
+ after(function () {
+ console.log('2 after');
+ });
+});
+
+after(function () {
+ console.log('root after');
+});
+afterEach(function () {
+ console.log('root after each');
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-before.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-before.fixture.js
new file mode 100644
index 0000000000..1e1bc71a16
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-before.fixture.js
@@ -0,0 +1,12 @@
+'use strict';
+
+describe('suite', function () {
+ before(function (done) {
+ setTimeout(done, 10);
+ setTimeout(done, 30);
+ });
+
+ it('test1', function (done) {
+ setTimeout(done, 50);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-beforeEach.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-beforeEach.fixture.js
new file mode 100644
index 0000000000..32de2bf442
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-beforeEach.fixture.js
@@ -0,0 +1,16 @@
+'use strict';
+
+describe('suite', function () {
+ beforeEach(function (done) {
+ setTimeout(done, 10);
+ setTimeout(done, 20);
+ });
+
+ it('test1', function (done) {
+ setTimeout(done, 50);
+ });
+
+ it('test2', function (done) {
+ setTimeout(done, 50);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-specs.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-specs.fixture.js
new file mode 100644
index 0000000000..a8ae6d1ac4
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done-specs.fixture.js
@@ -0,0 +1,12 @@
+'use strict';
+
+describe('suite', function () {
+ it('test1', function (done) {
+ done();
+ setTimeout(done, 10);
+ });
+
+ it('test2', function (done) {
+ setTimeout(done, 20);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done.fixture.js
new file mode 100644
index 0000000000..f1b471c678
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/multiple-done.fixture.js
@@ -0,0 +1,20 @@
+'use strict';
+
+// The suite below should result in an additional error, but does
+// not. Uncomment once this bug is resolved.
+
+// describe('suite', function() {
+// beforeEach(function(done) {
+// done();
+// done();
+// });
+
+// it('test', function() {});
+// });
+
+it('should fail in a test-case', function (done) {
+ process.nextTick(function () {
+ done();
+ done();
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/async-only-async.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/async-only-async.fixture.js
new file mode 100644
index 0000000000..d5ba2b37a0
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/async-only-async.fixture.js
@@ -0,0 +1,5 @@
+'use strict';
+
+it('should pass', function (done) {
+ done();
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/async-only-sync.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/async-only-sync.fixture.js
new file mode 100644
index 0000000000..512fd0e4db
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/async-only-sync.fixture.js
@@ -0,0 +1,3 @@
+'use strict';
+
+it('throws an error', function () {});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/bail.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/bail.fixture.js
new file mode 100644
index 0000000000..5095e63158
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/bail.fixture.js
@@ -0,0 +1,23 @@
+'use strict';
+
+describe('suite1', function () {
+ it('should display this spec', function () {});
+
+ it('should only display this error', function (done) {
+ throw new Error('this should be displayed');
+ });
+
+ it('should not display this error', function (done) {
+ throw new Error('this should not be displayed');
+ });
+});
+
+describe('suite2', function () {
+ before(function (done) {
+ throw new Error('this hook should not be displayed');
+ });
+
+ it('should not display this error', function (done) {
+ throw new Error('this should not be displayed');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/delay-fail.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/delay-fail.fixture.js
new file mode 100644
index 0000000000..644cbc0281
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/delay-fail.fixture.js
@@ -0,0 +1,8 @@
+'use strict';
+
+setTimeout(function () {
+ throw new Error('oops');
+ /* eslint no-unreachable: off */
+ it('test', function () {});
+ run();
+}, 100);
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/delay.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/delay.fixture.js
new file mode 100644
index 0000000000..b2d49217db
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/delay.fixture.js
@@ -0,0 +1,16 @@
+'use strict';
+
+var assert = require('assert');
+var delay = 500;
+
+setTimeout(function () {
+ describe('delayed execution', function () {
+ it('should have no effect if attempted twice in the same suite', function () {
+ assert(true);
+ run();
+ assert(true);
+ });
+ });
+
+ run();
+}, delay);
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/grep.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/grep.fixture.js
new file mode 100644
index 0000000000..0939d084ec
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/grep.fixture.js
@@ -0,0 +1,19 @@
+'use strict';
+
+describe('grep', function () {
+ describe('Match', function () {
+ it('should run', function () {});
+ it('should also run', function () {});
+ });
+
+ describe('match', function () {
+ it('should run', function () {});
+ it('should also run', function () {});
+ });
+
+ describe('fail', function () {
+ it('should not be ran', function () {
+ throw new Error('Spec should not run');
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/bdd.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/bdd.fixture.js
new file mode 100644
index 0000000000..39323f3567
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/bdd.fixture.js
@@ -0,0 +1,72 @@
+'use strict';
+
+describe.only('should run this suite', function () {
+ it('should run this test', function () {});
+
+ it('should run this test', function () {});
+
+ it('should run this test', function () {});
+});
+
+describe('should not run this suite', function () {
+ it('should not run this test', function () {
+ (true).should.equal(false);
+ });
+
+ it('should not run this test', function () {
+ (true).should.equal(false);
+ });
+
+ it('should not run this test', function () {
+ (true).should.equal(false);
+ });
+});
+
+describe.only('should run this suite too', function () {
+ describe('should run this nested suite', function () {
+ it('should run this test', function () {});
+
+ it('should run this test', function () {});
+
+ it('should run this test', function () {});
+ });
+});
+
+describe.only('should run this suite, even', function () {
+ describe('should run this nested suite, even', function () {
+ describe('should run this doubly-nested suite!', function () {
+ it('should run this test', function () {});
+
+ it('should run this test', function () {});
+
+ it('should run this test', function () {});
+ });
+ });
+});
+
+describe('should run this suite with an exclusive test', function () {
+ it.only('should run this test', function () {});
+
+ describe('should not run this nested suite', function () {
+ describe.only('should not run this doubly-nested suite', function () {
+ it('should not run this test', function () {});
+
+ it('should not run this test', function () {});
+
+ it('should not run this test', function () {});
+ });
+ });
+});
+
+describe('should run this suite with an exclusive test (reverse order)', function () {
+ describe('should not run this nested suite', function () {
+ describe.only('should not run this doubly-nested suite', function () {
+ it('should not run this test', function () {});
+
+ it('should not run this test', function () {});
+
+ it('should not run this test', function () {});
+ });
+ });
+ it.only('should run this test', function () {});
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/qunit.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/qunit.fixture.js
new file mode 100644
index 0000000000..8bc598030d
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/qunit.fixture.js
@@ -0,0 +1,27 @@
+'use strict';
+
+suite.only('should run all tests in this suite');
+
+test('should run this test #1', function () {});
+
+test('should run this test #2', function () {});
+
+test('should run this test #3', function () {});
+
+test('should run this test #4', function () {});
+
+test('should run this test #5', function () {});
+
+suite('should not run any of this suite\'s tests');
+
+test('should not run this test', function () {
+ (false).should.equal(true);
+});
+
+test('should not run this test', function () {
+ (false).should.equal(true);
+});
+
+test('should not run this test', function () {
+ (false).should.equal(true);
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/tdd.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/tdd.fixture.js
new file mode 100644
index 0000000000..987ee6bfba
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/only/tdd.fixture.js
@@ -0,0 +1,37 @@
+'use strict';
+
+suite.only('should run all tests in this tdd suite', function () {
+ test('should run this test #1', function () {});
+
+ test('should run this test #2', function () {});
+
+ test('should run this test #3', function () {});
+
+ test('should run this test #4', function () {});
+});
+
+suite('should not run this suite', function () {
+ test('should not run this test', function () {
+ (true).should.equal(false);
+ });
+
+ test('should not run this test', function () {
+ (true).should.equal(false);
+ });
+
+ test('should not run this test', function () {
+ (true).should.equal(false);
+ });
+});
+
+suite.only('should run this suite too', function () {
+ suite('should run this nested suite', function () {
+ test('should run this test', function () {});
+
+ test('should run this test', function () {});
+
+ test('should run this test', function () {});
+
+ test('should run this test', function () {});
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/retries.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/retries.fixture.js
new file mode 100644
index 0000000000..8d2b0a40b6
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/retries.fixture.js
@@ -0,0 +1,7 @@
+'use strict';
+
+describe('retries', function () {
+ it('should fail', function () {
+ throw new Error('retry failure');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/sort-alpha.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/sort-alpha.fixture.js
new file mode 100644
index 0000000000..dd74303163
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/sort-alpha.fixture.js
@@ -0,0 +1,9 @@
+'use strict';
+
+describe('alpha', function () {
+ it('should be executed first', function () {
+ if (global.beta) {
+ throw new Error('alpha was not executed first');
+ }
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/options/sort-beta.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/sort-beta.fixture.js
new file mode 100644
index 0000000000..56da4a6523
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/options/sort-beta.fixture.js
@@ -0,0 +1,7 @@
+'use strict';
+
+describe('beta', function () {
+ it('should be executed second', function () {
+ global.beta = 1;
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/passing.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/passing.fixture.js
new file mode 100644
index 0000000000..baf142026d
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/passing.fixture.js
@@ -0,0 +1,13 @@
+'use strict';
+
+var assert = require('assert');
+
+describe('suite', function () {
+ it('test1', function () {
+ assert(true);
+ });
+
+ it('test2', function () {
+ assert(true);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-before.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-before.fixture.js
new file mode 100644
index 0000000000..efeaa93899
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-before.fixture.js
@@ -0,0 +1,18 @@
+'use strict';
+
+describe('skip in before', function () {
+ before(function (done) {
+ var self = this;
+ setTimeout(function () {
+ self.skip();
+ }, 50);
+ });
+
+ it('should never run this test', function () {
+ throw new Error('never thrown');
+ });
+
+ it('should never run this test', function () {
+ throw new Error('never thrown');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-beforeEach.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-beforeEach.fixture.js
new file mode 100644
index 0000000000..d6225564ba
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-beforeEach.fixture.js
@@ -0,0 +1,18 @@
+'use strict';
+
+describe('skip in beforeEach', function () {
+ beforeEach(function (done) {
+ var self = this;
+ setTimeout(function () {
+ self.skip();
+ }, 50);
+ });
+
+ it('should never run this test', function () {
+ throw new Error('never thrown');
+ });
+
+ it('should never run this test', function () {
+ throw new Error('never thrown');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-spec.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-spec.fixture.js
new file mode 100644
index 0000000000..44707b026c
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-async-spec.fixture.js
@@ -0,0 +1,14 @@
+'use strict';
+
+describe('skip in test', function () {
+ it('should skip async', function (done) {
+ var self = this;
+ setTimeout(function () {
+ self.skip();
+ }, 50);
+ });
+
+ it('should run other tests in the suite', function () {
+ // Do nothing
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-before.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-before.fixture.js
new file mode 100644
index 0000000000..5e3b208efa
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-before.fixture.js
@@ -0,0 +1,15 @@
+'use strict';
+
+describe('skip in before', function () {
+ before(function () {
+ this.skip();
+ });
+
+ it('should never run this test', function () {
+ throw new Error('never thrown');
+ });
+
+ it('should never run this test', function () {
+ throw new Error('never thrown');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-beforeEach.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-beforeEach.fixture.js
new file mode 100644
index 0000000000..0bd155ba55
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-beforeEach.fixture.js
@@ -0,0 +1,15 @@
+'use strict';
+
+describe('skip in beforeEach', function () {
+ beforeEach(function () {
+ this.skip();
+ });
+
+ it('should never run this test', function () {
+ throw new Error('never thrown');
+ });
+
+ it('should never run this test', function () {
+ throw new Error('never thrown');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-spec.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-spec.fixture.js
new file mode 100644
index 0000000000..1d22f0b77d
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/skip-sync-spec.fixture.js
@@ -0,0 +1,12 @@
+'use strict';
+
+describe('skip in test', function () {
+ it('should skip immediately', function () {
+ this.skip();
+ throw new Error('never thrown');
+ });
+
+ it('should run other tests in the suite', function () {
+ // Do nothing
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/spec.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/spec.fixture.js
new file mode 100644
index 0000000000..d750fcad1a
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/pending/spec.fixture.js
@@ -0,0 +1,5 @@
+'use strict';
+
+describe('suite', function () {
+ it('pending spec');
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/1794/issue-1794.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/1794/issue-1794.fixture.js
new file mode 100644
index 0000000000..8867369546
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/1794/issue-1794.fixture.js
@@ -0,0 +1,5 @@
+'use strict';
+
+test('pass', function () {
+ // pass
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/1794/simple-ui.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/1794/simple-ui.js
new file mode 100644
index 0000000000..5cfde0465f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/1794/simple-ui.js
@@ -0,0 +1,28 @@
+'use strict';
+
+var path = '../../../../../lib/';
+var Mocha = require(path + 'mocha');
+var Test = require(path + 'test');
+
+/**
+ * A simple UI that only exposes a single function: test
+ */
+module.exports = Mocha.interfaces['simple-ui'] = function (suite) {
+ suite.on('pre-require', function (context, file, mocha) {
+ var common = require(path + 'interfaces/common')([suite], context);
+
+ context.run = mocha.options.delay && common.runWithSuite(suite);
+
+ /**
+ * Describes a specification or test-case with the given `title`
+ * and callback `fn` acting as a thunk.
+ */
+ context.test = function (title, fn) {
+ var test = new Test(title, fn);
+ test.file = file;
+ suite.addTest(test);
+
+ return test;
+ };
+ });
+};
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1327.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1327.fixture.js
new file mode 100644
index 0000000000..e788278d6d
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1327.fixture.js
@@ -0,0 +1,17 @@
+'use strict';
+
+it('test 1', function () {
+ console.log('testbody1');
+ process.nextTick(function () {
+ throw new Error('Too bad');
+ });
+});
+
+it('test 2', function () {
+ console.log('testbody2');
+});
+
+it('test 3', function () {
+ console.log('testbody3');
+ throw new Error('OUCH');
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1417.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1417.js
new file mode 100644
index 0000000000..13ce053784
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1417.js
@@ -0,0 +1,22 @@
+'use strict';
+
+/**
+ * This file should generate only one failure per spec for the thrown error.
+ * It should not report misleading 'multiple calls to done()'.
+ */
+
+it('fails exactly once when a global error is thrown synchronously and done errors', function (done) {
+ setTimeout(function () {
+ done(new Error('test error'));
+ }, 1); // Not 0 - it will 'succeed', but won't test the breaking condition
+
+ throw new Error('sync error');
+});
+
+it('fails exactly once when a global error is thrown synchronously and done completes', function (done) {
+ setTimeout(function () {
+ done();
+ }, 1); // Not 0 - it will 'succeed', but won't test the breaking condition
+
+ throw new Error('sync error');
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1991.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1991.fixture.js
new file mode 100644
index 0000000000..024f02519f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-1991.fixture.js
@@ -0,0 +1,49 @@
+'use strict';
+
+/* eslint no-unused-vars: off */
+
+function MemoryLeak () {
+ this.myArr = [];
+ for (var i = 0; i < 1000000; i++) {
+ this.myArr.push(i);
+ }
+}
+
+var numOfTests = 300;
+for (var i = 0; i < numOfTests; i += 1) {
+ /*
+ * This Test suite will crash V8 due to:
+ * 'FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory'
+ * if all the deferred functions references have not been cleared
+ */
+ describe('Memory Leak Suite #' + i, function () {
+ // The <closureVar> variable will be accessed by the test below.
+ // As long as those test's functions are
+ // referenced in memory, the closure variable may not be garbage collected
+ // as it is still referenced.
+ // * In a chrome heap snapshot it will appear under "system / Context" (a scope)
+ var closureVar;
+
+ before(function () {
+ var x = closureVar ? 1 : 2;
+ });
+
+ after(function () {
+ var x = closureVar[0];
+ });
+
+ beforeEach(function () {
+ var x = closureVar ? 1 : 2;
+ });
+
+ afterEach(function () {
+ var x = closureVar[0];
+ });
+
+ it('access a variable via a closure', function () {
+ // slow performance on older node.js versions
+ this.timeout(1000);
+ closureVar = new MemoryLeak();
+ });
+ });
+}
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2315.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2315.js
new file mode 100644
index 0000000000..fe18841d1c
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2315.js
@@ -0,0 +1,11 @@
+'use strict';
+
+describe('issue-2315: cannot read property currentRetry of undefined', function () {
+ before(function () {
+ process.nextTick(function () {
+ throw new Error();
+ });
+ });
+
+ it('something', function () {});
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2406.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2406.fixture.js
new file mode 100644
index 0000000000..b3770014dd
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2406.fixture.js
@@ -0,0 +1,17 @@
+'use strict';
+
+describe('outer describe', function () {
+ it('should not run this test', function () {});
+ describe('this suite should not run', function () {
+ it('should not run this test', function () {});
+ });
+ describe.only('this .only suite should run', function () {
+ describe('this suite should run', function () {
+ it('should run this test in a nested suite', function () {});
+ });
+ it('should run this test', function () {});
+ });
+ describe('this suite should not run', function () {
+ it('should not run this test', function () {});
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2417.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2417.fixture.js
new file mode 100644
index 0000000000..58f49cf846
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/regression/issue-2417.fixture.js
@@ -0,0 +1,9 @@
+'use strict';
+
+describe('outer describe', function () {
+ describe.only('outer describe.only', function () {
+ it.only('inner it.only', function () {
+ // should run and exit without error
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/async.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/async.fixture.js
new file mode 100644
index 0000000000..56d067fc05
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/async.fixture.js
@@ -0,0 +1,30 @@
+'use strict';
+
+describe('retries', function () {
+ var times = 0;
+ before(function () {
+ console.log('before');
+ });
+
+ after(function () {
+ console.log('after');
+ });
+
+ beforeEach(function () {
+ console.log('before each', times);
+ });
+
+ afterEach(function () {
+ console.log('after each', times);
+ });
+
+ it('should allow override and run appropriate hooks', function (done) {
+ this.timeout(200);
+ this.retries(2);
+ console.log('TEST', times);
+ if (++times < 3) {
+ return setTimeout(done, 300);
+ }
+ setTimeout(done, 50);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/early-pass.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/early-pass.fixture.js
new file mode 100644
index 0000000000..ddad40399e
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/early-pass.fixture.js
@@ -0,0 +1,13 @@
+'use strict';
+
+describe('retries', function () {
+ this.retries(1);
+ var times = 0;
+
+ it('should pass after 1 retry', function () {
+ times++;
+ if (times !== 2) {
+ throw new Error('retry error ' + times);
+ }
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/hooks.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/hooks.fixture.js
new file mode 100644
index 0000000000..b4fc081aaa
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/hooks.fixture.js
@@ -0,0 +1,27 @@
+'use strict';
+
+describe('retries', function () {
+ var times = 0;
+ before(function () {
+ console.log('before');
+ });
+
+ after(function () {
+ console.log('after');
+ });
+
+ beforeEach(function () {
+ console.log('before each', times);
+ });
+
+ afterEach(function () {
+ console.log('after each', times);
+ });
+
+ it('should allow override and run appropriate hooks', function () {
+ this.retries(4);
+ console.log('TEST', times);
+ times++;
+ throw new Error('retry error');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/nested.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/nested.fixture.js
new file mode 100644
index 0000000000..877d519d7f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/retries/nested.fixture.js
@@ -0,0 +1,11 @@
+'use strict';
+
+describe('retries', function () {
+ this.retries(3);
+ describe('nested', function () {
+ it('should fail after only 1 retry', function () {
+ this.retries(1);
+ throw new Error('retry error');
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-no-callback.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-no-callback.fixture.js
new file mode 100644
index 0000000000..80d046438f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-no-callback.fixture.js
@@ -0,0 +1,3 @@
+'use strict';
+
+describe('a suite without a callback');
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-skipped-callback.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-skipped-callback.fixture.js
new file mode 100644
index 0000000000..6def25de7f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-skipped-callback.fixture.js
@@ -0,0 +1,3 @@
+'use strict';
+
+xdescribe('a pending suite with a callback', function () {});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-skipped-no-callback.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-skipped-no-callback.fixture.js
new file mode 100644
index 0000000000..e9381159bf
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/suite/suite-skipped-no-callback.fixture.js
@@ -0,0 +1,3 @@
+'use strict';
+
+xdescribe('a pending suite without a callback');
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/timeout.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/timeout.fixture.js
new file mode 100644
index 0000000000..d237436811
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/timeout.fixture.js
@@ -0,0 +1,19 @@
+'use strict';
+
+describe('timeout', function () {
+ this.timeout(1);
+
+ it('should be honored with sync suites', function () {
+ sleep(2);
+ });
+
+ it('should be honored with async suites', function (done) {
+ sleep(2);
+ done();
+ });
+
+ function sleep (ms) {
+ var start = Date.now();
+ while (start + ms > Date.now());
+ }
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/uncaught-hook.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/uncaught-hook.fixture.js
new file mode 100644
index 0000000000..54f30c56e9
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/uncaught-hook.fixture.js
@@ -0,0 +1,15 @@
+'use strict';
+
+describe('uncaught', function () {
+ beforeEach(function (done) {
+ process.nextTick(function () {
+ throw new Error('oh noes');
+ });
+ });
+
+ it('test', function (done) {
+ process.nextTick(function () {
+ throw new Error("I'm uncaught!");
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/fixtures/uncaught.fixture.js b/tests/lib/mocha-3.1.2/test/integration/fixtures/uncaught.fixture.js
new file mode 100644
index 0000000000..6a2ded880c
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/fixtures/uncaught.fixture.js
@@ -0,0 +1,22 @@
+'use strict';
+
+/**
+ * This file should only generate one failure per spec despite the fact that
+ * Mocha is capable of detecting two distinct exceptions during test execution.
+ */
+
+it('fails exactly once when a global error is thrown first', function (done) {
+ setTimeout(function () {
+ throw new Error('global error');
+ }, 0);
+});
+
+it('fails exactly once when a global error is thrown second', function (done) {
+ setTimeout(function () {
+ done(new Error('test error'));
+ }, 0);
+
+ setTimeout(function () {
+ throw new Error('global error');
+ }, 0);
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/helpers.js b/tests/lib/mocha-3.1.2/test/integration/helpers.js
new file mode 100644
index 0000000000..7f6a608a6f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/helpers.js
@@ -0,0 +1,193 @@
+'use strict';
+
+var spawn = require('child_process').spawn;
+var path = require('path');
+var fs = require('fs');
+var baseReporter = require('../../lib/reporters/base');
+
+module.exports = {
+ /**
+ * Invokes the mocha binary for the given fixture with color output disabled.
+ * Accepts an array of additional command line args to pass. The callback is
+ * invoked with a summary of the run, in addition to its output. The summary
+ * includes the number of passing, pending, and failing tests, as well as the
+ * exit code. Useful for testing different reporters.
+ *
+ * Example response:
+ * {
+ * pending: 0,
+ * passing: 0,
+ * failing: 1,
+ * code: 1,
+ * output: '...'
+ * }
+ *
+ * @param {string} fixturePath
+ * @param {array} args
+ * @param {function} fn
+ */
+ runMocha: function (fixturePath, args, fn) {
+ var path;
+
+ path = resolveFixturePath(fixturePath);
+ args = args || [];
+
+ invokeMocha(args.concat(['-C', path]), function (err, res) {
+ if (err) return fn(err);
+
+ fn(null, getSummary(res));
+ });
+ },
+
+ /**
+ * Invokes the mocha binary on the code of the body of the function.
+ * Accepts an array of additional command line args to pass. The callback is
+ * invoked with a summary of the run, in addition to its output. The summary
+ * includes the number of passing, pending, and failing tests, as well as the
+ * exit code. Useful for testing different reporters.
+ *
+ * Example response:
+ * {
+ * pending: 0,
+ * passing: 0,
+ * failing: 1,
+ * code: 1,
+ * output: '...'
+ * }
+ *
+ * @param {function} fixture
+ * @param {array} args
+ * @param {function} fn
+ */
+ runMochaFunction: function (fixture, args, fn) {
+ var path = resolveFixturePath(fixture.name + '.js' || 'tempfile.js');
+ args = args || [];
+
+ var fixtureContent = 'var fn = ' + fixture.toString() + '; fn()';
+ fs.writeFileSync(path, fixtureContent, 'utf8');
+
+ function cleanup () {
+ fs.unlink(path);
+ fn.apply(this, arguments);
+ }
+
+ invokeMocha(args.concat(['-C', path]), function (err, res) {
+ if (err) {
+ return cleanup(err);
+ }
+
+ cleanup(null, getSummary(res));
+ });
+ },
+
+ /**
+ * Invokes the mocha binary for the given fixture using the JSON reporter,
+ * returning the parsed output, as well as exit code.
+ *
+ * @param {string} fixturePath
+ * @param {array} args
+ * @param {function} fn
+ */
+ runMochaJSON: function (fixturePath, args, fn) {
+ var path;
+
+ path = resolveFixturePath(fixturePath);
+ args = args || [];
+
+ invokeMocha(args.concat(['--reporter', 'json', path]), function (err, res) {
+ if (err) return fn(err);
+
+ try {
+ var result = JSON.parse(res.output);
+ result.code = res.code;
+ } catch (err) {
+ return fn(err);
+ }
+
+ fn(null, result);
+ });
+ },
+
+ /**
+ * Returns an array of diffs corresponding to exceptions thrown from specs,
+ * given the plaintext output (-C) of a mocha run.
+ *
+ * @param {string} output
+ * returns {string[]}
+ */
+ getDiffs: function (output) {
+ var diffs, i, inDiff, inStackTrace;
+
+ diffs = [];
+ output.split('\n').forEach(function (line) {
+ if (line.match(/^\s{2}\d+\)/)) {
+ // New spec, e.g. "1) spec title"
+ diffs.push([]);
+ i = diffs.length - 1;
+ inStackTrace = false;
+ inDiff = false;
+ } else if (!diffs.length || inStackTrace) {
+ // Haven't encountered a spec yet
+ // or we're in the middle of a stack trace
+ return;
+ } else if (line.indexOf('+ expected - actual') !== -1) {
+ inDiff = true;
+ } else if (line.match(/at Context/)) {
+ // At the start of a stack trace
+ inStackTrace = true;
+ inDiff = false;
+ } else if (inDiff) {
+ diffs[i].push(line);
+ }
+ });
+
+ // Ignore empty lines before/after diff
+ return diffs.map(function (diff) {
+ return diff.slice(1, -3).join('\n');
+ });
+ },
+
+ /**
+ * regular expression used for splitting lines based on new line / dot symbol.
+ */
+ splitRegExp: new RegExp('[\\n' + baseReporter.symbols.dot + ']+')
+};
+
+function invokeMocha (args, fn) {
+ var output, mocha, listener;
+
+ output = '';
+ args = [path.join('bin', 'mocha')].concat(args);
+ mocha = spawn(process.execPath, args);
+
+ listener = function (data) {
+ output += data;
+ };
+
+ mocha.stdout.on('data', listener);
+ mocha.stderr.on('data', listener);
+ mocha.on('error', fn);
+
+ mocha.on('close', function (code) {
+ fn(null, {
+ output: output.split('\n').join('\n'),
+ code: code
+ });
+ });
+}
+
+function resolveFixturePath (fixture) {
+ return path.join('./test/integration/fixtures', fixture);
+}
+
+function getSummary (res) {
+ return ['passing', 'pending', 'failing'].reduce(function (summary, type) {
+ var pattern, match;
+
+ pattern = new RegExp(' (\\d+) ' + type + '\\s');
+ match = pattern.exec(res.output);
+ summary[type] = (match) ? parseInt(match, 10) : 0;
+
+ return summary;
+ }, res);
+}
diff --git a/tests/lib/mocha-3.1.2/test/integration/hook-err.spec.js b/tests/lib/mocha-3.1.2/test/integration/hook-err.spec.js
new file mode 100644
index 0000000000..fbdd7e8e38
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/hook-err.spec.js
@@ -0,0 +1,217 @@
+'use strict';
+
+var assert = require('assert');
+var runMocha = require('./helpers').runMocha;
+var splitRegExp = require('./helpers').splitRegExp;
+var bang = require('../../lib/reporters/base').symbols.bang;
+
+describe('hook error handling', function () {
+ var lines;
+
+ describe('before hook error', function () {
+ before(run('hooks/before-hook-error.fixture.js'));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ ['before', bang + 'test 3']
+ );
+ });
+ });
+
+ describe('before hook error tip', function () {
+ before(run('hooks/before-hook-error-tip.fixture.js', onlyErrorTitle));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ ['1) spec 2 "before all" hook:']
+ );
+ });
+ });
+
+ describe('before each hook error', function () {
+ before(run('hooks/beforeEach-hook-error.fixture.js'));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ ['before', bang + 'test 3']
+ );
+ });
+ });
+
+ describe('after hook error', function () {
+ before(run('hooks/after-hook-error.fixture.js'));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ ['test 1', 'test 2', 'after', bang + 'test 3']
+ );
+ });
+ });
+
+ describe('after each hook error', function () {
+ before(run('hooks/afterEach-hook-error.fixture.js'));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ ['test 1', 'after', bang + 'test 3']
+ );
+ });
+ });
+
+ describe('multiple hook errors', function () {
+ before(run('hooks/multiple-hook-error.fixture.js'));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ [
+ 'root before',
+ '1-1 before',
+ 'root before each',
+ '1 before each',
+ '1-1 before each',
+ bang + '1-1 after each',
+ '1 after each',
+ 'root after each',
+ '1-1 after',
+ bang + '1-2 before',
+ 'root before each',
+ '1 before each',
+ '1-2 before each',
+ '1-2 test 1',
+ '1-2 after each',
+ bang + '1 after each',
+ 'root after each',
+ '1-2 after',
+ '1 after',
+ '2-1 before',
+ 'root before each',
+ '2 before each',
+ bang + '2 after each',
+ bang + 'root after each',
+ '2-1 after',
+ '2 after',
+ 'root after'
+ ]
+ );
+ });
+ });
+
+ describe('async - before hook error', function () {
+ before(run('hooks/before-hook-async-error.fixture.js'));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ ['before', bang + 'test 3']
+ );
+ });
+ });
+
+ describe('async - before hook error tip', function () {
+ before(run('hooks/before-hook-async-error-tip.fixture.js', onlyErrorTitle));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ ['1) spec 2 "before all" hook:']
+ );
+ });
+ });
+
+ describe('async - before each hook error', function () {
+ before(run('hooks/beforeEach-hook-async-error.fixture.js'));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ ['before', bang + 'test 3']
+ );
+ });
+ });
+
+ describe('async - after hook error', function () {
+ before(run('hooks/after-hook-async-error.fixture.js'));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ ['test 1', 'test 2', 'after', bang + 'test 3']
+ );
+ });
+ });
+
+ describe('async - after each hook error', function () {
+ before(run('hooks/afterEach-hook-async-error.fixture.js'));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ ['test 1', 'after', bang + 'test 3']
+ );
+ });
+ });
+
+ describe('async - multiple hook errors', function () {
+ before(run('hooks/multiple-hook-async-error.fixture.js'));
+ it('should verify results', function () {
+ assert.deepEqual(
+ lines,
+ [
+ 'root before',
+ '1-1 before',
+ 'root before each',
+ '1 before each',
+ '1-1 before each',
+ bang + '1-1 after each',
+ '1 after each',
+ 'root after each',
+ '1-1 after',
+ bang + '1-2 before',
+ 'root before each',
+ '1 before each',
+ '1-2 before each',
+ '1-2 test 1',
+ '1-2 after each',
+ bang + '1 after each',
+ 'root after each',
+ '1-2 after',
+ '1 after',
+ '2-1 before',
+ 'root before each',
+ '2 before each',
+ bang + '2 after each',
+ bang + 'root after each',
+ '2-1 after',
+ '2 after',
+ 'root after'
+ ]
+ );
+ });
+ });
+
+ function run (fnPath, outputFilter) {
+ return function (done) {
+ runMocha(fnPath, [], function (err, res) {
+ assert.ifError(err);
+
+ lines = res.output
+ .split(splitRegExp)
+ .map(function (line) {
+ return line.trim();
+ })
+ .filter(outputFilter || onlyConsoleOutput());
+
+ done();
+ });
+ };
+ }
+});
+
+function onlyConsoleOutput () {
+ var foundSummary = false;
+ return function (line) {
+ if (!foundSummary) {
+ foundSummary = !!(/\(\d+ms\)/).exec(line);
+ }
+ return !foundSummary && line.length > 0;
+ };
+}
+
+function onlyErrorTitle (line) {
+ return !!(/^1\)/).exec(line);
+}
diff --git a/tests/lib/mocha-3.1.2/test/integration/hooks.spec.js b/tests/lib/mocha-3.1.2/test/integration/hooks.spec.js
new file mode 100644
index 0000000000..0d31cbfdf4
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/hooks.spec.js
@@ -0,0 +1,45 @@
+'use strict';
+
+var assert = require('assert');
+var run = require('./helpers').runMocha;
+var splitRegExp = require('./helpers').splitRegExp;
+var args = [];
+
+describe('hooks', function () {
+ it('are ran in correct order', function (done) {
+ run('cascade.fixture.js', args, function (err, res) {
+ var lines, expected;
+
+ assert(!err);
+
+ lines = res.output.split(splitRegExp).map(function (line) {
+ return line.trim();
+ }).filter(function (line) {
+ return line.length;
+ }).slice(0, -1);
+
+ expected = [
+ 'before one',
+ 'before two',
+ 'before three',
+ 'before each one',
+ 'before each two',
+ 'before each three',
+ 'TEST three',
+ 'after each three',
+ 'after each two',
+ 'after each one',
+ 'after three',
+ 'after two',
+ 'after one'
+ ];
+
+ expected.forEach(function (line, i) {
+ assert.equal(lines[i], line);
+ });
+
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/multiple-done.spec.js b/tests/lib/mocha-3.1.2/test/integration/multiple-done.spec.js
new file mode 100644
index 0000000000..76a6483115
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/multiple-done.spec.js
@@ -0,0 +1,98 @@
+'use strict';
+
+var assert = require('assert');
+var run = require('./helpers').runMochaJSON;
+var args = [];
+
+describe('multiple calls to done()', function () {
+ var res;
+ describe('from a spec', function () {
+ before(function (done) {
+ run('multiple-done.fixture.js', args, function (err, result) {
+ res = result;
+ done(err);
+ });
+ });
+
+ it('results in failures', function () {
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 1);
+ assert.equal(res.stats.failures, 1);
+ assert.equal(res.code, 1);
+ });
+
+ it('throws a descriptive error', function () {
+ assert.equal(res.failures[0].err.message,
+ 'done() called multiple times');
+ });
+ });
+
+ describe('with multiple specs', function () {
+ before(function (done) {
+ run('multiple-done-specs.fixture.js', args, function (err, result) {
+ res = result;
+ done(err);
+ });
+ });
+
+ it('results in a failure', function () {
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 2);
+ assert.equal(res.stats.failures, 1);
+ assert.equal(res.code, 1);
+ });
+
+ it('correctly attributes the error', function () {
+ assert.equal(res.failures[0].fullTitle, 'suite test1');
+ assert.equal(res.failures[0].err.message,
+ 'done() called multiple times');
+ });
+ });
+
+ describe('from a before hook', function () {
+ before(function (done) {
+ run('multiple-done-before.fixture.js', args, function (err, result) {
+ res = result;
+ done(err);
+ });
+ });
+
+ it('results in a failure', function () {
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 1);
+ assert.equal(res.stats.failures, 1);
+ assert.equal(res.code, 1);
+ });
+
+ it('correctly attributes the error', function () {
+ assert.equal(res.failures[0].fullTitle, 'suite "before all" hook');
+ assert.equal(res.failures[0].err.message,
+ 'done() called multiple times');
+ });
+ });
+
+ describe('from a beforeEach hook', function () {
+ before(function (done) {
+ run('multiple-done-beforeEach.fixture.js', args, function (err, result) {
+ res = result;
+ done(err);
+ });
+ });
+
+ it('results in a failure', function () {
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 2);
+ assert.equal(res.stats.failures, 2);
+ assert.equal(res.code, 2);
+ });
+
+ it('correctly attributes the errors', function () {
+ assert.equal(res.failures.length, 2);
+ res.failures.forEach(function (failure) {
+ assert.equal(failure.fullTitle, 'suite "before each" hook');
+ assert.equal(failure.err.message,
+ 'done() called multiple times');
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/only.spec.js b/tests/lib/mocha-3.1.2/test/integration/only.spec.js
new file mode 100644
index 0000000000..b37a4b263e
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/only.spec.js
@@ -0,0 +1,45 @@
+'use strict';
+
+var run = require('./helpers').runMochaJSON;
+var assert = require('assert');
+
+describe('.only()', function () {
+ describe('bdd', function () {
+ it('should run only tests that marked as `only`', function (done) {
+ run('options/only/bdd.fixture.js', ['--ui', 'bdd'], function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 11);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+
+ describe('tdd', function () {
+ it('should run only tests that marked as `only`', function (done) {
+ run('options/only/tdd.fixture.js', ['--ui', 'tdd'], function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 8);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+
+ describe('qunit', function () {
+ it('should run only tests that marked as `only`', function (done) {
+ run('options/only/qunit.fixture.js', ['--ui', 'qunit'], function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 5);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/options.spec.js b/tests/lib/mocha-3.1.2/test/integration/options.spec.js
new file mode 100644
index 0000000000..7c7a3cc75e
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/options.spec.js
@@ -0,0 +1,183 @@
+'use strict';
+
+var assert = require('assert');
+var run = require('./helpers').runMochaJSON;
+var args = [];
+
+describe('options', function () {
+ describe('--async-only', function () {
+ before(function () {
+ args = ['--async-only'];
+ });
+
+ it('should fail synchronous specs', function (done) {
+ run('options/async-only-sync.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 1);
+
+ assert.equal(res.failures[0].title, 'throws an error');
+ assert.equal(res.code, 1);
+ done();
+ });
+ });
+
+ it('should allow asynchronous specs', function (done) {
+ run('options/async-only-async.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 1);
+ assert.equal(res.stats.failures, 0);
+
+ assert.equal(res.passes[0].title, 'should pass');
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+
+ describe('--bail', function () {
+ before(function () {
+ args = ['--bail'];
+ });
+
+ it('should stop after the first error', function (done) {
+ run('options/bail.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 1);
+ assert.equal(res.stats.failures, 1);
+
+ assert.equal(res.passes[0].title, 'should display this spec');
+ assert.equal(res.failures[0].title, 'should only display this error');
+ assert.equal(res.code, 1);
+ done();
+ });
+ });
+ });
+
+ describe('--sort', function () {
+ before(function () {
+ args = ['--sort'];
+ });
+
+ it('should sort tests in alphabetical order', function (done) {
+ run('options/sort*', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 2);
+ assert.equal(res.stats.failures, 0);
+
+ assert.equal(res.passes[0].fullTitle,
+ 'alpha should be executed first');
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+
+ describe('--delay', function () {
+ before(function () {
+ args = ['--delay'];
+ });
+
+ it('should run the generated test suite', function (done) {
+ run('options/delay.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 1);
+ assert.equal(res.stats.failures, 0);
+
+ assert.equal(res.passes[0].title,
+ 'should have no effect if attempted twice in the same suite');
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+
+ it('should throw an error if the test suite failed to run', function (done) {
+ run('options/delay-fail.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 1);
+
+ assert.equal(res.failures[0].title,
+ 'Uncaught error outside test suite');
+ assert.equal(res.code, 1);
+ done();
+ });
+ });
+ });
+
+ describe('--grep', function () {
+ it('runs specs matching a string', function (done) {
+ args = ['--grep', 'match'];
+ run('options/grep.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 2);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+
+ describe('runs specs matching a RegExp', function () {
+ it('with RegExp like strings(pattern follow by flag)', function (done) {
+ args = ['--grep', '/match/i'];
+ run('options/grep.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 4);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+
+ it('string as pattern', function (done) {
+ args = ['--grep', '.*'];
+ run('options/grep.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 4);
+ assert.equal(res.stats.failures, 1);
+ assert.equal(res.code, 1);
+ done();
+ });
+ });
+ });
+
+ describe('with --invert', function () {
+ it('runs specs that do not match the pattern', function (done) {
+ args = ['--grep', 'fail', '--invert'];
+ run('options/grep.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 4);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+ });
+
+ describe('--retries', function () {
+ it('retries after a certain threshold', function (done) {
+ args = ['--retries', '3'];
+ run('options/retries.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.tests, 1);
+ assert.equal(res.tests[0].currentRetry, 3);
+ assert.equal(res.stats.failures, 1);
+ assert.equal(res.code, 1);
+ done();
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/pending.spec.js b/tests/lib/mocha-3.1.2/test/integration/pending.spec.js
new file mode 100644
index 0000000000..19ae30ad3a
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/pending.spec.js
@@ -0,0 +1,102 @@
+'use strict';
+
+var assert = require('assert');
+var run = require('./helpers').runMochaJSON;
+var args = [];
+
+describe('pending', function () {
+ describe('pending specs', function () {
+ it('should be created by omitting a function', function (done) {
+ run('pending/spec.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 1);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+
+ describe('synchronous skip()', function () {
+ describe('in spec', function () {
+ it('should immediately skip the spec and run all others', function (done) {
+ run('pending/skip-sync-spec.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 1);
+ assert.equal(res.stats.passes, 1);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+
+ describe('in before', function () {
+ it('should skip all suite specs', function (done) {
+ run('pending/skip-sync-before.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 2);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+
+ describe('in beforeEach', function () {
+ it('should skip all suite specs', function (done) {
+ run('pending/skip-sync-beforeEach.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 2);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+ });
+
+ describe('asynchronous skip()', function () {
+ describe('in spec', function () {
+ it('should immediately skip the spec and run all others', function (done) {
+ run('pending/skip-async-spec.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 1);
+ assert.equal(res.stats.passes, 1);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+
+ describe('in before', function () {
+ it('should skip all suite specs', function (done) {
+ run('pending/skip-async-before.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 2);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+
+ describe('in beforeEach', function () {
+ it('should skip all suite specs', function (done) {
+ run('pending/skip-sync-beforeEach.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 2);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/regression.spec.js b/tests/lib/mocha-3.1.2/test/integration/regression.spec.js
new file mode 100644
index 0000000000..ffd17aa979
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/regression.spec.js
@@ -0,0 +1,119 @@
+'use strict';
+
+var assert = require('assert');
+var fs = require('fs');
+var path = require('path');
+var run = require('./helpers').runMocha;
+var runJSON = require('./helpers').runMochaJSON;
+
+describe('regressions', function () {
+ it('issue-1327: should run all 3 specs exactly once', function (done) {
+ var args = [];
+ run('regression/issue-1327.fixture.js', args, function (err, res) {
+ var occurences = function (str) {
+ var pattern = new RegExp(str, 'g');
+ return (res.output.match(pattern) || []).length;
+ };
+
+ assert(!err);
+ assert.equal(occurences('testbody1'), 1);
+ assert.equal(occurences('testbody2'), 1);
+ assert.equal(occurences('testbody3'), 1);
+
+ assert.equal(res.code, 1);
+ done();
+ });
+ });
+
+ it('should not duplicate mocha.opts args in process.argv', function () {
+ var processArgv = process.argv.join('');
+ var mochaOpts = fs.readFileSync(path.join(__dirname, '..', 'mocha.opts'), 'utf-8').split(/[\s]+/).join('');
+ assert.notEqual(processArgv.indexOf(mochaOpts), -1, 'process.argv missing mocha.opts');
+ assert.equal(processArgv.indexOf(mochaOpts), processArgv.lastIndexOf(mochaOpts), 'process.argv contains duplicated mocha.opts');
+ });
+
+ it('issue-1794: Can\'t --require custom UI and use it', function (done) {
+ var simpleUiPath = path.join(__dirname, 'fixtures', 'regression', '1794', 'simple-ui.js');
+ var args = ['--require', simpleUiPath, '--ui', 'simple-ui'];
+ run('regression/1794/issue-1794.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.code, 0, 'Custom UI should be loaded');
+ done();
+ });
+ });
+
+ it('issue-1991: Declarations do not get cleaned up unless you set them to `null` - Memory Leak', function (done) {
+ // on a modern MBP takes ±5 seconds on node 4.0, but on older laptops with node 0.12 ±40 seconds.
+ // Could easily take longer on even weaker machines (Travis-CI containers for example).
+ this.timeout(120000);
+ run('regression/issue-1991.fixture.js', [], function (err, res) {
+ assert(!err);
+ assert.equal(/process out of memory/.test(res.output), false, 'fixture\'s process out of memory!');
+ assert.equal(res.code, 0, 'Runnable fn (it/before[Each]/after[Each]) references should be deleted to avoid memory leaks');
+ done();
+ });
+ });
+
+ describe('issue-2286: after doesn\'t execute if test was skipped in beforeEach', function () {
+ var afterWasRun = false;
+ describe('suite with skipped test for meta test', function () {
+ beforeEach(function () { this.skip(); });
+ after(function () { afterWasRun = true; });
+ it('should be pending', function () {});
+ });
+ after('meta test', function () {
+ afterWasRun.should.be.ok();
+ });
+ });
+
+ it('issue-2315: cannot read property currentRetry of undefined', function (done) {
+ runJSON('regression/issue-2315.js', [], function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 1);
+ assert.equal(res.code, 1);
+ done();
+ });
+ });
+
+ it('issue-2406: should run nested describe.only suites', function (done) {
+ this.timeout(2000);
+ runJSON('regression/issue-2406.fixture.js', [], function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 2);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+
+ it('issue-2417: should not recurse infinitely with .only suites nested within each other', function () {
+ runJSON('regression/issue-2417.fixture.js', [], function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 1);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.code, 0);
+ });
+ });
+
+ it('issue-1417 uncaught exceptions from async specs', function (done) {
+ runJSON('regression/issue-1417.js', [], function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 2);
+
+ assert.equal(res.failures[0].title,
+ 'fails exactly once when a global error is thrown synchronously and done errors');
+ assert.equal(res.failures[0].err.message, 'sync error');
+ assert.equal(res.failures[1].title,
+ 'fails exactly once when a global error is thrown synchronously and done completes');
+ assert.equal(res.failures[1].err.message, 'sync error');
+ assert.equal(res.code, 2);
+ done();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/reporters.spec.js b/tests/lib/mocha-3.1.2/test/integration/reporters.spec.js
new file mode 100644
index 0000000000..5cfee57037
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/reporters.spec.js
@@ -0,0 +1,63 @@
+'use strict';
+
+var assert = require('assert');
+var os = require('os');
+var fs = require('fs');
+var crypto = require('crypto');
+var path = require('path');
+var run = require('./helpers').runMocha;
+
+describe('reporters', function () {
+ describe('markdown', function () {
+ var res;
+
+ before(function (done) {
+ run('passing.fixture.js', ['--reporter', 'markdown'], function (err, result) {
+ res = result;
+ done(err);
+ });
+ });
+
+ it('does not exceed maximum callstack (issue: 1875)', function () {
+ assert(res.output.indexOf('RangeError') === -1, 'Threw RangeError');
+ });
+
+ it('contains spec src', function () {
+ var src = [
+ '```js',
+ 'assert(true);',
+ '```'
+ ].join('\n');
+
+ assert(res.output.indexOf(src) !== -1, 'No assert found');
+ });
+ });
+
+ describe('xunit', function () {
+ it('prints test cases with --reporter-options output (issue: 1864)', function (done) {
+ var randomStr = crypto.randomBytes(8).toString('hex');
+ var tmpDir = os.tmpDir().replace(new RegExp(path.sep + '$'), '');
+ var tmpFile = tmpDir + path.sep + 'test-issue-1864-' + randomStr + '.xml';
+
+ var args = ['--reporter=xunit', '--reporter-options', 'output=' + tmpFile];
+ var expectedOutput = [
+ '<testcase classname="suite" name="test1" time="',
+ '<testcase classname="suite" name="test2" time="',
+ '</testsuite>'
+ ];
+
+ run('passing.fixture.js', args, function (err, result) {
+ if (err) return done(err);
+
+ var xml = fs.readFileSync(tmpFile, 'utf8');
+ fs.unlinkSync(tmpFile);
+
+ expectedOutput.forEach(function (line) {
+ assert(xml.indexOf(line) !== -1, 'XML did not contain ' + line);
+ });
+
+ done(err);
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/retries.spec.js b/tests/lib/mocha-3.1.2/test/integration/retries.spec.js
new file mode 100644
index 0000000000..28ed702c5f
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/retries.spec.js
@@ -0,0 +1,108 @@
+'use strict';
+
+var assert = require('assert');
+var helpers = require('./helpers');
+var args = [];
+var bang = require('../../lib/reporters/base').symbols.bang;
+
+describe('retries', function () {
+ it('are ran in correct order', function (done) {
+ helpers.runMocha('retries/hooks.fixture.js', args, function (err, res) {
+ var lines, expected;
+
+ assert(!err);
+
+ lines = res.output.split(helpers.splitRegExp).map(function (line) {
+ return line.trim();
+ }).filter(function (line) {
+ return line.length;
+ }).slice(0, -1);
+
+ expected = [
+ 'before',
+ 'before each 0',
+ 'TEST 0',
+ 'after each 1',
+ 'before each 1',
+ 'TEST 1',
+ 'after each 2',
+ 'before each 2',
+ 'TEST 2',
+ 'after each 3',
+ 'before each 3',
+ 'TEST 3',
+ 'after each 4',
+ 'before each 4',
+ 'TEST 4',
+ bang + 'after each 5',
+ 'after'
+ ];
+
+ expected.forEach(function (line, i) {
+ assert.equal(lines[i], line);
+ });
+
+ assert.equal(res.code, 1);
+ done();
+ });
+ });
+
+ it('should exit early if test passes', function (done) {
+ helpers.runMochaJSON('retries/early-pass.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.passes, 1);
+ assert.equal(res.stats.failures, 0);
+ assert.equal(res.tests[0].currentRetry, 1);
+ assert.equal(res.stats.tests, 1);
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+
+ it('should let test override', function (done) {
+ helpers.runMochaJSON('retries/nested.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 1);
+ assert.equal(res.stats.tests, 1);
+ assert.equal(res.tests[0].currentRetry, 1);
+ assert.equal(res.code, 1);
+ done();
+ });
+ });
+
+ it('should not hang w/ async test', function (done) {
+ helpers.runMocha('retries/async.fixture.js', args, function (err, res) {
+ var lines, expected;
+
+ assert(!err);
+
+ lines = res.output.split(helpers.splitRegExp).map(function (line) {
+ return line.trim();
+ }).filter(function (line) {
+ return line.length;
+ }).slice(0, -1);
+
+ expected = [
+ 'before',
+ 'before each 0',
+ 'TEST 0',
+ 'after each 1',
+ 'before each 1',
+ 'TEST 1',
+ 'after each 2',
+ 'before each 2',
+ 'TEST 2',
+ 'after each 3',
+ 'after'
+ ];
+
+ expected.forEach(function (line, i) {
+ assert.equal(lines[i], line);
+ });
+
+ assert.equal(res.code, 0);
+ done();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/suite.spec.js b/tests/lib/mocha-3.1.2/test/integration/suite.spec.js
new file mode 100644
index 0000000000..171a929ed1
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/suite.spec.js
@@ -0,0 +1,43 @@
+'use strict';
+
+var assert = require('assert');
+var run = require('./helpers').runMocha;
+var args = [];
+
+describe('suite w/no callback', function () {
+ this.timeout(1000);
+ it('should throw a helpful error message when a callback for suite is not supplied', function (done) {
+ run('suite/suite-no-callback.fixture.js', args, function (err, res) {
+ assert(!err);
+ var result = res.output.match(/no callback was supplied/) || [];
+ assert.equal(result.length, 1);
+ done();
+ });
+ });
+});
+
+describe('skipped suite w/no callback', function () {
+ this.timeout(1000);
+ it('should not throw an error when a callback for skipped suite is not supplied', function (done) {
+ run('suite/suite-skipped-no-callback.fixture.js', args, function (err, res) {
+ assert(!err);
+ var pattern = new RegExp('Error', 'g');
+ var result = res.output.match(pattern) || [];
+ assert.equal(result.length, 0);
+ done();
+ });
+ });
+});
+
+describe('skipped suite w/ callback', function () {
+ this.timeout(1000);
+ it('should not throw an error when a callback for skipped suite is supplied', function (done) {
+ run('suite/suite-skipped-callback.fixture.js', args, function (err, res) {
+ assert(!err);
+ var pattern = new RegExp('Error', 'g');
+ var result = res.output.match(pattern) || [];
+ assert.equal(result.length, 0);
+ done();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/timeout.spec.js b/tests/lib/mocha-3.1.2/test/integration/timeout.spec.js
new file mode 100644
index 0000000000..4e0f989e86
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/timeout.spec.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var assert = require('assert');
+var run = require('./helpers').runMochaJSON;
+var args = [];
+
+describe('this.timeout()', function () {
+ it('is respected by sync and async suites', function (done) {
+ run('timeout.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 2);
+ assert.equal(res.code, 2);
+ done();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/integration/uncaught.spec.js b/tests/lib/mocha-3.1.2/test/integration/uncaught.spec.js
new file mode 100644
index 0000000000..92e39c195e
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/integration/uncaught.spec.js
@@ -0,0 +1,37 @@
+'use strict';
+
+var assert = require('assert');
+var run = require('./helpers').runMochaJSON;
+var args = [];
+
+describe('uncaught exceptions', function () {
+ it('handles uncaught exceptions from hooks', function (done) {
+ run('uncaught-hook.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 1);
+
+ assert.equal(res.failures[0].fullTitle,
+ 'uncaught "before each" hook');
+ assert.equal(res.code, 1);
+ done();
+ });
+ });
+
+ it('handles uncaught exceptions from async specs', function (done) {
+ run('uncaught.fixture.js', args, function (err, res) {
+ assert(!err);
+ assert.equal(res.stats.pending, 0);
+ assert.equal(res.stats.passes, 0);
+ assert.equal(res.stats.failures, 2);
+
+ assert.equal(res.failures[0].title,
+ 'fails exactly once when a global error is thrown first');
+ assert.equal(res.failures[1].title,
+ 'fails exactly once when a global error is thrown second');
+ assert.equal(res.code, 2);
+ done();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/jsapi/index.js b/tests/lib/mocha-3.1.2/test/jsapi/index.js
new file mode 100644
index 0000000000..42133578e0
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/jsapi/index.js
@@ -0,0 +1,30 @@
+'use strict';
+
+var Mocha = require('../../');
+
+var mocha = new Mocha({
+ ui: 'bdd',
+ globals: ['okGlobalA', 'okGlobalB', 'okGlobalC', 'callback*'],
+ // ignoreLeaks: true,
+ growl: true
+});
+
+// mocha.reporter('spec');
+require('should');
+
+mocha.addFile('test/suite.spec.js');
+mocha.addFile('test/runner.spec.js');
+mocha.addFile('test/runnable.spec.js');
+mocha.addFile('test/hook-sync.spec.js');
+mocha.addFile('test/hook-sync-nested.spec.js');
+mocha.addFile('test/hook-async.spec.js');
+mocha.addFile('test/acceptance/duration.spec.js');
+mocha.addFile('test/acceptance/fs.spec.js');
+mocha.addFile('test/acceptance/globals.spec.js');
+mocha.addFile('test/acceptance/timeout.spec.js');
+
+mocha.run(function () {
+ console.log('done');
+}).on('pass', function (test) {
+ // console.log('... %s', test.title);
+});
diff --git a/tests/lib/mocha-3.1.2/test/mocha.opts b/tests/lib/mocha-3.1.2/test/mocha.opts
new file mode 100644
index 0000000000..36146eb65e
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/mocha.opts
@@ -0,0 +1,8 @@
+--require should
+--require ./test/setup
+--reporter dot
+--ui bdd
+--globals okGlobalA,okGlobalB
+--globals okGlobalC
+--globals callback*
+--timeout 200
diff --git a/tests/lib/mocha-3.1.2/test/mocha.spec.js b/tests/lib/mocha-3.1.2/test/mocha.spec.js
new file mode 100644
index 0000000000..618742cdbd
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/mocha.spec.js
@@ -0,0 +1,35 @@
+'use strict';
+
+var Mocha = require('../');
+var Test = Mocha.Test;
+
+describe('Mocha', function () {
+ var blankOpts = { reporter: function () {} }; // no output
+
+ describe('.run(fn)', function () {
+ it('should not raise errors if callback was not provided', function () {
+ var mocha = new Mocha(blankOpts);
+ mocha.run();
+ });
+
+ it('should execute the callback when complete', function (done) {
+ var mocha = new Mocha(blankOpts);
+ mocha.run(function () {
+ done();
+ });
+ });
+
+ it('should execute the callback with the number of failures ' +
+ 'as parameter', function (done) {
+ var mocha = new Mocha(blankOpts);
+ var failingTest = new Test('failing test', function () {
+ throw new Error('such fail');
+ });
+ mocha.suite.addTest(failingTest);
+ mocha.run(function (failures) {
+ failures.should.equal(1);
+ done();
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/ms.spec.js b/tests/lib/mocha-3.1.2/test/ms.spec.js
new file mode 100644
index 0000000000..26f5c30209
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/ms.spec.js
@@ -0,0 +1,82 @@
+'use strict';
+var ms = require('../lib/ms');
+
+describe('.ms()', function () {
+ // Helpers
+ var time = {
+ minutes: function (n) { return n * 60 * 1000; },
+ hours: function (n) { return n * this.minutes(60); },
+ days: function (n) { return n * this.hours(24); },
+ years: function (n) { return n * this.days(365.25); }
+ };
+ describe('get a value that less than 1 second', function () {
+ it('should return milliseconds representation', function () {
+ ms(200).should.equal('200ms');
+ ms(30).should.equal('30ms');
+ ms(2000).should.not.equal('2000ms');
+ });
+ });
+
+ describe('seconds representation', function () {
+ it('should return short format', function () {
+ ms(2000).should.equal('2s');
+ });
+
+ it('should return long format', function () {
+ ms(2000, { long: true }).should.equal('2 seconds');
+ ms(1000, { long: true }).should.equal('1 second');
+ ms(1010, { long: true }).should.equal('1 second');
+ });
+ });
+
+ describe('minutess representation', function () {
+ it('should return short format', function () {
+ ms(time.minutes(1)).should.equal('1m');
+ });
+
+ it('should return long format', function () {
+ ms(time.minutes(1), { long: true }).should.equal('1 minute');
+ ms(time.minutes(3), { long: true }).should.equal('3 minutes');
+ });
+ });
+
+ describe('hours representation', function () {
+ it('should return short format', function () {
+ ms(time.hours(1)).should.equal('1h');
+ });
+
+ it('should return long format', function () {
+ ms(time.hours(1), { long: true }).should.equal('1 hour');
+ ms(time.hours(3), { long: true }).should.equal('3 hours');
+ });
+ });
+
+ describe('days representation', function () {
+ it('should return short format', function () {
+ ms(time.days(1)).should.equal('1d');
+ });
+
+ it('should return long format', function () {
+ ms(time.days(1), { long: true }).should.equal('1 day');
+ ms(time.days(3), { long: true }).should.equal('3 days');
+ });
+ });
+
+ describe('Getting string value', function () {
+ it('should return the milliseconds representation(Number)', function () {
+ ms('1 second').should.equal(1000);
+
+ ms('1 minute').should.equal(time.minutes(1));
+ ms('6 minutes').should.equal(time.minutes(6));
+
+ ms('1 hour').should.equal(time.hours(1));
+ ms('5 hours').should.equal(time.hours(5));
+
+ ms('1 day').should.equal(time.days(1));
+ ms('3 days').should.equal(time.days(3));
+
+ ms('1 year').should.equal(time.years(1));
+ ms('2 years').should.equal(time.years(2));
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/reporters/base.spec.js b/tests/lib/mocha-3.1.2/test/reporters/base.spec.js
new file mode 100644
index 0000000000..6282d882ff
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/reporters/base.spec.js
@@ -0,0 +1,213 @@
+'use strict';
+
+var assert = require('assert');
+
+var Base = require('../../lib/reporters/base');
+var Assert = require('assert').AssertionError;
+
+function makeTest (err) {
+ return {
+ err: err,
+ fullTitle: function () {
+ return 'test title';
+ }
+ };
+}
+
+describe('Base reporter', function () {
+ var stdout;
+ var stdoutWrite;
+ var useColors;
+
+ beforeEach(function () {
+ stdout = [];
+ stdoutWrite = process.stdout.write;
+ process.stdout.write = function (string) {
+ stdout.push(string);
+ };
+ useColors = Base.useColors;
+ Base.useColors = false;
+ });
+
+ afterEach(function () {
+ process.stdout.write = stdoutWrite;
+ Base.useColors = useColors;
+ });
+
+ describe('showDiff', function () {
+ it('should show diffs by default', function () {
+ var err = new Assert({ actual: 'foo', expected: 'bar' });
+ var errOut;
+
+ var test = makeTest(err);
+
+ Base.list([test]);
+
+ errOut = stdout.join('\n');
+ errOut.should.match(/\- actual/);
+ errOut.should.match(/\+ expected/);
+ });
+
+ it('should show diffs if property set to `true`', function () {
+ var err = new Assert({ actual: 'foo', expected: 'bar' });
+ var errOut;
+
+ err.showDiff = true;
+ var test = makeTest(err);
+
+ Base.list([test]);
+
+ errOut = stdout.join('\n');
+ errOut.should.match(/\- actual/);
+ errOut.should.match(/\+ expected/);
+ });
+
+ it('should not show diffs when showDiff property set to `false`', function () {
+ var err = new Assert({ actual: 'foo', expected: 'bar' });
+ var errOut;
+
+ err.showDiff = false;
+ var test = makeTest(err);
+
+ Base.list([test]);
+
+ errOut = stdout.join('\n');
+ errOut.should.not.match(/\- actual/);
+ errOut.should.not.match(/\+ expected/);
+ });
+
+ it('should not show diffs when expected is not defined', function () {
+ var err = new Error('ouch');
+ var errOut;
+
+ var test = makeTest(err);
+
+ Base.list([test]);
+
+ errOut = stdout.join('\n');
+ errOut.should.not.match(/\- actual/);
+ errOut.should.not.match(/\+ expected/);
+ });
+ });
+
+ describe('Getting two strings', function () {
+ // Fix regression V1.2.1(see: issue #1241)
+ it('should show strings diff as is', function () {
+ var err = new Error('test');
+ var errOut;
+
+ err.actual = 'foo\nbar';
+ err.expected = 'foo\nbaz';
+ err.showDiff = true;
+ var test = makeTest(err);
+
+ Base.list([test]);
+
+ errOut = stdout.join('\n');
+
+ errOut.should.not.match(/"foo\\nbar"/);
+ errOut.should.match(/foo/).and.match(/bar/);
+ errOut.should.match(/test/);
+ errOut.should.match(/actual/);
+ errOut.should.match(/expected/);
+ });
+ });
+
+ it('should stringify objects', function () {
+ var err = new Error('test');
+ var errOut;
+
+ err.actual = {key: 'a1'};
+ err.expected = {key: 'e1'};
+ err.showDiff = true;
+ var test = makeTest(err);
+
+ Base.list([test]);
+
+ errOut = stdout.join('\n');
+ errOut.should.match(/"key"/);
+ errOut.should.match(/test/);
+ errOut.should.match(/\- actual/);
+ errOut.should.match(/\+ expected/);
+ });
+
+ it('should stringify Object.create(null)', function () {
+ var err = new Error('test');
+ var errOut;
+
+ err.actual = Object.create(null);
+ err.actual.hasOwnProperty = 1;
+ err.expected = Object.create(null);
+ err.expected.hasOwnProperty = 2;
+ err.showDiff = true;
+ var test = makeTest(err);
+
+ Base.list([test]);
+
+ errOut = stdout.join('\n');
+ errOut.should.match(/"hasOwnProperty"/);
+ errOut.should.match(/test/);
+ errOut.should.match(/\- actual/);
+ errOut.should.match(/\+ expected/);
+ });
+
+ it('should handle error messages that are not strings', function () {
+ var errOut;
+
+ try {
+ assert(false, true);
+ } catch (err) {
+ err.actual = false;
+ err.expected = true;
+ err.showDiff = true;
+ var test = makeTest(err);
+
+ Base.list([test]);
+
+ errOut = stdout.join('\n');
+ errOut.should.match(/\+true/);
+ errOut.should.match(/\-false/);
+ errOut.should.match(/\- actual/);
+ errOut.should.match(/\+ expected/);
+ }
+ });
+
+ it('should remove message from stack', function () {
+ var err = {
+ message: 'Error',
+ stack: 'Error\nfoo\nbar',
+ showDiff: false
+ };
+ var test = makeTest(err);
+
+ Base.list([test]);
+
+ var errOut = stdout.join('\n').trim();
+ errOut.should.equal('1) test title:\n Error\n foo\n bar');
+ });
+
+ it('should use the inspect() property if `message` is not set', function () {
+ var err = {
+ showDiff: false,
+ inspect: function () { return 'an error happened'; }
+ };
+ var test = makeTest(err);
+ Base.list([test]);
+ var errOut = stdout.join('\n').trim();
+ errOut.should.equal('1) test title:\n an error happened');
+ });
+
+ it('should not modify stack if it does not contain message', function () {
+ var err = {
+ message: 'Error',
+ stack: 'foo\nbar',
+ showDiff: false
+ };
+ var test = makeTest(err);
+
+ Base.list([test]);
+
+ var errOut = stdout.join('\n').trim();
+ errOut.should.equal('1) test title:\n Error\n foo\n bar');
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/reporters/json.spec.js b/tests/lib/mocha-3.1.2/test/reporters/json.spec.js
new file mode 100644
index 0000000000..74151fdc8b
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/reporters/json.spec.js
@@ -0,0 +1,63 @@
+'use strict';
+
+var Mocha = require('../../');
+var Suite = Mocha.Suite;
+var Runner = Mocha.Runner;
+var Test = Mocha.Test;
+
+describe('json reporter', function () {
+ var suite, runner;
+
+ beforeEach(function () {
+ var mocha = new Mocha({
+ reporter: 'json'
+ });
+ suite = new Suite('JSON suite', 'root');
+ runner = new Runner(suite);
+ /* eslint no-unused-vars: off */
+ var mochaReporter = new mocha._reporter(runner);
+ });
+
+ it('should have 1 test failure', function (done) {
+ var testTitle = 'json test 1';
+ var error = { message: 'oh shit' };
+
+ suite.addTest(new Test(testTitle, function (done) {
+ done(new Error(error.message));
+ }));
+
+ runner.run(function (failureCount) {
+ failureCount.should.be.exactly(1);
+ runner.should.have.property('testResults');
+ runner.testResults.should.have.property('failures');
+ runner.testResults.failures.should.be.an.instanceOf(Array);
+ runner.testResults.failures.should.have.a.lengthOf(1);
+
+ var failure = runner.testResults.failures[0];
+ failure.should.have.property('title', testTitle);
+ failure.err.message.should.equal(error.message);
+ failure.should.have.properties('err');
+
+ done();
+ });
+ });
+
+ it('should have 1 test pending', function (done) {
+ var testTitle = 'json test 1';
+
+ suite.addTest(new Test(testTitle));
+
+ runner.run(function (failureCount) {
+ failureCount.should.be.exactly(0);
+ runner.should.have.property('testResults');
+ runner.testResults.should.have.property('pending');
+ runner.testResults.pending.should.be.an.instanceOf(Array);
+ runner.testResults.pending.should.have.a.lengthOf(1);
+
+ var pending = runner.testResults.pending[0];
+ pending.should.have.property('title', testTitle);
+
+ done();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/reporters/nyan.spec.js b/tests/lib/mocha-3.1.2/test/reporters/nyan.spec.js
new file mode 100644
index 0000000000..07c455efd3
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/reporters/nyan.spec.js
@@ -0,0 +1,31 @@
+'use strict';
+
+var reporters = require('../../').reporters;
+var NyanCat = reporters.Nyan;
+
+describe('nyan face', function () {
+ it('nyan face:(x .x) when "failures" at least one', function () {
+ var nyanCat = new NyanCat({on: function () {}});
+ nyanCat.stats = { passes: 2, pending: 1, failures: 1 };
+ nyanCat.face().should.equal('( x .x)');
+ });
+
+ it('expected nyan face:(x .x) when "pending" at least one and no failing', function () {
+ var nyanCat = new NyanCat({on: function () {}});
+ nyanCat.stats = { passes: 2, pending: 1, failures: 0 };
+ nyanCat.face().should.equal('( o .o)');
+ });
+
+ it('expected nyan face:(^ .^) when "passing" only', function () {
+ var nyanCat = new NyanCat({on: function () {}});
+ nyanCat.stats = { passes: 1, pending: 0, failures: 0 };
+ nyanCat.face().should.equal('( ^ .^)');
+ });
+
+ it('nyan face:(- .-) when otherwise', function (done) {
+ var nyanCat = new NyanCat({on: function () {}});
+ nyanCat.stats = { passes: 0, pending: 0, failures: 0 };
+ nyanCat.face().should.equal('( - .-)');
+ done();
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/runnable.spec.js b/tests/lib/mocha-3.1.2/test/runnable.spec.js
new file mode 100644
index 0000000000..67cfcca38a
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/runnable.spec.js
@@ -0,0 +1,466 @@
+'use strict';
+
+var mocha = require('../');
+var utils = mocha.utils;
+var Runnable = mocha.Runnable;
+
+describe('Runnable(title, fn)', function () {
+ // For every test we poison the global time-related methods.
+ // runnable.js etc. should keep its own local copy, in order to fix GH-237.
+ // NB: we can't poison global.Date because the normal implementation of
+ // global.setTimeout uses it [1] so if the runnable.js keeps a copy of
+ // global.setTimeout (like it's supposed to), that will blow up.
+ // [1]: https://github.com/joyent/node/blob/7fc835afe362ebd30a0dbec81d3360bd24525222/lib/timers.js#L74
+ var setTimeout = global.setTimeout;
+ var setInterval = global.setInterval;
+ var clearTimeout = global.clearTimeout;
+ var clearInterval = global.clearInterval;
+
+ function poisonPill () {
+ throw new Error("Don't use global time-related stuff.");
+ }
+
+ beforeEach(function () {
+ global.setTimeout =
+ global.setInterval =
+ global.clearTimeout =
+ global.clearInterval = poisonPill;
+ });
+
+ afterEach(function () {
+ global.setTimeout = setTimeout;
+ global.setInterval = setInterval;
+ global.clearTimeout = clearTimeout;
+ global.clearInterval = clearInterval;
+ });
+
+ describe('#timeout(ms)', function () {
+ it('should set the timeout', function () {
+ var run = new Runnable();
+ run.timeout(1000);
+ run.timeout().should.equal(1000);
+ });
+ });
+
+ describe('#timeout(ms) when ms>2^31', function () {
+ it('should set disabled', function () {
+ var run = new Runnable();
+ run.timeout(1e10);
+ run.enableTimeouts().should.be.false;
+ });
+ });
+
+ describe('#enableTimeouts(enabled)', function () {
+ it('should set enabled', function () {
+ var run = new Runnable();
+ run.enableTimeouts(false);
+ run.enableTimeouts().should.equal(false);
+ });
+ });
+
+ describe('#slow(ms)', function () {
+ var run;
+
+ beforeEach(function () {
+ run = new Runnable();
+ });
+
+ it('should set the slow threshold', function () {
+ run.slow(100);
+ run.slow().should.equal(100);
+ });
+
+ it('should not set the slow threshold if the parameter is not passed', function () {
+ run.slow();
+ run.slow().should.equal(75);
+ });
+
+ it('should not set the slow threshold if the parameter is undefined', function () {
+ run.slow(undefined);
+ run.slow().should.equal(75);
+ });
+ });
+
+ describe('.title', function () {
+ it('should be present', function () {
+ new Runnable('foo').title.should.equal('foo');
+ });
+ });
+
+ describe('when arity >= 1', function () {
+ it('should be .async', function () {
+ var run = new Runnable('foo', function (done) {});
+ run.async.should.equal(1);
+ run.sync.should.be.false();
+ });
+ });
+
+ describe('when arity == 0', function () {
+ it('should be .sync', function () {
+ var run = new Runnable('foo', function () {});
+ run.async.should.be.equal(0);
+ run.sync.should.be.true();
+ });
+ });
+
+ describe('#globals', function () {
+ it('should allow for whitelisting globals', function (done) {
+ var test = new Runnable('foo', function () {});
+ test.async.should.be.equal(0);
+ test.sync.should.be.true();
+ test.globals(['foobar']);
+ test.run(done);
+ });
+ });
+
+ describe('#retries(n)', function () {
+ it('should set the number of retries', function () {
+ var run = new Runnable();
+ run.retries(1);
+ run.retries().should.equal(1);
+ });
+ });
+
+ describe('.run(fn)', function () {
+ describe('when .pending', function () {
+ it('should not invoke the callback', function (done) {
+ var test = new Runnable('foo', function () {
+ throw new Error('should not be called');
+ });
+
+ test.pending = true;
+ test.run(done);
+ });
+ });
+
+ describe('when sync', function () {
+ describe('without error', function () {
+ it('should invoke the callback', function (done) {
+ var calls = 0;
+ var test = new Runnable('foo', function () {
+ ++calls;
+ });
+
+ test.run(function (err) {
+ calls.should.equal(1);
+ test.duration.should.be.type('number');
+ done(err);
+ });
+ });
+ });
+
+ describe('when an exception is thrown', function () {
+ it('should invoke the callback', function (done) {
+ var calls = 0;
+ var test = new Runnable('foo', function () {
+ ++calls;
+ throw new Error('fail');
+ });
+
+ test.run(function (err) {
+ calls.should.equal(1);
+ err.message.should.equal('fail');
+ done();
+ });
+ });
+ });
+
+ describe('when an exception is thrown and is allowed to remain uncaught', function () {
+ it('throws an error when it is allowed', function (done) {
+ var test = new Runnable('foo', function () {
+ throw new Error('fail');
+ });
+ test.allowUncaught = true;
+ function fail () {
+ test.run(function () {});
+ }
+ fail.should.throw('fail');
+ done();
+ });
+ });
+ });
+
+ describe('when timeouts are disabled', function () {
+ it('should not error with timeout', function (done) {
+ var test = new Runnable('foo', function (done) {
+ setTimeout(process.nextTick.bind(undefined, done), 2);
+ });
+ test.timeout(1);
+ test.enableTimeouts(false);
+ test.run(done);
+ });
+ });
+
+ describe('when async', function () {
+ describe('without error', function () {
+ it('should invoke the callback', function (done) {
+ var test = new Runnable('foo', function (done) {
+ process.nextTick(done);
+ });
+
+ test.run(done);
+ });
+ });
+
+ describe('when the callback is invoked several times', function () {
+ describe('without an error', function () {
+ it('should emit a single "error" event', function (done) {
+ var calls = 0;
+ var errCalls = 0;
+
+ var test = new Runnable('foo', function (done) {
+ process.nextTick(done);
+ process.nextTick(done);
+ process.nextTick(done);
+ process.nextTick(done);
+ });
+
+ test.on('error', function (err) {
+ ++errCalls;
+ err.message.should.equal('done() called multiple times');
+ calls.should.equal(1);
+ errCalls.should.equal(1);
+ done();
+ });
+
+ test.run(function () {
+ ++calls;
+ });
+ });
+ });
+
+ describe('with an error', function () {
+ it('should emit a single "error" event', function (done) {
+ var calls = 0;
+ var errCalls = 0;
+
+ var test = new Runnable('foo', function (done) {
+ done(new Error('fail'));
+ process.nextTick(done);
+ done(new Error('fail'));
+ process.nextTick(done);
+ process.nextTick(done);
+ });
+
+ test.on('error', function (err) {
+ ++errCalls;
+ err.message.should.equal('fail');
+ calls.should.equal(1);
+ errCalls.should.equal(1);
+ done();
+ });
+
+ test.run(function () {
+ ++calls;
+ });
+ });
+ });
+ });
+
+ describe('when an exception is thrown', function () {
+ it('should invoke the callback', function (done) {
+ var test = new Runnable('foo', function (done) {
+ throw new Error('fail');
+ });
+
+ test.run(function (err) {
+ err.message.should.equal('fail');
+ done();
+ });
+ });
+
+ it('should not throw its own exception if passed a non-object', function (done) {
+ var test = new Runnable('foo', function (done) {
+ /* eslint no-throw-literal: off */
+ throw null;
+ });
+
+ test.run(function (err) {
+ err.message.should.equal(utils.undefinedError().message);
+ done();
+ });
+ });
+ });
+
+ describe('when an exception is thrown and is allowed to remain uncaught', function () {
+ it('throws an error when it is allowed', function (done) {
+ var test = new Runnable('foo', function (done) {
+ throw new Error('fail');
+ });
+ test.allowUncaught = true;
+ function fail () {
+ test.run(function () {});
+ }
+ fail.should.throw('fail');
+ done();
+ });
+ });
+
+ describe('when an error is passed', function () {
+ it('should invoke the callback', function (done) {
+ var test = new Runnable('foo', function (done) {
+ done(new Error('fail'));
+ });
+
+ test.run(function (err) {
+ err.message.should.equal('fail');
+ done();
+ });
+ });
+ });
+
+ describe('when done() is invoked with a non-Error object', function () {
+ it('should invoke the callback', function (done) {
+ var test = new Runnable('foo', function (done) {
+ done({ error: 'Test error' });
+ });
+
+ test.run(function (err) {
+ err.message.should.equal('done() invoked with non-Error: {"error":"Test error"}');
+ done();
+ });
+ });
+ });
+
+ describe('when done() is invoked with a string', function () {
+ it('should invoke the callback', function (done) {
+ var test = new Runnable('foo', function (done) {
+ done('Test error');
+ });
+
+ test.run(function (err) {
+ err.message.should.equal('done() invoked with non-Error: Test error');
+ done();
+ });
+ });
+ });
+
+ it('should allow updating the timeout', function (done) {
+ var callCount = 0;
+ var increment = function () {
+ callCount++;
+ };
+ var test = new Runnable('foo', function (done) {
+ setTimeout(increment, 1);
+ setTimeout(increment, 100);
+ });
+ test.timeout(10);
+ test.run(function (err) {
+ err.should.be.ok();
+ callCount.should.equal(1);
+ done();
+ });
+ });
+
+ it('should allow a timeout of 0');
+ });
+
+ describe('when fn returns a promise', function () {
+ describe('when the promise is fulfilled with no value', function () {
+ var fulfilledPromise = {
+ then: function (fulfilled, rejected) {
+ process.nextTick(fulfilled);
+ }
+ };
+
+ it('should invoke the callback', function (done) {
+ var test = new Runnable('foo', function () {
+ return fulfilledPromise;
+ });
+
+ test.run(done);
+ });
+ });
+
+ describe('when the promise is fulfilled with a value', function () {
+ var fulfilledPromise = {
+ then: function (fulfilled, rejected) {
+ process.nextTick(function () {
+ fulfilled({});
+ });
+ }
+ };
+
+ it('should invoke the callback', function (done) {
+ var test = new Runnable('foo', function () {
+ return fulfilledPromise;
+ });
+
+ test.run(done);
+ });
+ });
+
+ describe('when the promise is rejected', function () {
+ var expectedErr = new Error('fail');
+ var rejectedPromise = {
+ then: function (fulfilled, rejected) {
+ process.nextTick(function () {
+ rejected(expectedErr);
+ });
+ }
+ };
+
+ it('should invoke the callback', function (done) {
+ var test = new Runnable('foo', function () {
+ return rejectedPromise;
+ });
+
+ test.run(function (err) {
+ err.should.equal(expectedErr);
+ done();
+ });
+ });
+ });
+
+ describe('when the promise is rejected without a reason', function () {
+ var expectedErr = new Error('Promise rejected with no or falsy reason');
+ var rejectedPromise = {
+ then: function (fulfilled, rejected) {
+ process.nextTick(function () {
+ rejected();
+ });
+ }
+ };
+
+ it('should invoke the callback', function (done) {
+ var test = new Runnable('foo', function () {
+ return rejectedPromise;
+ });
+
+ test.run(function (err) {
+ err.should.eql(expectedErr);
+ done();
+ });
+ });
+ });
+
+ describe('when the promise takes too long to settle', function () {
+ var foreverPendingPromise = {
+ then: function () { }
+ };
+
+ it('should give the timeout error', function (done) {
+ var test = new Runnable('foo', function () {
+ return foreverPendingPromise;
+ });
+
+ test.timeout(10);
+ test.run(function (err) {
+ err.should.be.ok();
+ done();
+ });
+ });
+ });
+ });
+
+ describe('when fn returns a non-promise', function () {
+ it('should invoke the callback', function (done) {
+ var test = new Runnable('foo', function () {
+ return { then: 'i ran my tests' };
+ });
+
+ test.run(done);
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/runner.spec.js b/tests/lib/mocha-3.1.2/test/runner.spec.js
new file mode 100644
index 0000000000..7c69846ec8
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/runner.spec.js
@@ -0,0 +1,436 @@
+'use strict';
+
+var mocha = require('../');
+var Suite = mocha.Suite;
+var Runner = mocha.Runner;
+var Test = mocha.Test;
+var Hook = mocha.Hook;
+var path = require('path');
+var noop = mocha.utils.noop;
+
+describe('Runner', function () {
+ var suite;
+ var runner;
+
+ beforeEach(function () {
+ suite = new Suite('Suite', 'root');
+ runner = new Runner(suite);
+ });
+
+ describe('.grep()', function () {
+ it('should update the runner.total with number of matched tests', function () {
+ suite.addTest(new Test('im a test about lions', noop));
+ suite.addTest(new Test('im another test about lions', noop));
+ suite.addTest(new Test('im a test about bears', noop));
+ var newRunner = new Runner(suite);
+ newRunner.grep(/lions/);
+ newRunner.total.should.equal(2);
+ });
+
+ it('should update the runner.total with number of matched tests when inverted', function () {
+ suite.addTest(new Test('im a test about lions', noop));
+ suite.addTest(new Test('im another test about lions', noop));
+ suite.addTest(new Test('im a test about bears', noop));
+ var newRunner = new Runner(suite);
+ newRunner.grep(/lions/, true);
+ newRunner.total.should.equal(1);
+ });
+ });
+
+ describe('.grepTotal()', function () {
+ it('should return the total number of matched tests', function () {
+ suite.addTest(new Test('im a test about lions', noop));
+ suite.addTest(new Test('im another test about lions', noop));
+ suite.addTest(new Test('im a test about bears', noop));
+ runner.grep(/lions/);
+ runner.grepTotal(suite).should.equal(2);
+ });
+
+ it('should return the total number of matched tests when inverted', function () {
+ suite.addTest(new Test('im a test about lions', noop));
+ suite.addTest(new Test('im another test about lions', noop));
+ suite.addTest(new Test('im a test about bears', noop));
+ runner.grep(/lions/, true);
+ runner.grepTotal(suite).should.equal(1);
+ });
+ });
+
+ describe('.globalProps()', function () {
+ it('should include common non enumerable globals', function () {
+ var props = runner.globalProps();
+ props.should.containEql('setTimeout');
+ props.should.containEql('clearTimeout');
+ props.should.containEql('setInterval');
+ props.should.containEql('clearInterval');
+ props.should.containEql('Date');
+ props.should.containEql('XMLHttpRequest');
+ });
+ });
+
+ describe('.globals()', function () {
+ it('should default to the known globals', function () {
+ runner.globals().length.should.be.above(16);
+ });
+
+ it('should white-list globals', function () {
+ runner.globals(['foo', 'bar']);
+ runner.globals().should.containEql('foo');
+ runner.globals().should.containEql('bar');
+ });
+ });
+
+ describe('.checkGlobals(test)', function () {
+ it('should allow variables that match a wildcard', function (done) {
+ runner.globals(['foo*', 'giz*']);
+ global.foo = 'baz';
+ global.gizmo = 'quux';
+ runner.checkGlobals();
+ delete global.foo;
+ delete global.gizmo;
+ done();
+ });
+
+ it('should emit "fail" when a new global is introduced', function (done) {
+ var test = new Test('im a test', noop);
+ runner.checkGlobals();
+ global.foo = 'bar';
+ runner.on('fail', function (_test, err) {
+ _test.should.equal(test);
+ err.message.should.equal('global leak detected: foo');
+ delete global.foo;
+ done();
+ });
+ runner.checkGlobals(test);
+ });
+
+ it('should emit "fail" when a single new disallowed global is introduced after a single extra global is allowed', function (done) {
+ var doneCalled = false;
+ runner.globals('good');
+ global.bad = 1;
+ runner.on('fail', function () {
+ delete global.bad;
+ done();
+ doneCalled = true;
+ });
+ runner.checkGlobals(new Test('yet another test', noop));
+ if (!doneCalled) {
+ done(Error('Expected test failure did not occur.'));
+ }
+ });
+
+ it('should not fail when a new common global is introduced', function () {
+ // verify that the prop isn't enumerable
+ delete global.XMLHttpRequest;
+ global.propertyIsEnumerable('XMLHttpRequest').should.not.be.ok();
+
+ // create a new runner and keep a reference to the test.
+ var test = new Test('im a test about bears', noop);
+ suite.addTest(test);
+ var newRunner = new Runner(suite);
+
+ // make the prop enumerable again.
+ global.XMLHttpRequest = function () {};
+ global.propertyIsEnumerable('XMLHttpRequest').should.be.ok();
+
+ // verify the test hasn't failed.
+ newRunner.checkGlobals(test);
+ test.should.not.have.key('state');
+
+ // clean up our global space.
+ delete global.XMLHttpRequest;
+ });
+
+ it('should pluralize the error message when several are introduced', function (done) {
+ var test = new Test('im a test', noop);
+ runner.checkGlobals();
+ global.foo = 'bar';
+ global.bar = 'baz';
+ runner.on('fail', function (_test, err) {
+ _test.should.equal(test);
+ err.message.should.equal('global leaks detected: foo, bar');
+ delete global.foo;
+ delete global.bar;
+ done();
+ });
+ runner.checkGlobals(test);
+ });
+
+ it('should respect per test whitelisted globals', function () {
+ var test = new Test('im a test about lions', noop);
+ test.globals(['foo']);
+
+ suite.addTest(test);
+ var runner = new Runner(suite);
+
+ global.foo = 'bar';
+
+ // verify the test hasn't failed.
+ runner.checkGlobals(test);
+ test.should.not.have.key('state');
+
+ delete global.foo;
+ });
+
+ it('should respect per test whitelisted globals but still detect other leaks', function (done) {
+ var test = new Test('im a test about lions', noop);
+ test.globals(['foo']);
+
+ suite.addTest(test);
+
+ global.foo = 'bar';
+ global.bar = 'baz';
+ runner.on('fail', function (test, err) {
+ test.title.should.equal('im a test about lions');
+ err.message.should.equal('global leak detected: bar');
+ delete global.foo;
+ done();
+ });
+ runner.checkGlobals(test);
+ });
+
+ it('should emit "fail" when a global beginning with d is introduced', function (done) {
+ global.derp = 'bar';
+ runner.on('fail', function () {
+ delete global.derp;
+ done();
+ });
+ runner.checkGlobals(new Test('herp', function () {}));
+ });
+ });
+
+ describe('.hook(name, fn)', function () {
+ it('should execute hooks after failed test if suite bail is true', function (done) {
+ runner.fail(new Test('failed test', noop));
+ suite.bail(true);
+ suite.afterEach(function () {
+ suite.afterAll(function () {
+ done();
+ });
+ });
+ runner.hook('afterEach', function () {});
+ runner.hook('afterAll', function () {});
+ });
+ });
+
+ describe('.fail(test, err)', function () {
+ it('should increment .failures', function () {
+ runner.failures.should.equal(0);
+ runner.fail(new Test('one', noop), {});
+ runner.failures.should.equal(1);
+ runner.fail(new Test('two', noop), {});
+ runner.failures.should.equal(2);
+ });
+
+ it('should set test.state to "failed"', function () {
+ var test = new Test('some test', noop);
+ runner.fail(test, 'some error');
+ test.state.should.equal('failed');
+ });
+
+ it('should emit "fail"', function (done) {
+ var test = new Test('some other test', noop);
+ var err = {};
+ runner.on('fail', function (test, err) {
+ test.should.equal(test);
+ err.should.equal(err);
+ done();
+ });
+ runner.fail(test, err);
+ });
+
+ it('should emit a helpful message when failed with a string', function (done) {
+ var test = new Test('helpful test', noop);
+ var err = 'string';
+ runner.on('fail', function (test, err) {
+ err.message.should.equal('the string "string" was thrown, throw an Error :)');
+ done();
+ });
+ runner.fail(test, err);
+ });
+
+ it('should emit a the error when failed with an Error instance', function (done) {
+ var test = new Test('a test', noop);
+ var err = new Error('an error message');
+ runner.on('fail', function (test, err) {
+ err.message.should.equal('an error message');
+ done();
+ });
+ runner.fail(test, err);
+ });
+
+ it('should emit the error when failed with an Error-like object', function (done) {
+ var test = new Test('a test', noop);
+ var err = { message: 'an error message' };
+ runner.on('fail', function (test, err) {
+ err.message.should.equal('an error message');
+ done();
+ });
+ runner.fail(test, err);
+ });
+
+ it('should emit a helpful message when failed with an Object', function (done) {
+ var test = new Test('a test', noop);
+ var err = { x: 1 };
+ runner.on('fail', function (test, err) {
+ err.message.should.equal('the object {\n "x": 1\n} was thrown, throw an Error :)');
+ done();
+ });
+ runner.fail(test, err);
+ });
+
+ it('should emit a helpful message when failed with an Array', function (done) {
+ var test = new Test('a test', noop);
+ var err = [
+ 1,
+ 2
+ ];
+ runner.on('fail', function (test, err) {
+ err.message.should.equal('the array [\n 1\n 2\n] was thrown, throw an Error :)');
+ done();
+ });
+ runner.fail(test, err);
+ });
+
+ it('should recover if the error stack is not writable', function (done) {
+ var err = new Error('not evil');
+ Object.defineProperty(err, 'stack', {
+ value: err.stack
+ });
+ var test = new Test('a test', noop);
+
+ runner.on('fail', function (test, err) {
+ err.message.should.equal('not evil');
+ done();
+ });
+
+ runner.fail(test, err);
+ });
+ });
+
+ describe('.failHook(hook, err)', function () {
+ it('should increment .failures', function () {
+ runner.failures.should.equal(0);
+ runner.failHook(new Test('fail hook 1', noop), {});
+ runner.failures.should.equal(1);
+ runner.failHook(new Test('fail hook 2', noop), {});
+ runner.failures.should.equal(2);
+ });
+
+ it('should augment hook title with current test title', function () {
+ var hook = new Hook('"before each" hook');
+ hook.ctx = { currentTest: new Test('should behave', noop) };
+
+ runner.failHook(hook, {});
+ hook.title.should.equal('"before each" hook for "should behave"');
+
+ hook.ctx.currentTest = new Test('should obey', noop);
+ runner.failHook(hook, {});
+ hook.title.should.equal('"before each" hook for "should obey"');
+ });
+
+ it('should emit "fail"', function (done) {
+ var hook = new Hook();
+ var err = {};
+ runner.on('fail', function (hook, err) {
+ hook.should.equal(hook);
+ err.should.equal(err);
+ done();
+ });
+ runner.failHook(hook, err);
+ });
+
+ it('should emit "end" if suite bail is true', function (done) {
+ var hook = new Hook();
+ var err = {};
+ suite.bail(true);
+ runner.on('end', done);
+ runner.failHook(hook, err);
+ });
+
+ it('should not emit "end" if suite bail is not true', function (done) {
+ var hook = new Hook();
+ var err = {};
+ suite.bail(false);
+ runner.on('end', function () {
+ throw new Error('"end" was emit, but the bail is false');
+ });
+ runner.failHook(hook, err);
+ done();
+ });
+ });
+
+ describe('allowUncaught', function () {
+ it('should allow unhandled errors to propagate through', function (done) {
+ var newRunner = new Runner(suite);
+ newRunner.allowUncaught = true;
+ newRunner.test = new Test('failing test', function () {
+ throw new Error('allow unhandled errors');
+ });
+ function fail () {
+ newRunner.runTest();
+ }
+ fail.should.throw('allow unhandled errors');
+ done();
+ });
+ });
+
+ describe('stackTrace', function () {
+ var stack = [
+ 'AssertionError: foo bar',
+ 'at EventEmitter.<anonymous> (/usr/local/dev/test.js:16:12)',
+ 'at Context.<anonymous> (/usr/local/dev/test.js:19:5)',
+ 'Test.Runnable.run (/usr/local/lib/node_modules/mocha/lib/runnable.js:244:7)',
+ 'Runner.runTest (/usr/local/lib/node_modules/mocha/lib/runner.js:374:10)',
+ '/usr/local/lib/node_modules/mocha/lib/runner.js:452:12',
+ 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:299:14)',
+ '/usr/local/lib/node_modules/mocha/lib/runner.js:309:7',
+ 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:248:23)',
+ 'Immediate._onImmediate (/usr/local/lib/node_modules/mocha/lib/runner.js:276:5)',
+ 'at processImmediate [as _immediateCallback] (timers.js:321:17)'
+ ];
+
+ describe('shortStackTrace', function () {
+ beforeEach(function () {
+ if (path.sep !== '/') {
+ this.skip();
+ }
+ });
+
+ it('should prettify the stack-trace', function (done) {
+ var hook = new Hook();
+ var err = new Error();
+ // Fake stack-trace
+ err.stack = stack.join('\n');
+
+ runner.on('fail', function (hook, err) {
+ err.stack.should.equal(stack.slice(0, 3).join('\n'));
+ done();
+ });
+ runner.failHook(hook, err);
+ });
+ });
+
+ describe('longStackTrace', function () {
+ beforeEach(function () {
+ if (path.sep !== '/') {
+ this.skip();
+ }
+ });
+
+ it('should display the full stack-trace', function (done) {
+ var hook = new Hook();
+ var err = new Error();
+ // Fake stack-trace
+ err.stack = stack.join('\n');
+ // Add --stack-trace option
+ runner.fullStackTrace = true;
+
+ runner.on('fail', function (hook, err) {
+ err.stack.should.equal(stack.join('\n'));
+ done();
+ });
+ runner.failHook(hook, err);
+ });
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/sanity/sanity.spec.js b/tests/lib/mocha-3.1.2/test/sanity/sanity.spec.js
new file mode 100644
index 0000000000..b918f1c4f9
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/sanity/sanity.spec.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var assert = require('assert');
+
+describe('a production installation of Mocha', function () {
+ it('should be able to execute a test', function () {
+ assert.ok(true);
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/setup.js b/tests/lib/mocha-3.1.2/test/setup.js
new file mode 100644
index 0000000000..0ffe34c7e5
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/setup.js
@@ -0,0 +1,4 @@
+'use strict';
+
+global.expect = require('expect.js');
+global.assert = require('assert');
diff --git a/tests/lib/mocha-3.1.2/test/suite.spec.js b/tests/lib/mocha-3.1.2/test/suite.spec.js
new file mode 100644
index 0000000000..4cb62dd290
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/suite.spec.js
@@ -0,0 +1,440 @@
+'use strict';
+
+var mocha = require('../');
+var Suite = mocha.Suite;
+var Test = mocha.Test;
+
+describe('Suite', function () {
+ describe('.clone()', function () {
+ beforeEach(function () {
+ this.suite = new Suite('To be cloned');
+ this.suite._timeout = 3043;
+ this.suite._slow = 101;
+ this.suite._bail = true;
+ this.suite.suites.push(1);
+ this.suite.tests.push('hello');
+ this.suite._beforeEach.push(2);
+ this.suite._beforeAll.push(3);
+ this.suite._afterEach.push(4);
+ this.suite._afterAll.push(5);
+ });
+
+ it('should copy the title', function () {
+ this.suite.clone().title.should.equal('To be cloned');
+ });
+
+ it('should copy the timeout value', function () {
+ this.suite.clone().timeout().should.equal(3043);
+ });
+
+ it('should copy the slow value', function () {
+ this.suite.clone().slow().should.equal(101);
+ });
+
+ it('should copy the bail value', function () {
+ this.suite.clone().bail().should.be.true();
+ });
+
+ it('should not copy the values from the suites array', function () {
+ this.suite.clone().suites.should.be.empty();
+ });
+
+ it('should not copy the values from the tests array', function () {
+ this.suite.clone().tests.should.be.empty();
+ });
+
+ it('should not copy the values from the _beforeEach array', function () {
+ this.suite.clone()._beforeEach.should.be.empty();
+ });
+
+ it('should not copy the values from the _beforeAll array', function () {
+ this.suite.clone()._beforeAll.should.be.empty();
+ });
+
+ it('should not copy the values from the _afterEach array', function () {
+ this.suite.clone()._afterEach.should.be.empty();
+ });
+
+ it('should not copy the values from the _afterAll array', function () {
+ this.suite.clone()._afterAll.should.be.empty();
+ });
+ });
+
+ describe('.timeout()', function () {
+ beforeEach(function () {
+ this.suite = new Suite('A Suite');
+ });
+
+ describe('when no argument is passed', function () {
+ it('should return the timeout value', function () {
+ this.suite.timeout().should.equal(2000);
+ });
+ });
+
+ describe('when argument is passed', function () {
+ it('should return the Suite object', function () {
+ var newSuite = this.suite.timeout(5000);
+ newSuite.timeout().should.equal(5000);
+ });
+ });
+ });
+
+ describe('.slow()', function () {
+ beforeEach(function () {
+ this.suite = new Suite('A Suite');
+ });
+
+ describe('when given a string', function () {
+ it('should parse it', function () {
+ this.suite.slow('5 seconds');
+ this.suite.slow().should.equal(5000);
+ });
+ });
+
+ describe('when no argument is passed', function () {
+ it('should return the slow value', function () {
+ this.suite.slow().should.equal(75);
+ });
+ });
+
+ describe('when argument is passed', function () {
+ it('should return the Suite object', function () {
+ var newSuite = this.suite.slow(5000);
+ newSuite.slow().should.equal(5000);
+ });
+ });
+ });
+
+ describe('.bail()', function () {
+ beforeEach(function () {
+ this.suite = new Suite('A Suite');
+ this.suite._bail = true;
+ });
+
+ describe('when no argument is passed', function () {
+ it('should return the bail value', function () {
+ this.suite.bail().should.be.true();
+ });
+ });
+
+ describe('when argument is passed', function () {
+ it('should return the Suite object', function () {
+ var newSuite = this.suite.bail(false);
+ newSuite.bail().should.be.false();
+ });
+ });
+ });
+
+ describe('.beforeAll()', function () {
+ beforeEach(function () {
+ this.suite = new Suite('A Suite');
+ });
+
+ describe('wraps the passed in function in a Hook', function () {
+ it('adds it to _beforeAll', function () {
+ var fn = function () {};
+ this.suite.beforeAll(fn);
+
+ this.suite._beforeAll.should.have.length(1);
+ var beforeAllItem = this.suite._beforeAll[0];
+ beforeAllItem.title.should.match(/^"before all" hook/);
+ beforeAllItem.fn.should.equal(fn);
+ });
+
+ it('appends title to hook', function () {
+ var fn = function () {};
+ this.suite.beforeAll('test', fn);
+
+ this.suite._beforeAll.should.have.length(1);
+ var beforeAllItem = this.suite._beforeAll[0];
+ beforeAllItem.title.should.equal('"before all" hook: test');
+ beforeAllItem.fn.should.equal(fn);
+
+ function namedFn () {}
+ this.suite.beforeAll(namedFn);
+ this.suite._beforeAll.should.have.length(2);
+ beforeAllItem = this.suite._beforeAll[1];
+ beforeAllItem.title.should.equal('"before all" hook: namedFn');
+ beforeAllItem.fn.should.equal(namedFn);
+ });
+ });
+ });
+
+ describe('.afterAll()', function () {
+ beforeEach(function () {
+ this.suite = new Suite('A Suite');
+ });
+
+ describe('wraps the passed in function in a Hook', function () {
+ it('adds it to _afterAll', function () {
+ var fn = function () {};
+ this.suite.afterAll(fn);
+
+ this.suite._afterAll.should.have.length(1);
+ var afterAllItem = this.suite._afterAll[0];
+ afterAllItem.title.should.match(/^"after all" hook/);
+ afterAllItem.fn.should.equal(fn);
+ });
+ it('appends title to hook', function () {
+ var fn = function () {};
+ this.suite.afterAll('test', fn);
+
+ this.suite._afterAll.should.have.length(1);
+ var beforeAllItem = this.suite._afterAll[0];
+ beforeAllItem.title.should.equal('"after all" hook: test');
+ beforeAllItem.fn.should.equal(fn);
+
+ function namedFn () {}
+ this.suite.afterAll(namedFn);
+ this.suite._afterAll.should.have.length(2);
+ beforeAllItem = this.suite._afterAll[1];
+ beforeAllItem.title.should.equal('"after all" hook: namedFn');
+ beforeAllItem.fn.should.equal(namedFn);
+ });
+ });
+ });
+
+ describe('.beforeEach()', function () {
+ beforeEach(function () {
+ this.suite = new Suite('A Suite');
+ });
+
+ describe('wraps the passed in function in a Hook', function () {
+ it('adds it to _beforeEach', function () {
+ var fn = function () {};
+ this.suite.beforeEach(fn);
+
+ this.suite._beforeEach.should.have.length(1);
+ var beforeEachItem = this.suite._beforeEach[0];
+ beforeEachItem.title.should.match(/^"before each" hook/);
+ beforeEachItem.fn.should.equal(fn);
+ });
+
+ it('appends title to hook', function () {
+ var fn = function () {};
+ this.suite.beforeEach('test', fn);
+
+ this.suite._beforeEach.should.have.length(1);
+ var beforeAllItem = this.suite._beforeEach[0];
+ beforeAllItem.title.should.equal('"before each" hook: test');
+ beforeAllItem.fn.should.equal(fn);
+
+ function namedFn () {}
+ this.suite.beforeEach(namedFn);
+ this.suite._beforeEach.should.have.length(2);
+ beforeAllItem = this.suite._beforeEach[1];
+ beforeAllItem.title.should.equal('"before each" hook: namedFn');
+ beforeAllItem.fn.should.equal(namedFn);
+ });
+ });
+ });
+
+ describe('.afterEach()', function () {
+ beforeEach(function () {
+ this.suite = new Suite('A Suite');
+ });
+
+ describe('wraps the passed in function in a Hook', function () {
+ it('adds it to _afterEach', function () {
+ var fn = function () {};
+ this.suite.afterEach(fn);
+
+ this.suite._afterEach.should.have.length(1);
+ var afterEachItem = this.suite._afterEach[0];
+ afterEachItem.title.should.match(/^"after each" hook/);
+ afterEachItem.fn.should.equal(fn);
+ });
+
+ it('appends title to hook', function () {
+ var fn = function () {};
+ this.suite.afterEach('test', fn);
+
+ this.suite._afterEach.should.have.length(1);
+ var beforeAllItem = this.suite._afterEach[0];
+ beforeAllItem.title.should.equal('"after each" hook: test');
+ beforeAllItem.fn.should.equal(fn);
+
+ function namedFn () {}
+ this.suite.afterEach(namedFn);
+ this.suite._afterEach.should.have.length(2);
+ beforeAllItem = this.suite._afterEach[1];
+ beforeAllItem.title.should.equal('"after each" hook: namedFn');
+ beforeAllItem.fn.should.equal(namedFn);
+ });
+ });
+ });
+
+ describe('.addSuite()', function () {
+ beforeEach(function () {
+ this.first = new Suite('First suite');
+ this.first.timeout(4002);
+ this.first.slow(200);
+ this.second = new Suite('Second suite');
+ this.first.addSuite(this.second);
+ });
+
+ it('sets the parent on the added Suite', function () {
+ this.second.parent.should.equal(this.first);
+ });
+
+ it('copies the timeout value', function () {
+ this.second.timeout().should.equal(4002);
+ });
+
+ it('copies the slow value', function () {
+ this.second.slow().should.equal(200);
+ });
+
+ it('adds the suite to the suites collection', function () {
+ this.first.suites.should.have.length(1);
+ this.first.suites[0].should.equal(this.second);
+ });
+
+ it('treats suite as pending if its parent is pending', function () {
+ this.first.pending = true;
+ this.second.isPending.should.be.true;
+ });
+ });
+
+ // describe('.addTest()', function(){
+ // beforeEach(function(){
+ // this.suite = new Suite('A Suite', new Context);
+ // this.suite.timeout(4002);
+ // this.test = new Test('test');
+ // this.suite.addTest(this.test);
+ // });
+ //
+ // it('sets the parent on the added test', function(){
+ // this.test.parent.should.equal(this.suite);
+ // });
+ //
+ // it('copies the timeout value', function(){
+ // this.test.timeout().should.equal(4002);
+ // });
+ //
+ // it('adds the test to the tests collection', function(){
+ // this.suite.tests.should.have.length(1);
+ // this.suite.tests[0].should.equal(this.test);
+ // });
+ // });
+
+ describe('.fullTitle()', function () {
+ beforeEach(function () {
+ this.suite = new Suite('A Suite');
+ });
+
+ describe('when there is no parent', function () {
+ it('returns the suite title', function () {
+ this.suite.fullTitle().should.equal('A Suite');
+ });
+ });
+
+ describe('when there is a parent', function () {
+ it('returns the combination of parent\'s and suite\'s title', function () {
+ var parentSuite = new Suite('I am a parent');
+ parentSuite.addSuite(this.suite);
+ this.suite.fullTitle().should.equal('I am a parent A Suite');
+ });
+ });
+ });
+
+ describe('.total()', function () {
+ beforeEach(function () {
+ this.suite = new Suite('A Suite');
+ });
+
+ describe('when there are no nested suites or tests', function () {
+ it('should return 0', function () {
+ this.suite.total().should.equal(0);
+ });
+ });
+
+ describe('when there are several tests in the suite', function () {
+ it('should return the number', function () {
+ this.suite.addTest(new Test('a child test'));
+ this.suite.addTest(new Test('another child test'));
+ this.suite.total().should.equal(2);
+ });
+ });
+ });
+
+ describe('.eachTest(fn)', function () {
+ beforeEach(function () {
+ this.suite = new Suite('A Suite');
+ });
+
+ describe('when there are no nested suites or tests', function () {
+ it('should return 0', function () {
+ var n = 0;
+ function fn () { n++; }
+ this.suite.eachTest(fn);
+ n.should.equal(0);
+ });
+ });
+
+ describe('when there are several tests in the suite', function () {
+ it('should return the number', function () {
+ this.suite.addTest(new Test('a child test'));
+ this.suite.addTest(new Test('another child test'));
+
+ var n = 0;
+ function fn () { n++; }
+ this.suite.eachTest(fn);
+ n.should.equal(2);
+ });
+ });
+
+ describe('when there are several levels of nested suites', function () {
+ it('should return the number', function () {
+ this.suite.addTest(new Test('a child test'));
+ var suite = new Suite('a child suite');
+ suite.addTest(new Test('a test in a child suite'));
+ this.suite.addSuite(suite);
+
+ var n = 0;
+ function fn () { n++; }
+ this.suite.eachTest(fn);
+ n.should.equal(2);
+ });
+ });
+ });
+
+ describe('initialization', function () {
+ /* eslint no-new: off */
+ it('should throw an error if the title isn\'t a string', function () {
+ (function () {
+ new Suite(undefined, 'root');
+ }).should.throw();
+
+ (function () {
+ new Suite(function () {}, 'root');
+ }).should.throw();
+ });
+
+ it('should not throw if the title is a string', function () {
+ (function () {
+ new Suite('Bdd suite', 'root');
+ }).should.not.throw();
+ });
+ });
+});
+
+describe('Test', function () {
+ describe('initialization', function () {
+ it('should throw an error if the title isn\'t a string', function () {
+ (function () {
+ new Test(function () {});
+ }).should.throw();
+
+ (function () {
+ new Test(undefined, function () {});
+ }).should.throw();
+ });
+
+ it('should not throw if the title is a string', function () {
+ (function () {
+ new Test('test-case', function () {});
+ }).should.not.throw();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/test.spec.js b/tests/lib/mocha-3.1.2/test/test.spec.js
new file mode 100644
index 0000000000..73c09b3b06
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/test.spec.js
@@ -0,0 +1,77 @@
+'use strict';
+
+var mocha = require('../');
+var should = require('should');
+var Test = mocha.Test;
+
+describe('Test', function () {
+ describe('.clone()', function () {
+ beforeEach(function () {
+ this._test = new Test('To be cloned', function () {});
+ this._test._timeout = 3043;
+ this._test._slow = 101;
+ this._test._enableTimeouts = true;
+ this._test._retries = 3;
+ this._test._currentRetry = 1;
+ this._test._allowedGlobals = ['foo'];
+ this._test.parent = 'foo';
+ this._test.file = 'bar';
+ });
+
+ it('should copy the title', function () {
+ this._test.clone().title.should.equal('To be cloned');
+ });
+
+ it('should copy the timeout value', function () {
+ this._test.clone().timeout().should.equal(3043);
+ });
+
+ it('should copy the slow value', function () {
+ this._test.clone().slow().should.equal(101);
+ });
+
+ it('should copy the enableTimeouts value', function () {
+ this._test.clone().enableTimeouts().should.be.true();
+ });
+
+ it('should copy the retries value', function () {
+ this._test.clone().retries().should.equal(3);
+ });
+
+ it('should copy the currentRetry value', function () {
+ this._test.clone().currentRetry().should.equal(1);
+ });
+
+ it('should copy the globals value', function () {
+ this._test.clone().globals().should.not.be.empty();
+ });
+
+ it('should copy the parent value', function () {
+ this._test.clone().parent.should.equal('foo');
+ });
+
+ it('should copy the file value', function () {
+ this._test.clone().file.should.equal('bar');
+ });
+ });
+
+ describe('.isPending()', function () {
+ beforeEach(function () {
+ this._test = new Test('Is it skipped', function () {});
+ });
+
+ it('should not be pending by default', function () {
+ should(this._test.isPending()).not.be.ok();
+ });
+
+ it('should be pending when marked as such', function () {
+ this._test.pending = true;
+ should(this._test.isPending()).be.ok();
+ });
+
+ it('should be pending when its parent is pending', function () {
+ this._test.parent = { isPending: function () { return true; } };
+ should(this._test.isPending()).be.ok();
+ });
+ });
+});
diff --git a/tests/lib/mocha-3.1.2/test/utils.spec.js b/tests/lib/mocha-3.1.2/test/utils.spec.js
new file mode 100644
index 0000000000..ccfd861a78
--- /dev/null
+++ b/tests/lib/mocha-3.1.2/test/utils.spec.js
@@ -0,0 +1,263 @@
+'use strict';
+
+var mocha = require('..');
+var utils = mocha.utils;
+var path = require('path');
+var JSON = require('json3');
+
+describe('utils', function () {
+ describe('.clean()', function () {
+ var clean = utils.clean;
+ it('should remove the wrapping function declaration', function () {
+ clean('function (one, two, three) {\n//code\n}').should.equal('//code');
+ });
+
+ it('should handle newlines in the function declaration', function () {
+ clean('function (one, two, three)\n {\n//code\n}').should.equal('//code');
+ });
+
+ it('should remove space character indentation from the function body', function () {
+ clean(' //line1\n //line2').should.equal('//line1\n //line2');
+ });
+
+ it('should remove tab character indentation from the function body', function () {
+ clean('\t//line1\n\t\t//line2').should.equal('//line1\n\t//line2');
+ });
+
+ it('should handle functions with tabs in their declarations', function () {
+ clean('function\t(\t)\t{\n//code\n}').should.equal('//code');
+ });
+
+ it('should handle named functions without space after name', function () {
+ clean('function withName() {\n//code\n}').should.equal('//code');
+ });
+
+ it('should handle named functions with space after name', function () {
+ clean('function withName () {\n//code\n}').should.equal('//code');
+ });
+
+ it('should handle functions with no space between the end and the closing brace', function () {
+ clean('function() {/*code*/}').should.equal('/*code*/');
+ });
+
+ it('should handle functions with parentheses in the same line', function () {
+ clean('function() { if (true) { /* code */ } }').should.equal('if (true) { /* code */ }');
+ });
+
+ it('should handle empty functions', function () {
+ clean('function() {}').should.equal('');
+ });
+ });
+
+ describe('.isBuffer()', function () {
+ var isBuffer = utils.isBuffer;
+ it('should test if object is a Buffer', function () {
+ isBuffer(new Buffer([0x01])).should.equal(true);
+ isBuffer({}).should.equal(false);
+ });
+ });
+
+ describe('.map()', function () {
+ var map = utils.map;
+ it('should behave same as Array.prototype.map', function () {
+ var arr = [1, 2, 3];
+ map(arr, JSON.stringify).should.eql(arr.map(JSON.stringify));
+ });
+
+ it('should call the callback with 3 arguments[currentValue, index, array]', function () {
+ var index = 0;
+ map([1, 2, 3], function (e, i, arr) {
+ e.should.equal(arr[index]);
+ i.should.equal(index++);
+ });
+ });
+
+ it('should apply with the given scope', function () {
+ var scope = {};
+ map(['a', 'b', 'c'], function () {
+ this.should.equal(scope);
+ }, scope);
+ });
+ });
+
+ describe('.parseQuery()', function () {
+ var parseQuery = utils.parseQuery;
+ it('should get queryString and return key-value object', function () {
+ parseQuery('?foo=1&bar=2&baz=3').should.eql({
+ foo: '1',
+ bar: '2',
+ baz: '3'
+ });
+
+ parseQuery('?r1=^@(?!.*\\)$)&r2=m{2}&r3=^co.*').should.eql({
+ r1: '^@(?!.*\\)$)',
+ r2: 'm{2}',
+ r3: '^co.*'
+ });
+ });
+ });
+
+ describe('.stackTraceFilter()', function () {
+ describe('on node', function () {
+ var filter = utils.stackTraceFilter();
+
+ describe('on POSIX OS', function () {
+ before(function () {
+ if (path.sep !== '/') {
+ this.skip();
+ }
+ });
+
+ it('should get a stack-trace as a string and prettify it', function () {
+ var stack = [
+ 'AssertionError: foo bar',
+ 'at EventEmitter.<anonymous> (/usr/local/dev/test.js:16:12)',
+ 'at Context.<anonymous> (/usr/local/dev/test.js:19:5)',
+ 'Test.Runnable.run (/usr/local/lib/node_modules/mocha/lib/runnable.js:244:7)',
+ 'Runner.runTest (/usr/local/lib/node_modules/mocha/lib/runner.js:374:10)',
+ '/usr/local/lib/node_modules/mocha/lib/runner.js:452:12',
+ 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:299:14)',
+ '/usr/local/lib/node_modules/mocha/lib/runner.js:309:7',
+ 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:248:23)',
+ 'Immediate._onImmediate (/usr/local/lib/node_modules/mocha/lib/runner.js:276:5)',
+ 'at processImmediate [as _immediateCallback] (timers.js:321:17)'
+ ];
+ filter(stack.join('\n'))
+ .should
+ .equal(stack.slice(0, 3)
+ .join('\n'));
+
+ stack = [
+ 'AssertionError: bar baz',
+ 'at /usr/local/dev/some-test-file.js:25:8',
+ 'at tryCatcher (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/util.js:24:31)',
+ 'at Promise._resolveFromResolver (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:439:31)',
+ 'at new Promise (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:53:37)',
+ 'at yourFunction (/usr/local/dev/own/tmp/test1.js:24:13)',
+ 'at Context.<anonymous> (/usr/local/dev/some-test-file:30:4)',
+ 'Test.Runnable.run (/usr/local/lib/node_modules/mocha/lib/runnable.js:218:15)',
+ 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:248:23)',
+ 'Immediate._onImmediate (/usr/local/lib/node_modules/mocha/lib/runner.js:276:5)',
+ 'at processImmediate [as _immediateCallback] (timers.js:321:17)'
+ ];
+
+ filter(stack.join('\n'))
+ .should
+ .equal(stack.slice(0, 7)
+ .join('\n'));
+ });
+
+ it('does not ignore other bower_components and components',
+ function () {
+ var stack = [
+ 'Error: failed',
+ 'at assert (index.html:11:26)',
+ 'at Context.<anonymous> (test.js:17:18)',
+ 'at bower_components/should/should.js:4827:7',
+ 'at next (file:///.../bower_components/should/should.js:4766:23)',
+ 'at components/should/5.0.0/should.js:4827:7',
+ 'at next (file:///.../components/should/5.0.0/should.js:4766:23)',
+ 'at file:///.../bower_components/mocha/mocha.js:4794:5',
+ 'at timeslice (.../components/mocha/mocha.js:6218:27)',
+ 'at Test.require.register.Runnable.run (file:///.../components/mochajs/mocha/2.1.0/mocha.js:4463:15)',
+ 'at Runner.require.register.Runner.runTest (file:///.../components/mochajs/mocha/2.1.0/mocha.js:4892:10)',
+ 'at file:///.../components/mochajs/mocha/2.1.0/mocha.js:4970:12',
+ 'at next (file:///.../components/mochajs/mocha/2.1.0/mocha.js:4817:14)'
+ ];
+ filter(stack.join('\n'))
+ .should
+ .equal(stack.slice(0, 7)
+ .join('\n'));
+ });
+
+ it('should replace absolute with relative paths', function () {
+ var stack = [
+ 'Error: ' + process.cwd() + '/bla.js has a problem',
+ 'at foo (' + process.cwd() + '/foo/index.js:13:226)',
+ 'at bar (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:11:26)'
+ ];
+
+ var expected = [
+ 'Error: ' + process.cwd() + '/bla.js has a problem',
+ 'at foo (foo/index.js:13:226)',
+ 'at bar (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:11:26)'
+ ];
+
+ filter(stack.join('\n'))
+ .should
+ .equal(expected.join('\n'));
+ });
+ });
+
+ describe('on Windows', function () {
+ before(function () {
+ if (path.sep === '/') {
+ this.skip();
+ }
+ });
+
+ it('should work on Windows', function () {
+ var stack = [
+ 'Error: failed',
+ 'at Context.<anonymous> (C:\\Users\\ishida\\src\\test\\test\\mytest.js:5:9)',
+ 'at callFn (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runnable.js:326:21)',
+ 'at Test.Runnable.run (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runnable.js:319:7)',
+ 'at Runner.runTest (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:422:10)',
+ 'at C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:528:12',
+ 'at next (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:342:14)',
+ 'at C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:352:7',
+ 'at next (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:284:14)',
+ 'at Immediate._onImmediate (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:320:5)'
+ ];
+ filter(stack.join('\n'))
+ .should
+ .equal(stack.slice(0, 2)
+ .join('\n'));
+ });
+ });
+ });
+
+ describe('on browser', function () {
+ var filter;
+ before(function () {
+ global.document = true;
+ global.location = { href: 'localhost:3000/foo/bar/index.html' };
+ filter = utils.stackTraceFilter();
+ });
+ it('does not strip out other bower_components', function () {
+ var stack = [
+ 'Error: failed',
+ 'at assert (index.html:11:26)',
+ 'at Context.<anonymous> (test.js:17:18)',
+ 'at bower_components/should/should.js:4827:7',
+ 'at next (bower_components/should/should.js:4766:23)',
+ 'at components/should/5.0.0/should.js:4827:7',
+ 'at next (components/should/5.0.0/should.js:4766:23)',
+ 'at Runner.require.register.Runner.runTest (node_modules/mocha.js:4892:10)',
+ 'at localhost:3000/foo/bar/node_modules/mocha.js:4970:12',
+ 'at next (node_modules/mocha.js:4817:14)'
+ ];
+ filter(stack.join('\n')).should.equal(stack.slice(0, 7).join('\n'));
+ });
+
+ after(function () {
+ delete global.document;
+ delete global.location;
+ });
+ });
+ });
+
+ describe('.isPromise', function () {
+ it('should return true if the value is Promise-ish', function () {
+ utils.isPromise({then: function () {}}).should.be.true;
+ });
+
+ it('should return false if the value is not an object', function () {
+ utils.isPromise(1).should.be.false;
+ });
+
+ it('should return false if the value is an object w/o a "then" function', function () {
+ utils.isPromise({}).should.be.false;
+ });
+ });
+});