plugins/SnapshotPlugin.js

// use jest-like snapshots, can use with observable hooks...
// const snapshots = {}

const toarr = require('to-arr')

const SnapshotPlugin = {
  init(thisArg) {
    thisArg.snapshots = {
      ast: {},
      str: {},
    }
  },

  // ---

  /**
   * @private
   * @param  {*} state
   * @return {*} code generated state
   */
  getAst(state) {
    const {generate} = require('escodegen')
    const parsedState = generate(state)
    return parsedState
  },

  /**
   * @param  {String} [type='ast'] snapshot type to use
   * @param  {Number} [index=1]    index starting from last to use
   * @return {*} snapshot
   */
  getSnapshot(type = 'ast', index = 1) {
    const store = this.snapshots[type]
    const keys = Object.keys(store)
    const keyIndex = keys.length - index
    const key = keys[keyIndex]
    const state = store[key]

    if (type === 'ast') return this.getAst(state)
    return state
  },

  // ---

  /**
   * @private
   * @param  {*} state
   * @param  {number} [now=Date.now()]
   * @return {ObjChain} @chainable
   */
  snapAst(state, now = Date.now()) {
    const lave = require('lave')
    const snap = lave(state)
    this.snapshots.ast[now] = snap
    return this
  },

  /**
   * @private
   * @param  {*} state
   * @param  {number} [now=Date.now()]
   * @return {ObjChain} @chainable
   */
  snapStr(state, now = Date.now()) {
    const stringify = require('javascript-stringify')
    const snap = stringify(state)
    this.snapshots.str[now] = snap
    return this
  },

  /**
   * @param  {Array<string> | string} [types=['ast']] [ast, stringify]
   * @param  {Array<string> | string} [props=['data']] properties to snapshot
   * @return {ObjChain} @chainable
   */
  snapshot(types = ['ast'], props = ['data']) {
    const now = Date.now()
    const state = {}

    toarr(props).forEach(prop => (state[prop] = this[prop]))
    toarr(types).forEach(type => {
      if (type === 'ast') this.snapAst(state, now)
      else this.snapStr(state, now)
    })

    return this
  },
}

module.exports = SnapshotPlugin