if typeof process isnt 'undefined' and process.execPath and process.execPath.match /node|iojs/
  chai = require 'chai' unless chai
  noflo = require '../src/lib/NoFlo.coffee'
  path = require 'path'
  root = path.resolve __dirname, '../'
  urlPrefix = './'
else
  noflo = require 'noflo'
  root = 'noflo'
  urlPrefix = '/'

legacyBasic = ->
  c = new noflo.Component
  c.inPorts.add 'in',
    datatype: 'string'
  c.outPorts.add 'out',
    datatype: 'string'
  c.inPorts.in.on 'connect', ->
    c.outPorts.out.connect()
  c.inPorts.in.on 'begingroup', (group) ->
    c.outPorts.out.beginGroup group
  c.inPorts.in.on 'data', (data) ->
    c.outPorts.out.data data + c.nodeId
  c.inPorts.in.on 'endgroup', (group) ->
    c.outPorts.out.endGroup()
  c.inPorts.in.on 'disconnect', ->
    c.outPorts.out.disconnect()
  c

wirePatternAsync = ->
  c = new noflo.Component
  c.inPorts.add 'in',
    datatype: 'string'
  c.outPorts.add 'out',
    datatype: 'string'

  noflo.helpers.WirePattern c,
    in: 'in'
    out: 'out'
    async: true
    forwardGroups: true
  , (data, groups, out, callback) ->
    setTimeout ->
      out.send data + c.nodeId
      callback()
    , 1

wirePatternMerge = ->
  c = new noflo.Component
  c.inPorts.add 'in1',
    datatype: 'string'
  c.inPorts.add 'in2',
    datatype: 'string'
  c.outPorts.add 'out',
    datatype: 'string'

  noflo.helpers.WirePattern c,
    in: ['in1', 'in2']
    out: 'out'
    async: true
    forwardGroups: true
  , (data, groups, out, callback) ->
    out.send "1#{data['in1']}#{c.nodeId}2#{data['in2']}#{c.nodeId}"
    callback()

processAsync = ->
  c = new noflo.Component
  c.inPorts.add 'in',
    datatype: 'string'
  c.outPorts.add 'out',
    datatype: 'string'

  c.process (input, output) ->
    data = input.getData 'in'
    setTimeout ->
      output.sendDone data + c.nodeId
    , 1

processMerge = ->
  c = new noflo.Component
  c.inPorts.add 'in1',
    datatype: 'string'
  c.inPorts.add 'in2',
    datatype: 'string'
  c.outPorts.add 'out',
    datatype: 'string'

  c.forwardBrackets =
    'in1': ['out']

  c.process (input, output) ->
    return unless input.has 'in1', 'in2', (ip) -> ip.type is 'data'
    first = input.getData 'in1'
    second = input.getData 'in2'

    output.sendDone
      out: "1#{first}:2#{second}:#{c.nodeId}"

processGenerator = ->
  c = new noflo.Component
  c.inPorts.add 'start',
    datatype: 'bang'
  c.inPorts.add 'stop',
    datatype: 'bang'
  c.outPorts.add 'out',
    datatype: 'bang'
  c.autoOrdering = false

  cleanUp = ->
    return unless c.timer
    clearInterval c.timer.interval
    c.timer.deactivate()
    c.timer = null
  c.tearDown = (callback) ->
    cleanUp()
    callback()

  c.process (input, output, context) ->
    if input.hasData 'start'
      cleanUp() if c.timer
      input.getData 'start'
      c.timer = context
      c.timer.interval = setInterval ->
        output.send out: true
      , 100
    if input.hasData 'stop'
      input.getData 'stop'
      return output.done() unless c.timer
      cleanUp()
      output.done()

describe 'Network Lifecycle', ->
  loader = null
  before (done) ->
    loader = new noflo.ComponentLoader root
    loader.listComponents (err) ->
      return done err if err
      loader.registerComponent 'wirepattern', 'Async', wirePatternAsync
      loader.registerComponent 'wirepattern', 'Merge', wirePatternMerge
      loader.registerComponent 'process', 'Async', processAsync
      loader.registerComponent 'process', 'Merge', processMerge
      loader.registerComponent 'process', 'Generator', processGenerator
      loader.registerComponent 'legacy', 'Sync', legacyBasic
      done()

  describe 'with WirePattern sending to Process API', ->
    c = null
    ins = null
    out = null
    before (done) ->
      fbpData = "
      INPORT=Wp.IN:IN
      OUTPORT=Pc.OUT:OUT
      Wp(wirepattern/Async) OUT -> IN Pc(process/Async)
      "
      noflo.graph.loadFBP fbpData, (err, g) ->
        return done err if err
        loader.registerComponent 'scope', 'Connected', g
        loader.load 'scope/Connected', (err, instance) ->
          return done err if err
          c = instance
          ins = noflo.internalSocket.createSocket()
          c.inPorts.in.attach ins
          done()
    beforeEach ->
      out = noflo.internalSocket.createSocket()
      c.outPorts.out.attach out
    afterEach (done) ->
      c.outPorts.out.detach out
      out = null
      c.shutdown done

    it 'should forward old-style groups as expected', (done) ->
      expected = [
        'CONN'
        '< 1'
        '< a'
        'DATA bazWpPc'
        '>'
        '>'
        'DISC'
      ]
      received = []

      out.on 'connect', ->
        received.push 'CONN'
      out.on 'begingroup', (group) ->
        received.push "< #{group}"
      out.on 'data', (data) ->
        received.push "DATA #{data}"
      out.on 'endgroup', ->
        received.push '>'
      out.on 'disconnect', ->
        received.push 'DISC'

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        ins.connect()
        ins.beginGroup 1
        ins.beginGroup 'a'
        ins.send 'baz'
        ins.endGroup()
        ins.endGroup()
        ins.disconnect()
    it 'should forward new-style brackets as expected', (done) ->
      expected = [
        '< 1'
        '< a'
        'DATA fooWpPc'
        '>'
        '>'
      ]
      received = []
      brackets = []

      out.on 'ip', (ip) ->
        switch ip.type
          when 'openBracket'
            received.push "< #{ip.data}"
            brackets.push ip.data
          when 'data'
            received.push "DATA #{ip.data}"
          when 'closeBracket'
            received.push '>'
            brackets.pop()

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        ins.post new noflo.IP 'openBracket', 1
        ins.post new noflo.IP 'openBracket', 'a'
        ins.post new noflo.IP 'data', 'foo'
        ins.post new noflo.IP 'closeBracket', 'a'
        ins.post new noflo.IP 'closeBracket', 1
    it 'should forward scopes as expected', (done) ->
      expected = [
        'x < 1'
        'x < a'
        'x DATA barWpPc'
        'x >'
        'x >'
      ]
      received = []
      brackets = []

      out.on 'ip', (ip) ->
        switch ip.type
          when 'openBracket'
            received.push "#{ip.scope} < #{ip.data}"
            brackets.push ip.data
          when 'data'
            received.push "#{ip.scope} DATA #{ip.data}"
          when 'closeBracket'
            received.push "#{ip.scope} >"
            brackets.pop()

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        ins.post new noflo.IP 'openBracket', 1,
          scope: 'x'
        ins.post new noflo.IP 'openBracket', 'a',
          scope: 'x'
        ins.post new noflo.IP 'data', 'bar',
          scope: 'x'
        ins.post new noflo.IP 'closeBracket', 'a',
          scope: 'x'
        ins.post new noflo.IP 'closeBracket', 1,
          scope: 'x'

  describe 'pure Process API merging two inputs', ->
    c = null
    in1 = null
    in2 = null
    out = null
    before (done) ->
      fbpData = "
      INPORT=Pc1.IN:IN1
      INPORT=Pc2.IN:IN2
      OUTPORT=PcMerge.OUT:OUT
      Pc1(process/Async) OUT -> IN1 PcMerge(process/Merge)
      Pc2(process/Async) OUT -> IN2 PcMerge(process/Merge)
      "
      noflo.graph.loadFBP fbpData, (err, g) ->
        return done err if err
        loader.registerComponent 'scope', 'Merge', g
        loader.load 'scope/Merge', (err, instance) ->
          return done err if err
          c = instance
          in1 = noflo.internalSocket.createSocket()
          c.inPorts.in1.attach in1
          in2 = noflo.internalSocket.createSocket()
          c.inPorts.in2.attach in2
          done()
    beforeEach ->
      out = noflo.internalSocket.createSocket()
      c.outPorts.out.attach out
    afterEach (done) ->
      c.outPorts.out.detach out
      out = null
      c.shutdown done

    it 'should forward new-style brackets as expected', (done) ->
      expected = [
        'CONN'
        '< 1'
        '< a'
        'DATA 1bazPc1:2fooPc2:PcMerge'
        '>'
        '>'
        'DISC'
      ]
      received = []

      out.on 'connect', ->
        received.push 'CONN'
      out.on 'begingroup', (group) ->
        received.push "< #{group}"
      out.on 'data', (data) ->
        received.push "DATA #{data}"
      out.on 'endgroup', ->
        received.push '>'
      out.on 'disconnect', ->
        received.push 'DISC'

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        in2.connect()
        in2.send 'foo'
        in2.disconnect()
        in1.connect()
        in1.beginGroup 1
        in1.beginGroup 'a'
        in1.send 'baz'
        in1.endGroup()
        in1.endGroup()
        in1.disconnect()
    it 'should forward new-style brackets as expected regardless of sending order', (done) ->
      expected = [
        'CONN'
        '< 1'
        '< a'
        'DATA 1bazPc1:2fooPc2:PcMerge'
        '>'
        '>'
        'DISC'
      ]
      received = []

      out.on 'connect', ->
        received.push 'CONN'
      out.on 'begingroup', (group) ->
        received.push "< #{group}"
      out.on 'data', (data) ->
        received.push "DATA #{data}"
      out.on 'endgroup', ->
        received.push '>'
      out.on 'disconnect', ->
        received.push 'DISC'

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        in1.connect()
        in1.beginGroup 1
        in1.beginGroup 'a'
        in1.send 'baz'
        in1.endGroup()
        in1.endGroup()
        in1.disconnect()
        in2.connect()
        in2.send 'foo'
        in2.disconnect()
    it 'should forward scopes as expected', (done) ->
      expected = [
        'x < 1'
        'x DATA 1onePc1:2twoPc2:PcMerge'
        'x >'
      ]
      received = []
      brackets = []

      out.on 'ip', (ip) ->
        switch ip.type
          when 'openBracket'
            received.push "#{ip.scope} < #{ip.data}"
            brackets.push ip.data
          when 'data'
            received.push "#{ip.scope} DATA #{ip.data}"
          when 'closeBracket'
            received.push "#{ip.scope} >"
            brackets.pop()

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        in2.post new noflo.IP 'data', 'two',
          scope: 'x'
        in1.post new noflo.IP 'openBracket', 1,
          scope: 'x'
        in1.post new noflo.IP 'data', 'one',
          scope: 'x'
        in1.post new noflo.IP 'closeBracket', 1,
          scope: 'x'

  describe 'Process API mixed with legacy merging two inputs', ->
    c = null
    in1 = null
    in2 = null
    out = null
    before (done) ->
      fbpData = "
      INPORT=Leg1.IN:IN1
      INPORT=Leg2.IN:IN2
      OUTPORT=Leg3.OUT:OUT
      Leg1(legacy/Sync) OUT -> IN1 PcMerge(process/Merge)
      Leg2(legacy/Sync) OUT -> IN2 PcMerge(process/Merge)
      PcMerge OUT -> IN Leg3(legacy/Sync)
      "
      noflo.graph.loadFBP fbpData, (err, g) ->
        return done err if err
        loader.registerComponent 'scope', 'Merge', g
        loader.load 'scope/Merge', (err, instance) ->
          return done err if err
          c = instance
          in1 = noflo.internalSocket.createSocket()
          c.inPorts.in1.attach in1
          in2 = noflo.internalSocket.createSocket()
          c.inPorts.in2.attach in2
          done()
    beforeEach ->
      out = noflo.internalSocket.createSocket()
      c.outPorts.out.attach out
    afterEach (done) ->
      c.outPorts.out.detach out
      out = null
      c.shutdown done

    it 'should forward new-style brackets as expected', (done) ->
      expected = [
        'CONN'
        '< 1'
        '< a'
        'DATA 1bazLeg1:2fooLeg2:PcMergeLeg3'
        '>'
        '>'
        'DISC'
      ]
      received = []

      out.on 'connect', ->
        received.push 'CONN'
      out.on 'begingroup', (group) ->
        received.push "< #{group}"
      out.on 'data', (data) ->
        received.push "DATA #{data}"
      out.on 'endgroup', ->
        received.push '>'
      out.on 'disconnect', ->
        received.push 'DISC'

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        in2.connect()
        in2.send 'foo'
        in2.disconnect()
        in1.connect()
        in1.beginGroup 1
        in1.beginGroup 'a'
        in1.send 'baz'
        in1.endGroup()
        in1.endGroup()
        in1.disconnect()
    it 'should forward new-style brackets as expected regardless of sending order', (done) ->
      expected = [
        'CONN'
        '< 1'
        '< a'
        'DATA 1bazLeg1:2fooLeg2:PcMergeLeg3'
        '>'
        '>'
        'DISC'
      ]
      received = []

      out.on 'connect', ->
        received.push 'CONN'
      out.on 'begingroup', (group) ->
        received.push "< #{group}"
      out.on 'data', (data) ->
        received.push "DATA #{data}"
      out.on 'endgroup', ->
        received.push '>'
      out.on 'disconnect', ->
        received.push 'DISC'

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        in1.connect()
        in1.beginGroup 1
        in1.beginGroup 'a'
        in1.send 'baz'
        in1.endGroup()
        in1.endGroup()
        in1.disconnect()
        in2.connect()
        in2.send 'foo'
        in2.disconnect()

  describe 'Process API mixed with Legacy and WirePattern merging two inputs', ->
    c = null
    in1 = null
    in2 = null
    out = null
    before (done) ->
      fbpData = "
      INPORT=Leg1.IN:IN1
      INPORT=Leg2.IN:IN2
      OUTPORT=Wp.OUT:OUT
      Leg1(legacy/Sync) OUT -> IN1 PcMerge(process/Merge)
      Leg2(legacy/Sync) OUT -> IN2 PcMerge(process/Merge)
      PcMerge OUT -> IN Wp(wirepattern/Async)
      "
      noflo.graph.loadFBP fbpData, (err, g) ->
        return done err if err
        loader.registerComponent 'scope', 'Merge', g
        loader.load 'scope/Merge', (err, instance) ->
          return done err if err
          c = instance
          in1 = noflo.internalSocket.createSocket()
          c.inPorts.in1.attach in1
          in2 = noflo.internalSocket.createSocket()
          c.inPorts.in2.attach in2
          done()
    beforeEach ->
      out = noflo.internalSocket.createSocket()
      c.outPorts.out.attach out
    afterEach (done) ->
      c.outPorts.out.detach out
      out = null
      c.shutdown done

    it 'should forward new-style brackets as expected', (done) ->
      expected = [
        'CONN'
        '< 1'
        '< a'
        'DATA 1bazLeg1:2fooLeg2:PcMergeWp'
        '>'
        '>'
        'DISC'
      ]
      received = []

      out.on 'connect', ->
        received.push 'CONN'
      out.on 'begingroup', (group) ->
        received.push "< #{group}"
      out.on 'data', (data) ->
        received.push "DATA #{data}"
      out.on 'endgroup', ->
        received.push '>'
      out.on 'disconnect', ->
        received.push 'DISC'

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        in2.connect()
        in2.send 'foo'
        in2.disconnect()
        in1.connect()
        in1.beginGroup 1
        in1.beginGroup 'a'
        in1.send 'baz'
        in1.endGroup()
        in1.endGroup()
        in1.disconnect()
    it 'should forward new-style brackets as expected regardless of sending order', (done) ->
      expected = [
        'CONN'
        '< 1'
        '< a'
        'DATA 1bazLeg1:2fooLeg2:PcMergeWp'
        '>'
        '>'
        'DISC'
      ]
      received = []

      out.on 'connect', ->
        received.push 'CONN'
      out.on 'begingroup', (group) ->
        received.push "< #{group}"
      out.on 'data', (data) ->
        received.push "DATA #{data}"
      out.on 'endgroup', ->
        received.push '>'
      out.on 'disconnect', ->
        received.push 'DISC'

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        in1.connect()
        in1.beginGroup 1
        in1.beginGroup 'a'
        in1.send 'baz'
        in1.endGroup()
        in1.endGroup()
        in1.disconnect()
        in2.connect()
        in2.send 'foo'
        in2.disconnect()

  describe 'Process API mixed with WirePattern and legacy merging two inputs', ->
    c = null
    in1 = null
    in2 = null
    out = null
    before (done) ->
      fbpData = "
      INPORT=Leg1.IN:IN1
      INPORT=Leg2.IN:IN2
      OUTPORT=Leg3.OUT:OUT
      Leg1(legacy/Sync) OUT -> IN1 PcMerge(process/Merge)
      Leg2(legacy/Sync) OUT -> IN2 PcMerge(process/Merge)
      PcMerge OUT -> IN Wp(wirepattern/Async)
      Wp OUT -> IN Leg3(legacy/Sync)
      "
      noflo.graph.loadFBP fbpData, (err, g) ->
        return done err if err
        loader.registerComponent 'scope', 'Merge', g
        loader.load 'scope/Merge', (err, instance) ->
          return done err if err
          c = instance
          in1 = noflo.internalSocket.createSocket()
          c.inPorts.in1.attach in1
          in2 = noflo.internalSocket.createSocket()
          c.inPorts.in2.attach in2
          done()
    beforeEach ->
      out = noflo.internalSocket.createSocket()
      c.outPorts.out.attach out
    afterEach (done) ->
      c.outPorts.out.detach out
      out = null
      c.shutdown done

    it 'should forward new-style brackets as expected', (done) ->
      expected = [
        'START'
        'DATA -> IN Leg2() CONN'
        'Leg2() OUT -> IN2 PcMerge() CONN'
        'DATA -> IN Leg2() DATA foo'
        'Leg2() OUT -> IN2 PcMerge() DATA fooLeg2'
        'Leg2() OUT -> IN2 PcMerge() DISC'
        'DATA -> IN Leg2() DISC'
        'Leg1() OUT -> IN1 PcMerge() CONN'
        'Leg1() OUT -> IN1 PcMerge() < 1'
        'Leg1() OUT -> IN1 PcMerge() < a'
        'Leg1() OUT -> IN1 PcMerge() DATA bazLeg1'
        'PcMerge() OUT -> IN Wp() CONN'
        'PcMerge() OUT -> IN Wp() < 1'
        'PcMerge() OUT -> IN Wp() < a'
        'PcMerge() OUT -> IN Wp() DATA 1bazLeg1:2fooLeg2:PcMerge'
        'Leg1() OUT -> IN1 PcMerge() > a'
        'PcMerge() OUT -> IN Wp() > a'
        'Leg1() OUT -> IN1 PcMerge() > 1'
        'PcMerge() OUT -> IN Wp() > 1'
        'PcMerge() OUT -> IN Wp() DISC'
        'Leg1() OUT -> IN1 PcMerge() DISC'
        'Wp() OUT -> IN Leg3() CONN'
        'Wp() OUT -> IN Leg3() < 1'
        'Wp() OUT -> IN Leg3() < a'
        'Wp() OUT -> IN Leg3() DATA 1bazLeg1:2fooLeg2:PcMergeWp'
        'Wp() OUT -> IN Leg3() > a'
        'Wp() OUT -> IN Leg3() > 1'
        'Wp() OUT -> IN Leg3() DISC'
        'END'
      ]
      received = []

      wasStarted = false
      checkStart = ->
        received.push 'START'
      receiveConnect = (event) ->
        received.push "#{event.id} CONN"
      receiveEvent = (event) ->
        prefix = ''
        switch event.type
          when 'openBracket'
            prefix = '<'
            data = "#{prefix} #{event.data}"
          when 'data'
            prefix = 'DATA'
            data = "#{prefix} #{event.data}"
          when 'closeBracket'
            prefix = '>'
            data = "#{prefix} #{event.data}"
        received.push "#{event.id} #{data}"
      receiveDisconnect = (event) ->
        received.push "#{event.id} DISC"
      checkEnd = ->
        received.push 'END'
        c.network.graph.removeInitial 'foo', 'Leg2', 'in'
        c.network.removeListener 'connect', receiveConnect
        c.network.removeListener 'ip', receiveEvent
        c.network.removeListener 'disconnect', receiveDisconnect
        chai.expect(received).to.eql expected
        done()
      c.network.once 'start', checkStart
      c.network.on 'connect', receiveConnect
      c.network.on 'ip', receiveEvent
      c.network.on 'disconnect', receiveDisconnect
      c.network.once 'end', checkEnd

      c.network.graph.addInitial 'foo', 'Leg2', 'in'
      c.start (err) ->
        return done err if err
        in1.connect()
        in1.beginGroup 1
        in1.beginGroup 'a'
        in1.send 'baz'
        in1.endGroup()
        in1.endGroup()
        in1.disconnect()
    it 'should forward new-style brackets as expected regardless of sending order', (done) ->
      expected = [
        'CONN'
        '< 1'
        '< a'
        'DATA 1bazLeg1:2fooLeg2:PcMergeWpLeg3'
        '>'
        '>'
        'DISC'
      ]
      received = []

      out.on 'connect', ->
        received.push 'CONN'
      out.on 'begingroup', (group) ->
        received.push "< #{group}"
      out.on 'data', (data) ->
        received.push "DATA #{data}"
      out.on 'endgroup', ->
        received.push '>'
      out.on 'disconnect', ->
        received.push 'DISC'

      wasStarted = false
      checkStart = ->
        chai.expect(wasStarted).to.equal false
        wasStarted = true
      checkEnd = ->
        chai.expect(received).to.eql expected
        chai.expect(wasStarted).to.equal true
        done()
      c.network.once 'start', checkStart
      c.network.once 'end', checkEnd

      c.start (err) ->
        return done err if err
        in1.connect()
        in1.beginGroup 1
        in1.beginGroup 'a'
        in1.send 'baz'
        in1.endGroup()
        in1.endGroup()
        in1.disconnect()
        in2.connect()
        in2.send 'foo'
        in2.disconnect()

  describe 'with a Process API Generator component', ->
    c = null
    start = null
    stop = null
    out = null
    before (done) ->
      fbpData = "
      INPORT=PcGen.START:START
      INPORT=PcGen.STOP:STOP
      OUTPORT=Pc.OUT:OUT
      PcGen(process/Generator) OUT -> IN Pc(process/Async)
      "
      noflo.graph.loadFBP fbpData, (err, g) ->
        return done err if err
        loader.registerComponent 'scope', 'Connected', g
        loader.load 'scope/Connected', (err, instance) ->
          return done err if err
          instance.once 'ready', ->
            c = instance
            start = noflo.internalSocket.createSocket()
            c.inPorts.start.attach start
            stop = noflo.internalSocket.createSocket()
            c.inPorts.stop.attach stop
            done()
    beforeEach ->
      out = noflo.internalSocket.createSocket()
      c.outPorts.out.attach out
    afterEach (done) ->
      c.outPorts.out.detach out
      out = null
      c.shutdown done
    it 'should not be running initially', ->
      chai.expect(c.network.isRunning()).to.equal false
    it 'should not be running even when network starts', (done) ->
      c.start (err) ->
        return done err if err
        chai.expect(c.network.isRunning()).to.equal false
        done()
    it 'should start generating when receiving a start packet', (done) ->
      c.start (err) ->
        return done err if err
        out.once 'data', ->
          chai.expect(c.network.isRunning()).to.equal true
          done()
        start.send true
    it 'should stop generating when receiving a stop packet', (done) ->
      c.start (err) ->
        return done err if err
        out.once 'data', ->
          chai.expect(c.network.isRunning()).to.equal true
          stop.send true
          setTimeout ->
            chai.expect(c.network.isRunning()).to.equal false
            done()
          , 10
        start.send true
