| 'use strict'; | |
| const utils = require('../utils'); | |
| const Context = require('../context'); | |
| const Mocha = require('../mocha'); | |
| const collectFiles = require('./collect-files'); | |
| /** | |
| * Exports the `watchRun` function that runs mocha in "watch" mode. | |
| * @see module:lib/cli/run-helpers | |
| * @module | |
| * @private | |
| */ | |
| /** | |
| * Run Mocha in "watch" mode | |
| * @param {Mocha} mocha - Mocha instance | |
| * @param {Object} opts - Options | |
| * @param {string} opts.ui - User interface | |
| * @param {Object} fileCollectParams - Parameters that control test | |
| * file collection. See `lib/cli/collect-files.js`. | |
| * @param {string[]} fileCollectParams.extension - List of extensions to watch | |
| * @private | |
| */ | |
| module.exports = (mocha, {ui}, fileCollectParams) => { | |
| let runner; | |
| const files = collectFiles(fileCollectParams); | |
| console.log(); | |
| hideCursor(); | |
| process.on('SIGINT', () => { | |
| showCursor(); | |
| console.log('\n'); | |
| // By UNIX/Posix convention this indicates that the process was | |
| // killed by SIGINT which has portable number 2. | |
| process.exit(128 + 2); | |
| }); | |
| const watchFiles = utils.files(process.cwd(), fileCollectParams.extension); | |
| let runAgain = false; | |
| const loadAndRun = () => { | |
| try { | |
| mocha.files = files; | |
| runAgain = false; | |
| runner = mocha.run(() => { | |
| runner = null; | |
| if (runAgain) { | |
| rerun(); | |
| } | |
| }); | |
| } catch (e) { | |
| console.log(e.stack); | |
| } | |
| }; | |
| const purge = () => { | |
| watchFiles.forEach(Mocha.unloadFile); | |
| }; | |
| loadAndRun(); | |
| const rerun = () => { | |
| purge(); | |
| eraseLine(); | |
| mocha.suite = mocha.suite.clone(); | |
| mocha.suite.ctx = new Context(); | |
| mocha.ui(ui); | |
| loadAndRun(); | |
| }; | |
| utils.watch(watchFiles, () => { | |
| runAgain = true; | |
| if (runner) { | |
| runner.abort(); | |
| } else { | |
| rerun(); | |
| } | |
| }); | |
| }; | |
| /** | |
| * Hide the cursor. | |
| * @ignore | |
| * @private | |
| */ | |
| const hideCursor = () => { | |
| process.stdout.write('\u001b[?25l'); | |
| }; | |
| /** | |
| * Show the cursor. | |
| * @ignore | |
| * @private | |
| */ | |
| const showCursor = () => { | |
| process.stdout.write('\u001b[?25h'); | |
| }; | |
| /** | |
| * Erases the line on stdout | |
| * @private | |
| */ | |
| const eraseLine = () => { | |
| process.stdout.write('\u001b[2K'); | |
| }; |