(testFiles, opts)
| 601 | } |
| 602 | |
| 603 | function watchFiles(testFiles, opts) { |
| 604 | const runningProcesses = new SafeMap(); |
| 605 | const runningSubtests = new SafeMap(); |
| 606 | const watcherMode = opts.hasFiles ? 'filter' : 'all'; |
| 607 | const watcher = new FilesWatcher({ __proto__: null, debounce: 200, mode: watcherMode, signal: opts.signal }); |
| 608 | if (!opts.hasFiles) { |
| 609 | watcher.watchPath(opts.cwd); |
| 610 | } |
| 611 | const filesWatcher = { __proto__: null, watcher, runningProcesses, runningSubtests }; |
| 612 | opts.root.harness.watching = true; |
| 613 | |
| 614 | async function restartTestFile(file) { |
| 615 | const runningProcess = runningProcesses.get(file); |
| 616 | if (runningProcess) { |
| 617 | runningProcess.kill(); |
| 618 | await once(runningProcess, 'exit'); |
| 619 | } |
| 620 | if (!runningSubtests.size) { |
| 621 | // Reset the topLevel counter |
| 622 | opts.root.harness.counters.topLevel = 0; |
| 623 | } |
| 624 | |
| 625 | await runningSubtests.get(file); |
| 626 | runningSubtests.set(file, runTestFile(file, filesWatcher, opts)); |
| 627 | } |
| 628 | |
| 629 | // Watch for changes in current filtered files |
| 630 | const onChanged = ({ owners, eventType }) => { |
| 631 | if (!opts.hasFiles && (eventType === 'rename' || eventType === 'change')) { |
| 632 | const updatedTestFiles = createTestFileList(opts.globPatterns, opts.cwd); |
| 633 | const newFileName = ArrayPrototypeFind(updatedTestFiles, (x) => !ArrayPrototypeIncludes(testFiles, x)); |
| 634 | const previousFileName = ArrayPrototypeFind(testFiles, (x) => !ArrayPrototypeIncludes(updatedTestFiles, x)); |
| 635 | |
| 636 | testFiles = updatedTestFiles; |
| 637 | |
| 638 | // When file renamed (created / deleted) we need to update the watcher |
| 639 | if (newFileName) { |
| 640 | owners = new SafeSet().add(newFileName); |
| 641 | const resolveFileName = isAbsolute(newFileName) ? newFileName : resolve(opts.cwd, newFileName); |
| 642 | watcher.filterFile(resolveFileName, owners); |
| 643 | } |
| 644 | |
| 645 | if (!newFileName && previousFileName) { |
| 646 | return; // Avoid rerunning files when file deleted |
| 647 | } |
| 648 | } |
| 649 | // Reset the root start time to recalculate the duration |
| 650 | // of the run |
| 651 | opts.root.clearExecutionTime(); |
| 652 | opts.root.reporter[kEmitMessage]('test:watch:restarted'); |
| 653 | |
| 654 | // Restart test files |
| 655 | if (opts.isolation === 'none') { |
| 656 | PromisePrototypeThen(restartTestFile(kIsolatedProcessName), undefined, (error) => { |
| 657 | triggerUncaughtException(error, true /* fromPromise */); |
| 658 | }); |
| 659 | } else { |
| 660 | watcher.unfilterFilesOwnedBy(owners); |
no test coverage detected
searching dependent graphs…