choko-org / redux-boot

Modular Redux bootstrap with asynchronous side-effects.
MIT License
126 stars 7 forks source link

Add redux-promise tests with async actions #3

Closed sebas5384 closed 8 years ago

sebas5384 commented 8 years ago
recidive commented 8 years ago

We've filed this issue on Redux issue tracker:

https://github.com/reactjs/redux/issues/1584

sebas5384 commented 8 years ago
import {createStore, applyMiddleware} from 'redux'
import {createAction, handleActions} from 'redux-actions'
import promiseMiddleware from 'redux-promise'
import test from 'tape'

test('Use redux-actions with redux-promise to fire async side-effect actions in middlwares', (assert) => {

  const BOOT = 'BOOT';
  const AFTER_BOOT = 'AFTER_BOOT';
  const AFTER_AFTER_BOOT = 'AFTER_AFTER_BOOT';

  const someApi = {
    get(id) {
      return Promise.resolve({
        name: (id == 2) ? 'baz' : 'rock'
      })
    }
  }

  const bootAction = createAction(BOOT, async () => ({}))

  const afterBootAction = createAction(AFTER_BOOT, async (id) => {
    const result = await someApi.get(id)
    return result
  })

  const afterAfterBootAction = createAction(AFTER_AFTER_BOOT, async (id) => {
    const result = await someApi.get(id)
    return result
  })

  const initialState = {foo: 'bar'}

  const reducer = (state = initialState, action) => {
    switch (action.type) {
      case AFTER_BOOT:
        return {
          ...state,
          foo: action.payload.name
        }

      case AFTER_AFTER_BOOT:
        return {
          ...state,
          foo: action.payload.name
        }
      default:
        return state;
        break;
    }
  }

  const middlewares = [
    promiseMiddleware,
    function middle9({getState, dispatch}) {
      // Note the async keyword.
      return next => (action) => {

        console.log(action.type, 'ACTION')

        const nextResult = next(action)

        if (action.type == AFTER_AFTER_BOOT) {
          console.log(getState(), 'STATEEEE AFTER AFTER BOOT 9');
        }

        return nextResult
      }
    },
    function middleA({getState, dispatch}) {
      // Note the async keyword.
      return next => async (action) => {

        const nextResult = next(action)

        if (action.type == AFTER_BOOT) {
          // console.log(getState(), 'STATEEEE before A');
          // const sideffectB = await dispatch(afterAfterBootAction(3))
          console.log(getState(), 'STATEEEE AFTER BOOT');
        }

        return nextResult
      }
    },
    function middleB({getState, dispatch}) {
      // Note the async keyword.
      return next => async (action) => {

        const nextResult = next(action)

        if (action.type == BOOT) {
          const sideffectA = await dispatch(afterBootAction(2))
          console.log(getState(), 'STATEEEE A');
          const sideffectB = await dispatch(afterAfterBootAction(3))
          console.log(getState(), 'STATEEEE AFTER AFTER BOOT B');
        }

        return nextResult
      }
    }, 
    function middleC({getState, dispatch}) {
      // Note the async keyword.
      return next => (action) => {

        const nextResult = next(action)

        if (action.type == AFTER_AFTER_BOOT) {
          console.log(getState(), 'STATEEEE AFTER AFTER BOOT C');
        }

        return nextResult
      }
    }
  ]

  const store = createStore(reducer, initialState, applyMiddleware(...middlewares))

  // First action, and should fire other side-effects.
  const bootPromise = store.dispatch(bootAction())
    .then(() => {

      assert.equal(
        store.getState().foo,
        'rock',
        'Chainable async side-effect was handled'
      )

      assert.end()
    })

})