From c3aef5daca067583bd2702d43db90bf1db8af4f7 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 23 Jul 2018 13:12:17 +0700 Subject: [PATCH] Modernize some code Some things XO wouldn't catch. --- bench/compare.js | 69 ++++++++++++++++---------------- docs/recipes/when-to-use-plan.md | 4 +- lib/ava-files.js | 14 +++---- lib/serialize-error.js | 2 +- lib/watcher.js | 12 +++--- lib/worker/dependency-tracker.js | 4 +- lib/worker/subprocess.js | 16 ++++---- test/api.js | 14 ++----- test/fixture/debug-arg.js | 2 +- test/fixture/inspect-arg.js | 2 +- test/integration/assorted.js | 4 +- test/integration/concurrency.js | 22 +++++----- test/integration/watcher.js | 12 +++--- test/watcher.js | 8 ++-- 14 files changed, 89 insertions(+), 96 deletions(-) diff --git a/bench/compare.js b/bench/compare.js index b27dd9384..5713860fc 100644 --- a/bench/compare.js +++ b/bench/compare.js @@ -57,14 +57,14 @@ const results = {}; const fileNames = files.map(file => file['.file']); const stats = ['mean', 'stdDev', 'median', 'min', 'max']; -files.forEach(file => { +for (const file of files) { Object.keys(file) - .filter(key => !/^\./.test(key)) + .filter(key => !key.startsWith('.')) .forEach(key => { results[key] = results[key] || {}; results[key][file['.file']] = prepStats(file[key]); }); -}); +} const table = new Table(); table.push( @@ -78,37 +78,36 @@ table.push( stats.reduce(arr => arr.concat(fileNames), ['args']) ); -Object.keys(results) - .forEach(key => { - table.push(stats.reduce((arr, stat) => { - let min = Infinity; - let max = -Infinity; - - const statGroup = fileNames.map(fileName => { - let result = results[key][fileName]; - result = result && result[stat]; - - if (result) { - min = Math.min(min, result); - max = Math.max(max, result); - return result; - } - - return ''; - }); - - return arr.concat(statGroup.map(stat => { - if (stat === min) { - return chalk.green(stat); - } - - if (stat === max) { - return chalk.red(stat); - } - - return stat; - })); - }, [key])); - }); +for (const key of Object.keys(results)) { + table.push(stats.reduce((arr, stat) => { + let min = Infinity; + let max = -Infinity; + + const statGroup = fileNames.map(fileName => { + let result = results[key][fileName]; + result = result && result[stat]; + + if (result) { + min = Math.min(min, result); + max = Math.max(max, result); + return result; + } + + return ''; + }); + + return arr.concat(statGroup.map(stat => { + if (stat === min) { + return chalk.green(stat); + } + + if (stat === max) { + return chalk.red(stat); + } + + return stat; + })); + }, [key])); +} console.log(table.toString()); diff --git a/docs/recipes/when-to-use-plan.md b/docs/recipes/when-to-use-plan.md index 4975b677e..4aff2b0b5 100644 --- a/docs/recipes/when-to-use-plan.md +++ b/docs/recipes/when-to-use-plan.md @@ -119,7 +119,7 @@ In most cases, it's a bad idea to use any complex branching inside your tests. A ```js const testData = require('./fixtures/test-definitions.json'); -testData.forEach(testDefinition => { +for (const testDefinition of testData) { test('foo or bar', t => { const result = functionUnderTest(testDefinition.input); @@ -134,7 +134,7 @@ testData.forEach(testDefinition => { t.is(result.bar, testDefinition.foo); } }); -}); +} ``` ## Conclusion diff --git a/lib/ava-files.js b/lib/ava-files.js index fa422c775..bd45eac1e 100644 --- a/lib/ava-files.js +++ b/lib/ava-files.js @@ -158,7 +158,7 @@ class AvaFiles { const overrideDefaultIgnorePatterns = []; let hasPositivePattern = false; - this.sources.forEach(pattern => { + for (const pattern of this.sources) { mixedPatterns.push(pattern); // TODO: Why not just `pattern[0] !== '!'`? @@ -168,10 +168,10 @@ class AvaFiles { // Extract patterns that start with an ignored directory. These need to be // rematched separately. - if (defaultIgnore.indexOf(pattern.split('/')[0]) >= 0) { + if (defaultIgnore.includes(pattern.split('/')[0])) { overrideDefaultIgnorePatterns.push(pattern); } - }); + } // Same defaults as used for Chokidar if (!hasPositivePattern) { @@ -182,7 +182,7 @@ class AvaFiles { // Ignore paths outside the current working directory. // They can't be matched to a pattern. - if (/^\.\.\//.test(filePath)) { + if (filePath.startsWith('../')) { return false; } @@ -255,13 +255,13 @@ class AvaFiles { let paths = []; let ignored = []; - this.sources.forEach(pattern => { + for (const pattern of this.sources) { if (pattern[0] === '!') { ignored.push(pattern.slice(1)); } else { paths.push(pattern); } - }); + } // Allow source patterns to override the default ignore patterns. Chokidar // ignores paths that match the list of ignored patterns. It uses anymatch @@ -269,7 +269,7 @@ class AvaFiles { // that starts with an ignored directory, ensure the corresponding negation // pattern is added to the ignored paths. const overrideDefaultIgnorePatterns = paths - .filter(pattern => defaultIgnore.indexOf(pattern.split('/')[0]) >= 0) + .filter(pattern => defaultIgnore.includes(pattern.split('/')[0])) .map(pattern => `!${pattern}`); ignored = getDefaultIgnorePatterns().concat(ignored, overrideDefaultIgnorePatterns); diff --git a/lib/serialize-error.js b/lib/serialize-error.js index 502f129fe..ffe53db36 100644 --- a/lib/serialize-error.js +++ b/lib/serialize-error.js @@ -39,7 +39,7 @@ function buildSource(source) { const rel = path.relative(projectDir, file); const isWithinProject = rel.split(path.sep)[0] !== '..'; - const isDependency = isWithinProject && path.dirname(rel).split(path.sep).indexOf('node_modules') > -1; + const isDependency = isWithinProject && path.dirname(rel).split(path.sep).includes('node_modules'); return { isDependency, diff --git a/lib/watcher.js b/lib/watcher.js index c8efe4ff7..825a0a632 100644 --- a/lib/watcher.js +++ b/lib/watcher.js @@ -73,7 +73,7 @@ class TestDependency { } contains(source) { - return this.sources.indexOf(source) !== -1; + return this.sources.includes(source); } } @@ -97,7 +97,7 @@ class Watcher { let runOnlyExclusive = false; if (specificFiles) { - const exclusiveFiles = specificFiles.filter(file => this.filesWithExclusiveTests.indexOf(file) !== -1); + const exclusiveFiles = specificFiles.filter(file => this.filesWithExclusiveTests.includes(file)); runOnlyExclusive = exclusiveFiles.length !== this.filesWithExclusiveTests.length; if (runOnlyExclusive) { // The test files that previously contained exclusive tests are always @@ -294,21 +294,21 @@ class Watcher { sumPreviousFailures(beforeVector) { let total = 0; - this.filesWithFailures.forEach(state => { + for (const state of this.filesWithFailures) { if (state.vector < beforeVector) { total += state.count; } - }); + } return total; } cleanUnlinkedTests(unlinkedTests) { - unlinkedTests.forEach(testFile => { + for (const testFile of unlinkedTests) { this.updateTestDependencies(testFile, []); this.updateExclusivity(testFile, false); this.pruneFailures([testFile]); - }); + } } observeStdin(stdin) { diff --git a/lib/worker/dependency-tracker.js b/lib/worker/dependency-tracker.js index 6f87d79c5..c14a1987f 100644 --- a/lib/worker/dependency-tracker.js +++ b/lib/worker/dependency-tracker.js @@ -28,7 +28,7 @@ function track(filename) { exports.track = track; function install(testPath) { - Object.keys(require.extensions).forEach(ext => { + for (const ext of Object.keys(require.extensions)) { const wrappedHandler = require.extensions[ext]; require.extensions[ext] = (module, filename) => { @@ -38,6 +38,6 @@ function install(testPath) { wrappedHandler(module, filename); }; - }); + } } exports.install = install; diff --git a/lib/worker/subprocess.js b/lib/worker/subprocess.js index 591211ea9..45e3525c2 100644 --- a/lib/worker/subprocess.js +++ b/lib/worker/subprocess.js @@ -69,11 +69,11 @@ runner.on('finish', () => { } nowAndTimers.setImmediate(() => { - currentlyUnhandled().filter(rejection => { - return !attributedRejections.has(rejection.promise); - }).forEach(rejection => { - ipc.send({type: 'unhandled-rejection', err: serializeError('Unhandled rejection', true, rejection.reason)}); - }); + currentlyUnhandled() + .filter(rejection => !attributedRejections.has(rejection.promise)) + .forEach(rejection => { + ipc.send({type: 'unhandled-rejection', err: serializeError('Unhandled rejection', true, rejection.reason)}); + }); exit(0); }); @@ -103,15 +103,15 @@ dependencyTracking.install(testPath); precompilerHook.install(); try { - (options.require || []).forEach(x => { - const required = require(x); + for (const mod of (options.require || [])) { + const required = require(mod); try { if (required[Symbol.for('esm\u200D:package')]) { require = required(module); // eslint-disable-line no-global-assign } } catch (_) {} - }); + } require(testPath); diff --git a/test/api.js b/test/api.js index 7deb49bba..f4c222e49 100644 --- a/test/api.js +++ b/test/api.js @@ -627,18 +627,10 @@ test('caching is enabled by default', t => { return api.run([path.join(__dirname, 'fixture/caching/test.js')]) .then(() => { const files = fs.readdirSync(path.join(__dirname, 'fixture/caching/node_modules/.cache/ava')); - t.is(files.filter(x => endsWithJs(x)).length, 1); - t.is(files.filter(x => endsWithMap(x)).length, 1); + t.is(files.filter(x => x.endsWith('.js')).length, 1); + t.is(files.filter(x => x.endsWith('.map')).length, 1); t.is(files.length, 2); }); - - function endsWithJs(filename) { - return /\.js$/.test(filename); - } - - function endsWithMap(filename) { - return /\.map$/.test(filename); - } }); test('caching can be disabled', t => { @@ -702,7 +694,7 @@ test('emits dependencies for test files', t => { api.on('run', plan => { plan.status.on('stateChange', evt => { if (evt.type === 'dependencies') { - t.notEqual(testFiles.indexOf(evt.testFile), -1); + t.true(testFiles.includes(evt.testFile)); t.strictDeepEqual(evt.dependencies.slice(-3), sourceFiles); } }); diff --git a/test/fixture/debug-arg.js b/test/fixture/debug-arg.js index ad46b6e18..01809bd9b 100644 --- a/test/fixture/debug-arg.js +++ b/test/fixture/debug-arg.js @@ -1,5 +1,5 @@ import test from '../..'; test('test', t => { - t.true(process.execArgv[0].indexOf('--debug') === 0); + t.true(process.execArgv[0].startsWith('--debug')); }); diff --git a/test/fixture/inspect-arg.js b/test/fixture/inspect-arg.js index b11ffe44c..8cb103960 100644 --- a/test/fixture/inspect-arg.js +++ b/test/fixture/inspect-arg.js @@ -1,5 +1,5 @@ import test from '../..'; test('test', t => { - t.true(process.execArgv[0].indexOf('--inspect') === 0); + t.true(process.execArgv[0].startsWith('--inspect')); }); diff --git a/test/integration/assorted.js b/test/integration/assorted.js index 77ff1ca26..0eade8b0e 100644 --- a/test/integration/assorted.js +++ b/test/integration/assorted.js @@ -30,14 +30,14 @@ test('--match works', t => { }); }); -['--tap', '-t'].forEach(tapFlag => { +for (const tapFlag of ['--tap', '-t']) { test(`${tapFlag} should produce TAP output`, t => { execCli([tapFlag, 'test.js'], {dirname: 'fixture/watcher'}, err => { t.ok(!err); t.end(); }); }); -}); +} test('handles NODE_PATH', t => { const nodePaths = `fixture/node-paths/modules${path.delimiter}fixture/node-paths/deep/nested`; diff --git a/test/integration/concurrency.js b/test/integration/concurrency.js index 6d2980e06..7d95eed04 100644 --- a/test/integration/concurrency.js +++ b/test/integration/concurrency.js @@ -2,7 +2,9 @@ const test = require('tap').test; const {execCli} = require('../helper/cli'); -['--concurrency', '-c'].forEach(concurrencyFlag => { +const concurrencyFlags = ['--concurrency', '-c']; + +for (const concurrencyFlag of concurrencyFlags) { test(`bails when ${concurrencyFlag} is provided without value`, t => { execCli(['test.js', concurrencyFlag], {dirname: 'fixture/concurrency'}, (err, stdout, stderr) => { t.is(err.code, 1); @@ -10,9 +12,9 @@ const {execCli} = require('../helper/cli'); t.end(); }); }); -}); +} -['--concurrency', '-c'].forEach(concurrencyFlag => { +for (const concurrencyFlag of concurrencyFlags) { test(`bails when ${concurrencyFlag} is provided with an input that is a string`, t => { execCli([`${concurrencyFlag}=foo`, 'test.js', concurrencyFlag], {dirname: 'fixture/concurrency'}, (err, stdout, stderr) => { t.is(err.code, 1); @@ -20,9 +22,9 @@ const {execCli} = require('../helper/cli'); t.end(); }); }); -}); +} -['--concurrency', '-c'].forEach(concurrencyFlag => { +for (const concurrencyFlag of concurrencyFlags) { test(`bails when ${concurrencyFlag} is provided with an input that is a float`, t => { execCli([`${concurrencyFlag}=4.7`, 'test.js', concurrencyFlag], {dirname: 'fixture/concurrency'}, (err, stdout, stderr) => { t.is(err.code, 1); @@ -30,9 +32,9 @@ const {execCli} = require('../helper/cli'); t.end(); }); }); -}); +} -['--concurrency', '-c'].forEach(concurrencyFlag => { +for (const concurrencyFlag of concurrencyFlags) { test(`bails when ${concurrencyFlag} is provided with an input that is negative`, t => { execCli([`${concurrencyFlag}=-1`, 'test.js', concurrencyFlag], {dirname: 'fixture/concurrency'}, (err, stdout, stderr) => { t.is(err.code, 1); @@ -40,13 +42,13 @@ const {execCli} = require('../helper/cli'); t.end(); }); }); -}); +} -['--concurrency', '-c'].forEach(concurrencyFlag => { +for (const concurrencyFlag of concurrencyFlags) { test(`works when ${concurrencyFlag} is provided with a value`, t => { execCli([`${concurrencyFlag}=1`, 'test.js'], {dirname: 'fixture/concurrency'}, err => { t.ifError(err); t.end(); }); }); -}); +} diff --git a/test/integration/watcher.js b/test/integration/watcher.js index a241a3914..680d731bd 100644 --- a/test/integration/watcher.js +++ b/test/integration/watcher.js @@ -129,8 +129,8 @@ test('`"tap": true` config is ignored when --watch is given', t => { child.stderr.on('data', testOutput); }); -['--watch', '-w'].forEach(watchFlag => { - ['--tap', '-t'].forEach(tapFlag => { +for (const watchFlag of ['--watch', '-w']) { + for (const tapFlag of ['--tap', '-t']) { test(`bails when ${tapFlag} reporter is used while ${watchFlag} is given`, t => { execCli([tapFlag, watchFlag, 'test.js'], {dirname: 'fixture/watcher', env: {CI: ''}}, (err, stdout, stderr) => { t.is(err.code, 1); @@ -138,10 +138,10 @@ test('`"tap": true` config is ignored when --watch is given', t => { t.end(); }); }); - }); -}); + } +} -['--watch', '-w'].forEach(watchFlag => { +for (const watchFlag of ['--watch', '-w']) { test(`bails when CI is used while ${watchFlag} is given`, t => { execCli([watchFlag, 'test.js'], {dirname: 'fixture/watcher', env: {CI: true}}, (err, stdout, stderr) => { t.is(err.code, 1); @@ -149,4 +149,4 @@ test('`"tap": true` config is ignored when --watch is given', t => { t.end(); }); }); -}); +} diff --git a/test/watcher.js b/test/watcher.js index e0412a6b1..7d7412b8c 100644 --- a/test/watcher.js +++ b/test/watcher.js @@ -678,7 +678,7 @@ group('chokidar', (beforeEach, test, group) => { }); }); - ['r', 'rs'].forEach(input => { + for (const input of ['r', 'rs']) { test(`reruns initial tests when "${input}" is entered on stdin`, t => { t.plan(4); api.run.returns(Promise.resolve(runStatus)); @@ -700,7 +700,7 @@ group('chokidar', (beforeEach, test, group) => { })]); }); }); - }); + } test(`reruns previous tests and update snapshots when "u" is entered on stdin`, t => { const options = Object.assign({}, defaultApiOptions, {updateSnapshots: true}); @@ -726,7 +726,7 @@ group('chokidar', (beforeEach, test, group) => { }); }); - ['r', 'rs', 'u'].forEach(input => { + for (const input of ['r', 'rs', 'u']) { test(`entering "${input}" on stdin prevents the log from being cleared`, t => { t.plan(2); api.run.returns(Promise.resolve(runStatus)); @@ -818,7 +818,7 @@ group('chokidar', (beforeEach, test, group) => { t.is(before, clock.now); }); }); - }); + } test('does nothing if anything other than "rs" is entered on stdin', t => { t.plan(1);