diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..e9067bb70d --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +lib/to-iso-string/ diff --git a/.eslintrc b/.eslintrc index 57574b4fd1..d5c733f79f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -112,12 +112,11 @@ rules: radix: 2 semi: [2, always] semi-spacing: [2, { before: false, after: true }] - space-after-keywords: [2, always] space-before-blocks: [2, always] space-before-function-paren: [2, never] space-in-parens: [2, never] space-infix-ops: 2 - space-return-throw-case: 2 + keyword-spacing: 2 space-unary-ops: [2, { words: true, nonwords: false }] spaced-comment: [2, always, { exceptions: ['!'] }] strict: [0, global] # TODO: Change to error diff --git a/.gitignore b/.gitignore index e36f109724..99fb76a31b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,5 @@ -coverage.html -lib-cov .DS_Store node_modules -test-outputs *.sock testing _mocha.js @@ -15,3 +12,4 @@ lib/browser/diff.js *.diff npm-debug.log* .envrc +.karma/ diff --git a/.travis.yml b/.travis.yml index 29f9bff62d..29b4c419e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,12 +9,19 @@ dist: trusty language: node_js env: - global: PHANTOMJS_CDNURL='https://cnpmjs.org/downloads' + global: + # phantomjs hosts binaries @ bitbucket, which has fairly restrictive + # rate-limiting. pull it from this sketchy site in China instead. + - PHANTOMJS_CDNURL='https://cnpmjs.org/downloads' + # we're going to use s3 to temporarily store Karma test bundles for debugging + - AWS_ACCESS_KEY_ID=AKIAJ3QQTLQXWXYJ6PTA + - secure: k4musDC734E1NFOWaY5qb/l0B9K1cfusFTvMZFayTMs5ubKjeNYCgct2sDSvO5tO7Un935I0sYOOSRPvANPhs8dP1a/8/x0PnwIfnpoCFQCCaI0bWnIQj7nOZ2TaEB/fngZCerCFpNDlzqI6BmaR+XoMvA74v2YD/vVXnzvXNQk= matrix: + fast_finish: true include: - node_js: '6' - env: TARGET='clean lint test-node test-browser' + env: TARGET=test-node - node_js: '5' env: TARGET=test-node - node_js: '4' @@ -27,19 +34,22 @@ matrix: env: TARGET=test-node - node_js: '0.10' env: TARGET=test-node - - node_js: '0.8' - env: TARGET=test-node + - node_js: '6' + env: TARGET=lint + - node_js: '6' + env: TARGET=test-browser S3=1 + +before_install: scripts/travis-before-install.sh + +before_script: scripts/travis-before-script.sh -before_install: - # node 0.8 won't install our dev deps with an out-of-box npm; - # this upgrades it - - node ./scripts/upgrade-npm.js +script: make $TARGET -script: travis_retry make $TARGET +after_script: scripts/travis-after-script.sh notifications: urls: # for gitter - - secure: "nSYqkR0NKB/vB3PsPS+7+U2ZGhP+NbqFncPPZxsGb0TeRvuRL62BemEZGs5+VsajutCN8Dn/yXSIWkYZ6ivZt8xSQ9vk2OnboBMPH/e8P9t+6BBUyIb4ztJuHbsUyx1POYFyukT2TiqRuEGvUUACeXH0OIrWNPt254DipDhe2P0=" + - secure: fUrHenYJs+pTuLtgBRoYyrlyfVekxaIGmLWq7bhUUqBj/7p5eCkQFn13LlPht0/4WWZOiPBcdTN7tKnz3Ho7ATUJhAchvOWDUgL5gtTvOzeCHbPuCvHz/VLK6hMoPdbLA45M864NDLotfHvyh62WgQaVw9iPc80eb+umaDPrYiU= on_success: change on_failure: always diff --git a/CHANGELOG.md b/CHANGELOG.md index 2997f18253..26cffe5e8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,116 @@ +# 3.0.1 / 2016-08-03 + +## :bug: Bug Fix + +- [#2406]: Restore execution of nested `describe.only()` suites ([@not-an-aardvark]) + +[#2406]: https://github.com/mochajs/mocha/issues/2406 +[@not-an-aardvark]: https://github.com/not-an-aardvark + +# 3.0.0 / 2016-07-31 + +## :boom: Breaking Changes + +- :warning: Due to the increasing difficulty of applying security patches made within its dependency tree, as well as looming incompatibilities with Node.js v7.0, **Mocha no longer supports Node.js v0.8**. +- :warning: **Mocha may no longer be installed by versions of `npm` less than `1.4.0`.** Previously, this requirement only affected Mocha's development dependencies. In short, this allows Mocha to depend on packages which have dependencies fixed to major versions (`^`). +- `.only()` is no longer "fuzzy", can be used multiple times, and generally just works like you think it should. :joy: +- To avoid common bugs, when a test injects a callback function (suggesting asynchronous execution), calls it, *and* returns a `Promise`, Mocha will now throw an exception: + + ```js + const assert = require('assert'); + + it('should complete this test', function (done) { + return new Promise(function (resolve) { + assert.ok(true); + resolve(); + }) + .then(done); + }); + ``` + + The above test will fail with `Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.`. +- When a test timeout value *greater than* `2147483648` is specified in any context (`--timeout`, `mocha.setup()`, per-suite, per-test, etc.), the timeout will be *disabled* and the test(s) will be allowed to run indefinitely. This is equivalent to specifying a timeout value of `0`. See [MDN](https://developer.mozilla.org/docs/Web/API/WindowTimers/setTimeout#Maximum_delay_value) for reasoning. +- The `dot` reporter now uses more visually distinctive characters when indicating "pending" and "failed" tests. +- Mocha no longer supports [component](https://www.npmjs.com/package/component). +- The long-forsaken `HTMLCov` and `JSONCov` reporters--and any relationship to the "node-jscoverage" project--have been removed. +- `spec` reporter now omits leading carriage returns (`\r`) in non-TTY environment. + +## :tada: Enhancements + +- [#808]: Allow regular-expression-like strings in `--grep` and browser's `grep` querystring; enables flags such as `i` for case-insensitive matches and `u` for unicode. ([@a8m]) +- [#2000]: Use distinctive characters in `dot` reporter; `,` will denote a "pending" test and `!` will denote a "failing" test. ([@elliottcable]) +- [#1632]: Throw a useful exception when a suite or test lacks a title. ([@a8m]) +- [#1481]: Better `.only()` behavior. ([@a8m]) +- [#2334]: Allow `this.skip()` in async tests and hooks. ([@boneskull]) +- [#1320]: Throw a useful exception when test resolution method is overspecified. ([@jugglinmike]) +- [#2364]: Support `--preserve-symlinks`. ([@rosswarren]) + +## :bug: Bug Fixes + +- [#2259]: Restore ES3 compatibility. Specifically, support an environment lacking `Date.prototype.toISOString()`, `JSON`, or has a non-standard implementation of `JSON`. ([@ndhoule], [@boneskull]) +- [#2286]: Fix `after()` failing to execute if test skipped using `this.skip()` in `beforeEach()`; no longer marks the entire suite as "pending". ([@dasilvacontin], [@boneskull]) +- [#2208]: Fix function name display in `markdown` and `html` (browser) reporters. ([@ScottFreeCode]) +- [#2299]: Fix progress bar in `html` (browser) reporter. ([@AviVahl]) +- [#2307]: Fix `doc` reporter crashing when test fails. ([@jleyba]) +- [#2323]: Ensure browser entry point (`browser-entry.js`) is published to npm (for use with bundlers). ([@boneskull]) +- [#2310]: Ensure custom reporter with an absolute path works in Windows. ([@silentcloud]) +- [#2311]: Fix problem wherein calling `this.slow()` without a value would blast any previously set value. ([@boneskull]) +- [#1813]: Ensure Mocha's own test suite will run in Windows. ([@tswaters], [@TimothyGu], [@boneskull]) +- [#2317]: Ensure all interfaces are displayed in `--help` on CLI. ([@ScottFreeCode]) +- [#1644]: Don't exhibit undefined behavior when calling `this.timeout()` with very large values ([@callumacrae], [@boneskull]) +- [#2361]: Don't truncate name of thrown anonymous exception. ([@boneskull]) +- [#2367]: Fix invalid CSS. ([@bensontrent]) +- [#2401]: Remove carriage return before each test line in spec reporter. ([@Munter]) + +## :nut_and_bolt: Other + +- Upgrade production dependencies to address security advisories (and because now we can): `glob`, `commander`, `escape-string-regexp`, +and `supports-color`. ([@boneskull], [@RobLoach]) +- Add Windows to CI. ([@boneskull], [@TimothyGu]) +- Ensure appropriate `engines` field in `package.json`. ([@shinnn], [@boneskull]) +- [#2348]: Upgrade ESLint to v2 ([@anthony-redfox]) + +We :heart: our [backers and sponsors](https://opencollective.com/mochajs)! + +:shipit: + +[#2401]: https://github.com/mochajs/mocha/pull/2401 +[#2348]: https://github.com/mochajs/mocha/issues/2348 +[#808]: https://github.com/mochajs/mocha/issues/808 +[#2361]: https://github.com/mochajs/mocha/pull/2361 +[#2367]: https://github.com/mochajs/mocha/pull/2367 +[#2364]: https://github.com/mochajs/mocha/pull/2364 +[#1320]: https://github.com/mochajs/mocha/pull/1320 +[#2307]: https://github.com/mochajs/mocha/pull/2307 +[#2259]: https://github.com/mochajs/mocha/pull/2259 +[#2208]: https://github.com/mochajs/mocha/pull/2208 +[#2299]: https://github.com/mochajs/mocha/pull/2299 +[#2286]: https://github.com/mochajs/mocha/issues/2286 +[#1644]: https://github.com/mochajs/mocha/issues/1644 +[#2310]: https://github.com/mochajs/mocha/issues/2310 +[#2311]: https://github.com/mochajs/mocha/issues/2311 +[#2323]: https://github.com/mochajs/mocha/issues/2323 +[#2000]: https://github.com/mochajs/mocha/pull/2000 +[#1632]: https://github.com/mochajs/mocha/issues/1632 +[#1813]: https://github.com/mochajs/mocha/issues/1813 +[#2334]: https://github.com/mochajs/mocha/issues/2334 +[#2317]: https://github.com/mochajs/mocha/issues/2317 +[#1481]: https://github.com/mochajs/mocha/issues/1481 +[@elliottcable]: https://github.com/elliottcable +[@RobLoach]: https://github.com/robloach +[@AviVahl]: https://github.com/avivahl +[@silentcloud]: https://github.com/silentcloud +[@tswaters]: https://github.com/tswaters +[@jleyba]: https://github.com/jleyba +[@TimothyGu]: https://github.com/timothygu +[@callumacrae]: https://github.com/callumacrae +[@shinnn]: https://github.com/shinnn +[@bensontrent]: https://github.com/bensontrent +[@jugglinmike]: https://github.com/jugglinmike +[@rosswarren]: https://github.com/rosswarren +[@anthony-redfox]: https://github.com/anthony-redfox +[@Munter]: https://github.com/munter + # 2.5.3 / 2016-05-25 - [#2112] - Fix HTML reporter regression causing duplicate error output ([@danielstjules] via 6d24063) diff --git a/Makefile b/Makefile index 92daf92a18..73e941ef13 100644 --- a/Makefile +++ b/Makefile @@ -1,97 +1,80 @@ BROWSERIFY := "node_modules/.bin/browserify" ESLINT := "node_modules/.bin/eslint" KARMA := "node_modules/.bin/karma" +MOCHA := "bin/mocha" REPORTER ?= spec TM_BUNDLE = JavaScript\ mocha.tmbundle SRC = $(shell find lib -name "*.js" -type f | sort) TESTS = $(shell find test -name "*.js" -type f | sort) -SUPPORT = $(wildcard support/*.js) all: mocha.js -mocha.js: $(SRC) $(SUPPORT) +mocha.js: $(SRC) browser-entry.js @printf "==> [Browser :: build]\n" - @$(BROWSERIFY) ./browser-entry \ + $(BROWSERIFY) ./browser-entry \ --ignore 'fs' \ --ignore 'glob' \ - --ignore 'jade' \ --ignore 'path' \ - --ignore 'supports-color' \ - --exclude './lib-cov/mocha' > $@ + --ignore 'supports-color' > $@ clean: @printf "==> [Clean]\n" rm -f mocha.js - rm -rf test-outputs - rm -rf lib-cov - rm -f coverage.html - -test-cov: lib-cov - @printf "==> [Test :: Coverage]\n" - @COV=1 $(MAKE) test REPORTER=html-cov > coverage.html - -lib-cov: - @printf "==> [Coverage]\n" - @rm -fr ./$@ - @jscoverage lib $@ lint: @printf "==> [Test :: Lint]\n" - @$(ESLINT) $(SRC) + $(ESLINT) "lib/**/*.js" -test-node: test-bdd test-tdd test-qunit test-exports test-unit test-integration test-jsapi test-compilers test-glob test-requires test-reporters test-only +test-node: test-bdd test-tdd test-qunit test-exports test-unit test-integration test-jsapi test-compilers test-glob test-requires test-reporters test-only test-global-only -test-browser: test-browser-unit test-browser-bdd test-browser-qunit test-browser-tdd test-browser-exports +test-browser: clean mocha.js test-browser-unit test-browser-bdd test-browser-qunit test-browser-tdd test-browser-exports test: lint test-node test-browser -test-browser-unit: mocha.js +test-browser-unit: @printf "==> [Test :: Browser]\n" - @NODE_PATH=. $(KARMA) start + NODE_PATH=. $(KARMA) start test-browser-bdd: @printf "==> [Test :: Browser :: BDD]\n" - @MOCHA_UI=bdd $(MAKE) test-browser-unit + MOCHA_UI=bdd $(MAKE) test-browser-unit test-browser-qunit: @printf "==> [Test :: Browser :: QUnit]\n" - @MOCHA_UI=qunit $(MAKE) test-browser-unit + MOCHA_UI=qunit $(MAKE) test-browser-unit test-browser-tdd: @printf "==> [Test :: Browser :: TDD]\n" - @MOCHA_UI=tdd $(MAKE) test-browser-unit + MOCHA_UI=tdd $(MAKE) test-browser-unit test-jsapi: @printf "==> [Test :: JS API]\n" - @node test/jsapi + node test/jsapi test-unit: @printf "==> [Test :: Unit]\n" - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ test/acceptance/*.js \ --growl \ test/*.js test-integration: @printf "==> [Test :: Integrations]\n" - @./bin/mocha \ + $(MOCHA) --timeout 5000 \ --reporter $(REPORTER) \ test/integration/*.js test-compilers: @printf "==> [Test :: Compilers]\n" - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ --compilers coffee:coffee-script/register,foo:./test/compiler/foo \ test/acceptance/test.coffee \ test/acceptance/test.foo test-requires: @printf "==> [Test :: Requires]\n" - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ --compilers coffee:coffee-script/register \ --require test/acceptance/require/a.js \ --require test/acceptance/require/b.coffee \ @@ -101,88 +84,85 @@ test-requires: test-bdd: @printf "==> [Test :: BDD]\n" - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ --ui bdd \ test/acceptance/interfaces/bdd test-tdd: @printf "==> [Test :: TDD]\n" - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ --ui tdd \ test/acceptance/interfaces/tdd test-qunit: @printf "==> [Test :: QUnit]\n" - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ --ui qunit \ test/acceptance/interfaces/qunit test-exports: @printf "==> [Test :: Exports]\n" - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ --ui exports \ test/acceptance/interfaces/exports test-glob: @printf "==> [Test :: Glob]\n" - @./test/acceptance/glob/glob.sh + bash ./test/acceptance/glob/glob.sh test-reporters: @printf "==> [Test :: Reporters]\n" - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ test/reporters/*.js test-only: @printf "==> [Test :: Only]\n" - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ --ui tdd \ test/acceptance/misc/only/tdd - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ --ui bdd \ test/acceptance/misc/only/bdd - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ --ui qunit \ test/acceptance/misc/only/bdd-require - @./bin/mocha \ - --reporter $(REPORTER) \ +test-global-only: + @printf "==> [Test :: Global Only]\n" + $(MOCHA) --reporter $(REPORTER) \ + --ui tdd \ + test/acceptance/misc/only/global/tdd + + $(MOCHA) --reporter $(REPORTER) \ + --ui bdd \ + test/acceptance/misc/only/global/bdd + + $(MOCHA) --reporter $(REPORTER) \ --ui qunit \ - test/acceptance/misc/only/qunit + test/acceptance/misc/only/global/qunit test-mocha: @printf "==> [Test :: Mocha]\n" - @./bin/mocha \ - --reporter $(REPORTER) \ + $(MOCHA) --reporter $(REPORTER) \ test/mocha non-tty: @printf "==> [Test :: Non-TTY]\n" - @./bin/mocha \ - --reporter dot \ + $(MOCHA) --reporter dot \ test/acceptance/interfaces/bdd 2>&1 > /tmp/dot.out @echo dot: @cat /tmp/dot.out - @./bin/mocha \ - --reporter list \ + $(MOCHA) --reporter list \ test/acceptance/interfaces/bdd 2>&1 > /tmp/list.out @echo list: @cat /tmp/list.out - @./bin/mocha \ - --reporter spec \ + $(MOCHA) --reporter spec \ test/acceptance/interfaces/bdd 2>&1 > /tmp/spec.out @echo spec: @@ -190,6 +170,6 @@ non-tty: tm: @printf "==> [TM]\n" - @open editors/$(TM_BUNDLE) + open editors/$(TM_BUNDLE) -.PHONY: test-cov test-jsapi test-compilers watch test test-node test-bdd test-tdd test-qunit test-exports test-unit test-integration non-tty tm clean test-browser test-browser-unit test-browser-bdd test-browser-qunit test-browser-tdd test-browser-exports lint +.PHONY: test-jsapi test-compilers watch test test-node test-bdd test-tdd test-qunit test-exports test-unit test-integration non-tty tm clean test-browser test-browser-unit test-browser-bdd test-browser-qunit test-browser-tdd test-browser-exports lint test-only test-global-only diff --git a/bin/_mocha b/bin/_mocha index 268a589e8a..19dc2a6e71 100755 --- a/bin/_mocha +++ b/bin/_mocha @@ -106,7 +106,7 @@ program .option('--watch-extensions ,...', 'additional extensions to monitor with --watch', list, []) .option('--delay', 'wait for async suite definition') -program.name = 'mocha'; +program._name = 'mocha'; // init command @@ -255,11 +255,11 @@ mocha.suite.bail(program.bail); // --grep -if (program.grep) mocha.grep(new RegExp(program.grep)); +if (program.grep) mocha.grep(program.grep); // --fgrep -if (program.fgrep) mocha.grep(program.fgrep); +if (program.fgrep) mocha.fgrep(program.fgrep); // --invert diff --git a/bower.json b/bower.json index b21940fcbc..e96cc9526d 100644 --- a/bower.json +++ b/bower.json @@ -1,17 +1,7 @@ { "name": "mocha", - "homepage": "http://mocha.github.io/mocha", + "homepage": "https://mochajs.org", "description": "simple, flexible, fun test framework", - "authors": [ - "TJ Holowaychuk ", - "Joshua Appelman ", - "Oleg Gaidarenko ", - "Christoffer Hallas ", - "Christopher Hiller ", - "Travis Jeffery ", - "Johnathan Ong ", - "Guillermo Rauch " - ], "repository": { "type": "git", "url": "git://github.com/mochajs/mocha.git" @@ -25,15 +15,17 @@ "editors", "images", "lib", - "support", + "scripts", "test", - ".gitignore", - ".npmignore", - ".travis.yml", - "component.json", + "assets", + "media", + ".*", "index.js", + "karma.conf.js", + "browser-entry.js", "Makefile", - "package.json" + "package.json", + "appveyor.yml" ], "keywords": [ "mocha", diff --git a/browser-entry.js b/browser-entry.js index 27ea71f514..341a199914 100644 --- a/browser-entry.js +++ b/browser-entry.js @@ -132,8 +132,8 @@ mocha.run = function(fn){ mocha.globals('location'); var query = Mocha.utils.parseQuery(global.location.search || ''); - if (query.grep) mocha.grep(new RegExp(query.grep)); - if (query.fgrep) mocha.grep(query.fgrep); + if (query.grep) mocha.grep(query.grep); + if (query.fgrep) mocha.fgrep(query.fgrep); if (query.invert) mocha.invert(); return Mocha.prototype.run.call(mocha, function(err){ diff --git a/component.json b/component.json deleted file mode 100644 index 2f9246fbcd..0000000000 --- a/component.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "mocha", - "version": "2.4.0", - "repo": "mochajs/mocha", - "description": "simple, flexible, fun test framework", - "keywords": [ - "mocha", - "test", - "bdd", - "tdd", - "tap" - ], - "main": "mocha.js", - "scripts": [ - "mocha.js" - ], - "styles": [ - "mocha.css" - ] -} \ No newline at end of file diff --git a/index.js b/index.js index 169b271770..d2b7d19609 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,3 @@ -module.exports = process.env.COV - ? require('./lib-cov/mocha') - : require('./lib/mocha'); +'use strict'; + +module.exports = require('./lib/mocha'); diff --git a/karma.conf.js b/karma.conf.js index 853a5c5025..76e8ae631c 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,6 +1,12 @@ 'use strict'; +var fs = require('fs'); +var path = require('path'); +var mkdirp = require('mkdirp'); +var baseBundleDirpath = path.join(__dirname, '.karma'); + module.exports = function(config) { + var bundleDirpath; var cfg = { frameworks: [ 'browserify', @@ -25,9 +31,16 @@ module.exports = function(config) { debug: true, configure: function configure(b) { b.ignore('glob') - .ignore('jade') + .ignore('fs') + .ignore('path') .ignore('supports-color') - .exclude('./lib-cov/mocha'); + .on('bundled', function(err, content) { + if (!err && bundleDirpath) { + // write bundle to directory for debugging + fs.writeFileSync(path.join(bundleDirpath, + 'bundle.' + Date.now() + '.js'), content); + } + }); } }, reporters: ['spec'], @@ -38,37 +51,58 @@ module.exports = function(config) { }; // see https://github.com/saucelabs/karma-sauce-example - // TO RUN LOCALLY: - // Execute `CI=1 make test-browser`, once you've set the SAUCE_USERNAME and - // SAUCE_ACCESS_KEY env vars. - if (process.env.CI && !process.env.APPVEYOR) { - // we can't run SauceLabs tests on PRs from forks on Travis cuz security. - if (process.env.TRAVIS) { - if (process.env.TRAVIS_REPO_SLUG === 'mochajs/mocha' - && process.env.TRAVIS_PULL_REQUEST === 'false') { - addSauceTests(cfg); + // TO RUN LOCALLY, execute: + // `CI=1 SAUCE_USERNAME= SAUCE_ACCESS_KEY= make test-browser` + var env = process.env; + var sauceConfig; + + if (env.CI) { + console.error('CI mode enabled'); + if (env.TRAVIS) { + console.error('Travis-CI detected'); + bundleDirpath = path.join(baseBundleDirpath, process.env.TRAVIS_BUILD_ID); + if (env.SAUCE_USERNAME && env.SAUCE_ACCESS_KEY) { // correlate build/tunnel with Travis - cfg.sauceLabs.build = 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER - + ' (' + process.env.TRAVIS_BUILD_ID + ')'; - cfg.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; + sauceConfig = { + build: 'TRAVIS #' + env.TRAVIS_BUILD_NUMBER + + ' (' + env.TRAVIS_BUILD_ID + ')', + tunnelIdentifier: env.TRAVIS_JOB_NUMBER + }; + console.error('Configured SauceLabs'); + } else { + console.error('No SauceLabs credentials present'); } + } else if (env.APPVEYOR) { + console.error('AppVeyor detected'); + bundleDirpath = path.join(baseBundleDirpath, process.env.APPVEYOR_BUILD_ID); } else { - if (!(process.env.SAUCE_USERNAME || process.env.SAUCE_ACCESS_KEY)) { - throw new Error('Must set SAUCE_USERNAME and SAUCE_ACCESS_KEY ' - + 'environment variables!'); + console.error('Local/unknown environment detected'); + bundleDirpath = path.join(baseBundleDirpath, 'local'); + // don't need to run sauce from appveyor b/c travis does it. + if (!(env.SAUCE_USERNAME || env.SAUCE_ACCESS_KEY)) { + console.error('No SauceLabs credentials present'); + } else { + sauceConfig = { + build: require('os').hostname() + ' (' + Date.now() + ')' + }; + console.error('Configured SauceLabs'); } - - // remember, this is for a local run. - addSauceTests(cfg); - cfg.sauceLabs.build = require('os').hostname() + ' (' + Date.now() + ')'; } + mkdirp.sync(bundleDirpath); + } else { + console.error('CI mode disabled'); + } + + if (sauceConfig) { + cfg.sauceLabs = sauceConfig; + addSauceTests(cfg); } // the MOCHA_UI env var will determine if we're running interface-specific // tets. since you can only load one at a time, each must be run separately. // each has its own set of acceptance tests and a fixture. // the "bdd" fixture is used by default. - var ui = process.env.MOCHA_UI; + var ui = env.MOCHA_UI; if (ui) { if (cfg.sauceLabs) { cfg.sauceLabs.testName = 'Interface "' + ui + '" integration tests'; @@ -94,6 +128,12 @@ function addSauceTests(cfg) { platform: 'Windows 7', version: '8.0' }, + ie7: { + base: 'SauceLabs', + browserName: 'internet explorer', + platform: 'Windows XP', + version: '7.0' + }, chrome: { base: 'SauceLabs', browserName: 'chrome', diff --git a/lib/context.js b/lib/context.js index 4e7247b841..6d82fcadf4 100644 --- a/lib/context.js +++ b/lib/context.js @@ -1,3 +1,9 @@ +/** + * Module dependencies. + */ + +var JSON = require('json3'); + /** * Expose `Context`. */ diff --git a/lib/interfaces/bdd.js b/lib/interfaces/bdd.js index 8519a9a7b4..830a5fe67a 100644 --- a/lib/interfaces/bdd.js +++ b/lib/interfaces/bdd.js @@ -2,9 +2,7 @@ * Module dependencies. */ -var Suite = require('../suite'); var Test = require('../test'); -var escapeRe = require('escape-string-regexp'); /** * BDD-style interface: @@ -27,7 +25,7 @@ module.exports = function(suite) { var suites = [suite]; suite.on('pre-require', function(context, file, mocha) { - var common = require('./common')(suites, context); + var common = require('./common')(suites, context, mocha); context.before = common.before; context.after = common.after; @@ -41,12 +39,11 @@ module.exports = function(suite) { */ context.describe = context.context = function(title, fn) { - var suite = Suite.create(suites[0], title); - suite.file = file; - suites.unshift(suite); - fn.call(suite); - suites.shift(); - return suite; + return common.suite.create({ + title: title, + file: file, + fn: fn + }); }; /** @@ -54,11 +51,11 @@ module.exports = function(suite) { */ context.xdescribe = context.xcontext = context.describe.skip = function(title, fn) { - var suite = Suite.create(suites[0], title); - suite.pending = true; - suites.unshift(suite); - fn.call(suite); - suites.shift(); + return common.suite.skip({ + title: title, + file: file, + fn: fn + }); }; /** @@ -66,9 +63,11 @@ module.exports = function(suite) { */ context.describe.only = function(title, fn) { - var suite = context.describe(title, fn); - mocha.grep(suite.fullTitle()); - return suite; + return common.suite.only({ + title: title, + file: file, + fn: fn + }); }; /** @@ -77,7 +76,7 @@ module.exports = function(suite) { * acting as a thunk. */ - var it = context.it = context.specify = function(title, fn) { + context.it = context.specify = function(title, fn) { var suite = suites[0]; if (suite.isPending()) { fn = null; @@ -93,10 +92,7 @@ module.exports = function(suite) { */ context.it.only = function(title, fn) { - var test = it(title, fn); - var reString = '^' + escapeRe(test.fullTitle()) + '$'; - mocha.grep(new RegExp(reString)); - return test; + return common.test.only(mocha, context.it(title, fn)); }; /** diff --git a/lib/interfaces/common.js b/lib/interfaces/common.js index db939085ca..b367544a3f 100644 --- a/lib/interfaces/common.js +++ b/lib/interfaces/common.js @@ -1,13 +1,16 @@ 'use strict'; +var Suite = require('../suite'); + /** * Functions common to more than one interface. * * @param {Suite[]} suites * @param {Context} context + * @param {Mocha} mocha * @return {Object} An object containing common functions. */ -module.exports = function(suites, context) { +module.exports = function(suites, context, mocha) { return { /** * This is only present if flag --delay is passed into Mocha. It triggers @@ -62,7 +65,75 @@ module.exports = function(suites, context) { suites[0].afterEach(name, fn); }, + suite: { + /** + * Create an exclusive Suite; convenience function + * See docstring for create() below. + * + * @param {Object} opts + * @returns {Suite} + */ + only: function only(opts) { + mocha.options.hasOnly = true; + opts.isOnly = true; + return this.create(opts); + }, + + /** + * Create a Suite, but skip it; convenience function + * See docstring for create() below. + * + * @param {Object} opts + * @returns {Suite} + */ + skip: function skip(opts) { + opts.pending = true; + return this.create(opts); + }, + + /** + * Creates a suite. + * @param {Object} opts Options + * @param {string} opts.title Title of Suite + * @param {Function} [opts.fn] Suite Function (not always applicable) + * @param {boolean} [opts.pending] Is Suite pending? + * @param {string} [opts.file] Filepath where this Suite resides + * @param {boolean} [opts.isOnly] Is Suite exclusive? + * @returns {Suite} + */ + create: function create(opts) { + var suite = Suite.create(suites[0], opts.title); + suite.pending = Boolean(opts.pending); + suite.file = opts.file; + suites.unshift(suite); + if (opts.isOnly) { + suite.parent._onlySuites = suite.parent._onlySuites.concat(suite); + mocha.options.hasOnly = true; + } + if (typeof opts.fn === 'function') { + opts.fn.call(suite); + suites.shift(); + } + + return suite; + } + }, + test: { + + /** + * Exclusive test-case. + * + * @param {Object} mocha + * @param {Function} test + * @returns {*} + */ + only: function(mocha, test) { + test.parent._onlyTests = test.parent._onlyTests.concat(test); + mocha.options.hasOnly = true; + return test; + }, + /** * Pending test case. * diff --git a/lib/interfaces/qunit.js b/lib/interfaces/qunit.js index b79dcc68cb..a2d67ef90f 100644 --- a/lib/interfaces/qunit.js +++ b/lib/interfaces/qunit.js @@ -2,9 +2,7 @@ * Module dependencies. */ -var Suite = require('../suite'); var Test = require('../test'); -var escapeRe = require('escape-string-regexp'); /** * QUnit-style interface: @@ -35,7 +33,7 @@ module.exports = function(suite) { var suites = [suite]; suite.on('pre-require', function(context, file, mocha) { - var common = require('./common')(suites, context); + var common = require('./common')(suites, context, mocha); context.before = common.before; context.after = common.after; @@ -50,19 +48,24 @@ module.exports = function(suite) { if (suites.length > 1) { suites.shift(); } - var suite = Suite.create(suites[0], title); - suite.file = file; - suites.unshift(suite); - return suite; + return common.suite.create({ + title: title, + file: file + }); }; /** - * Exclusive test-case. + * Exclusive Suite. */ - context.suite.only = function(title, fn) { - var suite = context.suite(title, fn); - mocha.grep(suite.fullTitle()); + context.suite.only = function(title) { + if (suites.length > 1) { + suites.shift(); + } + return common.suite.only({ + title: title, + file: file + }); }; /** @@ -83,9 +86,7 @@ module.exports = function(suite) { */ context.test.only = function(title, fn) { - var test = context.test(title, fn); - var reString = '^' + escapeRe(test.fullTitle()) + '$'; - mocha.grep(new RegExp(reString)); + return common.test.only(mocha, context.test(title, fn)); }; context.test.skip = common.test.skip; diff --git a/lib/interfaces/tdd.js b/lib/interfaces/tdd.js index d37936ae41..445e992213 100644 --- a/lib/interfaces/tdd.js +++ b/lib/interfaces/tdd.js @@ -2,9 +2,7 @@ * Module dependencies. */ -var Suite = require('../suite'); var Test = require('../test'); -var escapeRe = require('escape-string-regexp'); /** * TDD-style interface: @@ -35,7 +33,7 @@ module.exports = function(suite) { var suites = [suite]; suite.on('pre-require', function(context, file, mocha) { - var common = require('./common')(suites, context); + var common = require('./common')(suites, context, mocha); context.setup = common.beforeEach; context.teardown = common.afterEach; @@ -48,31 +46,33 @@ module.exports = function(suite) { * nested suites and/or tests. */ context.suite = function(title, fn) { - var suite = Suite.create(suites[0], title); - suite.file = file; - suites.unshift(suite); - fn.call(suite); - suites.shift(); - return suite; + return common.suite.create({ + title: title, + file: file, + fn: fn + }); }; /** * Pending suite. */ context.suite.skip = function(title, fn) { - var suite = Suite.create(suites[0], title); - suite.pending = true; - suites.unshift(suite); - fn.call(suite); - suites.shift(); + return common.suite.skip({ + title: title, + file: file, + fn: fn + }); }; /** * Exclusive test-case. */ context.suite.only = function(title, fn) { - var suite = context.suite(title, fn); - mocha.grep(suite.fullTitle()); + return common.suite.only({ + title: title, + file: file, + fn: fn + }); }; /** @@ -95,9 +95,7 @@ module.exports = function(suite) { */ context.test.only = function(title, fn) { - var test = context.test(title, fn); - var reString = '^' + escapeRe(test.fullTitle()) + '$'; - mocha.grep(new RegExp(reString)); + return common.test.only(mocha, context.test(title, fn)); }; context.test.skip = common.test.skip; diff --git a/lib/mocha.js b/lib/mocha.js index 46775ab55c..a649715191 100644 --- a/lib/mocha.js +++ b/lib/mocha.js @@ -80,7 +80,7 @@ function Mocha(options) { this.grep(new RegExp(options.grep)); } if (options.fgrep) { - this.grep(options.fgrep); + this.fgrep(options.fgrep); } this.suite = new exports.Suite('', new exports.Context()); this.ui(options.ui); @@ -246,6 +246,17 @@ Mocha.prototype._growl = function(runner, reporter) { }); }; +/** + * Escape string and add it to grep as a regexp. + * + * @api public + * @param str + * @returns {Mocha} + */ +Mocha.prototype.fgrep = function(str) { + return this.grep(new RegExp(escapeRe(str))); +}; + /** * Add regexp to grep, if `re` is a string it is escaped. * @@ -256,10 +267,15 @@ Mocha.prototype._growl = function(runner, reporter) { * @return {Mocha} */ Mocha.prototype.grep = function(re) { - this.options.grep = typeof re === 'string' ? new RegExp(escapeRe(re)) : re; + if (utils.isString(re)) { + // extract args if it's regex-like, i.e: [string, pattern, flag] + var arg = re.match(/^\/(.*)\/(g|i|)$|.*/); + this.options.grep = new RegExp(arg[1] || arg[0], arg[2]); + } else { + this.options.grep = re; + } return this; }; - /** * Invert `.grep()` matches. * @@ -475,6 +491,7 @@ Mocha.prototype.run = function(fn) { var reporter = new this._reporter(runner, options); runner.ignoreLeaks = options.ignoreLeaks !== false; runner.fullStackTrace = options.fullStackTrace; + runner.hasOnly = options.hasOnly; runner.asyncOnly = options.asyncOnly; runner.allowUncaught = options.allowUncaught; if (options.grep) { diff --git a/lib/reporters/base.js b/lib/reporters/base.js index 4c9e8064cd..c754c5231f 100644 --- a/lib/reporters/base.js +++ b/lib/reporters/base.js @@ -78,7 +78,9 @@ exports.colors = { exports.symbols = { ok: '✓', err: '✖', - dot: '․' + dot: '․', + comma: ',', + bang: '!' }; // With node.js on Windows: use symbols available in terminal default fonts diff --git a/lib/reporters/dot.js b/lib/reporters/dot.js index e905dc6860..f8b4b41fe0 100644 --- a/lib/reporters/dot.js +++ b/lib/reporters/dot.js @@ -33,7 +33,7 @@ function Dot(runner) { if (++n % width === 0) { process.stdout.write('\n '); } - process.stdout.write(color('pending', Base.symbols.dot)); + process.stdout.write(color('pending', Base.symbols.comma)); }); runner.on('pass', function(test) { @@ -51,7 +51,7 @@ function Dot(runner) { if (++n % width === 0) { process.stdout.write('\n '); } - process.stdout.write(color('fail', Base.symbols.dot)); + process.stdout.write(color('fail', Base.symbols.bang)); }); runner.on('end', function() { diff --git a/lib/reporters/html-cov.js b/lib/reporters/html-cov.js deleted file mode 100644 index e3f2dd91e3..0000000000 --- a/lib/reporters/html-cov.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Module dependencies. - */ - -var JSONCov = require('./json-cov'); -var readFileSync = require('fs').readFileSync; -var join = require('path').join; - -/** - * Expose `HTMLCov`. - */ - -exports = module.exports = HTMLCov; - -/** - * Initialize a new `JsCoverage` reporter. - * - * @api public - * @param {Runner} runner - */ -function HTMLCov(runner) { - var jade = require('jade'); - var file = join(__dirname, '/templates/coverage.jade'); - var str = readFileSync(file, 'utf8'); - var fn = jade.compile(str, { filename: file }); - var self = this; - - JSONCov.call(this, runner, false); - - runner.on('end', function() { - process.stdout.write(fn({ - cov: self.cov, - coverageClass: coverageClass - })); - }); -} - -/** - * Return coverage class for a given coverage percentage. - * - * @api private - * @param {number} coveragePctg - * @return {string} - */ -function coverageClass(coveragePctg) { - if (coveragePctg >= 75) { - return 'high'; - } - if (coveragePctg >= 50) { - return 'medium'; - } - if (coveragePctg >= 25) { - return 'low'; - } - return 'terrible'; -} diff --git a/lib/reporters/index.js b/lib/reporters/index.js index 51f5cffee1..221a81d95b 100644 --- a/lib/reporters/index.js +++ b/lib/reporters/index.js @@ -14,6 +14,4 @@ exports.XUnit = exports.xunit = require('./xunit'); exports.Markdown = exports.markdown = require('./markdown'); exports.Progress = exports.progress = require('./progress'); exports.Landing = exports.landing = require('./landing'); -exports.JSONCov = exports['json-cov'] = require('./json-cov'); -exports.HTMLCov = exports['html-cov'] = require('./html-cov'); exports.JSONStream = exports['json-stream'] = require('./json-stream'); diff --git a/lib/reporters/json-cov.js b/lib/reporters/json-cov.js deleted file mode 100644 index 5a32569f03..0000000000 --- a/lib/reporters/json-cov.js +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Module dependencies. - */ - -var Base = require('./base'); - -/** - * Expose `JSONCov`. - */ - -exports = module.exports = JSONCov; - -/** - * Initialize a new `JsCoverage` reporter. - * - * @api public - * @param {Runner} runner - * @param {boolean} output - */ -function JSONCov(runner, output) { - Base.call(this, runner); - - output = arguments.length === 1 || output; - var self = this; - var tests = []; - var failures = []; - var passes = []; - - runner.on('test end', function(test) { - tests.push(test); - }); - - runner.on('pass', function(test) { - passes.push(test); - }); - - runner.on('fail', function(test) { - failures.push(test); - }); - - runner.on('end', function() { - var cov = global._$jscoverage || {}; - var result = self.cov = map(cov); - result.stats = self.stats; - result.tests = tests.map(clean); - result.failures = failures.map(clean); - result.passes = passes.map(clean); - if (!output) { - return; - } - process.stdout.write(JSON.stringify(result, null, 2)); - }); -} - -/** - * Map jscoverage data to a JSON structure - * suitable for reporting. - * - * @api private - * @param {Object} cov - * @return {Object} - */ - -function map(cov) { - var ret = { - instrumentation: 'node-jscoverage', - sloc: 0, - hits: 0, - misses: 0, - coverage: 0, - files: [] - }; - - for (var filename in cov) { - if (Object.prototype.hasOwnProperty.call(cov, filename)) { - var data = coverage(filename, cov[filename]); - ret.files.push(data); - ret.hits += data.hits; - ret.misses += data.misses; - ret.sloc += data.sloc; - } - } - - ret.files.sort(function(a, b) { - return a.filename.localeCompare(b.filename); - }); - - if (ret.sloc > 0) { - ret.coverage = (ret.hits / ret.sloc) * 100; - } - - return ret; -} - -/** - * Map jscoverage data for a single source file - * to a JSON structure suitable for reporting. - * - * @api private - * @param {string} filename name of the source file - * @param {Object} data jscoverage coverage data - * @return {Object} - */ -function coverage(filename, data) { - var ret = { - filename: filename, - coverage: 0, - hits: 0, - misses: 0, - sloc: 0, - source: {} - }; - - data.source.forEach(function(line, num) { - num++; - - if (data[num] === 0) { - ret.misses++; - ret.sloc++; - } else if (data[num] !== undefined) { - ret.hits++; - ret.sloc++; - } - - ret.source[num] = { - source: line, - coverage: data[num] === undefined ? '' : data[num] - }; - }); - - ret.coverage = ret.hits / ret.sloc * 100; - - return ret; -} - -/** - * Return a plain-object representation of `test` - * free of cyclic properties etc. - * - * @api private - * @param {Object} test - * @return {Object} - */ -function clean(test) { - return { - duration: test.duration, - currentRetry: test.currentRetry(), - fullTitle: test.fullTitle(), - title: test.title - }; -} diff --git a/lib/reporters/json-stream.js b/lib/reporters/json-stream.js index 02399e7dbc..f07f8657c0 100644 --- a/lib/reporters/json-stream.js +++ b/lib/reporters/json-stream.js @@ -3,6 +3,7 @@ */ var Base = require('./base'); +var JSON = require('json3'); /** * Expose `List`. diff --git a/lib/reporters/spec.js b/lib/reporters/spec.js index 77a73c4f43..28993a8f32 100644 --- a/lib/reporters/spec.js +++ b/lib/reporters/spec.js @@ -5,7 +5,6 @@ var Base = require('./base'); var inherits = require('../utils').inherits; var color = Base.color; -var cursor = Base.cursor; /** * Expose `Spec`. @@ -57,20 +56,17 @@ function Spec(runner) { fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s'); - cursor.CR(); console.log(fmt, test.title); } else { fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s') + color(test.speed, ' (%dms)'); - cursor.CR(); console.log(fmt, test.title, test.duration); } }); runner.on('fail', function(test) { - cursor.CR(); console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); }); diff --git a/lib/reporters/templates/coverage.jade b/lib/reporters/templates/coverage.jade deleted file mode 100644 index edd59d8864..0000000000 --- a/lib/reporters/templates/coverage.jade +++ /dev/null @@ -1,51 +0,0 @@ -doctype html -html - head - title Coverage - meta(charset='utf-8') - include script.html - include style.html - body - #coverage - h1#overview Coverage - include menu - - #stats(class=coverageClass(cov.coverage)) - .percentage #{cov.coverage | 0}% - .sloc= cov.sloc - .hits= cov.hits - .misses= cov.misses - - #files - for file in cov.files - .file - h2(id=file.filename)= file.filename - #stats(class=coverageClass(file.coverage)) - .percentage #{file.coverage | 0}% - .sloc= file.sloc - .hits= file.hits - .misses= file.misses - - table#source - thead - tr - th Line - th Hits - th Source - tbody - for line, number in file.source - if line.coverage > 0 - tr.hit - td.line= number - td.hits= line.coverage - td.source= line.source - else if 0 === line.coverage - tr.miss - td.line= number - td.hits 0 - td.source= line.source - else - tr - td.line= number - td.hits - td.source= line.source || ' ' diff --git a/lib/reporters/templates/menu.jade b/lib/reporters/templates/menu.jade deleted file mode 100644 index c682e3f0ee..0000000000 --- a/lib/reporters/templates/menu.jade +++ /dev/null @@ -1,13 +0,0 @@ -#menu - li - a(href='#overview') overview - for file in cov.files - li - span.cov(class=coverageClass(file.coverage)) #{file.coverage | 0} - a(href='##{file.filename}') - segments = file.filename.split('/') - basename = segments.pop() - if segments.length - span.dirname= segments.join('/') + '/' - span.basename= basename - a#logo(href='http://mochajs.org/') m diff --git a/lib/reporters/templates/script.html b/lib/reporters/templates/script.html deleted file mode 100644 index 073cf7939c..0000000000 --- a/lib/reporters/templates/script.html +++ /dev/null @@ -1,34 +0,0 @@ - diff --git a/lib/reporters/templates/style.html b/lib/reporters/templates/style.html deleted file mode 100644 index 4c9c37cfd9..0000000000 --- a/lib/reporters/templates/style.html +++ /dev/null @@ -1,324 +0,0 @@ - diff --git a/lib/runnable.js b/lib/runnable.js index 4bc2be2448..d89a7dd5d7 100644 --- a/lib/runnable.js +++ b/lib/runnable.js @@ -3,11 +3,12 @@ */ var EventEmitter = require('events').EventEmitter; +var JSON = require('json3'); var Pending = require('./pending'); var debug = require('debug')('mocha:runnable'); var milliseconds = require('./ms'); var utils = require('./utils'); -var inherits = utils.inherits; +var create = require('lodash.create'); /** * Save timer references to avoid Sinon interfering (see GH-237). @@ -61,7 +62,9 @@ function Runnable(title, fn) { /** * Inherit from `EventEmitter.prototype`. */ -inherits(Runnable, EventEmitter); +Runnable.prototype = create(EventEmitter.prototype, { + constructor: Runnable +}); /** * Set & get timeout `ms`. @@ -74,7 +77,8 @@ Runnable.prototype.timeout = function(ms) { if (!arguments.length) { return this._timeout; } - if (ms === 0) { + // see #1652 for reasoning + if (ms === 0 || ms > Math.pow(2, 31)) { this._enableTimeouts = false; } if (typeof ms === 'string') { @@ -350,7 +354,7 @@ Runnable.prototype.run = function(fn) { } function callFnAsync(fn) { - fn.call(ctx, function(err) { + var result = fn.call(ctx, function(err) { if (err instanceof Error || toString.call(err) === '[object Error]') { return done(err); } @@ -361,6 +365,10 @@ Runnable.prototype.run = function(fn) { } return done(new Error('done() invoked with non-Error: ' + err)); } + if (result && utils.isPromise(result)) { + return done(new Error('Resolution method is overspecified. Specify a callback *or* return a Promise; not both.')); + } + done(); }); } diff --git a/lib/runner.js b/lib/runner.js index 86bd4dc4af..ef82a33683 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -10,6 +10,7 @@ var debug = require('debug')('mocha:runner'); var Runnable = require('./runnable'); var filter = utils.filter; var indexOf = utils.indexOf; +var some = utils.some; var keys = utils.keys; var stackFilter = utils.stackTraceFilter(); var stringify = utils.stringify; @@ -778,6 +779,11 @@ Runner.prototype.run = function(fn) { var self = this; var rootSuite = this.suite; + // If there is an `only` filter + if (this.hasOnly) { + filterOnly(rootSuite); + } + fn = fn || function() {}; function uncaught(err) { @@ -833,6 +839,48 @@ Runner.prototype.abort = function() { return this; }; +/** + * Filter suites based on `isOnly` logic. + * + * @param {Array} suite + * @returns {Boolean} + * @api private + */ +function filterOnly(suite) { + if (suite._onlyTests.length) { + // If the suite contains `only` tests, run those and ignore any nested suites. + suite.tests = suite._onlyTests; + suite.suites = []; + } else { + // Otherwise, do not run any of the tests in this suite. + suite.tests = []; + suite._onlySuites.forEach(function(onlySuite) { + // If there are other `only` tests/suites nested in the current `only` suite, then filter the current suite. + // Otherwise, all of the tests on this `only` suite should be run, so don't filter it. + if (hasOnly(onlySuite)) { + filterOnly(suite); + } + }); + // Run the `only` suites, as well as any other suites that have `only` tests/suites as descendants. + suite.suites = filter(suite.suites, function(childSuite) { + return indexOf(suite._onlySuites, childSuite) !== -1 || filterOnly(childSuite); + }); + } + // Keep the suite only if there is something to run + return suite.tests.length || suite.suites.length; +} + +/** + * Determines whether a suite has an `only` test or suite as a descendant. + * + * @param {Array} suite + * @returns {Boolean} + * @api private + */ +function hasOnly(suite) { + return suite._onlyTests.length || suite._onlySuites.length || some(suite.suites, hasOnly); +} + /** * Filter leaks with the given globals flagged as `ok`. * diff --git a/lib/suite.js b/lib/suite.js index d43dd45604..bf3e4e9fef 100644 --- a/lib/suite.js +++ b/lib/suite.js @@ -41,6 +41,9 @@ exports.create = function(parent, title) { * @param {Context} parentContext */ function Suite(title, parentContext) { + if (!utils.isString(title)) { + throw new Error('Suite `title` should be a "string" but "' + typeof title + '" was given instead.'); + } this.title = title; function Context() {} Context.prototype = parentContext; @@ -58,6 +61,8 @@ function Suite(title, parentContext) { this._slow = 75; this._bail = false; this._retries = -1; + this._onlyTests = []; + this._onlySuites = []; this.delayed = false; } diff --git a/lib/test.js b/lib/test.js index a95cd31a48..05d4ed86d5 100644 --- a/lib/test.js +++ b/lib/test.js @@ -3,7 +3,8 @@ */ var Runnable = require('./runnable'); -var inherits = require('./utils').inherits; +var create = require('lodash.create'); +var isString = require('./utils').isString; /** * Expose `Test`. @@ -19,6 +20,9 @@ module.exports = Test; * @param {Function} fn */ function Test(title, fn) { + if (!isString(title)) { + throw new Error('Test `title` should be a "string" but "' + typeof title + '" was given instead.'); + } Runnable.call(this, title, fn); this.pending = !fn; this.type = 'test'; @@ -27,7 +31,9 @@ function Test(title, fn) { /** * Inherit from `Runnable.prototype`. */ -inherits(Test, Runnable); +Test.prototype = create(Runnable.prototype, { + constructor: Test +}); Test.prototype.clone = function() { var test = new Test(this.title, this.fn); diff --git a/lib/to-iso-string/LICENSE b/lib/to-iso-string/LICENSE new file mode 100644 index 0000000000..c25db56595 --- /dev/null +++ b/lib/to-iso-string/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 Segment.io, Inc. (friends@segment.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/lib/to-iso-string/index.js b/lib/to-iso-string/index.js new file mode 100644 index 0000000000..cd28d7be71 --- /dev/null +++ b/lib/to-iso-string/index.js @@ -0,0 +1,37 @@ +'use strict'; + +/** + * Pad a `number` with a ten's place zero. + * + * @param {number} number + * @return {string} + */ +function pad(number) { + var n = number.toString(); + return n.length === 1 ? '0' + n : n; +} + +/** + * Turn a `date` into an ISO string. + * + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString + * + * @param {Date} date + * @return {string} + */ +function toISOString(date) { + return date.getUTCFullYear() + + '-' + pad(date.getUTCMonth() + 1) + + '-' + pad(date.getUTCDate()) + + 'T' + pad(date.getUTCHours()) + + ':' + pad(date.getUTCMinutes()) + + ':' + pad(date.getUTCSeconds()) + + '.' + String((date.getUTCMilliseconds()/1000).toFixed(3)).slice(2, 5) + + 'Z'; +} + +/* + * Exports. + */ + +module.exports = toISOString; diff --git a/lib/utils.js b/lib/utils.js index 35e59c09c5..1cfbbae781 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -4,6 +4,7 @@ * Module dependencies. */ +var JSON = require('json3'); var basename = require('path').basename; var debug = require('debug')('mocha:watch'); var exists = require('fs').existsSync || require('path').existsSync; @@ -12,7 +13,7 @@ var join = require('path').join; var readdirSync = require('fs').readdirSync; var statSync = require('fs').statSync; var watchFile = require('fs').watchFile; -var toISOString = require('to-iso-string'); +var toISOString = require('./to-iso-string'); /** * Ignored directories. @@ -137,6 +138,23 @@ exports.filter = function(arr, fn) { return ret; }; +/** + * Array#some (<=IE8) + * + * @api private + * @param {Array} arr + * @param {Function} fn + * @return {Array} + */ +exports.some = function(arr, fn) { + for (var i = 0, l = arr.length; i < l; i++) { + if (fn(arr[i])) { + return true; + } + } + return false; +}; + /** * Object.keys (<=IE8) * @@ -748,3 +766,13 @@ exports.stackTraceFilter = function() { return stack.join('\n'); }; }; + +/** + * Crude, but effective. + * @api + * @param {*} value + * @returns {boolean} Whether or not `value` is a Promise + */ +exports.isPromise = function isPromise(value) { + return typeof value === 'object' && typeof value.then === 'function'; +}; diff --git a/mocha.css b/mocha.css index cd24c430d1..ec96b003c9 100644 --- a/mocha.css +++ b/mocha.css @@ -92,7 +92,7 @@ body { color: #fff; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); - -box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + box-shadow: inset 0 1px 1px rgba(0,0,0,.2); -webkit-border-radius: 5px; -moz-border-radius: 5px; -ms-border-radius: 5px; diff --git a/mocha.js b/mocha.js index df54445862..f98c2eca50 100644 --- a/mocha.js +++ b/mocha.js @@ -134,8 +134,8 @@ mocha.run = function(fn){ mocha.globals('location'); var query = Mocha.utils.parseQuery(global.location.search || ''); - if (query.grep) mocha.grep(new RegExp(query.grep)); - if (query.fgrep) mocha.grep(query.fgrep); + if (query.grep) mocha.grep(query.grep); + if (query.fgrep) mocha.fgrep(query.fgrep); if (query.invert) mocha.invert(); return Mocha.prototype.run.call(mocha, function(err){ @@ -168,7 +168,7 @@ global.mocha = mocha; module.exports = global; }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./lib/mocha":14,"_process":58,"browser-stdout":42}],2:[function(require,module,exports){ +},{"./lib/mocha":14,"_process":67,"browser-stdout":41}],2:[function(require,module,exports){ /* eslint-disable no-unused-vars */ module.exports = function(type) { return function() {}; @@ -504,6 +504,12 @@ exports.getWindowSize = function getWindowSize() { }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}],6:[function(require,module,exports){ +/** + * Module dependencies. + */ + +var JSON = require('json3'); + /** * Expose `Context`. */ @@ -609,7 +615,7 @@ Context.prototype.inspect = function() { }, 2); }; -},{}],7:[function(require,module,exports){ +},{"json3":54}],7:[function(require,module,exports){ /** * Module dependencies. */ @@ -657,14 +663,12 @@ Hook.prototype.error = function(err) { this._error = err; }; -},{"./runnable":35,"./utils":39}],8:[function(require,module,exports){ +},{"./runnable":33,"./utils":38}],8:[function(require,module,exports){ /** * Module dependencies. */ -var Suite = require('../suite'); var Test = require('../test'); -var escapeRe = require('escape-string-regexp'); /** * BDD-style interface: @@ -687,7 +691,7 @@ module.exports = function(suite) { var suites = [suite]; suite.on('pre-require', function(context, file, mocha) { - var common = require('./common')(suites, context); + var common = require('./common')(suites, context, mocha); context.before = common.before; context.after = common.after; @@ -701,12 +705,11 @@ module.exports = function(suite) { */ context.describe = context.context = function(title, fn) { - var suite = Suite.create(suites[0], title); - suite.file = file; - suites.unshift(suite); - fn.call(suite); - suites.shift(); - return suite; + return common.suite.create({ + title: title, + file: file, + fn: fn + }); }; /** @@ -714,11 +717,11 @@ module.exports = function(suite) { */ context.xdescribe = context.xcontext = context.describe.skip = function(title, fn) { - var suite = Suite.create(suites[0], title); - suite.pending = true; - suites.unshift(suite); - fn.call(suite); - suites.shift(); + return common.suite.skip({ + title: title, + file: file, + fn: fn + }); }; /** @@ -726,9 +729,11 @@ module.exports = function(suite) { */ context.describe.only = function(title, fn) { - var suite = context.describe(title, fn); - mocha.grep(suite.fullTitle()); - return suite; + return common.suite.only({ + title: title, + file: file, + fn: fn + }); }; /** @@ -737,7 +742,7 @@ module.exports = function(suite) { * acting as a thunk. */ - var it = context.it = context.specify = function(title, fn) { + context.it = context.specify = function(title, fn) { var suite = suites[0]; if (suite.isPending()) { fn = null; @@ -753,10 +758,7 @@ module.exports = function(suite) { */ context.it.only = function(title, fn) { - var test = it(title, fn); - var reString = '^' + escapeRe(test.fullTitle()) + '$'; - mocha.grep(new RegExp(reString)); - return test; + return common.test.only(mocha, context.it(title, fn)); }; /** @@ -776,17 +778,20 @@ module.exports = function(suite) { }); }; -},{"../suite":37,"../test":38,"./common":9,"escape-string-regexp":49}],9:[function(require,module,exports){ +},{"../test":36,"./common":9}],9:[function(require,module,exports){ 'use strict'; +var Suite = require('../suite'); + /** * Functions common to more than one interface. * * @param {Suite[]} suites * @param {Context} context + * @param {Mocha} mocha * @return {Object} An object containing common functions. */ -module.exports = function(suites, context) { +module.exports = function(suites, context, mocha) { return { /** * This is only present if flag --delay is passed into Mocha. It triggers @@ -841,7 +846,75 @@ module.exports = function(suites, context) { suites[0].afterEach(name, fn); }, + suite: { + /** + * Create an exclusive Suite; convenience function + * See docstring for create() below. + * + * @param {Object} opts + * @returns {Suite} + */ + only: function only(opts) { + mocha.options.hasOnly = true; + opts.isOnly = true; + return this.create(opts); + }, + + /** + * Create a Suite, but skip it; convenience function + * See docstring for create() below. + * + * @param {Object} opts + * @returns {Suite} + */ + skip: function skip(opts) { + opts.pending = true; + return this.create(opts); + }, + + /** + * Creates a suite. + * @param {Object} opts Options + * @param {string} opts.title Title of Suite + * @param {Function} [opts.fn] Suite Function (not always applicable) + * @param {boolean} [opts.pending] Is Suite pending? + * @param {string} [opts.file] Filepath where this Suite resides + * @param {boolean} [opts.isOnly] Is Suite exclusive? + * @returns {Suite} + */ + create: function create(opts) { + var suite = Suite.create(suites[0], opts.title); + suite.pending = Boolean(opts.pending); + suite.file = opts.file; + suites.unshift(suite); + if (opts.isOnly) { + suite.parent._onlySuites = suite.parent._onlySuites.concat(suite); + mocha.options.hasOnly = true; + } + if (typeof opts.fn === 'function') { + opts.fn.call(suite); + suites.shift(); + } + + return suite; + } + }, + test: { + + /** + * Exclusive test-case. + * + * @param {Object} mocha + * @param {Function} test + * @returns {*} + */ + only: function(mocha, test) { + test.parent._onlyTests = test.parent._onlyTests.concat(test); + mocha.options.hasOnly = true; + return test; + }, + /** * Pending test case. * @@ -863,7 +936,7 @@ module.exports = function(suites, context) { }; }; -},{}],10:[function(require,module,exports){ +},{"../suite":35}],10:[function(require,module,exports){ /** * Module dependencies. */ @@ -926,7 +999,7 @@ module.exports = function(suite) { } }; -},{"../suite":37,"../test":38}],11:[function(require,module,exports){ +},{"../suite":35,"../test":36}],11:[function(require,module,exports){ exports.bdd = require('./bdd'); exports.tdd = require('./tdd'); exports.qunit = require('./qunit'); @@ -937,9 +1010,7 @@ exports.exports = require('./exports'); * Module dependencies. */ -var Suite = require('../suite'); var Test = require('../test'); -var escapeRe = require('escape-string-regexp'); /** * QUnit-style interface: @@ -970,7 +1041,7 @@ module.exports = function(suite) { var suites = [suite]; suite.on('pre-require', function(context, file, mocha) { - var common = require('./common')(suites, context); + var common = require('./common')(suites, context, mocha); context.before = common.before; context.after = common.after; @@ -985,19 +1056,24 @@ module.exports = function(suite) { if (suites.length > 1) { suites.shift(); } - var suite = Suite.create(suites[0], title); - suite.file = file; - suites.unshift(suite); - return suite; + return common.suite.create({ + title: title, + file: file + }); }; /** - * Exclusive test-case. + * Exclusive Suite. */ - context.suite.only = function(title, fn) { - var suite = context.suite(title, fn); - mocha.grep(suite.fullTitle()); + context.suite.only = function(title) { + if (suites.length > 1) { + suites.shift(); + } + return common.suite.only({ + title: title, + file: file + }); }; /** @@ -1018,9 +1094,7 @@ module.exports = function(suite) { */ context.test.only = function(title, fn) { - var test = context.test(title, fn); - var reString = '^' + escapeRe(test.fullTitle()) + '$'; - mocha.grep(new RegExp(reString)); + return common.test.only(mocha, context.test(title, fn)); }; context.test.skip = common.test.skip; @@ -1028,14 +1102,12 @@ module.exports = function(suite) { }); }; -},{"../suite":37,"../test":38,"./common":9,"escape-string-regexp":49}],13:[function(require,module,exports){ +},{"../test":36,"./common":9}],13:[function(require,module,exports){ /** * Module dependencies. */ -var Suite = require('../suite'); var Test = require('../test'); -var escapeRe = require('escape-string-regexp'); /** * TDD-style interface: @@ -1066,7 +1138,7 @@ module.exports = function(suite) { var suites = [suite]; suite.on('pre-require', function(context, file, mocha) { - var common = require('./common')(suites, context); + var common = require('./common')(suites, context, mocha); context.setup = common.beforeEach; context.teardown = common.afterEach; @@ -1079,31 +1151,33 @@ module.exports = function(suite) { * nested suites and/or tests. */ context.suite = function(title, fn) { - var suite = Suite.create(suites[0], title); - suite.file = file; - suites.unshift(suite); - fn.call(suite); - suites.shift(); - return suite; + return common.suite.create({ + title: title, + file: file, + fn: fn + }); }; /** * Pending suite. */ context.suite.skip = function(title, fn) { - var suite = Suite.create(suites[0], title); - suite.pending = true; - suites.unshift(suite); - fn.call(suite); - suites.shift(); + return common.suite.skip({ + title: title, + file: file, + fn: fn + }); }; /** * Exclusive test-case. */ context.suite.only = function(title, fn) { - var suite = context.suite(title, fn); - mocha.grep(suite.fullTitle()); + return common.suite.only({ + title: title, + file: file, + fn: fn + }); }; /** @@ -1126,9 +1200,7 @@ module.exports = function(suite) { */ context.test.only = function(title, fn) { - var test = context.test(title, fn); - var reString = '^' + escapeRe(test.fullTitle()) + '$'; - mocha.grep(new RegExp(reString)); + return common.test.only(mocha, context.test(title, fn)); }; context.test.skip = common.test.skip; @@ -1136,7 +1208,7 @@ module.exports = function(suite) { }); }; -},{"../suite":37,"../test":38,"./common":9,"escape-string-regexp":49}],14:[function(require,module,exports){ +},{"../test":36,"./common":9}],14:[function(require,module,exports){ (function (process,global,__dirname){ /*! * mocha @@ -1220,7 +1292,7 @@ function Mocha(options) { this.grep(new RegExp(options.grep)); } if (options.fgrep) { - this.grep(options.fgrep); + this.fgrep(options.fgrep); } this.suite = new exports.Suite('', new exports.Context()); this.ui(options.ui); @@ -1386,6 +1458,17 @@ Mocha.prototype._growl = function(runner, reporter) { }); }; +/** + * Escape string and add it to grep as a regexp. + * + * @api public + * @param str + * @returns {Mocha} + */ +Mocha.prototype.fgrep = function(str) { + return this.grep(new RegExp(escapeRe(str))); +}; + /** * Add regexp to grep, if `re` is a string it is escaped. * @@ -1396,10 +1479,15 @@ Mocha.prototype._growl = function(runner, reporter) { * @return {Mocha} */ Mocha.prototype.grep = function(re) { - this.options.grep = typeof re === 'string' ? new RegExp(escapeRe(re)) : re; + if (utils.isString(re)) { + // extract args if it's regex-like, i.e: [string, pattern, flag] + var arg = re.match(/^\/(.*)\/(g|i|)$|.*/); + this.options.grep = new RegExp(arg[1] || arg[0], arg[2]); + } else { + this.options.grep = re; + } return this; }; - /** * Invert `.grep()` matches. * @@ -1615,6 +1703,7 @@ Mocha.prototype.run = function(fn) { var reporter = new this._reporter(runner, options); runner.ignoreLeaks = options.ignoreLeaks !== false; runner.fullStackTrace = options.fullStackTrace; + runner.hasOnly = options.hasOnly; runner.asyncOnly = options.asyncOnly; runner.allowUncaught = options.allowUncaught; if (options.grep) { @@ -1643,7 +1732,7 @@ Mocha.prototype.run = function(fn) { }; }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},"/lib") -},{"./context":6,"./hook":7,"./interfaces":11,"./reporters":22,"./runnable":35,"./runner":36,"./suite":37,"./test":38,"./utils":39,"_process":58,"escape-string-regexp":49,"growl":51,"path":43}],15:[function(require,module,exports){ +},{"./context":6,"./hook":7,"./interfaces":11,"./reporters":21,"./runnable":33,"./runner":34,"./suite":35,"./test":36,"./utils":38,"_process":67,"escape-string-regexp":47,"growl":49,"path":42}],15:[function(require,module,exports){ /** * Helpers. */ @@ -1872,7 +1961,9 @@ exports.colors = { exports.symbols = { ok: '✓', err: '✖', - dot: '․' + dot: '․', + comma: ',', + bang: '!' }; // With node.js on Windows: use symbols available in terminal default fonts @@ -1972,7 +2063,7 @@ exports.list = function(failures) { message = ''; } var stack = err.stack || message; - var index = stack.indexOf(message); + var index = message ? stack.indexOf(message) : -1; var actual = err.actual; var expected = err.expected; var escape = true; @@ -2281,7 +2372,7 @@ function sameType(a, b) { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../ms":15,"../utils":39,"_process":58,"diff":48,"supports-color":43,"tty":5}],18:[function(require,module,exports){ +},{"../ms":15,"../utils":38,"_process":67,"diff":46,"supports-color":42,"tty":5}],18:[function(require,module,exports){ /** * Module dependencies. */ @@ -2339,13 +2430,13 @@ function Doc(runner) { runner.on('fail', function(test, err) { console.log('%s
%s
', indent(), utils.escape(test.title)); - var code = utils.escape(utils.clean(test.fn.body)); + var code = utils.escape(utils.clean(test.body)); console.log('%s
%s
', indent(), code); console.log('%s
%s
', indent(), utils.escape(err)); }); } -},{"../utils":39,"./base":17}],19:[function(require,module,exports){ +},{"../utils":38,"./base":17}],19:[function(require,module,exports){ (function (process){ /** * Module dependencies. @@ -2382,7 +2473,7 @@ function Dot(runner) { if (++n % width === 0) { process.stdout.write('\n '); } - process.stdout.write(color('pending', Base.symbols.dot)); + process.stdout.write(color('pending', Base.symbols.comma)); }); runner.on('pass', function(test) { @@ -2400,7 +2491,7 @@ function Dot(runner) { if (++n % width === 0) { process.stdout.write('\n '); } - process.stdout.write(color('fail', Base.symbols.dot)); + process.stdout.write(color('fail', Base.symbols.bang)); }); runner.on('end', function() { @@ -2415,67 +2506,7 @@ function Dot(runner) { inherits(Dot, Base); }).call(this,require('_process')) -},{"../utils":39,"./base":17,"_process":58}],20:[function(require,module,exports){ -(function (process,__dirname){ -/** - * Module dependencies. - */ - -var JSONCov = require('./json-cov'); -var readFileSync = require('fs').readFileSync; -var join = require('path').join; - -/** - * Expose `HTMLCov`. - */ - -exports = module.exports = HTMLCov; - -/** - * Initialize a new `JsCoverage` reporter. - * - * @api public - * @param {Runner} runner - */ -function HTMLCov(runner) { - var jade = require('jade'); - var file = join(__dirname, '/templates/coverage.jade'); - var str = readFileSync(file, 'utf8'); - var fn = jade.compile(str, { filename: file }); - var self = this; - - JSONCov.call(this, runner, false); - - runner.on('end', function() { - process.stdout.write(fn({ - cov: self.cov, - coverageClass: coverageClass - })); - }); -} - -/** - * Return coverage class for a given coverage percentage. - * - * @api private - * @param {number} coveragePctg - * @return {string} - */ -function coverageClass(coveragePctg) { - if (coveragePctg >= 75) { - return 'high'; - } - if (coveragePctg >= 50) { - return 'medium'; - } - if (coveragePctg >= 25) { - return 'low'; - } - return 'terrible'; -} - -}).call(this,require('_process'),"/lib\\reporters") -},{"./json-cov":23,"_process":58,"fs":43,"jade":43,"path":43}],21:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":67}],20:[function(require,module,exports){ (function (global){ /* eslint-env browser */ @@ -2604,6 +2635,7 @@ function HTML(runner) { runner.on('suite end', function(suite) { if (suite.root) { + updateStats(); return; } stack.shift(); @@ -2674,7 +2706,7 @@ function HTML(runner) { function updateStats() { // TODO: add to stats - var percent = stats.tests / this.total * 100 | 0; + var percent = stats.tests / runner.total * 100 | 0; if (progress) { progress.update(percent).draw(ctx); } @@ -2822,7 +2854,7 @@ function on(el, event, fn) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../browser/progress":4,"../utils":39,"./base":17,"escape-string-regexp":49}],22:[function(require,module,exports){ +},{"../browser/progress":4,"../utils":38,"./base":17,"escape-string-regexp":47}],21:[function(require,module,exports){ // Alias exports to a their normalized format Mocha#reporter to prevent a need // for dynamic (try/catch) requires, which Browserify doesn't handle. exports.Base = exports.base = require('./base'); @@ -2839,172 +2871,16 @@ exports.XUnit = exports.xunit = require('./xunit'); exports.Markdown = exports.markdown = require('./markdown'); exports.Progress = exports.progress = require('./progress'); exports.Landing = exports.landing = require('./landing'); -exports.JSONCov = exports['json-cov'] = require('./json-cov'); -exports.HTMLCov = exports['html-cov'] = require('./html-cov'); exports.JSONStream = exports['json-stream'] = require('./json-stream'); -},{"./base":17,"./doc":18,"./dot":19,"./html":21,"./html-cov":20,"./json":25,"./json-cov":23,"./json-stream":24,"./landing":26,"./list":27,"./markdown":28,"./min":29,"./nyan":30,"./progress":31,"./spec":32,"./tap":33,"./xunit":34}],23:[function(require,module,exports){ -(function (process,global){ -/** - * Module dependencies. - */ - -var Base = require('./base'); - -/** - * Expose `JSONCov`. - */ - -exports = module.exports = JSONCov; - -/** - * Initialize a new `JsCoverage` reporter. - * - * @api public - * @param {Runner} runner - * @param {boolean} output - */ -function JSONCov(runner, output) { - Base.call(this, runner); - - output = arguments.length === 1 || output; - var self = this; - var tests = []; - var failures = []; - var passes = []; - - runner.on('test end', function(test) { - tests.push(test); - }); - - runner.on('pass', function(test) { - passes.push(test); - }); - - runner.on('fail', function(test) { - failures.push(test); - }); - - runner.on('end', function() { - var cov = global._$jscoverage || {}; - var result = self.cov = map(cov); - result.stats = self.stats; - result.tests = tests.map(clean); - result.failures = failures.map(clean); - result.passes = passes.map(clean); - if (!output) { - return; - } - process.stdout.write(JSON.stringify(result, null, 2)); - }); -} - -/** - * Map jscoverage data to a JSON structure - * suitable for reporting. - * - * @api private - * @param {Object} cov - * @return {Object} - */ - -function map(cov) { - var ret = { - instrumentation: 'node-jscoverage', - sloc: 0, - hits: 0, - misses: 0, - coverage: 0, - files: [] - }; - - for (var filename in cov) { - if (Object.prototype.hasOwnProperty.call(cov, filename)) { - var data = coverage(filename, cov[filename]); - ret.files.push(data); - ret.hits += data.hits; - ret.misses += data.misses; - ret.sloc += data.sloc; - } - } - - ret.files.sort(function(a, b) { - return a.filename.localeCompare(b.filename); - }); - - if (ret.sloc > 0) { - ret.coverage = (ret.hits / ret.sloc) * 100; - } - - return ret; -} - -/** - * Map jscoverage data for a single source file - * to a JSON structure suitable for reporting. - * - * @api private - * @param {string} filename name of the source file - * @param {Object} data jscoverage coverage data - * @return {Object} - */ -function coverage(filename, data) { - var ret = { - filename: filename, - coverage: 0, - hits: 0, - misses: 0, - sloc: 0, - source: {} - }; - - data.source.forEach(function(line, num) { - num++; - - if (data[num] === 0) { - ret.misses++; - ret.sloc++; - } else if (data[num] !== undefined) { - ret.hits++; - ret.sloc++; - } - - ret.source[num] = { - source: line, - coverage: data[num] === undefined ? '' : data[num] - }; - }); - - ret.coverage = ret.hits / ret.sloc * 100; - - return ret; -} - -/** - * Return a plain-object representation of `test` - * free of cyclic properties etc. - * - * @api private - * @param {Object} test - * @return {Object} - */ -function clean(test) { - return { - duration: test.duration, - currentRetry: test.currentRetry(), - fullTitle: test.fullTitle(), - title: test.title - }; -} - -}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./base":17,"_process":58}],24:[function(require,module,exports){ +},{"./base":17,"./doc":18,"./dot":19,"./html":20,"./json":23,"./json-stream":22,"./landing":24,"./list":25,"./markdown":26,"./min":27,"./nyan":28,"./progress":29,"./spec":30,"./tap":31,"./xunit":32}],22:[function(require,module,exports){ (function (process){ /** * Module dependencies. */ var Base = require('./base'); +var JSON = require('json3'); /** * Expose `List`. @@ -3062,7 +2938,7 @@ function clean(test) { } }).call(this,require('_process')) -},{"./base":17,"_process":58}],25:[function(require,module,exports){ +},{"./base":17,"_process":67,"json3":54}],23:[function(require,module,exports){ (function (process){ /** * Module dependencies. @@ -3156,7 +3032,7 @@ function errorJSON(err) { } }).call(this,require('_process')) -},{"./base":17,"_process":58}],26:[function(require,module,exports){ +},{"./base":17,"_process":67}],24:[function(require,module,exports){ (function (process){ /** * Module dependencies. @@ -3252,7 +3128,7 @@ function Landing(runner) { inherits(Landing, Base); }).call(this,require('_process')) -},{"../utils":39,"./base":17,"_process":58}],27:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":67}],25:[function(require,module,exports){ (function (process){ /** * Module dependencies. @@ -3317,7 +3193,7 @@ function List(runner) { inherits(List, Base); }).call(this,require('_process')) -},{"../utils":39,"./base":17,"_process":58}],28:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":67}],26:[function(require,module,exports){ (function (process){ /** * Module dependencies. @@ -3418,7 +3294,7 @@ function Markdown(runner) { } }).call(this,require('_process')) -},{"../utils":39,"./base":17,"_process":58}],29:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":67}],27:[function(require,module,exports){ (function (process){ /** * Module dependencies. @@ -3458,7 +3334,7 @@ function Min(runner) { inherits(Min, Base); }).call(this,require('_process')) -},{"../utils":39,"./base":17,"_process":58}],30:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":67}],28:[function(require,module,exports){ (function (process){ /** * Module dependencies. @@ -3723,7 +3599,7 @@ function write(string) { } }).call(this,require('_process')) -},{"../utils":39,"./base":17,"_process":58}],31:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":67}],29:[function(require,module,exports){ (function (process){ /** * Module dependencies. @@ -3816,7 +3692,7 @@ function Progress(runner, options) { inherits(Progress, Base); }).call(this,require('_process')) -},{"../utils":39,"./base":17,"_process":58}],32:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":67}],30:[function(require,module,exports){ /** * Module dependencies. */ @@ -3824,7 +3700,6 @@ inherits(Progress, Base); var Base = require('./base'); var inherits = require('../utils').inherits; var color = Base.color; -var cursor = Base.cursor; /** * Expose `Spec`. @@ -3876,20 +3751,17 @@ function Spec(runner) { fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s'); - cursor.CR(); console.log(fmt, test.title); } else { fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s') + color(test.speed, ' (%dms)'); - cursor.CR(); console.log(fmt, test.title, test.duration); } }); runner.on('fail', function(test) { - cursor.CR(); console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); }); @@ -3901,7 +3773,7 @@ function Spec(runner) { */ inherits(Spec, Base); -},{"../utils":39,"./base":17}],33:[function(require,module,exports){ +},{"../utils":38,"./base":17}],31:[function(require,module,exports){ /** * Module dependencies. */ @@ -3971,7 +3843,7 @@ function title(test) { return test.fullTitle().replace(/#/g, ''); } -},{"./base":17}],34:[function(require,module,exports){ +},{"./base":17}],32:[function(require,module,exports){ (function (process,global){ /** * Module dependencies. @@ -4141,18 +4013,19 @@ function tag(name, attrs, close, content) { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../utils":39,"./base":17,"_process":58,"fs":43,"mkdirp":55,"path":43}],35:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":67,"fs":42,"mkdirp":64,"path":42}],33:[function(require,module,exports){ (function (global){ /** * Module dependencies. */ var EventEmitter = require('events').EventEmitter; +var JSON = require('json3'); var Pending = require('./pending'); var debug = require('debug')('mocha:runnable'); var milliseconds = require('./ms'); var utils = require('./utils'); -var inherits = utils.inherits; +var create = require('lodash.create'); /** * Save timer references to avoid Sinon interfering (see GH-237). @@ -4206,7 +4079,9 @@ function Runnable(title, fn) { /** * Inherit from `EventEmitter.prototype`. */ -inherits(Runnable, EventEmitter); +Runnable.prototype = create(EventEmitter.prototype, { + constructor: Runnable +}); /** * Set & get timeout `ms`. @@ -4219,7 +4094,8 @@ Runnable.prototype.timeout = function(ms) { if (!arguments.length) { return this._timeout; } - if (ms === 0) { + // see #1652 for reasoning + if (ms === 0 || ms > Math.pow(2, 31)) { this._enableTimeouts = false; } if (typeof ms === 'string') { @@ -4241,7 +4117,7 @@ Runnable.prototype.timeout = function(ms) { * @return {Runnable|number} ms or Runnable instance. */ Runnable.prototype.slow = function(ms) { - if (!arguments.length) { + if (typeof ms === 'undefined') { return this._slow; } if (typeof ms === 'string') { @@ -4443,6 +4319,10 @@ Runnable.prototype.run = function(fn) { return callFnAsync(this.fn); } try { + // allows skip() to be used in an explicit async context + this.skip = function() { + done(new Pending()); + }; callFnAsync(this.fn); } catch (err) { done(utils.getError(err)); @@ -4491,7 +4371,7 @@ Runnable.prototype.run = function(fn) { } function callFnAsync(fn) { - fn.call(ctx, function(err) { + var result = fn.call(ctx, function(err) { if (err instanceof Error || toString.call(err) === '[object Error]') { return done(err); } @@ -4502,13 +4382,17 @@ Runnable.prototype.run = function(fn) { } return done(new Error('done() invoked with non-Error: ' + err)); } + if (result && utils.isPromise(result)) { + return done(new Error('Resolution method is overspecified. Specify a callback *or* return a Promise; not both.')); + } + done(); }); } }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./ms":15,"./pending":16,"./utils":39,"debug":2,"events":3}],36:[function(require,module,exports){ +},{"./ms":15,"./pending":16,"./utils":38,"debug":2,"events":3,"json3":54,"lodash.create":60}],34:[function(require,module,exports){ (function (process,global){ /** * Module dependencies. @@ -4522,6 +4406,7 @@ var debug = require('debug')('mocha:runner'); var Runnable = require('./runnable'); var filter = utils.filter; var indexOf = utils.indexOf; +var some = utils.some; var keys = utils.keys; var stackFilter = utils.stackTraceFilter(); var stringify = utils.stringify; @@ -5290,6 +5175,11 @@ Runner.prototype.run = function(fn) { var self = this; var rootSuite = this.suite; + // If there is an `only` filter + if (this.hasOnly) { + filterOnly(rootSuite); + } + fn = fn || function() {}; function uncaught(err) { @@ -5345,6 +5235,48 @@ Runner.prototype.abort = function() { return this; }; +/** + * Filter suites based on `isOnly` logic. + * + * @param {Array} suite + * @returns {Boolean} + * @api private + */ +function filterOnly(suite) { + if (suite._onlyTests.length) { + // If the suite contains `only` tests, run those and ignore any nested suites. + suite.tests = suite._onlyTests; + suite.suites = []; + } else { + // Otherwise, do not run any of the tests in this suite. + suite.tests = []; + suite._onlySuites.forEach(function(onlySuite) { + // If there are other `only` tests/suites nested in the current `only` suite, then filter the current suite. + // Otherwise, all of the tests on this `only` suite should be run, so don't filter it. + if (hasOnly(onlySuite)) { + filterOnly(suite); + } + }); + // Run the `only` suites, as well as any other suites that have `only` tests/suites as descendants. + suite.suites = filter(suite.suites, function(childSuite) { + return indexOf(suite._onlySuites, childSuite) !== -1 || filterOnly(childSuite); + }); + } + // Keep the suite only if there is something to run + return suite.tests.length || suite.suites.length; +} + +/** + * Determines whether a suite has an `only` test or suite as a descendant. + * + * @param {Array} suite + * @returns {Boolean} + * @api private + */ +function hasOnly(suite) { + return suite._onlyTests.length || suite._onlySuites.length || some(suite.suites, hasOnly); +} + /** * Filter leaks with the given globals flagged as `ok`. * @@ -5412,7 +5344,7 @@ function extraGlobals() { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./pending":16,"./runnable":35,"./utils":39,"_process":58,"debug":2,"events":3}],37:[function(require,module,exports){ +},{"./pending":16,"./runnable":33,"./utils":38,"_process":67,"debug":2,"events":3}],35:[function(require,module,exports){ /** * Module dependencies. */ @@ -5456,6 +5388,9 @@ exports.create = function(parent, title) { * @param {Context} parentContext */ function Suite(title, parentContext) { + if (!utils.isString(title)) { + throw new Error('Suite `title` should be a "string" but "' + typeof title + '" was given instead.'); + } this.title = title; function Context() {} Context.prototype = parentContext; @@ -5473,6 +5408,8 @@ function Suite(title, parentContext) { this._slow = 75; this._bail = false; this._retries = -1; + this._onlyTests = []; + this._onlySuites = []; this.delayed = false; } @@ -5809,13 +5746,14 @@ Suite.prototype.run = function run() { } }; -},{"./hook":7,"./ms":15,"./utils":39,"debug":2,"events":3}],38:[function(require,module,exports){ +},{"./hook":7,"./ms":15,"./utils":38,"debug":2,"events":3}],36:[function(require,module,exports){ /** * Module dependencies. */ var Runnable = require('./runnable'); -var inherits = require('./utils').inherits; +var create = require('lodash.create'); +var isString = require('./utils').isString; /** * Expose `Test`. @@ -5831,6 +5769,9 @@ module.exports = Test; * @param {Function} fn */ function Test(title, fn) { + if (!isString(title)) { + throw new Error('Test `title` should be a "string" but "' + typeof title + '" was given instead.'); + } Runnable.call(this, title, fn); this.pending = !fn; this.type = 'test'; @@ -5839,7 +5780,9 @@ function Test(title, fn) { /** * Inherit from `Runnable.prototype`. */ -inherits(Test, Runnable); +Test.prototype = create(Runnable.prototype, { + constructor: Test +}); Test.prototype.clone = function() { var test = new Test(this.title, this.fn); @@ -5855,7 +5798,46 @@ Test.prototype.clone = function() { return test; }; -},{"./runnable":35,"./utils":39}],39:[function(require,module,exports){ +},{"./runnable":33,"./utils":38,"lodash.create":60}],37:[function(require,module,exports){ +'use strict'; + +/** + * Pad a `number` with a ten's place zero. + * + * @param {number} number + * @return {string} + */ +function pad(number) { + var n = number.toString(); + return n.length === 1 ? '0' + n : n; +} + +/** + * Turn a `date` into an ISO string. + * + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString + * + * @param {Date} date + * @return {string} + */ +function toISOString(date) { + return date.getUTCFullYear() + + '-' + pad(date.getUTCMonth() + 1) + + '-' + pad(date.getUTCDate()) + + 'T' + pad(date.getUTCHours()) + + ':' + pad(date.getUTCMinutes()) + + ':' + pad(date.getUTCSeconds()) + + '.' + String((date.getUTCMilliseconds()/1000).toFixed(3)).slice(2, 5) + + 'Z'; +} + +/* + * Exports. + */ + +module.exports = toISOString; + +},{}],38:[function(require,module,exports){ (function (process,Buffer){ /* eslint-env browser */ @@ -5863,6 +5845,7 @@ Test.prototype.clone = function() { * Module dependencies. */ +var JSON = require('json3'); var basename = require('path').basename; var debug = require('debug')('mocha:watch'); var exists = require('fs').existsSync || require('path').existsSync; @@ -5871,7 +5854,7 @@ var join = require('path').join; var readdirSync = require('fs').readdirSync; var statSync = require('fs').statSync; var watchFile = require('fs').watchFile; -var toISOString = require('to-iso-string'); +var toISOString = require('./to-iso-string'); /** * Ignored directories. @@ -5997,11 +5980,28 @@ exports.filter = function(arr, fn) { }; /** - * Object.keys (<=IE8) + * Array#some (<=IE8) * * @api private - * @param {Object} obj - * @return {Array} keys + * @param {Array} arr + * @param {Function} fn + * @return {Array} + */ +exports.some = function(arr, fn) { + for (var i = 0, l = arr.length; i < l; i++) { + if (fn(arr[i])) { + return true; + } + } + return false; +}; + +/** + * Object.keys (<=IE8) + * + * @api private + * @param {Object} obj + * @return {Array} keys */ exports.keys = typeof Object.keys === 'function' ? Object.keys : function(obj) { var keys = []; @@ -6608,8 +6608,18 @@ exports.stackTraceFilter = function() { }; }; +/** + * Crude, but effective. + * @api + * @param {*} value + * @returns {boolean} Whether or not `value` is a Promise + */ +exports.isPromise = function isPromise(value) { + return typeof value === 'object' && typeof value.then === 'function'; +}; + }).call(this,require('_process'),require("buffer").Buffer) -},{"_process":58,"buffer":45,"debug":2,"fs":43,"glob":43,"path":43,"to-iso-string":72,"util":75}],40:[function(require,module,exports){ +},{"./to-iso-string":37,"_process":67,"buffer":44,"debug":2,"fs":42,"glob":42,"json3":54,"path":42,"util":82}],39:[function(require,module,exports){ 'use strict' exports.toByteArray = toByteArray @@ -6720,9 +6730,9 @@ function fromByteArray (uint8) { return parts.join('') } -},{}],41:[function(require,module,exports){ +},{}],40:[function(require,module,exports){ -},{}],42:[function(require,module,exports){ +},{}],41:[function(require,module,exports){ (function (process){ var WritableStream = require('stream').Writable var inherits = require('util').inherits @@ -6751,9 +6761,9 @@ BrowserStdout.prototype._write = function(chunks, encoding, cb) { } }).call(this,require('_process')) -},{"_process":58,"stream":59,"util":75}],43:[function(require,module,exports){ -arguments[4][41][0].apply(exports,arguments) -},{"dup":41}],44:[function(require,module,exports){ +},{"_process":67,"stream":78,"util":82}],42:[function(require,module,exports){ +arguments[4][40][0].apply(exports,arguments) +},{"dup":40}],43:[function(require,module,exports){ (function (global){ 'use strict'; @@ -6865,7 +6875,7 @@ exports.allocUnsafeSlow = function allocUnsafeSlow(size) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"buffer":45}],45:[function(require,module,exports){ +},{"buffer":44}],44:[function(require,module,exports){ (function (global){ /*! * The buffer module from node.js, for the browser. @@ -6921,7 +6931,7 @@ exports.kMaxLength = kMaxLength() function typedArraySupport () { try { var arr = new Uint8Array(1) - arr.foo = function () { return 42 } + arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} return arr.foo() === 42 && // typed array instances can be augmented typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` @@ -7065,7 +7075,7 @@ function allocUnsafe (that, size) { assertSize(size) that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) if (!Buffer.TYPED_ARRAY_SUPPORT) { - for (var i = 0; i < size; i++) { + for (var i = 0; i < size; ++i) { that[i] = 0 } } @@ -7243,14 +7253,14 @@ Buffer.concat = function concat (list, length) { var i if (length === undefined) { length = 0 - for (i = 0; i < list.length; i++) { + for (i = 0; i < list.length; ++i) { length += list[i].length } } var buffer = Buffer.allocUnsafe(length) var pos = 0 - for (i = 0; i < list.length; i++) { + for (i = 0; i < list.length; ++i) { var buf = list[i] if (!Buffer.isBuffer(buf)) { throw new TypeError('"list" argument must be an Array of Buffers') @@ -7282,7 +7292,6 @@ function byteLength (string, encoding) { switch (encoding) { case 'ascii': case 'binary': - // Deprecated case 'raw': case 'raws': return len @@ -7520,15 +7529,16 @@ function arrayIndexOf (arr, val, byteOffset, encoding) { } var foundIndex = -1 - for (var i = 0; byteOffset + i < arrLength; i++) { - if (read(arr, byteOffset + i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + for (var i = byteOffset; i < arrLength; ++i) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { if (foundIndex === -1) foundIndex = i - if (i - foundIndex + 1 === valLength) return (byteOffset + foundIndex) * indexSize + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize } else { if (foundIndex !== -1) i -= i - foundIndex foundIndex = -1 } } + return -1 } @@ -7593,7 +7603,7 @@ function hexWrite (buf, string, offset, length) { if (length > strLen / 2) { length = strLen / 2 } - for (var i = 0; i < length; i++) { + for (var i = 0; i < length; ++i) { var parsed = parseInt(string.substr(i * 2, 2), 16) if (isNaN(parsed)) return i buf[offset + i] = parsed @@ -7807,7 +7817,7 @@ function asciiSlice (buf, start, end) { var ret = '' end = Math.min(buf.length, end) - for (var i = start; i < end; i++) { + for (var i = start; i < end; ++i) { ret += String.fromCharCode(buf[i] & 0x7F) } return ret @@ -7817,7 +7827,7 @@ function binarySlice (buf, start, end) { var ret = '' end = Math.min(buf.length, end) - for (var i = start; i < end; i++) { + for (var i = start; i < end; ++i) { ret += String.fromCharCode(buf[i]) } return ret @@ -7830,7 +7840,7 @@ function hexSlice (buf, start, end) { if (!end || end < 0 || end > len) end = len var out = '' - for (var i = start; i < end; i++) { + for (var i = start; i < end; ++i) { out += toHex(buf[i]) } return out @@ -7873,7 +7883,7 @@ Buffer.prototype.slice = function slice (start, end) { } else { var sliceLen = end - start newBuf = new Buffer(sliceLen, undefined) - for (var i = 0; i < sliceLen; i++) { + for (var i = 0; i < sliceLen; ++i) { newBuf[i] = this[i + start] } } @@ -8100,7 +8110,7 @@ Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { function objectWriteUInt16 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> (littleEndian ? i : 1 - i) * 8 } @@ -8134,7 +8144,7 @@ Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert function objectWriteUInt32 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffffffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff } } @@ -8349,12 +8359,12 @@ Buffer.prototype.copy = function copy (target, targetStart, start, end) { if (this === target && start < targetStart && targetStart < end) { // descending copy from end - for (i = len - 1; i >= 0; i--) { + for (i = len - 1; i >= 0; --i) { target[i + targetStart] = this[i + start] } } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { // ascending copy from start - for (i = 0; i < len; i++) { + for (i = 0; i < len; ++i) { target[i + targetStart] = this[i + start] } } else { @@ -8415,7 +8425,7 @@ Buffer.prototype.fill = function fill (val, start, end, encoding) { var i if (typeof val === 'number') { - for (i = start; i < end; i++) { + for (i = start; i < end; ++i) { this[i] = val } } else { @@ -8423,7 +8433,7 @@ Buffer.prototype.fill = function fill (val, start, end, encoding) { ? val : utf8ToBytes(new Buffer(val, encoding).toString()) var len = bytes.length - for (i = 0; i < end - start; i++) { + for (i = 0; i < end - start; ++i) { this[i + start] = bytes[i % len] } } @@ -8465,7 +8475,7 @@ function utf8ToBytes (string, units) { var leadSurrogate = null var bytes = [] - for (var i = 0; i < length; i++) { + for (var i = 0; i < length; ++i) { codePoint = string.charCodeAt(i) // is surrogate component @@ -8540,7 +8550,7 @@ function utf8ToBytes (string, units) { function asciiToBytes (str) { var byteArray = [] - for (var i = 0; i < str.length; i++) { + for (var i = 0; i < str.length; ++i) { // Node's code seems to be doing this and not & 0x7F.. byteArray.push(str.charCodeAt(i) & 0xFF) } @@ -8550,7 +8560,7 @@ function asciiToBytes (str) { function utf16leToBytes (str, units) { var c, hi, lo var byteArray = [] - for (var i = 0; i < str.length; i++) { + for (var i = 0; i < str.length; ++i) { if ((units -= 2) < 0) break c = str.charCodeAt(i) @@ -8568,7 +8578,7 @@ function base64ToBytes (str) { } function blitBuffer (src, dst, offset, length) { - for (var i = 0; i < length; i++) { + for (var i = 0; i < length; ++i) { if ((i + offset >= dst.length) || (i >= src.length)) break dst[i + offset] = src[i] } @@ -8580,14 +8590,7 @@ function isnan (val) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"base64-js":40,"ieee754":52,"isarray":46}],46:[function(require,module,exports){ -var toString = {}.toString; - -module.exports = Array.isArray || function (arr) { - return toString.call(arr) == '[object Array]'; -}; - -},{}],47:[function(require,module,exports){ +},{"base64-js":39,"ieee754":50,"isarray":53}],45:[function(require,module,exports){ (function (Buffer){ // Copyright Joyent, Inc. and other Node contributors. // @@ -8698,7 +8701,7 @@ function objectToString(o) { } }).call(this,{"isBuffer":require("../../is-buffer/index.js")}) -},{"../../is-buffer/index.js":54}],48:[function(require,module,exports){ +},{"../../is-buffer/index.js":52}],46:[function(require,module,exports){ /* See LICENSE file for terms of use */ /* @@ -9319,7 +9322,7 @@ function objectToString(o) { } }(this)); -},{}],49:[function(require,module,exports){ +},{}],47:[function(require,module,exports){ 'use strict'; var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; @@ -9329,10 +9332,10 @@ module.exports = function (str) { throw new TypeError('Expected a string'); } - return str.replace(matchOperatorsRe, '\\$&'); + return str.replace(matchOperatorsRe, '\\$&'); }; -},{}],50:[function(require,module,exports){ +},{}],48:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -9392,8 +9395,12 @@ EventEmitter.prototype.emit = function(type) { er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); + err.context = er; + throw err; } - throw TypeError('Uncaught, unspecified "error" event.'); } } @@ -9632,7 +9639,7 @@ function isUndefined(arg) { return arg === void 0; } -},{}],51:[function(require,module,exports){ +},{}],49:[function(require,module,exports){ (function (process){ // Growl - Copyright TJ Holowaychuk (MIT Licensed) @@ -9926,7 +9933,7 @@ function growl(msg, options, fn) { }; }).call(this,require('_process')) -},{"_process":58,"child_process":43,"fs":43,"os":56,"path":43}],52:[function(require,module,exports){ +},{"_process":67,"child_process":42,"fs":42,"os":65,"path":42}],50:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = nBytes * 8 - mLen - 1 @@ -10012,7 +10019,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],53:[function(require,module,exports){ +},{}],51:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { @@ -10037,7 +10044,7 @@ if (typeof Object.create === 'function') { } } -},{}],54:[function(require,module,exports){ +},{}],52:[function(require,module,exports){ /** * Determine if an object is Buffer * @@ -10056,146 +10063,2176 @@ module.exports = function (obj) { )) } -},{}],55:[function(require,module,exports){ -(function (process){ -var path = require('path'); -var fs = require('fs'); -var _0777 = parseInt('0777', 8); +},{}],53:[function(require,module,exports){ +var toString = {}.toString; -module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; -function mkdirP (p, opts, f, made) { - if (typeof opts === 'function') { - f = opts; - opts = {}; - } - else if (!opts || typeof opts !== 'object') { - opts = { mode: opts }; - } - - var mode = opts.mode; - var xfs = opts.fs || fs; - - if (mode === undefined) { - mode = _0777 & (~process.umask()); - } - if (!made) made = null; - - var cb = f || function () {}; - p = path.resolve(p); - - xfs.mkdir(p, mode, function (er) { - if (!er) { - made = made || p; - return cb(null, made); +},{}],54:[function(require,module,exports){ +(function (global){ +/*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */ +;(function () { + // Detect the `define` function exposed by asynchronous module loaders. The + // strict `define` check is necessary for compatibility with `r.js`. + var isLoader = typeof define === "function" && define.amd; + + // A set of types used to distinguish objects from primitives. + var objectTypes = { + "function": true, + "object": true + }; + + // Detect the `exports` object exposed by CommonJS implementations. + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + + // Use the `global` object exposed by Node (including Browserify via + // `insert-module-globals`), Narwhal, and Ringo as the default context, + // and the `window` object in browsers. Rhino exports a `global` function + // instead. + var root = objectTypes[typeof window] && window || this, + freeGlobal = freeExports && objectTypes[typeof module] && module && !module.nodeType && typeof global == "object" && global; + + if (freeGlobal && (freeGlobal["global"] === freeGlobal || freeGlobal["window"] === freeGlobal || freeGlobal["self"] === freeGlobal)) { + root = freeGlobal; + } + + // Public: Initializes JSON 3 using the given `context` object, attaching the + // `stringify` and `parse` functions to the specified `exports` object. + function runInContext(context, exports) { + context || (context = root["Object"]()); + exports || (exports = root["Object"]()); + + // Native constructor aliases. + var Number = context["Number"] || root["Number"], + String = context["String"] || root["String"], + Object = context["Object"] || root["Object"], + Date = context["Date"] || root["Date"], + SyntaxError = context["SyntaxError"] || root["SyntaxError"], + TypeError = context["TypeError"] || root["TypeError"], + Math = context["Math"] || root["Math"], + nativeJSON = context["JSON"] || root["JSON"]; + + // Delegate to the native `stringify` and `parse` implementations. + if (typeof nativeJSON == "object" && nativeJSON) { + exports.stringify = nativeJSON.stringify; + exports.parse = nativeJSON.parse; + } + + // Convenience aliases. + var objectProto = Object.prototype, + getClass = objectProto.toString, + isProperty, forEach, undef; + + // Test the `Date#getUTC*` methods. Based on work by @Yaffle. + var isExtended = new Date(-3509827334573292); + try { + // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical + // results for certain dates in Opera >= 10.53. + isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 && + // Safari < 2.0.2 stores the internal millisecond time value correctly, + // but clips the values returned by the date methods to the range of + // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]). + isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708; + } catch (exception) {} + + // Internal: Determines whether the native `JSON.stringify` and `parse` + // implementations are spec-compliant. Based on work by Ken Snyder. + function has(name) { + if (has[name] !== undef) { + // Return cached feature test result. + return has[name]; + } + var isSupported; + if (name == "bug-string-char-index") { + // IE <= 7 doesn't support accessing string characters using square + // bracket notation. IE 8 only supports this for primitives. + isSupported = "a"[0] != "a"; + } else if (name == "json") { + // Indicates whether both `JSON.stringify` and `JSON.parse` are + // supported. + isSupported = has("json-stringify") && has("json-parse"); + } else { + var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'; + // Test `JSON.stringify`. + if (name == "json-stringify") { + var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended; + if (stringifySupported) { + // A test function object with a custom `toJSON` method. + (value = function () { + return 1; + }).toJSON = value; + try { + stringifySupported = + // Firefox 3.1b1 and b2 serialize string, number, and boolean + // primitives as object literals. + stringify(0) === "0" && + // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object + // literals. + stringify(new Number()) === "0" && + stringify(new String()) == '""' && + // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or + // does not define a canonical JSON representation (this applies to + // objects with `toJSON` properties as well, *unless* they are nested + // within an object or array). + stringify(getClass) === undef && + // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and + // FF 3.1b3 pass this test. + stringify(undef) === undef && + // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s, + // respectively, if the value is omitted entirely. + stringify() === undef && + // FF 3.1b1, 2 throw an error if the given value is not a number, + // string, array, object, Boolean, or `null` literal. This applies to + // objects with custom `toJSON` methods as well, unless they are nested + // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON` + // methods entirely. + stringify(value) === "1" && + stringify([value]) == "[1]" && + // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of + // `"[null]"`. + stringify([undef]) == "[null]" && + // YUI 3.0.0b1 fails to serialize `null` literals. + stringify(null) == "null" && + // FF 3.1b1, 2 halts serialization if an array contains a function: + // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3 + // elides non-JSON values from objects and arrays, unless they + // define custom `toJSON` methods. + stringify([undef, getClass, null]) == "[null,null,null]" && + // Simple serialization test. FF 3.1b1 uses Unicode escape sequences + // where character escape codes are expected (e.g., `\b` => `\u0008`). + stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized && + // FF 3.1b1 and b2 ignore the `filter` and `width` arguments. + stringify(null, value) === "1" && + stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" && + // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly + // serialize extended years. + stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' && + // The milliseconds are optional in ES 5, but required in 5.1. + stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' && + // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative + // four-digit years instead of six-digit years. Credits: @Yaffle. + stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' && + // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond + // values less than 1000. Credits: @Yaffle. + stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"'; + } catch (exception) { + stringifySupported = false; + } + } + isSupported = stringifySupported; } - switch (er.code) { - case 'ENOENT': - mkdirP(path.dirname(p), opts, function (er, made) { - if (er) cb(er, made); - else mkdirP(p, opts, cb, made); - }); - break; + // Test `JSON.parse`. + if (name == "json-parse") { + var parse = exports.parse; + if (typeof parse == "function") { + try { + // FF 3.1b1, b2 will throw an exception if a bare literal is provided. + // Conforming implementations should also coerce the initial argument to + // a string prior to parsing. + if (parse("0") === 0 && !parse(false)) { + // Simple parsing test. + value = parse(serialized); + var parseSupported = value["a"].length == 5 && value["a"][0] === 1; + if (parseSupported) { + try { + // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings. + parseSupported = !parse('"\t"'); + } catch (exception) {} + if (parseSupported) { + try { + // FF 4.0 and 4.0.1 allow leading `+` signs and leading + // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow + // certain octal literals. + parseSupported = parse("01") !== 1; + } catch (exception) {} + } + if (parseSupported) { + try { + // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal + // points. These environments, along with FF 3.1b1 and 2, + // also allow trailing commas in JSON objects and arrays. + parseSupported = parse("1.") !== 1; + } catch (exception) {} + } + } + } + } catch (exception) { + parseSupported = false; + } + } + isSupported = parseSupported; + } + } + return has[name] = !!isSupported; + } + + if (!has("json")) { + // Common `[[Class]]` name aliases. + var functionClass = "[object Function]", + dateClass = "[object Date]", + numberClass = "[object Number]", + stringClass = "[object String]", + arrayClass = "[object Array]", + booleanClass = "[object Boolean]"; + + // Detect incomplete support for accessing string characters by index. + var charIndexBuggy = has("bug-string-char-index"); + + // Define additional utility methods if the `Date` methods are buggy. + if (!isExtended) { + var floor = Math.floor; + // A mapping between the months of the year and the number of days between + // January 1st and the first of the respective month. + var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; + // Internal: Calculates the number of days between the Unix epoch and the + // first day of the given month. + var getDay = function (year, month) { + return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400); + }; + } - // In the case of any other error, just see if there's a dir - // there already. If so, then hooray! If not, then something - // is borked. - default: - xfs.stat(p, function (er2, stat) { - // if the stat fails, then that's super weird. - // let the original error be the failure reason. - if (er2 || !stat.isDirectory()) cb(er, made) - else cb(null, made); - }); - break; + // Internal: Determines if a property is a direct property of the given + // object. Delegates to the native `Object#hasOwnProperty` method. + if (!(isProperty = objectProto.hasOwnProperty)) { + isProperty = function (property) { + var members = {}, constructor; + if ((members.__proto__ = null, members.__proto__ = { + // The *proto* property cannot be set multiple times in recent + // versions of Firefox and SeaMonkey. + "toString": 1 + }, members).toString != getClass) { + // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but + // supports the mutable *proto* property. + isProperty = function (property) { + // Capture and break the object's prototype chain (see section 8.6.2 + // of the ES 5.1 spec). The parenthesized expression prevents an + // unsafe transformation by the Closure Compiler. + var original = this.__proto__, result = property in (this.__proto__ = null, this); + // Restore the original prototype chain. + this.__proto__ = original; + return result; + }; + } else { + // Capture a reference to the top-level `Object` constructor. + constructor = members.constructor; + // Use the `constructor` property to simulate `Object#hasOwnProperty` in + // other environments. + isProperty = function (property) { + var parent = (this.constructor || constructor).prototype; + return property in this && !(property in parent && this[property] === parent[property]); + }; + } + members = null; + return isProperty.call(this, property); + }; + } + + // Internal: Normalizes the `for...in` iteration algorithm across + // environments. Each enumerated key is yielded to a `callback` function. + forEach = function (object, callback) { + var size = 0, Properties, members, property; + + // Tests for bugs in the current environment's `for...in` algorithm. The + // `valueOf` property inherits the non-enumerable flag from + // `Object.prototype` in older versions of IE, Netscape, and Mozilla. + (Properties = function () { + this.valueOf = 0; + }).prototype.valueOf = 0; + + // Iterate over a new instance of the `Properties` class. + members = new Properties(); + for (property in members) { + // Ignore all properties inherited from `Object.prototype`. + if (isProperty.call(members, property)) { + size++; + } } - }); -} + Properties = members = null; + + // Normalize the iteration algorithm. + if (!size) { + // A list of non-enumerable properties inherited from `Object.prototype`. + members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"]; + // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable + // properties. + forEach = function (object, callback) { + var isFunction = getClass.call(object) == functionClass, property, length; + var hasProperty = !isFunction && typeof object.constructor != "function" && objectTypes[typeof object.hasOwnProperty] && object.hasOwnProperty || isProperty; + for (property in object) { + // Gecko <= 1.0 enumerates the `prototype` property of functions under + // certain conditions; IE does not. + if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) { + callback(property); + } + } + // Manually invoke the callback for each non-enumerable property. + for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property)); + }; + } else if (size == 2) { + // Safari <= 2.0.4 enumerates shadowed properties twice. + forEach = function (object, callback) { + // Create a set of iterated properties. + var members = {}, isFunction = getClass.call(object) == functionClass, property; + for (property in object) { + // Store each property name to prevent double enumeration. The + // `prototype` property of functions is not enumerated due to cross- + // environment inconsistencies. + if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) { + callback(property); + } + } + }; + } else { + // No bugs detected; use the standard `for...in` algorithm. + forEach = function (object, callback) { + var isFunction = getClass.call(object) == functionClass, property, isConstructor; + for (property in object) { + if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) { + callback(property); + } + } + // Manually invoke the callback for the `constructor` property due to + // cross-environment inconsistencies. + if (isConstructor || isProperty.call(object, (property = "constructor"))) { + callback(property); + } + }; + } + return forEach(object, callback); + }; -mkdirP.sync = function sync (p, opts, made) { - if (!opts || typeof opts !== 'object') { - opts = { mode: opts }; - } - - var mode = opts.mode; - var xfs = opts.fs || fs; - - if (mode === undefined) { - mode = _0777 & (~process.umask()); - } - if (!made) made = null; + // Public: Serializes a JavaScript `value` as a JSON string. The optional + // `filter` argument may specify either a function that alters how object and + // array members are serialized, or an array of strings and numbers that + // indicates which properties should be serialized. The optional `width` + // argument may be either a string or number that specifies the indentation + // level of the output. + if (!has("json-stringify")) { + // Internal: A map of control characters and their escaped equivalents. + var Escapes = { + 92: "\\\\", + 34: '\\"', + 8: "\\b", + 12: "\\f", + 10: "\\n", + 13: "\\r", + 9: "\\t" + }; - p = path.resolve(p); + // Internal: Converts `value` into a zero-padded string such that its + // length is at least equal to `width`. The `width` must be <= 6. + var leadingZeroes = "000000"; + var toPaddedString = function (width, value) { + // The `|| 0` expression is necessary to work around a bug in + // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`. + return (leadingZeroes + (value || 0)).slice(-width); + }; - try { - xfs.mkdirSync(p, mode); - made = made || p; - } - catch (err0) { - switch (err0.code) { - case 'ENOENT' : - made = sync(path.dirname(p), opts, made); - sync(p, opts, made); + // Internal: Double-quotes a string `value`, replacing all ASCII control + // characters (characters with code unit values between 0 and 31) with + // their escaped equivalents. This is an implementation of the + // `Quote(value)` operation defined in ES 5.1 section 15.12.3. + var unicodePrefix = "\\u00"; + var quote = function (value) { + var result = '"', index = 0, length = value.length, useCharIndex = !charIndexBuggy || length > 10; + var symbols = useCharIndex && (charIndexBuggy ? value.split("") : value); + for (; index < length; index++) { + var charCode = value.charCodeAt(index); + // If the character is a control character, append its Unicode or + // shorthand escape sequence; otherwise, append the character as-is. + switch (charCode) { + case 8: case 9: case 10: case 12: case 13: case 34: case 92: + result += Escapes[charCode]; break; + default: + if (charCode < 32) { + result += unicodePrefix + toPaddedString(2, charCode.toString(16)); + break; + } + result += useCharIndex ? symbols[index] : value.charAt(index); + } + } + return result + '"'; + }; - // In the case of any other error, just see if there's a dir - // there already. If so, then hooray! If not, then something - // is borked. - default: - var stat; - try { - stat = xfs.statSync(p); + // Internal: Recursively serializes an object. Implements the + // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations. + var serialize = function (property, object, callback, properties, whitespace, indentation, stack) { + var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result; + try { + // Necessary for host object support. + value = object[property]; + } catch (exception) {} + if (typeof value == "object" && value) { + className = getClass.call(value); + if (className == dateClass && !isProperty.call(value, "toJSON")) { + if (value > -1 / 0 && value < 1 / 0) { + // Dates are serialized according to the `Date#toJSON` method + // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15 + // for the ISO 8601 date time string format. + if (getDay) { + // Manually compute the year, month, date, hours, minutes, + // seconds, and milliseconds if the `getUTC*` methods are + // buggy. Adapted from @Yaffle's `date-shim` project. + date = floor(value / 864e5); + for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++); + for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++); + date = 1 + date - getDay(year, month); + // The `time` value specifies the time within the day (see ES + // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used + // to compute `A modulo B`, as the `%` operator does not + // correspond to the `modulo` operation for negative numbers. + time = (value % 864e5 + 864e5) % 864e5; + // The hours, minutes, seconds, and milliseconds are obtained by + // decomposing the time within the day. See section 15.9.1.10. + hours = floor(time / 36e5) % 24; + minutes = floor(time / 6e4) % 60; + seconds = floor(time / 1e3) % 60; + milliseconds = time % 1e3; + } else { + year = value.getUTCFullYear(); + month = value.getUTCMonth(); + date = value.getUTCDate(); + hours = value.getUTCHours(); + minutes = value.getUTCMinutes(); + seconds = value.getUTCSeconds(); + milliseconds = value.getUTCMilliseconds(); } - catch (err1) { - throw err0; + // Serialize extended years correctly. + value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) + + "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) + + // Months, dates, hours, minutes, and seconds should have two + // digits; milliseconds should have three. + "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) + + // Milliseconds are optional in ES 5.0, but required in 5.1. + "." + toPaddedString(3, milliseconds) + "Z"; + } else { + value = null; + } + } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) { + // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the + // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3 + // ignores all `toJSON` methods on these objects unless they are + // defined directly on an instance. + value = value.toJSON(property); + } + } + if (callback) { + // If a replacement function was provided, call it to obtain the value + // for serialization. + value = callback.call(object, property, value); + } + if (value === null) { + return "null"; + } + className = getClass.call(value); + if (className == booleanClass) { + // Booleans are represented literally. + return "" + value; + } else if (className == numberClass) { + // JSON numbers must be finite. `Infinity` and `NaN` are serialized as + // `"null"`. + return value > -1 / 0 && value < 1 / 0 ? "" + value : "null"; + } else if (className == stringClass) { + // Strings are double-quoted and escaped. + return quote("" + value); + } + // Recursively serialize objects and arrays. + if (typeof value == "object") { + // Check for cyclic structures. This is a linear search; performance + // is inversely proportional to the number of unique nested objects. + for (length = stack.length; length--;) { + if (stack[length] === value) { + // Cyclic structures cannot be serialized by `JSON.stringify`. + throw TypeError(); + } + } + // Add the object to the stack of traversed objects. + stack.push(value); + results = []; + // Save the current indentation level and indent one additional level. + prefix = indentation; + indentation += whitespace; + if (className == arrayClass) { + // Recursively serialize array elements. + for (index = 0, length = value.length; index < length; index++) { + element = serialize(index, value, callback, properties, whitespace, indentation, stack); + results.push(element === undef ? "null" : element); + } + result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]"; + } else { + // Recursively serialize object members. Members are selected from + // either a user-specified list of property names, or the object + // itself. + forEach(properties || value, function (property) { + var element = serialize(property, value, callback, properties, whitespace, indentation, stack); + if (element !== undef) { + // According to ES 5.1 section 15.12.3: "If `gap` {whitespace} + // is not the empty string, let `member` {quote(property) + ":"} + // be the concatenation of `member` and the `space` character." + // The "`space` character" refers to the literal space + // character, not the `space` {width} argument provided to + // `JSON.stringify`. + results.push(quote(property) + ":" + (whitespace ? " " : "") + element); } - if (!stat.isDirectory()) throw err0; - break; - } - } - - return made; -}; + }); + result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}"; + } + // Remove the object from the traversed object stack. + stack.pop(); + return result; + } + }; -}).call(this,require('_process')) -},{"_process":58,"fs":43,"path":43}],56:[function(require,module,exports){ -exports.endianness = function () { return 'LE' }; + // Public: `JSON.stringify`. See ES 5.1 section 15.12.3. + exports.stringify = function (source, filter, width) { + var whitespace, callback, properties, className; + if (objectTypes[typeof filter] && filter) { + if ((className = getClass.call(filter)) == functionClass) { + callback = filter; + } else if (className == arrayClass) { + // Convert the property names array into a makeshift set. + properties = {}; + for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1)); + } + } + if (width) { + if ((className = getClass.call(width)) == numberClass) { + // Convert the `width` to an integer and create a string containing + // `width` number of space characters. + if ((width -= width % 1) > 0) { + for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " "); + } + } else if (className == stringClass) { + whitespace = width.length <= 10 ? width : width.slice(0, 10); + } + } + // Opera <= 7.54u2 discards the values associated with empty string keys + // (`""`) only if they are used directly within an object member list + // (e.g., `!("" in { "": 1})`). + return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []); + }; + } -exports.hostname = function () { - if (typeof location !== 'undefined') { - return location.hostname - } - else return ''; -}; + // Public: Parses a JSON source string. + if (!has("json-parse")) { + var fromCharCode = String.fromCharCode; + + // Internal: A map of escaped control characters and their unescaped + // equivalents. + var Unescapes = { + 92: "\\", + 34: '"', + 47: "/", + 98: "\b", + 116: "\t", + 110: "\n", + 102: "\f", + 114: "\r" + }; -exports.loadavg = function () { return [] }; + // Internal: Stores the parser state. + var Index, Source; -exports.uptime = function () { return 0 }; + // Internal: Resets the parser state and throws a `SyntaxError`. + var abort = function () { + Index = Source = null; + throw SyntaxError(); + }; -exports.freemem = function () { - return Number.MAX_VALUE; -}; + // Internal: Returns the next token, or `"$"` if the parser has reached + // the end of the source string. A token may be a string, number, `null` + // literal, or Boolean literal. + var lex = function () { + var source = Source, length = source.length, value, begin, position, isSigned, charCode; + while (Index < length) { + charCode = source.charCodeAt(Index); + switch (charCode) { + case 9: case 10: case 13: case 32: + // Skip whitespace tokens, including tabs, carriage returns, line + // feeds, and space characters. + Index++; + break; + case 123: case 125: case 91: case 93: case 58: case 44: + // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at + // the current position. + value = charIndexBuggy ? source.charAt(Index) : source[Index]; + Index++; + return value; + case 34: + // `"` delimits a JSON string; advance to the next character and + // begin parsing the string. String tokens are prefixed with the + // sentinel `@` character to distinguish them from punctuators and + // end-of-string tokens. + for (value = "@", Index++; Index < length;) { + charCode = source.charCodeAt(Index); + if (charCode < 32) { + // Unescaped ASCII control characters (those with a code unit + // less than the space character) are not permitted. + abort(); + } else if (charCode == 92) { + // A reverse solidus (`\`) marks the beginning of an escaped + // control character (including `"`, `\`, and `/`) or Unicode + // escape sequence. + charCode = source.charCodeAt(++Index); + switch (charCode) { + case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114: + // Revive escaped control characters. + value += Unescapes[charCode]; + Index++; + break; + case 117: + // `\u` marks the beginning of a Unicode escape sequence. + // Advance to the first character and validate the + // four-digit code point. + begin = ++Index; + for (position = Index + 4; Index < position; Index++) { + charCode = source.charCodeAt(Index); + // A valid sequence comprises four hexdigits (case- + // insensitive) that form a single hexadecimal value. + if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) { + // Invalid Unicode escape sequence. + abort(); + } + } + // Revive the escaped character. + value += fromCharCode("0x" + source.slice(begin, Index)); + break; + default: + // Invalid escape sequence. + abort(); + } + } else { + if (charCode == 34) { + // An unescaped double-quote character marks the end of the + // string. + break; + } + charCode = source.charCodeAt(Index); + begin = Index; + // Optimize for the common case where a string is valid. + while (charCode >= 32 && charCode != 92 && charCode != 34) { + charCode = source.charCodeAt(++Index); + } + // Append the string as-is. + value += source.slice(begin, Index); + } + } + if (source.charCodeAt(Index) == 34) { + // Advance to the next character and return the revived string. + Index++; + return value; + } + // Unterminated string. + abort(); + default: + // Parse numbers and literals. + begin = Index; + // Advance past the negative sign, if one is specified. + if (charCode == 45) { + isSigned = true; + charCode = source.charCodeAt(++Index); + } + // Parse an integer or floating-point value. + if (charCode >= 48 && charCode <= 57) { + // Leading zeroes are interpreted as octal literals. + if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) { + // Illegal octal literal. + abort(); + } + isSigned = false; + // Parse the integer component. + for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++); + // Floats cannot contain a leading decimal point; however, this + // case is already accounted for by the parser. + if (source.charCodeAt(Index) == 46) { + position = ++Index; + // Parse the decimal component. + for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); + if (position == Index) { + // Illegal trailing decimal. + abort(); + } + Index = position; + } + // Parse exponents. The `e` denoting the exponent is + // case-insensitive. + charCode = source.charCodeAt(Index); + if (charCode == 101 || charCode == 69) { + charCode = source.charCodeAt(++Index); + // Skip past the sign following the exponent, if one is + // specified. + if (charCode == 43 || charCode == 45) { + Index++; + } + // Parse the exponential component. + for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); + if (position == Index) { + // Illegal empty exponent. + abort(); + } + Index = position; + } + // Coerce the parsed value to a JavaScript number. + return +source.slice(begin, Index); + } + // A negative sign may only precede numbers. + if (isSigned) { + abort(); + } + // `true`, `false`, and `null` literals. + if (source.slice(Index, Index + 4) == "true") { + Index += 4; + return true; + } else if (source.slice(Index, Index + 5) == "false") { + Index += 5; + return false; + } else if (source.slice(Index, Index + 4) == "null") { + Index += 4; + return null; + } + // Unrecognized token. + abort(); + } + } + // Return the sentinel `$` character if the parser has reached the end + // of the source string. + return "$"; + }; -exports.totalmem = function () { - return Number.MAX_VALUE; -}; + // Internal: Parses a JSON `value` token. + var get = function (value) { + var results, hasMembers; + if (value == "$") { + // Unexpected end of input. + abort(); + } + if (typeof value == "string") { + if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") { + // Remove the sentinel `@` character. + return value.slice(1); + } + // Parse object and array literals. + if (value == "[") { + // Parses a JSON array, returning a new JavaScript array. + results = []; + for (;; hasMembers || (hasMembers = true)) { + value = lex(); + // A closing square bracket marks the end of the array literal. + if (value == "]") { + break; + } + // If the array literal contains elements, the current token + // should be a comma separating the previous element from the + // next. + if (hasMembers) { + if (value == ",") { + value = lex(); + if (value == "]") { + // Unexpected trailing `,` in array literal. + abort(); + } + } else { + // A `,` must separate each array element. + abort(); + } + } + // Elisions and leading commas are not permitted. + if (value == ",") { + abort(); + } + results.push(get(value)); + } + return results; + } else if (value == "{") { + // Parses a JSON object, returning a new JavaScript object. + results = {}; + for (;; hasMembers || (hasMembers = true)) { + value = lex(); + // A closing curly brace marks the end of the object literal. + if (value == "}") { + break; + } + // If the object literal contains members, the current token + // should be a comma separator. + if (hasMembers) { + if (value == ",") { + value = lex(); + if (value == "}") { + // Unexpected trailing `,` in object literal. + abort(); + } + } else { + // A `,` must separate each object member. + abort(); + } + } + // Leading commas are not permitted, object property names must be + // double-quoted strings, and a `:` must separate each property + // name and value. + if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") { + abort(); + } + results[value.slice(1)] = get(lex()); + } + return results; + } + // Unexpected token encountered. + abort(); + } + return value; + }; -exports.cpus = function () { return [] }; + // Internal: Updates a traversed object member. + var update = function (source, property, callback) { + var element = walk(source, property, callback); + if (element === undef) { + delete source[property]; + } else { + source[property] = element; + } + }; -exports.type = function () { return 'Browser' }; + // Internal: Recursively traverses a parsed JSON object, invoking the + // `callback` function for each value. This is an implementation of the + // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2. + var walk = function (source, property, callback) { + var value = source[property], length; + if (typeof value == "object" && value) { + // `forEach` can't be used to traverse an array in Opera <= 8.54 + // because its `Object#hasOwnProperty` implementation returns `false` + // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`). + if (getClass.call(value) == arrayClass) { + for (length = value.length; length--;) { + update(value, length, callback); + } + } else { + forEach(value, function (property) { + update(value, property, callback); + }); + } + } + return callback.call(source, property, value); + }; -exports.release = function () { - if (typeof navigator !== 'undefined') { - return navigator.appVersion; + // Public: `JSON.parse`. See ES 5.1 section 15.12.2. + exports.parse = function (source, callback) { + var result, value; + Index = 0; + Source = "" + source; + result = get(lex()); + // If a JSON string contains multiple tokens, it is invalid. + if (lex() != "$") { + abort(); + } + // Reset the parser state. + Index = Source = null; + return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result; + }; + } } - return ''; -}; - -exports.networkInterfaces -= exports.getNetworkInterfaces -= function () { return {} }; -exports.arch = function () { return 'javascript' }; + exports["runInContext"] = runInContext; + return exports; + } + + if (freeExports && !isLoader) { + // Export for CommonJS environments. + runInContext(root, freeExports); + } else { + // Export for web browsers and JavaScript engines. + var nativeJSON = root.JSON, + previousJSON = root["JSON3"], + isRestored = false; + + var JSON3 = runInContext(root, (root["JSON3"] = { + // Public: Restores the original value of the global `JSON` object and + // returns a reference to the `JSON3` object. + "noConflict": function () { + if (!isRestored) { + isRestored = true; + root.JSON = nativeJSON; + root["JSON3"] = previousJSON; + nativeJSON = previousJSON = null; + } + return JSON3; + } + })); + + root.JSON = { + "parse": JSON3.parse, + "stringify": JSON3.stringify + }; + } + + // Export for asynchronous module loaders. + if (isLoader) { + define(function () { + return JSON3; + }); + } +}).call(this); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],55:[function(require,module,exports){ +/** + * lodash 3.2.0 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ +var baseCopy = require('lodash._basecopy'), + keys = require('lodash.keys'); + +/** + * The base implementation of `_.assign` without support for argument juggling, + * multiple sources, and `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ +function baseAssign(object, source) { + return source == null + ? object + : baseCopy(source, keys(source), object); +} + +module.exports = baseAssign; + +},{"lodash._basecopy":56,"lodash.keys":63}],56:[function(require,module,exports){ +/** + * lodash 3.0.1 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property names to copy. + * @param {Object} [object={}] The object to copy properties to. + * @returns {Object} Returns `object`. + */ +function baseCopy(source, props, object) { + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; +} + +module.exports = baseCopy; + +},{}],57:[function(require,module,exports){ +/** + * lodash 3.0.3 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} prototype The object to inherit from. + * @returns {Object} Returns the new object. + */ +var baseCreate = (function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object; + object.prototype = undefined; + } + return result || {}; + }; +}()); + +/** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ +function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +module.exports = baseCreate; + +},{}],58:[function(require,module,exports){ +/** + * lodash 3.9.1 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** `Object#toString` result references. */ +var funcTag = '[object Function]'; + +/** Used to detect host constructors (Safari > 5). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** + * Checks if `value` is object-like. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var fnToString = Function.prototype.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; +} + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in older versions of Chrome and Safari which return 'function' for regexes + // and Safari 8 equivalents which return 'object' for typed array constructors. + return isObject(value) && objToString.call(value) == funcTag; +} + +/** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ +function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is a native function. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ +function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); +} + +module.exports = getNative; + +},{}],59:[function(require,module,exports){ +/** + * lodash 3.0.9 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** Used to detect unsigned integer values. */ +var reIsUint = /^\d+$/; + +/** + * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * of an array-like value. + */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new function. + */ +function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; +} + +/** + * Gets the "length" property value of `object`. + * + * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) + * that affects Safari on at least iOS 8.1-8.3 ARM64. + * + * @private + * @param {Object} object The object to query. + * @returns {*} Returns the "length" value. + */ +var getLength = baseProperty('length'); + +/** + * Checks if `value` is array-like. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + */ +function isArrayLike(value) { + return value != null && isLength(getLength(value)); +} + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; +} + +/** + * Checks if the provided arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`. + */ +function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object)) { + var other = object[index]; + return value === value ? (value === other) : (other !== other); + } + return false; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength). + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + */ +function isLength(value) { + return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ +function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +module.exports = isIterateeCall; + +},{}],60:[function(require,module,exports){ +/** + * lodash 3.1.1 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ +var baseAssign = require('lodash._baseassign'), + baseCreate = require('lodash._basecreate'), + isIterateeCall = require('lodash._isiterateecall'); + +/** + * Creates an object that inherits from the given `prototype` object. If a + * `properties` object is provided its own enumerable properties are assigned + * to the created object. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ +function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; +} + +module.exports = create; + +},{"lodash._baseassign":55,"lodash._basecreate":57,"lodash._isiterateecall":59}],61:[function(require,module,exports){ +/** + * lodash 3.0.8 (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright 2012-2016 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new function. + */ +function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; +} + +/** + * Gets the "length" property value of `object`. + * + * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) + * that affects Safari on at least iOS 8.1-8.3 ARM64. + * + * @private + * @param {Object} object The object to query. + * @returns {*} Returns the "length" value. + */ +var getLength = baseProperty('length'); + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +function isArguments(value) { + // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode. + return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && + (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); +} + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(getLength(value)) && !isFunction(value); +} + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); +} + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8 which returns 'object' for typed array and weak map constructors, + // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This function is loosely based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +module.exports = isArguments; + +},{}],62:[function(require,module,exports){ +/** + * lodash 3.0.4 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** `Object#toString` result references. */ +var arrayTag = '[object Array]', + funcTag = '[object Function]'; + +/** Used to detect host constructors (Safari > 5). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** + * Checks if `value` is object-like. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var fnToString = Function.prototype.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeIsArray = getNative(Array, 'isArray'); + +/** + * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) + * of an array-like value. + */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + */ +function isLength(value) { + return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(function() { return arguments; }()); + * // => false + */ +var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; +}; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in older versions of Chrome and Safari which return 'function' for regexes + // and Safari 8 equivalents which return 'object' for typed array constructors. + return isObject(value) && objToString.call(value) == funcTag; +} + +/** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ +function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is a native function. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ +function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); +} + +module.exports = isArray; + +},{}],63:[function(require,module,exports){ +/** + * lodash 3.1.2 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ +var getNative = require('lodash._getnative'), + isArguments = require('lodash.isarguments'), + isArray = require('lodash.isarray'); + +/** Used to detect unsigned integer values. */ +var reIsUint = /^\d+$/; + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeKeys = getNative(Object, 'keys'); + +/** + * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) + * of an array-like value. + */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new function. + */ +function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; +} + +/** + * Gets the "length" property value of `object`. + * + * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) + * that affects Safari on at least iOS 8.1-8.3 ARM64. + * + * @private + * @param {Object} object The object to query. + * @returns {*} Returns the "length" value. + */ +var getLength = baseProperty('length'); + +/** + * Checks if `value` is array-like. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + */ +function isArrayLike(value) { + return value != null && isLength(getLength(value)); +} + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + */ +function isLength(value) { + return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * A fallback implementation of `Object.keys` which creates an array of the + * own enumerable property names of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function shimKeys(object) { + var props = keysIn(object), + propsLength = props.length, + length = propsLength && object.length; + + var allowIndexes = !!length && isLength(length) && + (isArray(object) || isArguments(object)); + + var index = -1, + result = []; + + while (++index < propsLength) { + var key = props[index]; + if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; +} + +/** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ +function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) + * for more details. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ +var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if ((typeof Ctor == 'function' && Ctor.prototype === object) || + (typeof object != 'function' && isArrayLike(object))) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; +}; + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = (length && isLength(length) && + (isArray(object) || isArguments(object)) && length) || 0; + + var Ctor = object.constructor, + index = -1, + isProto = typeof Ctor == 'function' && Ctor.prototype === object, + result = Array(length), + skipIndexes = length > 0; + + while (++index < length) { + result[index] = (index + ''); + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && + !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; +} + +module.exports = keys; + +},{"lodash._getnative":58,"lodash.isarguments":61,"lodash.isarray":62}],64:[function(require,module,exports){ +(function (process){ +var path = require('path'); +var fs = require('fs'); +var _0777 = parseInt('0777', 8); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, opts, f, made) { + if (typeof opts === 'function') { + f = opts; + opts = {}; + } + else if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = _0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + p = path.resolve(p); + + xfs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), opts, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, opts, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + xfs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, opts, made) { + if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = _0777 & (~process.umask()); + } + if (!made) made = null; + + p = path.resolve(p); + + try { + xfs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), opts, made); + sync(p, opts, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = xfs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; + +}).call(this,require('_process')) +},{"_process":67,"fs":42,"path":42}],65:[function(require,module,exports){ +exports.endianness = function () { return 'LE' }; + +exports.hostname = function () { + if (typeof location !== 'undefined') { + return location.hostname + } + else return ''; +}; + +exports.loadavg = function () { return [] }; + +exports.uptime = function () { return 0 }; + +exports.freemem = function () { + return Number.MAX_VALUE; +}; + +exports.totalmem = function () { + return Number.MAX_VALUE; +}; + +exports.cpus = function () { return [] }; + +exports.type = function () { return 'Browser' }; + +exports.release = function () { + if (typeof navigator !== 'undefined') { + return navigator.appVersion; + } + return ''; +}; + +exports.networkInterfaces += exports.getNetworkInterfaces += function () { return {} }; + +exports.arch = function () { return 'javascript' }; exports.platform = function () { return 'browser' }; @@ -10205,7 +12242,7 @@ exports.tmpdir = exports.tmpDir = function () { exports.EOL = '\n'; -},{}],57:[function(require,module,exports){ +},{}],66:[function(require,module,exports){ (function (process){ 'use strict'; @@ -10252,237 +12289,131 @@ function nextTick(fn, arg1, arg2, arg3) { } }).call(this,require('_process')) -},{"_process":58}],58:[function(require,module,exports){ +},{"_process":67}],67:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = setTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - clearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - setTimeout(drainQueue, 0); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],59:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -module.exports = Stream; - -var EE = require('events').EventEmitter; -var inherits = require('inherits'); - -inherits(Stream, EE); -Stream.Readable = require('readable-stream/readable.js'); -Stream.Writable = require('readable-stream/writable.js'); -Stream.Duplex = require('readable-stream/duplex.js'); -Stream.Transform = require('readable-stream/transform.js'); -Stream.PassThrough = require('readable-stream/passthrough.js'); - -// Backwards-compat with node 0.4.x -Stream.Stream = Stream; - +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. -// old-style streams. Note that the pipe method (the only relevant -// part of this class) is overridden in the Readable class. - -function Stream() { - EE.call(this); -} - -Stream.prototype.pipe = function(dest, options) { - var source = this; - - function ondata(chunk) { - if (dest.writable) { - if (false === dest.write(chunk) && source.pause) { - source.pause(); - } - } - } - - source.on('data', ondata); +var cachedSetTimeout; +var cachedClearTimeout; - function ondrain() { - if (source.readable && source.resume) { - source.resume(); +(function () { + try { + cachedSetTimeout = setTimeout; + } catch (e) { + cachedSetTimeout = function () { + throw new Error('setTimeout is not defined'); } } - - dest.on('drain', ondrain); - - // If the 'end' option is not supplied, dest.end() will be called when - // source gets the 'end' or 'close' events. Only dest.end() once. - if (!dest._isStdio && (!options || options.end !== false)) { - source.on('end', onend); - source.on('close', onclose); - } - - var didOnEnd = false; - function onend() { - if (didOnEnd) return; - didOnEnd = true; - - dest.end(); - } - - - function onclose() { - if (didOnEnd) return; - didOnEnd = true; - - if (typeof dest.destroy === 'function') dest.destroy(); - } - - // don't leave dangling pipes when there are errors. - function onerror(er) { - cleanup(); - if (EE.listenerCount(this, 'error') === 0) { - throw er; // Unhandled stream error in pipe. + try { + cachedClearTimeout = clearTimeout; + } catch (e) { + cachedClearTimeout = function () { + throw new Error('clearTimeout is not defined'); } } +} ()) +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; - source.on('error', onerror); - dest.on('error', onerror); - - // remove all the event listeners that were added. - function cleanup() { - source.removeListener('data', ondata); - dest.removeListener('drain', ondrain); +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} - source.removeListener('end', onend); - source.removeListener('close', onclose); +function drainQueue() { + if (draining) { + return; + } + var timeout = cachedSetTimeout(cleanUpNextTick); + draining = true; - source.removeListener('error', onerror); - dest.removeListener('error', onerror); + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + cachedClearTimeout(timeout); +} - source.removeListener('end', cleanup); - source.removeListener('close', cleanup); +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + cachedSetTimeout(drainQueue, 0); + } +}; - dest.removeListener('close', cleanup); - } +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; - source.on('end', cleanup); - source.on('close', cleanup); +function noop() {} - dest.on('close', cleanup); +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; - dest.emit('pipe', source); +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; - // Allow for unix-like usage: A.pipe(B).pipe(C) - return dest; +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); }; +process.umask = function() { return 0; }; -},{"events":50,"inherits":53,"readable-stream/duplex.js":61,"readable-stream/passthrough.js":67,"readable-stream/readable.js":68,"readable-stream/transform.js":69,"readable-stream/writable.js":70}],60:[function(require,module,exports){ -arguments[4][46][0].apply(exports,arguments) -},{"dup":46}],61:[function(require,module,exports){ +},{}],68:[function(require,module,exports){ module.exports = require("./lib/_stream_duplex.js") -},{"./lib/_stream_duplex.js":62}],62:[function(require,module,exports){ +},{"./lib/_stream_duplex.js":69}],69:[function(require,module,exports){ // a duplex stream is just a stream that is both readable and writable. // Since JS doesn't have multiple prototypal inheritance, this class // prototypally inherits from Readable, and then parasitically from @@ -10558,7 +12489,7 @@ function forEach(xs, f) { f(xs[i], i); } } -},{"./_stream_readable":64,"./_stream_writable":66,"core-util-is":47,"inherits":53,"process-nextick-args":57}],63:[function(require,module,exports){ +},{"./_stream_readable":71,"./_stream_writable":73,"core-util-is":45,"inherits":51,"process-nextick-args":66}],70:[function(require,module,exports){ // a passthrough stream. // basically just the most minimal sort of Transform stream. // Every written chunk gets output as-is. @@ -10585,7 +12516,7 @@ function PassThrough(options) { PassThrough.prototype._transform = function (chunk, encoding, cb) { cb(null, chunk); }; -},{"./_stream_transform":65,"core-util-is":47,"inherits":53}],64:[function(require,module,exports){ +},{"./_stream_transform":72,"core-util-is":45,"inherits":51}],71:[function(require,module,exports){ (function (process){ 'use strict'; @@ -11481,7 +13412,7 @@ function indexOf(xs, x) { return -1; } }).call(this,require('_process')) -},{"./_stream_duplex":62,"_process":58,"buffer":45,"buffer-shims":44,"core-util-is":47,"events":50,"inherits":53,"isarray":60,"process-nextick-args":57,"string_decoder/":71,"util":41}],65:[function(require,module,exports){ +},{"./_stream_duplex":69,"_process":67,"buffer":44,"buffer-shims":43,"core-util-is":45,"events":48,"inherits":51,"isarray":53,"process-nextick-args":66,"string_decoder/":79,"util":40}],72:[function(require,module,exports){ // a transform stream is a readable/writable stream where you do // something with the data. Sometimes it's called a "filter", // but that's not a great name for it, since that implies a thing where @@ -11662,7 +13593,7 @@ function done(stream, er) { return stream.push(null); } -},{"./_stream_duplex":62,"core-util-is":47,"inherits":53}],66:[function(require,module,exports){ +},{"./_stream_duplex":69,"core-util-is":45,"inherits":51}],73:[function(require,module,exports){ (function (process){ // A bit simpler than readable streams. // Implement an async ._write(chunk, encoding, cb), and it'll handle all @@ -12191,10 +14122,10 @@ function CorkedRequest(state) { }; } }).call(this,require('_process')) -},{"./_stream_duplex":62,"_process":58,"buffer":45,"buffer-shims":44,"core-util-is":47,"events":50,"inherits":53,"process-nextick-args":57,"util-deprecate":73}],67:[function(require,module,exports){ +},{"./_stream_duplex":69,"_process":67,"buffer":44,"buffer-shims":43,"core-util-is":45,"events":48,"inherits":51,"process-nextick-args":66,"util-deprecate":80}],74:[function(require,module,exports){ module.exports = require("./lib/_stream_passthrough.js") -},{"./lib/_stream_passthrough.js":63}],68:[function(require,module,exports){ +},{"./lib/_stream_passthrough.js":70}],75:[function(require,module,exports){ (function (process){ var Stream = (function (){ try { @@ -12214,13 +14145,142 @@ if (!process.browser && process.env.READABLE_STREAM === 'disable' && Stream) { } }).call(this,require('_process')) -},{"./lib/_stream_duplex.js":62,"./lib/_stream_passthrough.js":63,"./lib/_stream_readable.js":64,"./lib/_stream_transform.js":65,"./lib/_stream_writable.js":66,"_process":58}],69:[function(require,module,exports){ +},{"./lib/_stream_duplex.js":69,"./lib/_stream_passthrough.js":70,"./lib/_stream_readable.js":71,"./lib/_stream_transform.js":72,"./lib/_stream_writable.js":73,"_process":67}],76:[function(require,module,exports){ module.exports = require("./lib/_stream_transform.js") -},{"./lib/_stream_transform.js":65}],70:[function(require,module,exports){ +},{"./lib/_stream_transform.js":72}],77:[function(require,module,exports){ module.exports = require("./lib/_stream_writable.js") -},{"./lib/_stream_writable.js":66}],71:[function(require,module,exports){ +},{"./lib/_stream_writable.js":73}],78:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Stream; + +var EE = require('events').EventEmitter; +var inherits = require('inherits'); + +inherits(Stream, EE); +Stream.Readable = require('readable-stream/readable.js'); +Stream.Writable = require('readable-stream/writable.js'); +Stream.Duplex = require('readable-stream/duplex.js'); +Stream.Transform = require('readable-stream/transform.js'); +Stream.PassThrough = require('readable-stream/passthrough.js'); + +// Backwards-compat with node 0.4.x +Stream.Stream = Stream; + + + +// old-style streams. Note that the pipe method (the only relevant +// part of this class) is overridden in the Readable class. + +function Stream() { + EE.call(this); +} + +Stream.prototype.pipe = function(dest, options) { + var source = this; + + function ondata(chunk) { + if (dest.writable) { + if (false === dest.write(chunk) && source.pause) { + source.pause(); + } + } + } + + source.on('data', ondata); + + function ondrain() { + if (source.readable && source.resume) { + source.resume(); + } + } + + dest.on('drain', ondrain); + + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); + } + + var didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; + + dest.end(); + } + + + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + + if (typeof dest.destroy === 'function') dest.destroy(); + } + + // don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EE.listenerCount(this, 'error') === 0) { + throw er; // Unhandled stream error in pipe. + } + } + + source.on('error', onerror); + dest.on('error', onerror); + + // remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); + + source.removeListener('end', onend); + source.removeListener('close', onclose); + + source.removeListener('error', onerror); + dest.removeListener('error', onerror); + + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); + + dest.removeListener('close', cleanup); + } + + source.on('end', cleanup); + source.on('close', cleanup); + + dest.on('close', cleanup); + + dest.emit('pipe', source); + + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +}; + +},{"events":48,"inherits":51,"readable-stream/duplex.js":68,"readable-stream/passthrough.js":74,"readable-stream/readable.js":75,"readable-stream/transform.js":76,"readable-stream/writable.js":77}],79:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -12443,48 +14503,7 @@ function base64DetectIncompleteChar(buffer) { this.charLength = this.charReceived ? 3 : 0; } -},{"buffer":45}],72:[function(require,module,exports){ - -/** - * Expose `toIsoString`. - */ - -module.exports = toIsoString; - - -/** - * Turn a `date` into an ISO string. - * - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString - * - * @param {Date} date - * @return {String} - */ - -function toIsoString (date) { - return date.getUTCFullYear() - + '-' + pad(date.getUTCMonth() + 1) - + '-' + pad(date.getUTCDate()) - + 'T' + pad(date.getUTCHours()) - + ':' + pad(date.getUTCMinutes()) - + ':' + pad(date.getUTCSeconds()) - + '.' + String((date.getUTCMilliseconds()/1000).toFixed(3)).slice(2, 5) - + 'Z'; -} - - -/** - * Pad a `number` with a ten's place zero. - * - * @param {Number} number - * @return {String} - */ - -function pad (number) { - var n = number.toString(); - return n.length === 1 ? '0' + n : n; -} -},{}],73:[function(require,module,exports){ +},{"buffer":44}],80:[function(require,module,exports){ (function (global){ /** @@ -12555,14 +14574,14 @@ function config (name) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],74:[function(require,module,exports){ +},{}],81:[function(require,module,exports){ module.exports = function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function'; } -},{}],75:[function(require,module,exports){ +},{}],82:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -13152,4 +15171,4 @@ function hasOwnProperty(obj, prop) { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":74,"_process":58,"inherits":53}]},{},[1]); +},{"./support/isBuffer":81,"_process":67,"inherits":51}]},{},[1]); diff --git a/package.json b/package.json index 3840adf7f5..5114f2a3c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mocha", - "version": "2.5.3", + "version": "3.0.1", "description": "simple, flexible, fun test framework", "keywords": [ "mocha", @@ -11,328 +11,312 @@ ], "author": "TJ Holowaychuk ", "contributors": [ - "TJ Holowaychuk ", - "Travis Jeffery ", - "Christopher Hiller ", - "Daniel St. Jules ", - "Joshua Appelman ", - "David da Silva Contín ", - "Guillermo Rauch ", - "Ariel Mashraki ", - "Attila Domokos ", - "John Firebaugh ", - "Jo Liss ", - "Nathan Rajlich ", - "Nathan Houle ", - "Mike Pennisi ", - "James Carr ", - "Brendan Nee ", - "Glen Mailer ", - "Mislav Marohnić ", - "Aaron Heckmann ", - "Ryunosuke SATO ", - "Jonathan Ong ", - "Joshua Krall ", - "Maximilian Antoni ", - "hokaccha ", - "Domenic Denicola ", - "Forbes Lindesay ", - "Raynos ", - "Xavier Antoviaque ", - "Andreas Lind Petersen ", - "Ben Lindsey ", - "Mathieu Desvé ", - "Fredrik Enestad ", - "Rico Sta. Cruz ", - "Paul Miller ", - "Ben Bradley ", - "fool2fish ", - "Cory Thomas ", - "Sune Simonsen ", - "Michael Demmer ", - "Tyson Tate ", - "eiji.ienaga ", - "Valentin Agachi ", - "Sindre Sorhus ", - "Merrick Christensen ", - "Wil Moore III ", - "Nathan Bowser ", - "Jesse Dailey ", - "Benjie Gillam ", - "Vlad Magdalin ", - "David Henderson ", - "Long Ho ", - "Adam Gruber ", - "Sean Lang ", - "Shawn Krisman ", - "Simon Gaeremynck ", - "John Reeves ", - "Soel ", - "Buck Doyle ", - "Max Goodman ", - "Jonas Westerlund ", - "Michael Riley ", - "Ian Storm Taylor ", - "Timo Tijhof ", - "Ian W. Remmel ", - "Tobias Bieniek ", - "Arian Stolwijk ", - "Nathan Alderson ", - "Brian Beck ", - "Dominique Quatravaux ", - "Xavier Damman ", - "Benjamin Eidelman ", - "Outsider ", - "fcrisci ", - "FARKAS Máté ", - "Parker Moore ", - "Paul Armstrong ", - "jsdevel ", - "Justin DuJardin ", - "Juzer Ali ", - "Jacob Wejendorp ", - "monowerker ", - "Alexander Early ", - "Quang Van ", - "Quanlong He ", - "James Nylen ", - "Konstantin Käfer ", - "Jordan Sexton ", - "Josh Lory ", - "Julien Wajsberg ", - "Jussi Virtanen ", - "Jérémie Astori ", - "Katie Gengler ", - "Keith Cirkel ", - "Kent C. Dodds ", - "Kevin Burke ", - "Kevin Conway ", - "Kevin Kirsche ", - "Kirill Korolyov ", - "Koen Punt ", - "Kris Rasmussen ", - "Kyle Mitchell ", - "Laszlo Bacsi ", - "Liam Newman ", - "Linus Unnebäck ", - "Maciej Małecki ", - "Mal Graty ", - "Marc Kuo ", - "Marcello Bastea-Forte ", - "Mark Banner ", - "Martin Marko ", - "Matija Marohnić ", - "Matt Robenolt ", - "Matt Smith ", - "Matthew Shanley ", - "Mattias Tidlund ", - "Michael Jackson ", - "Michael Olson ", - "Michael Schoonmaker ", - "Michal Charemza ", - "Moshe Kolodny ", - "Nathan Black ", - "Nick Fitzgerald ", - "Nicolo Taddei ", - "Noshir Patel ", - "OlegTsyba ", - "Panu Horsmalahti ", - "Pavel Zubkou ", - "Pete Hawkins ", - "Phil Sung ", - "Prayag Verma ", - "R56 ", - "Refael Ackermann ", - "Richard Dingwall ", - "Richard Knop ", - "Rob Raux ", - "Rob Wu ", - "Robert Rossmann ", - "Romain Prieto ", - "Roman Neuhauser ", - "Roman Shtylman ", - "Russ Bradberry ", - "Russell Munson ", - "Rustem Mustafin ", - "Ryan Hubbard ", - "Ryan Shaw ", - "Salehen Shovon Rahman ", - "Sam Mussell ", - "Sasha Koss ", - "ScottFreeCode ", - "Seiya Konno ", - "Sergey Simonchik ", - "Sergio Santoro ", - "Shaine Hatch ", - "Simon Goumaz ", - "Sorin Iclanzan ", - "Standa Opichal ", - "Stephen Mathieson ", - "Steve Mason ", - "Stewart Taylor ", - "Stone ", - "Tapiwa Kelvin ", - "Teddy Zeenny ", - "Thedark1337 ", - "Tim Ehat ", - "Tingan Ho ", - "Todd Agulnick ", - "Tom Coquereau ", - "Tom Hughes ", - "Vadim Nikitin ", - "Victor Costan ", - "Will Langstroth ", - "Yanis Wang ", - "Yuest Wang ", - "Zsolt Takács ", - "abrkn ", - "airportyh ", - "amsul ", - "badunk ", - "claudyus ", - "fengmk2 ", - "gaye ", - "gigadude ", - "grasGendarme ", - "klaemo ", - "lakmeer ", - "lodr ", - "mrShturman ", - "nexdrew ", - "nishigori ", - "omardelarosa ", - "qiuzuhui ", - "ryym ", - "samuel goldszmidt ", - "sebv ", - "slyg ", - "startswithaj ", - "tgautier@yahoo.com ", - "tmont ", - "traleig1 ", - "vlad ", - "wsw ", - "yuitest ", - "Aaron Hamid ", - "zhiyelee ", - "Aaron Krause ", - "Adam Crabtree ", - "Adrian Ludwig ", - "Ajay Kodali ", - "Andreas Brekken ", - "Andrew Nesbitt ", - "Andrey Popp <8mayday@gmail.com>", - "Andrii Shumada ", - "Anis Safine ", - "Arnaud Brousseau ", - "Atsuya Takagi ", - "Austin Birch ", - "Ben Noordhuis ", - "Ben Vinegar ", - "Benoit Larroque ", - "Benoît Zugmeyer ", - "Berker Peksag ", - "Bjørge Næss ", - "Brian Lalor ", - "Brian M. Carlson ", - "Brian Moore ", - "Bryan Donovan ", - "C. Scott Ananian ", - "Casey Foster ", - "Charles Lowell ", - "Chris Buckley ", - "ChrisWren ", - "Connor Dunn ", - "Corey Butler ", - "Daniel Stockman ", - "Dave McKenna ", - "Denis Bardadym ", - "Devin Weaver ", - "Di Wu ", - "Diogo Monteiro ", - "Dmitry Shirokov ", - "Dominic Barnes ", - "Douglas Christopher Wilson ", - "Duncan Beevers ", - "Fede Ramirez ", - "Fedor Indutny ", - "Florian Margaine ", - "Frederico Silva ", - "Fredrik Lindin ", - "Gabriel Silk ", - "Gareth Murphy ", - "Gavin Mogan ", - "Giovanni Bassi ", - "Glen Huang ", - "Greg Perkins ", - "Guy Arye ", - "Gyandeep Singh ", - "Harish ", - "Harry Brundage ", - "Herman Junge ", - "Ian Young ", - "Ian Zamojc ", - "Ivan ", - "JP Bochi ", - "Jaakko Salonen ", - "Jake Craige ", - "Jake Marsh ", - "Jakub Nešetřil ", - "James Bowes ", - "James G. Kim ", - "James Lal ", - "Jan Kopriva ", - "Jason Barry ", - "Jason Lai ", - "Javier Aranda ", - "Jean Ponchon ", - "Jeff Kunkle ", - "Jeff Schilling ", - "Jeremy Martin ", - "Jimmy Cuadra ", - "Joao Moreno ", - "Joey Cozza ", - "John Doty ", - "Johnathon Sanders ", - "Jonas Dohse ", - "Jonathan Creamer ", - "Jonathan Delgado ", - "Jonathan Kim ", - "Jonathan Park " + "aaroncrows (https://github.com/aaroncrows)", + "Aaron Hamid (https://github.com/ahamid)", + "Aaron Heckmann (https://github.com/aheckmann)", + "Adam Crabtree (CrabDude's alias) (https://github.com/CrabBot)", + "Adam Gruber (https://github.com/adamgruber)", + "Adrian Ludwig (https://github.com/adrian-ludwig)", + "Ainthe Kitchen (https://github.com/ainthek)", + "ajaykodali (https://github.com/ajaykodali)", + "Alex Early (https://github.com/aearly)", + "Alex Pham (https://github.com/thedark1337)", + "amsul (https://github.com/amsul)", + "Andreas Brekken (https://github.com/abrkn)", + "Andreas Lind (https://github.com/papandreou)", + "Andrew Miller (https://github.com/vnikiti)", + "Andrew Nesbitt (https://github.com/andrew)", + "Andrey Popp <8mayday@gmail.com> (https://github.com/andreypopp)", + "Andrii Shumada (https://github.com/eagleeye)", + "Anis Safine (https://github.com/anis)", + "Arian Stolwijk (https://github.com/arian)", + "Ariel Mashraki (https://github.com/a8m)", + "Arnaud Brousseau (https://github.com/ArnaudBrousseau)", + "Atsuya Takagi (https://github.com/atsuya)", + "Attila Domokos (https://github.com/adomokos)", + "Austin Birch (https://github.com/austinbirch)", + "Avi Vahl (https://github.com/AviVahl)", + "Ben Bradley (https://github.com/ben-bradley)", + "beneidel (https://github.com/beneidel)", + "Benjie Gillam (https://github.com/benjie)", + "Ben Noordhuis (https://github.com/bnoordhuis)", + "Benoit Larroque (https://github.com/zetaben)", + "Benoît Zugmeyer (https://github.com/BenoitZugmeyer)", + "Ben Vinegar (https://github.com/benvinegar)", + "Berker Peksag (https://github.com/berkerpeksag)", + "Bjørge Næss (https://github.com/bjoerge)", + "Brendan Nee (https://github.com/brendannee)", + "Brian Beck (https://github.com/exogen)", + "Brian C (https://github.com/brianc)", + "Brian Lalor (https://github.com/blalor)", + "Brian Moore (https://github.com/bionicbrian)", + "Bryan Donovan (https://github.com/BryanDonovan)", + "Buck Doyle (https://github.com/backspace)", + "C. Scott Ananian (https://github.com/cscott)", + "Casey Foster (https://github.com/caseywebdev)", + "Charles Lowell (https://github.com/cowboyd)", + "Chris Buckley (https://github.com/cmbuckley)", + "Christopher Hiller (https://github.com/boneskull)", + "Chris Wren (https://github.com/ChrisWren)", + "Clemens Stolle (https://github.com/klaemo)", + "Connor Dunn (https://github.com/Connorhd)", + "Corey Butler (https://github.com/coreybutler)", + "Cory Thomas (https://github.com/dump247)", + "cybertk (https://github.com/cybertk)", + "Daniel Ericsson (https://github.com/monowerker)", + "Daniel St. Jules (https://github.com/danielstjules)", + "Daniel Stockman (https://github.com/evocateur)", + "Dave McKenna (https://github.com/davemckenna01)", + "David da Silva (https://github.com/dasilvacontin)", + "David Henderson (https://github.com/dhendo)", + "Denis Bardadym (https://github.com/btd)", + "Devin Weaver (https://github.com/sukima)", + "Diogo Monteiro (https://github.com/diogogmt)", + "Dmitry Shirokov (https://github.com/runk)", + "Domenic Denicola (https://github.com/domenic)", + "Dominic Barnes (https://github.com/dominicbarnes)", + "domq (https://github.com/domq)", + "Douglas Wilson (https://github.com/dougwilson)", + "Duncan Beevers (https://github.com/duncanbeevers)", + "Duncan Wong (https://github.com/badunk)", + "eiji.ienaga (https://github.com/haru01)", + "Fabio Crisci (https://github.com/piuccio)", + "Fede Ramirez (https://github.com/2fd)", + "Fedor Indutny (https://github.com/indutny)", + "fengmk2 (https://github.com/fengmk2)", + "Florian Margaine (https://github.com/ralt)", + "Forbes Lindesay (https://github.com/ForbesLindesay)", + "Frederico Silva (https://github.com/fredericosilva)", + "Fredrik Enestad (https://github.com/fredr)", + "Fredrik Lindin (https://github.com/Cowboy-coder)", + "Gabriel Silk (https://github.com/gsilk)", + "Gareth Aye (https://github.com/gaye)", + "Gavin Mogan (https://github.com/halkeye)", + "gigadude (https://github.com/gigadude)", + "Giovanni Bassi (https://github.com/giggio)", + "Glen Huang (https://github.com/curvedmark)", + "Glen Mailer (https://github.com/glenjamin)", + "Greg Perkins (https://github.com/gregrperkins)", + "Guillermo Rauch (https://github.com/rauchg)", + "Guy Arye (https://github.com/aryeguy)", + "Gyandeep Singh (https://github.com/gyandeeps)", + "Harish (https://github.com/hyeluri)", + "Harry Brundage (https://github.com/airhorns)", + "Ian Remmel (https://github.com/ianwremmel)", + "Ian Storm Taylor (https://github.com/ianstormtaylor)", + "Ian Young (https://github.com/iangreenleaf)", + "Ivan (https://github.com/ivanstoyanov)", + "Jaakko Salonen (https://github.com/jsalonen)", + "Jacob Wejendorp (https://github.com/wejendorp)", + "Jake Craige (https://github.com/jakecraige)", + "Jake Marsh (https://github.com/jakemmarsh)", + "Jake Mc (https://github.com/startswithaj)", + "Jake Verbaten (https://github.com/Raynos)", + "Jakub Nešetřil (https://github.com/zzen)", + "James Bowes (https://github.com/jbowes)", + "James Carr (https://github.com/jamescarr)", + "James G. Kim (https://github.com/jgkim)", + "James Lal (https://github.com/lightsofapollo)", + "James Nylen (https://github.com/nylen)", + "Jason (https://github.com/jlai)", + "Jason Barry (https://github.com/JCBarry)", + "Javier Aranda (https://github.com/javierav)", + "jcreamer898 (https://github.com/jcreamer898)", + "Jean Ponchon (https://github.com/nopnop)", + "Jeff Kunkle (https://github.com/kunklejr)", + "Jeff Schilling (https://github.com/jschilli)", + "JeongHoon Byun (aka Outsider) (https://github.com/outsideris)", + "Jeremy Martin (https://github.com/jmar777)", + "jimenglish81 (https://github.com/jimenglish81)", + "Jimmy Cuadra (https://github.com/jimmycuadra)", + "jldailey (https://github.com/jldailey)", + "jleyba (https://github.com/jleyba)", + "Joey Cozza (https://github.com/joeycozza)", + "Johnathon Sanders (https://github.com/outdooricon)", + "John Doty (https://github.com/jrhdoty)", + "John Firebaugh (https://github.com/jfirebaugh)", + "John Reeves (https://github.com/jonnyreeves)", + "Jo Liss (https://github.com/joliss)", + "Jonas Dohse (https://github.com/dohse)", + "Jonathan Kim (https://github.com/jkimbo)", + "Jonathan Park (https://github.com/park9140)", + "jongleberry (https://github.com/jonathanong)", + "Jordan Sexton (https://github.com/jordansexton)", + "Joseph Spencer (https://github.com/jsdevel)", + "Josh Lory (https://github.com/joshlory)", + "Joshua Appelman (https://github.com/jbnicolai)", + "Joshua Krall (https://github.com/jkrall)", + "João Moreno (https://github.com/joaomoreno)", + "João Paulo Bochi (https://github.com/jpbochi)", + "jugglinmike (https://github.com/jugglinmike)", + "Julien Wajsberg (https://github.com/julienw)", + "Jussi Virtanen (https://github.com/jvirtanen)", + "Justin DuJardin (https://github.com/justindujardin)", + "Juzer Ali (https://github.com/juzerali)", + "Jérémie Astori (https://github.com/astorije)", + "Katie Gengler (https://github.com/kategengler)", + "Kazuhito Hokamura (https://github.com/hokaccha)", + "Keith Cirkel (https://github.com/keithamus)", + "Kent C. Dodds (https://github.com/kentcdodds)", + "Kevin Burke (https://github.com/kevinburke)", + "Kevin Conway (https://github.com/kevinconway)", + "Kevin Kirsche (https://github.com/kkirsche)", + "Kirill Korolyov (https://github.com/Dremora)", + "Koen Punt (https://github.com/koenpunt)", + "Konstantin Käfer (https://github.com/kkaefer)", + "Kris Rasmussen (https://github.com/krisr)", + "Kyle Mitchell (https://github.com/kemitchell)", + "lakmeer (https://github.com/lakmeer)", + "Liam Newman (https://github.com/bitwiseman)", + "Linus Unnebäck (https://github.com/LinusU)", + "Long Ho (https://github.com/longlho)", + "László Bácsi (https://github.com/lackac)", + "Maciej Małecki (https://github.com/mmalecki)", + "Mal Graty (https://github.com/mal)", + "Marcello Bastéa-Forte (https://github.com/marcello3d)", + "Marc Kuo (https://github.com/mck-)", + "Mark Banner (https://github.com/Standard8)", + "Matija Marohnić (https://github.com/silvenon)", + "Matthew Shanley (https://github.com/arkadyan)", + "mattias-lw (https://github.com/mattias-lw)", + "Matt Robenolt (https://github.com/mattrobenolt)", + "Matt Smith (https://github.com/twobitfool)", + "Max Goodman (https://github.com/chromakode)", + "Maximilian Antoni (https://github.com/mantoni)", + "Merrick Christensen (https://github.com/iammerrick)", + "michael-adsk (https://github.com/michael-adsk)", + "Michael Demmer (https://github.com/demmer)", + "Michael Jackson (https://github.com/mjackson)", + "Michael Schoonmaker (https://github.com/Schoonology)", + "Michal Charemza (https://github.com/michalc)", + "Mike Olson (https://github.com/mwolson)", + "Mislav Marohnić (https://github.com/mislav)", + "mrShturman (https://github.com/mrShturman)", + "Nathan Alderson (https://github.com/nathanalderson)", + "Nathan Black (https://github.com/nathanboktae)", + "Nathan Bowser (https://github.com/nathanbowser)", + "Nathan Houle (https://github.com/ndhoule)", + "Nathan Rajlich (https://github.com/TooTallNate)", + "Nick Fitzgerald (https://github.com/fitzgen)", + "noirlab (https://github.com/noirlab)", + "Noshir Patel (https://github.com/noshir-patel)", + "OlegTsyba (https://github.com/OlegTsyba)", + "omar (https://github.com/omardelarosa)", + "Panu Horsmalahti (https://github.com/panuhorsmalahti)", + "Parker Moore (https://github.com/parkr)", + "Paul Armstrong (https://github.com/paularmstrong)", + "Paul Miller (https://github.com/paulmillr)", + "Pavel Zubkou (https://github.com/irnc)", + "Pete Hawkins (https://github.com/phawk)", + "Phil Sung (https://github.com/psung)", + "Prayag Verma (https://github.com/pra85)", + "qiu zuhui (https://github.com/qiuzuhui)", + "Quang Van (https://github.com/quangv)", + "Rauno (https://github.com/Rauno56)", + "Refael Ackermann (https://github.com/refack)", + "Richard Dingwall (https://github.com/rdingwall)", + "Richard Knop (https://github.com/RichardKnop)", + "Rico Sta. Cruz (https://github.com/rstacruz)", + "Robert Rossmann (https://github.com/Alaneor)", + "Rob Wu (https://github.com/Rob--W)", + "Romain (https://github.com/rprieto)", + "Roman Neuhauser (https://github.com/roman-neuhauser)", + "Roman Shtylman (https://github.com/defunctzombie)", + "Russ Bradberry (https://github.com/devdazed)", + "Russell Munson (https://github.com/rmunson)", + "Ryan (https://github.com/ryan-shaw)", + "Ryan Hubbard (https://github.com/ryedog)", + "Ryunosuke Sato (https://github.com/tricknotes)", + "ryym (https://github.com/ryym)", + "Salehen Shovon Rahman (https://github.com/shovon)", + "Salvador de la Puente González (https://github.com/delapuente)", + "Sam Mussell (https://github.com/smussell)", + "Samuel Goldszmidt (https://github.com/ouhouhsami)", + "Sasha Koss (https://github.com/kossnocorp)", + "Scott Santucci (https://github.com/ScottFreeCode)", + "Sean Lang (https://github.com/slang800)", + "seb vincent (https://github.com/sebv)", + "Seiya Konno (https://github.com/nulltask)", + "Sergey Simonchik (https://github.com/segrey)", + "Sergio Santoro (https://github.com/taueres)", + "Shahar Soel (https://github.com/bd82)", + "Shaine Hatch (https://github.com/shaine)", + "Shiwei Wang (https://github.com/wsw0108)", + "Simon Gaeremynck (https://github.com/simong)", + "Simon Goumaz (https://github.com/sgoumaz)", + "Sindre Sorhus (https://github.com/sindresorhus)", + "slientcloud (https://github.com/silentcloud)", + "Sorin Iclanzan (https://github.com/iclanzan)", + "Standa Opichal (https://github.com/opichals)", + "Stephen Mathieson (https://github.com/stephenmathieson)", + "Steve Mason (https://github.com/spmason)", + "Stewart Taylor (https://github.com/Stewart-Taylor)", + "Sune Simonsen (https://github.com/sunesimonsen)", + "Sylvain Faucherand (https://github.com/slyg)", + "Takuya Nishigori (https://github.com/nishigori)", + "Taylor Gautier (https://github.com/tsgautier)", + "Teddy Zeenny (https://github.com/teddyzeenny)", + "Thomas Grainger (https://github.com/graingert)", + "Tim Ehat (https://github.com/timehat)", + "Timothy Gu (https://github.com/TimothyGu)", + "Timo Tijhof (https://github.com/Krinkle)", + "Tingan Ho (https://github.com/tinganho)", + "TJ Holowaychuk (https://github.com/tj)", + "Tobias Bieniek (https://github.com/Turbo87)", + "Toby Ho (https://github.com/airportyh)", + "Todd Agulnick (https://github.com/tawdle)", + "Tom Hughes (https://github.com/tomhughes)", + "Tommy Montgomery (https://github.com/tmont)", + "traleig1 (https://github.com/traleig1)", + "Travis Jeffery (https://github.com/travisjeffery)", + "Tyson Tate (https://github.com/tysontate)", + "Valentin Agachi (https://github.com/avaly)", + "Victor Costan (https://github.com/pwnall)", + "Vladimir Chernis (https://github.com/vlazzle)", + "Vlad Magdalin (https://github.com/callmevlad)", + "Will Langstroth (https://github.com/wlangstroth)", + "Wil Moore III (https://github.com/wilmoore)", + "Xavier Antoviaque (https://github.com/antoviaque)", + "Xavier Damman (https://github.com/xdamman)", + "Yanis Wang (https://github.com/yaniswang)", + "yuitest (https://github.com/yuitest)", + "Zhiye Li (https://github.com/zhiyelee)", + "Zhouxuan Yang (https://github.com/fool2fish)", + "Zsolt Takács (https://github.com/oker1)" ], "license": "MIT", "repository": { "type": "git", - "url": "git://github.com/mochajs/mocha.git" + "url": "https://github.com/mochajs/mocha.git" }, "bin": { "mocha": "./bin/mocha", "_mocha": "./bin/_mocha" }, "engines": { - "node": ">= 0.8.x" + "node": ">= 0.10.x", + "npm": ">= 1.4.x" }, "scripts": { "test": "make test" }, "dependencies": { - "commander": "2.3.0", + "browser-stdout": "1.3.0", + "commander": "2.9.0", "debug": "2.2.0", "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.11", + "escape-string-regexp": "1.0.5", + "glob": "7.0.5", "growl": "1.9.2", - "jade": "0.26.3", + "json3": "3.3.2", + "lodash.create": "3.1.1", "mkdirp": "0.5.1", - "os-tmpdir": "1.0.1", - "supports-color": "1.2.0", - "to-iso-string": "0.0.2" + "supports-color": "3.1.2" }, "devDependencies": { - "browser-stdout": "^1.2.0", "browserify": "^13.0.0", - "coffee-script": "~1.8.0", - "eslint": "^1.2.1", + "coffee-script": "^1.10.0", + "eslint": "^2.13.1", "expect.js": "^0.3.1", "karma": "^1.1.0", "karma-browserify": "^5.0.5", @@ -342,8 +326,9 @@ "karma-sauce-launcher": "^1.0.0", "karma-spec-reporter": "0.0.26", "phantomjs": "1.9.8", - "should": "~8.0.0", - "through2": "~0.6.5", + "rimraf": "^2.5.2", + "should": "^9.0.2", + "through2": "^2.0.1", "watchify": "^3.7.0" }, "files": [ @@ -354,23 +339,19 @@ "mocha.css", "mocha.js", "browser-entry.js", - "LICENSE" + "LICENSE", + "bower.json" ], "browser": { "debug": "./lib/browser/debug.js", "events": "./lib/browser/events.js", "tty": "./lib/browser/tty.js", "./index.js": "./browser-entry.js", - "jade": false, "fs": false, "glob": false, "path": false, "supports-color": false }, - "licenses": [ - { - "type": "MIT", - "url": "https://raw.github.com/mochajs/mocha/master/LICENSE" - } - ] + "homepage": "https://mochajs.org", + "logo": "https://cldup.com/S9uQ-cOLYz.svg" } diff --git a/scripts/travis-after-script.sh b/scripts/travis-after-script.sh new file mode 100755 index 0000000000..e93c98f796 --- /dev/null +++ b/scripts/travis-after-script.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# syncs Karma test bundles to S3 if $S3 is set + +if [ ${S3} ] +then + mkdir -p .karma/${TRAVIS_JOB_NUMBER} + cp ./mocha.js ".karma/${TRAVIS_JOB_NUMBER}/mocha.js" + aws s3 sync ".karma/${TRAVIS_JOB_NUMBER}" "s3://mochajs/karma-bundles/${TRAVIS_JOB_NUMBER}" +fi diff --git a/scripts/travis-before-install.sh b/scripts/travis-before-install.sh new file mode 100755 index 0000000000..c725d38948 --- /dev/null +++ b/scripts/travis-before-install.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +npm install --production +# this avoids our mocha.opts (and thus devDependencies) in a roundabout way +./bin/mocha --opts /dev/null --reporter spec test/sanity/sanity.js diff --git a/scripts/travis-before-script.sh b/scripts/travis-before-script.sh new file mode 100755 index 0000000000..e5c6b25414 --- /dev/null +++ b/scripts/travis-before-script.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# installs awscli from pip if $S3 is set + +if [ ${S3} ] +then + sudo pip install awscli +fi diff --git a/scripts/upgrade-npm.js b/scripts/upgrade-npm.js deleted file mode 100644 index 2e8be81e0a..0000000000 --- a/scripts/upgrade-npm.js +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env node - -/** - * This upgrades npm on Travis when using Node.js 0.8x - */ - -if (process.env.TRAVIS_NODE_VERSION === '0.8') { - var exec = require('child_process').exec; - // ensure *dependencies* can be installed using provided npm - exec('npm install --production', function (err) { - if (err) { - throw new Error(err); - } - exec('npm install --global npm@2', function (err) { - if (err) { - throw new Error(err); - } - console.log('Upgraded to npm@2'); - }); - }); -} diff --git a/test/acceptance/fs.js b/test/acceptance/fs.js index f4c92ea727..3a70f2752c 100644 --- a/test/acceptance/fs.js +++ b/test/acceptance/fs.js @@ -1,6 +1,7 @@ var fs = require('fs'); var path = require('path'); -var tmpFile = path.join.bind(path, require('os-tmpdir')()); +var os = require('os'); +var tmpFile = path.join.bind(path, os.tmpdir()); describe('fs.readFile()', function(){ describe('when the file exists', function(){ diff --git a/test/acceptance/lookup-files.js b/test/acceptance/lookup-files.js index 7b84d93171..5d4a48d8af 100644 --- a/test/acceptance/lookup-files.js +++ b/test/acceptance/lookup-files.js @@ -1,23 +1,35 @@ +'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 fs = require('fs'), - path = require('path'), - existsSync = fs.existsSync || path.existsSync, - tmpDir = require('os-tmpdir')(), - tmpFile = path.join.bind(path, tmpDir), - symlinkSupported = false; + var tmpDir = path.join(os.tmpDir(), 'mocha-lookup-files'); + var existsSync = fs.existsSync; + var tmpFile = path.join.bind(path, tmpDir); + var symlinkSupported = false; - 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) { - } + (function testSymlinkSupport() { + makeTempDir(); - cleanup(); + 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')); @@ -66,18 +78,13 @@ describe('lookupFiles', function() { .length(expectedLength); }); - afterEach(cleanup); + afterEach(removeTempDir); + + function makeTempDir() { + mkdirp.sync(tmpDir); + } - function cleanup() { - [ - 'mocha-utils.js', - 'mocha-utils-link.js', - 'bob' - ].forEach(function(path) { - try { - fs.unlinkSync(tmpFile(path)); - } catch (ignored) { - } - }); + function removeTempDir() { + rimraf.sync(tmpDir); } }); diff --git a/test/acceptance/misc/only/bdd.js b/test/acceptance/misc/only/bdd.js index bb05ad9792..7a33a74eac 100644 --- a/test/acceptance/misc/only/bdd.js +++ b/test/acceptance/misc/only/bdd.js @@ -1,14 +1,125 @@ describe('should only run .only test in this bdd suite', function() { it('should not run this test', function() { - var zero = 0; - expect(zero).to.equal(1, 'this test should have been skipped'); + (0).should.equal(1, 'this test should have been skipped'); }); - it.only('should run this test', function() { - var zero = 0; - expect(zero).to.equal(0, 'this .only test should run'); + 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() { - var zero = 0; - expect(zero).to.equal(1, 'this test should have been skipped'); + (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/test/acceptance/misc/only/global/bdd.js b/test/acceptance/misc/only/global/bdd.js new file mode 100644 index 0000000000..e923876f84 --- /dev/null +++ b/test/acceptance/misc/only/global/bdd.js @@ -0,0 +1,12 @@ +// 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); +}); \ No newline at end of file diff --git a/test/acceptance/misc/only/global/qunit.js b/test/acceptance/misc/only/global/qunit.js new file mode 100644 index 0000000000..59ad72c3bf --- /dev/null +++ b/test/acceptance/misc/only/global/qunit.js @@ -0,0 +1,12 @@ +// 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); +}); \ No newline at end of file diff --git a/test/acceptance/misc/only/global/tdd.js b/test/acceptance/misc/only/global/tdd.js new file mode 100644 index 0000000000..08d456848b --- /dev/null +++ b/test/acceptance/misc/only/global/tdd.js @@ -0,0 +1,12 @@ +// 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); +}); \ No newline at end of file diff --git a/test/acceptance/misc/only/qunit.js b/test/acceptance/misc/only/qunit.js index 07c240f617..1248adeba7 100644 --- a/test/acceptance/misc/only/qunit.js +++ b/test/acceptance/misc/only/qunit.js @@ -1,15 +1,73 @@ -function ok(expr, msg) { - if (!expr) throw new Error(msg); -} +// 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() { - ok(0 === 1, 'this test should have been skipped'); + (0).should.equal(1, 'this test should have been skipped'); }); -test.only('should run this test', function() { - ok(0 === 0, 'this .only test should run'); +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() { - ok(0 === 1, 'this test should have been skipped'); + (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); +}); \ No newline at end of file diff --git a/test/acceptance/misc/only/tdd.js b/test/acceptance/misc/only/tdd.js index 306d06a9f9..7e37e7a3b3 100644 --- a/test/acceptance/misc/only/tdd.js +++ b/test/acceptance/misc/only/tdd.js @@ -1,14 +1,125 @@ suite('should only run .only test in this tdd suite', function() { test('should not run this test', function() { - var zero = 0; - expect(zero).to.equal(1, 'this test should have been skipped'); + (0).should.equal(1, 'this test should have been skipped'); }); - test.only('should run this test', function() { - var zero = 0; - expect(zero).to.equal(0, 'this .only test should run'); + 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() { - var zero = 0; - expect(zero).to.equal(1, 'this test should have been skipped'); + (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/test/acceptance/overspecified-async.js b/test/acceptance/overspecified-async.js new file mode 100644 index 0000000000..2844920379 --- /dev/null +++ b/test/acceptance/overspecified-async.js @@ -0,0 +1,8 @@ +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/test/acceptance/throw.js b/test/acceptance/throw.js index 1016a19efe..46cfbad6ad 100644 --- a/test/acceptance/throw.js +++ b/test/acceptance/throw.js @@ -6,7 +6,7 @@ describe('a test that throws', function () { var suite, runner; beforeEach(function(){ - suite = new Suite(null, 'root'); + suite = new Suite('Suite', 'root'); runner = new Runner(suite); }) diff --git a/test/acceptance/utils.js b/test/acceptance/utils.js index 366d2d8579..a2383a739f 100644 --- a/test/acceptance/utils.js +++ b/test/acceptance/utils.js @@ -1,5 +1,6 @@ var utils = require('../../lib/utils'); -var toISOString = require('to-iso-string'); +var toISOString = require('../../lib/to-iso-string'); +var JSON = require('json3'); describe('lib/utils', function () { describe('clean', function () { diff --git a/test/color.js b/test/color.js index 3913c0099c..5ee46e71c4 100644 --- a/test/color.js +++ b/test/color.js @@ -3,7 +3,7 @@ var child_process = require('child_process'); var path = require('path'); describe('Mocha', function() { - this.timeout(1000); + this.timeout(2000); it('should not output colors to pipe', function(cb) { var command = [path.join('bin', 'mocha'), '--grep', 'missing-test']; diff --git a/test/grep.js b/test/grep.js index ff9d25a171..bbc5c55eba 100644 --- a/test/grep.js +++ b/test/grep.js @@ -5,44 +5,61 @@ describe('Mocha', 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(){ - it('should add a RegExp to the mocha.options object', function(){ - var mocha = new Mocha; - mocha.grep(/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 convert grep string to a RegExp', function(){ - var mocha = new Mocha; - mocha.grep('foo'); - mocha.options.grep.toString().should.equal('/foo/'); - }) + 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(); - }) - }) -}) + mocha.options.invert.should.be.ok; + }); + }); +}); diff --git a/test/integration/diffs.js b/test/integration/diffs.js index 25d9ae6d7f..111b6f2042 100644 --- a/test/integration/diffs.js +++ b/test/integration/diffs.js @@ -15,7 +15,6 @@ function getExpectedOutput() { describe('diffs', function() { var diffs, expected; - this.timeout(2000); before(function(done) { run('diffs/diffs.js', ['-C'], function(err, res) { diff --git a/test/integration/fixtures/options/grep.js b/test/integration/fixtures/options/grep.js index 5e163f5ee7..94785dc7db 100644 --- a/test/integration/fixtures/options/grep.js +++ b/test/integration/fixtures/options/grep.js @@ -1,10 +1,15 @@ 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(){ + describe('fail', function() { it('should not be ran', function() { throw new Error('Spec should not run'); }); diff --git a/test/integration/fixtures/options/only/bdd.js b/test/integration/fixtures/options/only/bdd.js new file mode 100644 index 0000000000..783ce19b0b --- /dev/null +++ b/test/integration/fixtures/options/only/bdd.js @@ -0,0 +1,71 @@ +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/test/integration/fixtures/options/only/qunit.js b/test/integration/fixtures/options/only/qunit.js new file mode 100644 index 0000000000..9fa95f440b --- /dev/null +++ b/test/integration/fixtures/options/only/qunit.js @@ -0,0 +1,26 @@ +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); +}); \ No newline at end of file diff --git a/test/integration/fixtures/options/only/tdd.js b/test/integration/fixtures/options/only/tdd.js new file mode 100644 index 0000000000..129a9e5d74 --- /dev/null +++ b/test/integration/fixtures/options/only/tdd.js @@ -0,0 +1,35 @@ +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/test/integration/fixtures/regression/issue-1991.js b/test/integration/fixtures/regression/issue-1991.js index ee08a1d043..96860332a2 100644 --- a/test/integration/fixtures/regression/issue-1991.js +++ b/test/integration/fixtures/regression/issue-1991.js @@ -39,7 +39,7 @@ for (var i = 0; i < numOfTests; i += 1) { it('access a variable via a closure', function () { // slow performance on older node.js versions - this.timeout(2000); + this.timeout(1000); closureVar = new MemoryLeak(); }); diff --git a/test/integration/fixtures/regression/issue-2406.js b/test/integration/fixtures/regression/issue-2406.js new file mode 100644 index 0000000000..c800228f1e --- /dev/null +++ b/test/integration/fixtures/regression/issue-2406.js @@ -0,0 +1,15 @@ +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/test/integration/hook.err.js b/test/integration/hook.err.js index f874b8f3b6..f3a16c15d1 100644 --- a/test/integration/hook.err.js +++ b/test/integration/hook.err.js @@ -1,10 +1,9 @@ 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() { - this.timeout(2000); - var lines; describe('before hook error', function() { @@ -12,7 +11,7 @@ describe('hook error handling', function() { it('should verify results', function() { assert.deepEqual( lines, - ['before', 'test 3'] + ['before', bang + 'test 3'] ); }); }); @@ -32,7 +31,7 @@ describe('hook error handling', function() { it('should verify results', function() { assert.deepEqual( lines, - ['before', 'test 3'] + ['before', bang + 'test 3'] ); }); }); @@ -42,7 +41,7 @@ describe('hook error handling', function() { it('should verify results', function() { assert.deepEqual( lines, - ['test 1', 'test 2', 'after', 'test 3'] + ['test 1', 'test 2', 'after', bang + 'test 3'] ); }); }); @@ -52,7 +51,7 @@ describe('hook error handling', function() { it('should verify results', function() { assert.deepEqual( lines, - ['test 1', 'after', 'test 3'] + ['test 1', 'after', bang + 'test 3'] ); }); }); @@ -68,25 +67,25 @@ describe('hook error handling', function() { 'root before each', '1 before each', '1-1 before each', - '1-1 after each', + bang + '1-1 after each', '1 after each', 'root after each', '1-1 after', - '1-2 before', + bang + '1-2 before', 'root before each', '1 before each', '1-2 before each', '1-2 test 1', '1-2 after each', - '1 after each', + bang + '1 after each', 'root after each', '1-2 after', '1 after', '2-1 before', 'root before each', '2 before each', - '2 after each', - 'root after each', + bang + '2 after each', + bang + 'root after each', '2-1 after', '2 after', 'root after' @@ -100,7 +99,7 @@ describe('hook error handling', function() { it('should verify results', function() { assert.deepEqual( lines, - ['before', 'test 3'] + ['before', bang + 'test 3'] ); }); }); @@ -120,7 +119,7 @@ describe('hook error handling', function() { it('should verify results', function() { assert.deepEqual( lines, - ['before', 'test 3'] + ['before', bang + 'test 3'] ); }); }); @@ -130,7 +129,7 @@ describe('hook error handling', function() { it('should verify results', function() { assert.deepEqual( lines, - ['test 1', 'test 2', 'after', 'test 3'] + ['test 1', 'test 2', 'after', bang + 'test 3'] ); }); }); @@ -140,7 +139,7 @@ describe('hook error handling', function() { it('should verify results', function() { assert.deepEqual( lines, - ['test 1', 'after', 'test 3'] + ['test 1', 'after', bang + 'test 3'] ); }); }); @@ -156,25 +155,25 @@ describe('hook error handling', function() { 'root before each', '1 before each', '1-1 before each', - '1-1 after each', + bang + '1-1 after each', '1 after each', 'root after each', '1-1 after', - '1-2 before', + bang + '1-2 before', 'root before each', '1 before each', '1-2 before each', '1-2 test 1', '1-2 after each', - '1 after each', + bang + '1 after each', 'root after each', '1-2 after', '1 after', '2-1 before', 'root before each', '2 before each', - '2 after each', - 'root after each', + bang + '2 after each', + bang + 'root after each', '2-1 after', '2 after', 'root after' diff --git a/test/integration/hooks.js b/test/integration/hooks.js index 1795856072..acd829f7c9 100644 --- a/test/integration/hooks.js +++ b/test/integration/hooks.js @@ -4,8 +4,6 @@ var splitRegExp = require('./helpers').splitRegExp; var args = []; describe('hooks', function() { - this.timeout(2000); - it('are ran in correct order', function(done) { run('cascade.js', args, function(err, res) { var lines, expected; diff --git a/test/integration/multiple.done.js b/test/integration/multiple.done.js index d9d9645f32..0159e90e43 100644 --- a/test/integration/multiple.done.js +++ b/test/integration/multiple.done.js @@ -4,8 +4,6 @@ var args = []; describe('multiple calls to done()', function() { var res; - this.timeout(2000); - describe('from a spec', function() { before(function(done) { run('multiple.done.js', args, function(err, result) { diff --git a/test/integration/only.js b/test/integration/only.js new file mode 100644 index 0000000000..dc7644e5a4 --- /dev/null +++ b/test/integration/only.js @@ -0,0 +1,37 @@ +var run = require('./helpers').runMochaJSON; +var assert = require('assert'); + +describe('.only()', function() { + it('should run only tests that marked as `only`', function(done) { + run('options/only/bdd.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(); + }); + }); + + it('should run only tests that marked as `only`', function(done) { + run('options/only/tdd.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(); + }); + }); + + it('should run only tests that marked as `only`', function(done) { + run('options/only/qunit.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/test/integration/options.js b/test/integration/options.js index 1e25b6ef3d..5e18ac5e71 100644 --- a/test/integration/options.js +++ b/test/integration/options.js @@ -3,8 +3,6 @@ var run = require('./helpers').runMochaJSON; var args = []; describe('options', function() { - this.timeout(2000); - describe('--async-only', function() { before(function() { @@ -125,15 +123,29 @@ describe('options', function() { }); }); - it('runs specs matching a RegExp', function(done) { - args = ['--grep', '.*']; - run('options/grep.js', args, function(err, res) { - assert(!err); - assert.equal(res.stats.pending, 0); - assert.equal(res.stats.passes, 2); - assert.equal(res.stats.failures, 1); - assert.equal(res.code, 1); - 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.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.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(); + }); }); }); @@ -143,7 +155,7 @@ describe('options', function() { run('options/grep.js', args, function(err, res) { assert(!err); assert.equal(res.stats.pending, 0); - assert.equal(res.stats.passes, 2); + assert.equal(res.stats.passes, 4); assert.equal(res.stats.failures, 0); assert.equal(res.code, 0); done(); diff --git a/test/integration/pending.js b/test/integration/pending.js index 6d63b1fae1..0c18ab4bc7 100644 --- a/test/integration/pending.js +++ b/test/integration/pending.js @@ -4,8 +4,6 @@ var args = []; describe('pending', function() { describe('pending specs', function() { - this.timeout(2000); - it('should be created by omitting a function', function(done) { run('pending/spec.js', args, function(err, res) { assert(!err); @@ -19,8 +17,6 @@ describe('pending', function() { }); describe('synchronous skip()', function() { - this.timeout(2000); - describe('in spec', function() { it('should immediately skip the spec and run all others', function(done) { run('pending/skip.sync.spec.js', args, function(err, res) { @@ -62,8 +58,6 @@ describe('pending', function() { }); describe('asynchronous skip()', function() { - this.timeout(2000); - describe('in spec', function() { it('should immediately skip the spec and run all others', function(done) { run('pending/skip.async.spec.js', args, function(err, res) { diff --git a/test/integration/regression.js b/test/integration/regression.js index 6e6606a5ff..69925be20d 100644 --- a/test/integration/regression.js +++ b/test/integration/regression.js @@ -1,11 +1,10 @@ -var assert = require('assert'); -var fs = require('fs'); -var path = require('path'); -var run = require('./helpers').runMocha; +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() { - this.timeout(2000); - it('issue-1327: should run all 3 specs exactly once', function(done) { var args = []; run('regression/issue-1327.js', args, function(err, res) { @@ -62,4 +61,16 @@ describe('regressions', function() { afterWasRun.should.be.ok(); }); }); + + it('issue-2406: should run nested describe.only suites', function(done) { + this.timeout(2000); + runJSON('regression/issue-2406.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(); + }); + }); }); diff --git a/test/integration/reporters.js b/test/integration/reporters.js index 19cf0bdd1e..c2f022fe29 100644 --- a/test/integration/reporters.js +++ b/test/integration/reporters.js @@ -6,8 +6,6 @@ var path = require('path'); var run = require('./helpers').runMocha; describe('reporters', function() { - this.timeout(3000); - describe('markdown', function() { var res; diff --git a/test/integration/retries.js b/test/integration/retries.js index 756cc9dd9b..56516b3a92 100644 --- a/test/integration/retries.js +++ b/test/integration/retries.js @@ -1,10 +1,9 @@ var assert = require('assert'); var helpers = require('./helpers'); var args = []; +var bang = require('../../lib/reporters/base').symbols.bang; describe('retries', function() { - this.timeout(2000); - it('are ran in correct order', function(done) { helpers.runMocha('retries/hooks.js', args, function(err, res) { var lines, expected; @@ -33,7 +32,7 @@ describe('retries', function() { 'after each 4', 'before each 4', 'TEST 4', - 'after each 5', + bang + 'after each 5', 'after' ]; diff --git a/test/integration/timeout.js b/test/integration/timeout.js index c8321c0b66..b2dfb201f3 100644 --- a/test/integration/timeout.js +++ b/test/integration/timeout.js @@ -3,8 +3,6 @@ var run = require('./helpers').runMochaJSON; var args = []; describe('this.timeout()', function() { - this.timeout(2000); - it('is respected by sync and async suites', function(done) { run('timeout.js', args, function(err, res) { assert(!err); diff --git a/test/integration/uncaught.js b/test/integration/uncaught.js index 2ca186e471..92a0ce5d35 100644 --- a/test/integration/uncaught.js +++ b/test/integration/uncaught.js @@ -3,8 +3,6 @@ var run = require('./helpers').runMochaJSON; var args = []; describe('uncaught exceptions', function() { - this.timeout(2000); - it('handles uncaught exceptions from hooks', function(done) { run('uncaught.hook.js', args, function(err, res) { assert(!err); diff --git a/test/runnable.js b/test/runnable.js index a3d88adda2..d6b020a6a1 100644 --- a/test/runnable.js +++ b/test/runnable.js @@ -41,6 +41,14 @@ describe('Runnable(title, fn)', function(){ }) }) + 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; diff --git a/test/runner.js b/test/runner.js index 7673a8384e..37aeb22d6f 100644 --- a/test/runner.js +++ b/test/runner.js @@ -7,7 +7,7 @@ describe('Runner', function(){ var suite, runner; beforeEach(function(){ - suite = new Suite(null, 'root'); + suite = new Suite('Suite', 'root'); runner = new Runner(suite); }) diff --git a/test/sanity/sanity.js b/test/sanity/sanity.js new file mode 100644 index 0000000000..59d5896515 --- /dev/null +++ b/test/sanity/sanity.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/test/suite.js b/test/suite.js index 6588e24817..7fead0745a 100644 --- a/test/suite.js +++ b/test/suite.js @@ -398,4 +398,42 @@ describe('Suite', function(){ }); }); + + describe('initialization', function() { + 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(); + }); + }); +}); \ No newline at end of file diff --git a/test/utils.js b/test/utils.js index 881e5342a9..501ea7abe8 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,5 +1,6 @@ var mocha = require('..'); var utils = mocha.utils; +var JSON = require('json3'); describe('utils', function() { describe('.clean()', function() { @@ -182,4 +183,18 @@ describe('utils', function() { }); }); }); + + 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; + }); + }); });