index.js 22 KB

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