ava 0.21.0 → 0.25.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/api.js CHANGED
@@ -2,9 +2,11 @@
2
2
  const EventEmitter = require('events');
3
3
  const path = require('path');
4
4
  const fs = require('fs');
5
+ const os = require('os');
5
6
  const commonPathPrefix = require('common-path-prefix');
6
7
  const uniqueTempDir = require('unique-temp-dir');
7
8
  const findCacheDir = require('find-cache-dir');
9
+ const isCi = require('is-ci');
8
10
  const resolveCwd = require('resolve-cwd');
9
11
  const debounce = require('lodash.debounce');
10
12
  const autoBind = require('auto-bind');
@@ -53,6 +55,7 @@ class Api extends EventEmitter {
53
55
  this.options = Object.assign({match: []}, options);
54
56
  this.options.require = resolveModules(this.options.require);
55
57
  }
58
+
56
59
  _runFile(file, runStatus, execArgv) {
57
60
  const hash = this.precompiler.precompileFile(file);
58
61
  const precompiled = Object.assign({}, this._precompiledHelpers);
@@ -69,17 +72,20 @@ class Api extends EventEmitter {
69
72
 
70
73
  return emitter;
71
74
  }
75
+
72
76
  run(files, options) {
73
77
  return new AvaFiles({cwd: this.options.resolveTestsFrom, files})
74
78
  .findTestFiles()
75
79
  .then(files => this._run(files, options));
76
80
  }
81
+
77
82
  _onTimeout(runStatus) {
78
83
  const timeout = ms(this.options.timeout);
79
84
  const err = new AvaError(`Exited because no new tests completed within the last ${timeout}ms of inactivity`);
80
85
  this._handleError(runStatus, err);
81
86
  runStatus.emit('timeout');
82
87
  }
88
+
83
89
  _setupTimeout(runStatus) {
84
90
  const timeout = ms(this.options.timeout);
85
91
 
@@ -90,9 +96,11 @@ class Api extends EventEmitter {
90
96
  runStatus._restartTimer();
91
97
  runStatus.on('test', runStatus._restartTimer);
92
98
  }
99
+
93
100
  _cancelTimeout(runStatus) {
94
101
  runStatus._restartTimer.cancel();
95
102
  }
103
+
96
104
  _setupPrecompiler(files) {
97
105
  const isCacheEnabled = this.options.cacheEnabled !== false;
98
106
  let cacheDir = uniqueTempDir();
@@ -119,6 +127,7 @@ class Api extends EventEmitter {
119
127
  });
120
128
  });
121
129
  }
130
+
122
131
  _precompileHelpers() {
123
132
  this._precompiledHelpers = {};
124
133
 
@@ -134,6 +143,7 @@ class Api extends EventEmitter {
134
143
  this._precompiledHelpers[file] = hash;
135
144
  });
136
145
  }
146
+
137
147
  _run(files, options) {
138
148
  options = options || {};
139
149
 
@@ -160,18 +170,20 @@ class Api extends EventEmitter {
160
170
  this._setupTimeout(runStatus);
161
171
  }
162
172
 
163
- let overwatch;
173
+ let concurrency = Math.min(os.cpus().length, isCi ? 2 : Infinity);
174
+
164
175
  if (this.options.concurrency > 0) {
165
- const concurrency = this.options.serial ? 1 : this.options.concurrency;
166
- overwatch = this._runWithPool(files, runStatus, concurrency);
167
- } else {
168
- // _runWithoutPool exists to preserve legacy behavior, specifically around `.only`
169
- overwatch = this._runWithoutPool(files, runStatus);
176
+ concurrency = this.options.concurrency;
177
+ }
178
+
179
+ if (this.options.serial) {
180
+ concurrency = 1;
170
181
  }
171
182
 
172
- return overwatch;
183
+ return this._runWithPool(files, runStatus, concurrency);
173
184
  });
174
185
  }
186
+
175
187
  _computeForkExecArgs(files) {
176
188
  const execArgv = this.options.testOnlyExecArgv || process.execArgv;
177
189
  let debugArgIndex = -1;
@@ -217,85 +229,14 @@ class Api extends EventEmitter {
217
229
  return forkExecArgv;
218
230
  });
219
231
  }
232
+
220
233
  _handleError(runStatus, err) {
221
234
  runStatus.handleExceptions({
222
235
  exception: err,
223
236
  file: err.file ? path.relative(process.cwd(), err.file) : undefined
224
237
  });
225
238
  }
226
- _runWithoutPool(files, runStatus) {
227
- const tests = [];
228
- let execArgvList;
229
-
230
- // TODO: This should be cleared at the end of the run
231
- runStatus.on('timeout', () => {
232
- tests.forEach(fork => {
233
- fork.exit();
234
- });
235
- });
236
239
 
237
- return this._computeForkExecArgs(files)
238
- .then(argvList => {
239
- execArgvList = argvList;
240
- })
241
- .return(files)
242
- .each((file, index) => {
243
- return new Promise(resolve => {
244
- const forkArgs = execArgvList[index];
245
- const test = this._runFile(file, runStatus, forkArgs);
246
- tests.push(test);
247
- test.on('stats', resolve);
248
- test.catch(resolve);
249
- }).catch(err => {
250
- err.results = [];
251
- err.file = file;
252
- return Promise.reject(err);
253
- });
254
- })
255
- .then(() => {
256
- if (this.options.match.length > 0 && !runStatus.hasExclusive) {
257
- const err = new AvaError('Couldn\'t find any matching tests');
258
- err.file = undefined;
259
- err.results = [];
260
- return Promise.reject(err);
261
- }
262
-
263
- const method = this.options.serial ? 'mapSeries' : 'map';
264
- const options = {
265
- runOnlyExclusive: runStatus.hasExclusive
266
- };
267
-
268
- return Promise[method](files, (file, index) => {
269
- return tests[index].run(options).catch(err => {
270
- err.file = file;
271
- this._handleError(runStatus, err);
272
- return getBlankResults();
273
- });
274
- });
275
- })
276
- .catch(err => {
277
- this._handleError(runStatus, err);
278
- return err.results;
279
- })
280
- .tap(results => {
281
- // If no tests ran, make sure to tear down the child processes
282
- if (results.length === 0) {
283
- tests.forEach(test => {
284
- test.send('teardown');
285
- });
286
- }
287
- })
288
- .then(results => {
289
- // Cancel debounced _onTimeout() from firing
290
- if (this.options.timeout) {
291
- this._cancelTimeout(runStatus);
292
- }
293
-
294
- runStatus.processResults(results);
295
-
296
- return runStatus;
297
- });
298
- }
299
240
  _runWithPool(files, runStatus, concurrency) {
300
241
  const tests = [];
301
242
  let execArgvList;
package/cli.js CHANGED
@@ -8,7 +8,7 @@ if (importLocal(__filename)) {
8
8
  debug('Using local install of AVA');
9
9
  } else {
10
10
  if (debug.enabled) {
11
- require('time-require'); // eslint-disable-line import/no-unassigned-import
11
+ require('@ladjs/time-require'); // eslint-disable-line import/no-unassigned-import
12
12
  }
13
13
 
14
14
  try {
package/index.js.flow CHANGED
@@ -69,7 +69,7 @@ type AssertContext = {
69
69
  // Assert that contents matches regex.
70
70
  regex(contents: string, regex: RegExp, message?: string): void;
71
71
  // Assert that contents matches a snapshot.
72
- snapshot(contents: any, message?: string): void;
72
+ snapshot: ((contents: any, message?: string) => void) & ((contents: any, options: {id: string}, message?: string) => void);
73
73
  // Assert that contents does not match regex.
74
74
  notRegex(contents: string, regex: RegExp, message?: string): void;
75
75
  // Assert that error is falsy.
@@ -81,8 +81,10 @@ type AssertContext = {
81
81
  */
82
82
 
83
83
  type TestContext = AssertContext & {
84
+ title: string;
84
85
  plan(count: number): void;
85
86
  skip: AssertContext;
87
+ log(...values: Array<any>): void;
86
88
  };
87
89
  type ContextualTestContext = TestContext & { context: any; };
88
90
  type ContextualCallbackTestContext = TestContext & { context: any; end(): void; };
package/lib/assert.js CHANGED
@@ -49,14 +49,22 @@ class AssertionError extends Error {
49
49
 
50
50
  if (opts.stack) {
51
51
  this.stack = opts.stack;
52
+ } else {
53
+ const limitBefore = Error.stackTraceLimit;
54
+ Error.stackTraceLimit = Infinity;
55
+ Error.captureStackTrace(this);
56
+ Error.stackTraceLimit = limitBefore;
52
57
  }
53
58
  }
54
59
  }
55
60
  exports.AssertionError = AssertionError;
56
61
 
57
62
  function getStack() {
63
+ const limitBefore = Error.stackTraceLimit;
64
+ Error.stackTraceLimit = Infinity;
58
65
  const obj = {};
59
66
  Error.captureStackTrace(obj, getStack);
67
+ Error.stackTraceLimit = limitBefore;
60
68
  return obj.stack;
61
69
  }
62
70
 
@@ -64,6 +72,7 @@ function wrapAssertions(callbacks) {
64
72
  const pass = callbacks.pass;
65
73
  const pending = callbacks.pending;
66
74
  const fail = callbacks.fail;
75
+ const log = callbacks.log;
67
76
 
68
77
  const noop = () => {};
69
78
  const makeRethrow = reason => () => {
@@ -86,14 +95,25 @@ function wrapAssertions(callbacks) {
86
95
  if (Object.is(actual, expected)) {
87
96
  pass(this);
88
97
  } else {
89
- const actualDescriptor = concordance.describe(actual, concordanceOptions);
90
- const expectedDescriptor = concordance.describe(expected, concordanceOptions);
91
- fail(this, new AssertionError({
92
- assertion: 'is',
93
- message,
94
- raw: {actual, expected},
95
- values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)]
96
- }));
98
+ const result = concordance.compare(actual, expected, concordanceOptions);
99
+ const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions);
100
+ const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions);
101
+
102
+ if (result.pass) {
103
+ fail(this, new AssertionError({
104
+ assertion: 'is',
105
+ message,
106
+ raw: {actual, expected},
107
+ values: [formatDescriptorWithLabel('Values are deeply equal to each other, but they are not the same:', actualDescriptor)]
108
+ }));
109
+ } else {
110
+ fail(this, new AssertionError({
111
+ assertion: 'is',
112
+ message,
113
+ raw: {actual, expected},
114
+ values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)]
115
+ }));
116
+ }
97
117
  }
98
118
  },
99
119
 
@@ -110,6 +130,18 @@ function wrapAssertions(callbacks) {
110
130
  }
111
131
  },
112
132
 
133
+ log() {
134
+ const args = Array.from(arguments, value => {
135
+ return typeof value === 'string' ?
136
+ value :
137
+ concordance.format(value, concordanceOptions);
138
+ });
139
+
140
+ if (args.length > 0) {
141
+ log(this, args.join(' '));
142
+ }
143
+ },
144
+
113
145
  deepEqual(actual, expected, message) {
114
146
  const result = concordance.compare(actual, expected, concordanceOptions);
115
147
  if (result.pass) {
package/lib/ava-files.js CHANGED
@@ -125,6 +125,7 @@ class AvaFiles {
125
125
 
126
126
  autoBind(this);
127
127
  }
128
+
128
129
  findTestFiles() {
129
130
  return handlePaths(this.files, this.excludePatterns, {
130
131
  cwd: this.cwd,
@@ -134,6 +135,7 @@ class AvaFiles {
134
135
  symlinks: Object.create(null)
135
136
  });
136
137
  }
138
+
137
139
  findTestHelpers() {
138
140
  return handlePaths(defaultHelperPatterns(), ['!**/node_modules/**'], {
139
141
  cwd: this.cwd,
@@ -144,6 +146,7 @@ class AvaFiles {
144
146
  symlinks: Object.create(null)
145
147
  });
146
148
  }
149
+
147
150
  isSource(filePath) {
148
151
  let mixedPatterns = [];
149
152
  const defaultIgnorePatterns = getDefaultIgnorePatterns();
@@ -195,6 +198,7 @@ class AvaFiles {
195
198
 
196
199
  return false;
197
200
  }
201
+
198
202
  isTest(filePath) {
199
203
  const excludePatterns = this.excludePatterns;
200
204
  const initialPatterns = this.files.concat(excludePatterns);
@@ -241,6 +245,7 @@ class AvaFiles {
241
245
  // excludePatterns into account. This mimicks the behavior in api.js
242
246
  return multimatch(matchable(filePath), recursivePatterns.concat(excludePatterns)).length === 1;
243
247
  }
248
+
244
249
  getChokidarPatterns() {
245
250
  let paths = [];
246
251
  let ignored = [];
@@ -6,6 +6,7 @@ const figures = require('figures');
6
6
  const configManager = require('hullabaloo-config-manager');
7
7
  const md5Hex = require('md5-hex');
8
8
  const makeDir = require('make-dir');
9
+ const semver = require('semver');
9
10
  const colors = require('./colors');
10
11
 
11
12
  function validate(conf) {
@@ -99,6 +100,7 @@ function build(projectDir, cacheDir, userOptions, powerAssert) {
99
100
 
100
101
  const baseOptions = {
101
102
  babelrc: false,
103
+ plugins: [],
102
104
  presets: [
103
105
  ['@ava/transform-test-files', {powerAssert}]
104
106
  ]
@@ -107,6 +109,12 @@ function build(projectDir, cacheDir, userOptions, powerAssert) {
107
109
  baseOptions.presets.unshift('@ava/stage-4');
108
110
  }
109
111
 
112
+ // Include object rest spread support for node versions that support it
113
+ // natively.
114
+ if (userOptions === 'default' && semver.satisfies(process.versions.node, '>= 8.3.0')) {
115
+ baseOptions.plugins.push('babel-plugin-syntax-object-rest-spread');
116
+ }
117
+
110
118
  const baseConfig = configManager.createConfig({
111
119
  dir: AVA_DIR, // Presets are resolved relative to this directory
112
120
  hash: md5Hex(JSON.stringify(baseOptions)),
@@ -8,6 +8,7 @@ let ignoreStackLines = [];
8
8
 
9
9
  const avaInternals = /\/ava\/(?:lib\/)?[\w-]+\.js:\d+:\d+\)?$/;
10
10
  const avaDependencies = /\/node_modules\/(?:bluebird|empower-core|(?:ava\/node_modules\/)?(?:babel-runtime|core-js))\//;
11
+ const stackFrameLine = /^.+( \(.+:\d+:\d+\)|:\d+:\d+)$/;
11
12
 
12
13
  if (!debug.enabled) {
13
14
  ignoreStackLines = StackUtils.nodeInternals();
@@ -17,21 +18,55 @@ if (!debug.enabled) {
17
18
 
18
19
  const stackUtils = new StackUtils({internals: ignoreStackLines});
19
20
 
21
+ function extractFrames(stack) {
22
+ return stack
23
+ .split('\n')
24
+ .map(line => line.trim())
25
+ .filter(line => stackFrameLine.test(line))
26
+ .join('\n');
27
+ }
28
+
29
+ /**
30
+ * Given a string value of the format generated for the `stack` property of a
31
+ * V8 error object, return a string that contains only stack frame information
32
+ * for frames that have relevance to the consumer.
33
+ *
34
+ * For example, given the following string value:
35
+ *
36
+ * ```
37
+ * Error
38
+ * at inner (/home/ava/ex.js:7:12)
39
+ * at /home/ava/ex.js:12:5
40
+ * at outer (/home/ava/ex.js:13:4)
41
+ * at Object.<anonymous> (/home/ava/ex.js:14:3)
42
+ * at Module._compile (module.js:570:32)
43
+ * at Object.Module._extensions..js (module.js:579:10)
44
+ * at Module.load (module.js:487:32)
45
+ * at tryModuleLoad (module.js:446:12)
46
+ * at Function.Module._load (module.js:438:3)
47
+ * at Module.runMain (module.js:604:10)
48
+ * ```
49
+ *
50
+ * ...this function returns the following string value:
51
+ *
52
+ * ```
53
+ * inner (/home/ava/ex.js:7:12)
54
+ * /home/ava/ex.js:12:5
55
+ * outer (/home/ava/ex.js:13:4)
56
+ * Object.<anonymous> (/home/ava/ex.js:14:3)
57
+ * ```
58
+ */
20
59
  module.exports = stack => {
21
60
  if (!stack) {
22
61
  return '';
23
62
  }
24
63
 
64
+ stack = extractFrames(stack);
25
65
  // Workaround for https://github.com/tapjs/stack-utils/issues/14
26
66
  // TODO: fix it in `stack-utils`
27
67
  stack = cleanStack(stack);
28
68
 
29
- const title = stack.split('\n')[0];
30
- const lines = stackUtils
31
- .clean(stack)
32
- .split('\n')
33
- .map(x => ` ${x}`)
34
- .join('\n');
35
-
36
- return `${title}\n${lines}`;
69
+ return stackUtils.clean(stack)
70
+ // Remove the trailing newline inserted by the `stack-utils` module
71
+ .trim();
37
72
  };
@@ -33,6 +33,7 @@ class CachingPrecompiler {
33
33
  this.fileHashes = {};
34
34
  this.transform = this._createTransform();
35
35
  }
36
+
36
37
  precompileFile(filePath) {
37
38
  if (!this.fileHashes[filePath]) {
38
39
  const source = stripBomBuf(fs.readFileSync(filePath));
@@ -41,11 +42,13 @@ class CachingPrecompiler {
41
42
 
42
43
  return this.fileHashes[filePath];
43
44
  }
45
+
44
46
  // Conditionally called by caching-transform when precompiling is required
45
47
  _init() {
46
48
  this.babel = require('babel-core');
47
49
  return this._transform;
48
50
  }
51
+
49
52
  _transform(code, filePath, hash) {
50
53
  code = code.toString();
51
54
 
@@ -73,12 +76,11 @@ class CachingPrecompiler {
73
76
 
74
77
  // Append source map comment to transformed code
75
78
  // So that other libraries (like nyc) can find the source map
76
- const dirPath = path.dirname(filePath);
77
- const relativeMapPath = path.relative(dirPath, mapPath);
78
- const comment = convertSourceMap.generateMapFileComment(relativeMapPath);
79
+ const comment = convertSourceMap.generateMapFileComment(mapPath);
79
80
 
80
81
  return `${result.code}\n${comment}`;
81
82
  }
83
+
82
84
  _createTransform() {
83
85
  const salt = packageHash.sync([
84
86
  require.resolve('../package.json'),
@@ -93,6 +95,7 @@ class CachingPrecompiler {
93
95
  ext: '.js'
94
96
  });
95
97
  }
98
+
96
99
  _generateHash(code, filePath, salt) {
97
100
  const hash = md5Hex([code, filePath, salt]);
98
101
  this.fileHashes[filePath] = hash;
package/lib/cli.js CHANGED
@@ -43,7 +43,7 @@ exports.run = () => {
43
43
  --match, -m Only run tests with matching title (Can be repeated)
44
44
  --watch, -w Re-run tests when tests and source files change
45
45
  --timeout, -T Set global timeout
46
- --concurrency, -c Maximum number of test files running at the same time (EXPERIMENTAL)
46
+ --concurrency, -c Max number of test files running at the same time (Default: CPU cores)
47
47
  --update-snapshots, -u Update snapshots
48
48
 
49
49
  Examples
@@ -75,7 +75,7 @@ exports.run = () => {
75
75
  ],
76
76
  default: {
77
77
  cache: conf.cache,
78
- color: 'color' in conf ? conf.color : require('supports-color') !== false,
78
+ color: 'color' in conf ? conf.color : require('supports-color').stdout !== false,
79
79
  concurrency: conf.concurrency,
80
80
  failFast: conf.failFast,
81
81
  init: conf.init,
@@ -119,7 +119,12 @@ exports.run = () => {
119
119
  }
120
120
 
121
121
  if (cli.flags.concurrency === '') {
122
- throw new Error(colors.error(figures.cross) + ' The --concurrency and -c flags must be provided the maximum number of test files to run at once.');
122
+ throw new Error(colors.error(figures.cross) + ' The --concurrency and -c flags must be provided.');
123
+ }
124
+
125
+ if (cli.flags.concurrency &&
126
+ (!Number.isInteger(Number.parseFloat(cli.flags.concurrency)) || parseInt(cli.flags.concurrency, 10) < 0)) {
127
+ throw new Error(colors.error(figures.cross) + ' The --concurrency and -c flags must be a nonnegative integer.');
123
128
  }
124
129
 
125
130
  if (hasFlag('--require') || hasFlag('-r')) {
@@ -144,6 +149,7 @@ exports.run = () => {
144
149
  timeout: conf.timeout,
145
150
  concurrency: conf.concurrency ? parseInt(conf.concurrency, 10) : 0,
146
151
  updateSnapshots: conf.updateSnapshots,
152
+ snapshotDir: conf.snapshotDir ? path.resolve(projectDir, conf.snapshotDir) : null,
147
153
  color: conf.color
148
154
  });
149
155
 
@@ -152,7 +158,7 @@ exports.run = () => {
152
158
  if (conf.tap && !conf.watch) {
153
159
  reporter = new TapReporter();
154
160
  } else if (conf.verbose || isCi) {
155
- reporter = new VerboseReporter({color: conf.color});
161
+ reporter = new VerboseReporter({color: conf.color, watching: conf.watch});
156
162
  } else {
157
163
  reporter = new MiniReporter({color: conf.color, watching: conf.watch});
158
164
  }
package/lib/colors.js CHANGED
@@ -2,6 +2,7 @@
2
2
  const chalk = require('chalk');
3
3
 
4
4
  module.exports = {
5
+ log: chalk.gray,
5
6
  title: chalk.bold.white,
6
7
  error: chalk.red,
7
8
  skip: chalk.yellow,
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
  const concordance = require('concordance');
3
3
  const dotProp = require('dot-prop');
4
+ const generate = require('babel-generator').default;
4
5
  const concordanceOptions = require('./concordance-options').default;
5
6
 
6
7
  // When adding patterns, don't forget to add to
@@ -15,31 +16,16 @@ const PATTERNS = [
15
16
  't.notRegex(contents, regex, [message])'
16
17
  ];
17
18
 
18
- const isRangeMatch = (a, b) => {
19
- return (a[0] === b[0] && a[1] === b[1]) ||
20
- (a[0] > b[0] && a[0] < b[1]) ||
21
- (a[1] > b[0] && a[1] < b[1]);
22
- };
23
-
24
- const computeStatement = (tokens, range) => {
25
- return tokens
26
- .filter(token => isRangeMatch(token.range, range))
27
- .map(token => token.value === undefined ? token.type.label : token.value)
28
- .join('');
29
- };
30
-
19
+ const computeStatement = node => generate(node, {quotes: 'single'}).code;
31
20
  const getNode = (ast, path) => dotProp.get(ast, path.replace(/\//g, '.'));
32
21
 
33
22
  const formatter = context => {
34
23
  const ast = JSON.parse(context.source.ast);
35
- const tokens = JSON.parse(context.source.tokens);
36
24
  const args = context.args[0].events;
37
-
38
25
  return args
39
26
  .map(arg => {
40
- const range = getNode(ast, arg.espath).range;
41
- const statement = computeStatement(tokens, range);
42
-
27
+ const node = getNode(ast, arg.espath);
28
+ const statement = computeStatement(node);
43
29
  const formatted = concordance.format(arg.value, concordanceOptions);
44
30
  return [statement, formatted];
45
31
  })
package/lib/fork.js CHANGED
@@ -10,12 +10,10 @@ if (fs.realpathSync(__filename) !== __filename) {
10
10
  console.warn('WARNING: `npm link ava` and the `--preserve-symlink` flag are incompatible. We have detected that AVA is linked via `npm link`, and that you are using either an early version of Node 6, or the `--preserve-symlink` flag. This breaks AVA. You should upgrade to Node 6.2.0+, avoid the `--preserve-symlink` flag, or avoid using `npm link ava`.');
11
11
  }
12
12
 
13
- let env = process.env;
13
+ const env = Object.assign({NODE_ENV: 'test'}, process.env);
14
14
 
15
15
  // Ensure NODE_PATH paths are absolute
16
16
  if (env.NODE_PATH) {
17
- env = Object.assign({}, env);
18
-
19
17
  env.NODE_PATH = env.NODE_PATH
20
18
  .split(path.delimiter)
21
19
  .map(x => path.resolve(x))
package/lib/logger.js CHANGED
@@ -6,6 +6,7 @@ class Logger {
6
6
  this.reporter = reporter;
7
7
  autoBind(this);
8
8
  }
9
+
9
10
  start(runStatus) {
10
11
  if (!this.reporter.start) {
11
12
  return;
@@ -13,6 +14,7 @@ class Logger {
13
14
 
14
15
  this.write(this.reporter.start(runStatus), runStatus);
15
16
  }
17
+
16
18
  reset(runStatus) {
17
19
  if (!this.reporter.reset) {
18
20
  return;
@@ -20,9 +22,11 @@ class Logger {
20
22
 
21
23
  this.write(this.reporter.reset(runStatus), runStatus);
22
24
  }
25
+
23
26
  test(test, runStatus) {
24
27
  this.write(this.reporter.test(test, runStatus), runStatus);
25
28
  }
29
+
26
30
  unhandledError(err, runStatus) {
27
31
  if (!this.reporter.unhandledError) {
28
32
  return;
@@ -30,6 +34,7 @@ class Logger {
30
34
 
31
35
  this.write(this.reporter.unhandledError(err, runStatus), runStatus);
32
36
  }
37
+
33
38
  finish(runStatus) {
34
39
  if (!this.reporter.finish) {
35
40
  return;
@@ -37,6 +42,7 @@ class Logger {
37
42
 
38
43
  this.write(this.reporter.finish(runStatus), runStatus);
39
44
  }
45
+
40
46
  section() {
41
47
  if (!this.reporter.section) {
42
48
  return;
@@ -44,6 +50,7 @@ class Logger {
44
50
 
45
51
  this.write(this.reporter.section());
46
52
  }
53
+
47
54
  clear() {
48
55
  if (!this.reporter.clear) {
49
56
  return false;
@@ -52,6 +59,7 @@ class Logger {
52
59
  this.write(this.reporter.clear());
53
60
  return true;
54
61
  }
62
+
55
63
  write(str, runStatus) {
56
64
  if (typeof str === 'undefined') {
57
65
  return;
@@ -59,6 +67,7 @@ class Logger {
59
67
 
60
68
  this.reporter.write(str, runStatus);
61
69
  }
70
+
62
71
  stdout(data, runStatus) {
63
72
  if (!this.reporter.stdout) {
64
73
  return;
@@ -66,6 +75,7 @@ class Logger {
66
75
 
67
76
  this.reporter.stdout(data, runStatus);
68
77
  }
78
+
69
79
  stderr(data, runStatus) {
70
80
  if (!this.reporter.stderr) {
71
81
  return;
@@ -73,6 +83,7 @@ class Logger {
73
83
 
74
84
  this.reporter.stderr(data, runStatus);
75
85
  }
86
+
76
87
  exit(code) {
77
88
  process.exit(code); // eslint-disable-line unicorn/no-process-exit
78
89
  }
package/lib/main.js CHANGED
@@ -13,7 +13,8 @@ const runner = new Runner({
13
13
  match: opts.match,
14
14
  projectDir: opts.projectDir,
15
15
  serial: opts.serial,
16
- updateSnapshots: opts.updateSnapshots
16
+ updateSnapshots: opts.updateSnapshots,
17
+ snapshotDir: opts.snapshotDir
17
18
  });
18
19
 
19
20
  worker.setRunner(runner);
@@ -22,8 +23,6 @@ worker.setRunner(runner);
22
23
  // that no more tests should be logged
23
24
  let isFailed = false;
24
25
 
25
- Error.stackTraceLimit = Infinity;
26
-
27
26
  function test(props) {
28
27
  if (isFailed) {
29
28
  return;