diff --git a/lib/cmd/test.js b/lib/cmd/test.js index 8b15ef43..e4b73f4d 100644 --- a/lib/cmd/test.js +++ b/lib/cmd/test.js @@ -69,6 +69,7 @@ class TestCommand extends Command { /* istanbul ignore next */ if (!Array.isArray(requireArr)) requireArr = [ requireArr ]; + requireArr.unshift(require.resolve('../mocha-clean')); requireArr.push(require.resolve('co-mocha')); if (requireArr.includes('intelli-espower-loader')) { diff --git a/lib/mocha-clean.js b/lib/mocha-clean.js new file mode 100644 index 00000000..10ade833 --- /dev/null +++ b/lib/mocha-clean.js @@ -0,0 +1,27 @@ +// inspired by https://github.com/rstacruz/mocha-clean + +'use strict'; + +const mocha = require('mocha'); +const internal = [ + '(timers.js:', + '(node.js:', + '(module.js:', + '(domain.js:', + 'GeneratorFunctionPrototype.next (native)', + '__mocha_internal__', + 'node_modules', +]; + +// monkey-patch `Runner#fail` to modify stack +const originFn = mocha.Runner.prototype.fail; +mocha.Runner.prototype.fail = function(test, err) { + if (err.stack) { + const stack = err.stack.split('\n').filter(line => { + // console.log(!internal.some(key => line.includes(key)), line); + return !internal.some(key => line.includes(key)); + }); + err.stack = stack.join('\n'); + } + return originFn.call(this, test, err); +}; diff --git a/package.json b/package.json index bc2cf8ea..2daef457 100644 --- a/package.json +++ b/package.json @@ -12,14 +12,14 @@ "co-mocha": "^1.2.0", "common-bin": "^2.4.0", "debug": "^2.6.8", - "detect-port": "^1.1.3", + "detect-port": "^1.2.0", "egg-utils": "^2.2.0", "globby": "^6.1.0", "intelli-espower-loader": "^1.0.1", "istanbul": "^1.1.0-alpha.1", "mocha": "^3.4.2", "mz-modules": "^1.0.0", - "power-assert": "^1.4.2", + "power-assert": "^1.4.3", "ypkgfiles": "^1.4.0" }, "devDependencies": { diff --git a/test/fixtures/test-files/test/clean.test.js b/test/fixtures/test-files/test/clean.test.js new file mode 100644 index 00000000..73a39583 --- /dev/null +++ b/test/fixtures/test-files/test/clean.test.js @@ -0,0 +1,9 @@ +'use strict'; + +describe('clean.test.js', () => { + it('should fail with simplify stack', () => { + [ 1 ].forEach(() => { + throw new Error('clean.test.js throw'); + }); + }); +}); diff --git a/test/lib/cmd/test.test.js b/test/lib/cmd/test.test.js index 45309cb6..a2a9455c 100644 --- a/test/lib/cmd/test.test.js +++ b/test/lib/cmd/test.test.js @@ -3,6 +3,7 @@ const path = require('path'); const coffee = require('coffee'); const mm = require('mm'); +const assert = require('assert'); describe('test/lib/cmd/test.test.js', () => { const eggBin = require.resolve('../../../bin/egg-bin.js'); @@ -22,6 +23,19 @@ describe('test/lib/cmd/test.test.js', () => { .end(done); }); + it('should clean mocha error stack', done => { + coffee.fork(eggBin, [ 'test', 'test/clean.test.js' ], { cwd }) + // .debug() + .end((err, { stdout, code }) => { + assert(stdout.includes('Error: clean.test.js throw')); + assert(stdout.match(/at forEach.*clean\.test\.js:6:13/)); + assert(stdout.match(/at Context\.it.*clean\.test\.js:5:11/)); + assert(stdout.match(/\bat\s+/g).length === 3); + assert(code === 1); + done(err); + }); + }); + it('should ignore node_modules and fixtures', done => { mm(process.env, 'TESTS', 'test/**/*.test.js'); coffee.fork(eggBin, [ 'test' ], { cwd: path.join(__dirname, '../../fixtures/test-files-glob') })