index.cjs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. var __defProp = Object.defineProperty;
  2. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  3. var __getOwnPropNames = Object.getOwnPropertyNames;
  4. var __hasOwnProp = Object.prototype.hasOwnProperty;
  5. var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
  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. // src/index.js
  20. var index_exports = {};
  21. __export(index_exports, {
  22. SpiesGroup: () => SpiesGroup,
  23. createSpiesGroup: () => createSpiesGroup,
  24. createSpy: () => createSpy
  25. });
  26. module.exports = __toCommonJS(index_exports);
  27. // src/create-spy.js
  28. function _parseSpyArgs(target, methodNameOrImplFromSpy, customImplForMethodFromSpy) {
  29. let originalFn;
  30. let customImplementation;
  31. let isMethodSpy = false;
  32. let objToSpyOn;
  33. let methodName;
  34. const isLikelyFunctionSpy = typeof target === "function" && customImplForMethodFromSpy === void 0;
  35. const isLikelyMethodSpy = typeof target === "object" && target !== null && typeof methodNameOrImplFromSpy === "string";
  36. if (isLikelyFunctionSpy) {
  37. originalFn = target;
  38. if (methodNameOrImplFromSpy !== void 0) {
  39. if (typeof methodNameOrImplFromSpy !== "function") {
  40. throw new TypeError(
  41. "When spying on a function, the second argument (custom implementation) must be a function if provided."
  42. );
  43. }
  44. customImplementation = methodNameOrImplFromSpy;
  45. }
  46. } else if (isLikelyMethodSpy) {
  47. methodName = methodNameOrImplFromSpy;
  48. objToSpyOn = target;
  49. isMethodSpy = true;
  50. if (!(methodName in target)) {
  51. throw new TypeError(
  52. `Attempted to spy on a non-existent property: "${methodName}"`
  53. );
  54. }
  55. const propertyToSpyOn = target[methodName];
  56. if (typeof propertyToSpyOn !== "function") {
  57. throw new TypeError(
  58. `Attempted to spy on "${methodName}" which is not a function. It is a "${typeof propertyToSpyOn}".`
  59. );
  60. }
  61. originalFn = propertyToSpyOn;
  62. if (customImplForMethodFromSpy !== void 0) {
  63. if (typeof customImplForMethodFromSpy !== "function") {
  64. throw new TypeError(
  65. "When spying on a method, the third argument (custom implementation) must be a function if provided."
  66. );
  67. }
  68. customImplementation = customImplForMethodFromSpy;
  69. }
  70. } else {
  71. if (target === null && methodNameOrImplFromSpy === void 0 && customImplForMethodFromSpy === void 0) {
  72. throw new TypeError("Attempted to spy on null.");
  73. }
  74. if (methodNameOrImplFromSpy === void 0 && typeof target !== "function") {
  75. throw new TypeError(
  76. `Attempted to spy on a ${typeof target} which is not a function.`
  77. );
  78. }
  79. throw new Error(
  80. "Invalid arguments. Valid signatures:\n createSpy(function, [customImplementationFunction])\n createSpy(object, methodNameString, [customImplementationFunction])"
  81. );
  82. }
  83. return {
  84. originalFn,
  85. // определение функции для выполнения шпионом: либо
  86. // пользовательская реализация, либо оригинальная функция
  87. fnToExecute: customImplementation || originalFn,
  88. isMethodSpy,
  89. objToSpyOn,
  90. methodName
  91. };
  92. }
  93. __name(_parseSpyArgs, "_parseSpyArgs");
  94. function createSpy(target, methodNameOrImpl, customImplForMethod) {
  95. const { originalFn, fnToExecute, isMethodSpy, objToSpyOn, methodName } = _parseSpyArgs(target, methodNameOrImpl, customImplForMethod);
  96. const callLog = {
  97. count: 0,
  98. calls: []
  99. };
  100. const spy = /* @__PURE__ */ __name(function(...args) {
  101. callLog.count++;
  102. const callInfo = {
  103. // сохранение аргументов, с которыми
  104. // был вызван шпион
  105. args: [...args],
  106. // сохранение контекста (this)
  107. // вызова шпиона
  108. thisArg: this,
  109. returnValue: void 0,
  110. error: void 0
  111. };
  112. try {
  113. callInfo.returnValue = fnToExecute.apply(this, args);
  114. callLog.calls.push(callInfo);
  115. return callInfo.returnValue;
  116. } catch (e) {
  117. callInfo.error = e;
  118. callLog.calls.push(callInfo);
  119. throw e;
  120. }
  121. }, "spy");
  122. Object.defineProperty(spy, "callCount", {
  123. get: /* @__PURE__ */ __name(() => callLog.count, "get"),
  124. enumerable: true,
  125. configurable: false
  126. });
  127. Object.defineProperty(spy, "called", {
  128. get: /* @__PURE__ */ __name(() => callLog.count > 0, "get"),
  129. enumerable: true,
  130. configurable: false
  131. });
  132. spy.getCall = (n) => {
  133. if (typeof n !== "number" || n < 0 || n >= callLog.calls.length) {
  134. throw new RangeError(
  135. `Invalid call index ${n}. Spy has ${callLog.calls.length} call(s).`
  136. );
  137. }
  138. return callLog.calls[n];
  139. };
  140. spy.calledWith = (...expectedArgs) => {
  141. return callLog.calls.some(
  142. (call) => call.args.length === expectedArgs.length && call.args.every((arg, i) => Object.is(arg, expectedArgs[i]))
  143. );
  144. };
  145. spy.nthCalledWith = (n, ...expectedArgs) => {
  146. const call = spy.getCall(n);
  147. return call.args.length === expectedArgs.length && call.args.every((arg, i) => Object.is(arg, expectedArgs[i]));
  148. };
  149. spy.nthCallReturned = (n, expectedReturnValue) => {
  150. const call = spy.getCall(n);
  151. if (call.error) return false;
  152. return Object.is(call.returnValue, expectedReturnValue);
  153. };
  154. spy.nthCallThrew = (n, expectedError) => {
  155. const call = spy.getCall(n);
  156. if (call.error === void 0) return false;
  157. if (expectedError === void 0) return true;
  158. if (call.error === expectedError) return true;
  159. if (typeof expectedError === "string") {
  160. return call.error && typeof call.error.message === "string" && call.error.message === expectedError;
  161. }
  162. if (typeof expectedError === "function" && call.error instanceof expectedError) {
  163. return true;
  164. }
  165. if (expectedError instanceof Error && call.error instanceof Error) {
  166. return call.error.name === expectedError.name && call.error.message === expectedError.message;
  167. }
  168. return Object.is(call.error, expectedError);
  169. };
  170. spy.restore = () => {
  171. if (isMethodSpy && objToSpyOn) {
  172. if (originalFn !== void 0) {
  173. objToSpyOn[methodName] = originalFn;
  174. }
  175. }
  176. callLog.count = 0;
  177. callLog.calls = [];
  178. };
  179. if (isMethodSpy && objToSpyOn) {
  180. objToSpyOn[methodName] = spy;
  181. }
  182. return spy;
  183. }
  184. __name(createSpy, "createSpy");
  185. // src/create-spies-group.js
  186. function SpiesGroup() {
  187. this.spies = [];
  188. }
  189. __name(SpiesGroup, "SpiesGroup");
  190. SpiesGroup.prototype.on = function(target, methodNameOrImpl, customImplForMethod) {
  191. const spy = createSpy(target, methodNameOrImpl, customImplForMethod);
  192. this.spies.push(spy);
  193. return spy;
  194. };
  195. SpiesGroup.prototype.restore = function() {
  196. this.spies.forEach((spy) => spy.restore());
  197. this.spies = [];
  198. return this;
  199. };
  200. function createSpiesGroup() {
  201. return new SpiesGroup();
  202. }
  203. __name(createSpiesGroup, "createSpiesGroup");
  204. // Annotate the CommonJS export names for ESM import in node:
  205. 0 && (module.exports = {
  206. SpiesGroup,
  207. createSpiesGroup,
  208. createSpy
  209. });