import { expect } from 'chai'
import sinon from 'sinon'
import * as graphHelper from '@/lib/graphHelper'
import Graph from 'graphology'
import { random } from 'graphology-layout'

describe('graphHelper.js', () => {
  afterEach(() => {
    sinon.restore()
  })

  it('dataSourceIsValid returns false if data source is not valid for graph', () => {
    // no columns
    let dataSources = {}

    expect(graphHelper.dataSourceIsValid(dataSources)).to.eql(false)

    // the records are not JSONs
    dataSources = {
      id: [1, 2]
    }

    expect(graphHelper.dataSourceIsValid(dataSources)).to.eql(false)

    // too few keys in JSON
    dataSources = {
      doc: ['{"id": 1}', '{"id": 2}']
    }

    expect(graphHelper.dataSourceIsValid(dataSources)).to.eql(false)

    // no key that could be an object type
    dataSources = {
      doc: ['{"foo": "hello", "type": 1}', '{"object_type": 0, "bar": true}']
    }

    expect(graphHelper.dataSourceIsValid(dataSources)).to.eql(false)

    // valid
    dataSources = {
      doc: ['{"foo": "hello", "type": 1}', '{"type": 0, "bar": true}']
    }

    expect(graphHelper.dataSourceIsValid(dataSources)).to.eql(true)
  })

  it('buildNodes', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "label": "cat"}',
        '{"type": 0, "node_id": 2, "label": "dog"}',
        '{"type": 0, "node_id": null, "label": "bird"}',
        '{"object_type": 0, "node_id": 4, "label": "insect"}',
        '{"type": 1, "source": 1, "target": ""}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: null,
        objectType: null,
        edgeSource: null,
        edgeTarget: null
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    expect(graph.export().nodes).to.eql([])

    graph.clear()

    options.structure.nodeId = 'node_id'
    options.structure.objectType = 'type'
    graphHelper.buildNodes(graph, dataSources, options)
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: { data: { type: 0, node_id: 1, label: 'cat' } }
      },
      {
        key: '2',
        attributes: { data: { type: 0, node_id: 2, label: 'dog' } }
      }
    ])
  })

  it('buildEdges', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "label": "cat"}',
        '{"type": 0, "node_id": 2, "label": "dog"}',
        '{"type": 0, "node_id": 3, "label": "bird"}',
        '{"type": 1, "source": 1, "target": 2}',
        '{"type": 1, "source": 1, "target": 8}',
        '{"type": 1, "from": 1, "to": 3}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: null,
        edgeSource: null,
        edgeTarget: null
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.buildEdges(graph, dataSources, options)
    expect(graph.export().edges).to.eql([])

    graph.clear()

    options.structure.objectType = 'type'
    options.structure.edgeSource = 'source'
    options.structure.edgeTarget = 'target'

    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.buildEdges(graph, dataSources, options)

    const edges = graph.export().edges
    expect(edges.length).to.eql(1)
    expect(edges[0].source).to.equal('1')
    expect(edges[0].target).to.equal('2')
    expect(edges[0].attributes).to.eql({
      data: { type: 1, source: 1, target: 2 }
    })
  })

  it('udpateNodes - lables', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "label": "cat"}',
        '{"type": 0, "node_id": 2, "label": "dog"}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: null,
        edgeTarget: null
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.updateNodes(graph, {
      label: {
        source: 'label',
        color: 'green'
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, label: 'cat' },
          label: 'cat',
          labelColor: 'green'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, label: 'dog' },
          label: 'dog',
          labelColor: 'green'
        }
      }
    ])

    graphHelper.updateNodes(graph, {
      label: {
        source: null,
        color: 'green'
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, label: 'cat' },
          label: '',
          labelColor: 'green'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, label: 'dog' },
          label: '',
          labelColor: 'green'
        }
      }
    ])
  })

  it('udpateEdges - lables', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "label": "cat"}',
        '{"type": 0, "node_id": 2, "label": "mouse"}',
        '{"type": 1, "source": 1, "target": 2, "label": "eats"}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: 'source',
        edgeTarget: 'target'
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.buildEdges(graph, dataSources, options)
    graphHelper.updateEdges(graph, {
      label: {
        source: 'label',
        color: 'green'
      }
    })
    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2, label: 'eats' },
        label: 'eats',
        labelColor: 'green'
      }
    ])

    graphHelper.updateEdges(graph, {
      label: {
        source: null,
        color: 'green'
      }
    })
    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2, label: 'eats' },
        label: '',
        labelColor: 'green'
      }
    ])
  })

  it('udpateNodes - size - constant', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "label": "cat"}',
        '{"type": 0, "node_id": 2, "label": "dog"}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: null,
        edgeTarget: null
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.updateNodes(graph, {
      size: {
        type: 'constant',
        value: 25
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, label: 'cat' },
          size: 25
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, label: 'dog' },
          size: 25
        }
      }
    ])
  })

  it('udpateEdges - size - constant', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "label": "cat"}',
        '{"type": 0, "node_id": 2, "label": "mouse"}',
        '{"type": 1, "source": 1, "target": 2}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: 'source',
        edgeTarget: 'target'
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.buildEdges(graph, dataSources, options)
    graphHelper.updateEdges(graph, {
      size: {
        type: 'constant',
        value: 20
      }
    })
    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2 },
        size: 20
      }
    ])
  })

  it('udpateNodes - size - variable', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "points": 0}',
        '{"type": 0, "node_id": 2, "points": 8}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: null,
        edgeTarget: null
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.updateNodes(graph, {
      size: {
        type: 'variable',
        source: 'points',
        scale: 4,
        mode: 'diameter',
        min: 1
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, points: 0 },
          size: 0.5
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, points: 8 },
          size: 16
        }
      }
    ])

    graphHelper.updateNodes(graph, {
      size: {
        type: 'variable',
        source: 'points',
        scale: 4,
        mode: 'area',
        min: 1
      }
    })

    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, points: 0 },
          size: 0.5
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, points: 8 },
          size: 4
        }
      }
    ])
  })

  it('udpateEdges - size - variable', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "label": "cat"}',
        '{"type": 0, "node_id": 2, "label": "mouse"}',
        '{"type": 0, "node_id": 3, "label": "cheese"}',
        '{"type": 1, "source": 1, "target": 2, "weight": 5}',
        '{"type": 1, "source": 2, "target": 3, "weight": 2}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: 'source',
        edgeTarget: 'target'
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.buildEdges(graph, dataSources, options)
    graphHelper.updateEdges(graph, {
      size: {
        type: 'variable',
        source: 'weight',
        scale: 2,
        min: 6
      }
    })

    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2, weight: 5 },
        size: 10
      },
      {
        data: { type: 1, source: 2, target: 3, weight: 2 },
        size: 6
      }
    ])
  })

  it('udpateNodes - size - computed', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1}', // 0
        '{"type": 0, "node_id": 2}', // 2
        '{"type": 0, "node_id": 3}', // 0
        '{"type": 1, "source": 2, "target": 1}',
        '{"type": 1, "source": 2, "target": 3}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: 'source',
        edgeTarget: 'target'
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.buildEdges(graph, dataSources, options)
    graphHelper.updateNodes(graph, {
      size: {
        type: 'calculated',
        method: 'outDegree',
        scale: 4,
        mode: 'diameter',
        min: 1
      }
    })

    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1 },
          size: 0.5
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2 },
          size: 4
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3 },
          size: 0.5
        }
      }
    ])

    graphHelper.updateNodes(graph, {
      size: {
        type: 'calculated',
        method: 'outDegree',
        scale: 4,
        mode: 'area',
        min: 1
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1 },
          size: 0.5
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2 },
          size: 2
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3 },
          size: 0.5
        }
      }
    ])
  })

  it('udpateNodes - color - constant', () => {
    const dataSources = {
      doc: ['{"type": 0, "node_id": 1}', '{"type": 0, "node_id": 2}']
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: null,
        edgeTarget: null
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.updateNodes(graph, {
      color: {
        type: 'constant',
        value: '#a1b8c380',
        opacity: 50
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1 },
          color: '#a1b8c340'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2 },
          color: '#a1b8c340'
        }
      }
    ])
  })

  it('udpateEdges - color - constant', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "label": "cat"}',
        '{"type": 0, "node_id": 2, "label": "mouse"}',
        '{"type": 1, "source": 1, "target": 2}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: 'source',
        edgeTarget: 'target'
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.buildEdges(graph, dataSources, options)
    graphHelper.updateEdges(graph, {
      color: {
        type: 'constant',
        value: '#df78af'
      }
    })
    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2 },
        color: '#df78af'
      }
    ])
  })

  it('udpateNodes - color - variable', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "color": "red", "points": 5}',
        '{"type": 0, "node_id": 2, "color": "#abcdff", "points": 15}',
        '{"type": 0, "node_id": 3, "color": "#12345680", "points": 10}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: null,
        edgeTarget: null
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.updateNodes(graph, {
      color: {
        type: 'variable',
        source: 'color',
        sourceUsage: 'direct',
        opacity: 50
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, color: 'red', points: 5 },
          color: '#ff000080'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
          color: '#abcdff80'
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
          color: '#12345640'
        }
      }
    ])

    const colorscale = ['#aaaaff', '#8888ff', '#6666ff', '#4444ff', '#0000ff']
    graphHelper.updateNodes(graph, {
      color: {
        type: 'variable',
        source: 'points',
        sourceUsage: 'map_to',
        colorscale,
        mode: 'categorical',
        colorscaleDirection: 'normal',
        opacity: 50
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, color: 'red', points: 5 },
          color: '#aaaaff80'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
          color: '#6666ff80'
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
          color: '#8888ff80'
        }
      }
    ])

    graphHelper.updateNodes(graph, {
      color: {
        type: 'variable',
        source: 'points',
        sourceUsage: 'map_to',
        colorscale,
        mode: 'categorical',
        colorscaleDirection: 'reversed',
        opacity: 50
      }
    })

    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, color: 'red', points: 5 },
          color: '#0000ff80'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
          color: '#6666ff80'
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
          color: '#4444ff80'
        }
      }
    ])

    graphHelper.updateNodes(graph, {
      color: {
        type: 'variable',
        source: 'points',
        sourceUsage: 'map_to',
        colorscale,
        mode: 'continious',
        colorscaleDirection: 'normal',
        opacity: 50
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, color: 'red', points: 5 },
          color: '#aaaaff80'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
          color: '#0000ff80'
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
          color: '#6666ff80'
        }
      }
    ])

    graphHelper.updateNodes(graph, {
      color: {
        type: 'variable',
        source: 'points',
        sourceUsage: 'map_to',
        colorscale,
        mode: 'continious',
        colorscaleDirection: 'reversed',
        opacity: 50
      }
    })

    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, color: 'red', points: 5 },
          color: '#0000ff80'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
          color: '#aaaaff80'
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
          color: '#6666ff80'
        }
      }
    ])

    graphHelper.updateNodes(graph, {
      color: {
        type: 'variable',
        source: 'points',
        sourceUsage: 'map_to',
        colorscale: ['#aaaaff', '#0000ff'],
        mode: 'continious',
        colorscaleDirection: 'normal',
        opacity: 50
      }
    })

    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, color: 'red', points: 5 },
          color: '#aaaaff80'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
          color: '#0000ff80'
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
          color: '#5555ff80'
        }
      }
    ])
  })

  it('udpateNodes makes nodes black when apply continious color for categories', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "country": "NL"}',
        '{"type": 0, "node_id": 2, "country": "GB"}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: null,
        edgeTarget: null
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.updateNodes(graph, {
      color: {
        type: 'variable',
        source: 'country',
        sourceUsage: 'map_to',
        mode: 'continious',
        colorscaleDirection: 'normal',
        opacity: 100
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, country: 'NL' },
          color: '#000000ff'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, country: 'GB' },
          color: '#000000ff'
        }
      }
    ])
  })

  it('udpateEdges - color - variable', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "label": "cat"}',
        '{"type": 0, "node_id": 2, "label": "mouse"}',
        '{"type": 0, "node_id": 3, "label": "cheese"}',
        '{"type": 1, "source": 1, "target": 2, "color": "red", "weight": 5}',
        '{"type": 1, "source": 1, "target": 3, "color": "red", "weight": 15}',
        '{"type": 1, "source": 2, "target": 3, "color": "red", "weight": 10}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: 'source',
        edgeTarget: 'target'
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.buildEdges(graph, dataSources, options)
    graphHelper.updateEdges(graph, {
      color: {
        type: 'variable',
        source: 'color',
        sourceUsage: 'direct'
      }
    })
    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2, color: 'red', weight: 5 },
        color: '#ff0000ff'
      },
      {
        data: { type: 1, source: 1, target: 3, color: 'red', weight: 15 },
        color: '#ff0000ff'
      },
      {
        data: { type: 1, source: 2, target: 3, color: 'red', weight: 10 },
        color: '#ff0000ff'
      }
    ])

    const colorscale = ['#aaaaff', '#8888ff', '#6666ff', '#4444ff', '#0000ff']
    graphHelper.updateEdges(graph, {
      color: {
        type: 'variable',
        source: 'weight',
        sourceUsage: 'map_to',
        colorscale,
        mode: 'categorical',
        colorscaleDirection: 'normal'
      }
    })

    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2, color: 'red', weight: 5 },
        color: '#aaaaffff'
      },
      {
        data: { type: 1, source: 1, target: 3, color: 'red', weight: 15 },
        color: '#6666ffff'
      },
      {
        data: { type: 1, source: 2, target: 3, color: 'red', weight: 10 },
        color: '#8888ffff'
      }
    ])

    graphHelper.updateEdges(graph, {
      color: {
        type: 'variable',
        source: 'weight',
        sourceUsage: 'map_to',
        colorscale,
        mode: 'categorical',
        colorscaleDirection: 'reversed'
      }
    })

    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2, color: 'red', weight: 5 },
        color: '#0000ffff'
      },
      {
        data: { type: 1, source: 1, target: 3, color: 'red', weight: 15 },
        color: '#6666ffff'
      },
      {
        data: { type: 1, source: 2, target: 3, color: 'red', weight: 10 },
        color: '#4444ffff'
      }
    ])

    graphHelper.updateEdges(graph, {
      color: {
        type: 'variable',
        source: 'weight',
        sourceUsage: 'map_to',
        colorscale,
        mode: 'continious',
        colorscaleDirection: 'normal'
      }
    })

    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2, color: 'red', weight: 5 },
        color: '#aaaaffff'
      },
      {
        data: { type: 1, source: 1, target: 3, color: 'red', weight: 15 },
        color: '#0000ffff'
      },
      {
        data: { type: 1, source: 2, target: 3, color: 'red', weight: 10 },
        color: '#6666ffff'
      }
    ])

    graphHelper.updateEdges(graph, {
      color: {
        type: 'variable',
        source: 'weight',
        sourceUsage: 'map_to',
        colorscale,
        mode: 'continious',
        colorscaleDirection: 'reversed'
      }
    })

    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2, color: 'red', weight: 5 },
        color: '#0000ffff'
      },
      {
        data: { type: 1, source: 1, target: 3, color: 'red', weight: 15 },
        color: '#aaaaffff'
      },
      {
        data: { type: 1, source: 2, target: 3, color: 'red', weight: 10 },
        color: '#6666ffff'
      }
    ])
  })

  it('udpateNodes - color - calculated', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1}',
        '{"type": 0, "node_id": 2}',
        '{"type": 0, "node_id": 3}',
        '{"type": 1, "source": 2, "target": 3}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: 'source',
        edgeTarget: 'target'
      }
    }

    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.buildEdges(graph, dataSources, options)

    const colorscale = ['#aaaaff', '#8888ff', '#6666ff', '#4444ff', '#0000ff']

    graphHelper.updateNodes(graph, {
      color: {
        type: 'calculated',
        method: 'degree',
        colorscale,
        mode: 'categorical',
        colorscaleDirection: 'normal',
        opacity: 50
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1 },
          color: '#aaaaff80'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2 },
          color: '#8888ff80'
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3 },
          color: '#8888ff80'
        }
      }
    ])

    graphHelper.updateNodes(graph, {
      color: {
        type: 'calculated',
        method: 'outDegree',
        colorscale,
        mode: 'categorical',
        colorscaleDirection: 'reversed',
        opacity: 50
      }
    })

    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1 },
          color: '#0000ff80'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2 },
          color: '#4444ff80'
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3 },
          color: '#0000ff80'
        }
      }
    ])

    graphHelper.updateNodes(graph, {
      color: {
        type: 'calculated',
        method: 'degree',
        colorscale,
        mode: 'continious',
        colorscaleDirection: 'normal',
        opacity: 100
      }
    })
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1 },
          color: '#aaaaffff'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2 },
          color: '#0000ffff'
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3 },
          color: '#0000ffff'
        }
      }
    ])

    graphHelper.updateNodes(graph, {
      color: {
        type: 'calculated',
        method: 'degree',
        colorscale,
        mode: 'continious',
        colorscaleDirection: 'reversed',
        opacity: 100
      }
    })

    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1 },
          color: '#0000ffff'
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2 },
          color: '#aaaaffff'
        }
      },
      {
        key: '3',
        attributes: {
          data: { type: 0, node_id: 3 },
          color: '#aaaaffff'
        }
      }
    ])
  })

  it('udpateEdges - direction', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1}',
        '{"type": 0, "node_id": 2}',
        '{"type": 1, "source": 1, "target": 2}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: 'source',
        edgeTarget: 'target'
      }
    }
    graphHelper.buildNodes(graph, dataSources, options)
    graphHelper.buildEdges(graph, dataSources, options)
    graphHelper.updateEdges(graph, {
      showDirection: true
    })
    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2 },
        type: 'arrow'
      }
    ])

    graphHelper.updateEdges(graph, {
      showDirection: false
    })
    expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
      {
        data: { type: 1, source: 1, target: 2 },
        type: 'line'
      }
    ])
  })

  it('getDiminishedColor', () => {
    const diminishedColor = graphHelper.getDiminishedColor(
      '#FF0000CC',
      '#0000FF'
    )
    expect(diminishedColor).to.equal('#3300cc')
  })

  it('reduceNodes', () => {
    const settings = {
      style: {
        backgroundColor: '#0000FF'
      }
    }

    const nodeData = {
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue'
    }

    let interactionState = {
      selectedNodeId: 'node-1',
      hoveredNodeId: 'node-2',
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: new Set(['node-1.1']),
      neighborsOfHoveredNode: new Set(['node-2.1']),
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }

    expect(
      graphHelper.reduceNodes('node-1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'black',
      zIndex: 2,
      highlighted: true,
      forceLabel: true
    })
    expect(
      graphHelper.reduceNodes('node-2', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'black',
      zIndex: 2,
      highlighted: true,
      forceLabel: true
    })

    expect(
      graphHelper.reduceNodes('node-1.1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })

    expect(
      graphHelper.reduceNodes('node-2.1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })

    expect(
      graphHelper.reduceNodes('node-3', nodeData, interactionState, settings)
    ).to.eql({
      color: '#3300cc',
      label: '',
      labelColor: 'blue',
      zIndex: 1,
      highlighted: false
    })

    interactionState = {
      selectedNodeId: 'node-1',
      hoveredNodeId: null,
      selectedEdgeId: null,
      hoveredEdgeId: 'edge-2-2.1',
      neighborsOfSelectedNode: new Set(['node-1.1']),
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: ['node-2', 'node-2.1']
    }

    expect(
      graphHelper.reduceNodes('node-1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'black',
      zIndex: 2,
      highlighted: true,
      forceLabel: true
    })

    expect(
      graphHelper.reduceNodes('node-2', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })

    expect(
      graphHelper.reduceNodes('node-1.1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })

    expect(
      graphHelper.reduceNodes('node-1.1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })

    expect(
      graphHelper.reduceNodes('node-3', nodeData, interactionState, settings)
    ).to.eql({
      color: '#3300cc',
      label: '',
      labelColor: 'blue',
      zIndex: 1,
      highlighted: false
    })

    interactionState = {
      selectedNodeId: null,
      hoveredNodeId: null,
      selectedEdgeId: 'edge-1-1.1',
      hoveredEdgeId: 'edge-2-2.1',
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: ['node-1', 'node-1.1'],
      hoveredEdgeExtremities: ['node-2', 'node-2.1']
    }

    expect(
      graphHelper.reduceNodes('node-1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })
    expect(
      graphHelper.reduceNodes('node-2', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })
    expect(
      graphHelper.reduceNodes('node-1.1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })
    expect(
      graphHelper.reduceNodes('node-2.1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })

    expect(
      graphHelper.reduceNodes('node-3', nodeData, interactionState, settings)
    ).to.eql({
      color: '#3300cc',
      label: '',
      labelColor: 'blue',
      zIndex: 1,
      highlighted: false
    })

    interactionState = {
      selectedNodeId: null,
      hoveredNodeId: 'node-2',
      selectedEdgeId: 'edge-1',
      hoveredEdgeId: null,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: new Set(['node-2.1']),
      selectedEdgeExtremities: ['node-1', 'node-1.1'],
      hoveredEdgeExtremities: []
    }

    expect(
      graphHelper.reduceNodes('node-1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })
    expect(
      graphHelper.reduceNodes('node-2', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'black',
      zIndex: 2,
      highlighted: true,
      forceLabel: true
    })
    expect(
      graphHelper.reduceNodes('node-1.1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })
    expect(
      graphHelper.reduceNodes('node-2.1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue',
      zIndex: 2,
      highlighted: false,
      forceLabel: true
    })

    expect(
      graphHelper.reduceNodes('node-3', nodeData, interactionState, settings)
    ).to.eql({
      color: '#3300cc',
      label: '',
      labelColor: 'blue',
      zIndex: 1,
      highlighted: false
    })

    interactionState = {
      selectedNodeId: null,
      hoveredNodeId: null,
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }

    expect(
      graphHelper.reduceNodes('node-1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue'
    })
    expect(
      graphHelper.reduceNodes('node-2', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue'
    })
    expect(
      graphHelper.reduceNodes('node-1.1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue'
    })
    expect(
      graphHelper.reduceNodes('node-2.1', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue'
    })

    expect(
      graphHelper.reduceNodes('node-3', nodeData, interactionState, settings)
    ).to.eql({
      color: '#FF0000CC',
      label: 'Node label',
      labelColor: 'blue'
    })
  })

  it('reduceEdges - node_alone', () => {
    const settings = {
      style: {
        backgroundColor: '#0000FF',
        highlightMode: 'node_alone'
      }
    }

    const edgeData = { color: '#FF0000CC', label: 'Edge label', size: 3 }
    const graph = new Graph()
    graph.addNode('node-1.1')
    graph.addNode('node-1.2')
    graph.addNode('node-1.3')
    graph.addNode('node-2.1')
    graph.addNode('node-2.2')
    const edge1112 = graph.addEdge('node-1.1', 'node-1.2', edgeData)
    const edge1113 = graph.addEdge('node-1.1', 'node-1.3', edgeData)
    const edge1213 = graph.addEdge('node-1.2', 'node-1.3', edgeData)
    const edge2122 = graph.addEdge('node-2.1', 'node-2.2', edgeData)

    const hiddenEdgeStyle = { color: '#3300cc', label: '', zIndex: 1, size: 3 }
    const highlightedEdgeStyle = {
      color: '#FF0000CC',
      label: 'Edge label',
      zIndex: 2,
      size: 6,
      forceLabel: true
    }

    let interactionState = {
      selectedNodeId: null,
      hoveredNodeId: null,
      selectedEdgeId: edge2122,
      hoveredEdgeId: edge1112,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: ['node-2.1', 'node-2.2'],
      hoveredEdgeExtremities: ['node-1.1', 'node-1.2']
    }
    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(highlightedEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(highlightedEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    interactionState = {
      selectedNodeId: 'node-1.1',
      hoveredNodeId: null,
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: new Set(['node-1.2', 'node-1.3']),
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }
    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    interactionState = {
      selectedNodeId: null,
      hoveredNodeId: 'node-1.1',
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: new Set(['node-1.2', 'node-1.3']),
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }
    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    interactionState = {
      selectedNodeId: null,
      hoveredNodeId: null,
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }

    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)

    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)
  })

  it('reduceEdges - node_and_neighbors', () => {
    const settings = {
      style: {
        backgroundColor: '#0000FF',
        highlightMode: 'node_and_neighbors'
      }
    }

    const edgeData = { color: '#FF0000CC', label: 'Edge label', size: 3 }
    const graph = new Graph()
    graph.addNode('node-1.1')
    graph.addNode('node-1.2')
    graph.addNode('node-1.3')
    graph.addNode('node-2.1')
    graph.addNode('node-2.2')
    const edge1112 = graph.addEdge('node-1.1', 'node-1.2', edgeData)
    const edge1113 = graph.addEdge('node-1.1', 'node-1.3', edgeData)
    const edge1213 = graph.addEdge('node-1.2', 'node-1.3', edgeData)
    const edge2122 = graph.addEdge('node-2.1', 'node-2.2', edgeData)

    const hiddenEdgeStyle = { color: '#3300cc', label: '', zIndex: 1, size: 3 }
    const highlightedEdgeStyle = {
      color: '#FF0000CC',
      label: 'Edge label',
      zIndex: 2,
      size: 6,
      forceLabel: true
    }
    const visibleEdgeStyle = {
      color: '#FF0000CC',
      label: 'Edge label',
      zIndex: 2,
      size: 3
    }

    let interactionState = {
      selectedNodeId: null,
      hoveredNodeId: null,
      selectedEdgeId: edge2122,
      hoveredEdgeId: edge1112,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: ['node-2.1', 'node-2.2'],
      hoveredEdgeExtremities: ['node-1.1', 'node-1.2']
    }
    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(highlightedEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(highlightedEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    interactionState = {
      selectedNodeId: 'node-1.1',
      hoveredNodeId: null,
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: new Set(['node-1.2', 'node-1.3']),
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }
    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(visibleEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(visibleEdgeStyle)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    interactionState = {
      selectedNodeId: null,
      hoveredNodeId: 'node-1.1',
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: new Set(['node-1.2', 'node-1.3']),
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }
    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(visibleEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(visibleEdgeStyle)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    interactionState = {
      selectedNodeId: null,
      hoveredNodeId: null,
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }

    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)

    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)
  })

  it('reduceEdges - include_neighbor_edges', () => {
    const settings = {
      style: {
        backgroundColor: '#0000FF',
        highlightMode: 'include_neighbor_edges'
      }
    }

    const edgeData = { color: '#FF0000CC', label: 'Edge label', size: 3 }
    const graph = new Graph()
    graph.addNode('node-1.1')
    graph.addNode('node-1.2')
    graph.addNode('node-1.3')
    graph.addNode('node-2.1')
    graph.addNode('node-2.2')
    const edge1112 = graph.addEdge('node-1.1', 'node-1.2', edgeData)
    const edge1113 = graph.addEdge('node-1.1', 'node-1.3', edgeData)
    const edge1213 = graph.addEdge('node-1.2', 'node-1.3', edgeData)
    const edge2122 = graph.addEdge('node-2.1', 'node-2.2', edgeData)

    const hiddenEdgeStyle = { color: '#3300cc', label: '', zIndex: 1, size: 3 }
    const highlightedEdgeStyle = {
      color: '#FF0000CC',
      label: 'Edge label',
      zIndex: 2,
      size: 6,
      forceLabel: true
    }
    const visibleEdgeStyle = {
      color: '#FF0000CC',
      label: 'Edge label',
      zIndex: 2,
      size: 3
    }

    let interactionState = {
      selectedNodeId: null,
      hoveredNodeId: null,
      selectedEdgeId: edge2122,
      hoveredEdgeId: edge1112,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: ['node-2.1', 'node-2.2'],
      hoveredEdgeExtremities: ['node-1.1', 'node-1.2']
    }
    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(highlightedEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(highlightedEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)

    interactionState = {
      selectedNodeId: 'node-1.1',
      hoveredNodeId: null,
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: new Set(['node-1.2', 'node-1.3']),
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }
    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(visibleEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(visibleEdgeStyle)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(visibleEdgeStyle)

    interactionState = {
      selectedNodeId: null,
      hoveredNodeId: 'node-1.1',
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: new Set(['node-1.2', 'node-1.3']),
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }
    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(hiddenEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(visibleEdgeStyle)
    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(visibleEdgeStyle)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(visibleEdgeStyle)

    interactionState = {
      selectedNodeId: null,
      hoveredNodeId: null,
      selectedEdgeId: null,
      hoveredEdgeId: null,
      neighborsOfSelectedNode: undefined,
      neighborsOfHoveredNode: undefined,
      selectedEdgeExtremities: [],
      hoveredEdgeExtremities: []
    }

    expect(
      graphHelper.reduceEdges(
        edge2122,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)
    expect(
      graphHelper.reduceEdges(
        edge1112,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)

    expect(
      graphHelper.reduceEdges(
        edge1113,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)

    expect(
      graphHelper.reduceEdges(
        edge1213,
        edgeData,
        interactionState,
        settings,
        graph
      )
    ).to.eql(edgeData)
  })

  it('clearNodeCoordinates', () => {
    const dataSources = {
      doc: [
        '{"type": 0, "node_id": 1, "label": "cat"}',
        '{"type": 0, "node_id": 2, "label": "dog"}'
      ]
    }
    const graph = new Graph()
    const options = {
      structure: {
        nodeId: 'node_id',
        objectType: 'type',
        edgeSource: null,
        edgeTarget: null
      }
    }

    graphHelper.buildNodes(graph, dataSources, options)
    random.assign(graph)
    graphHelper.clearNodeCoordinates(graph)
    expect(graph.export().nodes).to.eql([
      {
        key: '1',
        attributes: {
          data: { type: 0, node_id: 1, label: 'cat' },
          x: undefined,
          y: undefined
        }
      },
      {
        key: '2',
        attributes: {
          data: { type: 0, node_id: 2, label: 'dog' },
          x: undefined,
          y: undefined
        }
      }
    ])
  })
})
