noflo = require 'noflo'
fs = require 'fs'
path = require 'path'
chai = require 'chai'
baseDir = path.resolve __dirname, '../'
schema = require './utils/schema'

describe 'FetchAndFlatten component', ->
  c = null
  ins = null
  out = null
  user = 'f16b6380-029f-11e4-9191-0800200c9a66'
  error = null
  loader = null
  before ->
    loader = new noflo.ComponentLoader baseDir
    do schema.before
  beforeEach (done) ->
    @timeout 10000
    loader.load 'harpy/FetchAndFlatten', (err, instance) ->
      c = instance
      c.once 'ready', ->
        ins = noflo.internalSocket.createSocket()
        out = noflo.internalSocket.createSocket()
        error = noflo.internalSocket.createSocket()
        c.inPorts.in.attach ins
        c.outPorts.out.attach out
        c.outPorts.error.attach error
        c.network.start (err) ->
          return done err if err
          setTimeout done, 1
  after ->
    do schema.after

  describe 'when instantiated', ->
    it 'should have an input port', ->
      chai.expect(c.inPorts.in).to.be.an 'object'
    it 'should have an output port', ->
      chai.expect(c.outPorts.out).to.be.an 'object'

  describe 'fetching a TechCrunch article', ->
    it 'should be able flatten it without info', (done) ->
      @timeout 10000

      groups = []
      url = 'http://techcrunch.com/2013/08/01/noflo-launches-kickstarter-campaign-to-provide-a-way-for-everyone-to-understand-and-visualize-code/'
      error.on 'data', (data) ->
        done data
      out.on 'begingroup', (group) ->
        groups.push group
      out.on 'data', (data) ->
        chai.expect(groups[0]).to.equal 'foo'
        chai.expect(data).to.be.an 'object'
        chai.expect(data.id).to.be.a 'undefined'
        chai.expect(data.options).to.eql
          user: user
          compress: true
        chai.expect(data.metadata).to.be.an 'object'
        chai.expect(data.metadata.isBasedOnUrl).to.equal url
        chai.expect(data.content).to.be.an 'array'
        chai.expect(data.content.length).to.equal 1
        schema.validate data, 'item', done
      out.on 'endgroup', ->
        groups.pop()

      ins.beginGroup 'foo'
      ins.send
        options:
          user: user
          compress: true
        url: url
      ins.endGroup()
      ins.disconnect()

    it 'should be able flatten it with site info', (done) ->
      @timeout 10000

      groups = []
      url = 'http://techcrunch.com/2013/03/26/embedly-now-goes-beyond-embedding-with-new-products-extract-display-for-making-sense-of-links-resizing-images/'
      error.on 'data', (data) ->
        done data
      out.on 'begingroup', (group) ->
        groups.push group
      out.on 'data', (data) ->
        chai.expect(groups[0]).to.equal 'foo'
        chai.expect(data).to.be.an 'object'
        chai.expect(data.id).to.be.a 'undefined'
        chai.expect(data.options).to.eql
          user: user
          site: 'the-domains/techcrunch.com'
          compress: true
        chai.expect(data.metadata).to.be.an 'object'
        chai.expect(data.metadata.isBasedOnUrl).to.equal url
        chai.expect(data.content).to.be.an 'array'
        chai.expect(data.content.length).to.equal 1
        schema.validate data, 'item', done
      out.on 'endgroup', ->
        groups.pop()

      ins.beginGroup 'foo'
      ins.send
        options:
          site: 'the-domains/techcrunch.com'
          user: user
          compress: true
        url: url
      ins.endGroup()
      ins.disconnect()

  describe 'fetching an Instagram photo', ->
    it 'should be able flatten it with info', (done) ->
      @timeout 10000

      groups = []
      url = 'https://instagram.com/p/zWd25EIZMW/'
      error.on 'data', (data) ->
        chai.expect(true).to.equal false
        done()
      out.on 'begingroup', (group) ->
        groups.push group
      out.on 'data', (data) ->
        chai.expect(groups[0]).to.equal 'foo'
        chai.expect(data).to.be.an 'object'
        chai.expect(data.id).to.be.a 'undefined'
        chai.expect(data.options).to.eql
          user: user
          compress: true
        chai.expect(data.metadata).to.be.an 'object'
        chai.expect(data.metadata.isBasedOnUrl).to.equal url
        chai.expect(data.content).to.be.an 'array'
        chai.expect(data.content.length).to.equal 1
        chai.expect(data.content[0].src).to.contain 'https://scontent.cdninstagram.com/'
        chai.expect(data.content[0].type).to.equal 'image'
        schema.validate data, 'item', done
      out.on 'endgroup', ->
        groups.pop()

      ins.beginGroup 'foo'
      ins.send
        options:
          user: user
          compress: true
        url: url
      ins.endGroup()
      ins.disconnect()

  describe 'fetching an Instagram video', ->
    it 'should be able flatten it with info', (done) ->
      @timeout 10000

      groups = []
      url = 'https://www.instagram.com/p/BAqirNbwEc0/'
      error.on 'data', (data) ->
        chai.expect(true).to.equal false
        done()
      out.on 'begingroup', (group) ->
        groups.push group
      out.on 'data', (data) ->
        chai.expect(groups[0]).to.equal 'vid'
        chai.expect(data).to.be.an 'object'
        chai.expect(data.id).to.be.a 'undefined'
        chai.expect(data.options).to.eql
          user: user
          compress: true
        chai.expect(data.metadata).to.be.an 'object'
        chai.expect(data.metadata.isBasedOnUrl).to.equal url
        chai.expect(data.content).to.be.an 'array'
        chai.expect(data.content.length).to.equal 1
        chai.expect(data.content[0].type).to.equal 'video'
        schema.validate data, 'item', done
      out.on 'endgroup', ->
        groups.pop()

      ins.beginGroup 'vid'
      ins.send
        options:
          user: user
          compress: true
        url: url
      ins.endGroup()
      ins.disconnect()

  describe 'fetching a Google image search result with data URL', ->
    it 'should be able flatten it without info', (done) ->
      @timeout 10000

      groups = []
      url = 'https://www.google.com/search?newwindow=1&safe=off&site=&tbm=isch&source=hp&biw=1916&bih=1105&q=lolcatz&oq=lolcatz&gs_l=img.3..0i10l10.81.1179.0.1349.7.7.0.0/NX.0.0.194.676.2j4.6.0.enullwli...0...1.1.60.img..1.6.673.AqY-7NBkZNo'
      html = fs.readFileSync path.resolve(__dirname, './fixtures/fetch/dataurl.html'), 'utf-8'
      error.on 'data', (data) ->
        done data
      out.on 'begingroup', (group) ->
        groups.push group
      out.on 'data', (data) ->
        chai.expect(groups[0]).to.equal 'foo'
        chai.expect(data).to.be.an 'object'
        chai.expect(data.id).to.be.a 'undefined'
        chai.expect(data.options).to.eql
          user: user
          compress: true
        chai.expect(data.metadata.isBasedOnUrl).to.equal url
        chai.expect(data.content).to.be.an 'array'
        chai.expect(data.content.length).to.equal 1
        chai.expect(data.content[0].src.indexOf('amazonaws')).to.not.equal -1
        chai.expect(data.content[0].html.indexOf('amazonaws')).to.not.equal -1
        schema.validate data, 'item', done
      out.on 'endgroup', ->
        groups.pop()

      ins.beginGroup 'foo'
      ins.send
        options:
          user: user
          compress: true
        url: url
        content: html
        type: 'text/html'
      ins.endGroup()
      ins.disconnect()

  describe 'fetching a gist', ->
    it 'should be able flatten it with info', (done) ->
      @timeout 10000

      groups = []
      url = 'https://gist.github.com/bergie/0da832c1ec85d6bde68c'
      error.on 'data', (data) ->
        done data
      out.on 'begingroup', (group) ->
        groups.push group
      out.on 'data', (data) ->
        chai.expect(groups[0]).to.equal 'foo'
        chai.expect(data).to.be.an 'object'
        chai.expect(data.id).to.be.a 'undefined'
        chai.expect(data.options).to.eql
          user: user
          compress: false
        chai.expect(data.metadata).to.be.an 'object'
        chai.expect(data.metadata.isBasedOnUrl).to.equal 'https://gist.github.com/0da832c1ec85d6bde68c'
        chai.expect(data.content).to.be.an 'array'
        types = data.content.map (b) -> b.type
        chai.expect(types).to.eql [
          'code'
          'code'
        ]
        schema.validate data, 'item', done
      out.on 'endgroup', ->
        groups.pop()

      ins.beginGroup 'foo'
      ins.send
        options:
          user: user
          compress: false
        url: url
      ins.endGroup()
      ins.disconnect()

  describe 'fetching a tweet', ->
    it 'should be able flatten it with info', (done) ->
      @timeout 10000

      groups = []
      url = 'https://twitter.com/elonmusk/status/743603466631733248'
      error.on 'data', (data) ->
        done data
      out.on 'begingroup', (group) ->
        groups.push group
      out.on 'data', (data) ->
        chai.expect(groups[0]).to.equal 'elon'
        chai.expect(data).to.be.an 'object'
        chai.expect(data.id).to.be.a 'undefined'
        chai.expect(data.options).to.eql
          user: user
          compress: false
        chai.expect(data.metadata).to.be.an 'object'
        chai.expect(data.metadata.isBasedOnUrl).to.equal 'https://twitter.com/elonmusk/status/743603466631733248'
        chai.expect(data.metadata.author).to.be.an 'array'
        chai.expect(data.metadata.author[0].name).to.equal 'elonmusk'
        chai.expect(data.metadata.author[0].url).to.equal 'http://twitter.com/elonmusk'
        chai.expect(data.metadata.author[0].avatar).to.be.an 'object'
        chai.expect(data.metadata.author[0].avatar.src).to.be.a 'string'
        chai.expect(data.content).to.be.an 'array'
        types = data.content.map (b) -> b.type
        chai.expect(types).to.eql [
          'quote'
        ]
        chai.expect(data.content[0].metadata).to.eql data.metadata
        schema.validate data, 'item', done
      out.on 'endgroup', ->
        groups.pop()

      ins.beginGroup 'elon'
      ins.send
        options:
          user: user
          compress: false
        url: url
      ins.endGroup()
      ins.disconnect()

  describe 'fetching a Medium post', ->
    it 'should be able flatten it with info', (done) ->
      @timeout 10000

      groups = []
      url = 'https://medium.com/backchannel/license-to-not-drive-6dbea84b9c45'
      error.on 'data', (data) ->
        done data
      out.on 'begingroup', (group) ->
        groups.push group
      out.on 'data', (data) ->
        chai.expect(groups[0]).to.equal 'foo'
        chai.expect(data).to.be.an 'object'
        chai.expect(data.id).to.be.a 'undefined'
        chai.expect(data.metadata).to.be.an 'object'
        chai.expect(data.metadata.isBasedOnUrl).to.equal 'https://medium.com/backchannel/license-to-not-drive-6dbea84b9c45'
        chai.expect(data.metadata.publisher).to.be.an 'object'
        chai.expect(data.metadata.publisher.name).to.equal 'Backchannel'
        chai.expect(data.metadata.via).to.be.an 'object'
        chai.expect(data.metadata.via.name).to.equal 'bergie.today'
        chai.expect(data.metadata.via.url).to.equal 'http://bergie.today/'
        chai.expect(data.content).to.be.an 'array'
        types = data.content.map (b) -> b.type
        chai.expect(types).to.eql [
          'article'
        ]
        chai.expect(data.options).to.eql
          user: user
          compress: true
        schema.validate data, 'item', done
      out.on 'endgroup', ->
        groups.pop()

      ins.beginGroup 'foo'
      ins.send
        options:
          user: user
          compress: true
          via:
            url: 'http://bergie.today/'
        url: url
      ins.endGroup()
      ins.disconnect()
