spy.mjs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import * as tinyspy from 'tinyspy';
  2. const spies = /* @__PURE__ */ new Set();
  3. function isMockFunction(fn2) {
  4. return typeof fn2 === "function" && "_isMockFunction" in fn2 && fn2._isMockFunction;
  5. }
  6. function spyOn(obj, method, accessType) {
  7. const dictionary = {
  8. get: "getter",
  9. set: "setter"
  10. };
  11. const objMethod = accessType ? { [dictionary[accessType]]: method } : method;
  12. const stub = tinyspy.spyOn(obj, objMethod);
  13. return enhanceSpy(stub);
  14. }
  15. let callOrder = 0;
  16. function enhanceSpy(spy) {
  17. const stub = spy;
  18. let implementation;
  19. let instances = [];
  20. let invocations = [];
  21. const mockContext = {
  22. get calls() {
  23. return stub.calls;
  24. },
  25. get instances() {
  26. return instances;
  27. },
  28. get invocationCallOrder() {
  29. return invocations;
  30. },
  31. get results() {
  32. return stub.results.map(([callType, value]) => {
  33. const type = callType === "error" ? "throw" : "return";
  34. return { type, value };
  35. });
  36. },
  37. get lastCall() {
  38. return stub.calls[stub.calls.length - 1];
  39. }
  40. };
  41. let onceImplementations = [];
  42. let name = stub.name;
  43. stub.getMockName = () => name || "vi.fn()";
  44. stub.mockName = (n) => {
  45. name = n;
  46. return stub;
  47. };
  48. stub.mockClear = () => {
  49. stub.reset();
  50. instances = [];
  51. invocations = [];
  52. return stub;
  53. };
  54. stub.mockReset = () => {
  55. stub.mockClear();
  56. implementation = () => void 0;
  57. onceImplementations = [];
  58. return stub;
  59. };
  60. stub.mockRestore = () => {
  61. stub.mockReset();
  62. implementation = void 0;
  63. return stub;
  64. };
  65. stub.getMockImplementation = () => implementation;
  66. stub.mockImplementation = (fn2) => {
  67. implementation = fn2;
  68. return stub;
  69. };
  70. stub.mockImplementationOnce = (fn2) => {
  71. onceImplementations.push(fn2);
  72. return stub;
  73. };
  74. stub.mockReturnThis = () => stub.mockImplementation(function() {
  75. return this;
  76. });
  77. stub.mockReturnValue = (val) => stub.mockImplementation(() => val);
  78. stub.mockReturnValueOnce = (val) => stub.mockImplementationOnce(() => val);
  79. stub.mockResolvedValue = (val) => stub.mockImplementation(() => Promise.resolve(val));
  80. stub.mockResolvedValueOnce = (val) => stub.mockImplementationOnce(() => Promise.resolve(val));
  81. stub.mockRejectedValue = (val) => stub.mockImplementation(() => Promise.reject(val));
  82. stub.mockRejectedValueOnce = (val) => stub.mockImplementationOnce(() => Promise.reject(val));
  83. Object.defineProperty(stub, "mock", {
  84. get: () => mockContext
  85. });
  86. stub.willCall(function(...args) {
  87. instances.push(this);
  88. invocations.push(++callOrder);
  89. const impl = onceImplementations.shift() || implementation || stub.getOriginal() || (() => {
  90. });
  91. return impl.apply(this, args);
  92. });
  93. spies.add(stub);
  94. return stub;
  95. }
  96. function fn(implementation) {
  97. return enhanceSpy(tinyspy.spyOn({ fn: implementation || (() => {
  98. }) }, "fn"));
  99. }
  100. export { fn, isMockFunction, spies, spyOn };