From cc97a4dd2a967e1c2273bd5f4c5f49a5bf2e2585 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 27 Mar 2019 21:01:33 +0100 Subject: remove node_modules --- node_modules/ava/lib/watcher.js | 376 ---------------------------------------- 1 file changed, 376 deletions(-) delete mode 100644 node_modules/ava/lib/watcher.js (limited to 'node_modules/ava/lib/watcher.js') diff --git a/node_modules/ava/lib/watcher.js b/node_modules/ava/lib/watcher.js deleted file mode 100644 index 3f5ed3ee7..000000000 --- a/node_modules/ava/lib/watcher.js +++ /dev/null @@ -1,376 +0,0 @@ -'use strict'; -const nodePath = require('path'); -const debug = require('debug')('ava:watcher'); -const diff = require('lodash.difference'); -const chokidar = require('chokidar'); -const flatten = require('arr-flatten'); -const union = require('array-union'); -const uniq = require('array-uniq'); -const AvaFiles = require('./ava-files'); - -function rethrowAsync(err) { - // Don't swallow exceptions. Note that any - // expected error should already have been logged - setImmediate(() => { - throw err; - }); -} - -const MIN_DEBOUNCE_DELAY = 10; -const INITIAL_DEBOUNCE_DELAY = 100; - -class Debouncer { - constructor(watcher) { - this.watcher = watcher; - this.timer = null; - this.repeat = false; - } - - debounce(delay) { - if (this.timer) { - this.again = true; - return; - } - - delay = delay ? Math.max(delay, MIN_DEBOUNCE_DELAY) : INITIAL_DEBOUNCE_DELAY; - - const timer = setTimeout(() => { - this.watcher.busy.then(() => { - // Do nothing if debouncing was canceled while waiting for the busy - // promise to fulfil - if (this.timer !== timer) { - return; - } - - if (this.again) { - this.timer = null; - this.again = false; - this.debounce(delay / 2); - } else { - this.watcher.runAfterChanges(); - this.timer = null; - this.again = false; - } - }); - }, delay); - - this.timer = timer; - } - - cancel() { - if (this.timer) { - clearTimeout(this.timer); - this.timer = null; - this.again = false; - } - } -} - -class TestDependency { - constructor(file, sources) { - this.file = file; - this.sources = sources; - } - - contains(source) { - return this.sources.indexOf(source) !== -1; - } -} - -class Watcher { - constructor(logger, api, files, sources) { - this.debouncer = new Debouncer(this); - this.avaFiles = new AvaFiles({ - files, - sources - }); - - this.clearLogOnNextRun = true; - this.runVector = 0; - this.previousFiles = files; - this.run = (specificFiles, updateSnapshots) => { - if (this.runVector > 0) { - const cleared = this.clearLogOnNextRun && logger.clear(); - if (!cleared) { - logger.reset(); - logger.section(); - } - this.clearLogOnNextRun = true; - - logger.reset(); - logger.start(); - } - - this.runVector += 1; - - const currentVector = this.runVector; - - let runOnlyExclusive = false; - - if (specificFiles) { - const exclusiveFiles = specificFiles.filter(file => this.filesWithExclusiveTests.indexOf(file) !== -1); - - runOnlyExclusive = exclusiveFiles.length !== this.filesWithExclusiveTests.length; - - if (runOnlyExclusive) { - // The test files that previously contained exclusive tests are always - // run, together with the remaining specific files. - const remainingFiles = diff(specificFiles, exclusiveFiles); - specificFiles = this.filesWithExclusiveTests.concat(remainingFiles); - } - } - - this.touchedFiles.clear(); - this.previousFiles = specificFiles || files; - this.busy = api.run(this.previousFiles, {runOnlyExclusive, updateSnapshots: updateSnapshots === true}) - .then(runStatus => { - runStatus.previousFailCount = this.sumPreviousFailures(currentVector); - logger.finish(runStatus); - - const badCounts = runStatus.failCount + runStatus.rejectionCount + runStatus.exceptionCount; - this.clearLogOnNextRun = this.clearLogOnNextRun && badCounts === 0; - }) - .catch(rethrowAsync); - }; - - this.testDependencies = []; - this.trackTestDependencies(api, sources); - - this.touchedFiles = new Set(); - this.trackTouchedFiles(api); - - this.filesWithExclusiveTests = []; - this.trackExclusivity(api); - - this.filesWithFailures = []; - this.trackFailures(api); - - this.dirtyStates = {}; - this.watchFiles(); - this.rerunAll(); - } - - watchFiles() { - const patterns = this.avaFiles.getChokidarPatterns(); - - chokidar.watch(patterns.paths, { - ignored: patterns.ignored, - ignoreInitial: true - }).on('all', (event, path) => { - if (event === 'add' || event === 'change' || event === 'unlink') { - debug('Detected %s of %s', event, path); - this.dirtyStates[path] = event; - this.debouncer.debounce(); - } - }); - } - - trackTestDependencies(api) { - const relative = absPath => nodePath.relative(process.cwd(), absPath); - - api.on('test-run', runStatus => { - runStatus.on('dependencies', (file, dependencies) => { - const sourceDeps = dependencies.map(x => relative(x)).filter(this.avaFiles.isSource); - this.updateTestDependencies(file, sourceDeps); - }); - }); - } - - updateTestDependencies(file, sources) { - if (sources.length === 0) { - this.testDependencies = this.testDependencies.filter(dep => dep.file !== file); - return; - } - - const isUpdate = this.testDependencies.some(dep => { - if (dep.file !== file) { - return false; - } - - dep.sources = sources; - - return true; - }); - - if (!isUpdate) { - this.testDependencies.push(new TestDependency(file, sources)); - } - } - - trackTouchedFiles(api) { - api.on('test-run', runStatus => { - runStatus.on('touchedFiles', files => { - for (const file of files) { - this.touchedFiles.add(nodePath.relative(process.cwd(), file)); - } - }); - }); - } - - trackExclusivity(api) { - api.on('stats', stats => { - this.updateExclusivity(stats.file, stats.hasExclusive); - }); - } - - updateExclusivity(file, hasExclusiveTests) { - const index = this.filesWithExclusiveTests.indexOf(file); - - if (hasExclusiveTests && index === -1) { - this.filesWithExclusiveTests.push(file); - } else if (!hasExclusiveTests && index !== -1) { - this.filesWithExclusiveTests.splice(index, 1); - } - } - - trackFailures(api) { - api.on('test-run', (runStatus, files) => { - files.forEach(file => { - this.pruneFailures(nodePath.relative(process.cwd(), file)); - }); - - const currentVector = this.runVector; - runStatus.on('error', err => { - this.countFailure(err.file, currentVector); - }); - runStatus.on('test', result => { - if (result.error) { - this.countFailure(result.file, currentVector); - } - }); - }); - } - - pruneFailures(file) { - this.filesWithFailures = this.filesWithFailures.filter(state => state.file !== file); - } - - countFailure(file, vector) { - const isUpdate = this.filesWithFailures.some(state => { - if (state.file !== file) { - return false; - } - - state.count++; - return true; - }); - - if (!isUpdate) { - this.filesWithFailures.push({ - file, - vector, - count: 1 - }); - } - } - - sumPreviousFailures(beforeVector) { - let total = 0; - - this.filesWithFailures.forEach(state => { - if (state.vector < beforeVector) { - total += state.count; - } - }); - - return total; - } - - cleanUnlinkedTests(unlinkedTests) { - unlinkedTests.forEach(testFile => { - this.updateTestDependencies(testFile, []); - this.updateExclusivity(testFile, false); - this.pruneFailures(testFile); - }); - } - - observeStdin(stdin) { - stdin.resume(); - stdin.setEncoding('utf8'); - - stdin.on('data', data => { - data = data.trim().toLowerCase(); - if (data !== 'r' && data !== 'rs' && data !== 'u') { - return; - } - - // Cancel the debouncer, it might rerun specific tests whereas *all* tests - // need to be rerun - this.debouncer.cancel(); - this.busy.then(() => { - // Cancel the debouncer again, it might have restarted while waiting for - // the busy promise to fulfil - this.debouncer.cancel(); - this.clearLogOnNextRun = false; - if (data === 'u') { - this.updatePreviousSnapshots(); - } else { - this.rerunAll(); - } - }); - }); - } - - rerunAll() { - this.dirtyStates = {}; - this.run(); - } - - updatePreviousSnapshots() { - this.dirtyStates = {}; - this.run(this.previousFiles, true); - } - - runAfterChanges() { - const dirtyStates = this.dirtyStates; - this.dirtyStates = {}; - - const dirtyPaths = Object.keys(dirtyStates).filter(path => { - if (this.touchedFiles.has(path)) { - debug('Ignoring known touched file %s', path); - this.touchedFiles.delete(path); - return false; - } - return true; - }); - const dirtyTests = dirtyPaths.filter(this.avaFiles.isTest); - const dirtySources = diff(dirtyPaths, dirtyTests); - const addedOrChangedTests = dirtyTests.filter(path => dirtyStates[path] !== 'unlink'); - const unlinkedTests = diff(dirtyTests, addedOrChangedTests); - - this.cleanUnlinkedTests(unlinkedTests); - - // No need to rerun tests if the only change is that tests were deleted - if (unlinkedTests.length === dirtyPaths.length) { - return; - } - - if (dirtySources.length === 0) { - // Run any new or changed tests - this.run(addedOrChangedTests); - return; - } - - // Try to find tests that depend on the changed source files - const testsBySource = dirtySources.map(path => { - return this.testDependencies.filter(dep => dep.contains(path)).map(dep => { - debug('%s is a dependency of %s', path, dep.file); - return dep.file; - }); - }, this).filter(tests => tests.length > 0); - - // Rerun all tests if source files were changed that could not be traced to - // specific tests - if (testsBySource.length !== dirtySources.length) { - debug('Sources remain that cannot be traced to specific tests: %O', dirtySources); - debug('Rerunning all tests'); - this.run(); - return; - } - - // Run all affected tests - this.run(union(addedOrChangedTests, uniq(flatten(testsBySource)))); - } -} - -module.exports = Watcher; -- cgit v1.2.3