All files throughAgent.js

100% Statements 43/43
100% Branches 28/28
100% Functions 16/16
100% Lines 39/39

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      14x 14x   14x 3x         11x 23x 7x 3x 4x 12x   2x                     17x 17x 17x       14x       40x 40x   40x       3x 3x 7x 7x 6x   3x       74x 45x   74x 41x   74x 18x   74x 22x   72x 43x   72x       27x 27x 27x     9x        
import React, { Children } from 'react'
import PropTypes from 'prop-types'
 
const throughAgent = (area, key) => (AgentComponent) => {
  let getKey = null
 
  if( !(typeof area === 'string' || area instanceof String ) ) {
    throw new Error(
      "type error: throughAgent(area:string, key:string|function)"
    )
  }
 
  if( typeof key === 'string' || key instanceof String ) {
    getKey = props => props[key]
  } else if ( typeof key === 'function' ) {
    getKey = key
  } else if (key === undefined || key === null) {
    getKey = props => 'default'
  } else {
    throw new Error(
      "type error: throughAgent(area:string, key:string|function)"
    )
  }
 
  class ThroughAgent extends React.Component {
    static contextTypes = {
      through: PropTypes.object,
    }
 
    constructor(props, context) {
      super(props, context)
      this.data = {}
      this.update(this.data)
    }
 
    componentWillUnmount = () => {
      this.update({})
    }
 
    item = (elem, syncUpdate = true) => {
      const key = elem && getKey(elem.props)
      const data = (!elem || !key) ?
        {} : { [key]: elem.props }
      this.update(data, syncUpdate)
    }
 
    items = (elem, syncUpdate = true) => {
      const data = {}
      React.Children.forEach(elem.props.children, function(elem) {
        const key = elem && getKey(elem.props)
        if(!elem || !key) { return }
        data[key] = elem.props
      })
      this.update(data, syncUpdate)
    }
 
    update = (data, syncUpdate) => {
      const add = Object.keys(data).filter(
        key => !Object.prototype.hasOwnProperty.call(this.data, key)
      )
      const remove = Object.keys(this.data).filter(
        key => !Object.prototype.hasOwnProperty.call(data, key)
      )
      remove.forEach(
        key => this.context.through.remove(area, key)
      )
      add.forEach(
        key => this.context.through.add(area, key)
      )
      Object.keys(data).forEach(
        key => this.context.through.update(area, key, data[key], syncUpdate)
      )
      this.data = data
    }
 
    render() {
      const {item, items} = this
      const through = Object.assign({item, items}, this.props.through)
      return <AgentComponent {...this.props} {...{[area]:{item, items}}} />
    }
  }
  return ThroughAgent
}
 
export default throughAgent