markdown.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. "use strict";
  2. var __create = Object.create;
  3. var __defProp = Object.defineProperty;
  4. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  5. var __getOwnPropNames = Object.getOwnPropertyNames;
  6. var __getProtoOf = Object.getPrototypeOf;
  7. var __hasOwnProp = Object.prototype.hasOwnProperty;
  8. var __export = (target, all) => {
  9. for (var name in all)
  10. __defProp(target, name, { get: all[name], enumerable: true });
  11. };
  12. var __copyProps = (to, from, except, desc) => {
  13. if (from && typeof from === "object" || typeof from === "function") {
  14. for (let key of __getOwnPropNames(from))
  15. if (!__hasOwnProp.call(to, key) && key !== except)
  16. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  17. }
  18. return to;
  19. };
  20. var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  21. // If the importer is in node compatibility mode or this is not an ESM
  22. // file that has been converted to a CommonJS file using a Babel-
  23. // compatible transform (i.e. "__esModule" has not been set), then set
  24. // "default" to the CommonJS "module.exports" for node compatibility.
  25. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  26. mod
  27. ));
  28. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  29. var markdown_exports = {};
  30. __export(markdown_exports, {
  31. default: () => markdown_default
  32. });
  33. module.exports = __toCommonJS(markdown_exports);
  34. var import_fs = __toESM(require("fs"));
  35. var import_path = __toESM(require("path"));
  36. class MarkdownReporter {
  37. constructor(options) {
  38. this._fatalErrors = [];
  39. this._options = options;
  40. }
  41. printsToStdio() {
  42. return false;
  43. }
  44. onBegin(config, suite) {
  45. this._config = config;
  46. this._suite = suite;
  47. }
  48. onError(error) {
  49. this._fatalErrors.push(error);
  50. }
  51. async onEnd(result) {
  52. const summary = this._generateSummary();
  53. const lines = [];
  54. if (this._fatalErrors.length)
  55. lines.push(`**${this._fatalErrors.length} fatal errors, not part of any test**`);
  56. if (summary.unexpected.length) {
  57. lines.push(`**${summary.unexpected.length} failed**`);
  58. this._printTestList(":x:", summary.unexpected, lines);
  59. }
  60. if (summary.flaky.length) {
  61. lines.push(`<details>`);
  62. lines.push(`<summary><b>${summary.flaky.length} flaky</b></summary>`);
  63. this._printTestList(":warning:", summary.flaky, lines, " <br/>");
  64. lines.push(`</details>`);
  65. lines.push(``);
  66. }
  67. if (summary.interrupted.length) {
  68. lines.push(`<details>`);
  69. lines.push(`<summary><b>${summary.interrupted.length} interrupted</b></summary>`);
  70. this._printTestList(":warning:", summary.interrupted, lines, " <br/>");
  71. lines.push(`</details>`);
  72. lines.push(``);
  73. }
  74. const skipped = summary.skipped ? `, ${summary.skipped} skipped` : "";
  75. const didNotRun = summary.didNotRun ? `, ${summary.didNotRun} did not run` : "";
  76. lines.push(`**${summary.expected} passed${skipped}${didNotRun}**`);
  77. lines.push(``);
  78. await this.publishReport(lines.join("\n"));
  79. }
  80. async publishReport(report) {
  81. const maybeRelativeFile = this._options.outputFile || "report.md";
  82. const reportFile = import_path.default.resolve(this._options.configDir, maybeRelativeFile);
  83. await import_fs.default.promises.mkdir(import_path.default.dirname(reportFile), { recursive: true });
  84. await import_fs.default.promises.writeFile(reportFile, report);
  85. }
  86. _generateSummary() {
  87. let didNotRun = 0;
  88. let skipped = 0;
  89. let expected = 0;
  90. const interrupted = [];
  91. const interruptedToPrint = [];
  92. const unexpected = [];
  93. const flaky = [];
  94. this._suite.allTests().forEach((test) => {
  95. switch (test.outcome()) {
  96. case "skipped": {
  97. if (test.results.some((result) => result.status === "interrupted")) {
  98. if (test.results.some((result) => !!result.error))
  99. interruptedToPrint.push(test);
  100. interrupted.push(test);
  101. } else if (!test.results.length || test.expectedStatus !== "skipped") {
  102. ++didNotRun;
  103. } else {
  104. ++skipped;
  105. }
  106. break;
  107. }
  108. case "expected":
  109. ++expected;
  110. break;
  111. case "unexpected":
  112. unexpected.push(test);
  113. break;
  114. case "flaky":
  115. flaky.push(test);
  116. break;
  117. }
  118. });
  119. return {
  120. didNotRun,
  121. skipped,
  122. expected,
  123. interrupted,
  124. unexpected,
  125. flaky
  126. };
  127. }
  128. _printTestList(prefix, tests, lines, suffix) {
  129. for (const test of tests)
  130. lines.push(`${prefix} ${formatTestTitle(this._config.rootDir, test)}${suffix || ""}`);
  131. lines.push(``);
  132. }
  133. }
  134. function formatTestTitle(rootDir, test) {
  135. const [, projectName, , ...titles] = test.titlePath();
  136. const relativeTestPath = import_path.default.relative(rootDir, test.location.file);
  137. const location = `${relativeTestPath}:${test.location.line}`;
  138. const projectTitle = projectName ? `[${projectName}] \u203A ` : "";
  139. const testTitle = `${projectTitle}${location} \u203A ${titles.join(" \u203A ")}`;
  140. const extraTags = test.tags.filter((t) => !testTitle.includes(t));
  141. const formattedTags = extraTags.map((t) => `\`${t}\``).join(" ");
  142. return `${testTitle}${extraTags.length ? " " + formattedTags : ""}`;
  143. }
  144. var markdown_default = MarkdownReporter;