text: import { initializeWeb3, getNetworkId } from '../src/web3/web3Saga'
  import { call, put } from 'redux-saga/effects'
  import { runSaga } from 'redux-saga'
  import * as Action from '../src/web3/constants'
  
  const hasWeb3Shape = obj => {
    expect(obj).toHaveProperty('currentProvider')
    expect(obj).toHaveProperty('BatchRequest')
    expect(obj).toHaveProperty('version')
    expect(obj).toHaveProperty('utils')
    expect(obj).toHaveProperty('eth')
  }
  
  describe('Resolving Web3', () => {
    let web3Options, resolvedWeb3, gen
  
    describe('with customProvider', () => {
      beforeAll(async () => {
        global.window = {}
        web3Options = { customProvider: global.provider }
      })
  
      test('get web3', async () => {
        gen = initializeWeb3(web3Options)
  
        // First action dispatched
        expect(gen.next().value).toEqual(put({ type: Action.WEB3_INITIALIZED }))
  
        resolvedWeb3 = gen.next().value
        expect(resolvedWeb3).toEqual(global.provider)
      })
    })
  
    describe('with ethereum, EIP-1102 compliance', () => {
      test('invokes `ethereum.enable`', async () => {
        const mockedEthereumEnable = jest.fn()
        const ethereum = { enable: mockedEthereumEnable }
        global.window = { ethereum }
  
        gen = initializeWeb3({})
        let next = gen.next()
        // get permission according to EIP 1102
        //
  
        expect(next.value).toEqual(
          call({ context: ethereum, fn: ethereum.enable })
        )
  
        // return an account to simulate opt-in
        next = gen.next('0x123')
        expect(next.value).toEqual(put({ type: Action.WEB3_INITIALIZED }))
  
        resolvedWeb3 = gen.next().value
        hasWeb3Shape(resolvedWeb3)
      })
  
      test('loads when user opts in', async () => {
        const mockedEthereumEnable = jest.fn(() => '0x123')
        const ethereum = { enable: mockedEthereumEnable }
        global.window = { ethereum }
        const dispatched = []
  
        const result = await runSaga({
          dispatch: (action) => dispatched.push(action),
          getState: () => ({ state: 'test' })
        }, initializeWeb3, {}).done
  
        // result should be a proper web3 provider
        expect(result).toBeInstanceOf(require('web3'))
      })
  
      test('does not load when user opts out', async () => {
        // opt out
        global.window = { ethereum: { enable: jest.fn(() => undefined) } }
        const dispatched = []
  
        const web3Result = await runSaga(
          {
            dispatch: action => dispatched.push(action),
            getState: () => ({ state: 'test' })
          },
          initializeWeb3,
          {}
        ).done
  
        // saga result should be undefined if an exception occurs
        expect(web3Result).toBe(undefined)
  
        // and the last action should be WEB3_USER_DENIED
        expect(dispatched.pop()).toEqual({ type: Action.WEB3_USER_DENIED })
      })
  
      test('does not load when provider throws an error', async () => {
        // simulate opting out
        const mockedEthereumEnable = jest.fn(() => { throw new Error('oops') })
        const ethereum = { enable: mockedEthereumEnable }
        global.window = { ethereum }
        const dispatched = []
  
        const result = await runSaga({
          dispatch: (action) => dispatched.push(action),
          getState: () => ({ state: 'test' })
        }, initializeWeb3, {}).done
  
        // saga result is undefined when exception is thrown
        expect(result).toBe(undefined)
  
        // and the last action should be WEB3_FAILED
        expect(dispatched.pop()).toEqual({ type: Action.WEB3_FAILED })
      })
    })
  
    describe('with injected web3', () => {
      beforeAll(async () => {
        global.window = {}
        global.window.web3 = { currentProvider: global.provider }
        gen = initializeWeb3({})
      })
  
      test('get web3', async () => {
        // First action dispatched
        expect(gen.next().value).toEqual(put({ type: Action.WEB3_INITIALIZED }))
      })
    })
  
    describe('with websocket fallback web3', () => {
      let gen
  
      beforeAll(async () => {
        global.window = {}
        global.provider.providers = { WebSocketProvider: jest.fn() }
      })
  
      test('get web3', async () => {
        web3Options = {
          fallback: {
            type: 'ws',
            url: 'ws://localhost:12345'
          }
        }
        gen = initializeWeb3(web3Options)
  
        // First action dispatched
        expect(gen.next().value).toEqual(put({ type: Action.WEB3_INITIALIZED }))
        resolvedWeb3 = gen.next().value
  
        // is it a Web3 object?
        hasWeb3Shape(resolvedWeb3)
      })
  
      test('fails when fallback type is unknown', async () => {
        web3Options = {
          fallback: {
            type: 'thewrongtype',
            url: 'ws://localhost:12345'
          }
        }
        gen = initializeWeb3(web3Options)
  
        const error = new Error('Invalid web3 fallback provided.')
        expect(gen.next().value).toEqual(put({ type: Action.WEB3_FAILED, error }))
      })
    })
  
    describe('Exhausts options', () => {
      beforeAll(async () => {
        global.window = {}
        gen = initializeWeb3({})
      })
  
      test('with failure', async () => {
        const error = new Error('Cannot find injected web3 or valid fallback.')
        expect(gen.next().value).toEqual(put({ type: Action.WEB3_FAILED, error }))
      })
    })
  })
  