Files

Return to Package Diff Home.
Brought to you by Intrinsic.

Package Diff: tap @ 13.0.3 .. 13.0.4

bin/run.js

@@ -17,108 +17,11 @@
const tsNode = require.resolve('ts-node/register')
const esm = require.resolve('esm')
const jsx = require.resolve('./jsx.js')
-const mkdirp = require('mkdirp')
+const mkdirp = require('mkdirp').sync
const which = require('which')
const {ProcessDB} = require('istanbul-lib-processinfo')
const rimraf = require('rimraf').sync
-
-const watchStart = exports.watchStart = options => {
- if (!options.coverage)
- throw new Error('--watch requires coverage to be enabled')
-
- const args = [__filename, ...options._.parsed.filter(c => c !== '--watch')]
- console.error('initial test run', args.slice(1))
- const c = spawn(process.execPath, args, {
- stdio: 'inherit'
- })
- c.on('close', () => watchMain(options, args))
-}
-
-const watchList = index => [...new Set([
- ...Object.keys(index.files),
- ...Object.keys(index.externalIds),
-])]
-
-const watchMain = exports.watchMain = (options, args) => {
- const saveFolder = 'node_modules/.cache/tap'
- mkdirp.sync(saveFolder)
- const saveFile = saveFolder + '/watch-' + process.pid
- require('signal-exit')(() => rimraf(saveFile))
-
- const chokidar = require('chokidar')
- // watch all the files we just covered
- const indexFile = '.nyc_output/processinfo/index.json'
- let index = JSON.parse(fs.readFileSync(indexFile, 'utf8'))
- const filelist = watchList(index)
- const watcher = chokidar.watch(filelist)
-
- const queue = []
- let child = null
-
- const run = (ev, file) => {
- const tests = testsFromChange(index, file)
-
- if (file && tests) {
- queue.push(...tests)
- console.error(ev, file, '\n')
- }
-
- if (child) {
- console.error('test in progress, queuing for next run\n')
- return
- }
-
- const set = [...new Set(queue)]
- console.error('running tests', set, '\n')
- fs.writeFileSync(saveFile, set.join('\n') + '\n')
- queue.length = 0
- child = spawn(process.execPath, [...args, '--save=' + saveFile], {
- stdio: 'inherit'
- }).on('close', () => {
- // handle cases where a new file is added to index.
- index = JSON.parse(fs.readFileSync(indexFile, 'utf8'))
- const newFilelist = watchList(index).filter(f => !filelist.includes(f))
- filelist.push(...newFilelist)
- newFilelist.forEach(f => watcher.add(f))
- child = null
-
- // if --bail left some on the list, then add them too
- // but ignore if it's not there.
- const leftover = (() => {
- try {
- return fs.readFileSync(saveFile, 'utf8').trim().split('\n')
- } catch (er) {
- return []
- }
- })()
- const runAgain = queue.length
- queue.push(...leftover)
-
- if (runAgain)
- run()
- })
- }
-
- watchMain.close = () => watcher.close()
-
- // ignore the first crop of add events, since we already ran the tests
- setTimeout(() => watcher.on('all', run), 100)
-}
-
-const testsFromChange = exports.testsFromChange = (index, file) =>
- index.externalIds[file] ? [file]
- : testsFromFile(index, file)
-
-const testsFromFile = exports.testsFromFile = (index, file) =>
- Array.from((index.files[file] || []).reduce((set, uuid) => {
- for (let process = index.processes[uuid];
- process;
- process = process.parent && index.processes[process.parent]) {
- if (process.externalId)
- set.add(process.externalId)
- }
- return set
- }, new Set()))
+const Watch = require('../lib/watch.js')
const filesFromTest = exports.filesFromTest = (index, testFile) => {
const set = index.externalIds[testFile]
@@ -266,10 +169,10 @@
throw er
})
- // we test this function directly, not from here.
+ // we test this directly, not from here.
/* istanbul ignore next */
if (options.watch)
- return watchStart(options)
+ return new Watch(options).pipe(process.stderr)
options.grep = options.grep.map(strToRegExp)
@@ -297,7 +200,7 @@
options.files.push('-')
if (options['output-dir'] !== null)
- mkdirp.sync(options['output-dir'])
+ mkdirp(options['output-dir'])
if (options.files.length === 1 && options.files[0] === '-') {
setupTapEnv(options)
@@ -609,7 +512,7 @@
if (options['output-dir'] !== null) {
tap.on('spawn', t => {
const dir = options['output-dir'] + '/' + path.dirname(t.name)
- mkdirp.sync(dir)
+ mkdirp(dir)
const file = dir + '/' + path.basename(t.name) + '.tap'
t.proc.stdout.pipe(fs.createWriteStream(file))
})
@@ -636,8 +539,13 @@
? require(path.resolve(options['coverage-map']))
: null
+ const seen = new Set()
for (let i = 0; i < options.files.length; i++) {
const file = options.files[i]
+ if (seen.has(file))
+ continue
+
+ seen.add(file)
// Pick up stdin after all the other files are handled.
if (file === '-') {

lib/watch.js

@@ -0,0 +1,162 @@
+const chokidar = require('chokidar')
+const EE = require('events')
+const Minipass = require('minipass')
+const bin = require.resolve('../bin/run.js')
+const {spawn} = require('child_process')
+const mkdirp = require('mkdirp').sync
+const rimraf = require('rimraf').sync
+const onExit = require('signal-exit')
+const {writeFileSync, readFileSync} = require('fs')
+const util = require('util')
+
+class Watch extends Minipass {
+ constructor (options) {
+ if (!options.coverage)
+ throw new Error('--watch requires coverage to be enabled')
+ super()
+ this.args = [bin, ...options._.parsed, '--no-watch']
+ this.positionals = [...options._]
+ this.log('initial test run', this.args)
+ this.proc = spawn(process.execPath, this.args, {
+ stdio: 'inherit'
+ })
+ this.proc.on('close', () => this.main())
+ const saveFolder = 'node_modules/.cache/tap'
+ mkdirp(saveFolder)
+ this.saveFile = saveFolder + '/watch-' + process.pid
+ /* istanbul ignore next */
+ onExit(() => rimraf(this.saveFile))
+ this.index = null
+ this.indexFile = '.nyc_output/processinfo/index.json'
+ this.fileList = []
+ this.queue = []
+ this.watcher = null
+ }
+
+ readIndex () {
+ this.index = JSON.parse(readFileSync(this.indexFile, 'utf8'))
+ }
+
+ kill (signal) {
+ if (this.proc)
+ this.proc.kill(signal)
+ }
+
+ watchList () {
+ if (!this.index)
+ this.readIndex()
+ return [...new Set([
+ ...Object.keys(this.index.files),
+ ...Object.keys(this.index.externalIds),
+ ])]
+ }
+
+ pause () {
+ if (this.watcher)
+ this.watcher.close()
+ this.watcher = null
+ }
+
+ resume () {
+ if (!this.watcher)
+ this.watch()
+ }
+
+ main () {
+ this.proc = null
+ this.fileList = this.watchList()
+ this.watch()
+ }
+
+ watch () {
+ this.pause()
+ const sawAdd = new Map()
+ const watcher = this.watcher = chokidar.watch(this.fileList)
+ // ignore the first crop of add events, since we already ran the tests
+ watcher.on('all', (ev, file) => {
+ if (ev === 'add' && !sawAdd.get(file))
+ sawAdd.set(file, true)
+ else
+ this.onChange(ev, file)
+ })
+ return watcher
+ }
+
+ onChange (ev, file) {
+ const tests = this.testsFromChange(file)
+
+ this.queue.push(...tests)
+ this.log(ev, file)
+
+ if (this.proc)
+ return this.log('test in progress, queuing for next run')
+
+ this.run()
+ }
+
+ run () {
+ const set = [...new Set(this.queue)]
+ this.log('running tests', set)
+ writeFileSync(this.saveFile, set.join('\n') + '\n')
+ this.queue.length = 0
+
+ this.proc = spawn(process.execPath, [
+ ...this.args, '--save=' + this.saveFile
+ ], { stdio: 'inherit' })
+ this.proc.on('close', (code, signal) => this.onClose(code, signal))
+ this.emit('process', this.proc)
+ }
+
+ onClose (code, signal) {
+ this.readIndex()
+ this.proc = null
+ const newFileList = this.watchList(this.index)
+ .filter(f => !this.fileList.includes(f))
+ this.fileList.push(...newFileList)
+ this.resume()
+ newFileList.forEach(f => this.watcher.add(f))
+
+ // if there are any failures (especially, from a bail out)
+ // then add those, but ignore if it's not there.
+ const leftover = (() => {
+ try {
+ return fs.readFileSync(saveFile, 'utf8').trim().split('\n')
+ } catch (er) {
+ return []
+ }
+ })()
+ // run again if something was added during the process
+ const runAgain = this.queue.length
+ this.queue.push(...leftover)
+
+ if (runAgain)
+ this.run()
+ else
+ this.emit('afterProcess')
+ }
+
+ log (...args) {
+ this.write(util.format(...args) + '\n')
+ }
+
+ testsFromChange (file) {
+ return this.index.externalIds[file] ? [file]
+ : this.testsFromFile(file)
+ }
+
+ testsFromFile (file) {
+ const reducer = (set, uuid) => {
+ for (let process = this.index.processes[uuid];
+ process;
+ process = process.parent && this.index.processes[process.parent]) {
+ if (process.externalId)
+ set.add(process.externalId)
+ }
+ return set
+ }
+ const procs = this.index.files[file] || /* istanbul ignore next */ []
+ return [...procs.reduce(reducer, new Set())]
+ }
+}
+
+module.exports = Watch

package.json

@@ -1,6 +1,6 @@
{
"name": "tap",
- "version": "13.0.3",
+ "version": "13.0.4",
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
"description": "A Test-Anything-Protocol library",
"homepage": "http://node-tap.org/",
@@ -22,6 +22,7 @@
"chokidar": "^2.1.5",
"color-support": "^1.1.0",
"coveralls": "^3.0.3",
+ "diff": "^4.0.1",
"domain-browser": "^1.2.0",
"esm": "^3.2.22",
"findit": "^2.0.0",