import ExhaustivePaginatedFetcher from '../ExhaustivePaginatedFetcher'

class FakeFetcher {
  constructor ({perPage = '5', total = '20', onePage = [0, 1, 2, 3, 4], getStub = sinon.stub()} = {}) {
    this.onePage = onePage
    this.total = total
    this.perPage = perPage
    this.getStub = getStub.resolves(this.onePage)
  }

  get (url, params) {
    return this.getStub.apply(null, arguments)
  }

  fetch () {
    return Promise.resolve({
      headers: {
        get: type => type === 'total' ? this.total : this.perPage
      },
      json: () => Promise.resolve(this.onePage)
    })
  }

  callHeaders () {}

  appendQueryParams (url) {
    return url
  }
}

describe('ExhaustivePaginatedFetcher', () => {
  it('combines pages', () => {
    const fetcher = new ExhaustivePaginatedFetcher()
    const pages = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    const result = fetcher.combinePages(pages)
    const shouldBe = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    expect(result).to.be.an('array').that.is.not.empty()
    expect(result).to.eql(shouldBe)
  })

  it('fetch can use mock superclass', async () => {
    const fetcher = new ExhaustivePaginatedFetcher({SuperClass: FakeFetcher})
    const res = await fetcher.fetch()
    expect(res.headers.get('total')).to.equal('20')
  })

  it('uses returned page size on future requests', async () => {
    const getStub = sinon.stub()
    const fetcher = new ExhaustivePaginatedFetcher({
      SuperClass: FakeFetcher,
      total: '10',
      getStub
    })
    await fetcher.get('/foo', { per_page: 1000 })
    // calls fetch for first stub, then get for subsequent, so only expect one get call
    expect(getStub).to.have.been.calledOnce()
    expect(getStub.args[0][1]).to.include({ per_page: 5 })
  })

  it('exhausts all pages from a get request', async () => {
    const fetcher = new ExhaustivePaginatedFetcher({SuperClass: FakeFetcher})
    const res = await fetcher.get()
    expect(res).to.eql([0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4])
  })

  it('handles responses of 1 page', async () => {
    const fetcher = new ExhaustivePaginatedFetcher({
      SuperClass: FakeFetcher,
      perPage: '10',
      total: '5',
      onePage: [0, 1, 2, 3, 4]
    })

    const res = await fetcher.get()
    expect(res).to.eql([0, 1, 2, 3, 4])
  })

  it('handles empty response', async () => {
    const fetcher = new ExhaustivePaginatedFetcher({
      SuperClass: FakeFetcher,
      perPage: '10',
      total: '0',
      onePage: []
    })

    const res = await fetcher.get()
    expect(res).to.eql([])
  })
})
