Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 24KB

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