Status.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. function _chalk() {
  7. const data = _interopRequireDefault(require('chalk'));
  8. _chalk = function _chalk() {
  9. return data;
  10. };
  11. return data;
  12. }
  13. function _stringLength() {
  14. const data = _interopRequireDefault(require('string-length'));
  15. _stringLength = function _stringLength() {
  16. return data;
  17. };
  18. return data;
  19. }
  20. var _utils = require('./utils');
  21. function _interopRequireDefault(obj) {
  22. return obj && obj.__esModule ? obj : {default: obj};
  23. }
  24. function _defineProperty(obj, key, value) {
  25. if (key in obj) {
  26. Object.defineProperty(obj, key, {
  27. value: value,
  28. enumerable: true,
  29. configurable: true,
  30. writable: true
  31. });
  32. } else {
  33. obj[key] = value;
  34. }
  35. return obj;
  36. }
  37. const RUNNING_TEXT = ' RUNS ';
  38. const RUNNING = _chalk().default.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
  39. /**
  40. * This class is a perf optimization for sorting the list of currently
  41. * running tests. It tries to keep tests in the same positions without
  42. * shifting the whole list.
  43. */
  44. class CurrentTestList {
  45. constructor() {
  46. _defineProperty(this, '_array', void 0);
  47. this._array = [];
  48. }
  49. add(testPath, config) {
  50. const index = this._array.indexOf(null);
  51. const record = {
  52. config,
  53. testPath
  54. };
  55. if (index !== -1) {
  56. this._array[index] = record;
  57. } else {
  58. this._array.push(record);
  59. }
  60. }
  61. delete(testPath) {
  62. const record = this._array.find(
  63. record => record !== null && record.testPath === testPath
  64. );
  65. this._array[this._array.indexOf(record || null)] = null;
  66. }
  67. get() {
  68. return this._array;
  69. }
  70. }
  71. /**
  72. * A class that generates the CLI status of currently running tests
  73. * and also provides an ANSI escape sequence to remove status lines
  74. * from the terminal.
  75. */
  76. class Status {
  77. constructor() {
  78. _defineProperty(this, '_cache', void 0);
  79. _defineProperty(this, '_callback', void 0);
  80. _defineProperty(this, '_currentTests', void 0);
  81. _defineProperty(this, '_done', void 0);
  82. _defineProperty(this, '_emitScheduled', void 0);
  83. _defineProperty(this, '_estimatedTime', void 0);
  84. _defineProperty(this, '_interval', void 0);
  85. _defineProperty(this, '_aggregatedResults', void 0);
  86. _defineProperty(this, '_showStatus', void 0);
  87. this._cache = null;
  88. this._currentTests = new CurrentTestList();
  89. this._done = false;
  90. this._emitScheduled = false;
  91. this._estimatedTime = 0;
  92. this._showStatus = false;
  93. }
  94. onChange(callback) {
  95. this._callback = callback;
  96. }
  97. runStarted(aggregatedResults, options) {
  98. this._estimatedTime = (options && options.estimatedTime) || 0;
  99. this._showStatus = options && options.showStatus;
  100. this._interval = setInterval(() => this._tick(), 1000);
  101. this._aggregatedResults = aggregatedResults;
  102. this._debouncedEmit();
  103. }
  104. runFinished() {
  105. this._done = true;
  106. if (this._interval) clearInterval(this._interval);
  107. this._emit();
  108. }
  109. testStarted(testPath, config) {
  110. this._currentTests.add(testPath, config);
  111. if (!this._showStatus) {
  112. this._emit();
  113. } else {
  114. this._debouncedEmit();
  115. }
  116. }
  117. testFinished(_config, testResult, aggregatedResults) {
  118. const testFilePath = testResult.testFilePath;
  119. this._aggregatedResults = aggregatedResults;
  120. this._currentTests.delete(testFilePath);
  121. this._debouncedEmit();
  122. }
  123. get() {
  124. if (this._cache) {
  125. return this._cache;
  126. }
  127. if (this._done) {
  128. return {
  129. clear: '',
  130. content: ''
  131. };
  132. }
  133. const width = process.stdout.columns;
  134. let content = '\n';
  135. this._currentTests.get().forEach(record => {
  136. if (record) {
  137. const config = record.config,
  138. testPath = record.testPath;
  139. const projectDisplayName = config.displayName
  140. ? (0, _utils.printDisplayName)(config) + ' '
  141. : '';
  142. const prefix = RUNNING + projectDisplayName;
  143. content +=
  144. (0, _utils.wrapAnsiString)(
  145. prefix +
  146. (0, _utils.trimAndFormatPath)(
  147. (0, _stringLength().default)(prefix),
  148. config,
  149. testPath,
  150. width
  151. ),
  152. width
  153. ) + '\n';
  154. }
  155. });
  156. if (this._showStatus && this._aggregatedResults) {
  157. content +=
  158. '\n' +
  159. (0, _utils.getSummary)(this._aggregatedResults, {
  160. estimatedTime: this._estimatedTime,
  161. roundTime: true,
  162. width
  163. });
  164. }
  165. let height = 0;
  166. for (let i = 0; i < content.length; i++) {
  167. if (content[i] === '\n') {
  168. height++;
  169. }
  170. }
  171. const clear = '\r\x1B[K\r\x1B[1A'.repeat(height);
  172. return (this._cache = {
  173. clear,
  174. content
  175. });
  176. }
  177. _emit() {
  178. this._cache = null;
  179. if (this._callback) this._callback();
  180. }
  181. _debouncedEmit() {
  182. if (!this._emitScheduled) {
  183. // Perf optimization to avoid two separate renders When
  184. // one test finishes and another test starts executing.
  185. this._emitScheduled = true;
  186. setTimeout(() => {
  187. this._emit();
  188. this._emitScheduled = false;
  189. }, 100);
  190. }
  191. }
  192. _tick() {
  193. this._debouncedEmit();
  194. }
  195. }
  196. exports.default = Status;