UNPKG

muk-prop

Version:

Mock object methods and properties.

82 lines (71 loc) 1.82 kB
'use strict'; // Keep track of mocks let mocks = []; const cache = new Map(); /** * Mocks a value of an object. * * @param {Object} obj * @param {string} key * @param {any} value */ const method = module.exports = (obj, key, value) => { const hasOwn = Object.prototype.hasOwnProperty; const hasOwnProperty = hasOwn.call(obj, key); mocks.push({ obj, key, descriptor: Object.getOwnPropertyDescriptor(obj, key), // Make sure the key exists on object not the prototype hasOwnProperty, }); // Delete the origin key, redefine it below if (hasOwnProperty) { delete obj[key]; } // Set a flag that checks if it is mocked let flag = cache.get(obj); if (!flag) { flag = new Set(); cache.set(obj, flag); } flag.add(key); const descriptor = { configurable: true, enumerable: true, }; // Map.prototype.get/set are not valid getter/setter const hasGetter = value && hasOwn.call(value, 'get'); const hasSetter = value && hasOwn.call(value, 'set'); if (hasGetter || hasSetter) { // Default to undefined descriptor.get = value.get; descriptor.set = value.set; } else { // Without getter/setter mode descriptor.value = value; descriptor.writable = true; } Object.defineProperty(obj, key, descriptor); }; /** * Restore all mocks */ method.restore = () => { for (let i = mocks.length - 1; i >= 0; i--) { let m = mocks[i]; if (!m.hasOwnProperty) { // Delete the mock key, use key on the prototype delete m.obj[m.key]; } else { // Redefine the origin key instead of the mock key Object.defineProperty(m.obj, m.key, m.descriptor); } } mocks = []; cache.clear(); }; method.isMocked = (obj, key) => { let flag = cache.get(obj); return flag ? flag.has(key) : false; };