版博士V2.0程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

286 строки
9.4 KiB

  1. import { format, deepClone, stringify, getOwnProperties, getType, toArray } from '@vitest/utils';
  2. function partitionSuiteChildren(suite) {
  3. let tasksGroup = [];
  4. const tasksGroups = [];
  5. for (const c of suite.tasks) {
  6. if (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) {
  7. tasksGroup.push(c);
  8. } else {
  9. tasksGroups.push(tasksGroup);
  10. tasksGroup = [c];
  11. }
  12. }
  13. if (tasksGroup.length > 0)
  14. tasksGroups.push(tasksGroup);
  15. return tasksGroups;
  16. }
  17. const IS_RECORD_SYMBOL = "@@__IMMUTABLE_RECORD__@@";
  18. const IS_COLLECTION_SYMBOL = "@@__IMMUTABLE_ITERABLE__@@";
  19. const isImmutable = (v) => v && (v[IS_COLLECTION_SYMBOL] || v[IS_RECORD_SYMBOL]);
  20. const OBJECT_PROTO = Object.getPrototypeOf({});
  21. function getUnserializableMessage(err) {
  22. if (err instanceof Error)
  23. return `<unserializable>: ${err.message}`;
  24. if (typeof err === "string")
  25. return `<unserializable>: ${err}`;
  26. return "<unserializable>";
  27. }
  28. function serializeError(val, seen = /* @__PURE__ */ new WeakMap()) {
  29. if (!val || typeof val === "string")
  30. return val;
  31. if (typeof val === "function")
  32. return `Function<${val.name || "anonymous"}>`;
  33. if (typeof val === "symbol")
  34. return val.toString();
  35. if (typeof val !== "object")
  36. return val;
  37. if (isImmutable(val))
  38. return serializeError(val.toJSON(), seen);
  39. if (val instanceof Promise || val.constructor && val.constructor.prototype === "AsyncFunction")
  40. return "Promise";
  41. if (typeof Element !== "undefined" && val instanceof Element)
  42. return val.tagName;
  43. if (typeof val.asymmetricMatch === "function")
  44. return `${val.toString()} ${format(val.sample)}`;
  45. if (seen.has(val))
  46. return seen.get(val);
  47. if (Array.isArray(val)) {
  48. const clone = new Array(val.length);
  49. seen.set(val, clone);
  50. val.forEach((e, i) => {
  51. try {
  52. clone[i] = serializeError(e, seen);
  53. } catch (err) {
  54. clone[i] = getUnserializableMessage(err);
  55. }
  56. });
  57. return clone;
  58. } else {
  59. const clone = /* @__PURE__ */ Object.create(null);
  60. seen.set(val, clone);
  61. let obj = val;
  62. while (obj && obj !== OBJECT_PROTO) {
  63. Object.getOwnPropertyNames(obj).forEach((key) => {
  64. if (key in clone)
  65. return;
  66. try {
  67. clone[key] = serializeError(val[key], seen);
  68. } catch (err) {
  69. delete clone[key];
  70. clone[key] = getUnserializableMessage(err);
  71. }
  72. });
  73. obj = Object.getPrototypeOf(obj);
  74. }
  75. return clone;
  76. }
  77. }
  78. function normalizeErrorMessage(message) {
  79. return message.replace(/__vite_ssr_import_\d+__\./g, "");
  80. }
  81. function processError(err, options = {}) {
  82. if (!err || typeof err !== "object")
  83. return err;
  84. if (err.stack)
  85. err.stackStr = String(err.stack);
  86. if (err.name)
  87. err.nameStr = String(err.name);
  88. const clonedActual = deepClone(err.actual);
  89. const clonedExpected = deepClone(err.expected);
  90. const { replacedActual, replacedExpected } = replaceAsymmetricMatcher(clonedActual, clonedExpected);
  91. err.actual = replacedActual;
  92. err.expected = replacedExpected;
  93. const maxDiffSize = options.outputDiffMaxSize ?? 1e4;
  94. if (typeof err.expected !== "string")
  95. err.expected = stringify(err.expected, 10, { maxLength: maxDiffSize });
  96. if (typeof err.actual !== "string")
  97. err.actual = stringify(err.actual, 10, { maxLength: maxDiffSize });
  98. try {
  99. if (typeof err.message === "string")
  100. err.message = normalizeErrorMessage(err.message);
  101. if (typeof err.cause === "object" && typeof err.cause.message === "string")
  102. err.cause.message = normalizeErrorMessage(err.cause.message);
  103. } catch {
  104. }
  105. try {
  106. return serializeError(err);
  107. } catch (e) {
  108. return serializeError(new Error(`Failed to fully serialize error: ${e == null ? void 0 : e.message}
  109. Inner error message: ${err == null ? void 0 : err.message}`));
  110. }
  111. }
  112. function isAsymmetricMatcher(data) {
  113. const type = getType(data);
  114. return type === "Object" && typeof data.asymmetricMatch === "function";
  115. }
  116. function isReplaceable(obj1, obj2) {
  117. const obj1Type = getType(obj1);
  118. const obj2Type = getType(obj2);
  119. return obj1Type === obj2Type && obj1Type === "Object";
  120. }
  121. function replaceAsymmetricMatcher(actual, expected, actualReplaced = /* @__PURE__ */ new WeakSet(), expectedReplaced = /* @__PURE__ */ new WeakSet()) {
  122. if (!isReplaceable(actual, expected))
  123. return { replacedActual: actual, replacedExpected: expected };
  124. if (actualReplaced.has(actual) || expectedReplaced.has(expected))
  125. return { replacedActual: actual, replacedExpected: expected };
  126. actualReplaced.add(actual);
  127. expectedReplaced.add(expected);
  128. getOwnProperties(expected).forEach((key) => {
  129. const expectedValue = expected[key];
  130. const actualValue = actual[key];
  131. if (isAsymmetricMatcher(expectedValue)) {
  132. if (expectedValue.asymmetricMatch(actualValue))
  133. actual[key] = expectedValue;
  134. } else if (isAsymmetricMatcher(actualValue)) {
  135. if (actualValue.asymmetricMatch(expectedValue))
  136. expected[key] = actualValue;
  137. } else if (isReplaceable(actualValue, expectedValue)) {
  138. const replaced = replaceAsymmetricMatcher(
  139. actualValue,
  140. expectedValue,
  141. actualReplaced,
  142. expectedReplaced
  143. );
  144. actual[key] = replaced.replacedActual;
  145. expected[key] = replaced.replacedExpected;
  146. }
  147. });
  148. return {
  149. replacedActual: actual,
  150. replacedExpected: expected
  151. };
  152. }
  153. function interpretTaskModes(suite, namePattern, onlyMode, parentIsOnly, allowOnly) {
  154. const suiteIsOnly = parentIsOnly || suite.mode === "only";
  155. suite.tasks.forEach((t) => {
  156. const includeTask = suiteIsOnly || t.mode === "only";
  157. if (onlyMode) {
  158. if (t.type === "suite" && (includeTask || someTasksAreOnly(t))) {
  159. if (t.mode === "only") {
  160. checkAllowOnly(t, allowOnly);
  161. t.mode = "run";
  162. }
  163. } else if (t.mode === "run" && !includeTask) {
  164. t.mode = "skip";
  165. } else if (t.mode === "only") {
  166. checkAllowOnly(t, allowOnly);
  167. t.mode = "run";
  168. }
  169. }
  170. if (t.type === "test") {
  171. if (namePattern && !getTaskFullName(t).match(namePattern))
  172. t.mode = "skip";
  173. } else if (t.type === "suite") {
  174. if (t.mode === "skip")
  175. skipAllTasks(t);
  176. else
  177. interpretTaskModes(t, namePattern, onlyMode, includeTask, allowOnly);
  178. }
  179. });
  180. if (suite.mode === "run") {
  181. if (suite.tasks.length && suite.tasks.every((i) => i.mode !== "run"))
  182. suite.mode = "skip";
  183. }
  184. }
  185. function getTaskFullName(task) {
  186. return `${task.suite ? `${getTaskFullName(task.suite)} ` : ""}${task.name}`;
  187. }
  188. function someTasksAreOnly(suite) {
  189. return suite.tasks.some((t) => t.mode === "only" || t.type === "suite" && someTasksAreOnly(t));
  190. }
  191. function skipAllTasks(suite) {
  192. suite.tasks.forEach((t) => {
  193. if (t.mode === "run") {
  194. t.mode = "skip";
  195. if (t.type === "suite")
  196. skipAllTasks(t);
  197. }
  198. });
  199. }
  200. function checkAllowOnly(task, allowOnly) {
  201. if (allowOnly)
  202. return;
  203. const error = processError(new Error("[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error"));
  204. task.result = {
  205. state: "fail",
  206. error,
  207. errors: [error]
  208. };
  209. }
  210. function generateHash(str) {
  211. let hash = 0;
  212. if (str.length === 0)
  213. return `${hash}`;
  214. for (let i = 0; i < str.length; i++) {
  215. const char = str.charCodeAt(i);
  216. hash = (hash << 5) - hash + char;
  217. hash = hash & hash;
  218. }
  219. return `${hash}`;
  220. }
  221. function calculateSuiteHash(parent) {
  222. parent.tasks.forEach((t, idx) => {
  223. t.id = `${parent.id}_${idx}`;
  224. if (t.type === "suite")
  225. calculateSuiteHash(t);
  226. });
  227. }
  228. function createChainable(keys, fn) {
  229. function create(context) {
  230. const chain2 = function(...args) {
  231. return fn.apply(context, args);
  232. };
  233. Object.assign(chain2, fn);
  234. chain2.withContext = () => chain2.bind(context);
  235. for (const key of keys) {
  236. Object.defineProperty(chain2, key, {
  237. get() {
  238. return create({ ...context, [key]: true });
  239. }
  240. });
  241. }
  242. return chain2;
  243. }
  244. const chain = create({});
  245. chain.fn = fn;
  246. return chain;
  247. }
  248. function isAtomTest(s) {
  249. return s.type === "test" || s.type === "custom";
  250. }
  251. function getTests(suite) {
  252. return toArray(suite).flatMap((s) => isAtomTest(s) ? [s] : s.tasks.flatMap((c) => isAtomTest(c) ? [c] : getTests(c)));
  253. }
  254. function getTasks(tasks = []) {
  255. return toArray(tasks).flatMap((s) => isAtomTest(s) ? [s] : [s, ...getTasks(s.tasks)]);
  256. }
  257. function getSuites(suite) {
  258. return toArray(suite).flatMap((s) => s.type === "suite" ? [s, ...getSuites(s.tasks)] : []);
  259. }
  260. function hasTests(suite) {
  261. return toArray(suite).some((s) => s.tasks.some((c) => isAtomTest(c) || hasTests(c)));
  262. }
  263. function hasFailed(suite) {
  264. return toArray(suite).some((s) => {
  265. var _a;
  266. return ((_a = s.result) == null ? void 0 : _a.state) === "fail" || s.type === "suite" && hasFailed(s.tasks);
  267. });
  268. }
  269. function getNames(task) {
  270. const names = [task.name];
  271. let current = task;
  272. while ((current == null ? void 0 : current.suite) || (current == null ? void 0 : current.file)) {
  273. current = current.suite || current.file;
  274. if (current == null ? void 0 : current.name)
  275. names.unshift(current.name);
  276. }
  277. return names;
  278. }
  279. export { calculateSuiteHash as a, partitionSuiteChildren as b, createChainable as c, hasFailed as d, getTests as e, getTasks as f, generateHash as g, hasTests as h, interpretTaskModes as i, getSuites as j, getNames as k, serializeError as l, processError as p, replaceAsymmetricMatcher as r, someTasksAreOnly as s };