ava 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.js CHANGED
@@ -8,184 +8,21 @@ var debug = require('debug')('ava');
8
8
  var resolveCwd = require('resolve-cwd');
9
9
  var localCLI = resolveCwd('ava/cli');
10
10
 
11
- if (localCLI && localCLI !== __filename) {
11
+ // Use path.relative() to detect local AVA installation,
12
+ // because __filename's case is inconsistent on Windows
13
+ // see https://github.com/nodejs/node/issues/6624
14
+ if (localCLI && path.relative(localCLI, __filename) !== '') {
12
15
  debug('Using local install of AVA');
13
- require(localCLI);
14
- return;
15
- }
16
-
17
- if (debug.enabled) {
18
- require('time-require');
19
- }
20
-
21
- var updateNotifier = require('update-notifier');
22
- var figures = require('figures');
23
- var arrify = require('arrify');
24
- var meow = require('meow');
25
- var Promise = require('bluebird');
26
- var pkgConf = require('pkg-conf');
27
- var isCi = require('is-ci');
28
- var hasFlag = require('has-flag');
29
- var colors = require('./lib/colors');
30
- var verboseReporter = require('./lib/reporters/verbose');
31
- var miniReporter = require('./lib/reporters/mini');
32
- var tapReporter = require('./lib/reporters/tap');
33
- var Logger = require('./lib/logger');
34
- var Watcher = require('./lib/watcher');
35
- var babelConfig = require('./lib/babel-config');
36
- var Api = require('./api');
37
-
38
- // Bluebird specific
39
- Promise.longStackTraces();
40
-
41
- var conf = pkgConf.sync('ava');
42
-
43
- var pkgDir = path.dirname(pkgConf.filepath(conf));
44
-
45
- try {
46
- conf.babel = babelConfig.validate(conf.babel);
47
- } catch (err) {
48
- console.log('\n ' + err.message);
49
- process.exit(1);
50
- }
51
-
52
- var cli = meow([
53
- 'Usage',
54
- ' ava [<file|directory|glob> ...]',
55
- '',
56
- 'Options',
57
- ' --init Add AVA to your project',
58
- ' --fail-fast Stop after first test failure',
59
- ' --serial, -s Run tests serially',
60
- ' --require, -r Module to preload (Can be repeated)',
61
- ' --tap, -t Generate TAP output',
62
- ' --verbose, -v Enable verbose output',
63
- ' --no-cache Disable the transpiler cache',
64
- ' --match, -m Only run tests with matching title (Can be repeated)',
65
- ' --watch, -w Re-run tests when tests and source files change',
66
- ' --source, -S Pattern to match source files so tests can be re-run (Can be repeated)',
67
- ' --timeout, -T Set global timeout',
68
- ' --concurrency, -c Maximum number of test files running at the same time (EXPERIMENTAL)',
69
- '',
70
- 'Examples',
71
- ' ava',
72
- ' ava test.js test2.js',
73
- ' ava test-*.js',
74
- ' ava test',
75
- ' ava --init',
76
- ' ava --init foo.js',
77
- '',
78
- 'Default patterns when no arguments:',
79
- 'test.js test-*.js test/**/*.js **/__tests__/**/*.js **/*.test.js'
80
- ], {
81
- string: [
82
- '_',
83
- 'require',
84
- 'timeout',
85
- 'source',
86
- 'match',
87
- 'concurrency'
88
- ],
89
- boolean: [
90
- 'fail-fast',
91
- 'verbose',
92
- 'serial',
93
- 'tap',
94
- 'watch'
95
- ],
96
- default: conf,
97
- alias: {
98
- t: 'tap',
99
- v: 'verbose',
100
- r: 'require',
101
- s: 'serial',
102
- m: 'match',
103
- w: 'watch',
104
- S: 'source',
105
- T: 'timeout',
106
- c: 'concurrency'
107
- }
108
- });
109
-
110
- updateNotifier({pkg: cli.pkg}).notify();
111
-
112
- if (cli.flags.init) {
113
- require('ava-init')();
114
- return;
115
- }
116
-
117
- if (
118
- ((hasFlag('--watch') || hasFlag('-w')) && (hasFlag('--tap') || hasFlag('-t'))) ||
119
- (conf.watch && conf.tap)
120
- ) {
121
- console.error(' ' + colors.error(figures.cross) + ' The TAP reporter is not available when using watch mode.');
122
- process.exit(1);
123
- }
124
-
125
- var api = new Api({
126
- failFast: cli.flags.failFast,
127
- serial: cli.flags.serial,
128
- require: arrify(cli.flags.require),
129
- cacheEnabled: cli.flags.cache !== false,
130
- explicitTitles: cli.flags.watch,
131
- match: arrify(cli.flags.match),
132
- babelConfig: conf.babel,
133
- resolveTestsFrom: cli.input.length === 0 ? pkgDir : process.cwd(),
134
- timeout: cli.flags.timeout,
135
- concurrency: cli.flags.concurrency ? parseInt(cli.flags.concurrency, 10) : 0
136
- });
137
-
138
- var reporter;
139
-
140
- if (cli.flags.tap && !cli.flags.watch) {
141
- reporter = tapReporter();
142
- } else if (cli.flags.verbose || isCi) {
143
- reporter = verboseReporter();
16
+ require(localCLI); // eslint-disable-line import/no-dynamic-require
144
17
  } else {
145
- reporter = miniReporter({watching: cli.flags.watch});
146
- }
147
-
148
- reporter.api = api;
149
- var logger = new Logger(reporter);
150
-
151
- logger.start();
152
-
153
- api.on('test-run', function (runStatus) {
154
- reporter.api = runStatus;
155
- runStatus.on('test', logger.test);
156
- runStatus.on('error', logger.unhandledError);
157
-
158
- runStatus.on('stdout', logger.stdout);
159
- runStatus.on('stderr', logger.stderr);
160
- });
161
-
162
- var files = cli.input.length ? cli.input : arrify(conf.files);
18
+ if (debug.enabled) {
19
+ require('time-require'); // eslint-disable-line import/no-unassigned-import
20
+ }
163
21
 
164
- if (cli.flags.watch) {
165
22
  try {
166
- var watcher = new Watcher(logger, api, files, arrify(cli.flags.source));
167
- watcher.observeStdin(process.stdin);
23
+ require('./lib/cli').run();
168
24
  } catch (err) {
169
- if (err.name === 'AvaError') {
170
- // An AvaError may be thrown if chokidar is not installed. Log it nicely.
171
- console.error(' ' + colors.error(figures.cross) + ' ' + err.message);
172
- logger.exit(1);
173
- } else {
174
- // Rethrow so it becomes an uncaught exception.
175
- throw err;
176
- }
25
+ console.error('\n ' + err.message);
26
+ process.exit(1);
177
27
  }
178
- } else {
179
- api.run(files)
180
- .then(function (runStatus) {
181
- logger.finish(runStatus);
182
- logger.exit(runStatus.failCount > 0 || runStatus.rejectionCount > 0 || runStatus.exceptionCount > 0 ? 1 : 0);
183
- })
184
- .catch(function (err) {
185
- // Don't swallow exceptions. Note that any expected error should already
186
- // have been logged.
187
- setImmediate(function () {
188
- throw err;
189
- });
190
- });
191
28
  }
package/index.js CHANGED
@@ -1,101 +1,8 @@
1
1
  'use strict';
2
- var path = require('path');
3
- var chalk = require('chalk');
4
- var serializeError = require('./lib/serialize-error');
5
- var globals = require('./lib/globals');
6
- var Runner = require('./lib/runner');
7
- var send = require('./lib/send');
8
2
 
9
- var opts = globals.options;
10
- var runner = new Runner({
11
- serial: opts.serial,
12
- bail: opts.failFast,
13
- match: opts.match
14
- });
15
-
16
- // check if the test is being run without AVA cli
17
- var isForked = typeof process.send === 'function';
18
-
19
- if (!isForked) {
20
- var fp = path.relative('.', process.argv[1]);
21
-
22
- console.log();
23
- console.error('Test files must be run with the AVA CLI:\n\n ' + chalk.grey.dim('$') + ' ' + chalk.cyan('ava ' + fp) + '\n');
24
-
25
- process.exit(1); // eslint-disable-line xo/no-process-exit
3
+ // Ensure the same AVA install is loaded by the test file as by the test worker.
4
+ if (process.env.AVA_PATH && process.env.AVA_PATH !== __dirname) {
5
+ module.exports = require(process.env.AVA_PATH); // eslint-disable-line import/no-dynamic-require
6
+ } else {
7
+ module.exports = require('./lib/main');
26
8
  }
27
-
28
- // note that test files have require('ava')
29
- require('./lib/test-worker').avaRequired = true;
30
-
31
- // if fail-fast is enabled, use this variable to detect
32
- // that no more tests should be logged
33
- var isFailed = false;
34
-
35
- Error.stackTraceLimit = Infinity;
36
-
37
- function test(props) {
38
- if (isFailed) {
39
- return;
40
- }
41
-
42
- var hasError = typeof props.error !== 'undefined';
43
-
44
- // don't display anything if it's a passed hook
45
- if (!hasError && props.type !== 'test') {
46
- return;
47
- }
48
-
49
- if (hasError) {
50
- props.error = serializeError(props.error);
51
- } else {
52
- props.error = null;
53
- }
54
-
55
- send('test', props);
56
-
57
- if (hasError && opts.failFast) {
58
- isFailed = true;
59
- exit();
60
- }
61
- }
62
-
63
- function exit() {
64
- var stats = runner._buildStats();
65
-
66
- send('results', {
67
- stats: stats
68
- });
69
- }
70
-
71
- globals.setImmediate(function () {
72
- var hasExclusive = runner.tests.hasExclusive;
73
- var numberOfTests = runner.tests.tests.concurrent.length + runner.tests.tests.serial.length;
74
-
75
- if (numberOfTests === 0) {
76
- send('no-tests', {avaRequired: true});
77
- return;
78
- }
79
-
80
- send('stats', {
81
- testCount: numberOfTests,
82
- hasExclusive: hasExclusive
83
- });
84
-
85
- runner.on('test', test);
86
-
87
- process.on('ava-run', function (options) {
88
- runner.run(options).then(exit);
89
- });
90
-
91
- process.on('ava-init-exit', function () {
92
- exit();
93
- });
94
- });
95
-
96
- module.exports = runner.test;
97
-
98
- // TypeScript imports the `default` property for
99
- // an ES2015 default import (`import test from 'ava'`)
100
- // See: https://github.com/Microsoft/TypeScript/issues/2242#issuecomment-83694181
101
- module.exports.default = runner.test;
package/index.js.flow ADDED
@@ -0,0 +1,218 @@
1
+ /* @flow */
2
+
3
+ /**
4
+ * Misc Setup Types
5
+ */
6
+
7
+ type PromiseLike<R> = {
8
+ then<U>(
9
+ onFulfill?: (value: R) => Promise<U> | U,
10
+ onReject?: (error: any) => Promise<U> | U
11
+ ): Promise<U>;
12
+ }
13
+
14
+ type ObservableLike = {
15
+ subscribe(observer: (value: {}) => void): void;
16
+ };
17
+
18
+ type SpecialReturnTypes =
19
+ | PromiseLike<any>
20
+ | Iterator<any>
21
+ | ObservableLike;
22
+
23
+ type Constructor = Class<{
24
+ constructor(...args: Array<any>): any
25
+ }>;
26
+
27
+ type ErrorValidator =
28
+ | Constructor
29
+ | RegExp
30
+ | string
31
+ | ((error: any) => boolean);
32
+
33
+ /**
34
+ * Asertion Types
35
+ */
36
+
37
+ type AssertContext = {
38
+ // Passing assertion.
39
+ pass(message?: string): void;
40
+ // Failing assertion.
41
+ fail(message?: string): void;
42
+ // Assert that value is truthy.
43
+ truthy(value: mixed, message?: string): void;
44
+ // Assert that value is falsy.
45
+ falsy(value: mixed, message?: string): void;
46
+ // DEPRECATED, use `truthy`. Assert that value is truthy.
47
+ ok(value: mixed, message?: string): void;
48
+ // DEPRECATED, use `falsy`. Assert that value is falsy.
49
+ notOk(value: mixed, message?: string): void;
50
+ // Assert that value is true.
51
+ true(value: boolean, message?: string): void;
52
+ // Assert that value is false.
53
+ false(value: boolean, message?: string): void;
54
+ // Assert that value is equal to expected.
55
+ is<U>(value: U, expected: U, message?: string): void;
56
+ // Assert that value is not equal to expected.
57
+ not<U>(value: U, expected: U, message?: string): void;
58
+ // Assert that value is deep equal to expected.
59
+ deepEqual<U>(value: U, expected: U, message?: string): void;
60
+ // Assert that value is not deep equal to expected.
61
+ notDeepEqual<U>(value: U, expected: U, message?: string): void;
62
+ // Assert that function throws an error or promise rejects.
63
+ // DEPRECATED, use `deepEqual`. Assert that value is deep equal to expected.
64
+ // @param error Can be a constructor, regex, error message or validation function.
65
+ same<U>(value: U, expected: U, message?: string): void;
66
+ // DEPRECATED use `notDeepEqual`. Assert that value is not deep equal to expected.
67
+ notSame<U>(value: U, expected: U, message?: string): void;
68
+ // Assert that function throws an error or promise rejects.
69
+ // @param error Can be a constructor, regex, error message or validation function.
70
+ throws(value: PromiseLike<mixed>, error?: ErrorValidator, message?: string): Promise<mixed>;
71
+ throws(value: () => void, error?: ErrorValidator, message?: string): mixed;
72
+ // Assert that function doesn't throw an error or promise resolves.
73
+ notThrows<U>(value: PromiseLike<U>, message?: string): Promise<U>;
74
+ notThrows(value: () => void, message?: string): void;
75
+ // Assert that contents matches regex.
76
+ regex(contents: string, regex: RegExp, message?: string): void;
77
+ // Assert that contents does not match regex.
78
+ notRegex(contents: string, regex: RegExp, message?: string): void;
79
+ // Assert that error is falsy.
80
+ ifError(error: any, message?: string): void;
81
+ };
82
+
83
+ /**
84
+ * Context Types
85
+ */
86
+
87
+ type TestContext = AssertContext & {
88
+ plan(count: number): void;
89
+ skip: AssertContext;
90
+ };
91
+ type CallbackTestContext = TestContext & { end(): void; };
92
+ type ContextualTestContext = TestContext & { context: any; };
93
+ type ContextualCallbackTestContext = CallbackTestContext & { context: any; };
94
+
95
+ /**
96
+ * Test Types
97
+ */
98
+
99
+ type Test = (t: TestContext) => SpecialReturnTypes | void;
100
+ type CallbackTest = (t: CallbackTestContext) => void;
101
+ type ContextualTest = (t: ContextualTestContext) => SpecialReturnTypes | void;
102
+ type ContextualCallbackTest = (t: ContextualCallbackTestContext) => void;
103
+
104
+ /**
105
+ * Macro Types
106
+ */
107
+
108
+ type Macro<T> = {
109
+ (t: T, ...args: Array<any>): void;
110
+ title?: (providedTitle: string, ...args: Array<any>) => string;
111
+ };
112
+
113
+ type Macros<T> =
114
+ | Macro<T>
115
+ | Array<Macro<T>>;
116
+
117
+ /**
118
+ * Method Types
119
+ */
120
+
121
+ type TestMethod = {
122
+ ( implementation: Test): void;
123
+ (name: string, implementation: Test): void;
124
+ ( implementation: Macros<TestContext>, ...args: Array<any>): void;
125
+ (name: string, implementation: Macros<TestContext>, ...args: Array<any>): void;
126
+
127
+ serial : TestMethod;
128
+ before : TestMethod;
129
+ after : TestMethod;
130
+ skip : TestMethod;
131
+ todo : TestMethod;
132
+ failing : TestMethod;
133
+ only : TestMethod;
134
+ beforeEach : TestMethod;
135
+ afterEach : TestMethod;
136
+ cb : CallbackTestMethod;
137
+ always : TestMethod;
138
+ };
139
+
140
+ type CallbackTestMethod = {
141
+ ( implementation: CallbackTest): void;
142
+ (name: string, implementation: CallbackTest): void;
143
+ ( implementation: Macros<CallbackTestContext>, ...args: Array<any>): void;
144
+ (name: string, implementation: Macros<CallbackTestContext>, ...args: Array<any>): void;
145
+
146
+ serial : CallbackTestMethod;
147
+ before : CallbackTestMethod;
148
+ after : CallbackTestMethod;
149
+ skip : CallbackTestMethod;
150
+ todo : CallbackTestMethod;
151
+ failing : CallbackTestMethod;
152
+ only : CallbackTestMethod;
153
+ beforeEach : CallbackTestMethod;
154
+ afterEach : CallbackTestMethod;
155
+ cb : CallbackTestMethod;
156
+ always : CallbackTestMethod;
157
+ };
158
+
159
+ type ContextualTestMethod = {
160
+ ( implementation: ContextualTest): void;
161
+ (name: string, implementation: ContextualTest): void;
162
+ ( implementation: Macros<ContextualTestContext>, ...args: Array<any>): void;
163
+ (name: string, implementation: Macros<ContextualTestContext>, ...args: Array<any>): void;
164
+
165
+ serial : ContextualTestMethod;
166
+ before : ContextualTestMethod;
167
+ after : ContextualTestMethod;
168
+ skip : ContextualTestMethod;
169
+ todo : ContextualTestMethod;
170
+ failing : ContextualTestMethod;
171
+ only : ContextualTestMethod;
172
+ beforeEach : ContextualTestMethod;
173
+ afterEach : ContextualTestMethod;
174
+ cb : ContextualCallbackTestMethod;
175
+ always : ContextualTestMethod;
176
+ };
177
+
178
+ type ContextualCallbackTestMethod = {
179
+ ( implementation: ContextualCallbackTest): void;
180
+ (name: string, implementation: ContextualCallbackTest): void;
181
+ ( implementation: Macros<ContextualCallbackTestContext>, ...args: Array<any>): void;
182
+ (name: string, implementation: Macros<ContextualCallbackTestContext>, ...args: Array<any>): void;
183
+
184
+ serial : ContextualCallbackTestMethod;
185
+ before : ContextualCallbackTestMethod;
186
+ after : ContextualCallbackTestMethod;
187
+ skip : ContextualCallbackTestMethod;
188
+ todo : ContextualCallbackTestMethod;
189
+ failing : ContextualCallbackTestMethod;
190
+ only : ContextualCallbackTestMethod;
191
+ beforeEach : ContextualCallbackTestMethod;
192
+ afterEach : ContextualCallbackTestMethod;
193
+ cb : ContextualCallbackTestMethod;
194
+ always : ContextualCallbackTestMethod;
195
+ };
196
+
197
+ /**
198
+ * Public API
199
+ */
200
+
201
+ declare module.exports: {
202
+ ( run: ContextualTest): void;
203
+ (name: string, run: ContextualTest): void;
204
+ ( run: Macros<ContextualTestContext>, ...args: Array<any>): void;
205
+ (name: string, run: Macros<ContextualTestContext>, ...args: Array<any>): void;
206
+
207
+ beforeEach : TestMethod;
208
+ afterEach : TestMethod;
209
+ serial : ContextualTestMethod;
210
+ before : ContextualTestMethod;
211
+ after : ContextualTestMethod;
212
+ skip : ContextualTestMethod;
213
+ todo : ContextualTestMethod;
214
+ failing : ContextualTestMethod;
215
+ only : ContextualTestMethod;
216
+ cb : ContextualCallbackTestMethod;
217
+ always : ContextualTestMethod;
218
+ };
package/lib/assert.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
  var util = require('util');
3
3
  var assert = require('core-assert');
4
- var deepEqual = require('not-so-shallow');
4
+ var deepEqual = require('lodash.isequal');
5
5
  var observableToPromise = require('observable-to-promise');
6
6
  var isObservable = require('is-observable');
7
7
  var isPromise = require('is-promise');
@@ -147,18 +147,18 @@ x.notRegex = function (contents, regex, msg) {
147
147
  test(!regex.test(contents), create(regex, contents, '!==', msg, x.notRegex));
148
148
  };
149
149
 
150
- x.ifError = x.error = function (err, msg) {
150
+ x.ifError = function (err, msg) {
151
151
  test(!err, create(err, 'Error', '!==', msg, x.ifError));
152
152
  };
153
153
 
154
154
  /*
155
155
  * deprecated APIs
156
156
  */
157
- x.doesNotThrow = util.deprecate(x.notThrows, getDeprecationNotice('doesNotThrow()', 'notThrows()'));
158
157
  x.ok = util.deprecate(x.truthy, getDeprecationNotice('ok()', 'truthy()'));
159
158
  x.notOk = util.deprecate(x.falsy, getDeprecationNotice('notOk()', 'falsy()'));
160
159
  x.same = util.deprecate(x.deepEqual, getDeprecationNotice('same()', 'deepEqual()'));
161
160
  x.notSame = util.deprecate(x.notDeepEqual, getDeprecationNotice('notSame()', 'notDeepEqual()'));
161
+ x.error = util.deprecate(x.ifError, getDeprecationNotice('error()', 'ifError()'));
162
162
 
163
163
  function getDeprecationNotice(oldApi, newApi) {
164
164
  return 'DEPRECATION NOTICE: ' + oldApi + ' has been renamed to ' + newApi + ' and will eventually be removed. See https://github.com/avajs/ava-codemods to help upgrade your codebase automatically.';
@@ -4,6 +4,7 @@ var chalk = require('chalk');
4
4
  var figures = require('figures');
5
5
  var convertSourceMap = require('convert-source-map');
6
6
  var objectAssign = require('object-assign');
7
+ var semver = require('semver');
7
8
  var colors = require('./colors');
8
9
 
9
10
  function validate(conf) {
@@ -40,9 +41,13 @@ function lazy(initFn) {
40
41
  }
41
42
 
42
43
  var defaultPresets = lazy(function () {
44
+ var esPreset = semver.satisfies(process.version, '>=4') ?
45
+ 'babel-preset-es2015-node4' :
46
+ 'babel-preset-es2015';
47
+
43
48
  return [
44
49
  require('babel-preset-stage-2'),
45
- require('babel-preset-es2015')
50
+ require(esPreset) // eslint-disable-line import/no-dynamic-require
46
51
  ];
47
52
  });
48
53
 
@@ -57,7 +62,7 @@ var rewritePlugin = lazy(function () {
57
62
  });
58
63
 
59
64
  function rewriteBabelRuntimePaths(path) {
60
- var isBabelPath = /^babel-runtime[\\\/]?/.test(path.node.value);
65
+ var isBabelPath = /^babel-runtime[\\/]?/.test(path.node.value);
61
66
 
62
67
  if (path.isLiteral() && isBabelPath) {
63
68
  path.node.value = require.resolve(path.node.value);
@@ -77,14 +82,13 @@ var espowerPlugin = lazy(function () {
77
82
 
78
83
  var defaultPlugins = lazy(function () {
79
84
  return [
80
- espowerPlugin(),
81
85
  require('babel-plugin-ava-throws-helper'),
82
86
  rewritePlugin(),
83
87
  require('babel-plugin-transform-runtime')
84
88
  ];
85
89
  });
86
90
 
87
- function build(babelConfig, filePath, code) {
91
+ function build(babelConfig, powerAssert, filePath, code) {
88
92
  babelConfig = validate(babelConfig);
89
93
 
90
94
  var options;
@@ -115,7 +119,9 @@ function build(babelConfig, filePath, code) {
115
119
  ast: false
116
120
  });
117
121
 
118
- options.plugins = (options.plugins || []).concat(defaultPlugins());
122
+ options.plugins = (options.plugins || [])
123
+ .concat(powerAssert ? espowerPlugin() : [])
124
+ .concat(defaultPlugins());
119
125
 
120
126
  return options;
121
127
  }
@@ -2,6 +2,25 @@
2
2
  var StackUtils = require('stack-utils');
3
3
  var debug = require('debug')('ava');
4
4
 
5
+ //-----------
6
+ // embedded `clean-stack` module (because it requires Node.js 4)
7
+ var extractPathRegex = /\s+at.*(?:\(|\s)(.*)\)?/;
8
+ var pathRegex = /^(?:(?:(?:node|(?:internal\/[\w/]*|.*node_modules\/babel-polyfill\/.*)?\w+)\.js:\d+:\d+)|native)/;
9
+
10
+ var cleanStack = function (stack) {
11
+ return stack.replace(/\\/g, '/').split('\n').filter(function (x) {
12
+ var pathMatches = x.match(extractPathRegex);
13
+ if (pathMatches === null || !pathMatches[1]) {
14
+ return true;
15
+ }
16
+
17
+ return !pathRegex.test(pathMatches[1]);
18
+ }).filter(function (x) {
19
+ return x.trim() !== '';
20
+ }).join('\n');
21
+ };
22
+ //-----------
23
+
5
24
  function indent(str) {
6
25
  return ' ' + str;
7
26
  }
@@ -25,6 +44,10 @@ module.exports = function (stack) {
25
44
  return '';
26
45
  }
27
46
 
47
+ // workaround for https://github.com/tapjs/stack-utils/issues/14
48
+ // TODO: fix it in `stack-utils`
49
+ stack = cleanStack(stack);
50
+
28
51
  var title = stack.split('\n')[0];
29
52
  var lines = stackUtils
30
53
  .clean(stack)