list.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. "use strict";
  2. var __defProp = Object.defineProperty;
  3. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  4. var __getOwnPropNames = Object.getOwnPropertyNames;
  5. var __hasOwnProp = Object.prototype.hasOwnProperty;
  6. var __export = (target, all) => {
  7. for (var name in all)
  8. __defProp(target, name, { get: all[name], enumerable: true });
  9. };
  10. var __copyProps = (to, from, except, desc) => {
  11. if (from && typeof from === "object" || typeof from === "function") {
  12. for (let key of __getOwnPropNames(from))
  13. if (!__hasOwnProp.call(to, key) && key !== except)
  14. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  15. }
  16. return to;
  17. };
  18. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  19. var list_exports = {};
  20. __export(list_exports, {
  21. default: () => list_default
  22. });
  23. module.exports = __toCommonJS(list_exports);
  24. var import_utils = require("playwright-core/lib/utils");
  25. var import_utilsBundle = require("playwright-core/lib/utilsBundle");
  26. var import_base = require("./base");
  27. var import_util = require("../util");
  28. const DOES_NOT_SUPPORT_UTF8_IN_TERMINAL = process.platform === "win32" && process.env.TERM_PROGRAM !== "vscode" && !process.env.WT_SESSION;
  29. const POSITIVE_STATUS_MARK = DOES_NOT_SUPPORT_UTF8_IN_TERMINAL ? "ok" : "\u2713";
  30. const NEGATIVE_STATUS_MARK = DOES_NOT_SUPPORT_UTF8_IN_TERMINAL ? "x" : "\u2718";
  31. class ListReporter extends import_base.TerminalReporter {
  32. constructor(options) {
  33. super(options);
  34. this._lastRow = 0;
  35. this._lastColumn = 0;
  36. this._testRows = /* @__PURE__ */ new Map();
  37. this._stepRows = /* @__PURE__ */ new Map();
  38. this._resultIndex = /* @__PURE__ */ new Map();
  39. this._stepIndex = /* @__PURE__ */ new Map();
  40. this._needNewLine = false;
  41. this._printSteps = (0, import_utils.getAsBooleanFromENV)("PLAYWRIGHT_LIST_PRINT_STEPS", options?.printSteps);
  42. }
  43. onBegin(suite) {
  44. super.onBegin(suite);
  45. const startingMessage = this.generateStartingMessage();
  46. if (startingMessage) {
  47. this.writeLine(startingMessage);
  48. this.writeLine("");
  49. }
  50. }
  51. onTestBegin(test, result) {
  52. const index = String(this._resultIndex.size + 1);
  53. this._resultIndex.set(result, index);
  54. if (!this.screen.isTTY)
  55. return;
  56. this._maybeWriteNewLine();
  57. this._testRows.set(test, this._lastRow);
  58. const prefix = this._testPrefix(index, "");
  59. const line = this.screen.colors.dim(this.formatTestTitle(test)) + this._retrySuffix(result);
  60. this._appendLine(line, prefix);
  61. }
  62. onStdOut(chunk, test, result) {
  63. super.onStdOut(chunk, test, result);
  64. this._dumpToStdio(test, chunk, this.screen.stdout);
  65. }
  66. onStdErr(chunk, test, result) {
  67. super.onStdErr(chunk, test, result);
  68. this._dumpToStdio(test, chunk, this.screen.stderr);
  69. }
  70. getStepIndex(testIndex, result, step) {
  71. if (this._stepIndex.has(step))
  72. return this._stepIndex.get(step);
  73. const ordinal = (result[lastStepOrdinalSymbol] || 0) + 1;
  74. result[lastStepOrdinalSymbol] = ordinal;
  75. const stepIndex = `${testIndex}.${ordinal}`;
  76. this._stepIndex.set(step, stepIndex);
  77. return stepIndex;
  78. }
  79. onStepBegin(test, result, step) {
  80. if (step.category !== "test.step")
  81. return;
  82. const testIndex = this._resultIndex.get(result) || "";
  83. if (!this.screen.isTTY)
  84. return;
  85. if (this._printSteps) {
  86. this._maybeWriteNewLine();
  87. this._stepRows.set(step, this._lastRow);
  88. const prefix = this._testPrefix(this.getStepIndex(testIndex, result, step), "");
  89. const line = test.title + this.screen.colors.dim((0, import_base.stepSuffix)(step));
  90. this._appendLine(line, prefix);
  91. } else {
  92. this._updateOrAppendLine(this._testRows, test, this.screen.colors.dim(this.formatTestTitle(test, step)) + this._retrySuffix(result), this._testPrefix(testIndex, ""));
  93. }
  94. }
  95. onStepEnd(test, result, step) {
  96. if (step.category !== "test.step")
  97. return;
  98. const testIndex = this._resultIndex.get(result) || "";
  99. if (!this._printSteps) {
  100. if (this.screen.isTTY)
  101. this._updateOrAppendLine(this._testRows, test, this.screen.colors.dim(this.formatTestTitle(test, step.parent)) + this._retrySuffix(result), this._testPrefix(testIndex, ""));
  102. return;
  103. }
  104. const index = this.getStepIndex(testIndex, result, step);
  105. const title = this.screen.isTTY ? test.title + this.screen.colors.dim((0, import_base.stepSuffix)(step)) : this.formatTestTitle(test, step);
  106. const prefix = this._testPrefix(index, "");
  107. let text = "";
  108. if (step.error)
  109. text = this.screen.colors.red(title);
  110. else
  111. text = title;
  112. text += this.screen.colors.dim(` (${(0, import_utilsBundle.ms)(step.duration)})`);
  113. this._updateOrAppendLine(this._stepRows, step, text, prefix);
  114. }
  115. _maybeWriteNewLine() {
  116. if (this._needNewLine) {
  117. this._needNewLine = false;
  118. this.screen.stdout.write("\n");
  119. ++this._lastRow;
  120. this._lastColumn = 0;
  121. }
  122. }
  123. _updateLineCountAndNewLineFlagForOutput(text) {
  124. this._needNewLine = text[text.length - 1] !== "\n";
  125. if (!this.screen.ttyWidth)
  126. return;
  127. for (const ch of text) {
  128. if (ch === "\n") {
  129. this._lastColumn = 0;
  130. ++this._lastRow;
  131. continue;
  132. }
  133. ++this._lastColumn;
  134. if (this._lastColumn > this.screen.ttyWidth) {
  135. this._lastColumn = 0;
  136. ++this._lastRow;
  137. }
  138. }
  139. }
  140. _dumpToStdio(test, chunk, stream) {
  141. if (this.config.quiet)
  142. return;
  143. const text = chunk.toString("utf-8");
  144. this._updateLineCountAndNewLineFlagForOutput(text);
  145. stream.write(chunk);
  146. }
  147. onTestEnd(test, result) {
  148. super.onTestEnd(test, result);
  149. const title = this.formatTestTitle(test);
  150. let prefix = "";
  151. let text = "";
  152. let index = this._resultIndex.get(result);
  153. if (!index) {
  154. index = String(this._resultIndex.size + 1);
  155. this._resultIndex.set(result, index);
  156. }
  157. if (result.status === "skipped") {
  158. prefix = this._testPrefix(index, this.screen.colors.green("-"));
  159. text = this.screen.colors.cyan(title) + this._retrySuffix(result);
  160. } else {
  161. const statusMark = result.status === "passed" ? POSITIVE_STATUS_MARK : NEGATIVE_STATUS_MARK;
  162. if (result.status === test.expectedStatus) {
  163. prefix = this._testPrefix(index, this.screen.colors.green(statusMark));
  164. text = title;
  165. } else {
  166. prefix = this._testPrefix(index, this.screen.colors.red(statusMark));
  167. text = this.screen.colors.red(title);
  168. }
  169. text += this._retrySuffix(result) + this.screen.colors.dim(` (${(0, import_utilsBundle.ms)(result.duration)})`);
  170. }
  171. this._updateOrAppendLine(this._testRows, test, text, prefix);
  172. }
  173. _updateOrAppendLine(entityRowNumbers, entity, text, prefix) {
  174. const row = entityRowNumbers.get(entity);
  175. if (row !== void 0 && this.screen.isTTY && this._lastRow - row < this.screen.ttyHeight) {
  176. this._updateLine(row, text, prefix);
  177. } else {
  178. this._maybeWriteNewLine();
  179. entityRowNumbers.set(entity, this._lastRow);
  180. this._appendLine(text, prefix);
  181. }
  182. }
  183. _appendLine(text, prefix) {
  184. const line = prefix + this.fitToScreen(text, prefix);
  185. if (process.env.PW_TEST_DEBUG_REPORTERS) {
  186. this.screen.stdout.write("#" + this._lastRow + " : " + line + "\n");
  187. } else {
  188. this.screen.stdout.write(line);
  189. this.screen.stdout.write("\n");
  190. }
  191. ++this._lastRow;
  192. this._lastColumn = 0;
  193. }
  194. _updateLine(row, text, prefix) {
  195. const line = prefix + this.fitToScreen(text, prefix);
  196. if (process.env.PW_TEST_DEBUG_REPORTERS)
  197. this.screen.stdout.write("#" + row + " : " + line + "\n");
  198. else
  199. this._updateLineForTTY(row, line);
  200. }
  201. _updateLineForTTY(row, line) {
  202. if (row !== this._lastRow)
  203. this.screen.stdout.write(`\x1B[${this._lastRow - row}A`);
  204. this.screen.stdout.write("\x1B[2K\x1B[0G");
  205. this.screen.stdout.write(line);
  206. if (row !== this._lastRow)
  207. this.screen.stdout.write(`\x1B[${this._lastRow - row}E`);
  208. }
  209. _testPrefix(index, statusMark) {
  210. const statusMarkLength = (0, import_util.stripAnsiEscapes)(statusMark).length;
  211. const indexLength = Math.ceil(Math.log10(this.totalTestCount + 1));
  212. return " " + statusMark + " ".repeat(3 - statusMarkLength) + this.screen.colors.dim(index.padStart(indexLength) + " ");
  213. }
  214. _retrySuffix(result) {
  215. return result.retry ? this.screen.colors.yellow(` (retry #${result.retry})`) : "";
  216. }
  217. onError(error) {
  218. super.onError(error);
  219. this._maybeWriteNewLine();
  220. const message = this.formatError(error).message + "\n";
  221. this._updateLineCountAndNewLineFlagForOutput(message);
  222. this.screen.stdout.write(message);
  223. }
  224. async onEnd(result) {
  225. await super.onEnd(result);
  226. this.screen.stdout.write("\n");
  227. this.epilogue(true);
  228. }
  229. }
  230. const lastStepOrdinalSymbol = Symbol("lastStepOrdinal");
  231. var list_default = ListReporter;