All files / lib parse-model.js

100% Statements 36/36
83.33% Branches 10/12
100% Functions 10/10
100% Lines 28/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 1181x 1x   1x 1x 1x                         23x 4x 4x   19x 19x 19x 19x   19x 19x   19x                               2x 2x 1x   15x                   3x                     2x                     2x     1x             18x                                   1x 1x   1x   1x    
import faker from 'faker'
import { numbers } from './helpers'
 
function configureFaker(config) {
  const { locale = 'en' } = config
  faker.locale = locale
}
 
/**
 * parseModel - Iterates over named keys of an object while recursively parses
 * the given node, until every leaf is parsed.
 * -> An Object model type is considered a Node.
 * -> A model type different than Object is considered a Leaf.
 *
 * @param  {Object} model an object with domain-specific keys
 * @return {Object}
 */
function parseModel(model) {
  if (model.type && typeof model.type === "string") {
    const { type, value, options } = model
    return modelAttributeTypes[type](value, options)
  }
  const modelKeys = Object.keys(model)
  const parsedModel = modelKeys.reduce((accumulator, currentValue) => {
    const { type, value, options } = model[currentValue]
    const _value = modelAttributeTypes[type](value, options)
 
    const _accumulator = Object.assign(accumulator, { [currentValue]: _value })
    return _accumulator
  }, {})
  return parsedModel
}
 
 
/**
 * parseArray - Takes a model, options, and size. If the size is an Array (ex. [1, 20])
 * it will use the randomBetween method from numbers to get a random number between
 * the first and second index.
 * If size is a simple number, it just uses that.
 * -> parseModel can be either a Node or a Leaf.
 *
 * @param  {Object} model   A model Node
 * @param  {Object} options [size: Number]
 * @return {Array} A parsed model
 */
function parseArray(model, options) {
  let size = options.size;
  if (Array.isArray(size)) {
    size = numbers.randomBetween(size)
  }
  return [...Array(size).keys()].map(() => parseModel(model.value));
}
 
/**
 * parseString -  For those times when you simply need a string 
 *
 * @param  {Object} model   A model Node
 * @return {String} A string
 */
function parseString(model) {
  return model;
}
 
/**
 * append - Given a model and options, appends a value to the parsed model.
 * -> parsedModel should return a Leaf.
 * @param  {Object} model A model Node
 * @param  {Object} options [text: Number|String>]
 * @return {String} A parsed model
 */
function append(model, options) {
  return `${parseModel(model)}${options.text}`
}
 
/**
 * prepend - Given a model and options, prepends a value to the parsed model.
 * -> parsedModel should return a Leaf.
 * @param  {Object} model A model Node
 * @param  {Object} options [text: Number|String>]
 * @return {String} A parsed model
 */
function prepend(model, options) {
  return `${options.text}${parseModel(model)}`
}
 
const modelAttributeTypes = {
  // Structure types
  Object: parseModel,
  Array: parseArray,
  String: parseString,
  // Data generators types
  // -- external libs
  faker: (args, options = {}) => Object.byString(faker, args)(...options),
  // -- internal libs
  append,
  prepend,
  randomNumberBetween: numbers.randomBetween,
  randomElementInArray: numbers.randomArray,
  randomNumberBetweenWithString: numbers.randomBetweenWithString
}
 
export {
  parseArray,
  parseString,
  parseModel,
  append,
  prepend
}
 
export default (modelData) => {
  const { config, model } = modelData
  configureFaker(config)
 
  const parsedModel = parseModel(model)
 
  return parsedModel
}