Dieses Repository beinhaltet HTML- und Javascript Code zur einer NotizenWebApp auf Basis von Web Storage. Zudem sind Mocha/Chai Tests im Browser enthalten. https://meinenotizen.netlify.app/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

watch-run.js 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. 'use strict';
  2. const path = require('path');
  3. const chokidar = require('chokidar');
  4. const Context = require('../context');
  5. const collectFiles = require('./collect-files');
  6. /**
  7. * Exports the `watchRun` function that runs mocha in "watch" mode.
  8. * @see module:lib/cli/run-helpers
  9. * @module
  10. * @private
  11. */
  12. /**
  13. * Run Mocha in "watch" mode
  14. * @param {Mocha} mocha - Mocha instance
  15. * @param {Object} opts - Options
  16. * @param {string[]} [opts.watchFiles] - List of paths and patterns to
  17. * watch. If not provided all files with an extension included in
  18. * `fileColletionParams.extension` are watched. See first argument of
  19. * `chokidar.watch`.
  20. * @param {string[]} opts.watchIgnore - List of paths and patterns to
  21. * exclude from watching. See `ignored` option of `chokidar`.
  22. * @param {Object} fileCollectParams - Parameters that control test
  23. * file collection. See `lib/cli/collect-files.js`.
  24. * @param {string[]} fileCollectParams.extension - List of extensions
  25. * to watch if `opts.watchFiles` is not given.
  26. * @private
  27. */
  28. module.exports = (mocha, {watchFiles, watchIgnore}, fileCollectParams) => {
  29. if (!watchFiles) {
  30. watchFiles = fileCollectParams.extension.map(ext => `**/*.${ext}`);
  31. }
  32. const watcher = chokidar.watch(watchFiles, {
  33. ignored: watchIgnore,
  34. ignoreInitial: true
  35. });
  36. const rerunner = createRerunner(mocha, () => {
  37. getWatchedFiles(watcher).forEach(file => {
  38. delete require.cache[file];
  39. });
  40. mocha.files = collectFiles(fileCollectParams);
  41. });
  42. watcher.on('ready', () => {
  43. rerunner.run();
  44. });
  45. watcher.on('all', () => {
  46. rerunner.scheduleRun();
  47. });
  48. console.log();
  49. hideCursor();
  50. process.on('exit', () => {
  51. showCursor();
  52. });
  53. process.on('SIGINT', () => {
  54. showCursor();
  55. console.log('\n');
  56. process.exit(128 + 2);
  57. });
  58. // Keyboard shortcut for restarting when "rs\n" is typed (ala Nodemon)
  59. process.stdin.resume();
  60. process.stdin.setEncoding('utf8');
  61. process.stdin.on('data', data => {
  62. const str = data
  63. .toString()
  64. .trim()
  65. .toLowerCase();
  66. if (str === 'rs') rerunner.scheduleRun();
  67. });
  68. };
  69. /**
  70. * Create an object that allows you to rerun tests on the mocha
  71. * instance. `beforeRun` is called everytime before `mocha.run()` is
  72. * called.
  73. *
  74. * @param {Mocha} mocha - Mocha instance
  75. * @param {function} beforeRun - Called just before `mocha.run()`
  76. */
  77. const createRerunner = (mocha, beforeRun) => {
  78. // Set to a `Runner` when mocha is running. Set to `null` when mocha is not
  79. // running.
  80. let runner = null;
  81. let rerunScheduled = false;
  82. const run = () => {
  83. try {
  84. beforeRun();
  85. resetMocha(mocha);
  86. runner = mocha.run(() => {
  87. runner = null;
  88. if (rerunScheduled) {
  89. rerun();
  90. }
  91. });
  92. } catch (e) {
  93. console.log(e.stack);
  94. }
  95. };
  96. const scheduleRun = () => {
  97. if (rerunScheduled) {
  98. return;
  99. }
  100. rerunScheduled = true;
  101. if (runner) {
  102. runner.abort();
  103. } else {
  104. rerun();
  105. }
  106. };
  107. const rerun = () => {
  108. rerunScheduled = false;
  109. eraseLine();
  110. run();
  111. };
  112. return {
  113. scheduleRun,
  114. run
  115. };
  116. };
  117. /**
  118. * Return the list of absolute paths watched by a chokidar watcher.
  119. *
  120. * @param watcher - Instance of a chokidar watcher
  121. * @return {string[]} - List of absolute paths
  122. */
  123. const getWatchedFiles = watcher => {
  124. const watchedDirs = watcher.getWatched();
  125. let watchedFiles = [];
  126. Object.keys(watchedDirs).forEach(dir => {
  127. watchedFiles = watchedFiles.concat(
  128. watchedDirs[dir].map(file => path.join(dir, file))
  129. );
  130. });
  131. return watchedFiles;
  132. };
  133. /**
  134. * Reset the internal state of the mocha instance so that tests can be rerun.
  135. *
  136. * @param {Mocha} mocha - Mocha instance
  137. * @private
  138. */
  139. const resetMocha = mocha => {
  140. mocha.unloadFiles();
  141. mocha.suite = mocha.suite.clone();
  142. mocha.suite.ctx = new Context();
  143. // Registers a callback on `mocha.suite` that wires new context to the DSL
  144. // (e.g. `describe`) that is exposed as globals when the test files are
  145. // reloaded.
  146. mocha.ui(mocha.options.ui);
  147. };
  148. /**
  149. * Hide the cursor.
  150. * @ignore
  151. * @private
  152. */
  153. const hideCursor = () => {
  154. process.stdout.write('\u001b[?25l');
  155. };
  156. /**
  157. * Show the cursor.
  158. * @ignore
  159. * @private
  160. */
  161. const showCursor = () => {
  162. process.stdout.write('\u001b[?25h');
  163. };
  164. /**
  165. * Erases the line on stdout
  166. * @private
  167. */
  168. const eraseLine = () => {
  169. process.stdout.write('\u001b[2K');
  170. };