<commit_before>'use strict'
/* eslint-env mocha */

const expect = require('chai').expect
const Node = require('../src')
const PeerInfo = require('peer-info')
const multiaddr = require('multiaddr')
const parallel = require('async/parallel')
const map = require('async/map')
const spawn = require('child_process').spawn
const path = require('path')
const pull = require('pull-stream')

describe('libp2p-ipfs-nodejs', () => {
  let nodeA // TCP
  let nodeB // TCP
  let nodeC // TCP
  let nodeD // TCP
  let nodeE // TCP + WebSockets
  let nodeF // WebSockets

  let nodeAMultiaddrTCP
  let nodeBMultiaddrTCP
  let nodeCMultiaddrTCP
  let nodeDMultiaddrTCP
  let nodeEMultiaddrTCP
  let nodeEMultiaddrWebSockets
  let nodeFMultiaddrWebSockets

  let spawnedNode

  it('create 6 nodes', (done) => {
    map([0, 1, 2, 3, 4, 5], (i, cb) => {
      PeerInfo.create(cb)
    }, (err, infos) => {
      if (err) {
        return done(err)
      }

      infos.forEach((info, i) => {
        if (i === 5) {
          return
        }
        info.multiaddr.add(multiaddr('/ip4/0.0.0.0/tcp/0'))
      })

      nodeA = new Node(infos[0])
      nodeB = new Node(infos[1])
      nodeC = new Node(infos[2])
      nodeD = new Node(infos[3])
      nodeE = new Node(infos[4])
      const maddrWS1 = multiaddr('/ip4/127.0.0.1/tcp/25001/ws')
      nodeE.peerInfo.multiaddr.add(maddrWS1)

      nodeEMultiaddrWebSockets = multiaddr(
        nodeE.peerInfo.multiaddrs[1].toString() +
        '/ipfs/' + nodeE.peerInfo.id.toB58String()
      )

      const pInfo = infos[5]
      const maddrWS2 = multiaddr('/ip4/127.0.0.1/tcp/25002/ws')
      pInfo.multiaddr.add(maddrWS2)

      nodeF = new Node(pInfo)

      nodeFMultiaddrWebSockets = multiaddr(
        nodeF.peerInfo.multiaddrs[0].toString() +
        '/ipfs/' + nodeF.peerInfo.id.toB58String()
      )

      done()
    })
  })

  it('start 6 nodes', (done) => {
    parallel([
      (cb) => nodeA.start(cb),
      (cb) => nodeB.start(cb),
      (cb) => nodeC.start(cb),
      (cb) => nodeD.start(cb),
      (cb) => nodeE.start(cb),
      (cb) => nodeF.start(cb)
    ], (err) => {
      expect(err).to.not.exist
      expect(nodeA.peerInfo.multiaddrs.length > 1).to.equal(true)
      expect(nodeB.peerInfo.multiaddrs.length > 1).to.equal(true)
      expect(nodeC.peerInfo.multiaddrs.length > 1).to.equal(true)
      expect(nodeD.peerInfo.multiaddrs.length > 1).to.equal(true)
      expect(nodeE.peerInfo.multiaddrs.length > 2).to.equal(true)
      expect(nodeF.peerInfo.multiaddrs.length).to.equal(1)
      done()
    })
  })

  it('extract TCP multiaddr', () => {
    nodeAMultiaddrTCP = multiaddr((
      nodeA.peerInfo.multiaddrs[0].toString() +
      '/ipfs/' + nodeA.peerInfo.id.toB58String()
      ).replace('0.0.0.0', '127.0.0.1')
    )
    nodeBMultiaddrTCP = multiaddr((
      nodeB.peerInfo.multiaddrs[0].toString() +
      '/ipfs/' + nodeB.peerInfo.id.toB58String()
      ).replace('0.0.0.0', '127.0.0.1')

    )
    nodeCMultiaddrTCP = multiaddr((
      nodeC.peerInfo.multiaddrs[0].toString() +
      '/ipfs/' + nodeC.peerInfo.id.toB58String()
      ).replace('0.0.0.0', '127.0.0.1')

    )
    nodeDMultiaddrTCP = multiaddr((
      nodeD.peerInfo.multiaddrs[0].toString() +
      '/ipfs/' + nodeD.peerInfo.id.toB58String()
      ).replace('0.0.0.0', '127.0.0.1')
    )

    // Note: Here is the multiaddrs[1] again because
    // the .replace in swarm switches the order of
    // the TCP and WS addr
    nodeEMultiaddrTCP = multiaddr((
      nodeE.peerInfo.multiaddrs[1].toString() +
      '/ipfs/' + nodeE.peerInfo.id.toB58String()
      ).replace('0.0.0.0', '127.0.0.1')
    )

    // console.log(nodeAMultiaddrTCP.toString())
    // console.log(nodeBMultiaddrTCP.toString())
    // console.log(nodeCMultiaddrTCP.toString())
    // console.log(nodeDMultiaddrTCP.toString())
    // console.log(nodeEMultiaddrTCP.toString())
  })

  it('handle echo proto in 6 nodes', () => {
    function echo (protocol, conn) {
      pull(conn, conn)
    }

    nodeA.handle('/echo/1.0.0', echo)
    nodeB.handle('/echo/1.0.0', echo)
    nodeC.handle('/echo/1.0.0', echo)
    nodeD.handle('/echo/1.0.0', echo)
    nodeE.handle('/echo/1.0.0', echo)
    nodeF.handle('/echo/1.0.0', echo)
  })

  // General connectivity tests

  it('libp2p.dialByMultiaddr nodeA to nodeB', (done) => {
    nodeA.dialByMultiaddr(nodeBMultiaddrTCP, (err) => {
      expect(err).to.not.exist
      // Some time for Identify to finish
      setTimeout(check, 500)

      function check () {
        parallel([
          (cb) => {
            const peers = nodeA.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(1)
            cb()
          },
          (cb) => {
            const peers = nodeB.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(1)
            cb()
          }
        ], done)
      }
      // TODO confirm that we got the pubkey through identify
    })
  })

  it('libp2p.dialByMultiaddr on Protocol nodeA to nodeB', (done) => {
    nodeA.dialByMultiaddr(nodeBMultiaddrTCP, '/echo/1.0.0', (err, conn) => {
      expect(err).to.not.exist
      parallel([
        (cb) => {
          const peers = nodeA.peerBook.getAll()
          expect(err).to.not.exist
          expect(Object.keys(peers)).to.have.length(1)
          cb()
        },
        (cb) => {
          const peers = nodeB.peerBook.getAll()
          expect(err).to.not.exist
          expect(Object.keys(peers)).to.have.length(1)
          cb()
        }
      ], () => {
        pull(
          pull.values([Buffer('hey')]),
          conn,
          pull.collect((err, data) => {
            expect(err).to.not.exist
            expect(data).to.be.eql([Buffer('hey')])
            done()
          })
        )
      })
    })
  })

  it('libp2p.hangupByMultiaddr nodeA to nodeB', (done) => {
    nodeA.hangUpByMultiaddr(nodeBMultiaddrTCP, (err) => {
      expect(err).to.not.exist
      setTimeout(check, 500)

      function check () {
        parallel([
          (cb) => {
            const peers = nodeA.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(0)
            expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)

            cb()
          },
          (cb) => {
            const peers = nodeB.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(0)
            expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
            cb()
          }
        ], done)
      }
    })
  })

  it('libp2p.dialByPeerInfo nodeA to nodeB', (done) => {
    nodeA.dialByPeerInfo(nodeB.peerInfo, (err) => {
      expect(err).to.not.exist
      // Some time for Identify to finish
      setTimeout(check, 500)

      function check () {
        parallel([
          (cb) => {
            const peers = nodeA.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(1)
            cb()
          },
          (cb) => {
            const peers = nodeB.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(1)
            cb()
          }
        ], done)
      }
      // TODO confirm that we got the pubkey through identify
    })
  })

  it('libp2p.dialByPeerInfo on Protocol nodeA to nodeB', (done) => {
    nodeA.dialByPeerInfo(nodeB.peerInfo, '/echo/1.0.0', (err, conn) => {
      expect(err).to.not.exist
      parallel([
        (cb) => {
          const peers = nodeA.peerBook.getAll()
          expect(err).to.not.exist
          expect(Object.keys(peers)).to.have.length(1)
          cb()
        },
        (cb) => {
          const peers = nodeB.peerBook.getAll()
          expect(err).to.not.exist
          expect(Object.keys(peers)).to.have.length(1)
          cb()
        }
      ], () => {
        pull(
          pull.values([Buffer('hey')]),
          conn,
          pull.collect((err, data) => {
            expect(err).to.not.exist
            expect(data).to.be.eql([Buffer('hey')])
            done()
          })
        )
      })
    })
  })

  it('libp2p.hangupByPeerInfo nodeA to nodeB', (done) => {
    nodeA.hangUpByPeerInfo(nodeB.peerInfo, (err) => {
      expect(err).to.not.exist
      setTimeout(check, 500)

      function check () {
        parallel([
          (cb) => {
            const peers = nodeA.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(0)
            expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)

            cb()
          },
          (cb) => {
            const peers = nodeB.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(0)
            expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
            cb()
          }
        ], done)
      }
    })
  })

  // NOTE, these dialById only works if a previous dial was made
  // until we have PeerRouting
  it.skip('libp2p.dialById nodeA to nodeB', (done) => {})
  it.skip('libp2p.dialById on Protocol nodeA to nodeB', (done) => {})
  it.skip('libp2p.hangupById nodeA to nodeB', (done) => {})

  it('nodeA dial to nodeC and nodeD', (done) => {
    let count = 0
    const next = () => ++count === 2 ? check() : null

    nodeA.dialByMultiaddr(nodeCMultiaddrTCP, next)
    nodeA.dialByMultiaddr(nodeDMultiaddrTCP, next)

    function check () {
      const peers = nodeA.peerBook.getAll()
      expect(Object.keys(peers)).to.have.length(2)
      done()
    }
  })

  // Multiple transport tests

  it('nodeA dial to nodeE', (done) => {
    nodeA.dialByMultiaddr(nodeEMultiaddrTCP, (err) => {
      expect(err).to.not.exist
      const peers = nodeA.peerBook.getAll()
      expect(Object.keys(peers)).to.have.length(3)
      done()
    })
  })

  // Until https://github.com/libp2p/js-libp2p/issues/46 is resolved
  // Everynode will be able to dial in WebSockets
  it.skip('nodeA fails to dial to nodeF', (done) => {
    nodeA.dialByMultiaddr(nodeFMultiaddrWebSockets, (err) => {
      expect(err).to.exist
      const peers = nodeA.peerBook.getAll()
      expect(Object.keys(peers)).to.have.length(3)
      done()
    })
  })

  it('nodeF fails to dial to nodeA', (done) => {
    nodeF.dialByMultiaddr(nodeAMultiaddrTCP, (err) => {
      expect(err).to.exist
      done()
    })
  })

  it('nodeF dial to nodeE', (done) => {
    nodeF.dialByMultiaddr(nodeEMultiaddrWebSockets, (err) => {
      expect(err).to.not.exist
      done()
    })
  })

  // Turbolence tests

  it('spawn a node in a different process', (done) => {
    const filePath = path.join(__dirname, './spawn-libp2p-node.js')
    spawnedNode = spawn(filePath)

    let spawned = false
    spawnedNode.stdout.on('data', (data) => {
      if (!spawned) {
        spawned = true
        done()
      }
    })
  })

  it('connect nodeA to that node', (done) => {
    const spawnedId = require('./test-data/test-id.json')
    const maddr = multiaddr('/ip4/127.0.0.1/tcp/12345/ipfs/' + spawnedId.id)
    nodeA.dialByMultiaddr(maddr, '/echo/1.0.0', (err, conn) => {
      expect(err).to.not.exist
      const peers = nodeA.peerBook.getAll()

      expect(Object.keys(peers)).to.have.length(4)

      pull(
        pull.values([Buffer('hey')]),
        conn,
        pull.collect((err, data) => {
          expect(err).to.not.exist
          expect(data).to.be.eql([Buffer('hey')])
          done()
        })
      )
    })
  })

  it('nodeE ping to nodeF', (done) => {
    nodeE.pingByPeerInfo(nodeF.peerInfo, (err, ping) => {
      expect(err).to.not.exist
      ping.once('ping', (time) => {
        expect(time).to.be.above(1)
        ping.stop()
        done()
      })
    })
  })

  it('crash that node, make sure nodeA continues going steady', (done) => {
    spawnedNode.kill('SIGKILL')

    setTimeout(check, 5000)

    function check () {
      const peers = nodeA.peerBook.getAll()
      expect(Object.keys(peers)).to.have.length(3)
      done()
    }
  })

  it('stop', (done) => {
    parallel([
      (cb) => nodeA.stop(cb),
      (cb) => nodeB.stop(cb),
      (cb) => nodeC.stop(cb),
      (cb) => nodeD.stop(cb),
      (cb) => nodeE.stop(cb),
      (cb) => nodeF.stop(cb)
    ], done)
  })
})
<commit_msg>fix: sometimes ping is super fast<commit_after>'use strict'
/* eslint-env mocha */

const expect = require('chai').expect
const Node = require('../src')
const PeerInfo = require('peer-info')
const multiaddr = require('multiaddr')
const parallel = require('async/parallel')
const map = require('async/map')
const spawn = require('child_process').spawn
const path = require('path')
const pull = require('pull-stream')

describe('libp2p-ipfs-nodejs', () => {
  let nodeA // TCP
  let nodeB // TCP
  let nodeC // TCP
  let nodeD // TCP
  let nodeE // TCP + WebSockets
  let nodeF // WebSockets

  let nodeAMultiaddrTCP
  let nodeBMultiaddrTCP
  let nodeCMultiaddrTCP
  let nodeDMultiaddrTCP
  let nodeEMultiaddrTCP
  let nodeEMultiaddrWebSockets
  let nodeFMultiaddrWebSockets

  let spawnedNode

  it('create 6 nodes', (done) => {
    map([0, 1, 2, 3, 4, 5], (i, cb) => {
      PeerInfo.create(cb)
    }, (err, infos) => {
      if (err) {
        return done(err)
      }

      infos.forEach((info, i) => {
        if (i === 5) {
          return
        }
        info.multiaddr.add(multiaddr('/ip4/0.0.0.0/tcp/0'))
      })

      nodeA = new Node(infos[0])
      nodeB = new Node(infos[1])
      nodeC = new Node(infos[2])
      nodeD = new Node(infos[3])
      nodeE = new Node(infos[4])
      const maddrWS1 = multiaddr('/ip4/127.0.0.1/tcp/25001/ws')
      nodeE.peerInfo.multiaddr.add(maddrWS1)

      nodeEMultiaddrWebSockets = multiaddr(
        nodeE.peerInfo.multiaddrs[1].toString() +
        '/ipfs/' + nodeE.peerInfo.id.toB58String()
      )

      const pInfo = infos[5]
      const maddrWS2 = multiaddr('/ip4/127.0.0.1/tcp/25002/ws')
      pInfo.multiaddr.add(maddrWS2)

      nodeF = new Node(pInfo)

      nodeFMultiaddrWebSockets = multiaddr(
        nodeF.peerInfo.multiaddrs[0].toString() +
        '/ipfs/' + nodeF.peerInfo.id.toB58String()
      )

      done()
    })
  })

  it('start 6 nodes', (done) => {
    parallel([
      (cb) => nodeA.start(cb),
      (cb) => nodeB.start(cb),
      (cb) => nodeC.start(cb),
      (cb) => nodeD.start(cb),
      (cb) => nodeE.start(cb),
      (cb) => nodeF.start(cb)
    ], (err) => {
      expect(err).to.not.exist
      expect(nodeA.peerInfo.multiaddrs.length > 1).to.equal(true)
      expect(nodeB.peerInfo.multiaddrs.length > 1).to.equal(true)
      expect(nodeC.peerInfo.multiaddrs.length > 1).to.equal(true)
      expect(nodeD.peerInfo.multiaddrs.length > 1).to.equal(true)
      expect(nodeE.peerInfo.multiaddrs.length > 2).to.equal(true)
      expect(nodeF.peerInfo.multiaddrs.length).to.equal(1)
      done()
    })
  })

  it('extract TCP multiaddr', () => {
    nodeAMultiaddrTCP = multiaddr((
      nodeA.peerInfo.multiaddrs[0].toString() +
      '/ipfs/' + nodeA.peerInfo.id.toB58String()
      ).replace('0.0.0.0', '127.0.0.1')
    )
    nodeBMultiaddrTCP = multiaddr((
      nodeB.peerInfo.multiaddrs[0].toString() +
      '/ipfs/' + nodeB.peerInfo.id.toB58String()
      ).replace('0.0.0.0', '127.0.0.1')

    )
    nodeCMultiaddrTCP = multiaddr((
      nodeC.peerInfo.multiaddrs[0].toString() +
      '/ipfs/' + nodeC.peerInfo.id.toB58String()
      ).replace('0.0.0.0', '127.0.0.1')

    )
    nodeDMultiaddrTCP = multiaddr((
      nodeD.peerInfo.multiaddrs[0].toString() +
      '/ipfs/' + nodeD.peerInfo.id.toB58String()
      ).replace('0.0.0.0', '127.0.0.1')
    )

    // Note: Here is the multiaddrs[1] again because
    // the .replace in swarm switches the order of
    // the TCP and WS addr
    nodeEMultiaddrTCP = multiaddr((
      nodeE.peerInfo.multiaddrs[1].toString() +
      '/ipfs/' + nodeE.peerInfo.id.toB58String()
      ).replace('0.0.0.0', '127.0.0.1')
    )

    // console.log(nodeAMultiaddrTCP.toString())
    // console.log(nodeBMultiaddrTCP.toString())
    // console.log(nodeCMultiaddrTCP.toString())
    // console.log(nodeDMultiaddrTCP.toString())
    // console.log(nodeEMultiaddrTCP.toString())
  })

  it('handle echo proto in 6 nodes', () => {
    function echo (protocol, conn) {
      pull(conn, conn)
    }

    nodeA.handle('/echo/1.0.0', echo)
    nodeB.handle('/echo/1.0.0', echo)
    nodeC.handle('/echo/1.0.0', echo)
    nodeD.handle('/echo/1.0.0', echo)
    nodeE.handle('/echo/1.0.0', echo)
    nodeF.handle('/echo/1.0.0', echo)
  })

  // General connectivity tests

  it('libp2p.dialByMultiaddr nodeA to nodeB', (done) => {
    nodeA.dialByMultiaddr(nodeBMultiaddrTCP, (err) => {
      expect(err).to.not.exist
      // Some time for Identify to finish
      setTimeout(check, 500)

      function check () {
        parallel([
          (cb) => {
            const peers = nodeA.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(1)
            cb()
          },
          (cb) => {
            const peers = nodeB.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(1)
            cb()
          }
        ], done)
      }
      // TODO confirm that we got the pubkey through identify
    })
  })

  it('libp2p.dialByMultiaddr on Protocol nodeA to nodeB', (done) => {
    nodeA.dialByMultiaddr(nodeBMultiaddrTCP, '/echo/1.0.0', (err, conn) => {
      expect(err).to.not.exist
      parallel([
        (cb) => {
          const peers = nodeA.peerBook.getAll()
          expect(err).to.not.exist
          expect(Object.keys(peers)).to.have.length(1)
          cb()
        },
        (cb) => {
          const peers = nodeB.peerBook.getAll()
          expect(err).to.not.exist
          expect(Object.keys(peers)).to.have.length(1)
          cb()
        }
      ], () => {
        pull(
          pull.values([Buffer('hey')]),
          conn,
          pull.collect((err, data) => {
            expect(err).to.not.exist
            expect(data).to.be.eql([Buffer('hey')])
            done()
          })
        )
      })
    })
  })

  it('libp2p.hangupByMultiaddr nodeA to nodeB', (done) => {
    nodeA.hangUpByMultiaddr(nodeBMultiaddrTCP, (err) => {
      expect(err).to.not.exist
      setTimeout(check, 500)

      function check () {
        parallel([
          (cb) => {
            const peers = nodeA.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(0)
            expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)

            cb()
          },
          (cb) => {
            const peers = nodeB.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(0)
            expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
            cb()
          }
        ], done)
      }
    })
  })

  it('libp2p.dialByPeerInfo nodeA to nodeB', (done) => {
    nodeA.dialByPeerInfo(nodeB.peerInfo, (err) => {
      expect(err).to.not.exist
      // Some time for Identify to finish
      setTimeout(check, 500)

      function check () {
        parallel([
          (cb) => {
            const peers = nodeA.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(1)
            cb()
          },
          (cb) => {
            const peers = nodeB.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(1)
            cb()
          }
        ], done)
      }
      // TODO confirm that we got the pubkey through identify
    })
  })

  it('libp2p.dialByPeerInfo on Protocol nodeA to nodeB', (done) => {
    nodeA.dialByPeerInfo(nodeB.peerInfo, '/echo/1.0.0', (err, conn) => {
      expect(err).to.not.exist
      parallel([
        (cb) => {
          const peers = nodeA.peerBook.getAll()
          expect(err).to.not.exist
          expect(Object.keys(peers)).to.have.length(1)
          cb()
        },
        (cb) => {
          const peers = nodeB.peerBook.getAll()
          expect(err).to.not.exist
          expect(Object.keys(peers)).to.have.length(1)
          cb()
        }
      ], () => {
        pull(
          pull.values([Buffer('hey')]),
          conn,
          pull.collect((err, data) => {
            expect(err).to.not.exist
            expect(data).to.be.eql([Buffer('hey')])
            done()
          })
        )
      })
    })
  })

  it('libp2p.hangupByPeerInfo nodeA to nodeB', (done) => {
    nodeA.hangUpByPeerInfo(nodeB.peerInfo, (err) => {
      expect(err).to.not.exist
      setTimeout(check, 500)

      function check () {
        parallel([
          (cb) => {
            const peers = nodeA.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(0)
            expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)

            cb()
          },
          (cb) => {
            const peers = nodeB.peerBook.getAll()
            expect(err).to.not.exist
            expect(Object.keys(peers)).to.have.length(0)
            expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
            cb()
          }
        ], done)
      }
    })
  })

  // NOTE, these dialById only works if a previous dial was made
  // until we have PeerRouting
  it.skip('libp2p.dialById nodeA to nodeB', (done) => {})
  it.skip('libp2p.dialById on Protocol nodeA to nodeB', (done) => {})
  it.skip('libp2p.hangupById nodeA to nodeB', (done) => {})

  it('nodeA dial to nodeC and nodeD', (done) => {
    let count = 0
    const next = () => ++count === 2 ? check() : null

    nodeA.dialByMultiaddr(nodeCMultiaddrTCP, next)
    nodeA.dialByMultiaddr(nodeDMultiaddrTCP, next)

    function check () {
      const peers = nodeA.peerBook.getAll()
      expect(Object.keys(peers)).to.have.length(2)
      done()
    }
  })

  // Multiple transport tests

  it('nodeA dial to nodeE', (done) => {
    nodeA.dialByMultiaddr(nodeEMultiaddrTCP, (err) => {
      expect(err).to.not.exist
      const peers = nodeA.peerBook.getAll()
      expect(Object.keys(peers)).to.have.length(3)
      done()
    })
  })

  // Until https://github.com/libp2p/js-libp2p/issues/46 is resolved
  // Everynode will be able to dial in WebSockets
  it.skip('nodeA fails to dial to nodeF', (done) => {
    nodeA.dialByMultiaddr(nodeFMultiaddrWebSockets, (err) => {
      expect(err).to.exist
      const peers = nodeA.peerBook.getAll()
      expect(Object.keys(peers)).to.have.length(3)
      done()
    })
  })

  it('nodeF fails to dial to nodeA', (done) => {
    nodeF.dialByMultiaddr(nodeAMultiaddrTCP, (err) => {
      expect(err).to.exist
      done()
    })
  })

  it('nodeF dial to nodeE', (done) => {
    nodeF.dialByMultiaddr(nodeEMultiaddrWebSockets, (err) => {
      expect(err).to.not.exist
      done()
    })
  })

  // Turbolence tests

  it('spawn a node in a different process', (done) => {
    const filePath = path.join(__dirname, './spawn-libp2p-node.js')
    spawnedNode = spawn(filePath)

    let spawned = false
    spawnedNode.stdout.on('data', (data) => {
      if (!spawned) {
        spawned = true
        done()
      }
    })
  })

  it('connect nodeA to that node', (done) => {
    const spawnedId = require('./test-data/test-id.json')
    const maddr = multiaddr('/ip4/127.0.0.1/tcp/12345/ipfs/' + spawnedId.id)
    nodeA.dialByMultiaddr(maddr, '/echo/1.0.0', (err, conn) => {
      expect(err).to.not.exist
      const peers = nodeA.peerBook.getAll()

      expect(Object.keys(peers)).to.have.length(4)

      pull(
        pull.values([Buffer('hey')]),
        conn,
        pull.collect((err, data) => {
          expect(err).to.not.exist
          expect(data).to.be.eql([Buffer('hey')])
          done()
        })
      )
    })
  })

  it('nodeE ping to nodeF', (done) => {
    nodeE.pingByPeerInfo(nodeF.peerInfo, (err, ping) => {
      expect(err).to.not.exist
      ping.once('ping', (time) => {
        expect(time).to.be.above(0)
        ping.stop()
        done()
      })
    })
  })

  it('crash that node, make sure nodeA continues going steady', (done) => {
    spawnedNode.kill('SIGKILL')

    setTimeout(check, 5000)

    function check () {
      const peers = nodeA.peerBook.getAll()
      expect(Object.keys(peers)).to.have.length(3)
      done()
    }
  })

  it('stop', (done) => {
    parallel([
      (cb) => nodeA.stop(cb),
      (cb) => nodeB.stop(cb),
      (cb) => nodeC.stop(cb),
      (cb) => nodeD.stop(cb),
      (cb) => nodeE.stop(cb),
      (cb) => nodeF.stop(cb)
    ], done)
  })
})
<|endoftext|>


<commit_before>var uuid = require('node-uuid').v4;

describe('Model.Doc', function() {
  beforeEach(function *() {
    yield fixtures.load(['docs', 'collections']);
  });

  it('should reject when update parentUUID outside a transaction', function() {
    var doc = fixtures.docs[0];
    var oldParentUUID = doc.parentUUID;
    return doc.updateAttributes({ parentUUID: uuid() }).then(function() {
      throw new Error('should reject');
    }).catch(function(err) {
      expect(err.message).to.eql('Updating the parentUUID should within a transaction');
    });
  });

  it('should update successfully when parentUUID is not touched', function() {
    var doc = fixtures.docs[0];
    doc.title = 'updated doc';
    return doc.save();
  });

  describe('.createWithTransaction()', function() {
    it('should reject is CollectionId is not specified', function() {
      return Doc.createWithTransaction({
        title: 'new doc',
        content: 'new content'
      }).then(function(doc) {
        throw new Error('should reject');
      }).catch(function(err) {
        expect(err.message).to.eql('CollectionId is not specified');
      });
    });

    it('should have a default UUID and null parentUUID', function() {
      return Doc.createWithTransaction({
        title: 'new doc',
        content: 'new content',
        CollectionId: fixtures.collections[0].id
      }).then(function(doc) {
        expect(doc).to.have.property('UUID');
        /* jshint expr:true */
        expect(doc.parentUUID).to.not.exist;
      });
    });

    it('should mark the previous version inactive', function() {
      var oldDoc = fixtures.docs[0];
      var newDoc;
      return Doc.createWithTransaction({
        UUID: oldDoc.UUID,
        title: 'new title',
        content: 'new content',
        CollectionId: fixtures.collections[0].id
      }).then(function(doc) {
        newDoc = doc;
        return oldDoc.reload();
      }).then(function() {
        expect(oldDoc.current).to.eql(false);
        expect(newDoc.current).to.eql(true);
      });
    });

    it('should calculate the distance between contents', function() {
      var oldDoc = fixtures.docs[0];
      return Doc.createWithTransaction({
        UUID: oldDoc.UUID,
        title: 'new title',
        content: '',
        CollectionId: fixtures.collections[0].id
      }).then(function(doc) {
        expect(doc.distance).to.eql(oldDoc.content.length);
      });
    });

    it('should reject when the parentUUID not exists', function() {
      return Doc.createWithTransaction({
        title: 'new title',
        content: '',
        parentUUID: uuid(),
        CollectionId: fixtures.collections[0].id
      }).then(function() {
        throw new Error('should reject');
      }).catch(function(err) {
        expect(err).to.have.property('message', 'Parent document not exists');
      });
    });

    it('should reject when the parentUUID belong another collection', function() {
      var collections = fixtures.collections;
      var docs = fixtures.docs;
      return collections[0].addDoc(docs[0]).then(function() {
        return Doc.createWithTransaction({
          title: 'new title',
          content: '',
          CollectionId: collections[1].id,
          parentUUID: docs[0].UUID
        });
      }).then(function() {
        throw new Error('should reject');
      }).catch(function(err) {
        expect(err).to.have.property('message', 'Parent document should belong to the same collection');
      });
    });

    it('should create the instance with parentUUID being set', function() {
      var collections = fixtures.collections;
      var docs = fixtures.docs;
      return collections[0].addDoc(docs[0]).then(function() {
        return Doc.createWithTransaction({
          title: 'new title',
          content: '',
          CollectionId: collections[0].id,
          parentUUID: docs[0].UUID
        });
      }).then(function(doc) {
        expect(doc.parentUUID).to.eql(docs[0].UUID);
      });
    });

    it('should rollback when creation fails', function() {
      sinon.stub(Doc, 'create', function() {
        return Promise.reject(new Error('reject'));
      });

      var oldDoc = fixtures.docs[0];
      var newDoc;
      return Doc.createWithTransaction({
        UUID: oldDoc.UUID,
        title: 'new title',
        content: 'new content',
        CollectionId: fixtures.collections[0].id
      }).then(function() {
        throw new Error('should reject');
      }).catch(function(err) {
        expect(err.message).to.eql('reject');
        return oldDoc.reload().then(function() {
          expect(oldDoc.current).to.eql(true);
          Doc.create.restore();
        });
      });
    });
  });

  describe('#setParent()', function() {
    it('should update the parent of document', function *() {
      var doc = fixtures.docs[0];
      var parentDoc = fixtures.docs[1];
      yield fixtures.collections[0].addDocs([doc, parentDoc]);
      yield doc.setParent(parentDoc.UUID);
      expect(yield doc.reload()).to.have.property('parentUUID', parentDoc.UUID);
    });

    it('should rollback when creation fails', function *() {
      var doc = fixtures.docs[0];
      var previousParentUUID = doc.parentUUID;
      var parentDoc = fixtures.docs[1];
      yield fixtures.collections[0].addDocs([doc, parentDoc]);
      sinon.stub(doc, 'save', function() {
        throw new Error('reject');
      });
      try {
        yield doc.setParent(parentDoc.UUID);
        throw new Error('should reject');
      } catch (err) {
        expect(err.message).to.eql('reject');
        expect(yield doc.reload()).to.have.property('parentUUID', previousParentUUID);
      }
    });
  });

  describe('#setOrder()', function() {
    it.only('should update the order of document', function *() {
      try {
        var collection = fixtures.collections[0];
        var docs = fixtures.docs;
        yield collection.addDocs(fixtures.docs);
        var parentDoc = docs[0];
        yield docs[1].setParent(parentDoc.UUID);
        yield docs[2].setParent(docs[1].UUID);
        yield docs[3].setParent(docs[1].UUID);
        yield docs[4].setParent(docs[1].UUID);
        yield docs[5].setParent(docs[1].UUID);
        yield docs[2].setOrder(0);
        yield docs[3].setOrder(1);
        yield docs[4].setOrder(2);
        yield docs[5].setOrder(3);
        yield docs[4].setOrder(1);
        var subDocs = yield Doc.findAll({
          where: { parentUUID: docs[1].UUID },
          order: '`order` ASC'
        });
        expect(subDocs.map(function(doc) { return doc.id; })).to.eql([3, 5, 4, 6]);
      } catch (err) {
        console.log(err);
        throw err;
      }
    });
  });
});
<commit_msg>Fix col name failed issue<commit_after>var uuid = require('node-uuid').v4;

describe('Model.Doc', function() {
  beforeEach(function *() {
    yield fixtures.load(['docs', 'collections']);
  });

  it('should reject when update parentUUID outside a transaction', function() {
    var doc = fixtures.docs[0];
    var oldParentUUID = doc.parentUUID;
    return doc.updateAttributes({ parentUUID: uuid() }).then(function() {
      throw new Error('should reject');
    }).catch(function(err) {
      expect(err.message).to.eql('Updating the parentUUID should within a transaction');
    });
  });

  it('should update successfully when parentUUID is not touched', function() {
    var doc = fixtures.docs[0];
    doc.title = 'updated doc';
    return doc.save();
  });

  describe('.createWithTransaction()', function() {
    it('should reject is CollectionId is not specified', function() {
      return Doc.createWithTransaction({
        title: 'new doc',
        content: 'new content'
      }).then(function(doc) {
        throw new Error('should reject');
      }).catch(function(err) {
        expect(err.message).to.eql('CollectionId is not specified');
      });
    });

    it('should have a default UUID and null parentUUID', function() {
      return Doc.createWithTransaction({
        title: 'new doc',
        content: 'new content',
        CollectionId: fixtures.collections[0].id
      }).then(function(doc) {
        expect(doc).to.have.property('UUID');
        /* jshint expr:true */
        expect(doc.parentUUID).to.not.exist;
      });
    });

    it('should mark the previous version inactive', function() {
      var oldDoc = fixtures.docs[0];
      var newDoc;
      return Doc.createWithTransaction({
        UUID: oldDoc.UUID,
        title: 'new title',
        content: 'new content',
        CollectionId: fixtures.collections[0].id
      }).then(function(doc) {
        newDoc = doc;
        return oldDoc.reload();
      }).then(function() {
        expect(oldDoc.current).to.eql(false);
        expect(newDoc.current).to.eql(true);
      });
    });

    it('should calculate the distance between contents', function() {
      var oldDoc = fixtures.docs[0];
      return Doc.createWithTransaction({
        UUID: oldDoc.UUID,
        title: 'new title',
        content: '',
        CollectionId: fixtures.collections[0].id
      }).then(function(doc) {
        expect(doc.distance).to.eql(oldDoc.content.length);
      });
    });

    it('should reject when the parentUUID not exists', function() {
      return Doc.createWithTransaction({
        title: 'new title',
        content: '',
        parentUUID: uuid(),
        CollectionId: fixtures.collections[0].id
      }).then(function() {
        throw new Error('should reject');
      }).catch(function(err) {
        expect(err).to.have.property('message', 'Parent document not exists');
      });
    });

    it('should reject when the parentUUID belong another collection', function() {
      var collections = fixtures.collections;
      var docs = fixtures.docs;
      return collections[0].addDoc(docs[0]).then(function() {
        return Doc.createWithTransaction({
          title: 'new title',
          content: '',
          CollectionId: collections[1].id,
          parentUUID: docs[0].UUID
        });
      }).then(function() {
        throw new Error('should reject');
      }).catch(function(err) {
        expect(err).to.have.property('message', 'Parent document should belong to the same collection');
      });
    });

    it('should create the instance with parentUUID being set', function() {
      var collections = fixtures.collections;
      var docs = fixtures.docs;
      return collections[0].addDoc(docs[0]).then(function() {
        return Doc.createWithTransaction({
          title: 'new title',
          content: '',
          CollectionId: collections[0].id,
          parentUUID: docs[0].UUID
        });
      }).then(function(doc) {
        expect(doc.parentUUID).to.eql(docs[0].UUID);
      });
    });

    it('should rollback when creation fails', function() {
      sinon.stub(Doc, 'create', function() {
        return Promise.reject(new Error('reject'));
      });

      var oldDoc = fixtures.docs[0];
      var newDoc;
      return Doc.createWithTransaction({
        UUID: oldDoc.UUID,
        title: 'new title',
        content: 'new content',
        CollectionId: fixtures.collections[0].id
      }).then(function() {
        throw new Error('should reject');
      }).catch(function(err) {
        expect(err.message).to.eql('reject');
        return oldDoc.reload().then(function() {
          expect(oldDoc.current).to.eql(true);
          Doc.create.restore();
        });
      });
    });
  });

  describe('#setParent()', function() {
    it('should update the parent of document', function *() {
      var doc = fixtures.docs[0];
      var parentDoc = fixtures.docs[1];
      yield fixtures.collections[0].addDocs([doc, parentDoc]);
      yield doc.setParent(parentDoc.UUID);
      expect(yield doc.reload()).to.have.property('parentUUID', parentDoc.UUID);
    });

    it('should rollback when creation fails', function *() {
      var doc = fixtures.docs[0];
      var previousParentUUID = doc.parentUUID;
      var parentDoc = fixtures.docs[1];
      yield fixtures.collections[0].addDocs([doc, parentDoc]);
      sinon.stub(doc, 'save', function() {
        throw new Error('reject');
      });
      try {
        yield doc.setParent(parentDoc.UUID);
        throw new Error('should reject');
      } catch (err) {
        expect(err.message).to.eql('reject');
        expect(yield doc.reload()).to.have.property('parentUUID', previousParentUUID);
      }
    });
  });

  describe('#setOrder()', function() {
    it('should update the order of document', function *() {
      var collection = fixtures.collections[0];
      var docs = fixtures.docs;
      yield collection.addDocs(fixtures.docs);
      var parentDoc = docs[0];
      yield docs[1].setParent(parentDoc.UUID);
      yield docs[2].setParent(docs[1].UUID);
      yield docs[3].setParent(docs[1].UUID);
      yield docs[4].setParent(docs[1].UUID);
      yield docs[5].setParent(docs[1].UUID);
      yield docs[2].setOrder(0);
      yield docs[3].setOrder(1);
      yield docs[4].setOrder(2);
      yield docs[5].setOrder(3);
      yield docs[4].setOrder(1);
      var subDocs = yield Doc.findAll({
        where: { parentUUID: docs[1].UUID },
        order: [sequelize.col('order')]
      });
      expect(subDocs.map(function(doc) { return doc.id; })).to.eql([3, 5, 4, 6]);
    });
  });
});
<|endoftext|>


<commit_before>/**
 * @copyright Copyright 2016 Kevin Locke <kevin@kevinlocke.name>
 * @license MIT
 */
'use strict';

var modulename = require('..');

describe('modulename', function() {
  it('does something', function(done) {
    // Assert something about modulename here
    modulename.works();
  });
});
<commit_msg>Use a real function for linting<commit_after>/**
 * @copyright Copyright 2016 Kevin Locke <kevin@kevinlocke.name>
 * @license MIT
 */
'use strict';

var modulename = require('..');

describe('modulename', function() {
  it('does something', function(done) {
    // Assert something about modulename here
    modulename.func();
  });
});
<|endoftext|>


<commit_before>var Date2 = require('../src/date-2');
var date = new Date2('25-03-2016','-');
console.log('date: ' + date);
date.addDays(3);
console.log('date + 3 days: ' + date);
date.removeDays(1);
console.log('date - 1 days: ' + date);
console.log('day of the week: ' + date.dayOfWeek());
console.log('day of week english: ' + date.dayOfWeekLetters('en'));
console.log('day of week francais: ' + date.dayOfWeekLetters('fr'));
console.log('is a working day: ' + date.isWorkingDay());
var date2 = new Date2('25 03 2016');
console.log('second date: ' + date2);
date2.setDelim('-');
console.log('setDelim \'-\': ' + date2);
console.log('day difference: ' + date.dayDifference(date2));
var date3 = new Date2('30 05 2017');
console.log('third date: ' + date3);
console.log(date3 + ' is in Range [' + date2 + ',' + date + '] ?: ' + date3.isInRange(date,date2));
var date3 = new Date2('26-03-2016');
console.log('third date: ' + date3);
console.log(date3 + ' is in Range [' + date2 + ',' + date + '] ?: ' + date3.isInRange(date,date2));<commit_msg>minor change<commit_after>var Date2 = require('../src/date-2');
var date = new Date2('25-03-2016','-');
console.log('date: ' + date);
date.addDays(3);
console.log('date + 3 days: ' + date);
date.removeDays(4);
console.log('date - 4 days: ' + date);
date.addWorkingDays(16);
console.log('date + 16 working days: '+date);
console.log('get next day: '+date.getNextDay());
console.log('get previous day: '+date.getPreviousDay());
date.nextDay();
console.log('to next day: '+date);
date.previousDay();
console.log('to previous day: '+date);
console.log('get next working day: '+date.getNextWorkingDay());
date.nextWorkingDay();
console.log('to next working day: '+date);
console.log('day of the week: ' + date.dayOfWeek());
console.log('day of week english: ' + date.dayOfWeekLetters('en'));
console.log('day of week francais: ' + date.dayOfWeekLetters('fr'));
console.log('is a working day: ' + date.isWorkingDay());
var date2 = new Date2('25 03 2016');
console.log('second date: ' + date2);
date2.setDelim('-');
console.log('setDelim \'-\': ' + date2);
console.log('day difference: ' + date.dayDifference(date2));
var date3 = new Date2('30 05 2017');
console.log('third date: ' + date3);
console.log(date3 + ' is in Range [' + date2 + ',' + date + '] ?: ' + date3.isInRange(date,date2));
var date3 = new Date2('26-03-2016');
console.log('third date: ' + date3);
console.log(date3 + ' is in Range [' + date2 + ',' + date + '] ?: ' + date3.isInRange(date,date2));<|endoftext|>


<commit_before>(function (){
  angular
    .module('userNotifications', [])
    .constant('TYPES', {
      INFO_TYPE: 'info',
      SUCCESS_TYPE: 'success',
      WARN_TYPE: 'warning',
      ERR_TYPE: 'error'
    })
    .service('userNotificationsService', ['$filter', '$timeout', 'TYPES', function ($filter, $timeout, TYPES){
      var TIMEOUT_TIME = 4000,
          _id = 0,
          _notifications = [];

      var service = {
        addNotification: addNotification,
        addNotifications: addNotifications,
        displayMessage: displayMessage,
        displayMessages: displayMessages,
        closeNotificationById: closeNotificationById,
        closeNotificationByType: closeNotificationByType,
        closeAllNotifications: closeAllNotifications,
        getNotifications: getNotifications,
        setTimeoutTime: setTimeoutTime,
        getTimeoutTime: getTimeoutTime
      };

      return service;
      //////////////////////////////////////////////////////////////
      /**
      * Display a notification.
      * @param {Object} notification - The notification object.
      * @return {Number|undefined} ids - Ids of displayed notifications.
      */
      function addNotification(notification){
        if(!notification || !angular.isObject(notification)){ return ; }

        if(notification.isReplace && notification.type){
            closeNotificationByType(notification.type);
        }

        if(angular.isString(notification.message)){
          return _pushNotification(notification.message, notification);
        } else if(angular.isArray(notification.message)) {
          var ids = [];
          angular.forEach(notification.message, function (message){
            ids.push(_pushNotification(message, notification));
          });
          return ids;
        }
      }

      /**
      * Display array of notifications.
      * @param {Array} notifications - The array of notifications.
      * @return {Array|undefined} ids - The ids of displayed notifications.
      */
      function addNotifications(notifications){
        if(!notifications || !angular.isArray(notifications)) { return; }

        var ids = [];

        angular.forEach(notifications, function (notification){
          if(notification && angular.isObject(notifications)){
            ids.push(addNotification(notification));
          }
        });
      }

      /**
      * Push notification to array of all opened notifications.
      * @param {String} message - Message for user.
      * @param {String} [notification] - Notification object.
      * @return {Number} id - Id of the opened notification.
      */
      function _pushNotification(message, notification){
        var id = _id++,
            notObj = notification || {},
            promise = notObj.isStatic ? null : createTimeout(id),
            type = getType(notObj.type);

       _notifications.push({
          id: id,
          message: message,
          type: type,
          promise: promise
        });
        return id;
      }

      /**
      * Check passed type and return the correct.
      * @param {String} type - Type of notification.
      * @return {String}
      */
      function getType(type){
        switch(type) {
          case TYPES.SUCCESS_TYPE:
          case TYPES.WARB_TYPE:
          case TYPES.ERR_TYPE:
            return type;
        }
        return TYPES.INFO_TYPE;
      }

      /**
      * Create a timeout that is used to close notification by id when time passes.
      * @param {Number} id - Notification id.
      * @return {Object} promise - Promise object of timeout.
      */
      function createTimeout(id){
        return $timeout(function() {
          closeNotificationById(id);
        }, TIMEOUT_TIME);
      }

      /**
      * Display a simple message.
      * @param {String|undefined} message - Message to display.
      */
      function displayMessage(message){
        if(!angular.isString(message)) { return; }

        return _pushNotification(message);
      }

      /**
      * Display messages.
      * @param {Array} messages - Array of messages to display.
      * @return {Array|undefined} ids - Ids of displayed messages.
      */
      function displayMessages(messages){
        if(!angular.isArray(messages)) { return; }

        var ids = [];
        messages.forEach(function (message){
          if(angular.isString(message)){
            ids.push(_pushNotification(message));
          }
        });
        return ids;
      }

      /**
      * Close notification by id.
      * @param {Number} id - Notification id.
      */
      function closeNotificationById(id){
        if(!angular.isNumber(id) || !isFinite(id)) { return; }

        angular.forEach(_notifications, function (item, index){
          if(item.id === id){
            $timeout.cancel(item.promise);
            _notifications.splice(index, 1);
            return;
          }
        });
      }

      /**
      * Close notification by type.
      * @param {String} type - Notification type.
      */
      function closeNotificationByType(type){
        if(!type || !angular.isString(type)) { return; }

        var ids = [];

        angular.forEach(_notifications, function (item, index){
          if(item.type === type){
            ids.push(item.id);
          }
        });

        angular.forEach(ids, function (id){
          closeNotificationById(id);
        });
      }

      /**
      * Close all notifications.
      */
      function closeAllNotifications(){
        angular.forEach(_notifications, function (item, index){
          $timeout.close(item.promise);
        });
        _notifications = [];
      }

      /**
      * Get notifications array.
      * @return {Array}
      */
      function getNotifications() {
        return _notifications;
      }

      /**
      * Set the current timeout time.
      * @param {Number} value New timeout time value.
      * @return {Boolean}
      */
      function setTimeoutTime(value) {
        if(!value || !angular.isNumber(value) || !isFinite(value)) { return false; }

        TIMEOUT_TIME = value;
        return true;
      }

      /**
      * Get the current timeout time.
      * @return {Number}
      */
      function getTimeoutTime() {
        return TIMEOUT_TIME;
      }
    }])
    .directive('userNotifications', ['$window', 'userNotificationsService', function ($window, userNotificationsService){
      return {
        template: '
' +
                      '

{{item.message}}

' +
                  '
',
        restrict: 'AE',
        link: function (scope, el, attr){
          scope.$watch(function () {
            return userNotificationsService.getNotifications();
          }, function () {
            scope.notifications = userNotificationsService.getNotifications();
          });
          scope.close = function (id) {
            userNotificationsService.closeNotificationById(id);
          };
        }
      };
    }]);
})();
<commit_msg>Minor style changes<commit_after>(function (){
  angular
    .module('userNotifications', [])
    .constant('TYPES', {
      INFO_TYPE: 'info',
      SUCCESS_TYPE: 'success',
      WARN_TYPE: 'warning',
      ERR_TYPE: 'error'
    })
    .service('userNotificationsService', ['$filter', '$timeout', 'TYPES', function ($filter, $timeout, TYPES) {
      var TIMEOUT_TIME = 4000,
          _id = 0,
          _notifications = [];

      var service = {
        addNotification: addNotification,
        addNotifications: addNotifications,
        displayMessage: displayMessage,
        displayMessages: displayMessages,
        closeNotificationById: closeNotificationById,
        closeNotificationByType: closeNotificationByType,
        closeAllNotifications: closeAllNotifications,
        getNotifications: getNotifications,
        setTimeoutTime: setTimeoutTime,
        getTimeoutTime: getTimeoutTime
      };

      return service;
      //////////////////////////////////////////////////////////////
      /**
      * Display a notification.
      * @param {Object} notification - The notification object.
      * @return {Number|undefined} ids - Ids of displayed notifications.
      */
      function addNotification(notification) {
        if (!notification || !angular.isObject(notification)) { return ; }

        if (notification.isReplace && notification.type) {
            closeNotificationByType(notification.type);
        }

        if(angular.isString(notification.message)){
          return _pushNotification(notification.message, notification);
        } else if (angular.isArray(notification.message)) {
          var ids = [];
          angular.forEach(notification.message, function (message) {
            ids.push(_pushNotification(message, notification));
          });
          return ids;
        }
      }

      /**
      * Display array of notifications.
      * @param {Array} notifications - The array of notifications.
      * @return {Array|undefined} ids - The ids of displayed notifications.
      */
      function addNotifications(notifications) {
        if (!notifications || !angular.isArray(notifications)) { return; }

        var ids = [];

        angular.forEach(notifications, function (notification) {
          if (notification && angular.isObject(notifications)) {
            ids.push(addNotification(notification));
          }
        });
      }

      /**
      * Push notification to array of all opened notifications.
      * @param {String} message - Message for user.
      * @param {String} [notification] - Notification object.
      * @return {Number} id - Id of the opened notification.
      */
      function _pushNotification(message, notification){
        var id = _id++,
            notObj = notification || {},
            promise = notObj.isStatic ? null : createTimeout(id),
            type = getType(notObj.type);

       _notifications.push({
          id: id,
          message: message,
          type: type,
          promise: promise
        });
        return id;
      }

      /**
      * Check passed type and return the correct.
      * @param {String} type - Type of notification.
      * @return {String}
      */
      function getType(type){
        switch(type) {
          case TYPES.SUCCESS_TYPE:
          case TYPES.WARB_TYPE:
          case TYPES.ERR_TYPE:
            return type;
        }
        return TYPES.INFO_TYPE;
      }

      /**
      * Create a timeout that is used to close notification by id when time passes.
      * @param {Number} id - Notification id.
      * @return {Object} promise - Promise object of timeout.
      */
      function createTimeout(id) {
        return $timeout(function() {
          closeNotificationById(id);
        }, TIMEOUT_TIME);
      }

      /**
      * Display a simple message.
      * @param {String|undefined} message - Message to display.
      */
      function displayMessage(message) {
        if (!angular.isString(message)) { return; }

        return _pushNotification(message);
      }

      /**
      * Display messages.
      * @param {Array} messages - Array of messages to display.
      * @return {Array|undefined} ids - Ids of displayed messages.
      */
      function displayMessages(messages){
        if (!angular.isArray(messages)) { return; }

        var ids = [];
        messages.forEach(function (message) {
          if (angular.isString(message)) {
            ids.push(_pushNotification(message));
          }
        });
        return ids;
      }

      /**
      * Close notification by id.
      * @param {Number} id - Notification id.
      */
      function closeNotificationById(id){
        if (!angular.isNumber(id) || !isFinite(id)) { return; }

        angular.forEach(_notifications, function (item, index) {
          if (item.id === id) {
            $timeout.cancel(item.promise);
            _notifications.splice(index, 1);
            return;
          }
        });
      }

      /**
      * Close notification by type.
      * @param {String} type - Notification type.
      */
      function closeNotificationByType(type) {
        if (!type || !angular.isString(type)) { return; }

        var ids = [];

        angular.forEach(_notifications, function (item, index) {
          if (item.type === type) {
            ids.push(item.id);
          }
        });

        angular.forEach(ids, function (id) {
          closeNotificationById(id);
        });
      }

      /**
      * Close all notifications.
      */
      function closeAllNotifications() {
        angular.forEach(_notifications, function (item, index) {
          $timeout.close(item.promise);
        });
        _notifications = [];
      }

      /**
      * Get notifications array.
      * @return {Array}
      */
      function getNotifications() {
        return _notifications;
      }

      /**
      * Set the current timeout time.
      * @param {Number} value New timeout time value.
      * @return {Boolean}
      */
      function setTimeoutTime(value) {
        if (!value || !angular.isNumber(value) || !isFinite(value)) { return false; }

        TIMEOUT_TIME = value;
        return true;
      }

      /**
      * Get the current timeout time.
      * @return {Number}
      */
      function getTimeoutTime() {
        return TIMEOUT_TIME;
      }
    }])
    .directive('userNotifications', ['$window', 'userNotificationsService', function ($window, userNotificationsService){
      return {
        template: '
' +
                      '

{{item.message}}

' +
                  '
',
        restrict: 'AE',
        link: function (scope, el, attr){
          scope.$watch(function () {
            return userNotificationsService.getNotifications();
          }, function () {
            scope.notifications = userNotificationsService.getNotifications();
          });
          scope.close = function (id) {
            userNotificationsService.closeNotificationById(id);
          };
        }
      };
    }]);
})();
<|endoftext|>


<commit_before>var promise = require('when');

describe('setup', function() {
  it('test env works', function() {
    expect(true).toBe(true);
  });
});

function promiseThatResolves() {
  return promise.promise(function(resolve) { resolve(); });
}
function promiseThatRejects() {
  return promise.promise(function(_, reject) { reject('A rejected promise'); });
}

describe('promises and jasmine', function() {
  it('the simplest passing promise test', function(done) {
    promiseThatResolves().then(success).done();

    function success() {
      expect(true).toBe(true);
      done();
    }
    // Issues here:
    // - missing `done();` on the last line makes the tests run looong (5s) until the timeout catches
    //   that would be acceptable, since it kinda gives a hint where to look
    // - to have the function success at all makes the flow of the test just a bit harder to read
  });

  it('a bit better passing promise test', function(done) {
    var success = jasmine.createSpy('success');
    promiseThatResolves().then(success).done();

    success.andCallFake(function() {
      expect(success).toHaveBeenCalled();
      done();
    });
    // Pro
    // - removes the little meaningful `expect(true).toBe(true);` and replaces it by something
    //   that shows a meaningful message when failing (kinda: `success should have been called ...`).
    //
    // Contra:
    // - the spy+callFake construct is not easy to understand on first sight
  });
});
<commit_msg>Example for a rejected promise test.<commit_after>var promise = require('when');

describe('setup', function() {
  it('test env works', function() {
    expect(true).toBe(true);
  });
});

function promiseThatResolves() {
  return promise.promise(function(resolve) { resolve(); });
}
function promiseThatRejects() {
  return promise.promise(function(_, reject) { reject('A rejected promise'); });
}

describe('promises and jasmine', function() {
  it('the simplest passing promise test', function(done) {
    promiseThatResolves().then(success).done();

    function success() {
      expect(true).toBe(true);
      done();
    }
    // Issues here:
    // - missing `done();` on the last line makes the tests run looong (5s) until the timeout catches
    //   that would be acceptable, since it kinda gives a hint where to look
    // - to have the function success at all makes the flow of the test just a bit harder to read
  });

  it('a bit better passing promise test', function(done) {
    var success = jasmine.createSpy('success');
    promiseThatResolves().then(success).done();

    success.andCallFake(function() {
      expect(success).toHaveBeenCalled();
      done();
    });
    // Pro
    // - removes the little meaningful `expect(true).toBe(true);` and replaces it by something
    //   that shows a meaningful message when failing (kinda: `success should have been called ...`).
    //
    // Contra:
    // - the spy+callFake construct is not easy to understand on first sight
  });

  it('a rejected promise example', function(done) {
    var success = jasmine.createSpy('success');
    var reject = jasmine.createSpy('reject');
    promiseThatRejects()
      .then(success)
      .catch(reject)
      .done();

    reject.andCallFake(function() {
      expect(reject).toHaveBeenCalled(); // we expect this, to pass test
      done();
    });
    success.andCallFake(function() {
      expect(success).not.toHaveBeenCalled(); // test fails when this is called
      done();
    });
    // Issues:
    // - if the promise resolves unexpectedly then the test will run into the timeout
    //   therefore I added the success spy+fake, sucks a bit imho
  });
});
<|endoftext|>


<commit_before>var tape = require('tape')
var render = require('../render')

tape('render', function(test) {

  test.same(
    render(
      { content: [ 'a b c' ] },
      { content: [ 'a d' ] })
      .content,
    [ { splits:
          [ { text: 'a' },
            { text: ' ' },
            { text: 'b', del: true },
            { text: ' ', del: true },
            { text: 'c', del: true },
            { text: 'd', ins: true } ] } ])

  test.same(
    render(
      { content: [ 'A B C' ] },
      { content: [ 'A C' ] })
      .content,
    [ { splits:
          [ { text: 'A' },
            { text: ' ' },
            { text: 'B', del: true },
            { text: ' ', del: true },
            { text: 'C' } ] } ])

  test.same(
    render(
      { content: [ 'A B C' ] },
      { content: [ 'A B C D' ] })
      .content,
    [ { splits:
          [ { text: 'A' },
            { text: ' ' },
            { text: 'B' },
            { text: ' ' },
            { text: 'C' },
            { text: ' ', ins: true },
            { text: 'D', ins: true } ] } ])

  test.same(
    render(
      { content: [ { use: 'Seller' } , ' pays.' ] },
      { content: [ { use: 'Buyer' } , ' pays.' ] })
      .content,
    [ { use: 'Seller', del: true },
      { use: 'Buyer', ins: true },
      { splits:
          [ { text: ' ' },
            { text: 'pays' },
            { text: '.' } ] } ])

  test.same(
    render(
      { content: [ { use: 'Seller' } , ' shall pay all tax.' ] },
      { content: [ 'The ', { use: 'Buyer' } , ' shall pay no tax.' ] })
      .content,
    [ { splits:
          [ { text: 'The' },
            { text: ' ' } ],
        ins: true },
      { use: 'Seller', del: true },
      { use: 'Buyer', ins: true },
      { splits:
          [ { text: ' ' },
            { text: 'shall' },
            { text: ' ' },
            { text: 'pay' },
            { text: ' ' },
            { text: 'all', del: true },
            { text: 'no', ins: true },
            { text: ' ' },
            { text: 'tax' },
            { text: '.' } ] } ])

  test.same(
    render(
      { content: [ 'The ', { use: 'Buyer' } , ' shall pay no tax.' ] },
      { content: [ { use: 'Seller' } , ' shall pay all tax.' ] })
      .content,
    [ { splits:
          [ { text: 'The' },
            { text: ' ' } ],
        del: true },
      { use: 'Buyer', del: true },
      { use: 'Seller', ins: true },
      { splits:
          [ { text: ' ' },
            { text: 'shall' },
            { text: ' ' },
            { text: 'pay' },
            { text: ' ' },
            { text: 'no', del: true },
            { text: 'all', ins: true },
            { text: ' ' },
            { text: 'tax' },
            { text: '.' } ] } ])

  test.same(
    render(
      { content: [ { form: { content: [ 'a b c' ] } } ] },
      { content: [ { form: { content: [ 'a d' ]   } } ] })
      .content,
    [ { form:
          { content:
              [ { splits:
                  [ { text: 'a' },
                    { text: ' ' },
                    { text: 'b', del: true },
                    { text: ' ', del: true },
                    { text: 'c', del: true },
                    { text: 'd', ins: true } ] } ] } } ])

  test.same(
    render(
      { content: [ 'a b c' ] },
      { content: [ 'a x c' ] })
      .content,
    [ { splits:
        [ { text: 'a' },
          { text: ' ' },
          { text: 'b', del: true },
          { text: 'x', ins: true },
          { text: ' ' },
          { text: 'c' } ] } ])

  test.same(
    render(
      { content: [ 'Hello ', { form: { content: [ 'a b c' ] } } ] },
      { content: [ { form: { content: [ 'a d' ]   } } ] })
      .content,
    [ { splits:
          [ { text: 'Hello' },
            { text: ' ' } ],
        del: true },
      { form:
          { content:
              [ { splits:
                    [ { text: 'a' },
                      { text: ' ' },
                      { text: 'b', del: true },
                      { text: ' ', del: true },
                      { text: 'c', del: true },
                      { text: 'd', ins: true } ] } ] } } ])

  test.end() })
<commit_msg>Test stacking of successive word replacements<commit_after>var tape = require('tape')
var render = require('../render')

tape('render', function(test) {

  test.same(
    render(
      { content: [ 'a b c' ] },
      { content: [ 'a d' ] })
      .content,
    [ { splits:
          [ { text: 'a' },
            { text: ' ' },
            { text: 'b', del: true },
            { text: ' ', del: true },
            { text: 'c', del: true },
            { text: 'd', ins: true } ] } ])

  test.same(
    render(
      { content: [ 'A B C' ] },
      { content: [ 'A C' ] })
      .content,
    [ { splits:
          [ { text: 'A' },
            { text: ' ' },
            { text: 'B', del: true },
            { text: ' ', del: true },
            { text: 'C' } ] } ])

  test.same(
    render(
      { content: [ 'A B C' ] },
      { content: [ 'A B C D' ] })
      .content,
    [ { splits:
          [ { text: 'A' },
            { text: ' ' },
            { text: 'B' },
            { text: ' ' },
            { text: 'C' },
            { text: ' ', ins: true },
            { text: 'D', ins: true } ] } ])

  test.same(
    render(
      { content: [ { use: 'Seller' } , ' pays.' ] },
      { content: [ { use: 'Buyer' } , ' pays.' ] })
      .content,
    [ { use: 'Seller', del: true },
      { use: 'Buyer', ins: true },
      { splits:
          [ { text: ' ' },
            { text: 'pays' },
            { text: '.' } ] } ])

  test.same(
    render(
      { content: [ { use: 'Seller' } , ' shall pay all tax.' ] },
      { content: [ 'The ', { use: 'Buyer' } , ' shall pay no tax.' ] })
      .content,
    [ { splits:
          [ { text: 'The' },
            { text: ' ' } ],
        ins: true },
      { use: 'Seller', del: true },
      { use: 'Buyer', ins: true },
      { splits:
          [ { text: ' ' },
            { text: 'shall' },
            { text: ' ' },
            { text: 'pay' },
            { text: ' ' },
            { text: 'all', del: true },
            { text: 'no', ins: true },
            { text: ' ' },
            { text: 'tax' },
            { text: '.' } ] } ])

  test.same(
    render(
      { content: [ 'The ', { use: 'Buyer' } , ' shall pay no tax.' ] },
      { content: [ { use: 'Seller' } , ' shall pay all tax.' ] })
      .content,
    [ { splits:
          [ { text: 'The' },
            { text: ' ' } ],
        del: true },
      { use: 'Buyer', del: true },
      { use: 'Seller', ins: true },
      { splits:
          [ { text: ' ' },
            { text: 'shall' },
            { text: ' ' },
            { text: 'pay' },
            { text: ' ' },
            { text: 'no', del: true },
            { text: 'all', ins: true },
            { text: ' ' },
            { text: 'tax' },
            { text: '.' } ] } ])

  test.same(
    render(
      { content: [ { form: { content: [ 'a b c' ] } } ] },
      { content: [ { form: { content: [ 'a d' ]   } } ] })
      .content,
    [ { form:
          { content:
              [ { splits:
                  [ { text: 'a' },
                    { text: ' ' },
                    { text: 'b', del: true },
                    { text: ' ', del: true },
                    { text: 'c', del: true },
                    { text: 'd', ins: true } ] } ] } } ])

  test.same(
    render(
      { content: [ 'a b c' ] },
      { content: [ 'a x c' ] })
      .content,
    [ { splits:
        [ { text: 'a' },
          { text: ' ' },
          { text: 'b', del: true },
          { text: 'x', ins: true },
          { text: ' ' },
          { text: 'c' } ] } ])

  test.same(
    render(
      { content: [ 'Hello ', { form: { content: [ 'a b c' ] } } ] },
      { content: [ { form: { content: [ 'a d' ]   } } ] })
      .content,
    [ { splits:
          [ { text: 'Hello' },
            { text: ' ' } ],
        del: true },
      { form:
          { content:
              [ { splits:
                    [ { text: 'a' },
                      { text: ' ' },
                      { text: 'b', del: true },
                      { text: ' ', del: true },
                      { text: 'c', del: true },
                      { text: 'd', ins: true } ] } ] } } ])

  test.same(
    render(
      { content: [ 'This is just a test.' ] },
      { content: [ 'This is an important provision.' ] })
      .content,
    [ { splits:
          [ { text: 'This' },
            { text: ' ' },
            { text: 'is' },
            { text: ' ' },
            { text: 'just', del: true },
            { text: ' ', del: true },
            { text: 'a', del: true },
            { text: ' ', del: true },
            { text: 'test', del: true },
            { text: 'an', ins: true },
            { text: ' ', ins: true },
            { text: 'important', ins: true },
            { text: ' ', ins: true },
            { text: 'provision', ins: true },
            { text: '.' } ] } ])

  test.same(
    render(
      { content: [ 'The ', { use: 'Buyer' }, ' pays all tax.' ] },
      { content: [ 'The ', { use: 'Seller' }, ' withholds all tax.' ] })
      .content,
    [ { splits:
          [ { text: 'The' },
            { text: ' ' } ] },
      { use: 'Buyer', del: true },
      { use: 'Seller', ins: true },
      { splits:
          [ { text: ' ' },
            { text: 'pays', del: true },
            { text: 'withholds', ins: true },
            { text: ' ' },
            { text: 'all' },
            { text: ' ' },
            { text: 'tax' },
            { text: '.' } ] } ])

  test.end() })
<|endoftext|>


<commit_before>import Vue from 'vue'
import SampleComponent from '../src/components/SampleComponent.vue'

function getRenderedText(Component, propsData) {
    const Ctor = Vue.extend(Component);
    const vm = new Ctor({propsData}).$mount();
    return vm.$el.textContent
}

describe('SampleComponent', () => {

    it('renders correctly with different props', () => {

        expect(getRenderedText(SampleComponent, {
            msg: 'Hello'
        })).toBe('Hello');

        expect(getRenderedText(SampleComponent, {
            msg: 'Bye'
        })).toBe('Bye');

    })
});

it('updates the rendered message when vm.message updates', done => {

    const vm = new Vue(SampleComponent).$mount();
    vm.message = 'foo';

    // wait a "tick" after state change before asserting DOM updates
    Vue.nextTick(() => {
        expect(vm.$el.textContent).toBe('foo')
        done()
    })

});<commit_msg>Remove unnecessary test<commit_after><|endoftext|>


<commit_before>const schema = require('../lib/schema')

const validConfigs = [
  [{daysUntilClose: false}],
  [{daysUntilClose: 1}],
  [{exemptLabels: ['foo']}],
  [{exemptLabels: 'foo'}, {exemptLabels: ['foo']}],
  [{exemptLabels: null}],
  [{exemptLabels: []}],
  [{exemptProjects: true}],
  [{exemptProjects: false}],
  [{exemptMilestones: true}],
  [{exemptMilestones: false}],
  [{staleLabel: 'stale'}],
  [{markComment: 'stale yo'}],
  [{markComment: false}],
  [{unmarkComment: 'not stale'}],
  [{unmarkComment: false}],
  [{closeComment: 'closing yo'}],
  [{closeComment: false}],
  [{limitPerRun: 1}],
  [{limitPerRun: 30}],
  [{only: null}],
  [{only: 'issues'}],
  [{only: 'pulls'}],
  [{pulls: {daysUntilStale: 2}}],
  [{issues: {staleLabel: 'stale-issue'}}],
  [{_extends: '.github'}],
  [{_extends: 'foobar'}]
]

const invalidConfigs = [
  [{daysUntilClose: true}, 'must be a number or false'],
  [{exemptProjects: 'nope'}, 'must be a boolean'],
  [{exemptMilestones: 'nope'}, 'must be a boolean'],
  [{staleLabel: ''}, 'not allowed to be empty'],
  [{staleLabel: false}, 'must be a string'],
  [{staleLabel: ['a', 'b']}, 'must be a string'],
  [{markComment: true}, 'must be a string or false'],
  [{unmarkComment: true}, 'must be a string or false'],
  [{closeComment: true}, 'must be a string or false'],
  [{limitPerRun: 31}, 'must be an integer between 1 and 30'],
  [{limitPerRun: 0}, 'must be an integer between 1 and 30'],
  [{limitPerRun: 0.5}, 'must be an integer between 1 and 30'],
  [{only: 'donuts'}, 'must be one of [issues, pulls, null]'],
  [{pulls: {daysUntilStale: 'no'}}, 'must be a number'],
  [{pulls: {lol: 'nope'}}, '"lol" is not allowed'],
  [{issues: {staleLabel: ''}}, 'not allowed to be empty'],
  [{_extends: true}, 'must be a string'],
  [{_extends: false}, 'must be a string']
]

describe('schema', () => {
  test('defaults', async () => {
    expect(schema.validate({}).value).toEqual({
      daysUntilStale: 60,
      daysUntilClose: 7,
      exemptLabels: ['pinned', 'security'],
      exemptProjects: false,
      exemptMilestones: false,
      staleLabel: 'wontfix',
      perform: true,
      markComment: 'This issue has been automatically marked as stale because ' +
        'it has not had recent activity. It will be closed if no further ' +
        'activity occurs. Thank you for your contributions.',
      unmarkComment: false,
      closeComment: false,
      limitPerRun: 30
    })
  })

  test('does not set defaults for pulls and issues', () => {
    expect(schema.validate({pulls: {daysUntilStale: 90}}).value.pulls).toEqual({
      daysUntilStale: 90
    })

    expect(schema.validate({issues: {daysUntilStale: 90}}).value.issues).toEqual({
      daysUntilStale: 90
    })
  })

  validConfigs.forEach(([example, expected = example]) => {
    test(`${JSON.stringify(example)} is valid`, () => {
      const result = schema.validate(example)
      expect(result.error).toBe(null)
      expect(result.value).toMatchObject(expected)
    })
  })

  invalidConfigs.forEach(([example, message]) => {
    test(`${JSON.stringify(example)} is invalid`, () => {
      const {error} = schema.validate(example)
      expect(error && error.toString()).toMatch(message)
    })
  })
})
<commit_msg>Update tests to match new default comment<commit_after>const schema = require('../lib/schema')

const validConfigs = [
  [{daysUntilClose: false}],
  [{daysUntilClose: 1}],
  [{exemptLabels: ['foo']}],
  [{exemptLabels: 'foo'}, {exemptLabels: ['foo']}],
  [{exemptLabels: null}],
  [{exemptLabels: []}],
  [{exemptProjects: true}],
  [{exemptProjects: false}],
  [{exemptMilestones: true}],
  [{exemptMilestones: false}],
  [{staleLabel: 'stale'}],
  [{markComment: 'stale yo'}],
  [{markComment: false}],
  [{unmarkComment: 'not stale'}],
  [{unmarkComment: false}],
  [{closeComment: 'closing yo'}],
  [{closeComment: false}],
  [{limitPerRun: 1}],
  [{limitPerRun: 30}],
  [{only: null}],
  [{only: 'issues'}],
  [{only: 'pulls'}],
  [{pulls: {daysUntilStale: 2}}],
  [{issues: {staleLabel: 'stale-issue'}}],
  [{_extends: '.github'}],
  [{_extends: 'foobar'}]
]

const invalidConfigs = [
  [{daysUntilClose: true}, 'must be a number or false'],
  [{exemptProjects: 'nope'}, 'must be a boolean'],
  [{exemptMilestones: 'nope'}, 'must be a boolean'],
  [{staleLabel: ''}, 'not allowed to be empty'],
  [{staleLabel: false}, 'must be a string'],
  [{staleLabel: ['a', 'b']}, 'must be a string'],
  [{markComment: true}, 'must be a string or false'],
  [{unmarkComment: true}, 'must be a string or false'],
  [{closeComment: true}, 'must be a string or false'],
  [{limitPerRun: 31}, 'must be an integer between 1 and 30'],
  [{limitPerRun: 0}, 'must be an integer between 1 and 30'],
  [{limitPerRun: 0.5}, 'must be an integer between 1 and 30'],
  [{only: 'donuts'}, 'must be one of [issues, pulls, null]'],
  [{pulls: {daysUntilStale: 'no'}}, 'must be a number'],
  [{pulls: {lol: 'nope'}}, '"lol" is not allowed'],
  [{issues: {staleLabel: ''}}, 'not allowed to be empty'],
  [{_extends: true}, 'must be a string'],
  [{_extends: false}, 'must be a string']
]

describe('schema', () => {
  test('defaults', async () => {
    expect(schema.validate({}).value).toEqual({
      daysUntilStale: 60,
      daysUntilClose: 7,
      exemptLabels: ['pinned', 'security'],
      exemptProjects: false,
      exemptMilestones: false,
      staleLabel: 'wontfix',
      perform: true,
      markComment: 'Is this still relevant? If so, what is blocking it? ' +
        'Is there anything you can do to help move it forward?',
      unmarkComment: false,
      closeComment: false,
      limitPerRun: 30
    })
  })

  test('does not set defaults for pulls and issues', () => {
    expect(schema.validate({pulls: {daysUntilStale: 90}}).value.pulls).toEqual({
      daysUntilStale: 90
    })

    expect(schema.validate({issues: {daysUntilStale: 90}}).value.issues).toEqual({
      daysUntilStale: 90
    })
  })

  validConfigs.forEach(([example, expected = example]) => {
    test(`${JSON.stringify(example)} is valid`, () => {
      const result = schema.validate(example)
      expect(result.error).toBe(null)
      expect(result.value).toMatchObject(expected)
    })
  })

  invalidConfigs.forEach(([example, message]) => {
    test(`${JSON.stringify(example)} is invalid`, () => {
      const {error} = schema.validate(example)
      expect(error && error.toString()).toMatch(message)
    })
  })
})
<|endoftext|>


<commit_before>var assert = require('assert');
var io = require('socket.io-client');

var server = require('../server');

var port = process.env.PORT || 8000;

var socketURL = `http://0.0.0.0:${port}`;

var options = {
  transports: ['websocket'],
  'force new connection': true
};

describe('Chat Server', function() {
  before(function() {
    server.listen(port);
  });

  after(function() {
    server.close();
  });

  it('Broadcasts count of connected users', function(done) {
    var client1 = io.connect(socketURL, options);

    client1.on('connect', () => {
      var client2 = io.connect(socketURL, options);

      client2.on('connect', () => {
        client2.on('connections', function(connections) {
          console.log('client2 connections', connections);
          assert.equal(connections, 2);
          client1.disconnect();
          client2.disconnect();
          done();
        });
      });
    });
  });

  it('Broadcasts lists', function(done) {
    var client3 = io.connect(socketURL, options);
    client3.on('connect', () => {
      client3.on('lists', data => {
        console.log('client3 received lists', data);
        assert.deepEqual(data, []);
        client3.disconnect();
        done();
      });
    });
  });

  it('Creates and Broadcasts lists', function(done) {
    var testListName = 'test list name';
    var testList = { name: testListName };
    var expectedResponse = [{ name: testListName, items: [] }];
    var client4 = io.connect(socketURL, options);
    client4.on('connect', () => {
      client4.emit('createList', testList);
      client4.on('lists', data => {
        console.log('client4 received lists', data);
        assert.deepEqual(data, []);
        client4.disconnect();

        var client5 = io.connect(socketURL, options);
        client5.on('connect', () => {
          client5.on('lists', data => {
            console.log('client5 received lists', data);
            assert.deepEqual(data, expectedResponse);
            client5.disconnect();
            done();
          });
        });
      });
    });
  });
});
<commit_msg>Cleanup server tests<commit_after>var assert = require('assert');
var io = require('socket.io-client');

var server = require('../server');

var port = process.env.PORT || 8000;

var socketURL = `http://0.0.0.0:${port}`;

var options = {
  transports: ['websocket'],
  'force new connection': true
};

describe('Chat Server', function() {
  before(function() {
    server.listen(port);
  });

  after(function() {
    server.close();
  });

  it('Broadcasts count of connected users', function(done) {
    var client1 = io.connect(socketURL, options);

    client1.on('connect', () => {
      var client2 = io.connect(socketURL, options);

      client2.on('connect', () => {
        client2.on('connections', function(connections) {
          assert.equal(connections, 2);
          client1.disconnect();
          client2.disconnect();
          done();
        });
      });
    });
  });

  it('Creates and Broadcasts lists', function(done) {
    var testListName = 'test list name';
    var testList = { name: testListName };
    var expectedResponse = [{ name: testListName, items: [] }];
    var client4 = io.connect(socketURL, options);
    client4.on('connect', () => {
      client4.emit('createList', testList);
      client4.on('lists', data => {
        assert.deepEqual(data, []);
        client4.disconnect();

        var client5 = io.connect(socketURL, options);
        client5.on('connect', () => {
          client5.on('lists', data => {
            assert.deepEqual(data, expectedResponse);
            client5.disconnect();
            done();
          });
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor'

import { UserData } from '/imports/api/indexDB.js';
import { APICalls } from '/server/serverdb/APICalls.js';
import { creditUserWith } from '../../utilities.js';

import {REWARDCOEFFICIENT} from '../REWARDCOEFFICIENT' //needed on client

Meteor.methods({
  rejectBounty: function(bountyId, reason) {
    if(UserData.findOne({_id: this.userId}).moderator) {
      var original = Bounties.findOne({_id: bountyId});
      Bounties.upsert(bountyId, {
        $set: {
          approved: false,
          pendingApproval: false,
          rejectedReason: reason,
          rejected: true,
          rejectedBy: Meteor.user().username
        }
      });
      Meteor.call("sendMessage", original.completedBy, ("The " + original.bountyType + " bounty you submitted for " + original.currencyName + "has been denied by a moderator. Please see your Pending list to see more details."))
    }
  },
  addNewBounty: (type, reward, time) => {
    if (Meteor.userId()) {
      let b = Bounties.find({
        userId: Meteor.userId(),
        type: type,
        completed: false
      }, {
        sort: {
          expiresAt: -1
        }
      }).fetch()[0]

      if (!(b && b.expiresAt > Date.now())) {
        Bounties.insert({
          _id: Random.id(16),
          userId: Meteor.userId(),
          type: type,
          expiresAt: Date.now() + time,
          currentlyAvailable: false,
          currentReward: reward,
          completed: false,
          pendingApproval: true
        })
      } else {
        throw new Meteor.Error('You are already working on this one.')
      }
    }
  },
  completeNewBounty: (type, id) => {
    Bounties.update({
      type: type,
      userId: Meteor.userId(),
      completed: false
    }, {
      $set: {
        completed: true,
        id: id
      }
    })
  },
  deleteNewBounty: (id, token) => {
    if (token === 's3rver-only')
      Bounties.remove({
        _id: id
      })
  },
  deleteNewBountyClient: (type) => {
    Bounties.remove({
      userId: Meteor.userId(),
      type: type,
      completed: false
    })
  },
  approveAPIbounty: function(bountyId) {
    if(UserData.findOne({_id: this.userId}).moderator) {
      var original = Bounties.findOne({_id: bountyId});
      if (original.completedBy == this.userId) {
        throw new Meteor.Error("Approving your own bounty is no fun!")
      }
      Bounties.upsert(bountyId, {
        $set: {
          approved: true,
          pendingApproval: false,
          approvedBy: this.userId,
          approvedTime: new Date().getTime()
        }
      });

      if(original.bountyType == "HashrateAPI") {
        APICalls.insert({
          currencyid: original.currencyId,
          currencyName: original.currencyName,
          callType: "Hashrate",
          createdAt: Date.now(),
          APICall: original.APICall,
          Hashrate: original.Hashrate,
          Height: original.Height,
          BlockReward: original.BlockReward,
          Emissions: original.Emissions,
          Timestamp: original.Timestamp,
          AtomicUnitFactor: original.AtomicUnitFactor,
          hashrateUnits: original.hashrateUnits,
          createdBy: original.completedBy,
          approvedBy: original.approvedBy
        }, function(error, result){
        })
      }
      creditUserWith(original.bountyReward, original.completedBy, ("completing the " + original.currencyName + " " + original.bountyType + "."));
      Meteor.call("sendMessage", original.completedBy, ("I have approved your bounty for " + original.currencyName), Meteor.user().username);
    }
  },
  completeAPIbounty: function(apiData){
    if(Meteor.user().username == Bounties.findOne({_id: apiData.bountyId}).currentUsername) {
      if(Date.now() < Bounties.findOne({_id: apiData.bountyId}).expiresAt) {
        Bounties.upsert(apiData.bountyId, {
          $set: {
            APICall: apiData.apiCall,
            Hashrate: apiData.hashrate,
            Height: (apiData.height ? apiData.height : null),
            Timestamp: (apiData.timestamp ? apiData.timestamp : null),
            BlockReward: (apiData.reward ? apiData.reward : null),
            Emissions: (apiData.emissions ? apiData.emissions : null),
            AtomicUnitFactor: (apiData.decimal ? apiData.decimal : null),
            pendingApproval: false,
            completedBy: Meteor.userId(),
            completedTime: Date.now(),
            bountyReward: ((Date.now() - Bounties.findOne({_id: apiData.bountyId}).creationTime) / REWARDCOEFFICIENT).toFixed(6)
          }
        }, false, function(error, result) {
          if(error) {
            throw new Meteor.Error('Error submitting data', error)
          }
        })
        fetchHashrate(apiData.bountyId);
      } else { throw new Meteor.Error('Error submitting data')}
    } else { throw new Meteor.Error('Error submitting data')}
  },
  cancelBounty: function(id) {
    if(Bounties.findOne({_id: id}).currentUsername == Meteor.user().username) {
      Bounties.upsert(id, {
        $set: {
          currentUsername: null,
          expiresAt: null,
          currentlyAvailable: true
        }
      });
      UserData.upsert(Meteor.userId(), {
        $set: {
          workingOnBounty: false
        }
      });
    }
  },
  startBounty: function(id){
    if(Bounties.findOne({_id: id}).currentlyAvailable == true) {
    if(Meteor.user() && !UserData.findOne({_id: this.userId}).workingOnBounty) {
    Bounties.upsert(id, {
      $set: {
        currentUsername: Meteor.user().username,
        expiresAt: Date.now() + 3600000,
        currentlyAvailable: false
      }
    }) //end Bounties upsert
    UserData.upsert(Meteor.userId(), {
      $set: {
        workingOnBounty: true
      }
    })// End UserData upsert
}} else {throw new Meteor.Error('startBounty method error', 'Cannot start bounty')}
} //end startBounty
}); //end methods<commit_msg>Problem: bounties server methods without bounties colleection<commit_after>import { Meteor } from 'meteor/meteor'

import { UserData, Bounties } from '/imports/api/indexDB.js';
import { APICalls } from '/server/serverdb/APICalls.js';
import { creditUserWith } from '../../utilities.js';

import {REWARDCOEFFICIENT} from '../REWARDCOEFFICIENT' //needed on client

Meteor.methods({
  rejectBounty: function(bountyId, reason) {
    if(UserData.findOne({_id: this.userId}).moderator) {
      var original = Bounties.findOne({_id: bountyId});
      Bounties.upsert(bountyId, {
        $set: {
          approved: false,
          pendingApproval: false,
          rejectedReason: reason,
          rejected: true,
          rejectedBy: Meteor.user().username
        }
      });
      Meteor.call("sendMessage", original.completedBy, ("The " + original.bountyType + " bounty you submitted for " + original.currencyName + "has been denied by a moderator. Please see your Pending list to see more details."))
    }
  },
  addNewBounty: (type, reward, time) => {
    if (Meteor.userId()) {
      let b = Bounties.find({
        userId: Meteor.userId(),
        type: type,
        completed: false
      }, {
        sort: {
          expiresAt: -1
        }
      }).fetch()[0]

      if (!(b && b.expiresAt > Date.now())) {
        Bounties.insert({
          _id: Random.id(16),
          userId: Meteor.userId(),
          type: type,
          expiresAt: Date.now() + time,
          currentlyAvailable: false,
          currentReward: reward,
          completed: false,
          pendingApproval: true
        })
      } else {
        throw new Meteor.Error('You are already working on this one.')
      }
    }
  },
  completeNewBounty: (type, id) => {
    Bounties.update({
      type: type,
      userId: Meteor.userId(),
      completed: false
    }, {
      $set: {
        completed: true,
        id: id
      }
    })
  },
  deleteNewBounty: (id, token) => {
    if (token === 's3rver-only')
      Bounties.remove({
        _id: id
      })
  },
  deleteNewBountyClient: (type) => {
    Bounties.remove({
      userId: Meteor.userId(),
      type: type,
      completed: false
    })
  },
  approveAPIbounty: function(bountyId) {
    if(UserData.findOne({_id: this.userId}).moderator) {
      var original = Bounties.findOne({_id: bountyId});
      if (original.completedBy == this.userId) {
        throw new Meteor.Error("Approving your own bounty is no fun!")
      }
      Bounties.upsert(bountyId, {
        $set: {
          approved: true,
          pendingApproval: false,
          approvedBy: this.userId,
          approvedTime: new Date().getTime()
        }
      });

      if(original.bountyType == "HashrateAPI") {
        APICalls.insert({
          currencyid: original.currencyId,
          currencyName: original.currencyName,
          callType: "Hashrate",
          createdAt: Date.now(),
          APICall: original.APICall,
          Hashrate: original.Hashrate,
          Height: original.Height,
          BlockReward: original.BlockReward,
          Emissions: original.Emissions,
          Timestamp: original.Timestamp,
          AtomicUnitFactor: original.AtomicUnitFactor,
          hashrateUnits: original.hashrateUnits,
          createdBy: original.completedBy,
          approvedBy: original.approvedBy
        }, function(error, result){
        })
      }
      creditUserWith(original.bountyReward, original.completedBy, ("completing the " + original.currencyName + " " + original.bountyType + "."));
      Meteor.call("sendMessage", original.completedBy, ("I have approved your bounty for " + original.currencyName), Meteor.user().username);
    }
  },
  completeAPIbounty: function(apiData){
    if(Meteor.user().username == Bounties.findOne({_id: apiData.bountyId}).currentUsername) {
      if(Date.now() < Bounties.findOne({_id: apiData.bountyId}).expiresAt) {
        Bounties.upsert(apiData.bountyId, {
          $set: {
            APICall: apiData.apiCall,
            Hashrate: apiData.hashrate,
            Height: (apiData.height ? apiData.height : null),
            Timestamp: (apiData.timestamp ? apiData.timestamp : null),
            BlockReward: (apiData.reward ? apiData.reward : null),
            Emissions: (apiData.emissions ? apiData.emissions : null),
            AtomicUnitFactor: (apiData.decimal ? apiData.decimal : null),
            pendingApproval: false,
            completedBy: Meteor.userId(),
            completedTime: Date.now(),
            bountyReward: ((Date.now() - Bounties.findOne({_id: apiData.bountyId}).creationTime) / REWARDCOEFFICIENT).toFixed(6)
          }
        }, false, function(error, result) {
          if(error) {
            throw new Meteor.Error('Error submitting data', error)
          }
        })
        fetchHashrate(apiData.bountyId);
      } else { throw new Meteor.Error('Error submitting data')}
    } else { throw new Meteor.Error('Error submitting data')}
  },
  cancelBounty: function(id) {
    if(Bounties.findOne({_id: id}).currentUsername == Meteor.user().username) {
      Bounties.upsert(id, {
        $set: {
          currentUsername: null,
          expiresAt: null,
          currentlyAvailable: true
        }
      });
      UserData.upsert(Meteor.userId(), {
        $set: {
          workingOnBounty: false
        }
      });
    }
  },
  startBounty: function(id){
    if(Bounties.findOne({_id: id}).currentlyAvailable == true) {
    if(Meteor.user() && !UserData.findOne({_id: this.userId}).workingOnBounty) {
    Bounties.upsert(id, {
      $set: {
        currentUsername: Meteor.user().username,
        expiresAt: Date.now() + 3600000,
        currentlyAvailable: false
      }
    }) //end Bounties upsert
    UserData.upsert(Meteor.userId(), {
      $set: {
        workingOnBounty: true
      }
    })// End UserData upsert
}} else {throw new Meteor.Error('startBounty method error', 'Cannot start bounty')}
} //end startBounty
}); //end methods<|endoftext|>