index.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. /*!
  2. * /**
  3. * * Copyright (c) Meta Platforms, Inc. and affiliates.
  4. * *
  5. * * This source code is licensed under the MIT license found in the
  6. * * LICENSE file in the root directory of this source tree.
  7. * * /
  8. */
  9. /******/ (() => { // webpackBootstrap
  10. /******/ "use strict";
  11. var __webpack_exports__ = {};
  12. // This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
  13. (() => {
  14. var exports = __webpack_exports__;
  15. Object.defineProperty(exports, "__esModule", ({
  16. value: true
  17. }));
  18. exports.spyOn = exports.replaceProperty = exports.mocked = exports.fn = exports.ModuleMocker = void 0;
  19. function _jestUtil() {
  20. const data = require("jest-util");
  21. _jestUtil = function () {
  22. return data;
  23. };
  24. return data;
  25. }
  26. /**
  27. * Copyright (c) Meta Platforms, Inc. and affiliates.
  28. *
  29. * This source code is licensed under the MIT license found in the
  30. * LICENSE file in the root directory of this source tree.
  31. */
  32. /// <reference lib="ESNext.Disposable" preserve="true" />
  33. /* eslint-disable local/prefer-rest-params-eventually */
  34. /**
  35. * All what the internal typings need is to be sure that we have any-function.
  36. * `FunctionLike` type ensures that and helps to constrain the type as well.
  37. * The default of `UnknownFunction` makes sure that `any`s do not leak to the
  38. * user side. For instance, calling `fn()` without implementation will return
  39. * a mock of `(...args: Array<unknown>) => unknown` type. If implementation
  40. * is provided, its typings are inferred correctly.
  41. */
  42. const MOCK_CONSTRUCTOR_NAME = 'mockConstructor';
  43. const FUNCTION_NAME_RESERVED_PATTERN = /[\s!-/:-@[-`{-~]/;
  44. const FUNCTION_NAME_RESERVED_REPLACE = new RegExp(FUNCTION_NAME_RESERVED_PATTERN.source, 'g');
  45. const RESERVED_KEYWORDS = new Set(['arguments', 'await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'enum', 'eval', 'export', 'extends', 'false', 'finally', 'for', 'function', 'if', 'implements', 'import', 'in', 'instanceof', 'interface', 'let', 'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'static', 'super', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield']);
  46. function matchArity(fn, length) {
  47. let mockConstructor;
  48. switch (length) {
  49. case 1:
  50. mockConstructor = function (_a) {
  51. return fn.apply(this, arguments);
  52. };
  53. break;
  54. case 2:
  55. mockConstructor = function (_a, _b) {
  56. return fn.apply(this, arguments);
  57. };
  58. break;
  59. case 3:
  60. mockConstructor = function (_a, _b, _c) {
  61. return fn.apply(this, arguments);
  62. };
  63. break;
  64. case 4:
  65. mockConstructor = function (_a, _b, _c, _d) {
  66. return fn.apply(this, arguments);
  67. };
  68. break;
  69. case 5:
  70. mockConstructor = function (_a, _b, _c, _d, _e) {
  71. return fn.apply(this, arguments);
  72. };
  73. break;
  74. case 6:
  75. mockConstructor = function (_a, _b, _c, _d, _e, _f) {
  76. return fn.apply(this, arguments);
  77. };
  78. break;
  79. case 7:
  80. mockConstructor = function (_a, _b, _c, _d, _e, _f, _g) {
  81. return fn.apply(this, arguments);
  82. };
  83. break;
  84. case 8:
  85. mockConstructor = function (_a, _b, _c, _d, _e, _f, _g, _h) {
  86. return fn.apply(this, arguments);
  87. };
  88. break;
  89. case 9:
  90. mockConstructor = function (_a, _b, _c, _d, _e, _f, _g, _h, _i) {
  91. return fn.apply(this, arguments);
  92. };
  93. break;
  94. default:
  95. mockConstructor = function () {
  96. return fn.apply(this, arguments);
  97. };
  98. break;
  99. }
  100. return mockConstructor;
  101. }
  102. function getObjectType(value) {
  103. return Object.prototype.toString.apply(value).slice(8, -1);
  104. }
  105. function getType(ref) {
  106. const typeName = getObjectType(ref);
  107. if (typeName === 'Function' || typeName === 'AsyncFunction' || typeName === 'GeneratorFunction' || typeName === 'AsyncGeneratorFunction') {
  108. return 'function';
  109. } else if (Array.isArray(ref)) {
  110. return 'array';
  111. } else if (typeName === 'Object' || typeName === 'Module') {
  112. return 'object';
  113. } else if (typeName === 'Number' || typeName === 'String' || typeName === 'Boolean' || typeName === 'Symbol') {
  114. return 'constant';
  115. } else if (typeName === 'Map' || typeName === 'WeakMap' || typeName === 'Set') {
  116. return 'collection';
  117. } else if (typeName === 'RegExp') {
  118. return 'regexp';
  119. } else if (ref === undefined) {
  120. return 'undefined';
  121. } else if (ref === null) {
  122. return 'null';
  123. } else {
  124. return null;
  125. }
  126. }
  127. function isReadonlyProp(object, prop) {
  128. if (prop === 'arguments' || prop === 'caller' || prop === 'callee' || prop === 'name' || prop === 'length') {
  129. const typeName = getObjectType(object);
  130. return typeName === 'Function' || typeName === 'AsyncFunction' || typeName === 'GeneratorFunction' || typeName === 'AsyncGeneratorFunction';
  131. }
  132. if (prop === 'source' || prop === 'global' || prop === 'ignoreCase' || prop === 'multiline') {
  133. return getObjectType(object) === 'RegExp';
  134. }
  135. return false;
  136. }
  137. class ModuleMocker {
  138. _environmentGlobal;
  139. _mockState;
  140. _mockConfigRegistry;
  141. _spyState;
  142. _invocationCallCounter;
  143. /**
  144. * @see README.md
  145. * @param global Global object of the test environment, used to create
  146. * mocks
  147. */
  148. constructor(global) {
  149. this._environmentGlobal = global;
  150. this._mockState = new WeakMap();
  151. this._mockConfigRegistry = new WeakMap();
  152. this._spyState = new Set();
  153. this._invocationCallCounter = 1;
  154. }
  155. _getSlots(object) {
  156. if (!object) {
  157. return [];
  158. }
  159. const slots = new Set();
  160. const EnvObjectProto = this._environmentGlobal.Object.prototype;
  161. const EnvFunctionProto = this._environmentGlobal.Function.prototype;
  162. const EnvRegExpProto = this._environmentGlobal.RegExp.prototype;
  163. // Also check the builtins in the current context as they leak through
  164. // core node modules.
  165. const ObjectProto = Object.prototype;
  166. const FunctionProto = Function.prototype;
  167. const RegExpProto = RegExp.prototype;
  168. // Properties of Object.prototype, Function.prototype and RegExp.prototype
  169. // are never reported as slots
  170. while (object != null && object !== EnvObjectProto && object !== EnvFunctionProto && object !== EnvRegExpProto && object !== ObjectProto && object !== FunctionProto && object !== RegExpProto) {
  171. const ownNames = Object.getOwnPropertyNames(object);
  172. for (const prop of ownNames) {
  173. if (!isReadonlyProp(object, prop)) {
  174. const propDesc = Object.getOwnPropertyDescriptor(object, prop);
  175. if (propDesc !== undefined && !propDesc.get || object.__esModule) {
  176. slots.add(prop);
  177. }
  178. }
  179. }
  180. object = Object.getPrototypeOf(object);
  181. }
  182. return [...slots];
  183. }
  184. _ensureMockConfig(f) {
  185. let config = this._mockConfigRegistry.get(f);
  186. if (!config) {
  187. config = this._defaultMockConfig();
  188. this._mockConfigRegistry.set(f, config);
  189. }
  190. return config;
  191. }
  192. _ensureMockState(f) {
  193. let state = this._mockState.get(f);
  194. if (!state) {
  195. state = this._defaultMockState();
  196. this._mockState.set(f, state);
  197. }
  198. if (state.calls.length > 0) {
  199. state.lastCall = state.calls.at(-1);
  200. }
  201. return state;
  202. }
  203. _defaultMockConfig() {
  204. return {
  205. mockImpl: undefined,
  206. mockName: 'jest.fn()',
  207. specificMockImpls: []
  208. };
  209. }
  210. _defaultMockState() {
  211. return {
  212. calls: [],
  213. contexts: [],
  214. instances: [],
  215. invocationCallOrder: [],
  216. results: []
  217. };
  218. }
  219. /* eslint-disable @typescript-eslint/unified-signatures */
  220. /* eslint-enable @typescript-eslint/unified-signatures */
  221. _makeComponent(metadata, restore) {
  222. if (metadata.type === 'object') {
  223. return new this._environmentGlobal.Object();
  224. } else if (metadata.type === 'array') {
  225. return new this._environmentGlobal.Array();
  226. } else if (metadata.type === 'regexp') {
  227. return new this._environmentGlobal.RegExp('');
  228. } else if (metadata.type === 'constant' || metadata.type === 'collection' || metadata.type === 'null' || metadata.type === 'undefined') {
  229. return metadata.value;
  230. } else if (metadata.type === 'function') {
  231. const prototype = metadata.members?.prototype?.members ?? {};
  232. const prototypeSlots = this._getSlots(prototype);
  233. // eslint-disable-next-line @typescript-eslint/no-this-alias
  234. const mocker = this;
  235. const mockConstructor = matchArity(function (...args) {
  236. const mockState = mocker._ensureMockState(f);
  237. const mockConfig = mocker._ensureMockConfig(f);
  238. mockState.instances.push(this);
  239. mockState.contexts.push(this);
  240. mockState.calls.push(args);
  241. // Create and record an "incomplete" mock result immediately upon
  242. // calling rather than waiting for the mock to return. This avoids
  243. // issues caused by recursion where results can be recorded in the
  244. // wrong order.
  245. const mockResult = {
  246. type: 'incomplete',
  247. value: undefined
  248. };
  249. mockState.results.push(mockResult);
  250. mockState.invocationCallOrder.push(mocker._invocationCallCounter++);
  251. // Will be set to the return value of the mock if an error is not thrown
  252. let finalReturnValue;
  253. // Will be set to the error that is thrown by the mock (if it throws)
  254. let thrownError;
  255. // Will be set to true if the mock throws an error. The presence of a
  256. // value in `thrownError` is not a 100% reliable indicator because a
  257. // function could throw a value of undefined.
  258. let callDidThrowError = false;
  259. try {
  260. // The bulk of the implementation is wrapped in an immediately
  261. // executed arrow function so the return value of the mock function
  262. // can be easily captured and recorded, despite the many separate
  263. // return points within the logic.
  264. finalReturnValue = (() => {
  265. if (this instanceof f) {
  266. // This is probably being called as a constructor
  267. for (const slot of prototypeSlots) {
  268. // Copy prototype methods to the instance to make
  269. // it easier to interact with mock instance call and
  270. // return values
  271. if (prototype[slot].type === 'function') {
  272. // @ts-expect-error no index signature
  273. const protoImpl = this[slot];
  274. // @ts-expect-error no index signature
  275. this[slot] = mocker.generateFromMetadata(prototype[slot]);
  276. // @ts-expect-error no index signature
  277. this[slot]._protoImpl = protoImpl;
  278. }
  279. }
  280. // Run the mock constructor implementation
  281. const mockImpl = mockConfig.specificMockImpls.length > 0 ? mockConfig.specificMockImpls.shift() : mockConfig.mockImpl;
  282. return mockImpl && mockImpl.apply(this, arguments);
  283. }
  284. // If mockImplementationOnce()/mockImplementation() is last set,
  285. // implementation use the mock
  286. let specificMockImpl = mockConfig.specificMockImpls.shift();
  287. if (specificMockImpl === undefined) {
  288. specificMockImpl = mockConfig.mockImpl;
  289. }
  290. if (specificMockImpl) {
  291. return specificMockImpl.apply(this, arguments);
  292. }
  293. // Otherwise use prototype implementation
  294. if (f._protoImpl) {
  295. return f._protoImpl.apply(this, arguments);
  296. }
  297. return undefined;
  298. })();
  299. } catch (error) {
  300. // Store the thrown error so we can record it, then re-throw it.
  301. thrownError = error;
  302. callDidThrowError = true;
  303. throw error;
  304. } finally {
  305. // Record the result of the function.
  306. // NOTE: Intentionally NOT pushing/indexing into the array of mock
  307. // results here to avoid corrupting results data if mockClear()
  308. // is called during the execution of the mock.
  309. // @ts-expect-error reassigning 'incomplete'
  310. mockResult.type = callDidThrowError ? 'throw' : 'return';
  311. mockResult.value = callDidThrowError ? thrownError : finalReturnValue;
  312. }
  313. return finalReturnValue;
  314. }, metadata.length || 0);
  315. const f = this._createMockFunction(metadata, mockConstructor);
  316. f._isMockFunction = true;
  317. f.getMockImplementation = () => this._ensureMockConfig(f).mockImpl;
  318. if (typeof restore === 'function') {
  319. this._spyState.add(restore);
  320. }
  321. this._mockState.set(f, this._defaultMockState());
  322. this._mockConfigRegistry.set(f, this._defaultMockConfig());
  323. Object.defineProperty(f, 'mock', {
  324. configurable: false,
  325. enumerable: true,
  326. get: () => this._ensureMockState(f),
  327. set: val => this._mockState.set(f, val)
  328. });
  329. f.mockClear = () => {
  330. this._mockState.delete(f);
  331. return f;
  332. };
  333. f.mockReset = () => {
  334. f.mockClear();
  335. this._mockConfigRegistry.delete(f);
  336. return f;
  337. };
  338. f.mockRestore = () => {
  339. f.mockReset();
  340. return restore ? restore() : undefined;
  341. };
  342. f.mockReturnValueOnce = value =>
  343. // next function call will return this value or default return value
  344. f.mockImplementationOnce(() => value);
  345. f.mockResolvedValueOnce = value => f.mockImplementationOnce(() => this._environmentGlobal.Promise.resolve(value));
  346. f.mockRejectedValueOnce = value => f.mockImplementationOnce(() => this._environmentGlobal.Promise.reject(value));
  347. f.mockReturnValue = value =>
  348. // next function call will return specified return value or this one
  349. f.mockImplementation(() => value);
  350. f.mockResolvedValue = value => f.mockImplementation(() => this._environmentGlobal.Promise.resolve(value));
  351. f.mockRejectedValue = value => f.mockImplementation(() => this._environmentGlobal.Promise.reject(value));
  352. f.mockImplementationOnce = fn => {
  353. // next function call will use this mock implementation return value
  354. // or default mock implementation return value
  355. const mockConfig = this._ensureMockConfig(f);
  356. mockConfig.specificMockImpls.push(fn);
  357. return f;
  358. };
  359. f.withImplementation = withImplementation.bind(this);
  360. if (Symbol.dispose) {
  361. f[Symbol.dispose] = f.mockRestore;
  362. }
  363. function withImplementation(fn, callback) {
  364. // Remember previous mock implementation, then set new one
  365. const mockConfig = this._ensureMockConfig(f);
  366. const previousImplementation = mockConfig.mockImpl;
  367. const previousSpecificImplementations = mockConfig.specificMockImpls;
  368. mockConfig.mockImpl = fn;
  369. mockConfig.specificMockImpls = [];
  370. const returnedValue = callback();
  371. if ((0, _jestUtil().isPromise)(returnedValue)) {
  372. return returnedValue.then(() => {
  373. mockConfig.mockImpl = previousImplementation;
  374. mockConfig.specificMockImpls = previousSpecificImplementations;
  375. });
  376. } else {
  377. mockConfig.mockImpl = previousImplementation;
  378. mockConfig.specificMockImpls = previousSpecificImplementations;
  379. }
  380. }
  381. f.mockImplementation = fn => {
  382. // next function call will use mock implementation return value
  383. const mockConfig = this._ensureMockConfig(f);
  384. mockConfig.mockImpl = fn;
  385. return f;
  386. };
  387. f.mockReturnThis = () => f.mockImplementation(function () {
  388. return this;
  389. });
  390. f.mockName = name => {
  391. if (name) {
  392. const mockConfig = this._ensureMockConfig(f);
  393. mockConfig.mockName = name;
  394. }
  395. return f;
  396. };
  397. f.getMockName = () => {
  398. const mockConfig = this._ensureMockConfig(f);
  399. return mockConfig.mockName || 'jest.fn()';
  400. };
  401. if (metadata.mockImpl) {
  402. f.mockImplementation(metadata.mockImpl);
  403. }
  404. return f;
  405. } else {
  406. const unknownType = metadata.type || 'undefined type';
  407. throw new Error(`Unrecognized type ${unknownType}`);
  408. }
  409. }
  410. _createMockFunction(metadata, mockConstructor) {
  411. let name = metadata.name;
  412. if (!name) {
  413. return mockConstructor;
  414. }
  415. // Preserve `name` property of mocked function.
  416. const boundFunctionPrefix = 'bound ';
  417. let bindCall = '';
  418. // if-do-while for perf reasons. The common case is for the if to fail.
  419. if (name.startsWith(boundFunctionPrefix)) {
  420. do {
  421. name = name.slice(boundFunctionPrefix.length);
  422. // Call bind() just to alter the function name.
  423. bindCall = '.bind(null)';
  424. } while (name && name.startsWith(boundFunctionPrefix));
  425. }
  426. // Special case functions named `mockConstructor` to guard for infinite loops
  427. if (name === MOCK_CONSTRUCTOR_NAME) {
  428. return mockConstructor;
  429. }
  430. if (
  431. // It's a syntax error to define functions with a reserved keyword as name
  432. RESERVED_KEYWORDS.has(name) ||
  433. // It's also a syntax error to define functions with a name that starts with a number
  434. /^\d/.test(name)) {
  435. name = `$${name}`;
  436. }
  437. // It's also a syntax error to define a function with a reserved character
  438. // as part of it's name.
  439. if (FUNCTION_NAME_RESERVED_PATTERN.test(name)) {
  440. name = name.replaceAll(FUNCTION_NAME_RESERVED_REPLACE, '$');
  441. }
  442. const body = `return function ${name}() {` + ` return ${MOCK_CONSTRUCTOR_NAME}.apply(this,arguments);` + `}${bindCall}`;
  443. const createConstructor = new this._environmentGlobal.Function(MOCK_CONSTRUCTOR_NAME, body);
  444. return createConstructor(mockConstructor);
  445. }
  446. _generateMock(metadata, callbacks, refs) {
  447. const mock = this._makeComponent(metadata);
  448. if (metadata.refID != null) {
  449. refs[metadata.refID] = mock;
  450. }
  451. for (const slot of this._getSlots(metadata.members)) {
  452. const slotMetadata = metadata.members && metadata.members[slot] || {};
  453. if (slotMetadata.ref == null) {
  454. mock[slot] = this._generateMock(slotMetadata, callbacks, refs);
  455. } else {
  456. callbacks.push(function (ref) {
  457. return () => mock[slot] = refs[ref];
  458. }(slotMetadata.ref));
  459. }
  460. }
  461. if (metadata.type !== 'undefined' && metadata.type !== 'null' && mock.prototype && typeof mock.prototype === 'object') {
  462. mock.prototype.constructor = mock;
  463. }
  464. return mock;
  465. }
  466. /**
  467. * Check whether the given property of an object has been already replaced.
  468. */
  469. _findReplacedProperty(object, propertyKey) {
  470. for (const spyState of this._spyState) {
  471. if ('object' in spyState && 'property' in spyState && spyState.object === object && spyState.property === propertyKey) {
  472. return spyState;
  473. }
  474. }
  475. return;
  476. }
  477. /**
  478. * @see README.md
  479. * @param metadata Metadata for the mock in the schema returned by the
  480. * getMetadata method of this module.
  481. */
  482. generateFromMetadata(metadata) {
  483. const callbacks = [];
  484. const refs = {};
  485. const mock = this._generateMock(metadata, callbacks, refs);
  486. for (const setter of callbacks) setter();
  487. return mock;
  488. }
  489. /**
  490. * @see README.md
  491. * @param component The component for which to retrieve metadata.
  492. */
  493. getMetadata(component, _refs) {
  494. const refs = _refs || new Map();
  495. const ref = refs.get(component);
  496. if (ref != null) {
  497. return {
  498. ref
  499. };
  500. }
  501. const type = getType(component);
  502. if (!type) {
  503. return null;
  504. }
  505. const metadata = {
  506. type
  507. };
  508. if (type === 'constant' || type === 'collection' || type === 'undefined' || type === 'null') {
  509. metadata.value = component;
  510. return metadata;
  511. } else if (type === 'function') {
  512. // @ts-expect-error component is a function so it has a name, but not
  513. // necessarily a string: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#function_names_in_classes
  514. const componentName = component.name;
  515. if (typeof componentName === 'string') {
  516. metadata.name = componentName;
  517. }
  518. if (this.isMockFunction(component)) {
  519. metadata.mockImpl = component.getMockImplementation();
  520. }
  521. }
  522. metadata.refID = refs.size;
  523. refs.set(component, metadata.refID);
  524. let members = null;
  525. // Leave arrays alone
  526. if (type !== 'array') {
  527. // @ts-expect-error component is object
  528. for (const slot of this._getSlots(component)) {
  529. if (type === 'function' && this.isMockFunction(component) && slot.startsWith('mock')) {
  530. continue;
  531. }
  532. // @ts-expect-error no index signature
  533. const slotMetadata = this.getMetadata(component[slot], refs);
  534. if (slotMetadata) {
  535. if (!members) {
  536. members = {};
  537. }
  538. members[slot] = slotMetadata;
  539. }
  540. }
  541. }
  542. if (members) {
  543. metadata.members = members;
  544. }
  545. return metadata;
  546. }
  547. isMockFunction(fn) {
  548. return fn != null && fn._isMockFunction === true;
  549. }
  550. fn(implementation) {
  551. const length = implementation ? implementation.length : 0;
  552. const fn = this._makeComponent({
  553. length,
  554. type: 'function'
  555. });
  556. if (implementation) {
  557. fn.mockImplementation(implementation);
  558. }
  559. return fn;
  560. }
  561. spyOn(object, methodKey, accessType) {
  562. if (object == null || typeof object !== 'object' && typeof object !== 'function') {
  563. throw new Error(`Cannot use spyOn on a primitive value; ${this._typeOf(object)} given`);
  564. }
  565. if (methodKey == null) {
  566. throw new Error('No property name supplied');
  567. }
  568. if (accessType) {
  569. return this._spyOnProperty(object, methodKey, accessType);
  570. }
  571. const original = object[methodKey];
  572. if (!original) {
  573. throw new Error(`Property \`${String(methodKey)}\` does not exist in the provided object`);
  574. }
  575. if (!this.isMockFunction(original)) {
  576. if (typeof original !== 'function') {
  577. throw new TypeError(`Cannot spy on the \`${String(methodKey)}\` property because it is not a function; ${this._typeOf(original)} given instead.${typeof original === 'object' ? '' : ` If you are trying to mock a property, use \`jest.replaceProperty(object, '${String(methodKey)}', value)\` instead.`}`);
  578. }
  579. const isMethodOwner = Object.prototype.hasOwnProperty.call(object, methodKey);
  580. let descriptor = Object.getOwnPropertyDescriptor(object, methodKey);
  581. let proto = Object.getPrototypeOf(object);
  582. while (!descriptor && proto !== null) {
  583. descriptor = Object.getOwnPropertyDescriptor(proto, methodKey);
  584. proto = Object.getPrototypeOf(proto);
  585. }
  586. let mock;
  587. if (descriptor && descriptor.get) {
  588. const originalGet = descriptor.get;
  589. mock = this._makeComponent({
  590. type: 'function'
  591. }, () => {
  592. descriptor.get = originalGet;
  593. Object.defineProperty(object, methodKey, descriptor);
  594. });
  595. descriptor.get = () => mock;
  596. Object.defineProperty(object, methodKey, descriptor);
  597. } else {
  598. mock = this._makeComponent({
  599. type: 'function'
  600. }, () => {
  601. if (isMethodOwner) {
  602. object[methodKey] = original;
  603. } else {
  604. delete object[methodKey];
  605. }
  606. });
  607. // @ts-expect-error overriding original method with a Mock
  608. object[methodKey] = mock;
  609. }
  610. mock.mockImplementation(function () {
  611. return original.apply(this, arguments);
  612. });
  613. }
  614. return object[methodKey];
  615. }
  616. _spyOnProperty(object, propertyKey, accessType) {
  617. let descriptor = Object.getOwnPropertyDescriptor(object, propertyKey);
  618. let proto = Object.getPrototypeOf(object);
  619. while (!descriptor && proto !== null) {
  620. descriptor = Object.getOwnPropertyDescriptor(proto, propertyKey);
  621. proto = Object.getPrototypeOf(proto);
  622. }
  623. if (!descriptor) {
  624. throw new Error(`Property \`${String(propertyKey)}\` does not exist in the provided object`);
  625. }
  626. if (!descriptor.configurable) {
  627. throw new Error(`Property \`${String(propertyKey)}\` is not declared configurable`);
  628. }
  629. if (!descriptor[accessType]) {
  630. throw new Error(`Property \`${String(propertyKey)}\` does not have access type ${accessType}`);
  631. }
  632. const original = descriptor[accessType];
  633. if (!this.isMockFunction(original)) {
  634. if (typeof original !== 'function') {
  635. throw new TypeError(`Cannot spy on the ${String(propertyKey)} property because it is not a function; ${this._typeOf(original)} given instead.${typeof original === 'object' ? '' : ` If you are trying to mock a property, use \`jest.replaceProperty(object, '${String(propertyKey)}', value)\` instead.`}`);
  636. }
  637. descriptor[accessType] = this._makeComponent({
  638. type: 'function'
  639. }, () => {
  640. // @ts-expect-error: mock is assignable
  641. descriptor[accessType] = original;
  642. Object.defineProperty(object, propertyKey, descriptor);
  643. });
  644. descriptor[accessType].mockImplementation(function () {
  645. // @ts-expect-error - wrong context
  646. return original.apply(this, arguments);
  647. });
  648. }
  649. Object.defineProperty(object, propertyKey, descriptor);
  650. return descriptor[accessType];
  651. }
  652. replaceProperty(object, propertyKey, value) {
  653. if (object == null || typeof object !== 'object' && typeof object !== 'function') {
  654. throw new Error(`Cannot use replaceProperty on a primitive value; ${this._typeOf(object)} given`);
  655. }
  656. if (propertyKey == null) {
  657. throw new Error('No property name supplied');
  658. }
  659. let descriptor = Object.getOwnPropertyDescriptor(object, propertyKey);
  660. let proto = Object.getPrototypeOf(object);
  661. while (!descriptor && proto !== null) {
  662. descriptor = Object.getOwnPropertyDescriptor(proto, propertyKey);
  663. proto = Object.getPrototypeOf(proto);
  664. }
  665. if (!descriptor) {
  666. throw new Error(`Property \`${String(propertyKey)}\` does not exist in the provided object`);
  667. }
  668. if (!descriptor.configurable) {
  669. throw new Error(`Property \`${String(propertyKey)}\` is not declared configurable`);
  670. }
  671. if (descriptor.get !== undefined) {
  672. throw new Error(`Cannot replace the \`${String(propertyKey)}\` property because it has a getter. Use \`jest.spyOn(object, '${String(propertyKey)}', 'get').mockReturnValue(value)\` instead.`);
  673. }
  674. if (descriptor.set !== undefined) {
  675. throw new Error(`Cannot replace the \`${String(propertyKey)}\` property because it has a setter. Use \`jest.spyOn(object, '${String(propertyKey)}', 'set').mockReturnValue(value)\` instead.`);
  676. }
  677. if (typeof descriptor.value === 'function') {
  678. throw new TypeError(`Cannot replace the \`${String(propertyKey)}\` property because it is a function. Use \`jest.spyOn(object, '${String(propertyKey)}')\` instead.`);
  679. }
  680. const existingRestore = this._findReplacedProperty(object, propertyKey);
  681. if (existingRestore) {
  682. return existingRestore.replaced.replaceValue(value);
  683. }
  684. const isPropertyOwner = Object.prototype.hasOwnProperty.call(object, propertyKey);
  685. const originalValue = descriptor.value;
  686. const restore = () => {
  687. if (isPropertyOwner) {
  688. object[propertyKey] = originalValue;
  689. } else {
  690. delete object[propertyKey];
  691. }
  692. };
  693. const replaced = {
  694. replaceValue: value => {
  695. object[propertyKey] = value;
  696. return replaced;
  697. },
  698. restore: () => {
  699. restore();
  700. this._spyState.delete(restore);
  701. }
  702. };
  703. restore.object = object;
  704. restore.property = propertyKey;
  705. restore.replaced = replaced;
  706. this._spyState.add(restore);
  707. return replaced.replaceValue(value);
  708. }
  709. clearAllMocks() {
  710. this._mockState = new WeakMap();
  711. }
  712. resetAllMocks() {
  713. this._mockConfigRegistry = new WeakMap();
  714. this._mockState = new WeakMap();
  715. }
  716. restoreAllMocks() {
  717. for (const restore of this._spyState) restore();
  718. this._spyState = new Set();
  719. }
  720. _typeOf(value) {
  721. return value == null ? `${value}` : typeof value;
  722. }
  723. mocked(source, _options) {
  724. return source;
  725. }
  726. }
  727. exports.ModuleMocker = ModuleMocker;
  728. const JestMock = new ModuleMocker(globalThis);
  729. const fn = exports.fn = JestMock.fn.bind(JestMock);
  730. const spyOn = exports.spyOn = JestMock.spyOn.bind(JestMock);
  731. const mocked = exports.mocked = JestMock.mocked.bind(JestMock);
  732. const replaceProperty = exports.replaceProperty = JestMock.replaceProperty.bind(JestMock);
  733. })();
  734. module.exports = __webpack_exports__;
  735. /******/ })()
  736. ;