okunishinishi/node-injectmock

View on GitHub
injectmock.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * Inject mock property to object(or module).
 * Useful to inject mock on unit test and restore safely after done.
 * @function injectmock
 * @param {object} module - Module to injected.
 * @param {string} key - Injection key.
 * @param {*} value - Value to inject.
 */

/**
 * Restore injected.
 * @name injectmock.restore
 * @function
 * @param {object} module - Module to injected.
 * @param {string} key - Injection key.
 */

/**
 * Restore all injected.
 * @name injectmock.restoreAll
 * @function
 */

'use strict'

/**
 * Inject mock functions to node modules.
 * @memberof injectmock
 * @inner
 * @constructor Injector
 */
function Injector () {
  const s = this
  s.injections = []
}
Injector.prototype = {
  /**
   * Inject a mock to a module.
   * @param {object} module - Module to injected.
   * @param {string} key - Injection key.
   * @param {*} value - Value to inject.
   * @returns {*} - Returns self.
   */
  inject (module, key, value) {
    const s = this
    s.injections.unshift({
      module: module,
      key: key,
      delete: !module.hasOwnProperty(key),
      origin: module[ key ],
      value: value
    })
    module[ key ] = value
    return s
  },
  /**
   * Restore injected.
   * @param {object} module - Module to injected.
   * @param {string} key - Injection key.
   * @returns {*} - Returns self.
   */
  restore (module, key) {
    const s = this
    var index = s._indexOfInjection(module, key)
    var injection = s.injections[ index ]
    if (injection) {
      if (injection.delete) {
        delete module[ key ]
      } else {
        module[ key ] = injection.origin
      }
      s.injections.splice(index, 1)
    } else {
      // Do nothing.
    }
    return s
  },
  /**
   * Restore all injected.
   * @returns {*} - Returns self.
   */
  restoreAll () {
    const s = this
    while (s.injections.length) {
      var injection = s.injections[ 0 ]
      s.restore(injection.module, injection.key)
    }
    return s
  },
  _indexOfInjection (module, key) {
    const s = this
    for (var i = 0, len = s.injections.length; i < len; i++) {
      let injection = s.injections[ i ]
      let hit = (injection.key === key) && (injection.module === module)
      if (hit) {
        return i
      }
    }
    return -1
  }
}

function context () {
  var injector = new Injector()
  var inject = injector.inject.bind(injector)
  inject.restore = injector.restore.bind(injector)
  inject.restoreAll = injector.restoreAll.bind(injector)
  return inject
}

var injectmock = context()

/**
 * Create new injectmock context.
 * @name injectmock.new
 * @function
 * @returns {injectmock} - New injectmock context.
 */
injectmock.new = context
/**
 * Do nothing.
 */
injectmock.noop = function () {

}

module.exports = injectmock