From 038c63636f435c599f1b20d9f515c2dfbdc501e8 Mon Sep 17 00:00:00 2001 From: Igwe Kalu Date: Sun, 16 Apr 2017 18:43:31 +0200 Subject: [PATCH 01/42] Support `--inspect-brk` on command-line --- bin/_mocha | 1 + bin/mocha | 1 + 2 files changed, 2 insertions(+) diff --git a/bin/_mocha b/bin/_mocha index 61aac40d3a..3539063aeb 100755 --- a/bin/_mocha +++ b/bin/_mocha @@ -91,6 +91,7 @@ program .option('--icu-data-dir', 'include ICU data') .option('--inline-diffs', 'display actual/expected differences inline within each string') .option('--inspect', 'activate devtools in chrome') + .option('--inspect-brk', 'activate devtools in chrome and break on the first line') .option('--interfaces', 'display available interfaces') .option('--no-deprecation', 'silence deprecation warnings') .option('--no-exit', 'require a clean shutdown of the event loop: mocha will not call process.exit') diff --git a/bin/mocha b/bin/mocha index c6aaa97b00..0097153d15 100755 --- a/bin/mocha +++ b/bin/mocha @@ -28,6 +28,7 @@ process.argv.slice(2).forEach(function (arg) { case '--debug': case '--debug-brk': case '--inspect': + case '--inspect-brk': args.unshift(arg); args.push('--no-timeouts'); break; From 73929ad851434a7253252ad054d37c40f9c692b9 Mon Sep 17 00:00:00 2001 From: David da Silva Date: Thu, 20 Apr 2017 17:39:11 +0200 Subject: [PATCH 02/42] Comment special treatment of '+' in URL query parsing --- lib/utils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/utils.js b/lib/utils.js index 7395750dcc..d66eba3bc3 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -322,7 +322,9 @@ exports.parseQuery = function (qs) { var key = pair.slice(0, i); var val = pair.slice(++i); + // Due to how the URLSearchParams API treats spaces obj[key] = decodeURIComponent(val.replace(/\+/g, '%20')); + return obj; }, {}); }; From 0a93024b475e58e75c5def6b2f5228bd363874de Mon Sep 17 00:00:00 2001 From: Sulabh Bista Date: Mon, 24 Apr 2017 01:45:04 -0700 Subject: [PATCH 03/42] Adds tests for loading reporters w/ relative/absolute paths (#2773) * Adds tests for loading reporters w/ relative/absolute paths * Fixes the test based on CR * Replaces '+' with path.join() --- test/integration/fixtures/simple-reporter.js | 26 +++++++++++++++++++ test/integration/reporters.spec.js | 27 ++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 test/integration/fixtures/simple-reporter.js diff --git a/test/integration/fixtures/simple-reporter.js b/test/integration/fixtures/simple-reporter.js new file mode 100644 index 0000000000..c2b4e53cd7 --- /dev/null +++ b/test/integration/fixtures/simple-reporter.js @@ -0,0 +1,26 @@ +var baseReporter = require('../../../lib/reporters/base'); +module.exports = simplereporter; + +function simplereporter (runner) { + baseReporter.call(this, runner); + + runner.on('suite', function (suite) { + console.log('on(\'suite\') called'); + }); + + runner.on('fail', function (test, err) { + console.log('on(\'fail\') called'); + }); + + runner.on('pass', function (test) { + console.log('on(\'pass\') called'); + }); + + runner.on('test end', function (test, err) { + console.log('on(\'test end\') called'); + }); + + runner.on('end', function () { + console.log('on(\'end\') called'); + }); +} diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index 5cfee57037..15b7e6533b 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -60,4 +60,31 @@ describe('reporters', function () { }); }); }); + + describe('loader', function () { + it('loads a reporter from a path relative to the current working directory', function (done) { + var reporterAtARelativePath = 'test/integration/fixtures/simple-reporter.js'; + + var args = ['--reporter=' + reporterAtARelativePath]; + + run('passing.fixture.js', args, function (err, result) { + assert(!err); + assert.equal(result.code, 0); + done(); + }); + }); + + it('loads a reporter from an absolute path', function (done) { + // Generates an absolute path string + var reporterAtAnAbsolutePath = path.join(process.cwd(), 'test/integration/fixtures/simple-reporter.js'); + + var args = ['--reporter=' + reporterAtAnAbsolutePath]; + + run('passing.fixture.js', args, function (err, result) { + assert(!err); + assert.equal(result.code, 0); + done(); + }); + }); + }); }); From 9bd9389c58e81b10bef9f4b2e5a54b77a026d2d0 Mon Sep 17 00:00:00 2001 From: David da Silva Date: Thu, 20 Apr 2017 18:19:57 +0200 Subject: [PATCH 04/42] Fix spec paths in test HTML files --- test/browser/grep.html | 2 +- test/browser/index.html | 6 +++--- test/browser/opts.html | 4 ++-- test/browser/stack-trace.html | 2 +- test/browser/ui.html | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/browser/grep.html b/test/browser/grep.html index 0ba47c8533..44bff517df 100644 --- a/test/browser/grep.html +++ b/test/browser/grep.html @@ -11,7 +11,7 @@ if (!expr) throw new Error(msg || 'failed'); } - +
diff --git a/test/browser/index.html b/test/browser/index.html index 9200b977e5..2331834ecf 100644 --- a/test/browser/index.html +++ b/test/browser/index.html @@ -12,9 +12,9 @@ } - - - + + + - - + + - + - +
From 1d3c5bcc945a2cf8ff3c640f7d3358b1a639bb4e Mon Sep 17 00:00:00 2001 From: David da Silva Date: Thu, 20 Apr 2017 18:20:55 +0200 Subject: [PATCH 05/42] Fix typo in karma.conf.js --- karma.conf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/karma.conf.js b/karma.conf.js index fa4996317a..efec486139 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -117,7 +117,7 @@ module.exports = function (config) { } // 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. + // tests. 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 = env.MOCHA_UI; From 861e968b516613a9f1d964668660450b446750dc Mon Sep 17 00:00:00 2001 From: David da Silva Date: Thu, 20 Apr 2017 18:21:26 +0200 Subject: [PATCH 06/42] Refactor literal play-icon hex code to a var --- lib/reporters/html.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/reporters/html.js b/lib/reporters/html.js index 3e755d2d63..e29aa36a5a 100644 --- a/lib/reporters/html.js +++ b/lib/reporters/html.js @@ -41,6 +41,8 @@ var statsTemplate = '
    ' + '
  • duration: 0s
  • ' + '
'; +var playIcon = '‣'; + /** * Initialize a new `HTML` reporter. * @@ -136,7 +138,7 @@ function HTML (runner) { runner.on('pass', function (test) { var url = self.testURL(test); var markup = '
  • %e%ems ' + - '

  • '; + '' + playIcon + ''; var el = fragment(markup, test.speed, test.title, test.duration, url); self.addCodeToggle(el, test.body); appendToStack(el); @@ -144,7 +146,7 @@ function HTML (runner) { }); runner.on('fail', function (test) { - var el = fragment('
  • %e

  • ', + var el = fragment('
  • %e ' + playIcon + '

  • ', test.title, self.testURL(test)); var stackString; // Note: Includes leading newline var message = test.err.toString(); From 1943e029da1d420e027ad8b5875c0e03e43b86c4 Mon Sep 17 00:00:00 2001 From: David da Silva Date: Thu, 20 Apr 2017 21:17:40 +0200 Subject: [PATCH 07/42] Add Changelog for v3.3.0 --- CHANGELOG.md | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b659a4efa8..de3574a6e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,91 @@ +# 3.3.0 / 2017-04-24 + +Thanks to all our contributors, maintainers, sponsors, and users! ❤️ + +As highlights: + +- We've got coverage now! +- Testing is looking less flaky \o/. +- No more nitpicking about "mocha.js" build on PRs. + +## :tada: Enhancements + +- [#2659]: Adds support for loading reporter from an absolute or relative path ([@sul4bh]) +- [#2769]: Support `--inspect-brk` on command-line ([@igwejk]) + +## :bug: Fixes + +- [#2662]: Replace unicode chars w/ hex codes in HTML reporter ([@rotemdan]) + +## :mag: Coverage + +- [#2672]: Add coverage for node tests ([@c089], [@Munter]) +- [#2680]: Increase tests coverage for base reporter ([@epallerols]) +- [#2690]: Increase tests coverage for doc reporter ([@craigtaub]) +- [#2701]: Increase tests coverage for landing, min, tap and list reporters ([@craigtaub]) +- [#2691]: Increase tests coverage for spec + dot reporters ([@craigtaub]) +- [#2698]: Increase tests coverage for xunit reporter ([@craigtaub]) +- [#2699]: Increase tests coverage for json-stream, markdown and progress reporters ([@craigtaub]) +- [#2703]: Cover .some() function in utils.js with tests ([@seppevs]) +- [#2773]: Add tests for loading reporters w/ relative/absolute paths ([@sul4bh]) + +## :nut_and_bolt: Other + +- Remove bin/.eslintrc; ensure execs are linted ([@boneskull]) +- [#2542]: Expand CONTRIBUTING.md ([@boneskull]) +- [#2660]: Double timeouts on integration tests ([@Munter]) +- [#2653]: Update copyright year ([@Scottkao85], [@Munter]) +- [#2621]: Update dependencies to enable Greenkeeper ([@boneskull], [@greenkeeper]) +- [#2625]: Use trusty container in travis-ci; use "artifacts" addon ([@boneskull]) +- [#2670]: doc(CONTRIBUTING): fix link to org members ([@coderbyheart]) +- Add Mocha propaganda to README.md ([@boneskull]) +- [#2470]: Avoid test flake in "delay" test ([@boneskull]) +- [#2675]: Limit browser concurrency on sauce ([@boneskull]) +- [#2669]: Use temporary test-only build of mocha.js for browsers tests ([@Munter]) +- Fix "projects" link in README.md ([@boneskull]) +- [#2678]: Chore(Saucelabs): test on IE9, IE10 and IE11 ([@coderbyheart]) +- [#2648]: Use `semistandard` directly ([@kt3k]) +- [#2727]: Make the build reproducible ([@lamby]) + +[@boneskull]: https://github.com/boneskull +[@c089]: https://github.com/c089 +[@coderbyheart]: https://github.com/coderbyheart +[@craigtaub]: https://github.com/craigtaub +[@epallerols]: https://github.com/epallerols +[@greenkeeper]: https://github.com/greenkeeper +[@igwejk]: https://github.com/igwejk +[@kt3k]: https://github.com/kt3k +[@lamby]: https://github.com/lamby +[@Munter]: https://github.com/Munter +[@rotemdan]: https://github.com/rotemdan +[@seppevs]: https://github.com/seppevs +[@sul4bh]: https://github.com/sul4bh + +[#2470]: https://github.com/mochajs/mocha/pull/2470 +[#2542]: https://github.com/mochajs/mocha/issues/2542 +[#2621]: https://github.com/mochajs/mocha/pull/2621 +[#2625]: https://github.com/mochajs/mocha/pull/2625 +[#2648]: https://github.com/mochajs/mocha/pull/2648 +[#2653]: https://github.com/mochajs/mocha/pull/2653 +[#2659]: https://github.com/mochajs/mocha/pull/2659 +[#2660]: https://github.com/mochajs/mocha/pull/2660 +[#2662]: https://github.com/mochajs/mocha/pull/2662 +[#2669]: https://github.com/mochajs/mocha/pull/2669 +[#2670]: https://github.com/mochajs/mocha/pull/2670 +[#2672]: https://github.com/mochajs/mocha/pull/2672 +[#2675]: https://github.com/mochajs/mocha/pull/2675 +[#2678]: https://github.com/mochajs/mocha/pull/2678 +[#2680]: https://github.com/mochajs/mocha/pull/2680 +[#2690]: https://github.com/mochajs/mocha/pull/2690 +[#2691]: https://github.com/mochajs/mocha/pull/2691 +[#2698]: https://github.com/mochajs/mocha/pull/2698 +[#2699]: https://github.com/mochajs/mocha/pull/2699 +[#2701]: https://github.com/mochajs/mocha/pull/2701 +[#2703]: https://github.com/mochajs/mocha/pull/2703 +[#2727]: https://github.com/mochajs/mocha/pull/2727 +[#2769]: https://github.com/mochajs/mocha/pull/2769 +[#2773]: https://github.com/mochajs/mocha/pull/2773 + # 3.2.0 / 2016-11-24 ## :newspaper: News From fb1687ec16e8ae347ca4498560f984e575224d59 Mon Sep 17 00:00:00 2001 From: David da Silva Date: Mon, 24 Apr 2017 11:08:00 +0200 Subject: [PATCH 08/42] :ship: Release v3.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e1353c727..6c42870d5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mocha", - "version": "3.2.0", + "version": "3.3.0", "description": "simple, flexible, fun test framework", "keywords": [ "mocha", From 4ed3fc58a3ba95a6420086d7af0d0a032308e36a Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 25 Apr 2017 06:14:38 +0300 Subject: [PATCH 09/42] Add license report and scan status Followup to @kborchers's email on JSF adopting FOSSA for license scanning. We're currently merging in PRs for scan status into repo READMEs (i.e. webpack/webpack#4768) Congrats on the passing license scan! In the PR is a green badge and report. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index d3a57cffe9..baaeb5bf9e 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ Once we gain ground on the above items, we can work together formalize our contr [![Build Status](https://api.travis-ci.org/mochajs/mocha.svg?branch=master)](http://travis-ci.org/mochajs/mocha) [![Coverage Status](https://coveralls.io/repos/github/mochajs/mocha/badge.svg)](https://coveralls.io/github/mochajs/mocha) +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha?ref=badge_shield) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mochajs/mocha?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![OpenCollective](https://opencollective.com/mochajs/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/mochajs/sponsors/badge.svg)](#sponsors) @@ -118,3 +119,5 @@ Does your company use Mocha? Ask your manager or marketing team if your company ## License [MIT](LICENSE) + +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha?ref=badge_large) From fb1e0830b5e235326b58b25da9f07c42da363404 Mon Sep 17 00:00:00 2001 From: Laurence Rowe Date: Tue, 31 Jan 2017 19:26:05 -0800 Subject: [PATCH 10/42] fix allowUncaught in browser squashed: - Setup error handler when allowUncaught. (f76afbc) - Avoid calling done() twice. (dae3428) --- lib/runnable.js | 7 +++++-- lib/runner.js | 7 +++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/runnable.js b/lib/runnable.js index e7b6aa12f0..ee8c4a3467 100644 --- a/lib/runnable.js +++ b/lib/runnable.js @@ -324,8 +324,11 @@ Runnable.prototype.run = function (fn) { } if (this.allowUncaught) { - callFn(this.fn); - done(); + if (this.isPending()) { + done(); + } else { + callFn(this.fn); + } return; } diff --git a/lib/runner.js b/lib/runner.js index 1d3dd959da..b024e0dcb5 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -432,15 +432,14 @@ Runner.prototype.runTest = function (fn) { if (this.asyncOnly) { test.asyncOnly = true; } - + test.on('error', function (err) { + self.fail(test, err); + }); if (this.allowUncaught) { test.allowUncaught = true; return test.run(fn); } try { - test.on('error', function (err) { - self.fail(test, err); - }); test.run(fn); } catch (err) { fn(err); From 4d1d91d68d88a394429cd70a9b15f4fb60fe5e6b Mon Sep 17 00:00:00 2001 From: Laurence Rowe Date: Tue, 31 Jan 2017 19:40:46 -0800 Subject: [PATCH 11/42] --allow-uncaught cli option --- bin/_mocha | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bin/_mocha b/bin/_mocha index 3539063aeb..7ba433ef05 100755 --- a/bin/_mocha +++ b/bin/_mocha @@ -108,7 +108,8 @@ program .option('--trace-deprecation', 'show stack traces on deprecations') .option('--use_strict', 'enforce strict mode') .option('--watch-extensions ,...', 'additional extensions to monitor with --watch', list, []) - .option('--delay', 'wait for async suite definition'); + .option('--delay', 'wait for async suite definition') + .option('--allow-uncaught', 'enable uncaught errors to propagate'); program._name = 'mocha'; @@ -314,6 +315,12 @@ if (program.delay) { mocha.delay(); } +// --allow-uncaught + +if (program.allowUncaught) { + mocha.allowUncaught(); +} + // --globals mocha.globals(globals); From 93392ddb061e6870eb3fc524a7eff600c881cef3 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Tue, 9 May 2017 13:29:10 -0700 Subject: [PATCH 12/42] no special case for macOS running Karma locally - also, reformat a conditional https://github.com/ariya/phantomjs/issues/14558 was causing seg faults at the time this change was made; it is no longer causing seg faults, so phantomjs should be the default. this was prompted by #2759 --- karma.conf.js | 12 ++++++------ package.json | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/karma.conf.js b/karma.conf.js index efec486139..30d5714665 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -4,7 +4,6 @@ var fs = require('fs'); var path = require('path'); var mkdirp = require('mkdirp'); var baseBundleDirpath = path.join(__dirname, '.karma'); -var osName = require('os-name'); module.exports = function (config) { var bundleDirpath; @@ -48,7 +47,7 @@ module.exports = function (config) { }, reporters: ['spec'], colors: true, - browsers: [osName() === 'macOS Sierra' ? 'Chrome' : 'PhantomJS'], // This is the default browser to run, locally + browsers: ['PhantomJS'], // This is the default browser to run, locally logLevel: config.LOG_INFO, client: { mocha: { @@ -97,13 +96,14 @@ module.exports = function (config) { 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 { + if (env.SAUCE_USERNAME || env.SAUCE_ACCESS_KEY) { sauceConfig = { - build: require('os').hostname() + ' (' + Date.now() + ')' + build: require('os') + .hostname() + ' (' + Date.now() + ')' }; console.error('Configured SauceLabs'); + } else { + console.error('No SauceLabs credentials present'); } } mkdirp.sync(bundleDirpath); diff --git a/package.json b/package.json index 6c42870d5a..2a9fc6009b 100644 --- a/package.json +++ b/package.json @@ -334,7 +334,6 @@ "karma-sauce-launcher": "coderbyheart/karma-sauce-launcher", "karma-spec-reporter": "0.0.26", "nyc": "^10.0.0", - "os-name": "^2.0.1", "phantomjs": "1.9.8", "rimraf": "^2.5.2", "semistandard": "^9.2.1", From dcfc09425c1569ec203ad7f93f972b0d71bbcb69 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Tue, 9 May 2017 13:39:36 -0700 Subject: [PATCH 13/42] Revert "use `semistandard` directly" This reverts commit bb70b188078b8db00e08b76b26489350dce38c99. --- .eslintrc.yaml | 11 +++++++++++ Makefile | 6 ++---- lib/browser/.eslintrc.yaml | 4 ++++ package.json | 12 +++++------- test/.eslintrc.yaml | 7 +++++++ 5 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 .eslintrc.yaml create mode 100644 lib/browser/.eslintrc.yaml create mode 100644 test/.eslintrc.yaml diff --git a/.eslintrc.yaml b/.eslintrc.yaml new file mode 100644 index 0000000000..911f22c681 --- /dev/null +++ b/.eslintrc.yaml @@ -0,0 +1,11 @@ +env: + node: true + browser: true +parserOptions: + ecmaVersion: 5 + sourceType: script +extends: semistandard +rules: + strict: + - error + - safe diff --git a/Makefile b/Makefile index 7b8ae94cb4..33408bfbad 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ BROWSERIFY := "node_modules/.bin/browserify" -SEMISTANDARD:= "node_modules/.bin/semistandard" +ESLINT := "node_modules/.bin/eslint" KARMA := "node_modules/.bin/karma" MOCHA := "bin/mocha" NYC := "node_modules/.bin/nyc" @@ -34,9 +34,7 @@ clean: lint: @printf "==> [Test :: Lint]\n" - $(SEMISTANDARD) $(SRC) - $(SEMISTANDARD) --env mocha --global assert --global expect --global run $(TESTS) - $(SEMISTANDARD) bin/* scripts/*.js *.js + $(ESLINT) . "bin/*" 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 diff --git a/lib/browser/.eslintrc.yaml b/lib/browser/.eslintrc.yaml new file mode 100644 index 0000000000..d85f537d3b --- /dev/null +++ b/lib/browser/.eslintrc.yaml @@ -0,0 +1,4 @@ +env: + node: false + browser: false + commonjs: true diff --git a/package.json b/package.json index 2a9fc6009b..ac8a6dcfea 100644 --- a/package.json +++ b/package.json @@ -323,6 +323,11 @@ "browserify": "^13.0.0", "coffee-script": "^1.10.0", "coveralls": "^2.11.15", + "eslint": "^3.11.1", + "eslint-config-semistandard": "^7.0.0", + "eslint-config-standard": "^6.2.1", + "eslint-plugin-promise": "^3.4.0", + "eslint-plugin-standard": "2.0.1", "expect.js": "^0.3.1", "istanbul-combine": "^0.3.0", "karma": "1.3.0", @@ -336,7 +341,6 @@ "nyc": "^10.0.0", "phantomjs": "1.9.8", "rimraf": "^2.5.2", - "semistandard": "^9.2.1", "should": "^11.1.1", "through2": "^2.0.1", "watchify": "^3.7.0" @@ -369,11 +373,5 @@ "phantomjs", "lodash.create" ] - }, - "semistandard": { - "ignore": [ - "/mocha.js", - "/lib/to-iso-string/**/*.js" - ] } } diff --git a/test/.eslintrc.yaml b/test/.eslintrc.yaml new file mode 100644 index 0000000000..1830a0b6f4 --- /dev/null +++ b/test/.eslintrc.yaml @@ -0,0 +1,7 @@ +env: + mocha: true +globals: + expect: false + assert: false + # https://github.com/sindresorhus/globals/pull/102 + run: false From ceee976873cd3fe0558e3373a407bafaf4bb5bad Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Tue, 9 May 2017 13:44:17 -0700 Subject: [PATCH 14/42] lint test/integration/fixtures/simple-reporter.js --- test/integration/fixtures/simple-reporter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/integration/fixtures/simple-reporter.js b/test/integration/fixtures/simple-reporter.js index c2b4e53cd7..d172b2ae66 100644 --- a/test/integration/fixtures/simple-reporter.js +++ b/test/integration/fixtures/simple-reporter.js @@ -1,3 +1,5 @@ +'use strict'; + var baseReporter = require('../../../lib/reporters/base'); module.exports = simplereporter; From 92561c833cfb9bb4122a22044103c8e3713f3c6d Mon Sep 17 00:00:00 2001 From: Jakob Krigovsky Date: Thu, 9 Mar 2017 16:30:18 +0100 Subject: [PATCH 15/42] Add `--no-warnings` flag --- bin/_mocha | 1 + bin/mocha | 1 + 2 files changed, 2 insertions(+) diff --git a/bin/_mocha b/bin/_mocha index 7ba433ef05..bfd526e774 100755 --- a/bin/_mocha +++ b/bin/_mocha @@ -96,6 +96,7 @@ program .option('--no-deprecation', 'silence deprecation warnings') .option('--no-exit', 'require a clean shutdown of the event loop: mocha will not call process.exit') .option('--no-timeouts', 'disables timeouts, given implicitly with --debug') + .option('--no-warnings', 'silence all node process warnings') .option('--opts ', 'specify opts path', 'test/mocha.opts') .option('--perf-basic-prof', 'enable perf linux profiler (basic support)') .option('--prof', 'log statistical profiling information') diff --git a/bin/mocha b/bin/mocha index 0097153d15..814d468ac7 100755 --- a/bin/mocha +++ b/bin/mocha @@ -39,6 +39,7 @@ process.argv.slice(2).forEach(function (arg) { case '--gc-global': case '--es_staging': case '--no-deprecation': + case '--no-warnings': case '--prof': case '--log-timer-events': case '--throw-deprecation': From 9f7f7edef19e5de7fc6a9f1ce969bf8579fa61ee Mon Sep 17 00:00:00 2001 From: Jakob Krigovsky Date: Thu, 9 Mar 2017 16:31:21 +0100 Subject: [PATCH 16/42] Add `--trace-warnings` flag --- bin/_mocha | 1 + bin/mocha | 1 + 2 files changed, 2 insertions(+) diff --git a/bin/_mocha b/bin/_mocha index bfd526e774..00514b5ce0 100755 --- a/bin/_mocha +++ b/bin/_mocha @@ -107,6 +107,7 @@ program .option('--throw-deprecation', 'throw an exception anytime a deprecated function is used') .option('--trace', 'trace function calls') .option('--trace-deprecation', 'show stack traces on deprecations') + .option('--trace-warnings', 'show stack traces on node process warnings') .option('--use_strict', 'enforce strict mode') .option('--watch-extensions ,...', 'additional extensions to monitor with --watch', list, []) .option('--delay', 'wait for async suite definition') diff --git a/bin/mocha b/bin/mocha index 814d468ac7..8ba64a0a06 100755 --- a/bin/mocha +++ b/bin/mocha @@ -44,6 +44,7 @@ process.argv.slice(2).forEach(function (arg) { case '--log-timer-events': case '--throw-deprecation': case '--trace-deprecation': + case '--trace-warnings': case '--use_strict': case '--allow-natives-syntax': case '--perf-basic-prof': From 7554b310d830353db554bc0e67649eb3e9e4cb32 Mon Sep 17 00:00:00 2001 From: Scott Santucci Date: Sun, 14 May 2017 02:09:15 -0400 Subject: [PATCH 17/42] Add Changelog for v3.4.0 --- CHANGELOG.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index de3574a6e4..851a830764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ +# 3.4.0 / 2017-05-14 + +Mocha is now moving to a quicker release schedule: when non-breaking changes are merged, a release should happen that week. + +This week's highlights: + +- `allowUncaught` added to commandline as `--allow-uncaught` (and bugfixed) +- warning-related Node flags + +## :tada: Enhancements + +- [#2793], [#2697]: add --allowUncaught to Node.js ([@lrowe]) +- [#2733]: Add `--no-warnings` and `--trace-warnings` flags ([@sonicdoe]) + +## :bug: Fixes + +- [#2793], [#2697]: fix broken allowUncaught ([@lrowe]) + +## :nut_and_bolt: Other + +- [#2778]: Add license report and scan status ([@xizhao]) +- [#2794]: no special case for macOS running Karma locally ([@boneskull]) +- [#2795]: reverts use of semistandard directly ([#2648]) ([@boneskull]) + +[@lrowe]: https://github.com/lrowe +[@sonicdoe]: https://github.com/sonicdoe +[@xizhao]: https://github.com/xizhao +[@boneskull]: https://github.com/boneskull + +[#2795]: https://github.com/mochajs/mocha/pull/2795 +[#2733]: https://github.com/mochajs/mocha/pull/2733 +[#2793]: https://github.com/mochajs/mocha/pull/2793 +[#2697]: https://github.com/mochajs/mocha/pull/2697 +[#2778]: https://github.com/mochajs/mocha/pull/2778 +[#2794]: https://github.com/mochajs/mocha/pull/2794 + # 3.3.0 / 2017-04-24 Thanks to all our contributors, maintainers, sponsors, and users! ❤️ From 4e3252ef4adaddcf9ed15bcd3abbb3c94029c7a3 Mon Sep 17 00:00:00 2001 From: ScottFreeCode Date: Sun, 14 May 2017 14:17:09 -0400 Subject: [PATCH 18/42] Force rebuild of mocha.js on npm version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ac8a6dcfea..c0586eb591 100644 --- a/package.json +++ b/package.json @@ -303,7 +303,7 @@ "precoverage": "rm -rf coverage", "coverage": "COVERAGE=true npm run test", "postcoverage": "istanbul-combine -d coverage -r lcov -r html coverage/reports/*/*.json", - "preversion": "make test && make mocha.js && git add mocha.js" + "preversion": "make test && rm mocha.js && make mocha.js && git add mocha.js" }, "dependencies": { "browser-stdout": "1.3.0", From 64d96d33e4ff3d266b150bb27f2103b833e1fa7b Mon Sep 17 00:00:00 2001 From: ScottFreeCode Date: Sun, 14 May 2017 19:22:02 +0100 Subject: [PATCH 19/42] :ship: Release v3.4.0 --- mocha.js | 2453 ++++++++++++++++++++++++++++++++------------------ package.json | 2 +- 2 files changed, 1583 insertions(+), 872 deletions(-) diff --git a/mocha.js b/mocha.js index 390f5907a9..07bf7ac288 100644 --- a/mocha.js +++ b/mocha.js @@ -189,7 +189,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":67,"browser-stdout":41}],2:[function(require,module,exports){ +},{"./lib/mocha":14,"_process":82,"browser-stdout":41}],2:[function(require,module,exports){ 'use strict'; function noop () {} @@ -647,7 +647,7 @@ Context.prototype.inspect = function () { }, 2); }; -},{"json3":54}],7:[function(require,module,exports){ +},{"json3":69}],7:[function(require,module,exports){ 'use strict'; /** @@ -1412,9 +1412,17 @@ Mocha.prototype.reporter = function (reporter, reporterOptions) { try { _reporter = require(reporter); } catch (err) { - err.message.indexOf('Cannot find module') !== -1 - ? console.warn('"' + reporter + '" reporter not found') - : console.warn('"' + reporter + '" reporter blew up with error:\n' + err.stack); + if (err.message.indexOf('Cannot find module') !== -1) { + // Try to load reporters from a path (absolute or relative) + try { + _reporter = require(path.resolve(process.cwd(), reporter)); + } catch (_err) { + err.message.indexOf('Cannot find module') !== -1 ? console.warn('"' + reporter + '" reporter not found') + : console.warn('"' + reporter + '" reporter blew up with error:\n' + err.stack); + } + } else { + console.warn('"' + reporter + '" reporter blew up with error:\n' + err.stack); + } } } if (!_reporter && reporter === 'teamcity') { @@ -1782,7 +1790,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":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){ +},{"./context":6,"./hook":7,"./interfaces":11,"./reporters":21,"./runnable":33,"./runner":34,"./suite":35,"./test":36,"./utils":38,"_process":82,"escape-string-regexp":62,"growl":64,"path":42}],15:[function(require,module,exports){ 'use strict'; /** @@ -2427,7 +2435,7 @@ function sameType (a, b) { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../ms":15,"../utils":38,"_process":67,"diff":46,"supports-color":42,"tty":5}],18:[function(require,module,exports){ +},{"../ms":15,"../utils":38,"_process":82,"diff":56,"supports-color":42,"tty":5}],18:[function(require,module,exports){ 'use strict'; /** @@ -2565,7 +2573,7 @@ function Dot (runner) { inherits(Dot, Base); }).call(this,require('_process')) -},{"../utils":38,"./base":17,"_process":67}],20:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":82}],20:[function(require,module,exports){ (function (global){ 'use strict'; @@ -2610,6 +2618,8 @@ var statsTemplate = '
      ' + '
    • duration: 0s
    • ' + '
    '; +var playIcon = '‣'; + /** * Initialize a new `HTML` reporter. * @@ -2705,7 +2715,7 @@ function HTML (runner) { runner.on('pass', function (test) { var url = self.testURL(test); var markup = '
  • %e%ems ' + - '

  • '; + '' + playIcon + ''; var el = fragment(markup, test.speed, test.title, test.duration, url); self.addCodeToggle(el, test.body); appendToStack(el); @@ -2713,7 +2723,7 @@ function HTML (runner) { }); runner.on('fail', function (test) { - var el = fragment('
  • %e

  • ', + var el = fragment('
  • %e ' + playIcon + '

  • ', test.title, self.testURL(test)); var stackString; // Note: Includes leading newline var message = test.err.toString(); @@ -2915,7 +2925,7 @@ function on (el, event, fn) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../browser/progress":4,"../utils":38,"./base":17,"escape-string-regexp":47}],21:[function(require,module,exports){ +},{"../browser/progress":4,"../utils":38,"./base":17,"escape-string-regexp":62}],21:[function(require,module,exports){ 'use strict'; // Alias exports to a their normalized format Mocha#reporter to prevent a need @@ -3003,7 +3013,7 @@ function clean (test) { } }).call(this,require('_process')) -},{"./base":17,"_process":67,"json3":54}],23:[function(require,module,exports){ +},{"./base":17,"_process":82,"json3":69}],23:[function(require,module,exports){ (function (process){ 'use strict'; @@ -3099,7 +3109,7 @@ function errorJSON (err) { } }).call(this,require('_process')) -},{"./base":17,"_process":67}],24:[function(require,module,exports){ +},{"./base":17,"_process":82}],24:[function(require,module,exports){ (function (process){ 'use strict'; @@ -3197,7 +3207,7 @@ function Landing (runner) { inherits(Landing, Base); }).call(this,require('_process')) -},{"../utils":38,"./base":17,"_process":67}],25:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":82}],25:[function(require,module,exports){ (function (process){ 'use strict'; @@ -3264,7 +3274,7 @@ function List (runner) { inherits(List, Base); }).call(this,require('_process')) -},{"../utils":38,"./base":17,"_process":67}],26:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":82}],26:[function(require,module,exports){ (function (process){ 'use strict'; @@ -3367,7 +3377,7 @@ function Markdown (runner) { } }).call(this,require('_process')) -},{"../utils":38,"./base":17,"_process":67}],27:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":82}],27:[function(require,module,exports){ (function (process){ 'use strict'; @@ -3409,7 +3419,7 @@ function Min (runner) { inherits(Min, Base); }).call(this,require('_process')) -},{"../utils":38,"./base":17,"_process":67}],28:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":82}],28:[function(require,module,exports){ (function (process){ 'use strict'; @@ -3676,7 +3686,7 @@ function write (string) { } }).call(this,require('_process')) -},{"../utils":38,"./base":17,"_process":67}],29:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":82}],29:[function(require,module,exports){ (function (process){ 'use strict'; @@ -3771,7 +3781,7 @@ function Progress (runner, options) { inherits(Progress, Base); }).call(this,require('_process')) -},{"../utils":38,"./base":17,"_process":67}],30:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":82}],30:[function(require,module,exports){ 'use strict'; /** @@ -4098,7 +4108,7 @@ function tag (name, attrs, close, content) { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../utils":38,"./base":17,"_process":67,"fs":42,"mkdirp":64,"path":42}],33:[function(require,module,exports){ +},{"../utils":38,"./base":17,"_process":82,"fs":42,"mkdirp":79,"path":42}],33:[function(require,module,exports){ (function (global){ 'use strict'; @@ -4426,8 +4436,11 @@ Runnable.prototype.run = function (fn) { } if (this.allowUncaught) { - callFn(this.fn); - done(); + if (this.isPending()) { + done(); + } else { + callFn(this.fn); + } return; } @@ -4488,7 +4501,7 @@ Runnable.prototype.run = function (fn) { }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./ms":15,"./pending":16,"./utils":38,"debug":2,"events":3,"json3":54,"lodash.create":60}],34:[function(require,module,exports){ +},{"./ms":15,"./pending":16,"./utils":38,"debug":2,"events":3,"json3":69,"lodash.create":75}],34:[function(require,module,exports){ (function (process,global){ 'use strict'; @@ -4924,15 +4937,14 @@ Runner.prototype.runTest = function (fn) { if (this.asyncOnly) { test.asyncOnly = true; } - + test.on('error', function (err) { + self.fail(test, err); + }); if (this.allowUncaught) { test.allowUncaught = true; return test.run(fn); } try { - test.on('error', function (err) { - self.fail(test, err); - }); test.run(fn); } catch (err) { fn(err); @@ -5173,9 +5185,9 @@ Runner.prototype.runSuite = function (suite, fn) { */ Runner.prototype.uncaught = function (err) { if (err) { - debug('uncaught exception %s', err !== function () { + debug('uncaught exception %s', err === (function () { return this; - }.call(err) ? err : (err.message || err)); + }.call(err)) ? (err.message || err) : err); } else { debug('uncaught undefined exception'); err = undefinedError(); @@ -5455,7 +5467,7 @@ function extraGlobals () { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./pending":16,"./runnable":33,"./utils":38,"_process":67,"debug":2,"events":3}],35:[function(require,module,exports){ +},{"./pending":16,"./runnable":33,"./utils":38,"_process":82,"debug":2,"events":3}],35:[function(require,module,exports){ 'use strict'; /** @@ -5913,7 +5925,7 @@ Test.prototype.clone = function () { return test; }; -},{"./runnable":33,"./utils":38,"lodash.create":60}],37:[function(require,module,exports){ +},{"./runnable":33,"./utils":38,"lodash.create":75}],37:[function(require,module,exports){ 'use strict'; /** @@ -6278,7 +6290,9 @@ exports.parseQuery = function (qs) { var key = pair.slice(0, i); var val = pair.slice(++i); - obj[key] = decodeURIComponent(val); + // Due to how the URLSearchParams API treats spaces + obj[key] = decodeURIComponent(val.replace(/\+/g, '%20')); + return obj; }, {}); }; @@ -6372,7 +6386,7 @@ var type = exports.type = function type (value) { return 'buffer'; } return Object.prototype.toString.call(value) - .replace(/^\[.+\s(.+?)\]$/, '$1') + .replace(/^\[.+\s(.+?)]$/, '$1') .toLowerCase(); }; @@ -6697,7 +6711,9 @@ exports.stackTraceFilter = function () { if (is.node) { cwd = process.cwd() + slash; } else { - cwd = (typeof location === 'undefined' ? window.location : location).href.replace(/\/[^\/]*$/, '/'); + cwd = (typeof location === 'undefined' + ? window.location + : location).href.replace(/\/[^/]*$/, '/'); slash = '/'; } @@ -6759,7 +6775,7 @@ exports.isPromise = function isPromise (value) { exports.noop = function () {}; }).call(this,require('_process'),require("buffer").Buffer) -},{"./to-iso-string":37,"_process":67,"buffer":44,"debug":2,"fs":42,"glob":42,"json3":54,"path":42,"util":84}],39:[function(require,module,exports){ +},{"./to-iso-string":37,"_process":82,"buffer":44,"debug":2,"fs":42,"glob":42,"json3":69,"path":42,"util":100}],39:[function(require,module,exports){ 'use strict' exports.byteLength = byteLength @@ -6906,7 +6922,7 @@ BrowserStdout.prototype._write = function(chunks, encoding, cb) { } }).call(this,require('_process')) -},{"_process":67,"stream":79,"util":84}],42:[function(require,module,exports){ +},{"_process":82,"stream":95,"util":100}],42:[function(require,module,exports){ arguments[4][40][0].apply(exports,arguments) },{"dup":40}],43:[function(require,module,exports){ (function (global){ @@ -8813,7 +8829,7 @@ function isnan (val) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"base64-js":39,"ieee754":50,"isarray":53}],45:[function(require,module,exports){ +},{"base64-js":39,"ieee754":65,"isarray":68}],45:[function(require,module,exports){ (function (Buffer){ // Copyright Joyent, Inc. and other Node contributors. // @@ -8924,646 +8940,1276 @@ function objectToString(o) { } }).call(this,{"isBuffer":require("../../is-buffer/index.js")}) -},{"../../is-buffer/index.js":52}],46:[function(require,module,exports){ -/* See LICENSE file for terms of use */ +},{"../../is-buffer/index.js":67}],46:[function(require,module,exports){ +/*istanbul ignore start*/"use strict"; + +exports.__esModule = true; +exports. /*istanbul ignore end*/convertChangesToDMP = convertChangesToDMP; +// See: http://code.google.com/p/google-diff-match-patch/wiki/API +function convertChangesToDMP(changes) { + var ret = [], + change = /*istanbul ignore start*/void 0 /*istanbul ignore end*/, + operation = /*istanbul ignore start*/void 0 /*istanbul ignore end*/; + for (var i = 0; i < changes.length; i++) { + change = changes[i]; + if (change.added) { + operation = 1; + } else if (change.removed) { + operation = -1; + } else { + operation = 0; + } -/* - * Text diff implementation. - * - * This library supports the following APIS: - * JsDiff.diffChars: Character by character diff - * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace - * JsDiff.diffLines: Line based diff - * - * JsDiff.diffCss: Diff targeted at CSS content - * - * These methods are based on the implementation proposed in - * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986). - * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927 - */ -(function(global, undefined) { - var objectPrototypeToString = Object.prototype.toString; + ret.push([operation, change.value]); + } + return ret; +} - /*istanbul ignore next*/ - function map(arr, mapper, that) { - if (Array.prototype.map) { - return Array.prototype.map.call(arr, mapper, that); - } - var other = new Array(arr.length); +},{}],47:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; - for (var i = 0, n = arr.length; i < n; i++) { - other[i] = mapper.call(that, arr[i], i, arr); +exports.__esModule = true; +exports. /*istanbul ignore end*/convertChangesToXML = convertChangesToXML; +function convertChangesToXML(changes) { + var ret = []; + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + if (change.added) { + ret.push(''); + } else if (change.removed) { + ret.push(''); } - return other; - } - function clonePath(path) { - return { newPos: path.newPos, components: path.components.slice(0) }; - } - function removeEmpty(array) { - var ret = []; - for (var i = 0; i < array.length; i++) { - if (array[i]) { - ret.push(array[i]); - } + + ret.push(escapeHTML(change.value)); + + if (change.added) { + ret.push(''); + } else if (change.removed) { + ret.push(''); } - return ret; } - function escapeHTML(s) { - var n = s; - n = n.replace(/&/g, '&'); - n = n.replace(//g, '>'); - n = n.replace(/"/g, '"'); + return ret.join(''); +} - return n; - } +function escapeHTML(s) { + var n = s; + n = n.replace(/&/g, '&'); + n = n.replace(//g, '>'); + n = n.replace(/"/g, '"'); - // This function handles the presence of circular references by bailing out when encountering an - // object that is already on the "stack" of items being processed. - function canonicalize(obj, stack, replacementStack) { - stack = stack || []; - replacementStack = replacementStack || []; + return n; +} - var i; - for (i = 0; i < stack.length; i += 1) { - if (stack[i] === obj) { - return replacementStack[i]; - } +},{}],48:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; + +exports.__esModule = true; +exports.arrayDiff = undefined; +exports. /*istanbul ignore end*/diffArrays = diffArrays; + +var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; + +/*istanbul ignore start*/ +var _base2 = _interopRequireDefault(_base); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +/*istanbul ignore end*/var arrayDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/arrayDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; +arrayDiff.tokenize = arrayDiff.join = function (value) { + return value.slice(); +}; + +function diffArrays(oldArr, newArr, callback) { + return arrayDiff.diff(oldArr, newArr, callback); +} + + +},{"./base":49}],49:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; + +exports.__esModule = true; +exports['default'] = /*istanbul ignore end*/Diff; +function Diff() {} + +Diff.prototype = { /*istanbul ignore start*/ + /*istanbul ignore end*/diff: function diff(oldString, newString) { + /*istanbul ignore start*/var /*istanbul ignore end*/options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + + var callback = options.callback; + if (typeof options === 'function') { + callback = options; + options = {}; } + this.options = options; - var canonicalizedObj; + var self = this; - if ('[object Array]' === objectPrototypeToString.call(obj)) { - stack.push(obj); - canonicalizedObj = new Array(obj.length); - replacementStack.push(canonicalizedObj); - for (i = 0; i < obj.length; i += 1) { - canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack); - } - stack.pop(); - replacementStack.pop(); - } else if (typeof obj === 'object' && obj !== null) { - stack.push(obj); - canonicalizedObj = {}; - replacementStack.push(canonicalizedObj); - var sortedKeys = [], - key; - for (key in obj) { - sortedKeys.push(key); - } - sortedKeys.sort(); - for (i = 0; i < sortedKeys.length; i += 1) { - key = sortedKeys[i]; - canonicalizedObj[key] = canonicalize(obj[key], stack, replacementStack); + function done(value) { + if (callback) { + setTimeout(function () { + callback(undefined, value); + }, 0); + return true; + } else { + return value; } - stack.pop(); - replacementStack.pop(); - } else { - canonicalizedObj = obj; } - return canonicalizedObj; - } - function buildValues(components, newString, oldString, useLongestToken) { - var componentPos = 0, - componentLen = components.length, - newPos = 0, - oldPos = 0; + // Allow subclasses to massage the input prior to running + oldString = this.castInput(oldString); + newString = this.castInput(newString); + + oldString = this.removeEmpty(this.tokenize(oldString)); + newString = this.removeEmpty(this.tokenize(newString)); + + var newLen = newString.length, + oldLen = oldString.length; + var editLength = 1; + var maxEditLength = newLen + oldLen; + var bestPath = [{ newPos: -1, components: [] }]; + + // Seed editLength = 0, i.e. the content starts with the same values + var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); + if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + // Identity per the equality and tokenizer + return done([{ value: this.join(newString), count: newString.length }]); + } + + // Main worker method. checks all permutations of a given edit length for acceptance. + function execEditLength() { + for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) { + var basePath = /*istanbul ignore start*/void 0 /*istanbul ignore end*/; + var addPath = bestPath[diagonalPath - 1], + removePath = bestPath[diagonalPath + 1], + _oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; + if (addPath) { + // No one else is going to attempt to use this value, clear it + bestPath[diagonalPath - 1] = undefined; + } - for (; componentPos < componentLen; componentPos++) { - var component = components[componentPos]; - if (!component.removed) { - if (!component.added && useLongestToken) { - var value = newString.slice(newPos, newPos + component.count); - value = map(value, function(value, i) { - var oldValue = oldString[oldPos + i]; - return oldValue.length > value.length ? oldValue : value; - }); + var canAdd = addPath && addPath.newPos + 1 < newLen, + canRemove = removePath && 0 <= _oldPos && _oldPos < oldLen; + if (!canAdd && !canRemove) { + // If this path is a terminal then prune + bestPath[diagonalPath] = undefined; + continue; + } - component.value = value.join(''); + // Select the diagonal that we want to branch from. We select the prior + // path whose position in the new string is the farthest from the origin + // and does not pass the bounds of the diff graph + if (!canAdd || canRemove && addPath.newPos < removePath.newPos) { + basePath = clonePath(removePath); + self.pushComponent(basePath.components, undefined, true); } else { - component.value = newString.slice(newPos, newPos + component.count).join(''); + basePath = addPath; // No need to clone, we've pulled it from the list + basePath.newPos++; + self.pushComponent(basePath.components, true, undefined); } - newPos += component.count; - // Common case - if (!component.added) { - oldPos += component.count; + _oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); + + // If we have hit the end of both strings, then we are done + if (basePath.newPos + 1 >= newLen && _oldPos + 1 >= oldLen) { + return done(buildValues(self, basePath.components, newString, oldString, self.useLongestToken)); + } else { + // Otherwise track this path as a potential candidate and continue. + bestPath[diagonalPath] = basePath; } - } else { - component.value = oldString.slice(oldPos, oldPos + component.count).join(''); - oldPos += component.count; + } - // Reverse add and remove so removes are output first to match common convention - // The diffing algorithm is tied to add then remove output and this is the simplest - // route to get the desired output with minimal overhead. - if (componentPos && components[componentPos - 1].added) { - var tmp = components[componentPos - 1]; - components[componentPos - 1] = components[componentPos]; - components[componentPos] = tmp; + editLength++; + } + + // Performs the length of edit iteration. Is a bit fugly as this has to support the + // sync and async mode which is never fun. Loops over execEditLength until a value + // is produced. + if (callback) { + (function exec() { + setTimeout(function () { + // This should not happen, but we want to be safe. + /* istanbul ignore next */ + if (editLength > maxEditLength) { + return callback(); + } + + if (!execEditLength()) { + exec(); + } + }, 0); + })(); + } else { + while (editLength <= maxEditLength) { + var ret = execEditLength(); + if (ret) { + return ret; } } } + }, + /*istanbul ignore start*/ /*istanbul ignore end*/pushComponent: function pushComponent(components, added, removed) { + var last = components[components.length - 1]; + if (last && last.added === added && last.removed === removed) { + // We need to clone here as the component clone operation is just + // as shallow array clone + components[components.length - 1] = { count: last.count + 1, added: added, removed: removed }; + } else { + components.push({ count: 1, added: added, removed: removed }); + } + }, + /*istanbul ignore start*/ /*istanbul ignore end*/extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) { + var newLen = newString.length, + oldLen = oldString.length, + newPos = basePath.newPos, + oldPos = newPos - diagonalPath, + commonCount = 0; + while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) { + newPos++; + oldPos++; + commonCount++; + } - return components; - } + if (commonCount) { + basePath.components.push({ count: commonCount }); + } - function Diff(ignoreWhitespace) { - this.ignoreWhitespace = ignoreWhitespace; + basePath.newPos = newPos; + return oldPos; + }, + /*istanbul ignore start*/ /*istanbul ignore end*/equals: function equals(left, right) { + return left === right; + }, + /*istanbul ignore start*/ /*istanbul ignore end*/removeEmpty: function removeEmpty(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + if (array[i]) { + ret.push(array[i]); + } + } + return ret; + }, + /*istanbul ignore start*/ /*istanbul ignore end*/castInput: function castInput(value) { + return value; + }, + /*istanbul ignore start*/ /*istanbul ignore end*/tokenize: function tokenize(value) { + return value.split(''); + }, + /*istanbul ignore start*/ /*istanbul ignore end*/join: function join(chars) { + return chars.join(''); } - Diff.prototype = { - diff: function(oldString, newString, callback) { - var self = this; +}; - function done(value) { - if (callback) { - setTimeout(function() { callback(undefined, value); }, 0); - return true; - } else { - return value; - } - } +function buildValues(diff, components, newString, oldString, useLongestToken) { + var componentPos = 0, + componentLen = components.length, + newPos = 0, + oldPos = 0; + + for (; componentPos < componentLen; componentPos++) { + var component = components[componentPos]; + if (!component.removed) { + if (!component.added && useLongestToken) { + var value = newString.slice(newPos, newPos + component.count); + value = value.map(function (value, i) { + var oldValue = oldString[oldPos + i]; + return oldValue.length > value.length ? oldValue : value; + }); - // Handle the identity case (this is due to unrolling editLength == 0 - if (newString === oldString) { - return done([{ value: newString }]); + component.value = diff.join(value); + } else { + component.value = diff.join(newString.slice(newPos, newPos + component.count)); } - if (!newString) { - return done([{ value: oldString, removed: true }]); + newPos += component.count; + + // Common case + if (!component.added) { + oldPos += component.count; } - if (!oldString) { - return done([{ value: newString, added: true }]); + } else { + component.value = diff.join(oldString.slice(oldPos, oldPos + component.count)); + oldPos += component.count; + + // Reverse add and remove so removes are output first to match common convention + // The diffing algorithm is tied to add then remove output and this is the simplest + // route to get the desired output with minimal overhead. + if (componentPos && components[componentPos - 1].added) { + var tmp = components[componentPos - 1]; + components[componentPos - 1] = components[componentPos]; + components[componentPos] = tmp; } + } + } - newString = this.tokenize(newString); - oldString = this.tokenize(oldString); + // Special case handle for when one terminal is ignored. For this case we merge the + // terminal into the prior string and drop the change. + var lastComponent = components[componentLen - 1]; + if (componentLen > 1 && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) { + components[componentLen - 2].value += lastComponent.value; + components.pop(); + } - var newLen = newString.length, oldLen = oldString.length; - var editLength = 1; - var maxEditLength = newLen + oldLen; - var bestPath = [{ newPos: -1, components: [] }]; + return components; +} - // Seed editLength = 0, i.e. the content starts with the same values - var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); - if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) { - // Identity per the equality and tokenizer - return done([{value: newString.join('')}]); - } +function clonePath(path) { + return { newPos: path.newPos, components: path.components.slice(0) }; +} - // Main worker method. checks all permutations of a given edit length for acceptance. - function execEditLength() { - for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) { - var basePath; - var addPath = bestPath[diagonalPath - 1], - removePath = bestPath[diagonalPath + 1], - oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; - if (addPath) { - // No one else is going to attempt to use this value, clear it - bestPath[diagonalPath - 1] = undefined; - } - var canAdd = addPath && addPath.newPos + 1 < newLen, - canRemove = removePath && 0 <= oldPos && oldPos < oldLen; - if (!canAdd && !canRemove) { - // If this path is a terminal then prune - bestPath[diagonalPath] = undefined; - continue; - } +},{}],50:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; - // Select the diagonal that we want to branch from. We select the prior - // path whose position in the new string is the farthest from the origin - // and does not pass the bounds of the diff graph - if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { - basePath = clonePath(removePath); - self.pushComponent(basePath.components, undefined, true); - } else { - basePath = addPath; // No need to clone, we've pulled it from the list - basePath.newPos++; - self.pushComponent(basePath.components, true, undefined); - } +exports.__esModule = true; +exports.characterDiff = undefined; +exports. /*istanbul ignore end*/diffChars = diffChars; - oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); +var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; - // If we have hit the end of both strings, then we are done - if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) { - return done(buildValues(basePath.components, newString, oldString, self.useLongestToken)); - } else { - // Otherwise track this path as a potential candidate and continue. - bestPath[diagonalPath] = basePath; - } - } +/*istanbul ignore start*/ +var _base2 = _interopRequireDefault(_base); - editLength++; - } +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - // Performs the length of edit iteration. Is a bit fugly as this has to support the - // sync and async mode which is never fun. Loops over execEditLength until a value - // is produced. - if (callback) { - (function exec() { - setTimeout(function() { - // This should not happen, but we want to be safe. - /*istanbul ignore next */ - if (editLength > maxEditLength) { - return callback(); - } +/*istanbul ignore end*/var characterDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/characterDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; +function diffChars(oldStr, newStr, callback) { + return characterDiff.diff(oldStr, newStr, callback); +} - if (!execEditLength()) { - exec(); - } - }, 0); - }()); - } else { - while (editLength <= maxEditLength) { - var ret = execEditLength(); - if (ret) { - return ret; - } - } - } - }, - pushComponent: function(components, added, removed) { - var last = components[components.length - 1]; - if (last && last.added === added && last.removed === removed) { - // We need to clone here as the component clone operation is just - // as shallow array clone - components[components.length - 1] = {count: last.count + 1, added: added, removed: removed }; - } else { - components.push({count: 1, added: added, removed: removed }); - } - }, - extractCommon: function(basePath, newString, oldString, diagonalPath) { - var newLen = newString.length, - oldLen = oldString.length, - newPos = basePath.newPos, - oldPos = newPos - diagonalPath, - - commonCount = 0; - while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) { - newPos++; - oldPos++; - commonCount++; - } +},{"./base":49}],51:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; - if (commonCount) { - basePath.components.push({count: commonCount}); - } +exports.__esModule = true; +exports.cssDiff = undefined; +exports. /*istanbul ignore end*/diffCss = diffCss; - basePath.newPos = newPos; - return oldPos; - }, +var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; - equals: function(left, right) { - var reWhitespace = /\S/; - return left === right || (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)); - }, - tokenize: function(value) { - return value.split(''); - } - }; +/*istanbul ignore start*/ +var _base2 = _interopRequireDefault(_base); - var CharDiff = new Diff(); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - var WordDiff = new Diff(true); - var WordWithSpaceDiff = new Diff(); - WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) { - return removeEmpty(value.split(/(\s+|\b)/)); - }; +/*istanbul ignore end*/var cssDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/cssDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; +cssDiff.tokenize = function (value) { + return value.split(/([{}:;,]|\s+)/); +}; - var CssDiff = new Diff(true); - CssDiff.tokenize = function(value) { - return removeEmpty(value.split(/([{}:;,]|\s+)/)); - }; +function diffCss(oldStr, newStr, callback) { + return cssDiff.diff(oldStr, newStr, callback); +} - var LineDiff = new Diff(); - var TrimmedLineDiff = new Diff(); - TrimmedLineDiff.ignoreTrim = true; +},{"./base":49}],52:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; - LineDiff.tokenize = TrimmedLineDiff.tokenize = function(value) { - var retLines = [], - lines = value.split(/^/m); - for (var i = 0; i < lines.length; i++) { - var line = lines[i], - lastLine = lines[i - 1], - lastLineLastChar = lastLine && lastLine[lastLine.length - 1]; +exports.__esModule = true; +exports.jsonDiff = undefined; - // Merge lines that may contain windows new lines - if (line === '\n' && lastLineLastChar === '\r') { - retLines[retLines.length - 1] = retLines[retLines.length - 1].slice(0, -1) + '\r\n'; - } else { - if (this.ignoreTrim) { - line = line.trim(); - // add a newline unless this is the last line. - if (i < lines.length - 1) { - line += '\n'; - } - } - retLines.push(line); - } - } +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; - return retLines; - }; +exports. /*istanbul ignore end*/diffJson = diffJson; +/*istanbul ignore start*/exports. /*istanbul ignore end*/canonicalize = canonicalize; - var PatchDiff = new Diff(); - PatchDiff.tokenize = function(value) { - var ret = [], - linesAndNewlines = value.split(/(\n|\r\n)/); +var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; - // Ignore the final empty token that occurs if the string ends with a new line - if (!linesAndNewlines[linesAndNewlines.length - 1]) { - linesAndNewlines.pop(); - } +/*istanbul ignore start*/ +var _base2 = _interopRequireDefault(_base); - // Merge the content and line separators into single tokens - for (var i = 0; i < linesAndNewlines.length; i++) { - var line = linesAndNewlines[i]; +/*istanbul ignore end*/ +var /*istanbul ignore start*/_line = require('./line') /*istanbul ignore end*/; - if (i % 2) { - ret[ret.length - 1] += line; - } else { - ret.push(line); - } +/*istanbul ignore start*/ +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +/*istanbul ignore end*/ + +var objectPrototypeToString = Object.prototype.toString; + +var jsonDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/jsonDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; +// Discriminate between two lines of pretty-printed, serialized JSON where one of them has a +// dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: +jsonDiff.useLongestToken = true; + +jsonDiff.tokenize = /*istanbul ignore start*/_line.lineDiff. /*istanbul ignore end*/tokenize; +jsonDiff.castInput = function (value) { + /*istanbul ignore start*/var /*istanbul ignore end*/undefinedReplacement = this.options.undefinedReplacement; + + + return typeof value === 'string' ? value : JSON.stringify(canonicalize(value), function (k, v) { + if (typeof v === 'undefined') { + return undefinedReplacement; } - return ret; - }; - var SentenceDiff = new Diff(); - SentenceDiff.tokenize = function(value) { - return removeEmpty(value.split(/(\S.+?[.!?])(?=\s+|$)/)); - }; + return v; + }, ' '); +}; +jsonDiff.equals = function (left, right) { + return (/*istanbul ignore start*/_base2['default']. /*istanbul ignore end*/prototype.equals(left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1')) + ); +}; - var JsonDiff = new Diff(); - // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a - // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: - JsonDiff.useLongestToken = true; - JsonDiff.tokenize = LineDiff.tokenize; - JsonDiff.equals = function(left, right) { - return LineDiff.equals(left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1')); - }; +function diffJson(oldObj, newObj, options) { + return jsonDiff.diff(oldObj, newObj, options); +} + +// This function handles the presence of circular references by bailing out when encountering an +// object that is already on the "stack" of items being processed. +function canonicalize(obj, stack, replacementStack) { + stack = stack || []; + replacementStack = replacementStack || []; - var JsDiff = { - Diff: Diff, + var i = /*istanbul ignore start*/void 0 /*istanbul ignore end*/; - diffChars: function(oldStr, newStr, callback) { return CharDiff.diff(oldStr, newStr, callback); }, - diffWords: function(oldStr, newStr, callback) { return WordDiff.diff(oldStr, newStr, callback); }, - diffWordsWithSpace: function(oldStr, newStr, callback) { return WordWithSpaceDiff.diff(oldStr, newStr, callback); }, - diffLines: function(oldStr, newStr, callback) { return LineDiff.diff(oldStr, newStr, callback); }, - diffTrimmedLines: function(oldStr, newStr, callback) { return TrimmedLineDiff.diff(oldStr, newStr, callback); }, + for (i = 0; i < stack.length; i += 1) { + if (stack[i] === obj) { + return replacementStack[i]; + } + } - diffSentences: function(oldStr, newStr, callback) { return SentenceDiff.diff(oldStr, newStr, callback); }, + var canonicalizedObj = /*istanbul ignore start*/void 0 /*istanbul ignore end*/; - diffCss: function(oldStr, newStr, callback) { return CssDiff.diff(oldStr, newStr, callback); }, - diffJson: function(oldObj, newObj, callback) { - return JsonDiff.diff( - typeof oldObj === 'string' ? oldObj : JSON.stringify(canonicalize(oldObj), undefined, ' '), - typeof newObj === 'string' ? newObj : JSON.stringify(canonicalize(newObj), undefined, ' '), - callback - ); - }, + if ('[object Array]' === objectPrototypeToString.call(obj)) { + stack.push(obj); + canonicalizedObj = new Array(obj.length); + replacementStack.push(canonicalizedObj); + for (i = 0; i < obj.length; i += 1) { + canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack); + } + stack.pop(); + replacementStack.pop(); + return canonicalizedObj; + } - createTwoFilesPatch: function(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader) { - var ret = []; + if (obj && obj.toJSON) { + obj = obj.toJSON(); + } - if (oldFileName == newFileName) { - ret.push('Index: ' + oldFileName); + if ( /*istanbul ignore start*/(typeof /*istanbul ignore end*/obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && obj !== null) { + stack.push(obj); + canonicalizedObj = {}; + replacementStack.push(canonicalizedObj); + var sortedKeys = [], + key = /*istanbul ignore start*/void 0 /*istanbul ignore end*/; + for (key in obj) { + /* istanbul ignore else */ + if (obj.hasOwnProperty(key)) { + sortedKeys.push(key); } - ret.push('==================================================================='); - ret.push('--- ' + oldFileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader)); - ret.push('+++ ' + newFileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader)); + } + sortedKeys.sort(); + for (i = 0; i < sortedKeys.length; i += 1) { + key = sortedKeys[i]; + canonicalizedObj[key] = canonicalize(obj[key], stack, replacementStack); + } + stack.pop(); + replacementStack.pop(); + } else { + canonicalizedObj = obj; + } + return canonicalizedObj; +} - var diff = PatchDiff.diff(oldStr, newStr); - diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier - // Formats a given set of lines for printing as context lines in a patch - function contextLines(lines) { - return map(lines, function(entry) { return ' ' + entry; }); - } +},{"./base":49,"./line":53}],53:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; - // Outputs the no newline at end of file warning if needed - function eofNL(curRange, i, current) { - var last = diff[diff.length - 2], - isLast = i === diff.length - 2, - isLastOfType = i === diff.length - 3 && current.added !== last.added; +exports.__esModule = true; +exports.lineDiff = undefined; +exports. /*istanbul ignore end*/diffLines = diffLines; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffTrimmedLines = diffTrimmedLines; - // Figure out if this is the last line for the given file and missing NL - if (!(/\n$/.test(current.value)) && (isLast || isLastOfType)) { - curRange.push('\\ No newline at end of file'); - } - } +var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; - var oldRangeStart = 0, newRangeStart = 0, curRange = [], - oldLine = 1, newLine = 1; - for (var i = 0; i < diff.length; i++) { - var current = diff[i], - lines = current.lines || current.value.replace(/\n$/, '').split('\n'); - current.lines = lines; - - if (current.added || current.removed) { - // If we have previous context, start with that - if (!oldRangeStart) { - var prev = diff[i - 1]; - oldRangeStart = oldLine; - newRangeStart = newLine; - - if (prev) { - curRange = contextLines(prev.lines.slice(-4)); - oldRangeStart -= curRange.length; - newRangeStart -= curRange.length; - } - } +/*istanbul ignore start*/ +var _base2 = _interopRequireDefault(_base); - // Output our changes - curRange.push.apply(curRange, map(lines, function(entry) { - return (current.added ? '+' : '-') + entry; - })); - eofNL(curRange, i, current); +/*istanbul ignore end*/ +var /*istanbul ignore start*/_params = require('../util/params') /*istanbul ignore end*/; - // Track the updated file position - if (current.added) { - newLine += lines.length; - } else { - oldLine += lines.length; - } - } else { - // Identical context lines. Track line changes - if (oldRangeStart) { - // Close out any changes that have been output (or join overlapping) - if (lines.length <= 8 && i < diff.length - 2) { - // Overlapping - curRange.push.apply(curRange, contextLines(lines)); - } else { - // end the range and output - var contextSize = Math.min(lines.length, 4); - ret.push( - '@@ -' + oldRangeStart + ',' + (oldLine - oldRangeStart + contextSize) - + ' +' + newRangeStart + ',' + (newLine - newRangeStart + contextSize) - + ' @@'); - ret.push.apply(ret, curRange); - ret.push.apply(ret, contextLines(lines.slice(0, contextSize))); - if (lines.length <= 4) { - eofNL(ret, i, current); - } +/*istanbul ignore start*/ +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - oldRangeStart = 0; - newRangeStart = 0; - curRange = []; - } - } - oldLine += lines.length; - newLine += lines.length; - } +/*istanbul ignore end*/var lineDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/lineDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; +lineDiff.tokenize = function (value) { + var retLines = [], + linesAndNewlines = value.split(/(\n|\r\n)/); + + // Ignore the final empty token that occurs if the string ends with a new line + if (!linesAndNewlines[linesAndNewlines.length - 1]) { + linesAndNewlines.pop(); + } + + // Merge the content and line separators into single tokens + for (var i = 0; i < linesAndNewlines.length; i++) { + var line = linesAndNewlines[i]; + + if (i % 2 && !this.options.newlineIsToken) { + retLines[retLines.length - 1] += line; + } else { + if (this.options.ignoreWhitespace) { + line = line.trim(); } + retLines.push(line); + } + } - return ret.join('\n') + '\n'; - }, + return retLines; +}; - createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) { - return JsDiff.createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader); - }, +function diffLines(oldStr, newStr, callback) { + return lineDiff.diff(oldStr, newStr, callback); +} +function diffTrimmedLines(oldStr, newStr, callback) { + var options = /*istanbul ignore start*/(0, _params.generateOptions) /*istanbul ignore end*/(callback, { ignoreWhitespace: true }); + return lineDiff.diff(oldStr, newStr, options); +} - applyPatch: function(oldStr, uniDiff) { - var diffstr = uniDiff.split('\n'), - hunks = [], - i = 0, - remEOFNL = false, - addEOFNL = false; - // Skip to the first change hunk - while (i < diffstr.length && !(/^@@/.test(diffstr[i]))) { - i++; - } +},{"../util/params":61,"./base":49}],54:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; - // Parse the unified diff - for (; i < diffstr.length; i++) { - if (diffstr[i][0] === '@') { - var chnukHeader = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/); - hunks.unshift({ - start: chnukHeader[3], - oldlength: +chnukHeader[2], - removed: [], - newlength: chnukHeader[4], - added: [] - }); - } else if (diffstr[i][0] === '+') { - hunks[0].added.push(diffstr[i].substr(1)); - } else if (diffstr[i][0] === '-') { - hunks[0].removed.push(diffstr[i].substr(1)); - } else if (diffstr[i][0] === ' ') { - hunks[0].added.push(diffstr[i].substr(1)); - hunks[0].removed.push(diffstr[i].substr(1)); - } else if (diffstr[i][0] === '\\') { - if (diffstr[i - 1][0] === '+') { - remEOFNL = true; - } else if (diffstr[i - 1][0] === '-') { - addEOFNL = true; - } - } - } +exports.__esModule = true; +exports.sentenceDiff = undefined; +exports. /*istanbul ignore end*/diffSentences = diffSentences; - // Apply the diff to the input - var lines = oldStr.split('\n'); - for (i = hunks.length - 1; i >= 0; i--) { - var hunk = hunks[i]; - // Sanity check the input string. Bail if we don't match. - for (var j = 0; j < hunk.oldlength; j++) { - if (lines[hunk.start - 1 + j] !== hunk.removed[j]) { - return false; - } - } - Array.prototype.splice.apply(lines, [hunk.start - 1, hunk.oldlength].concat(hunk.added)); - } +var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; - // Handle EOFNL insertion/removal - if (remEOFNL) { - while (!lines[lines.length - 1]) { - lines.pop(); - } - } else if (addEOFNL) { - lines.push(''); - } - return lines.join('\n'); - }, +/*istanbul ignore start*/ +var _base2 = _interopRequireDefault(_base); - convertChangesToXML: function(changes) { - var ret = []; - for (var i = 0; i < changes.length; i++) { - var change = changes[i]; - if (change.added) { - ret.push(''); - } else if (change.removed) { - ret.push(''); - } +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - ret.push(escapeHTML(change.value)); +/*istanbul ignore end*/var sentenceDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/sentenceDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; +sentenceDiff.tokenize = function (value) { + return value.split(/(\S.+?[.!?])(?=\s+|$)/); +}; - if (change.added) { - ret.push(''); - } else if (change.removed) { - ret.push(''); - } - } - return ret.join(''); - }, +function diffSentences(oldStr, newStr, callback) { + return sentenceDiff.diff(oldStr, newStr, callback); +} - // See: http://code.google.com/p/google-diff-match-patch/wiki/API - convertChangesToDMP: function(changes) { - var ret = [], - change, - operation; - for (var i = 0; i < changes.length; i++) { - change = changes[i]; - if (change.added) { - operation = 1; - } else if (change.removed) { - operation = -1; - } else { - operation = 0; - } - ret.push([operation, change.value]); - } - return ret; - }, +},{"./base":49}],55:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; - canonicalize: canonicalize - }; +exports.__esModule = true; +exports.wordDiff = undefined; +exports. /*istanbul ignore end*/diffWords = diffWords; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffWordsWithSpace = diffWordsWithSpace; - /*istanbul ignore next */ - /*global module */ - if (typeof module !== 'undefined' && module.exports) { - module.exports = JsDiff; - } else if (false) { - /*global define */ - define([], function() { return JsDiff; }); - } else if (typeof global.JsDiff === 'undefined') { - global.JsDiff = JsDiff; - } -}(this)); +var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; -},{}],47:[function(require,module,exports){ -'use strict'; +/*istanbul ignore start*/ +var _base2 = _interopRequireDefault(_base); -var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; +/*istanbul ignore end*/ +var /*istanbul ignore start*/_params = require('../util/params') /*istanbul ignore end*/; -module.exports = function (str) { - if (typeof str !== 'string') { - throw new TypeError('Expected a string'); - } +/*istanbul ignore start*/ +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - return str.replace(matchOperatorsRe, '\\$&'); -}; +/*istanbul ignore end*/ -},{}],48:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. +// Based on https://en.wikipedia.org/wiki/Latin_script_in_Unicode // -// 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 +// Ranges and exceptions: +// Latin-1 Supplement, 0080–00FF +// - U+00D7 × Multiplication sign +// - U+00F7 ÷ Division sign +// Latin Extended-A, 0100–017F +// Latin Extended-B, 0180–024F +// IPA Extensions, 0250–02AF +// Spacing Modifier Letters, 02B0–02FF +// - U+02C7 ˇ ˇ Caron +// - U+02D8 ˘ ˘ Breve +// - U+02D9 ˙ ˙ Dot Above +// - U+02DA ˚ ˚ Ring Above +// - U+02DB ˛ ˛ Ogonek +// - U+02DC ˜ ˜ Small Tilde +// - U+02DD ˝ ˝ Double Acute Accent +// Latin Extended Additional, 1E00–1EFF +var extendedWordChars = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/; + +var reWhitespace = /\S/; + +var wordDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/wordDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; +wordDiff.equals = function (left, right) { + return left === right || this.options.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right); +}; +wordDiff.tokenize = function (value) { + var tokens = value.split(/(\s+|\b)/); + + // Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set. + for (var i = 0; i < tokens.length - 1; i++) { + // If we have an empty string in the next field and we have only word chars before and after, merge + if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars.test(tokens[i]) && extendedWordChars.test(tokens[i + 2])) { + tokens[i] += tokens[i + 2]; + tokens.splice(i + 1, 2); + i--; + } + } + + return tokens; +}; + +function diffWords(oldStr, newStr, callback) { + var options = /*istanbul ignore start*/(0, _params.generateOptions) /*istanbul ignore end*/(callback, { ignoreWhitespace: true }); + return wordDiff.diff(oldStr, newStr, options); +} +function diffWordsWithSpace(oldStr, newStr, callback) { + return wordDiff.diff(oldStr, newStr, callback); +} + + +},{"../util/params":61,"./base":49}],56:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; + +exports.__esModule = true; +exports.canonicalize = exports.convertChangesToXML = exports.convertChangesToDMP = exports.parsePatch = exports.applyPatches = exports.applyPatch = exports.createPatch = exports.createTwoFilesPatch = exports.structuredPatch = exports.diffArrays = exports.diffJson = exports.diffCss = exports.diffSentences = exports.diffTrimmedLines = exports.diffLines = exports.diffWordsWithSpace = exports.diffWords = exports.diffChars = exports.Diff = undefined; +/*istanbul ignore end*/ +var /*istanbul ignore start*/_base = require('./diff/base') /*istanbul ignore end*/; + +/*istanbul ignore start*/ +var _base2 = _interopRequireDefault(_base); + +/*istanbul ignore end*/ +var /*istanbul ignore start*/_character = require('./diff/character') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_word = require('./diff/word') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_line = require('./diff/line') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_sentence = require('./diff/sentence') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_css = require('./diff/css') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_json = require('./diff/json') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_array = require('./diff/array') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_apply = require('./patch/apply') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_parse = require('./patch/parse') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_create = require('./patch/create') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_dmp = require('./convert/dmp') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_xml = require('./convert/xml') /*istanbul ignore end*/; + +/*istanbul ignore start*/ +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +exports. /*istanbul ignore end*/Diff = _base2['default']; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffChars = _character.diffChars; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffWords = _word.diffWords; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffWordsWithSpace = _word.diffWordsWithSpace; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffLines = _line.diffLines; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffTrimmedLines = _line.diffTrimmedLines; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffSentences = _sentence.diffSentences; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffCss = _css.diffCss; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffJson = _json.diffJson; +/*istanbul ignore start*/exports. /*istanbul ignore end*/diffArrays = _array.diffArrays; +/*istanbul ignore start*/exports. /*istanbul ignore end*/structuredPatch = _create.structuredPatch; +/*istanbul ignore start*/exports. /*istanbul ignore end*/createTwoFilesPatch = _create.createTwoFilesPatch; +/*istanbul ignore start*/exports. /*istanbul ignore end*/createPatch = _create.createPatch; +/*istanbul ignore start*/exports. /*istanbul ignore end*/applyPatch = _apply.applyPatch; +/*istanbul ignore start*/exports. /*istanbul ignore end*/applyPatches = _apply.applyPatches; +/*istanbul ignore start*/exports. /*istanbul ignore end*/parsePatch = _parse.parsePatch; +/*istanbul ignore start*/exports. /*istanbul ignore end*/convertChangesToDMP = _dmp.convertChangesToDMP; +/*istanbul ignore start*/exports. /*istanbul ignore end*/convertChangesToXML = _xml.convertChangesToXML; +/*istanbul ignore start*/exports. /*istanbul ignore end*/canonicalize = _json.canonicalize; /* See LICENSE file for terms of use */ + +/* + * Text diff implementation. + * + * This library supports the following APIS: + * JsDiff.diffChars: Character by character diff + * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace + * JsDiff.diffLines: Line based diff + * + * JsDiff.diffCss: Diff targeted at CSS content + * + * These methods are based on the implementation proposed in + * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986). + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927 + */ + + +},{"./convert/dmp":46,"./convert/xml":47,"./diff/array":48,"./diff/base":49,"./diff/character":50,"./diff/css":51,"./diff/json":52,"./diff/line":53,"./diff/sentence":54,"./diff/word":55,"./patch/apply":57,"./patch/create":58,"./patch/parse":59}],57:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; + +exports.__esModule = true; +exports. /*istanbul ignore end*/applyPatch = applyPatch; +/*istanbul ignore start*/exports. /*istanbul ignore end*/applyPatches = applyPatches; + +var /*istanbul ignore start*/_parse = require('./parse') /*istanbul ignore end*/; + +var /*istanbul ignore start*/_distanceIterator = require('../util/distance-iterator') /*istanbul ignore end*/; + +/*istanbul ignore start*/ +var _distanceIterator2 = _interopRequireDefault(_distanceIterator); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +/*istanbul ignore end*/function applyPatch(source, uniDiff) { + /*istanbul ignore start*/var /*istanbul ignore end*/options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + + if (typeof uniDiff === 'string') { + uniDiff = /*istanbul ignore start*/(0, _parse.parsePatch) /*istanbul ignore end*/(uniDiff); + } + + if (Array.isArray(uniDiff)) { + if (uniDiff.length > 1) { + throw new Error('applyPatch only works with a single input.'); + } + + uniDiff = uniDiff[0]; + } + + // Apply the diff to the input + var lines = source.split(/\r\n|[\n\v\f\r\x85]/), + delimiters = source.match(/\r\n|[\n\v\f\r\x85]/g) || [], + hunks = uniDiff.hunks, + compareLine = options.compareLine || function (lineNumber, line, operation, patchContent) /*istanbul ignore start*/{ + return (/*istanbul ignore end*/line === patchContent + ); + }, + errorCount = 0, + fuzzFactor = options.fuzzFactor || 0, + minLine = 0, + offset = 0, + removeEOFNL = /*istanbul ignore start*/void 0 /*istanbul ignore end*/, + addEOFNL = /*istanbul ignore start*/void 0 /*istanbul ignore end*/; + + /** + * Checks if the hunk exactly fits on the provided location + */ + function hunkFits(hunk, toPos) { + for (var j = 0; j < hunk.lines.length; j++) { + var line = hunk.lines[j], + operation = line[0], + content = line.substr(1); + + if (operation === ' ' || operation === '-') { + // Context sanity check + if (!compareLine(toPos + 1, lines[toPos], operation, content)) { + errorCount++; + + if (errorCount > fuzzFactor) { + return false; + } + } + toPos++; + } + } + + return true; + } + + // Search best fit offsets for each hunk based on the previous ones + for (var i = 0; i < hunks.length; i++) { + var hunk = hunks[i], + maxLine = lines.length - hunk.oldLines, + localOffset = 0, + toPos = offset + hunk.oldStart - 1; + + var iterator = /*istanbul ignore start*/(0, _distanceIterator2['default']) /*istanbul ignore end*/(toPos, minLine, maxLine); + + for (; localOffset !== undefined; localOffset = iterator()) { + if (hunkFits(hunk, toPos + localOffset)) { + hunk.offset = offset += localOffset; + break; + } + } + + if (localOffset === undefined) { + return false; + } + + // Set lower text limit to end of the current hunk, so next ones don't try + // to fit over already patched text + minLine = hunk.offset + hunk.oldStart + hunk.oldLines; + } + + // Apply patch hunks + for (var _i = 0; _i < hunks.length; _i++) { + var _hunk = hunks[_i], + _toPos = _hunk.offset + _hunk.newStart - 1; + if (_hunk.newLines == 0) { + _toPos++; + } + + for (var j = 0; j < _hunk.lines.length; j++) { + var line = _hunk.lines[j], + operation = line[0], + content = line.substr(1), + delimiter = _hunk.linedelimiters[j]; + + if (operation === ' ') { + _toPos++; + } else if (operation === '-') { + lines.splice(_toPos, 1); + delimiters.splice(_toPos, 1); + /* istanbul ignore else */ + } else if (operation === '+') { + lines.splice(_toPos, 0, content); + delimiters.splice(_toPos, 0, delimiter); + _toPos++; + } else if (operation === '\\') { + var previousOperation = _hunk.lines[j - 1] ? _hunk.lines[j - 1][0] : null; + if (previousOperation === '+') { + removeEOFNL = true; + } else if (previousOperation === '-') { + addEOFNL = true; + } + } + } + } + + // Handle EOFNL insertion/removal + if (removeEOFNL) { + while (!lines[lines.length - 1]) { + lines.pop(); + delimiters.pop(); + } + } else if (addEOFNL) { + lines.push(''); + delimiters.push('\n'); + } + for (var _k = 0; _k < lines.length - 1; _k++) { + lines[_k] = lines[_k] + delimiters[_k]; + } + return lines.join(''); +} + +// Wrapper that supports multiple file patches via callbacks. +function applyPatches(uniDiff, options) { + if (typeof uniDiff === 'string') { + uniDiff = /*istanbul ignore start*/(0, _parse.parsePatch) /*istanbul ignore end*/(uniDiff); + } + + var currentIndex = 0; + function processIndex() { + var index = uniDiff[currentIndex++]; + if (!index) { + return options.complete(); + } + + options.loadFile(index, function (err, data) { + if (err) { + return options.complete(err); + } + + var updatedContent = applyPatch(data, index, options); + options.patched(index, updatedContent, function (err) { + if (err) { + return options.complete(err); + } + + processIndex(); + }); + }); + } + processIndex(); +} + + +},{"../util/distance-iterator":60,"./parse":59}],58:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; + +exports.__esModule = true; +exports. /*istanbul ignore end*/structuredPatch = structuredPatch; +/*istanbul ignore start*/exports. /*istanbul ignore end*/createTwoFilesPatch = createTwoFilesPatch; +/*istanbul ignore start*/exports. /*istanbul ignore end*/createPatch = createPatch; + +var /*istanbul ignore start*/_line = require('../diff/line') /*istanbul ignore end*/; + +/*istanbul ignore start*/ +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +/*istanbul ignore end*/function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { + if (!options) { + options = {}; + } + if (typeof options.context === 'undefined') { + options.context = 4; + } + + var diff = /*istanbul ignore start*/(0, _line.diffLines) /*istanbul ignore end*/(oldStr, newStr, options); + diff.push({ value: '', lines: [] }); // Append an empty value to make cleanup easier + + function contextLines(lines) { + return lines.map(function (entry) { + return ' ' + entry; + }); + } + + var hunks = []; + var oldRangeStart = 0, + newRangeStart = 0, + curRange = [], + oldLine = 1, + newLine = 1; + /*istanbul ignore start*/ + var _loop = function _loop( /*istanbul ignore end*/i) { + var current = diff[i], + lines = current.lines || current.value.replace(/\n$/, '').split('\n'); + current.lines = lines; + + if (current.added || current.removed) { + /*istanbul ignore start*/ + var _curRange; + + /*istanbul ignore end*/ + // If we have previous context, start with that + if (!oldRangeStart) { + var prev = diff[i - 1]; + oldRangeStart = oldLine; + newRangeStart = newLine; + + if (prev) { + curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : []; + oldRangeStart -= curRange.length; + newRangeStart -= curRange.length; + } + } + + // Output our changes + /*istanbul ignore start*/(_curRange = /*istanbul ignore end*/curRange).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_curRange /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/lines.map(function (entry) { + return (current.added ? '+' : '-') + entry; + }))); + + // Track the updated file position + if (current.added) { + newLine += lines.length; + } else { + oldLine += lines.length; + } + } else { + // Identical context lines. Track line changes + if (oldRangeStart) { + // Close out any changes that have been output (or join overlapping) + if (lines.length <= options.context * 2 && i < diff.length - 2) { + /*istanbul ignore start*/ + var _curRange2; + + /*istanbul ignore end*/ + // Overlapping + /*istanbul ignore start*/(_curRange2 = /*istanbul ignore end*/curRange).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_curRange2 /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/contextLines(lines))); + } else { + /*istanbul ignore start*/ + var _curRange3; + + /*istanbul ignore end*/ + // end the range and output + var contextSize = Math.min(lines.length, options.context); + /*istanbul ignore start*/(_curRange3 = /*istanbul ignore end*/curRange).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_curRange3 /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/contextLines(lines.slice(0, contextSize)))); + + var hunk = { + oldStart: oldRangeStart, + oldLines: oldLine - oldRangeStart + contextSize, + newStart: newRangeStart, + newLines: newLine - newRangeStart + contextSize, + lines: curRange + }; + if (i >= diff.length - 2 && lines.length <= options.context) { + // EOF is inside this hunk + var oldEOFNewline = /\n$/.test(oldStr); + var newEOFNewline = /\n$/.test(newStr); + if (lines.length == 0 && !oldEOFNewline) { + // special case: old has no eol and no trailing context; no-nl can end up before adds + curRange.splice(hunk.oldLines, 0, '\\ No newline at end of file'); + } else if (!oldEOFNewline || !newEOFNewline) { + curRange.push('\\ No newline at end of file'); + } + } + hunks.push(hunk); + + oldRangeStart = 0; + newRangeStart = 0; + curRange = []; + } + } + oldLine += lines.length; + newLine += lines.length; + } + }; + + for (var i = 0; i < diff.length; i++) { + /*istanbul ignore start*/ + _loop( /*istanbul ignore end*/i); + } + + return { + oldFileName: oldFileName, newFileName: newFileName, + oldHeader: oldHeader, newHeader: newHeader, + hunks: hunks + }; +} + +function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { + var diff = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options); + + var ret = []; + if (oldFileName == newFileName) { + ret.push('Index: ' + oldFileName); + } + ret.push('==================================================================='); + ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader)); + ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader)); + + for (var i = 0; i < diff.hunks.length; i++) { + var hunk = diff.hunks[i]; + ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines + ' +' + hunk.newStart + ',' + hunk.newLines + ' @@'); + ret.push.apply(ret, hunk.lines); + } + + return ret.join('\n') + '\n'; +} + +function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) { + return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options); +} + + +},{"../diff/line":53}],59:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; + +exports.__esModule = true; +exports. /*istanbul ignore end*/parsePatch = parsePatch; +function parsePatch(uniDiff) { + /*istanbul ignore start*/var /*istanbul ignore end*/options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var diffstr = uniDiff.split(/\r\n|[\n\v\f\r\x85]/), + delimiters = uniDiff.match(/\r\n|[\n\v\f\r\x85]/g) || [], + list = [], + i = 0; + + function parseIndex() { + var index = {}; + list.push(index); + + // Parse diff metadata + while (i < diffstr.length) { + var line = diffstr[i]; + + // File header found, end parsing diff metadata + if (/^(\-\-\-|\+\+\+|@@)\s/.test(line)) { + break; + } + + // Diff index + var header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line); + if (header) { + index.index = header[1]; + } + + i++; + } + + // Parse file headers if they are defined. Unified diff requires them, but + // there's no technical issues to have an isolated hunk without file header + parseFileHeader(index); + parseFileHeader(index); + + // Parse hunks + index.hunks = []; + + while (i < diffstr.length) { + var _line = diffstr[i]; + + if (/^(Index:|diff|\-\-\-|\+\+\+)\s/.test(_line)) { + break; + } else if (/^@@/.test(_line)) { + index.hunks.push(parseHunk()); + } else if (_line && options.strict) { + // Ignore unexpected content unless in strict mode + throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(_line)); + } else { + i++; + } + } + } + + // Parses the --- and +++ headers, if none are found, no lines + // are consumed. + function parseFileHeader(index) { + var headerPattern = /^(---|\+\+\+)\s+([\S ]*)(?:\t(.*?)\s*)?$/; + var fileHeader = headerPattern.exec(diffstr[i]); + if (fileHeader) { + var keyPrefix = fileHeader[1] === '---' ? 'old' : 'new'; + index[keyPrefix + 'FileName'] = fileHeader[2]; + index[keyPrefix + 'Header'] = fileHeader[3]; + + i++; + } + } + + // Parses a hunk + // This assumes that we are at the start of a hunk. + function parseHunk() { + var chunkHeaderIndex = i, + chunkHeaderLine = diffstr[i++], + chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/); + + var hunk = { + oldStart: +chunkHeader[1], + oldLines: +chunkHeader[2] || 1, + newStart: +chunkHeader[3], + newLines: +chunkHeader[4] || 1, + lines: [], + linedelimiters: [] + }; + + var addCount = 0, + removeCount = 0; + for (; i < diffstr.length; i++) { + // Lines starting with '---' could be mistaken for the "remove line" operation + // But they could be the header for the next file. Therefore prune such cases out. + if (diffstr[i].indexOf('--- ') === 0 && i + 2 < diffstr.length && diffstr[i + 1].indexOf('+++ ') === 0 && diffstr[i + 2].indexOf('@@') === 0) { + break; + } + var operation = diffstr[i][0]; + + if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') { + hunk.lines.push(diffstr[i]); + hunk.linedelimiters.push(delimiters[i] || '\n'); + + if (operation === '+') { + addCount++; + } else if (operation === '-') { + removeCount++; + } else if (operation === ' ') { + addCount++; + removeCount++; + } + } else { + break; + } + } + + // Handle the empty block count case + if (!addCount && hunk.newLines === 1) { + hunk.newLines = 0; + } + if (!removeCount && hunk.oldLines === 1) { + hunk.oldLines = 0; + } + + // Perform optional sanity checking + if (options.strict) { + if (addCount !== hunk.newLines) { + throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1)); + } + if (removeCount !== hunk.oldLines) { + throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1)); + } + } + + return hunk; + } + + while (i < diffstr.length) { + parseIndex(); + } + + return list; +} + + +},{}],60:[function(require,module,exports){ +/*istanbul ignore start*/"use strict"; + +exports.__esModule = true; + +exports["default"] = /*istanbul ignore end*/function (start, minLine, maxLine) { + var wantForward = true, + backwardExhausted = false, + forwardExhausted = false, + localOffset = 1; + + return function iterator() { + if (wantForward && !forwardExhausted) { + if (backwardExhausted) { + localOffset++; + } else { + wantForward = false; + } + + // Check if trying to fit beyond text length, and if not, check it fits + // after offset location (or desired location on first iteration) + if (start + localOffset <= maxLine) { + return localOffset; + } + + forwardExhausted = true; + } + + if (!backwardExhausted) { + if (!forwardExhausted) { + wantForward = true; + } + + // Check if trying to fit before text beginning, and if not, check it fits + // before offset location + if (minLine <= start - localOffset) { + return -localOffset++; + } + + backwardExhausted = true; + return iterator(); + } + + // We tried to fit hunk before text beginning and beyond text lenght, then + // hunk can't fit on the text. Return undefined + }; +}; + + +},{}],61:[function(require,module,exports){ +/*istanbul ignore start*/'use strict'; + +exports.__esModule = true; +exports. /*istanbul ignore end*/generateOptions = generateOptions; +function generateOptions(options, defaults) { + if (typeof options === 'function') { + defaults.callback = options; + } else if (options) { + for (var name in options) { + /* istanbul ignore else */ + if (options.hasOwnProperty(name)) { + defaults[name] = options[name]; + } + } + } + return defaults; +} + + +},{}],62:[function(require,module,exports){ +'use strict'; + +var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; + +module.exports = function (str) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + + return str.replace(matchOperatorsRe, '\\$&'); +}; + +},{}],63:[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 @@ -9862,7 +10508,7 @@ function isUndefined(arg) { return arg === void 0; } -},{}],49:[function(require,module,exports){ +},{}],64:[function(require,module,exports){ (function (process){ // Growl - Copyright TJ Holowaychuk (MIT Licensed) @@ -10156,7 +10802,7 @@ function growl(msg, options, fn) { }; }).call(this,require('_process')) -},{"_process":67,"child_process":42,"fs":42,"os":65,"path":42}],50:[function(require,module,exports){ +},{"_process":82,"child_process":42,"fs":42,"os":80,"path":42}],65:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = nBytes * 8 - mLen - 1 @@ -10242,7 +10888,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],51:[function(require,module,exports){ +},{}],66:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { @@ -10267,7 +10913,7 @@ if (typeof Object.create === 'function') { } } -},{}],52:[function(require,module,exports){ +},{}],67:[function(require,module,exports){ /*! * Determine if an object is a Buffer * @@ -10290,14 +10936,14 @@ function isSlowBuffer (obj) { return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) } -},{}],53:[function(require,module,exports){ +},{}],68:[function(require,module,exports){ var toString = {}.toString; module.exports = Array.isArray || function (arr) { return toString.call(arr) == '[object Array]'; }; -},{}],54:[function(require,module,exports){ +},{}],69:[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 () { @@ -11203,7 +11849,7 @@ module.exports = Array.isArray || function (arr) { }).call(this); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],55:[function(require,module,exports){ +},{}],70:[function(require,module,exports){ /** * lodash 3.2.0 (Custom Build) * Build: `lodash modern modularize exports="npm" -o ./` @@ -11232,7 +11878,7 @@ function baseAssign(object, source) { module.exports = baseAssign; -},{"lodash._basecopy":56,"lodash.keys":63}],56:[function(require,module,exports){ +},{"lodash._basecopy":71,"lodash.keys":78}],71:[function(require,module,exports){ /** * lodash 3.0.1 (Custom Build) * Build: `lodash modern modularize exports="npm" -o ./` @@ -11266,7 +11912,7 @@ function baseCopy(source, props, object) { module.exports = baseCopy; -},{}],57:[function(require,module,exports){ +},{}],72:[function(require,module,exports){ /** * lodash 3.0.3 (Custom Build) * Build: `lodash modern modularize exports="npm" -o ./` @@ -11325,7 +11971,7 @@ function isObject(value) { module.exports = baseCreate; -},{}],58:[function(require,module,exports){ +},{}],73:[function(require,module,exports){ /** * lodash 3.9.1 (Custom Build) * Build: `lodash modern modularize exports="npm" -o ./` @@ -11464,7 +12110,7 @@ function isNative(value) { module.exports = getNative; -},{}],59:[function(require,module,exports){ +},{}],74:[function(require,module,exports){ /** * lodash 3.0.9 (Custom Build) * Build: `lodash modern modularize exports="npm" -o ./` @@ -11598,7 +12244,7 @@ function isObject(value) { module.exports = isIterateeCall; -},{}],60:[function(require,module,exports){ +},{}],75:[function(require,module,exports){ /** * lodash 3.1.1 (Custom Build) * Build: `lodash modern modularize exports="npm" -o ./` @@ -11655,7 +12301,7 @@ function create(prototype, properties, guard) { module.exports = create; -},{"lodash._baseassign":55,"lodash._basecreate":57,"lodash._isiterateecall":59}],61:[function(require,module,exports){ +},{"lodash._baseassign":70,"lodash._basecreate":72,"lodash._isiterateecall":74}],76:[function(require,module,exports){ /** * lodash (Custom Build) * Build: `lodash modularize exports="npm" -o ./` @@ -11886,7 +12532,7 @@ function isObjectLike(value) { module.exports = isArguments; -},{}],62:[function(require,module,exports){ +},{}],77:[function(require,module,exports){ /** * lodash 3.0.4 (Custom Build) * Build: `lodash modern modularize exports="npm" -o ./` @@ -12068,7 +12714,7 @@ function isNative(value) { module.exports = isArray; -},{}],63:[function(require,module,exports){ +},{}],78:[function(require,module,exports){ /** * lodash 3.1.2 (Custom Build) * Build: `lodash modern modularize exports="npm" -o ./` @@ -12306,7 +12952,7 @@ function keysIn(object) { module.exports = keys; -},{"lodash._getnative":58,"lodash.isarguments":61,"lodash.isarray":62}],64:[function(require,module,exports){ +},{"lodash._getnative":73,"lodash.isarguments":76,"lodash.isarray":77}],79:[function(require,module,exports){ (function (process){ var path = require('path'); var fs = require('fs'); @@ -12408,7 +13054,7 @@ mkdirP.sync = function sync (p, opts, made) { }; }).call(this,require('_process')) -},{"_process":67,"fs":42,"path":42}],65:[function(require,module,exports){ +},{"_process":82,"fs":42,"path":42}],80:[function(require,module,exports){ exports.endianness = function () { return 'LE' }; exports.hostname = function () { @@ -12455,7 +13101,7 @@ exports.tmpdir = exports.tmpDir = function () { exports.EOL = '\n'; -},{}],66:[function(require,module,exports){ +},{}],81:[function(require,module,exports){ (function (process){ 'use strict'; @@ -12502,7 +13148,7 @@ function nextTick(fn, arg1, arg2, arg3) { } }).call(this,require('_process')) -},{"_process":67}],67:[function(require,module,exports){ +},{"_process":82}],82:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -12673,6 +13319,10 @@ process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } process.binding = function (name) { throw new Error('process.binding is not supported'); @@ -12684,10 +13334,10 @@ process.chdir = function (dir) { }; process.umask = function() { return 0; }; -},{}],68:[function(require,module,exports){ -module.exports = require("./lib/_stream_duplex.js") +},{}],83:[function(require,module,exports){ +module.exports = require('./lib/_stream_duplex.js'); -},{"./lib/_stream_duplex.js":69}],69:[function(require,module,exports){ +},{"./lib/_stream_duplex.js":84}],84:[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 @@ -12763,7 +13413,7 @@ function forEach(xs, f) { f(xs[i], i); } } -},{"./_stream_readable":71,"./_stream_writable":73,"core-util-is":45,"inherits":51,"process-nextick-args":66}],70:[function(require,module,exports){ +},{"./_stream_readable":86,"./_stream_writable":88,"core-util-is":45,"inherits":66,"process-nextick-args":81}],85:[function(require,module,exports){ // a passthrough stream. // basically just the most minimal sort of Transform stream. // Every written chunk gets output as-is. @@ -12790,7 +13440,7 @@ function PassThrough(options) { PassThrough.prototype._transform = function (chunk, encoding, cb) { cb(null, chunk); }; -},{"./_stream_transform":72,"core-util-is":45,"inherits":51}],71:[function(require,module,exports){ +},{"./_stream_transform":87,"core-util-is":45,"inherits":66}],86:[function(require,module,exports){ (function (process){ 'use strict'; @@ -12804,6 +13454,10 @@ var processNextTick = require('process-nextick-args'); var isArray = require('isarray'); /**/ +/**/ +var Duplex; +/**/ + Readable.ReadableState = ReadableState; /**/ @@ -12815,14 +13469,7 @@ var EElistenerCount = function (emitter, type) { /**/ /**/ -var Stream; -(function () { - try { - Stream = require('st' + 'ream'); - } catch (_) {} finally { - if (!Stream) Stream = require('events').EventEmitter; - } -})(); +var Stream = require('./internal/streams/stream'); /**/ var Buffer = require('buffer').Buffer; @@ -12850,7 +13497,11 @@ var StringDecoder; util.inherits(Readable, Stream); +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. if (typeof emitter.prependListener === 'function') { return emitter.prependListener(event, fn); } else { @@ -12862,7 +13513,6 @@ function prependListener(emitter, event, fn) { } } -var Duplex; function ReadableState(options, stream) { Duplex = Duplex || require('./_stream_duplex'); @@ -12881,7 +13531,7 @@ function ReadableState(options, stream) { this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; // cast to ints. - this.highWaterMark = ~ ~this.highWaterMark; + this.highWaterMark = ~~this.highWaterMark; // A linked list is used to store data chunks instead of an array because the // linked list can remove elements from the beginning faster than @@ -12932,7 +13582,6 @@ function ReadableState(options, stream) { } } -var Duplex; function Readable(options) { Duplex = Duplex || require('./_stream_duplex'); @@ -13255,7 +13904,7 @@ function maybeReadMore_(stream, state) { // for virtual (non-string, non-buffer) streams, "length" is somewhat // arbitrary, and perhaps not very meaningful. Readable.prototype._read = function (n) { - this.emit('error', new Error('not implemented')); + this.emit('error', new Error('_read() is not implemented')); }; Readable.prototype.pipe = function (dest, pipeOpts) { @@ -13433,16 +14082,16 @@ Readable.prototype.unpipe = function (dest) { state.pipesCount = 0; state.flowing = false; - for (var _i = 0; _i < len; _i++) { - dests[_i].emit('unpipe', this); + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this); }return this; } // try to find the right one. - var i = indexOf(state.pipes, dest); - if (i === -1) return this; + var index = indexOf(state.pipes, dest); + if (index === -1) return this; - state.pipes.splice(i, 1); + state.pipes.splice(index, 1); state.pipesCount -= 1; if (state.pipesCount === 1) state.pipes = state.pipes[0]; @@ -13574,10 +14223,9 @@ Readable.prototype.wrap = function (stream) { } // proxy certain important events. - var events = ['error', 'close', 'destroy', 'pause', 'resume']; - forEach(events, function (ev) { - stream.on(ev, self.emit.bind(self, ev)); - }); + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], self.emit.bind(self, kProxyEvents[n])); + } // when we try to consume some more bytes, simply unpause the // underlying stream. @@ -13730,7 +14378,7 @@ function indexOf(xs, x) { return -1; } }).call(this,require('_process')) -},{"./_stream_duplex":69,"./internal/streams/BufferList":74,"_process":67,"buffer":44,"buffer-shims":43,"core-util-is":45,"events":48,"inherits":51,"isarray":53,"process-nextick-args":66,"string_decoder/":80,"util":40}],72:[function(require,module,exports){ +},{"./_stream_duplex":84,"./internal/streams/BufferList":89,"./internal/streams/stream":90,"_process":82,"buffer":44,"buffer-shims":43,"core-util-is":45,"events":63,"inherits":66,"isarray":68,"process-nextick-args":81,"string_decoder/":96,"util":40}],87:[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 @@ -13827,7 +14475,6 @@ function Transform(options) { this._transformState = new TransformState(this); - // when the writable side finishes, then flush out anything remaining. var stream = this; // start out asking for a readable event once data is transformed. @@ -13844,9 +14491,10 @@ function Transform(options) { if (typeof options.flush === 'function') this._flush = options.flush; } + // When the writable side finishes, then flush out anything remaining. this.once('prefinish', function () { - if (typeof this._flush === 'function') this._flush(function (er) { - done(stream, er); + if (typeof this._flush === 'function') this._flush(function (er, data) { + done(stream, er, data); });else done(stream); }); } @@ -13867,7 +14515,7 @@ Transform.prototype.push = function (chunk, encoding) { // an error, then that'll put the hurt on the whole operation. If you // never call cb(), then you'll never get another chunk. Transform.prototype._transform = function (chunk, encoding, cb) { - throw new Error('Not implemented'); + throw new Error('_transform() is not implemented'); }; Transform.prototype._write = function (chunk, encoding, cb) { @@ -13897,9 +14545,11 @@ Transform.prototype._read = function (n) { } }; -function done(stream, er) { +function done(stream, er, data) { if (er) return stream.emit('error', er); + if (data !== null && data !== undefined) stream.push(data); + // if there's nothing in the write buffer, then that means // that nothing more will ever be provided var ws = stream._writableState; @@ -13911,7 +14561,7 @@ function done(stream, er) { return stream.push(null); } -},{"./_stream_duplex":69,"core-util-is":45,"inherits":51}],73:[function(require,module,exports){ +},{"./_stream_duplex":84,"core-util-is":45,"inherits":66}],88:[function(require,module,exports){ (function (process){ // A bit simpler than readable streams. // Implement an async ._write(chunk, encoding, cb), and it'll handle all @@ -13929,6 +14579,10 @@ var processNextTick = require('process-nextick-args'); var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick; /**/ +/**/ +var Duplex; +/**/ + Writable.WritableState = WritableState; /**/ @@ -13943,14 +14597,7 @@ var internalUtil = { /**/ /**/ -var Stream; -(function () { - try { - Stream = require('st' + 'ream'); - } catch (_) {} finally { - if (!Stream) Stream = require('events').EventEmitter; - } -})(); +var Stream = require('./internal/streams/stream'); /**/ var Buffer = require('buffer').Buffer; @@ -13969,7 +14616,6 @@ function WriteReq(chunk, encoding, cb) { this.next = null; } -var Duplex; function WritableState(options, stream) { Duplex = Duplex || require('./_stream_duplex'); @@ -13989,8 +14635,9 @@ function WritableState(options, stream) { this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; // cast to ints. - this.highWaterMark = ~ ~this.highWaterMark; + this.highWaterMark = ~~this.highWaterMark; + // drain event flag. this.needDrain = false; // at the start of calling end() this.ending = false; @@ -14065,7 +14712,7 @@ function WritableState(options, stream) { this.corkedRequestsFree = new CorkedRequest(this); } -WritableState.prototype.getBuffer = function writableStateGetBuffer() { +WritableState.prototype.getBuffer = function getBuffer() { var current = this.bufferedRequest; var out = []; while (current) { @@ -14085,13 +14732,37 @@ WritableState.prototype.getBuffer = function writableStateGetBuffer() { } catch (_) {} })(); -var Duplex; +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function (object) { + if (realHasInstance.call(this, object)) return true; + + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function (object) { + return object instanceof this; + }; +} + function Writable(options) { Duplex = Duplex || require('./_stream_duplex'); - // Writable ctor is applied to Duplexes, though they're not - // instanceof Writable, they're instanceof Readable. - if (!(this instanceof Writable) && !(this instanceof Duplex)) return new Writable(options); + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { + return new Writable(options); + } this._writableState = new WritableState(options, this); @@ -14119,20 +14790,16 @@ function writeAfterEnd(stream, cb) { processNextTick(cb, er); } -// If we get something that is not a buffer, string, null, or undefined, -// and we're not in objectMode, then that's an error. -// Otherwise stream chunks are all considered to be of length=1, and the -// watermarks determine how many objects to keep in the buffer, rather than -// how many bytes or characters. +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. function validChunk(stream, state, chunk, cb) { var valid = true; var er = false; - // Always throw error if a null is written - // if we are not in object mode then throw - // if it is not a buffer, string, or undefined. + if (chunk === null) { er = new TypeError('May not write null values to stream'); - } else if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { er = new TypeError('Invalid non-string/buffer chunk'); } if (er) { @@ -14146,19 +14813,20 @@ function validChunk(stream, state, chunk, cb) { Writable.prototype.write = function (chunk, encoding, cb) { var state = this._writableState; var ret = false; + var isBuf = Buffer.isBuffer(chunk); if (typeof encoding === 'function') { cb = encoding; encoding = null; } - if (Buffer.isBuffer(chunk)) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; if (typeof cb !== 'function') cb = nop; - if (state.ended) writeAfterEnd(this, cb);else if (validChunk(this, state, chunk, cb)) { + if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { state.pendingcb++; - ret = writeOrBuffer(this, state, chunk, encoding, cb); + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); } return ret; @@ -14198,10 +14866,11 @@ function decodeChunk(state, chunk, encoding) { // if we're already writing something, then just put this // in the queue, and wait our turn. Otherwise, call _write // If we return false, then we need a drain event, so set that flag. -function writeOrBuffer(stream, state, chunk, encoding, cb) { - chunk = decodeChunk(state, chunk, encoding); - - if (Buffer.isBuffer(chunk)) encoding = 'buffer'; +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + chunk = decodeChunk(state, chunk, encoding); + if (Buffer.isBuffer(chunk)) encoding = 'buffer'; + } var len = state.objectMode ? 1 : chunk.length; state.length += len; @@ -14270,8 +14939,8 @@ function onwrite(stream, er) { asyncWrite(afterWrite, stream, state, finished, cb); /**/ } else { - afterWrite(stream, state, finished, cb); - } + afterWrite(stream, state, finished, cb); + } } } @@ -14351,7 +15020,7 @@ function clearBuffer(stream, state) { } Writable.prototype._write = function (chunk, encoding, cb) { - cb(new Error('not implemented')); + cb(new Error('_write() is not implemented')); }; Writable.prototype._writev = null; @@ -14422,7 +15091,6 @@ function CorkedRequest(state) { this.next = null; this.entry = null; - this.finish = function (err) { var entry = _this.entry; _this.entry = null; @@ -14440,7 +15108,7 @@ function CorkedRequest(state) { }; } }).call(this,require('_process')) -},{"./_stream_duplex":69,"_process":67,"buffer":44,"buffer-shims":43,"core-util-is":45,"events":48,"inherits":51,"process-nextick-args":66,"util-deprecate":81}],74:[function(require,module,exports){ +},{"./_stream_duplex":84,"./internal/streams/stream":90,"_process":82,"buffer":44,"buffer-shims":43,"core-util-is":45,"inherits":66,"process-nextick-args":81,"util-deprecate":97}],89:[function(require,module,exports){ 'use strict'; var Buffer = require('buffer').Buffer; @@ -14505,36 +15173,28 @@ BufferList.prototype.concat = function (n) { } return ret; }; -},{"buffer":44,"buffer-shims":43}],75:[function(require,module,exports){ -module.exports = require("./lib/_stream_passthrough.js") +},{"buffer":44,"buffer-shims":43}],90:[function(require,module,exports){ +module.exports = require('events').EventEmitter; -},{"./lib/_stream_passthrough.js":70}],76:[function(require,module,exports){ -(function (process){ -var Stream = (function (){ - try { - return require('st' + 'ream'); // hack to fix a circular dependency issue when used with browserify - } catch(_){} -}()); +},{"events":63}],91:[function(require,module,exports){ +module.exports = require('./readable').PassThrough + +},{"./readable":92}],92:[function(require,module,exports){ exports = module.exports = require('./lib/_stream_readable.js'); -exports.Stream = Stream || exports; +exports.Stream = exports; exports.Readable = exports; exports.Writable = require('./lib/_stream_writable.js'); exports.Duplex = require('./lib/_stream_duplex.js'); exports.Transform = require('./lib/_stream_transform.js'); exports.PassThrough = require('./lib/_stream_passthrough.js'); -if (!process.browser && process.env.READABLE_STREAM === 'disable' && Stream) { - module.exports = Stream; -} +},{"./lib/_stream_duplex.js":84,"./lib/_stream_passthrough.js":85,"./lib/_stream_readable.js":86,"./lib/_stream_transform.js":87,"./lib/_stream_writable.js":88}],93:[function(require,module,exports){ +module.exports = require('./readable').Transform -}).call(this,require('_process')) -},{"./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}],77:[function(require,module,exports){ -module.exports = require("./lib/_stream_transform.js") +},{"./readable":92}],94:[function(require,module,exports){ +module.exports = require('./lib/_stream_writable.js'); -},{"./lib/_stream_transform.js":72}],78:[function(require,module,exports){ -module.exports = require("./lib/_stream_writable.js") - -},{"./lib/_stream_writable.js":73}],79:[function(require,module,exports){ +},{"./lib/_stream_writable.js":88}],95:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -14663,230 +15323,281 @@ Stream.prototype.pipe = function(dest, options) { return dest; }; -},{"events":48,"inherits":51,"readable-stream/duplex.js":68,"readable-stream/passthrough.js":75,"readable-stream/readable.js":76,"readable-stream/transform.js":77,"readable-stream/writable.js":78}],80:[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. +},{"events":63,"inherits":66,"readable-stream/duplex.js":83,"readable-stream/passthrough.js":91,"readable-stream/readable.js":92,"readable-stream/transform.js":93,"readable-stream/writable.js":94}],96:[function(require,module,exports){ +'use strict'; var Buffer = require('buffer').Buffer; +var bufferShim = require('buffer-shims'); -var isBufferEncoding = Buffer.isEncoding - || function(encoding) { - switch (encoding && encoding.toLowerCase()) { - case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; - default: return false; - } - } - +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; -function assertEncoding(encoding) { - if (encoding && !isBufferEncoding(encoding)) { - throw new Error('Unknown encoding: ' + encoding); +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; } // StringDecoder provides an interface for efficiently splitting a series of // buffers into a series of JS strings without breaking apart multi-byte -// characters. CESU-8 is handled as part of the UTF-8 encoding. -// -// @TODO Handling all encodings inside a single object makes it very difficult -// to reason about this code, so it should be split up in the future. -// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code -// points as used by CESU-8. -var StringDecoder = exports.StringDecoder = function(encoding) { - this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); - assertEncoding(encoding); +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; switch (this.encoding) { - case 'utf8': - // CESU-8 represents each of Surrogate Pair by 3-bytes - this.surrogateSize = 3; - break; - case 'ucs2': case 'utf16le': - // UTF-16 represents each of Surrogate Pair by 2-bytes - this.surrogateSize = 2; - this.detectIncompleteChar = utf16DetectIncompleteChar; + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; break; case 'base64': - // Base-64 stores 3 bytes in 4 chars, and pads the remainder. - this.surrogateSize = 3; - this.detectIncompleteChar = base64DetectIncompleteChar; + this.text = base64Text; + this.end = base64End; + nb = 3; break; default: - this.write = passThroughWrite; + this.write = simpleWrite; + this.end = simpleEnd; return; } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = bufferShim.allocUnsafe(nb); +} - // Enough space to store all bytes of a single character. UTF-8 needs 4 - // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). - this.charBuffer = new Buffer(6); - // Number of bytes received for the current incomplete multi-byte character. - this.charReceived = 0; - // Number of bytes expected for the current incomplete multi-byte character. - this.charLength = 0; +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; }; +StringDecoder.prototype.end = utf8End; -// write decodes the given buffer and returns it as JS string that is -// guaranteed to not contain any partial multi-byte characters. Any partial -// character found at the end of the buffer is buffered up, and will be -// returned when calling write again with the remaining bytes. -// -// Note: Converting a Buffer containing an orphan surrogate to a String -// currently works, but converting a String to a Buffer (via `new Buffer`, or -// Buffer#write) will replace incomplete surrogates with the unicode -// replacement character. See https://codereview.chromium.org/121173009/ . -StringDecoder.prototype.write = function(buffer) { - var charStr = ''; - // if our last write ended with an incomplete multibyte character - while (this.charLength) { - // determine how many remaining bytes this buffer has to offer for this char - var available = (buffer.length >= this.charLength - this.charReceived) ? - this.charLength - this.charReceived : - buffer.length; - - // add the new bytes to the char buffer - buffer.copy(this.charBuffer, this.charReceived, 0, available); - this.charReceived += available; - - if (this.charReceived < this.charLength) { - // still not enough chars in this buffer? wait for more ... - return ''; - } - - // remove bytes belonging to the current character from the buffer - buffer = buffer.slice(available, buffer.length); - - // get the character that was split - charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); - - // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character - var charCode = charStr.charCodeAt(charStr.length - 1); - if (charCode >= 0xD800 && charCode <= 0xDBFF) { - this.charLength += this.surrogateSize; - charStr = ''; - continue; - } - this.charReceived = this.charLength = 0; +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; - // if there are no more bytes in this buffer, just emit our char - if (buffer.length === 0) { - return charStr; - } - break; +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; - // determine and set charLength / charReceived - this.detectIncompleteChar(buffer); +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return -1; +} - var end = buffer.length; - if (this.charLength) { - // buffer the incomplete character bytes we got - buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); - end -= this.charReceived; +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; } - - charStr += buffer.toString(this.encoding, 0, end); - - var end = charStr.length - 1; - var charCode = charStr.charCodeAt(end); - // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character - if (charCode >= 0xD800 && charCode <= 0xDBFF) { - var size = this.surrogateSize; - this.charLength += size; - this.charReceived += size; - this.charBuffer.copy(this.charBuffer, size, 0, size); - buffer.copy(this.charBuffer, 0, 0, size); - return charStr.substring(0, end); + if (--j < i) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; } - - // or just emit the charStr - return charStr; -}; - -// detectIncompleteChar determines if there is an incomplete UTF-8 character at -// the end of the given buffer. If so, it sets this.charLength to the byte -// length that character, and sets this.charReceived to the number of bytes -// that are available for this character. -StringDecoder.prototype.detectIncompleteChar = function(buffer) { - // determine how many bytes we have to check at the end of this buffer - var i = (buffer.length >= 3) ? 3 : buffer.length; - - // Figure out if one of the last i bytes of our buffer announces an - // incomplete char. - for (; i > 0; i--) { - var c = buffer[buffer.length - i]; - - // See http://en.wikipedia.org/wiki/UTF-8#Description - - // 110XXXXX - if (i == 1 && c >> 5 == 0x06) { - this.charLength = 2; - break; + if (--j < i) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; } + return nb; + } + return 0; +} - // 1110XXXX - if (i <= 2 && c >> 4 == 0x0E) { - this.charLength = 3; - break; +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// UTF-8 replacement characters ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'.repeat(p); + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'.repeat(p + 1); + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'.repeat(p + 2); + } } + } +} - // 11110XXX - if (i <= 3 && c >> 3 == 0x1E) { - this.charLength = 4; - break; +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character for each buffered byte of a (partial) +// character needs to be added to the output. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'.repeat(this.lastTotal - this.lastNeed); + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } } + return r; } - this.charReceived = i; -}; - -StringDecoder.prototype.end = function(buffer) { - var res = ''; - if (buffer && buffer.length) - res = this.write(buffer); + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} - if (this.charReceived) { - var cr = this.charReceived; - var buf = this.charBuffer; - var enc = this.encoding; - res += buf.slice(0, cr).toString(enc); +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); } + return r; +} - return res; -}; - -function passThroughWrite(buffer) { - return buffer.toString(this.encoding); +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); } -function utf16DetectIncompleteChar(buffer) { - this.charReceived = buffer.length % 2; - this.charLength = this.charReceived ? 2 : 0; +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; } -function base64DetectIncompleteChar(buffer) { - this.charReceived = buffer.length % 3; - this.charLength = this.charReceived ? 3 : 0; +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); } -},{"buffer":44}],81:[function(require,module,exports){ +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} +},{"buffer":44,"buffer-shims":43}],97:[function(require,module,exports){ (function (global){ /** @@ -14957,16 +15668,16 @@ function config (name) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],82:[function(require,module,exports){ -arguments[4][51][0].apply(exports,arguments) -},{"dup":51}],83:[function(require,module,exports){ +},{}],98:[function(require,module,exports){ +arguments[4][66][0].apply(exports,arguments) +},{"dup":66}],99:[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'; } -},{}],84:[function(require,module,exports){ +},{}],100:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -15556,4 +16267,4 @@ function hasOwnProperty(obj, prop) { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":83,"_process":67,"inherits":82}]},{},[1]); +},{"./support/isBuffer":99,"_process":82,"inherits":98}]},{},[1]); diff --git a/package.json b/package.json index c0586eb591..a65cf2b733 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mocha", - "version": "3.3.0", + "version": "3.4.0", "description": "simple, flexible, fun test framework", "keywords": [ "mocha", From ac0c1c8382a50963425e00d306e4d158f6bfd9c3 Mon Sep 17 00:00:00 2001 From: ScottFreeCode Date: Sun, 14 May 2017 15:05:35 -0400 Subject: [PATCH 20/42] v3.4.1 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 851a830764..a7544a7254 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 3.4.1 / 2017-05-14 + +Fixed a publishing mishap with git's autocrlf settings. + # 3.4.0 / 2017-05-14 Mocha is now moving to a quicker release schedule: when non-breaking changes are merged, a release should happen that week. diff --git a/package.json b/package.json index a65cf2b733..f681ba3e16 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mocha", - "version": "3.4.0", + "version": "3.4.1", "description": "simple, flexible, fun test framework", "keywords": [ "mocha", From 17a177011d3cd398a171ac12c32ae3b95831f142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20M=C3=BCller?= Date: Mon, 15 May 2017 09:57:54 +0200 Subject: [PATCH 21/42] Move linting into an npm script. Relates to #2805 --- Makefile | 3 +-- package.json | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 33408bfbad..ad8b097e4e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ BROWSERIFY := "node_modules/.bin/browserify" -ESLINT := "node_modules/.bin/eslint" KARMA := "node_modules/.bin/karma" MOCHA := "bin/mocha" NYC := "node_modules/.bin/nyc" @@ -34,7 +33,7 @@ clean: lint: @printf "==> [Test :: Lint]\n" - $(ESLINT) . "bin/*" + npm run lint 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 diff --git a/package.json b/package.json index f681ba3e16..a02ab9e803 100644 --- a/package.json +++ b/package.json @@ -299,6 +299,7 @@ "npm": ">= 1.4.x" }, "scripts": { + "lint": "eslint . bin/*", "test": "make test && make clean", "precoverage": "rm -rf coverage", "coverage": "COVERAGE=true npm run test", From 3e7152f1bbcf0715d115a2281383c6d84fa47462 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 22 May 2017 21:40:51 +0200 Subject: [PATCH 22/42] Remove call to deprecated os.tmpDir (#2802) --- test/acceptance/file-utils.spec.js | 2 +- test/integration/reporters.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/acceptance/file-utils.spec.js b/test/acceptance/file-utils.spec.js index 12dbddf878..540589821d 100644 --- a/test/acceptance/file-utils.spec.js +++ b/test/acceptance/file-utils.spec.js @@ -8,7 +8,7 @@ var mkdirp = require('mkdirp'); var rimraf = require('rimraf'); describe('file utils', function () { - var tmpDir = path.join(os.tmpDir(), 'mocha-file-lookup'); + var tmpDir = path.join(os.tmpdir(), 'mocha-file-lookup'); var existsSync = fs.existsSync; var tmpFile = path.join.bind(path, tmpDir); var symlinkSupported = false; diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index 15b7e6533b..19b4d8e30c 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -36,7 +36,7 @@ describe('reporters', function () { describe('xunit', function () { it('prints test cases with --reporter-options output (issue: 1864)', function (done) { var randomStr = crypto.randomBytes(8).toString('hex'); - var tmpDir = os.tmpDir().replace(new RegExp(path.sep + '$'), ''); + var tmpDir = os.tmpdir().replace(new RegExp(path.sep + '$'), ''); var tmpFile = tmpDir + path.sep + 'test-issue-1864-' + randomStr + '.xml'; var args = ['--reporter=xunit', '--reporter-options', 'output=' + tmpFile]; From 10ff0ec56932e575d93066de0c602c4c854072db Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 24 May 2017 08:34:20 -0700 Subject: [PATCH 23/42] Eagerly set process.exitCode (#2820) To workaround process being terminated earlier than expected. Simpler version of PR #2714 which only eagerly sets the exitcode without playing with the draining semantics. --- bin/_mocha | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bin/_mocha b/bin/_mocha index 00514b5ce0..7f3d01aa1d 100755 --- a/bin/_mocha +++ b/bin/_mocha @@ -476,12 +476,18 @@ function exitLater (code) { } function exit (code) { + var clampedCode = Math.min(code, 255); + + // Eagerly set the process's exit code in case stream.write doesn't + // execute its callback before the process terminates. + process.exitCode = clampedCode; + // flush output for Node.js Windows pipe bug // https://github.com/joyent/node/issues/6247 is just one bug example // https://github.com/visionmedia/mocha/issues/333 has a good discussion function done () { if (!(draining--)) { - process.exit(Math.min(code, 255)); + process.exit(clampedCode); } } From fc802a9ea5665dada4ae9f30738a34f237036aa3 Mon Sep 17 00:00:00 2001 From: David da Silva Date: Wed, 24 May 2017 17:56:48 +0200 Subject: [PATCH 24/42] :memo: Add Changelog for v3.4.2 --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7544a7254..98d445b880 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +# 3.4.2 / 2017-05-24 + +## :bug: Fixes + +- [#2802]: Remove call to deprecated os.tmpDir ([@makepanic]) +- [#2820]: Eagerly set process.exitCode ([@chrisleck]) + +## :nut_and_bolt: Other + +- [#2778]: Move linting into an npm script ([@Munter]) + +[@chrisleck]: https://github.com/chrisleck +[@makepanic]: https://github.com/makepanic +[@Munter]: https://github.com/Munter + +[#2802]: https://github.com/mochajs/mocha/issues/2802 +[#2820]: https://github.com/mochajs/mocha/pull/2820 + # 3.4.1 / 2017-05-14 Fixed a publishing mishap with git's autocrlf settings. From a15b20aca567a2e57129bccae773e782796bfaa3 Mon Sep 17 00:00:00 2001 From: David da Silva Date: Wed, 24 May 2017 17:59:03 +0200 Subject: [PATCH 25/42] :ship: Release v3.4.2 --- mocha.js | 607 +++++++++++++++++++++++---------------------------- package.json | 2 +- 2 files changed, 272 insertions(+), 337 deletions(-) diff --git a/mocha.js b/mocha.js index 07bf7ac288..4e59d156cf 100644 --- a/mocha.js +++ b/mocha.js @@ -6775,7 +6775,7 @@ exports.isPromise = function isPromise (value) { exports.noop = function () {}; }).call(this,require('_process'),require("buffer").Buffer) -},{"./to-iso-string":37,"_process":82,"buffer":44,"debug":2,"fs":42,"glob":42,"json3":69,"path":42,"util":100}],39:[function(require,module,exports){ +},{"./to-iso-string":37,"_process":82,"buffer":44,"debug":2,"fs":42,"glob":42,"json3":69,"path":42,"util":99}],39:[function(require,module,exports){ 'use strict' exports.byteLength = byteLength @@ -6922,7 +6922,7 @@ BrowserStdout.prototype._write = function(chunks, encoding, cb) { } }).call(this,require('_process')) -},{"_process":82,"stream":95,"util":100}],42:[function(require,module,exports){ +},{"_process":82,"stream":94,"util":99}],42:[function(require,module,exports){ arguments[4][40][0].apply(exports,arguments) },{"dup":40}],43:[function(require,module,exports){ (function (global){ @@ -13319,10 +13319,6 @@ process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; - -process.listeners = function (name) { return [] } process.binding = function (name) { throw new Error('process.binding is not supported'); @@ -13335,7 +13331,7 @@ process.chdir = function (dir) { process.umask = function() { return 0; }; },{}],83:[function(require,module,exports){ -module.exports = require('./lib/_stream_duplex.js'); +module.exports = require("./lib/_stream_duplex.js") },{"./lib/_stream_duplex.js":84}],84:[function(require,module,exports){ // a duplex stream is just a stream that is both readable and writable. @@ -13454,10 +13450,6 @@ var processNextTick = require('process-nextick-args'); var isArray = require('isarray'); /**/ -/**/ -var Duplex; -/**/ - Readable.ReadableState = ReadableState; /**/ @@ -13469,7 +13461,14 @@ var EElistenerCount = function (emitter, type) { /**/ /**/ -var Stream = require('./internal/streams/stream'); +var Stream; +(function () { + try { + Stream = require('st' + 'ream'); + } catch (_) {} finally { + if (!Stream) Stream = require('events').EventEmitter; + } +})(); /**/ var Buffer = require('buffer').Buffer; @@ -13497,11 +13496,7 @@ var StringDecoder; util.inherits(Readable, Stream); -var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; - function prependListener(emitter, event, fn) { - // Sadly this is not cacheable as some libraries bundle their own - // event emitter implementation with them. if (typeof emitter.prependListener === 'function') { return emitter.prependListener(event, fn); } else { @@ -13513,6 +13508,7 @@ function prependListener(emitter, event, fn) { } } +var Duplex; function ReadableState(options, stream) { Duplex = Duplex || require('./_stream_duplex'); @@ -13531,7 +13527,7 @@ function ReadableState(options, stream) { this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; // cast to ints. - this.highWaterMark = ~~this.highWaterMark; + this.highWaterMark = ~ ~this.highWaterMark; // A linked list is used to store data chunks instead of an array because the // linked list can remove elements from the beginning faster than @@ -13582,6 +13578,7 @@ function ReadableState(options, stream) { } } +var Duplex; function Readable(options) { Duplex = Duplex || require('./_stream_duplex'); @@ -13904,7 +13901,7 @@ function maybeReadMore_(stream, state) { // for virtual (non-string, non-buffer) streams, "length" is somewhat // arbitrary, and perhaps not very meaningful. Readable.prototype._read = function (n) { - this.emit('error', new Error('_read() is not implemented')); + this.emit('error', new Error('not implemented')); }; Readable.prototype.pipe = function (dest, pipeOpts) { @@ -14082,16 +14079,16 @@ Readable.prototype.unpipe = function (dest) { state.pipesCount = 0; state.flowing = false; - for (var i = 0; i < len; i++) { - dests[i].emit('unpipe', this); + for (var _i = 0; _i < len; _i++) { + dests[_i].emit('unpipe', this); }return this; } // try to find the right one. - var index = indexOf(state.pipes, dest); - if (index === -1) return this; + var i = indexOf(state.pipes, dest); + if (i === -1) return this; - state.pipes.splice(index, 1); + state.pipes.splice(i, 1); state.pipesCount -= 1; if (state.pipesCount === 1) state.pipes = state.pipes[0]; @@ -14223,9 +14220,10 @@ Readable.prototype.wrap = function (stream) { } // proxy certain important events. - for (var n = 0; n < kProxyEvents.length; n++) { - stream.on(kProxyEvents[n], self.emit.bind(self, kProxyEvents[n])); - } + var events = ['error', 'close', 'destroy', 'pause', 'resume']; + forEach(events, function (ev) { + stream.on(ev, self.emit.bind(self, ev)); + }); // when we try to consume some more bytes, simply unpause the // underlying stream. @@ -14378,7 +14376,7 @@ function indexOf(xs, x) { return -1; } }).call(this,require('_process')) -},{"./_stream_duplex":84,"./internal/streams/BufferList":89,"./internal/streams/stream":90,"_process":82,"buffer":44,"buffer-shims":43,"core-util-is":45,"events":63,"inherits":66,"isarray":68,"process-nextick-args":81,"string_decoder/":96,"util":40}],87:[function(require,module,exports){ +},{"./_stream_duplex":84,"./internal/streams/BufferList":89,"_process":82,"buffer":44,"buffer-shims":43,"core-util-is":45,"events":63,"inherits":66,"isarray":68,"process-nextick-args":81,"string_decoder/":95,"util":40}],87:[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 @@ -14475,6 +14473,7 @@ function Transform(options) { this._transformState = new TransformState(this); + // when the writable side finishes, then flush out anything remaining. var stream = this; // start out asking for a readable event once data is transformed. @@ -14491,10 +14490,9 @@ function Transform(options) { if (typeof options.flush === 'function') this._flush = options.flush; } - // When the writable side finishes, then flush out anything remaining. this.once('prefinish', function () { - if (typeof this._flush === 'function') this._flush(function (er, data) { - done(stream, er, data); + if (typeof this._flush === 'function') this._flush(function (er) { + done(stream, er); });else done(stream); }); } @@ -14515,7 +14513,7 @@ Transform.prototype.push = function (chunk, encoding) { // an error, then that'll put the hurt on the whole operation. If you // never call cb(), then you'll never get another chunk. Transform.prototype._transform = function (chunk, encoding, cb) { - throw new Error('_transform() is not implemented'); + throw new Error('Not implemented'); }; Transform.prototype._write = function (chunk, encoding, cb) { @@ -14545,11 +14543,9 @@ Transform.prototype._read = function (n) { } }; -function done(stream, er, data) { +function done(stream, er) { if (er) return stream.emit('error', er); - if (data !== null && data !== undefined) stream.push(data); - // if there's nothing in the write buffer, then that means // that nothing more will ever be provided var ws = stream._writableState; @@ -14579,10 +14575,6 @@ var processNextTick = require('process-nextick-args'); var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick; /**/ -/**/ -var Duplex; -/**/ - Writable.WritableState = WritableState; /**/ @@ -14597,7 +14589,14 @@ var internalUtil = { /**/ /**/ -var Stream = require('./internal/streams/stream'); +var Stream; +(function () { + try { + Stream = require('st' + 'ream'); + } catch (_) {} finally { + if (!Stream) Stream = require('events').EventEmitter; + } +})(); /**/ var Buffer = require('buffer').Buffer; @@ -14616,6 +14615,7 @@ function WriteReq(chunk, encoding, cb) { this.next = null; } +var Duplex; function WritableState(options, stream) { Duplex = Duplex || require('./_stream_duplex'); @@ -14635,9 +14635,8 @@ function WritableState(options, stream) { this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; // cast to ints. - this.highWaterMark = ~~this.highWaterMark; + this.highWaterMark = ~ ~this.highWaterMark; - // drain event flag. this.needDrain = false; // at the start of calling end() this.ending = false; @@ -14712,7 +14711,7 @@ function WritableState(options, stream) { this.corkedRequestsFree = new CorkedRequest(this); } -WritableState.prototype.getBuffer = function getBuffer() { +WritableState.prototype.getBuffer = function writableStateGetBuffer() { var current = this.bufferedRequest; var out = []; while (current) { @@ -14732,37 +14731,13 @@ WritableState.prototype.getBuffer = function getBuffer() { } catch (_) {} })(); -// Test _writableState for inheritance to account for Duplex streams, -// whose prototype chain only points to Readable. -var realHasInstance; -if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { - realHasInstance = Function.prototype[Symbol.hasInstance]; - Object.defineProperty(Writable, Symbol.hasInstance, { - value: function (object) { - if (realHasInstance.call(this, object)) return true; - - return object && object._writableState instanceof WritableState; - } - }); -} else { - realHasInstance = function (object) { - return object instanceof this; - }; -} - +var Duplex; function Writable(options) { Duplex = Duplex || require('./_stream_duplex'); - // Writable ctor is applied to Duplexes, too. - // `realHasInstance` is necessary because using plain `instanceof` - // would return false, as no `_writableState` property is attached. - - // Trying to use the custom `instanceof` for Writable here will also break the - // Node.js LazyTransform implementation, which has a non-trivial getter for - // `_writableState` that would lead to infinite recursion. - if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { - return new Writable(options); - } + // Writable ctor is applied to Duplexes, though they're not + // instanceof Writable, they're instanceof Readable. + if (!(this instanceof Writable) && !(this instanceof Duplex)) return new Writable(options); this._writableState = new WritableState(options, this); @@ -14790,16 +14765,20 @@ function writeAfterEnd(stream, cb) { processNextTick(cb, er); } -// Checks that a user-supplied chunk is valid, especially for the particular -// mode the stream is in. Currently this means that `null` is never accepted -// and undefined/non-string values are only allowed in object mode. +// If we get something that is not a buffer, string, null, or undefined, +// and we're not in objectMode, then that's an error. +// Otherwise stream chunks are all considered to be of length=1, and the +// watermarks determine how many objects to keep in the buffer, rather than +// how many bytes or characters. function validChunk(stream, state, chunk, cb) { var valid = true; var er = false; - + // Always throw error if a null is written + // if we are not in object mode then throw + // if it is not a buffer, string, or undefined. if (chunk === null) { er = new TypeError('May not write null values to stream'); - } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + } else if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { er = new TypeError('Invalid non-string/buffer chunk'); } if (er) { @@ -14813,20 +14792,19 @@ function validChunk(stream, state, chunk, cb) { Writable.prototype.write = function (chunk, encoding, cb) { var state = this._writableState; var ret = false; - var isBuf = Buffer.isBuffer(chunk); if (typeof encoding === 'function') { cb = encoding; encoding = null; } - if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + if (Buffer.isBuffer(chunk)) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; if (typeof cb !== 'function') cb = nop; - if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + if (state.ended) writeAfterEnd(this, cb);else if (validChunk(this, state, chunk, cb)) { state.pendingcb++; - ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + ret = writeOrBuffer(this, state, chunk, encoding, cb); } return ret; @@ -14866,11 +14844,10 @@ function decodeChunk(state, chunk, encoding) { // if we're already writing something, then just put this // in the queue, and wait our turn. Otherwise, call _write // If we return false, then we need a drain event, so set that flag. -function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { - if (!isBuf) { - chunk = decodeChunk(state, chunk, encoding); - if (Buffer.isBuffer(chunk)) encoding = 'buffer'; - } +function writeOrBuffer(stream, state, chunk, encoding, cb) { + chunk = decodeChunk(state, chunk, encoding); + + if (Buffer.isBuffer(chunk)) encoding = 'buffer'; var len = state.objectMode ? 1 : chunk.length; state.length += len; @@ -14939,8 +14916,8 @@ function onwrite(stream, er) { asyncWrite(afterWrite, stream, state, finished, cb); /**/ } else { - afterWrite(stream, state, finished, cb); - } + afterWrite(stream, state, finished, cb); + } } } @@ -15020,7 +14997,7 @@ function clearBuffer(stream, state) { } Writable.prototype._write = function (chunk, encoding, cb) { - cb(new Error('_write() is not implemented')); + cb(new Error('not implemented')); }; Writable.prototype._writev = null; @@ -15091,6 +15068,7 @@ function CorkedRequest(state) { this.next = null; this.entry = null; + this.finish = function (err) { var entry = _this.entry; _this.entry = null; @@ -15108,7 +15086,7 @@ function CorkedRequest(state) { }; } }).call(this,require('_process')) -},{"./_stream_duplex":84,"./internal/streams/stream":90,"_process":82,"buffer":44,"buffer-shims":43,"core-util-is":45,"inherits":66,"process-nextick-args":81,"util-deprecate":97}],89:[function(require,module,exports){ +},{"./_stream_duplex":84,"_process":82,"buffer":44,"buffer-shims":43,"core-util-is":45,"events":63,"inherits":66,"process-nextick-args":81,"util-deprecate":96}],89:[function(require,module,exports){ 'use strict'; var Buffer = require('buffer').Buffer; @@ -15174,27 +15152,35 @@ BufferList.prototype.concat = function (n) { return ret; }; },{"buffer":44,"buffer-shims":43}],90:[function(require,module,exports){ -module.exports = require('events').EventEmitter; - -},{"events":63}],91:[function(require,module,exports){ -module.exports = require('./readable').PassThrough +module.exports = require("./lib/_stream_passthrough.js") -},{"./readable":92}],92:[function(require,module,exports){ +},{"./lib/_stream_passthrough.js":85}],91:[function(require,module,exports){ +(function (process){ +var Stream = (function (){ + try { + return require('st' + 'ream'); // hack to fix a circular dependency issue when used with browserify + } catch(_){} +}()); exports = module.exports = require('./lib/_stream_readable.js'); -exports.Stream = exports; +exports.Stream = Stream || exports; exports.Readable = exports; exports.Writable = require('./lib/_stream_writable.js'); exports.Duplex = require('./lib/_stream_duplex.js'); exports.Transform = require('./lib/_stream_transform.js'); exports.PassThrough = require('./lib/_stream_passthrough.js'); -},{"./lib/_stream_duplex.js":84,"./lib/_stream_passthrough.js":85,"./lib/_stream_readable.js":86,"./lib/_stream_transform.js":87,"./lib/_stream_writable.js":88}],93:[function(require,module,exports){ -module.exports = require('./readable').Transform +if (!process.browser && process.env.READABLE_STREAM === 'disable' && Stream) { + module.exports = Stream; +} + +}).call(this,require('_process')) +},{"./lib/_stream_duplex.js":84,"./lib/_stream_passthrough.js":85,"./lib/_stream_readable.js":86,"./lib/_stream_transform.js":87,"./lib/_stream_writable.js":88,"_process":82}],92:[function(require,module,exports){ +module.exports = require("./lib/_stream_transform.js") -},{"./readable":92}],94:[function(require,module,exports){ -module.exports = require('./lib/_stream_writable.js'); +},{"./lib/_stream_transform.js":87}],93:[function(require,module,exports){ +module.exports = require("./lib/_stream_writable.js") -},{"./lib/_stream_writable.js":88}],95:[function(require,module,exports){ +},{"./lib/_stream_writable.js":88}],94:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -15323,281 +15309,230 @@ Stream.prototype.pipe = function(dest, options) { return dest; }; -},{"events":63,"inherits":66,"readable-stream/duplex.js":83,"readable-stream/passthrough.js":91,"readable-stream/readable.js":92,"readable-stream/transform.js":93,"readable-stream/writable.js":94}],96:[function(require,module,exports){ -'use strict'; +},{"events":63,"inherits":66,"readable-stream/duplex.js":83,"readable-stream/passthrough.js":90,"readable-stream/readable.js":91,"readable-stream/transform.js":92,"readable-stream/writable.js":93}],95:[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. var Buffer = require('buffer').Buffer; -var bufferShim = require('buffer-shims'); -var isEncoding = Buffer.isEncoding || function (encoding) { - encoding = '' + encoding; - switch (encoding && encoding.toLowerCase()) { - case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': - return true; - default: - return false; - } -}; +var isBufferEncoding = Buffer.isEncoding + || function(encoding) { + switch (encoding && encoding.toLowerCase()) { + case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; + default: return false; + } + } -function _normalizeEncoding(enc) { - if (!enc) return 'utf8'; - var retried; - while (true) { - switch (enc) { - case 'utf8': - case 'utf-8': - return 'utf8'; - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return 'utf16le'; - case 'latin1': - case 'binary': - return 'latin1'; - case 'base64': - case 'ascii': - case 'hex': - return enc; - default: - if (retried) return; // undefined - enc = ('' + enc).toLowerCase(); - retried = true; - } - } -}; -// Do not cache `Buffer.isEncoding` when checking encoding names as some -// modules monkey-patch it to support additional encodings -function normalizeEncoding(enc) { - var nenc = _normalizeEncoding(enc); - if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); - return nenc || enc; +function assertEncoding(encoding) { + if (encoding && !isBufferEncoding(encoding)) { + throw new Error('Unknown encoding: ' + encoding); + } } // StringDecoder provides an interface for efficiently splitting a series of // buffers into a series of JS strings without breaking apart multi-byte -// characters. -exports.StringDecoder = StringDecoder; -function StringDecoder(encoding) { - this.encoding = normalizeEncoding(encoding); - var nb; +// characters. CESU-8 is handled as part of the UTF-8 encoding. +// +// @TODO Handling all encodings inside a single object makes it very difficult +// to reason about this code, so it should be split up in the future. +// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code +// points as used by CESU-8. +var StringDecoder = exports.StringDecoder = function(encoding) { + this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); + assertEncoding(encoding); switch (this.encoding) { - case 'utf16le': - this.text = utf16Text; - this.end = utf16End; - nb = 4; - break; case 'utf8': - this.fillLast = utf8FillLast; - nb = 4; + // CESU-8 represents each of Surrogate Pair by 3-bytes + this.surrogateSize = 3; + break; + case 'ucs2': + case 'utf16le': + // UTF-16 represents each of Surrogate Pair by 2-bytes + this.surrogateSize = 2; + this.detectIncompleteChar = utf16DetectIncompleteChar; break; case 'base64': - this.text = base64Text; - this.end = base64End; - nb = 3; + // Base-64 stores 3 bytes in 4 chars, and pads the remainder. + this.surrogateSize = 3; + this.detectIncompleteChar = base64DetectIncompleteChar; break; default: - this.write = simpleWrite; - this.end = simpleEnd; + this.write = passThroughWrite; return; } - this.lastNeed = 0; - this.lastTotal = 0; - this.lastChar = bufferShim.allocUnsafe(nb); -} -StringDecoder.prototype.write = function (buf) { - if (buf.length === 0) return ''; - var r; - var i; - if (this.lastNeed) { - r = this.fillLast(buf); - if (r === undefined) return ''; - i = this.lastNeed; - this.lastNeed = 0; - } else { - i = 0; - } - if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); - return r || ''; + // Enough space to store all bytes of a single character. UTF-8 needs 4 + // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). + this.charBuffer = new Buffer(6); + // Number of bytes received for the current incomplete multi-byte character. + this.charReceived = 0; + // Number of bytes expected for the current incomplete multi-byte character. + this.charLength = 0; }; -StringDecoder.prototype.end = utf8End; -// Returns only complete characters in a Buffer -StringDecoder.prototype.text = utf8Text; +// write decodes the given buffer and returns it as JS string that is +// guaranteed to not contain any partial multi-byte characters. Any partial +// character found at the end of the buffer is buffered up, and will be +// returned when calling write again with the remaining bytes. +// +// Note: Converting a Buffer containing an orphan surrogate to a String +// currently works, but converting a String to a Buffer (via `new Buffer`, or +// Buffer#write) will replace incomplete surrogates with the unicode +// replacement character. See https://codereview.chromium.org/121173009/ . +StringDecoder.prototype.write = function(buffer) { + var charStr = ''; + // if our last write ended with an incomplete multibyte character + while (this.charLength) { + // determine how many remaining bytes this buffer has to offer for this char + var available = (buffer.length >= this.charLength - this.charReceived) ? + this.charLength - this.charReceived : + buffer.length; + + // add the new bytes to the char buffer + buffer.copy(this.charBuffer, this.charReceived, 0, available); + this.charReceived += available; + + if (this.charReceived < this.charLength) { + // still not enough chars in this buffer? wait for more ... + return ''; + } + + // remove bytes belonging to the current character from the buffer + buffer = buffer.slice(available, buffer.length); + + // get the character that was split + charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); + + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + var charCode = charStr.charCodeAt(charStr.length - 1); + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + this.charLength += this.surrogateSize; + charStr = ''; + continue; + } + this.charReceived = this.charLength = 0; -// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer -StringDecoder.prototype.fillLast = function (buf) { - if (this.lastNeed <= buf.length) { - buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); - return this.lastChar.toString(this.encoding, 0, this.lastTotal); + // if there are no more bytes in this buffer, just emit our char + if (buffer.length === 0) { + return charStr; + } + break; } - buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); - this.lastNeed -= buf.length; -}; -// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a -// continuation byte. -function utf8CheckByte(byte) { - if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; - return -1; -} + // determine and set charLength / charReceived + this.detectIncompleteChar(buffer); -// Checks at most 3 bytes at the end of a Buffer in order to detect an -// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) -// needed to complete the UTF-8 character (if applicable) are returned. -function utf8CheckIncomplete(self, buf, i) { - var j = buf.length - 1; - if (j < i) return 0; - var nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) self.lastNeed = nb - 1; - return nb; + var end = buffer.length; + if (this.charLength) { + // buffer the incomplete character bytes we got + buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); + end -= this.charReceived; } - if (--j < i) return 0; - nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) self.lastNeed = nb - 2; - return nb; + + charStr += buffer.toString(this.encoding, 0, end); + + var end = charStr.length - 1; + var charCode = charStr.charCodeAt(end); + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + var size = this.surrogateSize; + this.charLength += size; + this.charReceived += size; + this.charBuffer.copy(this.charBuffer, size, 0, size); + buffer.copy(this.charBuffer, 0, 0, size); + return charStr.substring(0, end); } - if (--j < i) return 0; - nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) { - if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + + // or just emit the charStr + return charStr; +}; + +// detectIncompleteChar determines if there is an incomplete UTF-8 character at +// the end of the given buffer. If so, it sets this.charLength to the byte +// length that character, and sets this.charReceived to the number of bytes +// that are available for this character. +StringDecoder.prototype.detectIncompleteChar = function(buffer) { + // determine how many bytes we have to check at the end of this buffer + var i = (buffer.length >= 3) ? 3 : buffer.length; + + // Figure out if one of the last i bytes of our buffer announces an + // incomplete char. + for (; i > 0; i--) { + var c = buffer[buffer.length - i]; + + // See http://en.wikipedia.org/wiki/UTF-8#Description + + // 110XXXXX + if (i == 1 && c >> 5 == 0x06) { + this.charLength = 2; + break; } - return nb; - } - return 0; -} -// Validates as many continuation bytes for a multi-byte UTF-8 character as -// needed or are available. If we see a non-continuation byte where we expect -// one, we "replace" the validated continuation bytes we've seen so far with -// UTF-8 replacement characters ('\ufffd'), to match v8's UTF-8 decoding -// behavior. The continuation byte check is included three times in the case -// where all of the continuation bytes for a character exist in the same buffer. -// It is also done this way as a slight performance increase instead of using a -// loop. -function utf8CheckExtraBytes(self, buf, p) { - if ((buf[0] & 0xC0) !== 0x80) { - self.lastNeed = 0; - return '\ufffd'.repeat(p); - } - if (self.lastNeed > 1 && buf.length > 1) { - if ((buf[1] & 0xC0) !== 0x80) { - self.lastNeed = 1; - return '\ufffd'.repeat(p + 1); - } - if (self.lastNeed > 2 && buf.length > 2) { - if ((buf[2] & 0xC0) !== 0x80) { - self.lastNeed = 2; - return '\ufffd'.repeat(p + 2); - } + // 1110XXXX + if (i <= 2 && c >> 4 == 0x0E) { + this.charLength = 3; + break; } - } -} -// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. -function utf8FillLast(buf) { - var p = this.lastTotal - this.lastNeed; - var r = utf8CheckExtraBytes(this, buf, p); - if (r !== undefined) return r; - if (this.lastNeed <= buf.length) { - buf.copy(this.lastChar, p, 0, this.lastNeed); - return this.lastChar.toString(this.encoding, 0, this.lastTotal); - } - buf.copy(this.lastChar, p, 0, buf.length); - this.lastNeed -= buf.length; -} - -// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a -// partial character, the character's bytes are buffered until the required -// number of bytes are available. -function utf8Text(buf, i) { - var total = utf8CheckIncomplete(this, buf, i); - if (!this.lastNeed) return buf.toString('utf8', i); - this.lastTotal = total; - var end = buf.length - (total - this.lastNeed); - buf.copy(this.lastChar, 0, end); - return buf.toString('utf8', i, end); -} - -// For UTF-8, a replacement character for each buffered byte of a (partial) -// character needs to be added to the output. -function utf8End(buf) { - var r = buf && buf.length ? this.write(buf) : ''; - if (this.lastNeed) return r + '\ufffd'.repeat(this.lastTotal - this.lastNeed); - return r; -} - -// UTF-16LE typically needs two bytes per character, but even if we have an even -// number of bytes available, we need to check if we end on a leading/high -// surrogate. In that case, we need to wait for the next two bytes in order to -// decode the last character properly. -function utf16Text(buf, i) { - if ((buf.length - i) % 2 === 0) { - var r = buf.toString('utf16le', i); - if (r) { - var c = r.charCodeAt(r.length - 1); - if (c >= 0xD800 && c <= 0xDBFF) { - this.lastNeed = 2; - this.lastTotal = 4; - this.lastChar[0] = buf[buf.length - 2]; - this.lastChar[1] = buf[buf.length - 1]; - return r.slice(0, -1); - } + // 11110XXX + if (i <= 3 && c >> 3 == 0x1E) { + this.charLength = 4; + break; } - return r; } - this.lastNeed = 1; - this.lastTotal = 2; - this.lastChar[0] = buf[buf.length - 1]; - return buf.toString('utf16le', i, buf.length - 1); -} + this.charReceived = i; +}; -// For UTF-16LE we do not explicitly append special replacement characters if we -// end on a partial character, we simply let v8 handle that. -function utf16End(buf) { - var r = buf && buf.length ? this.write(buf) : ''; - if (this.lastNeed) { - var end = this.lastTotal - this.lastNeed; - return r + this.lastChar.toString('utf16le', 0, end); - } - return r; -} +StringDecoder.prototype.end = function(buffer) { + var res = ''; + if (buffer && buffer.length) + res = this.write(buffer); -function base64Text(buf, i) { - var n = (buf.length - i) % 3; - if (n === 0) return buf.toString('base64', i); - this.lastNeed = 3 - n; - this.lastTotal = 3; - if (n === 1) { - this.lastChar[0] = buf[buf.length - 1]; - } else { - this.lastChar[0] = buf[buf.length - 2]; - this.lastChar[1] = buf[buf.length - 1]; + if (this.charReceived) { + var cr = this.charReceived; + var buf = this.charBuffer; + var enc = this.encoding; + res += buf.slice(0, cr).toString(enc); } - return buf.toString('base64', i, buf.length - n); -} -function base64End(buf) { - var r = buf && buf.length ? this.write(buf) : ''; - if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); - return r; + return res; +}; + +function passThroughWrite(buffer) { + return buffer.toString(this.encoding); } -// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) -function simpleWrite(buf) { - return buf.toString(this.encoding); +function utf16DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 2; + this.charLength = this.charReceived ? 2 : 0; } -function simpleEnd(buf) { - return buf && buf.length ? this.write(buf) : ''; +function base64DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 3; + this.charLength = this.charReceived ? 3 : 0; } -},{"buffer":44,"buffer-shims":43}],97:[function(require,module,exports){ + +},{"buffer":44}],96:[function(require,module,exports){ (function (global){ /** @@ -15668,16 +15603,16 @@ function config (name) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],98:[function(require,module,exports){ +},{}],97:[function(require,module,exports){ arguments[4][66][0].apply(exports,arguments) -},{"dup":66}],99:[function(require,module,exports){ +},{"dup":66}],98:[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'; } -},{}],100:[function(require,module,exports){ +},{}],99:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -16267,4 +16202,4 @@ function hasOwnProperty(obj, prop) { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":99,"_process":82,"inherits":98}]},{},[1]); +},{"./support/isBuffer":98,"_process":82,"inherits":97}]},{},[1]); diff --git a/package.json b/package.json index a02ab9e803..185eced0f8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mocha", - "version": "3.4.1", + "version": "3.4.2", "description": "simple, flexible, fun test framework", "keywords": [ "mocha", From 82ced23fe8aa5a279f236dbfc16409609119e0bb Mon Sep 17 00:00:00 2001 From: David da Silva Date: Wed, 24 May 2017 18:07:36 +0200 Subject: [PATCH 26/42] Add missing #2778 link in Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98d445b880..295971edde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ [@makepanic]: https://github.com/makepanic [@Munter]: https://github.com/Munter +[#2778]: https://github.com/mochajs/mocha/pulls/2778 [#2802]: https://github.com/mochajs/mocha/issues/2802 [#2820]: https://github.com/mochajs/mocha/pull/2820 From eee62beca1deb2e6e84e14a001276c1978833f05 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Tue, 23 May 2017 22:40:49 -0700 Subject: [PATCH 27/42] add config for probot-stale integration --- .github/stale.yml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000..748e2845f7 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,39 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 120 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 14 +# Issues with these labels will never be considered stale +exemptLabels: + - pr-please + - confirmed + - future + - bug + - chore + - feature + - unconfirmed + - usability + - to-merge + - browser + - reporter + - feature + - documentation + - nice-to-have + - needs-review + - qa + - usability + - semver-minor + - semver-major + - semver-patch + - reporter + - common-mistake +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + I am a bot that watches issues for inactivity. + + This issue hasn't had any recent activity, and I'm labeling it `stale`. In 14 days, if there are no further comments or activity, I will close this issue. + + Thanks for contributing to Mocha! +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false From 488385a6cbca90795a1bc04518b2a61c4cf65571 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Wed, 24 May 2017 12:11:23 -0700 Subject: [PATCH 28/42] move CONTRIBUTING.md to .github/CONTRIBUTING.md [ci skip] --- CONTRIBUTING.md => .github/CONTRIBUTING.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CONTRIBUTING.md => .github/CONTRIBUTING.md (100%) diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to .github/CONTRIBUTING.md From e806ea643eefc122c631e635abc09a42dc7d04ae Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Wed, 24 May 2017 12:14:05 -0700 Subject: [PATCH 29/42] remove greenkeeper config from package.json [ci skip] --- package.json | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/package.json b/package.json index 185eced0f8..fff3c6359c 100644 --- a/package.json +++ b/package.json @@ -368,11 +368,5 @@ "supports-color": false }, "homepage": "https://mochajs.org", - "logo": "https://cldup.com/S9uQ-cOLYz.svg", - "greenkeeper": { - "ignore": [ - "phantomjs", - "lodash.create" - ] - } + "logo": "https://cldup.com/S9uQ-cOLYz.svg" } From 2760d7e8afa4f0e80ceec367ce984a3586d9ed72 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Wed, 24 May 2017 12:24:11 -0700 Subject: [PATCH 30/42] update README.md with current status [ci skip] --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index baaeb5bf9e..9e4d4dcbea 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,9 @@ 1. Increase test coverage on Node.js and browser - Increase integration coverage for all reporters - `html` reporter must be tested in browser - - Basic console reporters (*not* `nyan`, `landing`, etc.) must be tested in **both** browser and Node.js contexts; PhantomJS can consume all console reporters - - Filesystem-based reporters must be tested in Node.js context + - ~~Basic console reporters (*not* `nyan`, `landing`, etc.) must be tested in **both** browser and Node.js contexts; PhantomJS can consume all console reporters~~ + - ~~Filesystem-based reporters must be tested in Node.js context~~ + - **UPDATE - May 24 2017**: Thanks to [community contributions](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md#mag-coverage), the coverage on most reporters has increased dramatically! The `html` reporter is still in [dire need of coverage](https://coveralls.io/builds/11674428/source?filename=lib%2Freporters%2Fhtml.js). - Increase coverage against all interfaces (`exports` in particular). Ideally this becomes a "matrix" where we repeat sets of integration tests across all interfaces. - Refactor non-Node.js-specific tests to allow them to run in a browser context. Node.js-specific tests include those which *require* the CLI or filesystem. Most everything else is fair game. 2. Review current open pull requests @@ -20,7 +21,7 @@ - Pull requests **must** have supporting tests. The only exceptions are pure cosmetic or non-functional changes. - Pull request contributors must sign the CLA. 3. Close old, inactive issues and pull requests - - A bot should do this. We need a bot. Got a bot? + - ~~A bot should do this. We need a bot. Got a bot?~~ We now use GitHub's own [probot-stale](https://www.npmjs.com/package/probot-stale). 4. Triage issues - If we run into "critical" bugs, they need fixing. - "Critical" means Mocha is broken w/o workarounds for a *large percentage* of users From 99b282b94c616dc803fc5f00f68cfb854908f263 Mon Sep 17 00:00:00 2001 From: Kunal Nagpal Date: Fri, 26 May 2017 22:26:13 +0530 Subject: [PATCH 31/42] Added code of conduct (#2832) Added code of conduct, resolves #2135 [ci skip] --- .github/CODE_OF_CONDUCT.md | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .github/CODE_OF_CONDUCT.md diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..4e63d0ac3d --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,51 @@ +# Mocha Code of Conduct + +## Be friendly and patient +We understand that everyone has different levels of experience or knowledge in many diverse fields, be it technical or +non-technical in nature. We also have areas of knowledge we are eager to expand; we want to be a community where people +can not only contribute, but feel comfortable to ask questions as well and learn along the way. If someone says something +wrong, or says something accidentally offensive, respond with patience and try to keep it polite and civil. Remember that +we all were newbies at one point. + +## Be welcoming +We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not +limited to, members of any race, ethnicity, culture, national origin, color, immigration status, social and economic class, +educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, +religion, and mental and physical ability. + +## Be considerate +Your work will be used by other people, and you in turn will depend on the work of others. Any decision you make will affect +users and colleagues, and you should take those consequences into account when making decisions. Remember that we’re a world-wide +community, so you might not be communicating in someone else’s primary language. + +## Be respectful +Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all +experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important +to remember that a community where people feel uncomfortable or threatened is not a productive one. Members of the JS Foundation +community should be respectful when dealing with other members as well as with people outside the JS Foundation community. + +## Be careful in the words that you choose +We are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put +down other participants. Harassment and other exclusionary behavior aren’t acceptable. This includes, but is not limited to: + +* Violent threats or language directed against another person. +* Discriminatory jokes and language. +* Posting sexually explicit or violent material. +* Posting (or threatening to post) other people’s personally identifying information (“doxing”). +* Personal insults, especially those using racist or sexist terms. +* Unwelcome sexual attention. +* Advocating for, or encouraging, any of the above behavior. +* Repeated harassment of others. In general, if someone asks you to stop, then stop. + +## When we disagree, try to understand why +Disagreements, both social and technical, happen all the time and JS Foundation projects are no exception. It is important +that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of the JS +Foundation comes from its varied community, people from a wide range of backgrounds. Different people have different +perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t +forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues +and learning from mistakes. + +Original text courtesy of the Speak Up! project and Django Project. + +## QUESTIONS? +If you have questions, please see the FAQ. If that doesn’t answer your questions, feel free to email conduct@js.foundation. From 4aaaaddef40c4cfb7e3ed88a926b7ac3fcd5a3a1 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Sat, 27 May 2017 12:51:01 -0700 Subject: [PATCH 32/42] revert 93392dd; downgrade to phantomjs v1.9.8; closes #2840 (#2841) --- karma.conf.js | 3 ++- package.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/karma.conf.js b/karma.conf.js index 30d5714665..2ba9d4d2e1 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -4,6 +4,7 @@ var fs = require('fs'); var path = require('path'); var mkdirp = require('mkdirp'); var baseBundleDirpath = path.join(__dirname, '.karma'); +var osName = require('os-name'); module.exports = function (config) { var bundleDirpath; @@ -47,7 +48,7 @@ module.exports = function (config) { }, reporters: ['spec'], colors: true, - browsers: ['PhantomJS'], // This is the default browser to run, locally + browsers: [osName() === 'macOS Sierra' ? 'Chrome' : 'PhantomJS'], // This is the default browser to run, locally logLevel: config.LOG_INFO, client: { mocha: { diff --git a/package.json b/package.json index fff3c6359c..562a182a8c 100644 --- a/package.json +++ b/package.json @@ -336,10 +336,11 @@ "karma-chrome-launcher": "^2.0.0", "karma-expect": "^1.1.2", "karma-mocha": "^1.3.0", - "karma-phantomjs-launcher": "^1.0.2", + "karma-phantomjs-launcher": "0.2.3", "karma-sauce-launcher": "coderbyheart/karma-sauce-launcher", "karma-spec-reporter": "0.0.26", "nyc": "^10.0.0", + "os-name": "^2.0.1", "phantomjs": "1.9.8", "rimraf": "^2.5.2", "should": "^11.1.1", From a054380203d1d7f271ff0649656779915ac28e63 Mon Sep 17 00:00:00 2001 From: David da Silva Date: Sat, 27 May 2017 22:25:11 +0200 Subject: [PATCH 33/42] Remove not-longer-necessary `run` global in .estlintrc (#2831) Sindre already merged it. --- test/.eslintrc.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/.eslintrc.yaml b/test/.eslintrc.yaml index 1830a0b6f4..a32fd84d48 100644 --- a/test/.eslintrc.yaml +++ b/test/.eslintrc.yaml @@ -3,5 +3,3 @@ env: globals: expect: false assert: false - # https://github.com/sindresorhus/globals/pull/102 - run: false From acd77015bd6af6675472c0ea71de40401ea25984 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Thu, 1 Jun 2017 13:30:40 -0700 Subject: [PATCH 34/42] increase timeout on http-meta tests --- test/http-meta-2.spec.js | 4 ++++ test/http-meta.spec.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/test/http-meta-2.spec.js b/test/http-meta-2.spec.js index 4530969041..18b4158467 100644 --- a/test/http-meta-2.spec.js +++ b/test/http-meta-2.spec.js @@ -73,6 +73,10 @@ describe('http server', function () { server.listen(PORT, done); }); + beforeEach(function () { + this.timeout(2000); + }); + after(function () { server.close(); }); diff --git a/test/http-meta.spec.js b/test/http-meta.spec.js index c92dbd2307..2ed7ed9204 100644 --- a/test/http-meta.spec.js +++ b/test/http-meta.spec.js @@ -46,6 +46,10 @@ describe('http requests', function () { server.listen(PORT, done); }); + beforeEach(function () { + this.timeout(2000); + }); + after(function () { server.close(); }); From 10e5ada8407eeb3081061ee5c6b53c5b8f5241c6 Mon Sep 17 00:00:00 2001 From: David da Silva Date: Sat, 3 Jun 2017 07:42:33 +0200 Subject: [PATCH 35/42] Declare main eslintrc as `root` (#2830) It will prevent config lookup to exit Mocha's project folder. --- .eslintrc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 911f22c681..d1e5b62c7d 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -1,3 +1,4 @@ +root: true env: node: true browser: true From e00d27bde9ce06fd25da9da6bd5f43e641631315 Mon Sep 17 00:00:00 2001 From: elergy Date: Wed, 31 May 2017 18:22:28 +0300 Subject: [PATCH 36/42] Set Node.js v.8 as a default version --- .travis.yml | 26 ++++++++++++++------------ appveyor.yml | 1 + 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3f03be785a..8a76015bdd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,8 +15,10 @@ env: matrix: fast_finish: true include: - - node_js: '7' + - node_js: '8' env: TARGET=test-node COVERAGE=true + - node_js: '7' + env: TARGET=test-node - node_js: '6' env: TARGET=test-node - node_js: '5' @@ -31,37 +33,37 @@ matrix: env: TARGET=test-node - node_js: '0.10' env: TARGET=test-node - - node_js: '7' + - node_js: '8' env: TARGET=lint # phantomjs - - node_js: '7' + - node_js: '8' env: TARGET=test-browser # chrome - - node_js: '7' + - node_js: '8' env: TARGET=test-browser BROWSER="chrome@latest" PLATFORM="Windows 8" # edge - - node_js: '7' + - node_js: '8' env: TARGET=test-browser BROWSER="MicrosoftEdge@latest" PLATFORM="Windows 10" # ie11 - - node_js: '7' + - node_js: '8' env: TARGET=test-browser BROWSER="internet explorer@11.0" PLATFORM="Windows 8.1" # ie10 - - node_js: '7' + - node_js: '8' env: TARGET=test-browser BROWSER="internet explorer@10.0" PLATFORM="Windows 8" # ie9 - - node_js: '7' + - node_js: '8' env: TARGET=test-browser BROWSER="internet explorer@9.0" PLATFORM="Windows 7" # ie8 - - node_js: '7' + - node_js: '8' env: TARGET=test-browser BROWSER="internet explorer@8.0" PLATFORM="Windows 7" # ie7 - - node_js: '7' + - node_js: '8' env: TARGET=test-browser BROWSER="internet explorer@7.0" PLATFORM="Windows XP" # firefox - - node_js: '7' + - node_js: '8' env: TARGET=test-browser BROWSER="firefox@latest" PLATFORM="Windows 8.1" # safari - - node_js: '7' + - node_js: '8' env: TARGET=test-browser BROWSER="safari@latest" PLATFORM="OS X 10.11" before_install: scripts/travis-before-install.sh diff --git a/appveyor.yml b/appveyor.yml index 6a2a6e1811..ff832db835 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,6 @@ environment: matrix: + - nodejs_version: '8' - nodejs_version: '7' - nodejs_version: '6' - nodejs_version: '4' From c0b5990e68c3bdb0e3902fa078add16f5989f9d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jupp=20M=C3=BCller?= Date: Sat, 20 May 2017 18:26:10 +0200 Subject: [PATCH 37/42] Pass flags for NAPI modules This change enables testing of NAPI modules[1]. This is achieved by passing the appropriate flags to node inside the mocha executable. --- bin/_mocha | 1 + bin/mocha | 1 + 2 files changed, 2 insertions(+) diff --git a/bin/_mocha b/bin/_mocha index 7f3d01aa1d..e47d0bd81b 100755 --- a/bin/_mocha +++ b/bin/_mocha @@ -99,6 +99,7 @@ program .option('--no-warnings', 'silence all node process warnings') .option('--opts ', 'specify opts path', 'test/mocha.opts') .option('--perf-basic-prof', 'enable perf linux profiler (basic support)') + .option('--napi-modules', 'enable experimental NAPI modules') .option('--prof', 'log statistical profiling information') .option('--log-timer-events', 'Time events including external callbacks') .option('--recursive', 'include sub directories') diff --git a/bin/mocha b/bin/mocha index 8ba64a0a06..d632fbc394 100755 --- a/bin/mocha +++ b/bin/mocha @@ -48,6 +48,7 @@ process.argv.slice(2).forEach(function (arg) { case '--use_strict': case '--allow-natives-syntax': case '--perf-basic-prof': + case '--napi-modules': args.unshift(arg); break; default: From 95cf2c4cce29643243b14f6b78a31c20c4d4deb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Popr=C3=A1di=20=C3=81rp=C3=A1d?= Date: Wed, 31 May 2017 17:15:46 +0200 Subject: [PATCH 38/42] fixed array test name in mocha/test/browser/index.html --- test/browser/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/browser/index.html b/test/browser/index.html index 2331834ecf..d8b7cc9f72 100644 --- a/test/browser/index.html +++ b/test/browser/index.html @@ -11,7 +11,7 @@ if (!expr) throw new Error(msg || 'failed'); } - + From 2928b38000f316fc8453f86d9df79cdffe6448ff Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Fri, 2 Jun 2017 22:48:45 -0700 Subject: [PATCH 39/42] ignore lockfiles for now --- .gitignore | 2 ++ .npmrc | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 .npmrc diff --git a/.gitignore b/.gitignore index 9b94c5bee0..da8160085d 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ npm-debug.log* .nyc_output/ coverage/ BUILDTMP/ +yarn.lock +package-lock.json diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000000..b15cbc2c02 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +package-lock=false + From 2bc9c4d1d638c8a95250757dd23724f788918abe Mon Sep 17 00:00:00 2001 From: Charlie Rudolph Date: Sun, 4 Jun 2017 05:04:11 -0700 Subject: [PATCH 40/42] Add --forbid-only and --forbid-pending options (#2696) * add --production option * update comment * fix lint * add tests * remove only * update * simplify * remove onlys * fix and * update self.failures * update test description * Remove breaking semicolon * fix lint --- bin/_mocha | 12 ++++- lib/mocha.js | 20 +++++++ lib/runner.js | 6 +++ .../fixtures/options/forbid-only/only.js | 7 +++ .../fixtures/options/forbid-only/passed.js | 7 +++ .../fixtures/options/forbid-pending/passed.js | 7 +++ .../options/forbid-pending/pending.js | 7 +++ .../fixtures/options/forbid-pending/skip.js | 7 +++ test/integration/options.spec.js | 52 +++++++++++++++++++ 9 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 test/integration/fixtures/options/forbid-only/only.js create mode 100644 test/integration/fixtures/options/forbid-only/passed.js create mode 100644 test/integration/fixtures/options/forbid-pending/passed.js create mode 100644 test/integration/fixtures/options/forbid-pending/pending.js create mode 100644 test/integration/fixtures/options/forbid-pending/skip.js diff --git a/bin/_mocha b/bin/_mocha index e47d0bd81b..c37d49fef5 100755 --- a/bin/_mocha +++ b/bin/_mocha @@ -112,7 +112,9 @@ program .option('--use_strict', 'enforce strict mode') .option('--watch-extensions ,...', 'additional extensions to monitor with --watch', list, []) .option('--delay', 'wait for async suite definition') - .option('--allow-uncaught', 'enable uncaught errors to propagate'); + .option('--allow-uncaught', 'enable uncaught errors to propagate') + .option('--forbid-only', 'causes test marked with only to fail the suite') + .option('--forbid-pending', 'causes pending tests and test marked with skip to fail the suite'); program._name = 'mocha'; @@ -334,6 +336,14 @@ if (program.retries) { mocha.suite.retries(program.retries); } +// --forbid-only + +if (program.forbidOnly) mocha.forbidOnly(); + +// --forbid-pending + +if (program.forbidPending) mocha.forbidPending(); + // custom compiler support var extensions = ['js']; diff --git a/lib/mocha.js b/lib/mocha.js index 8bacf27b17..bfc0238d46 100644 --- a/lib/mocha.js +++ b/lib/mocha.js @@ -483,6 +483,24 @@ Mocha.prototype.delay = function delay () { return this; }; +/** + * Tests marked only fail the suite + * @returns {Mocha} + */ +Mocha.prototype.forbidOnly = function () { + this.options.forbidOnly = true; + return this; +}; + +/** + * Pending tests and tests marked skip fail the suite + * @returns {Mocha} + */ +Mocha.prototype.forbidPending = function () { + this.options.forbidPending = true; + return this; +}; + /** * Run tests and invoke `fn()` when complete. * @@ -504,6 +522,8 @@ Mocha.prototype.run = function (fn) { runner.hasOnly = options.hasOnly; runner.asyncOnly = options.asyncOnly; runner.allowUncaught = options.allowUncaught; + runner.forbidOnly = options.forbidOnly; + runner.forbidPending = options.forbidPending; if (options.grep) { runner.grep(options.grep, options.invert); } diff --git a/lib/runner.js b/lib/runner.js index b024e0dcb5..039065a2e0 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -820,6 +820,12 @@ Runner.prototype.run = function (fn) { // callback this.on('end', function () { + if (self.forbidOnly && self.hasOnly) { + self.failures += self.stats.tests; + } + if (self.forbidPending) { + self.failures += self.stats.pending; + } debug('end'); process.removeListener('uncaughtException', uncaught); fn(self.failures); diff --git a/test/integration/fixtures/options/forbid-only/only.js b/test/integration/fixtures/options/forbid-only/only.js new file mode 100644 index 0000000000..c09e804126 --- /dev/null +++ b/test/integration/fixtures/options/forbid-only/only.js @@ -0,0 +1,7 @@ +'use strict'; + +describe('forbid only - test marked with only', function () { + it('test1', function () {}); + it.only('test2', function () {}); + it('test3', function () {}); +}); diff --git a/test/integration/fixtures/options/forbid-only/passed.js b/test/integration/fixtures/options/forbid-only/passed.js new file mode 100644 index 0000000000..6c4d4ac1d4 --- /dev/null +++ b/test/integration/fixtures/options/forbid-only/passed.js @@ -0,0 +1,7 @@ +'use strict'; + +describe('forbid only - `.only` is not used', function () { + it('test1', function () {}); + it('test2', function () {}); + it('test3', function () {}); +}); diff --git a/test/integration/fixtures/options/forbid-pending/passed.js b/test/integration/fixtures/options/forbid-pending/passed.js new file mode 100644 index 0000000000..cd12668f4d --- /dev/null +++ b/test/integration/fixtures/options/forbid-pending/passed.js @@ -0,0 +1,7 @@ +'use strict'; + +describe('forbid pending - all test pass', function () { + it('test1', function () {}); + it('test2', function () {}); + it('test3', function () {}); +}); diff --git a/test/integration/fixtures/options/forbid-pending/pending.js b/test/integration/fixtures/options/forbid-pending/pending.js new file mode 100644 index 0000000000..96abd0bf47 --- /dev/null +++ b/test/integration/fixtures/options/forbid-pending/pending.js @@ -0,0 +1,7 @@ +'use strict'; + +describe('forbid pending - test without function', function () { + it('test1', function () {}); + it('test2'); + it('test3', function () {}); +}); diff --git a/test/integration/fixtures/options/forbid-pending/skip.js b/test/integration/fixtures/options/forbid-pending/skip.js new file mode 100644 index 0000000000..c6fd31d303 --- /dev/null +++ b/test/integration/fixtures/options/forbid-pending/skip.js @@ -0,0 +1,7 @@ +'use strict'; + +describe('forbid pending - test marked with skip', function () { + it('test1', function () {}); + it.skip('test2', function () {}); + it('test3', function () {}); +}); diff --git a/test/integration/options.spec.js b/test/integration/options.spec.js index 7c7a3cc75e..325fbada8f 100644 --- a/test/integration/options.spec.js +++ b/test/integration/options.spec.js @@ -180,4 +180,56 @@ describe('options', function () { }); }); }); + + describe('--forbid-only', function () { + before(function () { + args = ['--forbid-only']; + }); + + it('succeeds if there are only passed tests', function (done) { + run('options/forbid-only/passed.js', args, function (err, res) { + assert(!err); + assert.equal(res.code, 0); + done(); + }); + }); + + it('fails if there are tests marked only', function (done) { + run('options/forbid-only/only.js', args, function (err, res) { + assert(!err); + assert.equal(res.code, 1); + done(); + }); + }); + }); + + describe('--forbid-pending', function () { + before(function () { + args = ['--forbid-pending']; + }); + + it('succeeds if there are only passed tests', function (done) { + run('options/forbid-pending/passed.js', args, function (err, res) { + assert(!err); + assert.equal(res.code, 0); + done(); + }); + }); + + it('fails if there are tests marked skip', function (done) { + run('options/forbid-pending/skip.js', args, function (err, res) { + assert(!err); + assert.equal(res.code, 1); + done(); + }); + }); + + it('fails if there are pending tests', function (done) { + run('options/forbid-pending/pending.js', args, function (err, res) { + assert(!err); + assert.equal(res.code, 1); + done(); + }); + }); + }); }); From f20de56637b2223f614ce40adc0d41a58030f042 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Sat, 27 May 2017 11:12:15 -0700 Subject: [PATCH 41/42] reorganize test hierarchy; closes #2838 --- Makefile | 52 ++-- karma.conf.js | 11 +- test/browser-fixtures/bdd.fixture.js | 2 + test/browser-fixtures/exports.fixture.js | 2 + test/browser-fixtures/qunit.fixture.js | 2 + test/browser-fixtures/tdd.fixture.js | 2 + test/browser/README.md | 3 + test/{acceptance => compiler}/test.coffee | 0 test/{acceptance => compiler}/test.foo | 0 test/{acceptance => }/glob/glob.sh | 10 +- test/{acceptance => }/glob/glob.spec.js | 0 test/{acceptance => }/interfaces/bdd.spec.js | 0 .../interfaces/exports.spec.js | 0 .../{acceptance => }/interfaces/qunit.spec.js | 0 test/{acceptance => }/interfaces/tdd.spec.js | 0 test/jsapi/index.js | 20 +- test/{acceptance => }/misc/exit.spec.js | 0 test/{acceptance => }/misc/many.spec.js | 0 test/{acceptance => }/misc/nontty.spec.js | 0 .../misc/only/bdd-require.spec.js | 2 +- test/{acceptance => }/misc/only/bdd.spec.js | 0 .../misc/only/global/bdd.spec.js | 0 .../misc/only/global/qunit.spec.js | 0 .../misc/only/global/tdd.spec.js | 0 test/{acceptance => }/misc/only/qunit.spec.js | 0 test/{acceptance => }/misc/only/tdd.spec.js | 0 test/{ => node-unit}/color.spec.js | 0 .../file-utils.spec.js | 0 test/{acceptance => node-unit}/fs.spec.js | 0 test/{ => node-unit}/http-meta-2.spec.js | 0 test/{ => node-unit}/http-meta.spec.js | 0 test/{acceptance => node-unit}/http.spec.js | 0 test/node-unit/stack-trace-filter.spec.js | 156 ++++++++++ test/{acceptance => }/require/a.js | 0 test/{acceptance => }/require/b.coffee | 0 test/{acceptance => }/require/c.js | 0 test/{acceptance => }/require/d.coffee | 0 test/{acceptance => }/require/require.spec.js | 0 test/{acceptance => unit}/context.spec.js | 0 test/{acceptance => unit}/duration.spec.js | 0 test/{acceptance => unit}/globals.spec.js | 0 test/{ => unit}/grep.spec.js | 2 +- test/{ => unit}/hook-async.spec.js | 0 test/{ => unit}/hook-sync-nested.spec.js | 0 test/{ => unit}/hook-sync.spec.js | 0 test/{ => unit}/hook-timeout.spec.js | 0 test/{ => unit}/mocha.spec.js | 2 +- test/{ => unit}/ms.spec.js | 2 +- .../overspecified-async.spec.js | 0 .../required-tokens.spec.js | 0 test/{acceptance => unit}/root.spec.js | 0 test/{ => unit}/runnable.spec.js | 28 +- test/{ => unit}/runner.spec.js | 2 +- test/{ => unit}/suite.spec.js | 2 +- test/{ => unit}/test.spec.js | 2 +- test/{acceptance => unit}/throw.spec.js | 0 test/{acceptance => unit}/timeout.spec.js | 0 test/{acceptance => unit}/utils.spec.js | 218 +++++++++++++- test/utils.spec.js | 285 ------------------ 59 files changed, 443 insertions(+), 362 deletions(-) create mode 100644 test/browser/README.md rename test/{acceptance => compiler}/test.coffee (100%) rename test/{acceptance => compiler}/test.foo (100%) rename test/{acceptance => }/glob/glob.sh (84%) rename test/{acceptance => }/glob/glob.spec.js (100%) rename test/{acceptance => }/interfaces/bdd.spec.js (100%) rename test/{acceptance => }/interfaces/exports.spec.js (100%) rename test/{acceptance => }/interfaces/qunit.spec.js (100%) rename test/{acceptance => }/interfaces/tdd.spec.js (100%) rename test/{acceptance => }/misc/exit.spec.js (100%) rename test/{acceptance => }/misc/many.spec.js (100%) rename test/{acceptance => }/misc/nontty.spec.js (100%) rename test/{acceptance => }/misc/only/bdd-require.spec.js (90%) rename test/{acceptance => }/misc/only/bdd.spec.js (100%) rename test/{acceptance => }/misc/only/global/bdd.spec.js (100%) rename test/{acceptance => }/misc/only/global/qunit.spec.js (100%) rename test/{acceptance => }/misc/only/global/tdd.spec.js (100%) rename test/{acceptance => }/misc/only/qunit.spec.js (100%) rename test/{acceptance => }/misc/only/tdd.spec.js (100%) rename test/{ => node-unit}/color.spec.js (100%) rename test/{acceptance => node-unit}/file-utils.spec.js (100%) rename test/{acceptance => node-unit}/fs.spec.js (100%) rename test/{ => node-unit}/http-meta-2.spec.js (100%) rename test/{ => node-unit}/http-meta.spec.js (100%) rename test/{acceptance => node-unit}/http.spec.js (100%) create mode 100644 test/node-unit/stack-trace-filter.spec.js rename test/{acceptance => }/require/a.js (100%) rename test/{acceptance => }/require/b.coffee (100%) rename test/{acceptance => }/require/c.js (100%) rename test/{acceptance => }/require/d.coffee (100%) rename test/{acceptance => }/require/require.spec.js (100%) rename test/{acceptance => unit}/context.spec.js (100%) rename test/{acceptance => unit}/duration.spec.js (100%) rename test/{acceptance => unit}/globals.spec.js (100%) rename test/{ => unit}/grep.spec.js (98%) rename test/{ => unit}/hook-async.spec.js (100%) rename test/{ => unit}/hook-sync-nested.spec.js (100%) rename test/{ => unit}/hook-sync.spec.js (100%) rename test/{ => unit}/hook-timeout.spec.js (100%) rename test/{ => unit}/mocha.spec.js (95%) rename test/{ => unit}/ms.spec.js (98%) rename test/{acceptance => unit}/overspecified-async.spec.js (100%) rename test/{acceptance => unit}/required-tokens.spec.js (100%) rename test/{acceptance => unit}/root.spec.js (100%) rename test/{ => unit}/runnable.spec.js (96%) rename test/{ => unit}/runner.spec.js (99%) rename test/{ => unit}/suite.spec.js (99%) rename test/{ => unit}/test.spec.js (98%) rename test/{acceptance => unit}/throw.spec.js (100%) rename test/{acceptance => unit}/timeout.spec.js (100%) rename test/{acceptance => unit}/utils.spec.js (71%) delete mode 100644 test/utils.spec.js diff --git a/Makefile b/Makefile index ad8b097e4e..2fa367e8ff 100644 --- a/Makefile +++ b/Makefile @@ -63,79 +63,79 @@ test-jsapi: test-unit: @printf "==> [Test :: Unit]\n" - $(call test_node,unit) test/acceptance/*.js \ - --growl \ - test/*.js + $(call test_node,unit) test/unit/*.spec.js \ + test/node-unit/*.spec.js \ + --growl test-integration: @printf "==> [Test :: Integrations]\n" $(call test_node,integration) --timeout 5000 \ - test/integration/*.js + test/integration/*.spec.js test-compilers: @printf "==> [Test :: Compilers]\n" $(call test_node,compilers) --compilers coffee:coffee-script/register,foo:./test/compiler/foo \ - test/acceptance/test.coffee \ - test/acceptance/test.foo + test/compiler/test.coffee \ + test/compiler/test.foo test-requires: @printf "==> [Test :: Requires]\n" $(call test_node,requires) --compilers coffee:coffee-script/register \ - --require test/acceptance/require/a.js \ - --require test/acceptance/require/b.coffee \ - --require test/acceptance/require/c.js \ - --require test/acceptance/require/d.coffee \ - test/acceptance/require/require.spec.js + --require test/require/a.js \ + --require test/require/b.coffee \ + --require test/require/c.js \ + --require test/require/d.coffee \ + test/require/require.spec.js test-bdd: @printf "==> [Test :: BDD]\n" $(call test_node,bdd) --ui bdd \ - test/acceptance/interfaces/bdd.spec + test/interfaces/bdd.spec test-tdd: @printf "==> [Test :: TDD]\n" $(call test_node,tdd) --ui tdd \ - test/acceptance/interfaces/tdd.spec + test/interfaces/tdd.spec test-qunit: @printf "==> [Test :: QUnit]\n" $(call test_node,qunit) --ui qunit \ - test/acceptance/interfaces/qunit.spec + test/interfaces/qunit.spec test-exports: @printf "==> [Test :: Exports]\n" $(call test_node,exports) --ui exports \ - test/acceptance/interfaces/exports.spec + test/interfaces/exports.spec test-glob: @printf "==> [Test :: Glob]\n" - bash ./test/acceptance/glob/glob.sh + bash ./test/glob/glob.sh test-reporters: @printf "==> [Test :: Reporters]\n" - $(call test_node,reporters) test/reporters/*.js + $(call test_node,reporters) test/reporters/*.spec.js test-only: @printf "==> [Test :: Only]\n" $(call test_node,only-tdd) --ui tdd \ - test/acceptance/misc/only/tdd.spec + test/misc/only/tdd.spec $(call test_node,only-bdd) --ui bdd \ - test/acceptance/misc/only/bdd.spec + test/misc/only/bdd.spec $(call test_node,only-bdd-require) --ui qunit \ - test/acceptance/misc/only/bdd-require.spec + test/misc/only/bdd-require.spec test-global-only: @printf "==> [Test :: Global Only]\n" $(call test_node,global-only-tdd) --ui tdd \ - test/acceptance/misc/only/global/tdd.spec + test/misc/only/global/tdd.spec $(call test_node,global-only-bdd) --ui bdd \ - test/acceptance/misc/only/global/bdd.spec + test/misc/only/global/bdd.spec $(call test_node,global-only-qunit) --ui qunit \ - test/acceptance/misc/only/global/qunit.spec + test/misc/only/global/qunit.spec test-mocha: @printf "==> [Test :: Mocha]\n" @@ -144,19 +144,19 @@ test-mocha: non-tty: @printf "==> [Test :: Non-TTY]\n" $(call test_node,non-tty-dot) --reporter dot \ - test/acceptance/interfaces/bdd.spec 2>&1 > /tmp/dot.out + test/interfaces/bdd.spec 2>&1 > /tmp/dot.out @echo dot: @cat /tmp/dot.out $(call test_node,non-tty-list) --reporter list \ - test/acceptance/interfaces/bdd.spec 2>&1 > /tmp/list.out + test/interfaces/bdd.spec 2>&1 > /tmp/list.out @echo list: @cat /tmp/list.out $(call test_node,non-tty-spec) --reporter spec \ - test/acceptance/interfaces/bdd.spec 2>&1 > /tmp/spec.out + test/interfaces/bdd.spec 2>&1 > /tmp/spec.out @echo spec: @cat /tmp/spec.out diff --git a/karma.conf.js b/karma.conf.js index 2ba9d4d2e1..c99150e2f9 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -18,14 +18,7 @@ module.exports = function (config) { // we use the BDD interface for all of the tests that // aren't interface-specific. 'test/browser-fixtures/bdd.fixture.js', - 'test/acceptance/*.spec.js' - ], - exclude: [ - 'test/acceptance/http.spec.js', - 'test/acceptance/fs.spec.js', - 'test/acceptance/file-utils.spec.js', - 'test/acceptance/require/**/*.js', - 'test/acceptance/misc/**/*.js' + 'test/unit/*.spec.js' ], preprocessors: { 'test/**/*.js': ['browserify'] @@ -128,7 +121,7 @@ module.exports = function (config) { } cfg.files = [ 'test/browser-fixtures/' + ui + '.fixture.js', - 'test/acceptance/interfaces/' + ui + '.spec.js' + 'test/interfaces/' + ui + '.spec.js' ]; } else if (cfg.sauceLabs) { cfg.sauceLabs.testName = 'Unit Tests'; diff --git a/test/browser-fixtures/bdd.fixture.js b/test/browser-fixtures/bdd.fixture.js index d19993676a..5fe802f74a 100644 --- a/test/browser-fixtures/bdd.fixture.js +++ b/test/browser-fixtures/bdd.fixture.js @@ -2,5 +2,7 @@ /* eslint-env browser */ +process.stdout = require('browser-stdout')(); + window.mocha.timeout(200) .ui('bdd'); diff --git a/test/browser-fixtures/exports.fixture.js b/test/browser-fixtures/exports.fixture.js index 97b8b97cbe..a4c25cff99 100644 --- a/test/browser-fixtures/exports.fixture.js +++ b/test/browser-fixtures/exports.fixture.js @@ -2,5 +2,7 @@ /* eslint-env browser */ +process.stdout = require('browser-stdout')(); + window.mocha.timeout(200) .ui('exports'); diff --git a/test/browser-fixtures/qunit.fixture.js b/test/browser-fixtures/qunit.fixture.js index a3fd887940..79b49498d5 100644 --- a/test/browser-fixtures/qunit.fixture.js +++ b/test/browser-fixtures/qunit.fixture.js @@ -2,5 +2,7 @@ /* eslint-env browser */ +process.stdout = require('browser-stdout')(); + window.mocha.timeout(200) .ui('qunit'); diff --git a/test/browser-fixtures/tdd.fixture.js b/test/browser-fixtures/tdd.fixture.js index 0c36f0c54b..2fdc8f758c 100644 --- a/test/browser-fixtures/tdd.fixture.js +++ b/test/browser-fixtures/tdd.fixture.js @@ -2,5 +2,7 @@ /* eslint-env browser */ +process.stdout = require('browser-stdout')(); + window.mocha.timeout(200) .ui('tdd'); diff --git a/test/browser/README.md b/test/browser/README.md new file mode 100644 index 0000000000..15e4178b3e --- /dev/null +++ b/test/browser/README.md @@ -0,0 +1,3 @@ +These files need to be run manually by loading the `.html` file(s) in a browser. + +It would be awesome if we could automate that! diff --git a/test/acceptance/test.coffee b/test/compiler/test.coffee similarity index 100% rename from test/acceptance/test.coffee rename to test/compiler/test.coffee diff --git a/test/acceptance/test.foo b/test/compiler/test.foo similarity index 100% rename from test/acceptance/test.foo rename to test/compiler/test.foo diff --git a/test/acceptance/glob/glob.sh b/test/glob/glob.sh similarity index 84% rename from test/acceptance/glob/glob.sh rename to test/glob/glob.sh index 823ba07fb9..c0cb21d3f8 100755 --- a/test/acceptance/glob/glob.sh +++ b/test/glob/glob.sh @@ -7,7 +7,7 @@ cd $SCRIPT_DIR || { exit 1 } -../../../bin/mocha -R json-stream ./*.js > /tmp/mocha-glob.txt || { +../../bin/mocha -R json-stream ./*.js > /tmp/mocha-glob.txt || { echo Globbing ./*.js in `pwd` failed. exit 1 } @@ -17,7 +17,7 @@ cat /tmp/mocha-glob.txt | grep -q -F '["end",{"suites":1,"tests":1,"passes":1,"p exit 1 } -../../../bin/mocha -R json-stream ./*-none.js 2> /tmp/mocha-glob.txt && { +../../bin/mocha -R json-stream ./*-none.js 2> /tmp/mocha-glob.txt && { echo Globbing './*-none.js' in `pwd` failed. exit 1 } @@ -27,7 +27,7 @@ cat /tmp/mocha-glob.txt | grep -q -F 'Could not find any test files matching pat exit 1 } -../../../bin/mocha -R json-stream ./*.js ./*-none.js >& /tmp/mocha-glob.txt || { +../../bin/mocha -R json-stream ./*.js ./*-none.js >& /tmp/mocha-glob.txt || { echo Globbing ./*.js ./*-none.js in `pwd` failed. exit 1 } @@ -43,7 +43,7 @@ cat /tmp/mocha-glob.txt | grep -q -F 'Could not find any test files matching pat # In windows, the shell passes globs unexpanded, executables do expansion if they support it. # Adding single-quotes around the glob below makes bash pass glob unexpanded, # allowing us to test windows-style globbing in bash. -../../../bin/mocha -R json-stream './*.js' > /tmp/mocha-glob.txt || { +../../bin/mocha -R json-stream './*.js' > /tmp/mocha-glob.txt || { echo Globbing './*.js' in `pwd` failed. exit 1 } @@ -53,7 +53,7 @@ cat /tmp/mocha-glob.txt | grep -q -F '["end",{"suites":1,"tests":1,"passes":1,"p exit 1 } -../../../bin/mocha -R json-stream './*-none.js' 2> /tmp/mocha-glob.txt && { +../../bin/mocha -R json-stream './*-none.js' 2> /tmp/mocha-glob.txt && { echo Globbing './*-none.js' in `pwd` failed. exit 1 } diff --git a/test/acceptance/glob/glob.spec.js b/test/glob/glob.spec.js similarity index 100% rename from test/acceptance/glob/glob.spec.js rename to test/glob/glob.spec.js diff --git a/test/acceptance/interfaces/bdd.spec.js b/test/interfaces/bdd.spec.js similarity index 100% rename from test/acceptance/interfaces/bdd.spec.js rename to test/interfaces/bdd.spec.js diff --git a/test/acceptance/interfaces/exports.spec.js b/test/interfaces/exports.spec.js similarity index 100% rename from test/acceptance/interfaces/exports.spec.js rename to test/interfaces/exports.spec.js diff --git a/test/acceptance/interfaces/qunit.spec.js b/test/interfaces/qunit.spec.js similarity index 100% rename from test/acceptance/interfaces/qunit.spec.js rename to test/interfaces/qunit.spec.js diff --git a/test/acceptance/interfaces/tdd.spec.js b/test/interfaces/tdd.spec.js similarity index 100% rename from test/acceptance/interfaces/tdd.spec.js rename to test/interfaces/tdd.spec.js diff --git a/test/jsapi/index.js b/test/jsapi/index.js index 42133578e0..430a205250 100644 --- a/test/jsapi/index.js +++ b/test/jsapi/index.js @@ -12,16 +12,16 @@ var mocha = new Mocha({ // mocha.reporter('spec'); require('should'); -mocha.addFile('test/suite.spec.js'); -mocha.addFile('test/runner.spec.js'); -mocha.addFile('test/runnable.spec.js'); -mocha.addFile('test/hook-sync.spec.js'); -mocha.addFile('test/hook-sync-nested.spec.js'); -mocha.addFile('test/hook-async.spec.js'); -mocha.addFile('test/acceptance/duration.spec.js'); -mocha.addFile('test/acceptance/fs.spec.js'); -mocha.addFile('test/acceptance/globals.spec.js'); -mocha.addFile('test/acceptance/timeout.spec.js'); +mocha.addFile('test/unit/suite.spec.js'); +mocha.addFile('test/unit/runner.spec.js'); +mocha.addFile('test/unit/runnable.spec.js'); +mocha.addFile('test/unit/hook-sync.spec.js'); +mocha.addFile('test/unit/hook-sync-nested.spec.js'); +mocha.addFile('test/unit/hook-async.spec.js'); +mocha.addFile('test/unit/duration.spec.js'); +mocha.addFile('test/node-unit/fs.spec.js'); +mocha.addFile('test/unit/globals.spec.js'); +mocha.addFile('test/unit/timeout.spec.js'); mocha.run(function () { console.log('done'); diff --git a/test/acceptance/misc/exit.spec.js b/test/misc/exit.spec.js similarity index 100% rename from test/acceptance/misc/exit.spec.js rename to test/misc/exit.spec.js diff --git a/test/acceptance/misc/many.spec.js b/test/misc/many.spec.js similarity index 100% rename from test/acceptance/misc/many.spec.js rename to test/misc/many.spec.js diff --git a/test/acceptance/misc/nontty.spec.js b/test/misc/nontty.spec.js similarity index 100% rename from test/acceptance/misc/nontty.spec.js rename to test/misc/nontty.spec.js diff --git a/test/acceptance/misc/only/bdd-require.spec.js b/test/misc/only/bdd-require.spec.js similarity index 90% rename from test/acceptance/misc/only/bdd-require.spec.js rename to test/misc/only/bdd-require.spec.js index 14710c4cd2..1c90d7acda 100644 --- a/test/acceptance/misc/only/bdd-require.spec.js +++ b/test/misc/only/bdd-require.spec.js @@ -2,7 +2,7 @@ /* jshint node: true */ -var mocha = require('../../../../lib/mocha'); +var mocha = require('../../../lib/mocha'); var beforeEach = mocha.beforeEach; var it = mocha.it; diff --git a/test/acceptance/misc/only/bdd.spec.js b/test/misc/only/bdd.spec.js similarity index 100% rename from test/acceptance/misc/only/bdd.spec.js rename to test/misc/only/bdd.spec.js diff --git a/test/acceptance/misc/only/global/bdd.spec.js b/test/misc/only/global/bdd.spec.js similarity index 100% rename from test/acceptance/misc/only/global/bdd.spec.js rename to test/misc/only/global/bdd.spec.js diff --git a/test/acceptance/misc/only/global/qunit.spec.js b/test/misc/only/global/qunit.spec.js similarity index 100% rename from test/acceptance/misc/only/global/qunit.spec.js rename to test/misc/only/global/qunit.spec.js diff --git a/test/acceptance/misc/only/global/tdd.spec.js b/test/misc/only/global/tdd.spec.js similarity index 100% rename from test/acceptance/misc/only/global/tdd.spec.js rename to test/misc/only/global/tdd.spec.js diff --git a/test/acceptance/misc/only/qunit.spec.js b/test/misc/only/qunit.spec.js similarity index 100% rename from test/acceptance/misc/only/qunit.spec.js rename to test/misc/only/qunit.spec.js diff --git a/test/acceptance/misc/only/tdd.spec.js b/test/misc/only/tdd.spec.js similarity index 100% rename from test/acceptance/misc/only/tdd.spec.js rename to test/misc/only/tdd.spec.js diff --git a/test/color.spec.js b/test/node-unit/color.spec.js similarity index 100% rename from test/color.spec.js rename to test/node-unit/color.spec.js diff --git a/test/acceptance/file-utils.spec.js b/test/node-unit/file-utils.spec.js similarity index 100% rename from test/acceptance/file-utils.spec.js rename to test/node-unit/file-utils.spec.js diff --git a/test/acceptance/fs.spec.js b/test/node-unit/fs.spec.js similarity index 100% rename from test/acceptance/fs.spec.js rename to test/node-unit/fs.spec.js diff --git a/test/http-meta-2.spec.js b/test/node-unit/http-meta-2.spec.js similarity index 100% rename from test/http-meta-2.spec.js rename to test/node-unit/http-meta-2.spec.js diff --git a/test/http-meta.spec.js b/test/node-unit/http-meta.spec.js similarity index 100% rename from test/http-meta.spec.js rename to test/node-unit/http-meta.spec.js diff --git a/test/acceptance/http.spec.js b/test/node-unit/http.spec.js similarity index 100% rename from test/acceptance/http.spec.js rename to test/node-unit/http.spec.js diff --git a/test/node-unit/stack-trace-filter.spec.js b/test/node-unit/stack-trace-filter.spec.js new file mode 100644 index 0000000000..72ce67a206 --- /dev/null +++ b/test/node-unit/stack-trace-filter.spec.js @@ -0,0 +1,156 @@ +'use strict'; + +var path = require('path'); +var utils = require('../../lib/utils'); + +describe('stackTraceFilter()', function () { + describe('on node', function () { + var filter = utils.stackTraceFilter(); + + describe('on POSIX OS', function () { + before(function () { + if (path.sep !== '/') { + this.skip(); + } + }); + + it('should get a stack-trace as a string and prettify it', function () { + var stack = [ + 'AssertionError: foo bar', + 'at EventEmitter. (/usr/local/dev/test.js:16:12)', + 'at Context. (/usr/local/dev/test.js:19:5)', + 'Test.Runnable.run (/usr/local/lib/node_modules/mocha/lib/runnable.js:244:7)', + 'Runner.runTest (/usr/local/lib/node_modules/mocha/lib/runner.js:374:10)', + '/usr/local/lib/node_modules/mocha/lib/runner.js:452:12', + 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:299:14)', + '/usr/local/lib/node_modules/mocha/lib/runner.js:309:7', + 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:248:23)', + 'Immediate._onImmediate (/usr/local/lib/node_modules/mocha/lib/runner.js:276:5)', + 'at processImmediate [as _immediateCallback] (timers.js:321:17)' + ]; + filter(stack.join('\n')) + .should + .equal(stack.slice(0, 3) + .join('\n')); + + stack = [ + 'AssertionError: bar baz', + 'at /usr/local/dev/some-test-file.js:25:8', + 'at tryCatcher (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/util.js:24:31)', + 'at Promise._resolveFromResolver (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:439:31)', + 'at new Promise (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:53:37)', + 'at yourFunction (/usr/local/dev/own/tmp/test1.js:24:13)', + 'at Context. (/usr/local/dev/some-test-file:30:4)', + 'Test.Runnable.run (/usr/local/lib/node_modules/mocha/lib/runnable.js:218:15)', + 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:248:23)', + 'Immediate._onImmediate (/usr/local/lib/node_modules/mocha/lib/runner.js:276:5)', + 'at processImmediate [as _immediateCallback] (timers.js:321:17)' + ]; + + filter(stack.join('\n')) + .should + .equal(stack.slice(0, 7) + .join('\n')); + }); + + it('does not ignore other bower_components and components', function () { + var stack = [ + 'Error: failed', + 'at assert (index.html:11:26)', + 'at Context. (test.js:17:18)', + 'at bower_components/should/should.js:4827:7', + 'at next (file:///.../bower_components/should/should.js:4766:23)', + 'at components/should/5.0.0/should.js:4827:7', + 'at next (file:///.../components/should/5.0.0/should.js:4766:23)', + 'at file:///.../bower_components/mocha/mocha.js:4794:5', + 'at timeslice (.../components/mocha/mocha.js:6218:27)', + 'at Test.require.register.Runnable.run (file:///.../components/mochajs/mocha/2.1.0/mocha.js:4463:15)', + 'at Runner.require.register.Runner.runTest (file:///.../components/mochajs/mocha/2.1.0/mocha.js:4892:10)', + 'at file:///.../components/mochajs/mocha/2.1.0/mocha.js:4970:12', + 'at next (file:///.../components/mochajs/mocha/2.1.0/mocha.js:4817:14)' + ]; + filter(stack.join('\n')) + .should + .equal(stack.slice(0, 7) + .join('\n')); + }); + + it('should replace absolute with relative paths', function () { + var stack = [ + 'Error: ' + process.cwd() + '/bla.js has a problem', + 'at foo (' + process.cwd() + '/foo/index.js:13:226)', + 'at bar (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:11:26)' + ]; + + var expected = [ + 'Error: ' + process.cwd() + '/bla.js has a problem', + 'at foo (foo/index.js:13:226)', + 'at bar (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:11:26)' + ]; + + filter(stack.join('\n')) + .should + .equal(expected.join('\n')); + }); + }); + + describe('on Windows', function () { + before(function () { + if (path.sep === '/') { + this.skip(); + } + }); + + it('should work on Windows', function () { + var stack = [ + 'Error: failed', + 'at Context. (C:\\Users\\ishida\\src\\test\\test\\mytest.js:5:9)', + 'at callFn (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runnable.js:326:21)', + 'at Test.Runnable.run (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runnable.js:319:7)', + 'at Runner.runTest (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:422:10)', + 'at C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:528:12', + 'at next (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:342:14)', + 'at C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:352:7', + 'at next (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:284:14)', + 'at Immediate._onImmediate (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:320:5)' + ]; + filter(stack.join('\n')) + .should + .equal(stack.slice(0, 2) + .join('\n')); + }); + }); + }); + + describe('on browser', function () { + var filter; + before(function () { + global.document = true; + global.location = {href: 'localhost:3000/foo/bar/index.html'}; + filter = utils.stackTraceFilter(); + }); + it('does not strip out other bower_components', function () { + var stack = [ + 'Error: failed', + 'at assert (index.html:11:26)', + 'at Context. (test.js:17:18)', + 'at bower_components/should/should.js:4827:7', + 'at next (bower_components/should/should.js:4766:23)', + 'at components/should/5.0.0/should.js:4827:7', + 'at next (components/should/5.0.0/should.js:4766:23)', + 'at Runner.require.register.Runner.runTest (node_modules/mocha.js:4892:10)', + 'at localhost:3000/foo/bar/node_modules/mocha.js:4970:12', + 'at next (node_modules/mocha.js:4817:14)' + ]; + filter(stack.join('\n')) + .should + .equal(stack.slice(0, 7) + .join('\n')); + }); + + after(function () { + delete global.document; + delete global.location; + }); + }); +}); diff --git a/test/acceptance/require/a.js b/test/require/a.js similarity index 100% rename from test/acceptance/require/a.js rename to test/require/a.js diff --git a/test/acceptance/require/b.coffee b/test/require/b.coffee similarity index 100% rename from test/acceptance/require/b.coffee rename to test/require/b.coffee diff --git a/test/acceptance/require/c.js b/test/require/c.js similarity index 100% rename from test/acceptance/require/c.js rename to test/require/c.js diff --git a/test/acceptance/require/d.coffee b/test/require/d.coffee similarity index 100% rename from test/acceptance/require/d.coffee rename to test/require/d.coffee diff --git a/test/acceptance/require/require.spec.js b/test/require/require.spec.js similarity index 100% rename from test/acceptance/require/require.spec.js rename to test/require/require.spec.js diff --git a/test/acceptance/context.spec.js b/test/unit/context.spec.js similarity index 100% rename from test/acceptance/context.spec.js rename to test/unit/context.spec.js diff --git a/test/acceptance/duration.spec.js b/test/unit/duration.spec.js similarity index 100% rename from test/acceptance/duration.spec.js rename to test/unit/duration.spec.js diff --git a/test/acceptance/globals.spec.js b/test/unit/globals.spec.js similarity index 100% rename from test/acceptance/globals.spec.js rename to test/unit/globals.spec.js diff --git a/test/grep.spec.js b/test/unit/grep.spec.js similarity index 98% rename from test/grep.spec.js rename to test/unit/grep.spec.js index dd21cf0090..bb620f9ba2 100644 --- a/test/grep.spec.js +++ b/test/unit/grep.spec.js @@ -1,6 +1,6 @@ 'use strict'; -var Mocha = require('../'); +var Mocha = require('../../lib/mocha'); describe('Mocha', function () { describe('"grep" option', function () { diff --git a/test/hook-async.spec.js b/test/unit/hook-async.spec.js similarity index 100% rename from test/hook-async.spec.js rename to test/unit/hook-async.spec.js diff --git a/test/hook-sync-nested.spec.js b/test/unit/hook-sync-nested.spec.js similarity index 100% rename from test/hook-sync-nested.spec.js rename to test/unit/hook-sync-nested.spec.js diff --git a/test/hook-sync.spec.js b/test/unit/hook-sync.spec.js similarity index 100% rename from test/hook-sync.spec.js rename to test/unit/hook-sync.spec.js diff --git a/test/hook-timeout.spec.js b/test/unit/hook-timeout.spec.js similarity index 100% rename from test/hook-timeout.spec.js rename to test/unit/hook-timeout.spec.js diff --git a/test/mocha.spec.js b/test/unit/mocha.spec.js similarity index 95% rename from test/mocha.spec.js rename to test/unit/mocha.spec.js index 618742cdbd..af0c44a730 100644 --- a/test/mocha.spec.js +++ b/test/unit/mocha.spec.js @@ -1,6 +1,6 @@ 'use strict'; -var Mocha = require('../'); +var Mocha = require('../../lib/mocha'); var Test = Mocha.Test; describe('Mocha', function () { diff --git a/test/ms.spec.js b/test/unit/ms.spec.js similarity index 98% rename from test/ms.spec.js rename to test/unit/ms.spec.js index 26f5c30209..6ceab5d409 100644 --- a/test/ms.spec.js +++ b/test/unit/ms.spec.js @@ -1,5 +1,5 @@ 'use strict'; -var ms = require('../lib/ms'); +var ms = require('../../lib/ms'); describe('.ms()', function () { // Helpers diff --git a/test/acceptance/overspecified-async.spec.js b/test/unit/overspecified-async.spec.js similarity index 100% rename from test/acceptance/overspecified-async.spec.js rename to test/unit/overspecified-async.spec.js diff --git a/test/acceptance/required-tokens.spec.js b/test/unit/required-tokens.spec.js similarity index 100% rename from test/acceptance/required-tokens.spec.js rename to test/unit/required-tokens.spec.js diff --git a/test/acceptance/root.spec.js b/test/unit/root.spec.js similarity index 100% rename from test/acceptance/root.spec.js rename to test/unit/root.spec.js diff --git a/test/runnable.spec.js b/test/unit/runnable.spec.js similarity index 96% rename from test/runnable.spec.js rename to test/unit/runnable.spec.js index 67cfcca38a..59bffff7be 100644 --- a/test/runnable.spec.js +++ b/test/unit/runnable.spec.js @@ -1,6 +1,6 @@ 'use strict'; -var mocha = require('../'); +var mocha = require('../../lib/mocha'); var utils = mocha.utils; var Runnable = mocha.Runnable; @@ -183,7 +183,9 @@ describe('Runnable(title, fn)', function () { describe('when timeouts are disabled', function () { it('should not error with timeout', function (done) { var test = new Runnable('foo', function (done) { - setTimeout(process.nextTick.bind(undefined, done), 2); + setTimeout(function () { + setTimeout(done); + }, 2); }); test.timeout(1); test.enableTimeouts(false); @@ -195,7 +197,7 @@ describe('Runnable(title, fn)', function () { describe('without error', function () { it('should invoke the callback', function (done) { var test = new Runnable('foo', function (done) { - process.nextTick(done); + setTimeout(done); }); test.run(done); @@ -210,9 +212,9 @@ describe('Runnable(title, fn)', function () { var test = new Runnable('foo', function (done) { process.nextTick(done); - process.nextTick(done); - process.nextTick(done); - process.nextTick(done); + setTimeout(done); + setTimeout(done); + setTimeout(done); }); test.on('error', function (err) { @@ -236,10 +238,10 @@ describe('Runnable(title, fn)', function () { var test = new Runnable('foo', function (done) { done(new Error('fail')); - process.nextTick(done); + setTimeout(done); done(new Error('fail')); - process.nextTick(done); - process.nextTick(done); + setTimeout(done); + setTimeout(done); }); test.on('error', function (err) { @@ -359,7 +361,7 @@ describe('Runnable(title, fn)', function () { describe('when the promise is fulfilled with no value', function () { var fulfilledPromise = { then: function (fulfilled, rejected) { - process.nextTick(fulfilled); + setTimeout(fulfilled); } }; @@ -375,7 +377,7 @@ describe('Runnable(title, fn)', function () { describe('when the promise is fulfilled with a value', function () { var fulfilledPromise = { then: function (fulfilled, rejected) { - process.nextTick(function () { + setTimeout(function () { fulfilled({}); }); } @@ -394,7 +396,7 @@ describe('Runnable(title, fn)', function () { var expectedErr = new Error('fail'); var rejectedPromise = { then: function (fulfilled, rejected) { - process.nextTick(function () { + setTimeout(function () { rejected(expectedErr); }); } @@ -416,7 +418,7 @@ describe('Runnable(title, fn)', function () { var expectedErr = new Error('Promise rejected with no or falsy reason'); var rejectedPromise = { then: function (fulfilled, rejected) { - process.nextTick(function () { + setTimeout(function () { rejected(); }); } diff --git a/test/runner.spec.js b/test/unit/runner.spec.js similarity index 99% rename from test/runner.spec.js rename to test/unit/runner.spec.js index 7c69846ec8..c3dc379dfb 100644 --- a/test/runner.spec.js +++ b/test/unit/runner.spec.js @@ -1,6 +1,6 @@ 'use strict'; -var mocha = require('../'); +var mocha = require('../../lib/mocha'); var Suite = mocha.Suite; var Runner = mocha.Runner; var Test = mocha.Test; diff --git a/test/suite.spec.js b/test/unit/suite.spec.js similarity index 99% rename from test/suite.spec.js rename to test/unit/suite.spec.js index 4cb62dd290..4233f957d6 100644 --- a/test/suite.spec.js +++ b/test/unit/suite.spec.js @@ -1,6 +1,6 @@ 'use strict'; -var mocha = require('../'); +var mocha = require('../../lib/mocha'); var Suite = mocha.Suite; var Test = mocha.Test; diff --git a/test/test.spec.js b/test/unit/test.spec.js similarity index 98% rename from test/test.spec.js rename to test/unit/test.spec.js index 73c09b3b06..455cfe04ae 100644 --- a/test/test.spec.js +++ b/test/unit/test.spec.js @@ -1,6 +1,6 @@ 'use strict'; -var mocha = require('../'); +var mocha = require('../../lib/mocha'); var should = require('should'); var Test = mocha.Test; diff --git a/test/acceptance/throw.spec.js b/test/unit/throw.spec.js similarity index 100% rename from test/acceptance/throw.spec.js rename to test/unit/throw.spec.js diff --git a/test/acceptance/timeout.spec.js b/test/unit/timeout.spec.js similarity index 100% rename from test/acceptance/timeout.spec.js rename to test/unit/timeout.spec.js diff --git a/test/acceptance/utils.spec.js b/test/unit/utils.spec.js similarity index 71% rename from test/acceptance/utils.spec.js rename to test/unit/utils.spec.js index 545bdfd265..85b1950727 100644 --- a/test/acceptance/utils.spec.js +++ b/test/unit/utils.spec.js @@ -6,13 +6,80 @@ var JSON = require('json3'); describe('lib/utils', function () { describe('clean', function () { + it('should remove the wrapping function declaration', function () { + utils.clean('function (one, two, three) {\n//code\n}') + .should + .equal('//code'); + }); + + it('should handle newlines in the function declaration', function () { + utils.clean('function (one, two, three)\n {\n//code\n}') + .should + .equal('//code'); + }); + + it('should remove space character indentation from the function body', + function () { + utils.clean(' //line1\n //line2') + .should + .equal('//line1\n //line2'); + }); + + it('should remove tab character indentation from the function body', + function () { + utils.clean('\t//line1\n\t\t//line2') + .should + .equal('//line1\n\t//line2'); + }); + + it('should handle functions with tabs in their declarations', function () { + utils.clean('function\t(\t)\t{\n//code\n}') + .should + .equal('//code'); + }); + + it('should handle named functions without space after name', function () { + utils.clean('function withName() {\n//code\n}') + .should + .equal('//code'); + }); + + it('should handle named functions with space after name', function () { + utils.clean('function withName () {\n//code\n}') + .should + .equal('//code'); + }); + + it( + 'should handle functions with no space between the end and the closing brace', + function () { + utils.clean('function() {/*code*/}') + .should + .equal('/*code*/'); + }); + + it('should handle functions with parentheses in the same line', + function () { + utils.clean('function() { if (true) { /* code */ } }') + .should + .equal('if (true) { /* code */ }'); + }); + + it('should handle empty functions', function () { + utils.clean('function() {}') + .should + .equal(''); + }); + it('should format a single line test function', function () { var fn = [ 'function () {', ' var a = 1;', '}' ].join('\n'); - expect(utils.clean(fn)).to.equal('var a = 1;'); + expect(utils.clean(fn)) + .to + .equal('var a = 1;'); }); it('should format a multi line test indented with spaces', function () { @@ -23,7 +90,9 @@ describe('lib/utils', function () { ' var b = 2;', ' var c = 3; }' ].join('\n'); - expect(utils.clean(fn)).to.equal('var a = 1;\n var b = 2;\nvar c = 3;'); + expect(utils.clean(fn)) + .to + .equal('var a = 1;\n var b = 2;\nvar c = 3;'); }); it('should format a multi line test indented with tabs', function () { @@ -34,7 +103,9 @@ describe('lib/utils', function () { '\t}', '}' ].join('\n'); - expect(utils.clean(fn)).to.equal('if (true) {\n\tvar a = 1;\n}'); + expect(utils.clean(fn)) + .to + .equal('if (true) {\n\tvar a = 1;\n}'); }); it('should format functions saved in windows style - spaces', function () { @@ -45,7 +116,9 @@ describe('lib/utils', function () { ' } while (false);', ' }' ].join('\r\n'); - expect(utils.clean(fn)).to.equal('do {\n "nothing";\n} while (false);'); + expect(utils.clean(fn)) + .to + .equal('do {\n "nothing";\n} while (false);'); }); it('should format functions saved in windows style - tabs', function () { @@ -58,7 +131,9 @@ describe('lib/utils', function () { '\t}', '}' ].join('\r\n'); - expect(utils.clean(fn)).to.equal('if (false) {\n\tvar json = {\n\t\tone : 1\n\t};\n}'); + expect(utils.clean(fn)) + .to + .equal('if (false) {\n\tvar json = {\n\t\tone : 1\n\t};\n}'); }); it('should format es6 arrow functions', function () { @@ -67,12 +142,16 @@ describe('lib/utils', function () { ' var a = 1;', '}' ].join('\n'); - expect(utils.clean(fn)).to.equal('var a = 1;'); + expect(utils.clean(fn)) + .to + .equal('var a = 1;'); }); it('should format es6 arrow functions with implicit return', function () { var fn = '() => foo()'; - expect(utils.clean(fn)).to.equal('foo()'); + expect(utils.clean(fn)) + .to + .equal('foo()'); }); }); @@ -415,4 +494,129 @@ describe('lib/utils', function () { Object.prototype.toString = toString; }); }); + + describe('isBuffer()', function () { + var isBuffer = utils.isBuffer; + it('should test if object is a Buffer', function () { + isBuffer(new Buffer([0x01])) + .should + .equal(true); + isBuffer({}) + .should + .equal(false); + }); + }); + + describe('map()', function () { + var map = utils.map; + it('should behave same as Array.prototype.map', function () { + var arr = [ + 1, + 2, + 3 + ]; + map(arr, JSON.stringify) + .should + .eql(arr.map(JSON.stringify)); + }); + + it('should call the callback with 3 arguments[currentValue, index, array]', + function () { + var index = 0; + map([ + 1, + 2, + 3 + ], function (e, i, arr) { + e.should.equal(arr[index]); + i.should.equal(index++); + }); + }); + + it('should apply with the given scope', function () { + var scope = {}; + map([ + 'a', + 'b', + 'c' + ], function () { + this.should.equal(scope); + }, scope); + }); + }); + + describe('some()', function () { + var some = utils.some; + + it( + 'should return true when some array elements pass the check of the fn parameter', + function () { + var result = some([ + 'a', + 'b', + 'c' + ], function (e) { + return e === 'b'; + }); + result.should.eql(true); + }); + + it( + 'should return false when none of the array elements pass the check of the fn parameter', + function () { + var result = some([ + 'a', + 'b', + 'c' + ], function (e) { + return e === 'd'; + }); + result.should.eql(false); + }); + }); + + describe('parseQuery()', function () { + var parseQuery = utils.parseQuery; + it('should get queryString and return key-value object', function () { + parseQuery('?foo=1&bar=2&baz=3') + .should + .eql({ + foo: '1', + bar: '2', + baz: '3' + }); + + parseQuery('?r1=^@(?!.*\\)$)&r2=m{2}&r3=^co.*') + .should + .eql({ + r1: '^@(?!.*\\)$)', + r2: 'm{2}', + r3: '^co.*' + }); + }); + + it('should parse "+" as a space', function () { + parseQuery('?grep=foo+bar') + .should + .eql({grep: 'foo bar'}); + }); + }); + + 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; + }); + }); }); diff --git a/test/utils.spec.js b/test/utils.spec.js deleted file mode 100644 index 2eaf908cd6..0000000000 --- a/test/utils.spec.js +++ /dev/null @@ -1,285 +0,0 @@ -'use strict'; - -var mocha = require('..'); -var utils = mocha.utils; -var path = require('path'); -var JSON = require('json3'); - -describe('utils', function () { - describe('.clean()', function () { - var clean = utils.clean; - it('should remove the wrapping function declaration', function () { - clean('function (one, two, three) {\n//code\n}').should.equal('//code'); - }); - - it('should handle newlines in the function declaration', function () { - clean('function (one, two, three)\n {\n//code\n}').should.equal('//code'); - }); - - it('should remove space character indentation from the function body', function () { - clean(' //line1\n //line2').should.equal('//line1\n //line2'); - }); - - it('should remove tab character indentation from the function body', function () { - clean('\t//line1\n\t\t//line2').should.equal('//line1\n\t//line2'); - }); - - it('should handle functions with tabs in their declarations', function () { - clean('function\t(\t)\t{\n//code\n}').should.equal('//code'); - }); - - it('should handle named functions without space after name', function () { - clean('function withName() {\n//code\n}').should.equal('//code'); - }); - - it('should handle named functions with space after name', function () { - clean('function withName () {\n//code\n}').should.equal('//code'); - }); - - it('should handle functions with no space between the end and the closing brace', function () { - clean('function() {/*code*/}').should.equal('/*code*/'); - }); - - it('should handle functions with parentheses in the same line', function () { - clean('function() { if (true) { /* code */ } }').should.equal('if (true) { /* code */ }'); - }); - - it('should handle empty functions', function () { - clean('function() {}').should.equal(''); - }); - }); - - describe('.isBuffer()', function () { - var isBuffer = utils.isBuffer; - it('should test if object is a Buffer', function () { - isBuffer(new Buffer([0x01])).should.equal(true); - isBuffer({}).should.equal(false); - }); - }); - - describe('.map()', function () { - var map = utils.map; - it('should behave same as Array.prototype.map', function () { - var arr = [1, 2, 3]; - map(arr, JSON.stringify).should.eql(arr.map(JSON.stringify)); - }); - - it('should call the callback with 3 arguments[currentValue, index, array]', function () { - var index = 0; - map([1, 2, 3], function (e, i, arr) { - e.should.equal(arr[index]); - i.should.equal(index++); - }); - }); - - it('should apply with the given scope', function () { - var scope = {}; - map(['a', 'b', 'c'], function () { - this.should.equal(scope); - }, scope); - }); - }); - - describe('.some()', function () { - var some = utils.some; - - it('should return true when some array elements pass the check of the fn parameter', function () { - var result = some(['a', 'b', 'c'], function (e) { - return e === 'b'; - }); - result.should.eql(true); - }); - - it('should return false when none of the array elements pass the check of the fn parameter', function () { - var result = some(['a', 'b', 'c'], function (e) { - return e === 'd'; - }); - result.should.eql(false); - }); - }); - - describe('.parseQuery()', function () { - var parseQuery = utils.parseQuery; - it('should get queryString and return key-value object', function () { - parseQuery('?foo=1&bar=2&baz=3').should.eql({ - foo: '1', - bar: '2', - baz: '3' - }); - - parseQuery('?r1=^@(?!.*\\)$)&r2=m{2}&r3=^co.*').should.eql({ - r1: '^@(?!.*\\)$)', - r2: 'm{2}', - r3: '^co.*' - }); - }); - - it('should parse "+" as a space', function () { - parseQuery('?grep=foo+bar').should.eql({grep: 'foo bar'}); - }); - }); - - describe('.stackTraceFilter()', function () { - describe('on node', function () { - var filter = utils.stackTraceFilter(); - - describe('on POSIX OS', function () { - before(function () { - if (path.sep !== '/') { - this.skip(); - } - }); - - it('should get a stack-trace as a string and prettify it', function () { - var stack = [ - 'AssertionError: foo bar', - 'at EventEmitter. (/usr/local/dev/test.js:16:12)', - 'at Context. (/usr/local/dev/test.js:19:5)', - 'Test.Runnable.run (/usr/local/lib/node_modules/mocha/lib/runnable.js:244:7)', - 'Runner.runTest (/usr/local/lib/node_modules/mocha/lib/runner.js:374:10)', - '/usr/local/lib/node_modules/mocha/lib/runner.js:452:12', - 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:299:14)', - '/usr/local/lib/node_modules/mocha/lib/runner.js:309:7', - 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:248:23)', - 'Immediate._onImmediate (/usr/local/lib/node_modules/mocha/lib/runner.js:276:5)', - 'at processImmediate [as _immediateCallback] (timers.js:321:17)' - ]; - filter(stack.join('\n')) - .should - .equal(stack.slice(0, 3) - .join('\n')); - - stack = [ - 'AssertionError: bar baz', - 'at /usr/local/dev/some-test-file.js:25:8', - 'at tryCatcher (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/util.js:24:31)', - 'at Promise._resolveFromResolver (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:439:31)', - 'at new Promise (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:53:37)', - 'at yourFunction (/usr/local/dev/own/tmp/test1.js:24:13)', - 'at Context. (/usr/local/dev/some-test-file:30:4)', - 'Test.Runnable.run (/usr/local/lib/node_modules/mocha/lib/runnable.js:218:15)', - 'next (/usr/local/lib/node_modules/mocha/lib/runner.js:248:23)', - 'Immediate._onImmediate (/usr/local/lib/node_modules/mocha/lib/runner.js:276:5)', - 'at processImmediate [as _immediateCallback] (timers.js:321:17)' - ]; - - filter(stack.join('\n')) - .should - .equal(stack.slice(0, 7) - .join('\n')); - }); - - it('does not ignore other bower_components and components', - function () { - var stack = [ - 'Error: failed', - 'at assert (index.html:11:26)', - 'at Context. (test.js:17:18)', - 'at bower_components/should/should.js:4827:7', - 'at next (file:///.../bower_components/should/should.js:4766:23)', - 'at components/should/5.0.0/should.js:4827:7', - 'at next (file:///.../components/should/5.0.0/should.js:4766:23)', - 'at file:///.../bower_components/mocha/mocha.js:4794:5', - 'at timeslice (.../components/mocha/mocha.js:6218:27)', - 'at Test.require.register.Runnable.run (file:///.../components/mochajs/mocha/2.1.0/mocha.js:4463:15)', - 'at Runner.require.register.Runner.runTest (file:///.../components/mochajs/mocha/2.1.0/mocha.js:4892:10)', - 'at file:///.../components/mochajs/mocha/2.1.0/mocha.js:4970:12', - 'at next (file:///.../components/mochajs/mocha/2.1.0/mocha.js:4817:14)' - ]; - filter(stack.join('\n')) - .should - .equal(stack.slice(0, 7) - .join('\n')); - }); - - it('should replace absolute with relative paths', function () { - var stack = [ - 'Error: ' + process.cwd() + '/bla.js has a problem', - 'at foo (' + process.cwd() + '/foo/index.js:13:226)', - 'at bar (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:11:26)' - ]; - - var expected = [ - 'Error: ' + process.cwd() + '/bla.js has a problem', - 'at foo (foo/index.js:13:226)', - 'at bar (/usr/local/dev/own/tmp/node_modules/bluebird/js/main/promise.js:11:26)' - ]; - - filter(stack.join('\n')) - .should - .equal(expected.join('\n')); - }); - }); - - describe('on Windows', function () { - before(function () { - if (path.sep === '/') { - this.skip(); - } - }); - - it('should work on Windows', function () { - var stack = [ - 'Error: failed', - 'at Context. (C:\\Users\\ishida\\src\\test\\test\\mytest.js:5:9)', - 'at callFn (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runnable.js:326:21)', - 'at Test.Runnable.run (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runnable.js:319:7)', - 'at Runner.runTest (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:422:10)', - 'at C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:528:12', - 'at next (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:342:14)', - 'at C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:352:7', - 'at next (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:284:14)', - 'at Immediate._onImmediate (C:\\Users\\ishida\\src\\test\\node_modules\\mocha\\lib\\runner.js:320:5)' - ]; - filter(stack.join('\n')) - .should - .equal(stack.slice(0, 2) - .join('\n')); - }); - }); - }); - - describe('on browser', function () { - var filter; - before(function () { - global.document = true; - global.location = { href: 'localhost:3000/foo/bar/index.html' }; - filter = utils.stackTraceFilter(); - }); - it('does not strip out other bower_components', function () { - var stack = [ - 'Error: failed', - 'at assert (index.html:11:26)', - 'at Context. (test.js:17:18)', - 'at bower_components/should/should.js:4827:7', - 'at next (bower_components/should/should.js:4766:23)', - 'at components/should/5.0.0/should.js:4827:7', - 'at next (components/should/5.0.0/should.js:4766:23)', - 'at Runner.require.register.Runner.runTest (node_modules/mocha.js:4892:10)', - 'at localhost:3000/foo/bar/node_modules/mocha.js:4970:12', - 'at next (node_modules/mocha.js:4817:14)' - ]; - filter(stack.join('\n')).should.equal(stack.slice(0, 7).join('\n')); - }); - - after(function () { - delete global.document; - delete global.location; - }); - }); - }); - - describe('.isPromise', function () { - it('should return true if the value is Promise-ish', function () { - utils.isPromise({then: function () {}}).should.be.true; - }); - - it('should return false if the value is not an object', function () { - utils.isPromise(1).should.be.false; - }); - - it('should return false if the value is an object w/o a "then" function', function () { - utils.isPromise({}).should.be.false; - }); - }); -}); From 7647e1820a9720e9d4b4f837aef1fd1a69c5b876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20M=C3=BCller?= Date: Mon, 15 May 2017 09:53:28 +0200 Subject: [PATCH 42/42] Linting: enforce unix line endings. Closes #2800 --- .eslintrc.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index d1e5b62c7d..d5673232e7 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -10,3 +10,6 @@ rules: strict: - error - safe + linebreak-style: + - error + - unix